| From david-b@pacbell.net Sat Mar 31 18:15:49 2007 |
| From: Tony Lindgren <tony@atomide.com> |
| Date: Sat, 31 Mar 2007 18:15:43 -0700 |
| Subject: USB: Allow transfer_buffer with transfer_dma |
| To: Tony Lindgren <tony@atomide.com>, Greg KH <gregkh@suse.de> |
| Cc: Alan Stern <stern@rowland.harvard.edu>, Felipe Balbi <ext-felipe.lima@nokia.com> |
| Message-ID: <200703311815.43784.david-b@pacbell.net> |
| Content-Disposition: inline |
| |
| From: Tony Lindgren <tony@atomide.com> |
| |
| Some host controller drivers may need a PIO fallback when a DMA channel |
| is temporarily unavailable. This patch provides an address that such |
| drivers can use for PIO in those cases, and nulls that field out when |
| no such address is available (highmem) which should help usbmon. |
| |
| Signed-off-by: Tony Lindgren <tony@atomide.com> |
| Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/usb/core/message.c | 16 +++++++++++++++- |
| 1 file changed, 15 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/usb/core/message.c |
| +++ b/drivers/usb/core/message.c |
| @@ -412,10 +412,24 @@ int usb_sg_init ( |
| io->urbs [i]->status = -EINPROGRESS; |
| io->urbs [i]->actual_length = 0; |
| |
| + /* |
| + * Some systems need to revert to PIO when DMA is temporarily |
| + * unavailable. For their sakes, both transfer_buffer and |
| + * transfer_dma are set when possible. However this can only |
| + * work on systems without HIGHMEM, since DMA buffers located |
| + * in high memory are not directly addressable by the CPU for |
| + * PIO ... so when HIGHMEM is in use, transfer_buffer is NULL |
| + * to prevent stale pointers and to help spot bugs. |
| + */ |
| if (dma) { |
| - /* hc may use _only_ transfer_dma */ |
| io->urbs [i]->transfer_dma = sg_dma_address (sg + i); |
| len = sg_dma_len (sg + i); |
| +#ifdef CONFIG_HIGHMEM |
| + io->urbs[i]->transfer_buffer = NULL; |
| +#else |
| + io->urbs[i]->transfer_buffer = |
| + page_address(sg[i].page) + sg[i].offset; |
| +#endif |
| } else { |
| /* hc may use _only_ transfer_buffer */ |
| io->urbs [i]->transfer_buffer = |