Insufficient memory reserved for xfer->dma_page_ptr?
Aman Sawrup
aman.sawrup at bluecoat.com
Tue Feb 19 22:33:42 UTC 2013
Hi Hans,
I think I might have found a bug in usbd_transfer_setup_sub that causes
insufficient memory allocated for xfer->dma_page_ptr. The code in
question is:
#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable) {
/*
* Setup "dma_page_ptr".
*
* Proof for formula below:
*
* Assume there are three USB frames having length "a", "b" and
* "c". These USB frames will at maximum need "z"
* "usb_page" structures. "z" is given by:
*
* z = ((a / USB_PAGE_SIZE) + 2) + ((b / USB_PAGE_SIZE) + 2) +
* ((c / USB_PAGE_SIZE) + 2);
*
* Constraining "a", "b" and "c" like this:
*
* (a + b + c) <= parm->bufsize
*
* We know that:
*
* z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2));
*
* Here is the general formula:
*/
xfer->dma_page_ptr = parm->dma_page_ptr;
parm->dma_page_ptr += (2 * n_frbuffers);
parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE);
}
#endif
What I observe happening on a 64-bit x86 system is 4608 bytes reserved
for xfer->dma_page_ptr. For example, this is what I see:
(gdb) p parm->dma_page_ptr
$75 = (struct usb_page *) 0x6dad46e0
(gdb) p xfer->dma_page_ptr
$76 = (struct usb_page *) 0x6dad34e0
(gdb) p /d 0x6dad46e0 - 0x6dad34e0
$79 = 4608
(gdb) p /d sizeof(struct usb_page)
$74 = 16
(gdb) p /d n_frbuffers
$68 = 128
(gdb) p /d parm->bufsize
$70 = 131072
I believe the amount of memory reserved needs to be much higher. For
example, if sizeof(struct usb_page) is 16 bytes, then for n_frbuffers of
128 and parm->bufsize of 131072, we need the following amount of memory
reserved:
parm->bufsize / USB_PAGE_SIZE * n_frbuffers * sizeof(struct usb_page)
= 131072 / 4096 * 128 * 16
= 65536
Thanks
Aman
More information about the freebsd-usb
mailing list