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