svn commit: r281545 - stable/10/sys/x86/iommu
Konstantin Belousov
kib at FreeBSD.org
Wed Apr 15 06:56:53 UTC 2015
Author: kib
Date: Wed Apr 15 06:56:51 2015
New Revision: 281545
URL: https://svnweb.freebsd.org/changeset/base/281545
Log:
MFC r281254:
Account for the offset of the page run when allocating the
dmar_map_entry.
Modified:
stable/10/sys/x86/iommu/busdma_dmar.c
stable/10/sys/x86/iommu/intel_dmar.h
stable/10/sys/x86/iommu/intel_gas.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/x86/iommu/busdma_dmar.c
==============================================================================
--- stable/10/sys/x86/iommu/busdma_dmar.c Wed Apr 15 05:24:39 2015 (r281544)
+++ stable/10/sys/x86/iommu/busdma_dmar.c Wed Apr 15 06:56:51 2015 (r281545)
@@ -459,6 +459,7 @@ dmar_bus_dmamap_load_something1(struct b
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;
@@ -473,7 +474,6 @@ dmar_bus_dmamap_load_something1(struct b
}
buflen1 = buflen > tag->common.maxsegsz ?
tag->common.maxsegsz : buflen;
- buflen -= buflen1;
size = round_page(offset + buflen1);
/*
@@ -484,7 +484,7 @@ dmar_bus_dmamap_load_something1(struct b
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)
@@ -503,6 +503,10 @@ dmar_bus_dmamap_load_something1(struct b
(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,
@@ -516,15 +520,16 @@ dmar_bus_dmamap_load_something1(struct b
(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);
@@ -538,6 +543,7 @@ dmar_bus_dmamap_load_something1(struct b
idx += OFF_TO_IDX(trunc_page(offset + buflen1));
offset += buflen1;
offset &= DMAR_PAGE_MASK;
+ buflen -= buflen1;
}
if (error == 0)
*segp = seg;
Modified: stable/10/sys/x86/iommu/intel_dmar.h
==============================================================================
--- stable/10/sys/x86/iommu/intel_dmar.h Wed Apr 15 05:24:39 2015 (r281544)
+++ stable/10/sys/x86/iommu/intel_dmar.h Wed Apr 15 06:56:51 2015 (r281545)
@@ -289,7 +289,7 @@ struct dmar_map_entry *dmar_gas_alloc_en
void dmar_gas_free_entry(struct dmar_ctx *ctx, struct dmar_map_entry *entry);
void dmar_gas_free_space(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);
void dmar_gas_free_region(struct dmar_ctx *ctx, struct dmar_map_entry *entry);
int dmar_gas_map_region(struct dmar_ctx *ctx, struct dmar_map_entry *entry,
Modified: stable/10/sys/x86/iommu/intel_gas.c
==============================================================================
--- stable/10/sys/x86/iommu/intel_gas.c Wed Apr 15 05:24:39 2015 (r281544)
+++ stable/10/sys/x86/iommu/intel_gas.c Wed Apr 15 06:56:51 2015 (r281545)
@@ -293,6 +293,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;
@@ -309,25 +310,28 @@ dmar_gas_match_one(struct dmar_gas_match
/* 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);
@@ -409,7 +413,7 @@ dmar_gas_lowermatch(struct dmar_gas_matc
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) {
@@ -465,7 +469,7 @@ dmar_gas_uppermatch(struct dmar_gas_matc
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;
@@ -476,6 +480,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;
@@ -617,7 +622,7 @@ dmar_gas_free_region(struct dmar_ctx *ct
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;
@@ -631,7 +636,7 @@ dmar_gas_map(struct dmar_ctx *ctx, const
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);
More information about the svn-src-stable-10
mailing list