atom feed5 messages in org.freebsd.freebsd-usbRequest for feedback on common data b...
FromSent OnAttachments
Hans Petter SelaskySep 25, 2007 4:31 pm 
John-Mark GurneySep 26, 2007 6:15 am 
Scott LongSep 26, 2007 11:16 am 
Hans Petter SelaskySep 26, 2007 12:56 pm 
Scott LongSep 26, 2007 6:13 pm 
Subject:Request for feedback on common data backstore in the kernel
From:Hans Petter Selasky (hsel@c2i.net)
Date:Sep 25, 2007 4:31:19 pm
List:org.freebsd.freebsd-usb

Hi,

Please keep me CC'ed, hence I'm not on all these lists.

In the kernel we currently have two different data backstores:

struct mbuf

and

struct buf

These two backstores serve two different device types. "mbufs" are for network devices and "buf" is for disk devices.

Problem:

The current backstores are loaded into DMA by using the BUS-DMA framework. This appears not to be too fast according to Kip Macy. See:

http://perforce.freebsd.org/chv.cgi?CH=126455

Some ideas I have:

When a buffer is out out of range for a hardware device and a data-copy is needed I want to simply copy that data in smaller parts to/from a pre-allocated bounce buffer. I want to avoid allocating this buffer when "bus_dmamap_load()" is called.

For pre-allocated USB DMA memory I currently have:

struct usbd_page

struct usbd_page { void *buffer; // virtual address bus_size_t physaddr; // as seen by one of my devices bus_dma_tag_t tag; bus_dmamap_t map; uint32_t length; };

Mostly only "length == PAGE_SIZE" is allowed. When USB allocates DMA memory it allocates the same size all the way and that is PAGE_SIZE bytes.

If two different PCI controllers want to communicate directly passing DMA buffers, technically one would need to translate the physical address for device 1 to the physical address as seen by device 2. If this translation table is sorted, the search will be rather quick. Another approach is to limit the number of translations:

#define N_MAX_PCI_TRANSLATE 4

struct usbd_page { void *buffer; // virtual address bus_size_t physaddr[N_MAX_PCI_TRANSLATE]; bus_dma_tag_t tag; bus_dmamap_t map; uint32_t length; };

Then PCI device 1 on bus X can use physaddr[0] and PCI device 2 on bus Y can use physaddr[1]. If the physaddr[] is equal to some magic then the DMA buffer is not reachable and must be bounced.

Then when two PCI devices talk together all they need to pass is a structure like this:

struct usbd_page_cache { struct usbd_page *page_start; uint32_t page_offset_buf; uint32_t page_offset_end; };

And the required DMA address is looked up in some nanos.

Has someone been thinking about this topic before ?

--HPS