summaryrefslogtreecommitdiff
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
authorRobert Morell <rmorell@nvidia.com>2011-01-26 19:06:48 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 11:48:55 -0800
commit2694a48d9007a8bdf1731c1b97d4942c9cc49296 (patch)
tree9f5394c7aca54d6ee0565428e91c12f240be89bd /drivers/usb/core/hcd.c
parentc8cf203a1d228fa001b95534f639ffb7a23d5386 (diff)
USB: HCD: Add driver hooks for (un)?map_urb_for_dma
Provide optional hooks for the host controller driver to override the default DMA mapping and unmapping routines. In general, these shouldn't be necessary unless the host controller has special DMA requirements, such as alignment contraints. If these are not specified, the general usb_hcd_(un)?map_urb_for_dma functions will be used instead. Also, pass the status to unmap_urb_for_dma so it can know whether the DMA buffer has been overwritten. Finally, add a flag to be used by these implementations if they allocated a temporary buffer so it can be freed properly when unmapping. Signed-off-by: Robert Morell <rmorell@nvidia.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 335c1ddb260d..d0b782c4523a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1281,6 +1281,14 @@ void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
}
EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_setup_for_dma);
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+ if (hcd->driver->unmap_urb_for_dma)
+ hcd->driver->unmap_urb_for_dma(hcd, urb);
+ else
+ usb_hcd_unmap_urb_for_dma(hcd, urb);
+}
+
void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
{
enum dma_data_direction dir;
@@ -1319,6 +1327,15 @@ EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_for_dma);
static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
gfp_t mem_flags)
{
+ if (hcd->driver->map_urb_for_dma)
+ return hcd->driver->map_urb_for_dma(hcd, urb, mem_flags);
+ else
+ return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+}
+
+int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
enum dma_data_direction dir;
int ret = 0;
@@ -1414,6 +1431,7 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
}
return ret;
}
+EXPORT_SYMBOL_GPL(usb_hcd_map_urb_for_dma);
/*-------------------------------------------------------------------------*/
@@ -1451,7 +1469,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
if (likely(status == 0)) {
status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
if (unlikely(status))
- usb_hcd_unmap_urb_for_dma(hcd, urb);
+ unmap_urb_for_dma(hcd, urb);
}
}
@@ -1557,7 +1575,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
!status))
status = -EREMOTEIO;
- usb_hcd_unmap_urb_for_dma(hcd, urb);
+ unmap_urb_for_dma(hcd, urb);
usbmon_urb_complete(&hcd->self, urb, status);
usb_unanchor_urb(urb);