Release DMA resources if submission fails in the HCD.

Signed-Off-By: Pete Zaitcev <[EMAIL PROTECTED]>

---

> Amazing indeed.

Just for the record, I didn't find it just by looking. IBM filed a bug
RH#236922 after they ran out of IOMMU. Our (older) uhci-hcd was rejecting
bulk requests sent to interrupt endpoints, so running their management
application on the GA kernel depletes sw-iommu.

> Do you think your new routine should be merged with urb_unlink()?   The 
> two always get called together.

Probably a good idea. How about now?

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e277258..3d657ba 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -901,17 +901,32 @@ EXPORT_SYMBOL (usb_calc_bus_time);
 
 /*-------------------------------------------------------------------------*/
 
-static void urb_unlink (struct urb *urb)
+static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
 {
        unsigned long           flags;
+       int at_root_hub = (urb->dev == hcd->self.root_hub);
 
        /* clear all state linking urb to this dev (and hcd) */
-
        spin_lock_irqsave (&hcd_data_lock, flags);
        list_del_init (&urb->urb_list);
        spin_unlock_irqrestore (&hcd_data_lock, flags);
-}
 
+       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
@@ -1014,7 +1029,7 @@ doit:
        status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
 done:
        if (unlikely (status)) {
-               urb_unlink (urb);
+               urb_unlink(hcd, urb);
                atomic_dec (&urb->use_count);
                if (urb->reject)
                        wake_up (&usb_kill_urb_queue);
@@ -1384,29 +1399,7 @@ 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);
-       }
-
+       urb_unlink(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/
_______________________________________________
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