diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2002-08-19 20:02:31 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2002-08-19 20:02:31 +0000 |
commit | a8f1e875558246527f7225e86ea65d9c3f076807 (patch) | |
tree | 848d5e47fd560b8e4564712810dd8f6021a28ac1 /sys | |
parent | a7e20a539355f710104f8e4b3144446f8ad01222 (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.c | 18 |
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? */ |