summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2002-08-19 20:02:31 +0000
committerJason Wright <jason@cvs.openbsd.org>2002-08-19 20:02:31 +0000
commita8f1e875558246527f7225e86ea65d9c3f076807 (patch)
tree848d5e47fd560b8e4564712810dd8f6021a28ac1 /sys
parenta7e20a539355f710104f8e4b3144446f8ad01222 (diff)
From NetBSD:
-Fix some corner cases in bus_dmamap_load_mbuf(). From Takeshi Nakayama <tn@catvmics.ne.jp> -Fix off-by-one error in iommu_dvmamap_load_raw() where if a DMA segment has just one byte on a page the page is never mapped into the IOMMU.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/dev/iommu.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/sys/arch/sparc64/dev/iommu.c b/sys/arch/sparc64/dev/iommu.c
index b4be85b8775..1f39cc44287 100644
--- a/sys/arch/sparc64/dev/iommu.c
+++ b/sys/arch/sparc64/dev/iommu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: iommu.c,v 1.18 2002/07/24 19:07:43 jason Exp $ */
+/* $OpenBSD: iommu.c,v 1.19 2002/08/19 20:02:30 jason Exp $ */
/* $NetBSD: iommu.c,v 1.47 2002/02/08 20:03:45 eeh Exp $ */
/*
@@ -574,7 +574,7 @@ iommu_dvmamap_load(t, is, map, buf, buflen, p, flags)
map->dm_segs[seg].ds_len));
map->dm_segs[seg].ds_len =
boundary - (sgstart & (boundary - 1));
- if (++seg > map->_dm_segcnt) {
+ if (++seg >= map->_dm_segcnt) {
/* Too many segments. Fail the operation. */
DPRINTF(IDB_INFO, ("iommu_dvmamap_load: "
"too many segments %d\n", seg));
@@ -836,6 +836,10 @@ printf("appending offset %x pa %lx, prev %lx dva %lx prev %lx\n",
(long)map->dm_segs[j].ds_addr,
map->dm_segs[j].ds_len));
} else {
+ if (j >= map->_dm_segcnt) {
+ iommu_dvmamap_unload(t, is, map);
+ return (E2BIG);
+ }
map->dm_segs[j].ds_addr = sgstart;
map->dm_segs[j].ds_len = left;
DPRINTF(IDB_INFO, ("iommu_dvmamap_load_raw: "
@@ -850,12 +854,12 @@ printf("appending offset %x pa %lx, prev %lx dva %lx prev %lx\n",
(sgend & ~(boundary - 1))) {
/* Need a new segment. */
map->dm_segs[j].ds_len =
- sgstart & (boundary - 1);
+ boundary - (sgstart & (boundary - 1));
DPRINTF(IDB_INFO, ("iommu_dvmamap_load_raw: "
"seg %d start %lx size %lx\n", j,
(long)map->dm_segs[j].ds_addr,
map->dm_segs[j].ds_len));
- if (++j > map->_dm_segcnt) {
+ if (++j >= map->_dm_segcnt) {
iommu_dvmamap_unload(t, is, map);
return (E2BIG);
}
@@ -868,7 +872,7 @@ printf("appending offset %x pa %lx, prev %lx dva %lx prev %lx\n",
panic("iommu_dmamap_load_raw: size botch");
/* Now map a series of pages. */
- while (dvmaddr < sgend) {
+ while (dvmaddr <= sgend) {
DPRINTF(IDB_BUSDMA,
("iommu_dvamap_load_raw: map %p "
"loading va %lx at pa %lx\n",
@@ -923,12 +927,12 @@ printf("appending offset %x pa %lx, prev %lx dva %lx prev %lx\n",
map->dm_segs[i].ds_addr = sgstart;
while ((sgstart & ~(boundary - 1)) != (sgend & ~(boundary - 1))) {
/* Oops. We crossed a boundary. Split the xfer. */
- map->dm_segs[i].ds_len = sgstart & (boundary - 1);
+ map->dm_segs[i].ds_len = boundary - (sgstart & (boundary - 1));
DPRINTF(IDB_INFO, ("iommu_dvmamap_load_raw: "
"seg %d start %lx size %lx\n", i,
(long)map->dm_segs[i].ds_addr,
map->dm_segs[i].ds_len));
- if (++i > map->_dm_segcnt) {
+ if (++i >= map->_dm_segcnt) {
/* Too many segments. Fail the operation. */
s = splhigh();
/* How can this fail? And if it does what can we do? */