summaryrefslogtreecommitdiffstats
path: root/sys/x86/iommu/busdma_dmar.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/x86/iommu/busdma_dmar.c')
-rw-r--r--sys/x86/iommu/busdma_dmar.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/sys/x86/iommu/busdma_dmar.c b/sys/x86/iommu/busdma_dmar.c
index 3f86c78..96b0bce 100644
--- a/sys/x86/iommu/busdma_dmar.c
+++ b/sys/x86/iommu/busdma_dmar.c
@@ -462,6 +462,7 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
bus_size_t buflen1;
int error, idx, gas_flags, seg;
+ KASSERT(offset < DMAR_PAGE_SIZE, ("offset %d", offset));
if (segs == NULL)
segs = tag->segments;
ctx = tag->ctx;
@@ -476,7 +477,6 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
}
buflen1 = buflen > tag->common.maxsegsz ?
tag->common.maxsegsz : buflen;
- buflen -= buflen1;
size = round_page(offset + buflen1);
/*
@@ -487,7 +487,7 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
if (seg + 1 < tag->common.nsegments)
gas_flags |= DMAR_GM_CANSPLIT;
- error = dmar_gas_map(ctx, &tag->common, size,
+ error = dmar_gas_map(ctx, &tag->common, size, offset,
DMAR_MAP_ENTRY_READ | DMAR_MAP_ENTRY_WRITE,
gas_flags, ma + idx, &entry);
if (error != 0)
@@ -506,6 +506,10 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
(uintmax_t)size, (uintmax_t)entry->start,
(uintmax_t)entry->end));
}
+ if (offset + buflen1 > size)
+ buflen1 = size - offset;
+ if (buflen1 > tag->common.maxsegsz)
+ buflen1 = tag->common.maxsegsz;
KASSERT(((entry->start + offset) & (tag->common.alignment - 1))
== 0,
@@ -519,15 +523,16 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
(uintmax_t)entry->start, (uintmax_t)entry->end,
(uintmax_t)tag->common.lowaddr,
(uintmax_t)tag->common.highaddr));
- KASSERT(dmar_test_boundary(entry->start, entry->end -
- entry->start, tag->common.boundary),
+ KASSERT(dmar_test_boundary(entry->start + offset, buflen1,
+ tag->common.boundary),
("boundary failed: ctx %p start 0x%jx end 0x%jx "
"boundary 0x%jx", ctx, (uintmax_t)entry->start,
(uintmax_t)entry->end, (uintmax_t)tag->common.boundary));
KASSERT(buflen1 <= tag->common.maxsegsz,
("segment too large: ctx %p start 0x%jx end 0x%jx "
- "maxsegsz 0x%jx", ctx, (uintmax_t)entry->start,
- (uintmax_t)entry->end, (uintmax_t)tag->common.maxsegsz));
+ "buflen1 0x%jx maxsegsz 0x%jx", ctx,
+ (uintmax_t)entry->start, (uintmax_t)entry->end,
+ (uintmax_t)buflen1, (uintmax_t)tag->common.maxsegsz));
DMAR_CTX_LOCK(ctx);
TAILQ_INSERT_TAIL(&map->map_entries, entry, dmamap_link);
@@ -541,6 +546,7 @@ dmar_bus_dmamap_load_something1(struct bus_dma_tag_dmar *tag,
idx += OFF_TO_IDX(trunc_page(offset + buflen1));
offset += buflen1;
offset &= DMAR_PAGE_MASK;
+ buflen -= buflen1;
}
if (error == 0)
*segp = seg;
OpenPOWER on IntegriCloud