On Mon, 1 Mar 2010, Albert Herranz wrote:

> >> Am I on the right path?
> > 
> > More or less.  I would do it somewhat differently:
> > 
> >     If URB_NO_TRANSFER_DMA_MAP is set then no map is needed.
> >     Otherwise if num_sgs > 0 then no map is needed.
> >     Otherwise if HCD_NO_COHERENT_MEM is set then use
> >             hcd_alloc_coherent().
> >     Otherwise if transfer_buffer_length > 0 then use
> >             dma_map_single().
> > 
> 
> I think that logic is not quite right.
> Remember that the final goal is to avoid allocating USB buffers from coherent 
> memory (because the USB drivers access USB buffers without access 
> restrictions but the platform I'm working on can't write to coherent memory 
> unless it is done in 32-bit chunks).

Actually the final goal is to make the mapping/unmapping algorithms 
clear and correct.  One of the subgoals involves avoiding coherent USB 
buffers, but there are others as well (if you look back the through the 
linux-usb mailing list for the last few weeks you'll see a discussion 
about a controller which has to use PIO for control transfers but can 
use DMA for other types).

> And we want to avoid bouncing at the USB layer too (that's what v1 did).
> 
> The strategy so far is:
> - we have modified the USB buffer allocation routines 
> hcd_buffer_alloc()/hcd_buffer_free() to always return normal kernel memory 
> when HCD_NO_COHERENT_MEM is set on the host controller.
> - during map_urb_for_dma()/unmap_urb_for_dma() we need to make sure that 
> those USB buffers are sync'ed, even if we are told 
> USB_NO_{SETUP,TRANSFER}_DMA_MAP
> 
> So the logic would be:
> 
>       If URB_NO_TRANSFER_DMA_MAP is _cleared_ then do the mapping

No, that's wrong because it ignores the HCD_LOCAL_MEM flag.

>       - this case covers normal kernel memory used as a buffer and not 
> already DMA mapped by a USB driver
> 
>       Otherwise if HCD_NO_COHERENT_MEM is set _and_ num_sgs == 0 _and_ 
> transfer_buffer_length > 0 then do the mapping too
>       - this case covers USB buffers allocated via usb_buffer_alloc() and 
> marked URB_NO_TRANSFER_DMA_MAP by a USB driver, which are allocated from 
> normal kernel memory when HCD_NO_COHERENT_MEM is set (we avoid bouncing 
> buffers here too, at least if they sit already within MEM2 in the Wii, but 
> anyway that's part of the platform DMA mapping code)
> 
>       s-g urbs do not need a mapping as they have already been mapped, marked 
> URB_NO_TRANSFER_DMA_MAP and have num_sgs > 0

Actually the test for transfer_buffer_length == 0 should be done first, 
since obviously no mapping is needed if there's no data.  (And in fact 
the current code does do this; I was wrong earlier when I said it 
doesn't.)

So let's make things a little easier by first testing the conditions 
under which no mapping is needed:

        If transfer_buffer_length is 0 then do nothing.
        Otherwise if num_sgs > 0 then do nothing.
        Otherwise if URB_NO_TRANSFER_DMA_MAP and transfer_dma
                are both set (this avoids your HCD_NO_COHERENT_MEM
                case) then do nothing.

The remaining cases all need mapping and/or bounce buffers:

        Otherwise if HCD_LOCAL_MEM is set then call hcd_alloc_coherent.
        Otherwise call dma_map_single.

Finally, the unmapping tests can be simplified greatly if the kind of
mapping is recorded in the URB flags.

Alan Stern

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to