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



The following reply was made to PR port-amd64/42980; it has been noted by GNATS.

From: Manuel Bouyer <bouyer%antioche.eu.org@localhost>
To: Julian Bourne <julian.bourne%gmail.com@localhost>
Cc: gnats-bugs%NetBSD.org@localhost, port-amd64-maintainer%NetBSD.org@localhost,
        gnats-admin%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: port-amd64/42980: satalink DMA fails under amd64
Date: Fri, 19 Mar 2010 17:06:25 +0100

 --2oS5YaxWCcQjTEyO
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 On Fri, Mar 19, 2010 at 04:41:16PM +0100, Manuel Bouyer wrote:
 > On Fri, Mar 19, 2010 at 09:47:39AM -0400, Julian Bourne wrote:
 > > I applied the patch to 5.0.2 (hope that was right - it
 > > applied cleanly) and rebuilt my xen dom0 target.
 > > 
 > > It hit a __kern_assert() in uvm_pglistalloc():403
 > > called from xen_bus_dmamem_alloc_range():
 > > 
 > > (boundary & (boundary - 1) == 0) failed
 > 
 > that's strange, because in xen_bus_dmamem_alloc_range() this could be either
 > boundary (and this check is already done in xen_bus_dmamem_alloc_range())
 > or size (which is rounded to PAGE_SIZE). Could you print the
 > values for boundary and size here ?
 
 ignore this, rounding up to PAGE_SIZE is not enough to make it a power of 2.
 
 The attached patch should be correct (at last I hope so, it's becoming more
 complex than I'd like ...)
 
 -- 
 Manuel Bouyer <bouyer%antioche.eu.org@localhost>
      NetBSD: 26 ans d'experience feront toujours la difference
 --
 
 --2oS5YaxWCcQjTEyO
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="busdma.diff"
 
 Index: x86/x86/bus_dma.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/x86/x86/bus_dma.c,v
 retrieving revision 1.45
 diff -u -p -u -r1.45 bus_dma.c
 --- x86/x86/bus_dma.c  28 Jun 2008 17:23:01 -0000      1.45
 +++ x86/x86/bus_dma.c  19 Mar 2010 16:05:28 -0000
 @@ -155,14 +155,28 @@ _bus_dmamem_alloc_range(bus_dma_tag_t t,
        struct vm_page *m;
        struct pglist mlist;
        int curseg, error;
 +      bus_size_t uboundary;
  
        /* Always round the size. */
        size = round_page(size);
  
 +      KASSERT(boundary >= PAGE_SIZE || boundary == 0);
 +
        /*
         * Allocate pages from the VM system.
 -       */
 -      error = uvm_pglistalloc(size, low, high, alignment, boundary,
 +       * We accept boundaries < size, splitting in multiple segments
 +       * if needed. uvm_pglistalloc does not, so compute an appropriate
 +         * boundary: next power of 2 >= size
 +         */
 +
 +      if (boundary == 0)
 +              uboundary = 0;
 +      else {
 +              uboundary = boundary;
 +              while (uboundary < size)
 +                      uboundary = uboundary << 1;
 +      }
 +      error = uvm_pglistalloc(size, low, high, alignment, uboundary,
            &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
        if (error)
                return (error);
 @@ -186,10 +200,13 @@ _bus_dmamem_alloc_range(bus_dma_tag_t t,
                        panic("_bus_dmamem_alloc_range");
                }
  #endif
 -              if (curaddr == (lastaddr + PAGE_SIZE))
 +              if (curaddr == (lastaddr + PAGE_SIZE) &&
 +                  (lastaddr & boundary) == (curaddr & boundary)) {
                        segs[curseg].ds_len += PAGE_SIZE;
 -              else {
 +              } else {
                        curseg++;
 +                      if (curseg >= nsegs)
 +                              return EFBIG;
                        segs[curseg].ds_addr = curaddr;
                        segs[curseg].ds_len = PAGE_SIZE;
                }
 Index: xen/x86/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/x86/xen_bus_dma.c      30 Jan 2010 19:14:20 -0000      1.11.8.1
 +++ xen/x86/xen_bus_dma.c      19 Mar 2010 16:05:28 -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);
 @@ -244,21 +244,32 @@ _xen_bus_dmamem_alloc_range(bus_dma_tag_
        struct pglist mlist;
        int curseg, error;
        int doingrealloc = 0;
 +      bus_size_t uboundary;
  
        /* Always round the size. */
        size = round_page(size);
  
        KASSERT((alignment & (alignment - 1)) == 0);
        KASSERT((boundary & (boundary - 1)) == 0);
 +      KASSERT(boundary >= PAGE_SIZE || boundary == 0);
 +                  
        if (alignment < PAGE_SIZE)
                alignment = PAGE_SIZE;
 -      if (boundary != 0 && boundary < size)
 -              return (EINVAL);
  
        /*
         * Allocate pages from the VM system.
 +       * We accept boundaries < size, splitting in multiple segments
 +       * if needed. uvm_pglistalloc does not, so compute an appropriate
 +       * boundary: next power of 2 >= size
         */
 -      error = uvm_pglistalloc(size, 0, avail_end, alignment, boundary,
 +      if (boundary == 0)
 +              uboundary = 0;
 +      else {
 +              uboundary = boundary;
 +              while (uboundary < size)
 +                      uboundary = uboundary << 1;
 +      }
 +      error = uvm_pglistalloc(size, 0, avail_end, alignment, uboundary,
            &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
        if (error)
                return (error);
 @@ -282,14 +293,18 @@ 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)
 -                              goto dorealloc;
 +                      if (curseg >= nsegs ||
 +                          (curaddr & (alignment - 1)) != 0) {
 +                              if (doingrealloc)
 +                                      return EFBIG;
 +                              else
 +                                      goto dorealloc;
 +                      }
                        segs[curseg].ds_addr = curaddr;
                        segs[curseg].ds_len = PAGE_SIZE;
                }
 @@ -343,7 +358,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;
 
 --2oS5YaxWCcQjTEyO--
 


Home | Main Index | Thread Index | Old Index