Hi,

Interesting reading.

On Wednesday 16 May 2007 16:08, Pete Zaitcev wrote:
> On Wed, 16 May 2007 14:49:37 +0200, Hans Petter Selasky <[EMAIL PROTECTED]> 
wrote:
> > I'm currently working on a Linux USB emulation layer for FreeBSD. In that
> > regard I have some issues that makes the stack peform non-optimal due to
> > its API design.
>
> I think that what you described is largely inevitable if such a significant
> difference exists in stack's architectures, but please see below.
>
> > What I would suggest is that when you allocate an URB and DMA'able
> > memory, you have to specify which pipe {CONTROL, BULK, INTERRUPT or ISOC}
> > it belongs to.
> >
> > What do you think?
>
> Just a side note, we are trying to move away from the pipe as a concept,
> because it turned out to be ficticious despite being spelled out in the
> spec. The real object to which you talk in the device turned out to
> be the endpoint, and the spec is deceiptive. So, let's assume that you
> want a kind of per-endpoint preallocation.
>
> > The reason is that in the new USB stack on FreeBSD, the USB transfer
> > descriptors are allocated along with the data-buffer, so that when you
> > unsetup an USB transfer, absolutely all memory related to a transfer is
> > freed. This also has a security implication in that when you have
> > pre-allocated all buffers and all USB host controller descriptors, you
> > will never get in the situation of not being able to allocate transfer
> > descriptors on the fly, like done on Linux.
>
> The requirement for massive on-the-fly allocations is a part of Linux
> stack that bothered me for a long time. This is especially annoying
> for block devices when pressure builds up in the VM, and dirty data
> has to be written out to a block storage device attached by USB.
> This is somewhat analogous to the problem which exists with NFS.
>
> So, in my drivers I leaned heavily towards the kind of preallocation
> which you are discussing. However, as you know we never had complete
> end-to-end preallocatin facilities, so this never was bulletproof.
>
> Attempts to do this also run against the paucity of IOMMU resources.
> We have tons of unnecessary allocations made with usb_buffer_alloc,
> of which I'm trying to rid us now. This happened because people
> somehow think that it's necessary to use such allocations whenever
> USB is involved.
>
> So, recently there was a backlash and giving up on this. Instead,
> we are moving to the model which the networking stack uses. This
> means, away from you. If anything, you're going to see less use
> of usb_buffer_alloc across Linux kernel.

Well, that is not so far away from me. What I plan, but have not implemented 
yet is the ability to set a custom buffer on a transfer.

My idea is that you have to specify the maximum transfer length. Then you 
allocate descriptors enough to handle that. Then you can do transfers of any 
size less than or equal to the maximum. All of the DMA memory allocation is 
done allocating single memory pages at a time. I use the scatter and gather 
capabilities available on the EHCI/OHCI controllers. There are no multi-page 
contiguous allocations.

>
> I suppose we could do one last effort:
>  - redefine usb_buffer_alloc to allow for endpoint argument
>  - implement methods in HCDs to allocate and free QPs and xxx_priv
>  - spell out in documentation very clearly that drivers should
>    NOT use these facilities by default and only use them when
>    memory pressure invokes these URBs
>
> This is something which, I think, only Greg Kroah can decide on doing
> or not doing.
>
> The core issue is, as far as I can tell, in vast majority of cases
> the end-to-end preallocation is unnecessary. If used, it adds enormous
> complexity, hurts performance, and eats IOMMU.

No, there is not very much extra complexity added to using end-to-end 
pre-allocation. Actually it makes the code simpler, once you first have 
overcome the first barriers.

http://www.turbocat.net/~hselasky/isdn4bsd/sources/src/sys/dev/usb/

If you have a look in my "ehci.c" and the function "ehci_xfer_setup()". This 
functions allocates both the so-called "URB", the required DMA buffer, a 
virtually linear buffer if wanted, and all required USB host controller 
descriptors.

Then look at "ehci_setup_standard_chain()". This function builds the 
descriptor chain. It is straight forward and fast.

http://www.turbocat.net/~hselasky/isdn4bsd/sources/src/sys/dev/usb/ehci.c

> We do not want it 
> used routinely. So, to implement truly useful preallocations, we
> have to have two paths or two chunks of code, one is smaller, less
> complex, less buggy, used commonly, and another far more complex,
> only used by usb-storage. Personally, I don't see it flying.

I would recommend that you split large USB-storage transfers into smaller 
pieces multiplies of wMaxPacketSize.

http://www.turbocat.net/~hselasky/isdn4bsd/sources/src/sys/dev/usb/umass.c

See the function "umass_t_bbb_data_write_callback()" for example.

--HPS

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to