aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-09-10 11:33:05 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:26 -0400
commit95cf82f99cfbd697c15572c444bd4f54f19745b0 (patch)
tree87d0bd6c842922231f5177522b6635532416d206 /drivers/usb
parent5ad4f71e2f19a06f738463da1f09ea7fda3a3db2 (diff)
USB: break apart flush_endpoint and disable_endpoint
This patch (as988) breaks usb_hcd_endpoint_disable() apart into two routines. The first, usb_hcd_flush_endpoint() does the -ESHUTDOWN unlinking of all URBs in the endpoint's queue and waits for them to complete. The second, usb_hcd_disable_endpoint() -- renamed for better grammatical style -- merely calls the HCD's endpoint_disable method. The changeover is easy because the routine currently has only one caller. This separation of function will be exploited in the following patch: When a device is suspended, the core will be able to cancel all outstanding URBs for that device while leaving the HCD's endpoint-related data structures intact for later. As an added benefit, HCDs no longer need to check for existing URBs in their endpoint_disable methods. It is now guaranteed that there will be none. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hcd.c48
-rw-r--r--drivers/usb/core/hcd.h4
-rw-r--r--drivers/usb/core/message.c3
3 files changed, 32 insertions, 23 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1c5e5d35e08d..e5874e8b8cbc 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1289,24 +1289,22 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb);
1289 1289
1290/*-------------------------------------------------------------------------*/ 1290/*-------------------------------------------------------------------------*/
1291 1291
1292/* disables the endpoint: cancels any pending urbs, then synchronizes with 1292/* Cancel all URBs pending on this endpoint and wait for the endpoint's
1293 * the hcd to make sure all endpoint state is gone from hardware, and then 1293 * queue to drain completely. The caller must first insure that no more
1294 * waits until the endpoint's queue is completely drained. use for 1294 * URBs can be submitted for this endpoint.
1295 * set_configuration, set_interface, driver removal, physical disconnect.
1296 *
1297 * example: a qh stored in ep->hcpriv, holding state related to endpoint
1298 * type, maxpacket size, toggle, halt status, and scheduling.
1299 */ 1295 */
1300void usb_hcd_endpoint_disable (struct usb_device *udev, 1296void usb_hcd_flush_endpoint(struct usb_device *udev,
1301 struct usb_host_endpoint *ep) 1297 struct usb_host_endpoint *ep)
1302{ 1298{
1303 struct usb_hcd *hcd; 1299 struct usb_hcd *hcd;
1304 struct urb *urb; 1300 struct urb *urb;
1305 1301
1302 if (!ep)
1303 return;
1306 might_sleep(); 1304 might_sleep();
1307 hcd = bus_to_hcd(udev->bus); 1305 hcd = bus_to_hcd(udev->bus);
1308 1306
1309 /* ep is already gone from udev->ep_{in,out}[]; no more submits */ 1307 /* No more submits can occur */
1310rescan: 1308rescan:
1311 spin_lock_irq(&hcd_urb_list_lock); 1309 spin_lock_irq(&hcd_urb_list_lock);
1312 list_for_each_entry (urb, &ep->urb_list, urb_list) { 1310 list_for_each_entry (urb, &ep->urb_list, urb_list) {
@@ -1345,18 +1343,7 @@ rescan:
1345 } 1343 }
1346 spin_unlock_irq(&hcd_urb_list_lock); 1344 spin_unlock_irq(&hcd_urb_list_lock);
1347 1345
1348 /* synchronize with the hardware, so old configuration state 1346 /* Wait until the endpoint queue is completely empty */
1349 * clears out immediately (and will be freed).
1350 */
1351 if (hcd->driver->endpoint_disable)
1352 hcd->driver->endpoint_disable (hcd, ep);
1353
1354 /* Wait until the endpoint queue is completely empty. Most HCDs
1355 * will have done this already in their endpoint_disable method,
1356 * but some might not. And there could be root-hub control URBs
1357 * still pending since they aren't affected by the HCDs'
1358 * endpoint_disable methods.
1359 */
1360 while (!list_empty (&ep->urb_list)) { 1347 while (!list_empty (&ep->urb_list)) {
1361 spin_lock_irq(&hcd_urb_list_lock); 1348 spin_lock_irq(&hcd_urb_list_lock);
1362 1349
@@ -1376,6 +1363,25 @@ rescan:
1376 } 1363 }
1377} 1364}
1378 1365
1366/* Disables the endpoint: synchronizes with the hcd to make sure all
1367 * endpoint state is gone from hardware. usb_hcd_flush_endpoint() must
1368 * have been called previously. Use for set_configuration, set_interface,
1369 * driver removal, physical disconnect.
1370 *
1371 * example: a qh stored in ep->hcpriv, holding state related to endpoint
1372 * type, maxpacket size, toggle, halt status, and scheduling.
1373 */
1374void usb_hcd_disable_endpoint(struct usb_device *udev,
1375 struct usb_host_endpoint *ep)
1376{
1377 struct usb_hcd *hcd;
1378
1379 might_sleep();
1380 hcd = bus_to_hcd(udev->bus);
1381 if (hcd->driver->endpoint_disable)
1382 hcd->driver->endpoint_disable(hcd, ep);
1383}
1384
1379/*-------------------------------------------------------------------------*/ 1385/*-------------------------------------------------------------------------*/
1380 1386
1381/* called in any context */ 1387/* called in any context */
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 0fc7b95259f5..1396141274f1 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -219,7 +219,9 @@ extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
219extern int usb_hcd_unlink_urb (struct urb *urb, int status); 219extern int usb_hcd_unlink_urb (struct urb *urb, int status);
220extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, 220extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
221 int status); 221 int status);
222extern void usb_hcd_endpoint_disable (struct usb_device *udev, 222extern void usb_hcd_flush_endpoint(struct usb_device *udev,
223 struct usb_host_endpoint *ep);
224extern void usb_hcd_disable_endpoint(struct usb_device *udev,
223 struct usb_host_endpoint *ep); 225 struct usb_host_endpoint *ep);
224extern int usb_hcd_get_frame_number (struct usb_device *udev); 226extern int usb_hcd_get_frame_number (struct usb_device *udev);
225 227
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d638375e22e7..98fcddba6908 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1017,7 +1017,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
1017 } 1017 }
1018 if (ep) { 1018 if (ep) {
1019 ep->enabled = 0; 1019 ep->enabled = 0;
1020 usb_hcd_endpoint_disable(dev, ep); 1020 usb_hcd_flush_endpoint(dev, ep);
1021 usb_hcd_disable_endpoint(dev, ep);
1021 } 1022 }
1022} 1023}
1023 1024