Release DMA resources if submission fails in the HCD.
Signed-Off-By: Pete Zaitcev <[EMAIL PROTECTED]>
---
This seems too obvious. Yet I went back to kernel 2.2.19 and we always
had this bug (well, in 2.2 we didn't because we used virt_to_bus).
I'm amazed that such things can lay in plain view for years.
Am I missing something here?!
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e277258..ced5a1c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -912,6 +912,28 @@ static void urb_unlink (struct urb *urb)
spin_unlock_irqrestore (&hcd_data_lock, flags);
}
+static void usb_hcd_unmap_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+ int at_root_hub = (urb->dev == hcd->self.root_hub);
+
+ /* lower level hcd code should use *_dma exclusively if the
+ * host controller does DMA */
+ if (hcd->self.uses_dma && !at_root_hub) {
+ if (usb_pipecontrol (urb->pipe)
+ && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ dma_unmap_single (hcd->self.controller, urb->setup_dma,
+ sizeof (struct usb_ctrlrequest),
+ DMA_TO_DEVICE);
+ if (urb->transfer_buffer_length != 0
+ && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+ dma_unmap_single (hcd->self.controller,
+ urb->transfer_dma,
+ urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? DMA_FROM_DEVICE
+ : DMA_TO_DEVICE);
+ }
+}
/* may be called in any context with a valid urb->dev usecount
* caller surrenders "ownership" of urb
@@ -1015,6 +1037,7 @@ doit:
done:
if (unlikely (status)) {
urb_unlink (urb);
+ usb_hcd_unmap_dma (hcd, urb);
atomic_dec (&urb->use_count);
if (urb->reject)
wake_up (&usb_kill_urb_queue);
@@ -1384,29 +1407,8 @@ EXPORT_SYMBOL (usb_bus_start_enum);
*/
void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
{
- int at_root_hub;
-
- at_root_hub = (urb->dev == hcd->self.root_hub);
urb_unlink (urb);
-
- /* lower level hcd code should use *_dma exclusively if the
- * host controller does DMA */
- if (hcd->self.uses_dma && !at_root_hub) {
- if (usb_pipecontrol (urb->pipe)
- && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
- dma_unmap_single (hcd->self.controller, urb->setup_dma,
- sizeof (struct usb_ctrlrequest),
- DMA_TO_DEVICE);
- if (urb->transfer_buffer_length != 0
- && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
- dma_unmap_single (hcd->self.controller,
- urb->transfer_dma,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
- ? DMA_FROM_DEVICE
- : DMA_TO_DEVICE);
- }
-
+ usb_hcd_unmap_dma (hcd, urb);
usbmon_urb_complete (&hcd->self, urb);
/* pass ownership to the completion handler */
urb->complete (urb);
-------------------------------------------------------------------------
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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel