summaryrefslogtreecommitdiffstats
path: root/sys/x86/iommu/intel_gas.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/x86/iommu/intel_gas.c')
-rw-r--r--sys/x86/iommu/intel_gas.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/sys/x86/iommu/intel_gas.c b/sys/x86/iommu/intel_gas.c
index d91da97..5a7a730 100644
--- a/sys/x86/iommu/intel_gas.c
+++ b/sys/x86/iommu/intel_gas.c
@@ -294,6 +294,7 @@ dmar_gas_fini_ctx(struct dmar_ctx *ctx)
struct dmar_gas_match_args {
struct dmar_ctx *ctx;
dmar_gaddr_t size;
+ int offset;
const struct bus_dma_tag_common *common;
u_int gas_flags;
struct dmar_map_entry *entry;
@@ -310,25 +311,28 @@ dmar_gas_match_one(struct dmar_gas_match_args *a, struct dmar_map_entry *prev,
/* DMAR_PAGE_SIZE to create gap after new entry. */
if (a->entry->start < prev->end + DMAR_PAGE_SIZE ||
- a->entry->start + a->size + DMAR_PAGE_SIZE > prev->end +
- prev->free_after)
+ a->entry->start + a->size + a->offset + DMAR_PAGE_SIZE >
+ prev->end + prev->free_after)
return (false);
/* No boundary crossing. */
- if (dmar_test_boundary(a->entry->start, a->size, a->common->boundary))
+ if (dmar_test_boundary(a->entry->start + a->offset, a->size,
+ a->common->boundary))
return (true);
/*
- * The start to start + size region crosses the boundary.
- * Check if there is enough space after the next boundary
- * after the prev->end.
+ * The start + offset to start + offset + size region crosses
+ * the boundary. Check if there is enough space after the
+ * next boundary after the prev->end.
*/
- bs = (a->entry->start + a->common->boundary) & ~(a->common->boundary
- - 1);
+ bs = (a->entry->start + a->offset + a->common->boundary) &
+ ~(a->common->boundary - 1);
start = roundup2(bs, a->common->alignment);
/* DMAR_PAGE_SIZE to create gap after new entry. */
- if (start + a->size + DMAR_PAGE_SIZE <= prev->end + prev->free_after &&
- start + a->size <= end && dmar_test_boundary(start, a->size,
+ if (start + a->offset + a->size + DMAR_PAGE_SIZE <=
+ prev->end + prev->free_after &&
+ start + a->offset + a->size <= end &&
+ dmar_test_boundary(start + a->offset, a->size,
a->common->boundary)) {
a->entry->start = start;
return (true);
@@ -410,7 +414,7 @@ dmar_gas_lowermatch(struct dmar_gas_match_args *a, struct dmar_map_entry *prev)
return (0);
}
}
- if (prev->free_down < a->size + DMAR_PAGE_SIZE)
+ if (prev->free_down < a->size + a->offset + DMAR_PAGE_SIZE)
return (ENOMEM);
l = RB_LEFT(prev, rb_entry);
if (l != NULL) {
@@ -466,7 +470,7 @@ dmar_gas_uppermatch(struct dmar_gas_match_args *a)
static int
dmar_gas_find_space(struct dmar_ctx *ctx,
const struct bus_dma_tag_common *common, dmar_gaddr_t size,
- u_int flags, struct dmar_map_entry *entry)
+ int offset, u_int flags, struct dmar_map_entry *entry)
{
struct dmar_gas_match_args a;
int error;
@@ -477,6 +481,7 @@ dmar_gas_find_space(struct dmar_ctx *ctx,
a.ctx = ctx;
a.size = size;
+ a.offset = offset;
a.common = common;
a.gas_flags = flags;
a.entry = entry;
@@ -618,7 +623,7 @@ dmar_gas_free_region(struct dmar_ctx *ctx, struct dmar_map_entry *entry)
int
dmar_gas_map(struct dmar_ctx *ctx, const struct bus_dma_tag_common *common,
- dmar_gaddr_t size, u_int eflags, u_int flags, vm_page_t *ma,
+ dmar_gaddr_t size, int offset, u_int eflags, u_int flags, vm_page_t *ma,
struct dmar_map_entry **res)
{
struct dmar_map_entry *entry;
@@ -632,7 +637,7 @@ dmar_gas_map(struct dmar_ctx *ctx, const struct bus_dma_tag_common *common,
if (entry == NULL)
return (ENOMEM);
DMAR_CTX_LOCK(ctx);
- error = dmar_gas_find_space(ctx, common, size, flags, entry);
+ error = dmar_gas_find_space(ctx, common, size, offset, flags, entry);
if (error == ENOMEM) {
DMAR_CTX_UNLOCK(ctx);
dmar_gas_free_entry(ctx, entry);
OpenPOWER on IntegriCloud