NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-amd64/42980: satalink DMA fails under amd64
On Tue, Mar 16, 2010 at 10:02:56PM -0400, Julian Bourne wrote:
> Further investigation: the EINVAL is being returned by the call to:
>
> bus_dmamem_alloc(...,size=65536,
> alignment=4096, boundary=8192,
> nsegs=17, flags=0x3)
>
> from _bus_dma_alloc_bouncebuf() on line 896;
> from _bus_dmamap_create() on line 283.
>
> This is all from: arch/x86/x86/bus_dma.c revision 1.45 (NetBSD-5.0.2).
>
> Ultimately, this is called from dev/pci/pciide_common.c revision 1.38
> on line 597 via bus_dmamap_create() - the error is printed out a few
> lines after.
I think the bug is from _bus_dma_alloc_bouncebuf(),
which doesn't pay enough attention to the boundary value vs size, before
calling bus_dmamem_alloc().
It seems to me that the right solution is to properly handle the boundary
in _xen_bus_dmamem_alloc_range() (the x86 version doens't need changes, this
is handled by uvm_pglistalloc()).
I think the attached patch should do it; can you test (and make sure you
removed your patch before, of course :) ?
--
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
NetBSD: 26 ans d'experience feront toujours la difference
--
Index: xen_bus_dma.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/x86/xen_bus_dma.c,v
retrieving revision 1.11.8.1
diff -u -p -u -r1.11.8.1 xen_bus_dma.c
--- xen_bus_dma.c 30 Jan 2010 19:14:20 -0000 1.11.8.1
+++ xen_bus_dma.c 18 Mar 2010 16:53:52 -0000
@@ -61,7 +61,7 @@ static inline int get_order(unsigned lon
}
static int
-_xen_alloc_contig(bus_size_t size, bus_size_t alignment, bus_size_t boundary,
+_xen_alloc_contig(bus_size_t size, bus_size_t alignment,
struct pglist *mlistp, int flags, bus_addr_t low, bus_addr_t high)
{
int order, i;
@@ -75,9 +75,9 @@ _xen_alloc_contig(bus_size_t size, bus_s
/*
* When requesting a contigous memory region, the hypervisor will
- * return a memory range aligned on size. This will automagically
- * handle "boundary", but the only way to enforce alignment
- * is to request a memory region of size max(alignment, size).
+ * return a memory range aligned on size.
+ * The only way to enforce alignment is to request a memory region
+ * of size max(alignment, size).
*/
order = max(get_order(size), get_order(alignment));
npages = (1 << order);
@@ -252,8 +252,6 @@ _xen_bus_dmamem_alloc_range(bus_dma_tag_
KASSERT((boundary & (boundary - 1)) == 0);
if (alignment < PAGE_SIZE)
alignment = PAGE_SIZE;
- if (boundary != 0 && boundary < size)
- return (EINVAL);
/*
* Allocate pages from the VM system.
@@ -282,10 +280,9 @@ again:
curaddr = _BUS_VM_PAGE_TO_BUS(m);
if (curaddr < low || curaddr >= high)
goto badaddr;
- if (curaddr == (lastaddr + PAGE_SIZE)) {
+ if (curaddr == (lastaddr + PAGE_SIZE) &&
+ (lastaddr & boundary) == (curaddr & boundary)) {
segs[curseg].ds_len += PAGE_SIZE;
- if ((lastaddr & boundary) != (curaddr & boundary))
- goto dorealloc;
} else {
curseg++;
if (curseg >= nsegs || (curaddr & (alignment - 1)) != 0)
@@ -343,7 +340,7 @@ dorealloc:
segs[curseg].ds_len = 0;
}
error = _xen_alloc_contig(size, alignment,
- boundary, &mlist, flags, low, high);
+ &mlist, flags, low, high);
if (error)
return error;
goto again;
Home |
Main Index |
Thread Index |
Old Index