Subject: bug in iommu_dvmamap_load_raw()
To: None <port-sparc64@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: port-sparc64
Date: 08/06/2001 21:31:27
--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hi,
I think I've found a bug in iommu_dvmamap_load_raw(), in the part that
count the size we need to extent_alloc(): when we need a new page because the
previous segment(s) and the current one are not in the same page, if we
round_page the size after adding the current's segment len we loose the current
segement len. In the case of a mapping with 2 small segments, each in its own
page, we end up allocating one page instead of 2. iommu_dvmamap_unload()
will properly compute the size of 2 pages, and we'll panic in
extent_free().
The attached patch solve this (at last it allows if_tl to work on sparc64),
but maybe I've missed another corner case where we should round_page the
size after adding the len ...
BTW, I discovered this while working on if_tl, and it looks only
iommu_dvmamap_load_raw() (so bus_dmamap_load_raw(), bus_dmamap_load_mbuf(),
bus_dmamap_load_uio()) is affected. However, the hme driver doesn't use
bus_dmamap_load_mbuf() :)
--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel.Bouyer@lip6.fr
--
--6TrnltStXW4iwmi0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff
Index: iommu.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/iommu.c,v
retrieving revision 1.36
diff -u -r1.36 iommu.c
--- iommu.c 2001/07/20 00:07:13 1.36
+++ iommu.c 2001/08/06 19:21:16
@@ -650,9 +650,9 @@
pa = segs[0].ds_addr;
sgsize = 0;
for (i=0; i<nsegs; i++) {
- sgsize += segs[i].ds_len;
if (round_page(pa) != round_page(segs[i].ds_addr))
sgsize = round_page(sgsize);
+ sgsize += segs[i].ds_len;
pa = segs[i].ds_addr + segs[i].ds_len;
}
sgsize = round_page(sgsize);
--6TrnltStXW4iwmi0--