aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Morell <rmorell@nvidia.com>2011-01-26 22:06:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-04 14:48:55 -0500
commit2694a48d9007a8bdf1731c1b97d4942c9cc49296 (patch)
tree9f5394c7aca54d6ee0565428e91c12f240be89bd
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>
-rw-r--r--drivers/usb/core/hcd.c22
-rw-r--r--include/linux/usb.h1
-rw-r--r--include/linux/usb/hcd.h15
3 files changed, 36 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)
1281} 1281}
1282EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_setup_for_dma); 1282EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_setup_for_dma);
1283 1283
1284static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
1285{
1286 if (hcd->driver->unmap_urb_for_dma)
1287 hcd->driver->unmap_urb_for_dma(hcd, urb);
1288 else
1289 usb_hcd_unmap_urb_for_dma(hcd, urb);
1290}
1291
1284void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 1292void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
1285{ 1293{
1286 enum dma_data_direction dir; 1294 enum dma_data_direction dir;
@@ -1319,6 +1327,15 @@ EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_for_dma);
1319static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 1327static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1320 gfp_t mem_flags) 1328 gfp_t mem_flags)
1321{ 1329{
1330 if (hcd->driver->map_urb_for_dma)
1331 return hcd->driver->map_urb_for_dma(hcd, urb, mem_flags);
1332 else
1333 return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
1334}
1335
1336int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1337 gfp_t mem_flags)
1338{
1322 enum dma_data_direction dir; 1339 enum dma_data_direction dir;
1323 int ret = 0; 1340 int ret = 0;
1324 1341
@@ -1414,6 +1431,7 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1414 } 1431 }
1415 return ret; 1432 return ret;
1416} 1433}
1434EXPORT_SYMBOL_GPL(usb_hcd_map_urb_for_dma);
1417 1435
1418/*-------------------------------------------------------------------------*/ 1436/*-------------------------------------------------------------------------*/
1419 1437
@@ -1451,7 +1469,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
1451 if (likely(status == 0)) { 1469 if (likely(status == 0)) {
1452 status = hcd->driver->urb_enqueue(hcd, urb, mem_flags); 1470 status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);
1453 if (unlikely(status)) 1471 if (unlikely(status))
1454 usb_hcd_unmap_urb_for_dma(hcd, urb); 1472 unmap_urb_for_dma(hcd, urb);
1455 } 1473 }
1456 } 1474 }
1457 1475
@@ -1557,7 +1575,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
1557 !status)) 1575 !status))
1558 status = -EREMOTEIO; 1576 status = -EREMOTEIO;
1559 1577
1560 usb_hcd_unmap_urb_for_dma(hcd, urb); 1578 unmap_urb_for_dma(hcd, urb);
1561 usbmon_urb_complete(&hcd->self, urb, status); 1579 usbmon_urb_complete(&hcd->self, urb, status);
1562 usb_unanchor_urb(urb); 1580 usb_unanchor_urb(urb);
1563 1581
diff --git a/include/linux/usb.h b/include/linux/usb.h
index bd69b65f3356..e63efeb378e3 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -976,6 +976,7 @@ extern int usb_disabled(void);
976#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */ 976#define URB_SETUP_MAP_SINGLE 0x00100000 /* Setup packet DMA mapped */
977#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */ 977#define URB_SETUP_MAP_LOCAL 0x00200000 /* HCD-local setup packet */
978#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */ 978#define URB_DMA_SG_COMBINED 0x00400000 /* S-G entries were combined */
979#define URB_ALIGNED_TEMP_BUFFER 0x00800000 /* Temp buffer was alloc'd */
979 980
980struct usb_iso_packet_descriptor { 981struct usb_iso_packet_descriptor {
981 unsigned int offset; 982 unsigned int offset;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 395704bdf5cc..92b96fe39307 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -233,6 +233,19 @@ struct hc_driver {
233 int (*urb_dequeue)(struct usb_hcd *hcd, 233 int (*urb_dequeue)(struct usb_hcd *hcd,
234 struct urb *urb, int status); 234 struct urb *urb, int status);
235 235
236 /*
237 * (optional) these hooks allow an HCD to override the default DMA
238 * mapping and unmapping routines. In general, they shouldn't be
239 * necessary unless the host controller has special DMA requirements,
240 * such as alignment contraints. If these are not specified, the
241 * general usb_hcd_(un)?map_urb_for_dma functions will be used instead
242 * (and it may be a good idea to call these functions in your HCD
243 * implementation)
244 */
245 int (*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
246 gfp_t mem_flags);
247 void (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
248
236 /* hw synch, freeing endpoint resources that urb_dequeue can't */ 249 /* hw synch, freeing endpoint resources that urb_dequeue can't */
237 void (*endpoint_disable)(struct usb_hcd *hcd, 250 void (*endpoint_disable)(struct usb_hcd *hcd,
238 struct usb_host_endpoint *ep); 251 struct usb_host_endpoint *ep);
@@ -329,6 +342,8 @@ extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
329extern int usb_hcd_unlink_urb(struct urb *urb, int status); 342extern int usb_hcd_unlink_urb(struct urb *urb, int status);
330extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, 343extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
331 int status); 344 int status);
345extern int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
346 gfp_t mem_flags);
332extern void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *); 347extern void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
333extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *); 348extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
334extern void usb_hcd_flush_endpoint(struct usb_device *udev, 349extern void usb_hcd_flush_endpoint(struct usb_device *udev,