diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-08-08 11:48:02 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:55:10 -0400 |
commit | e9df41c5c5899259541dc928872cad4d07b82076 (patch) | |
tree | 12bb0917eeecbe62b2b5d3dc576806c7f2728550 /drivers/usb/host/uhci-q.c | |
parent | b0e396e3097ce4914c643bc3f0c2fe0098f551eb (diff) |
USB: make HCDs responsible for managing endpoint queues
This patch (as954) implements a suggestion of David Brownell's. Now
the host controller drivers are responsible for linking and unlinking
URBs to/from their endpoint queues. This eliminates the possiblity of
strange situations where usbcore thinks an URB is linked but the HCD
thinks it isn't. It also means HCDs no longer have to check for URBs
being dequeued before they were fully enqueued.
In addition to the core changes, this requires changing every host
controller driver and the root-hub URB handler. For the most part the
required changes are fairly small; drivers have to call
usb_hcd_link_urb_to_ep() in their urb_enqueue method,
usb_hcd_check_unlink_urb() in their urb_dequeue method, and
usb_hcd_unlink_urb_from_ep() before giving URBs back. A few HCDs make
matters more complicated by the way they split up the flow of control.
In addition some method interfaces get changed. The endpoint argument
for urb_enqueue is now redundant so it is removed. The unlink status
is required by usb_hcd_check_unlink_urb(), so it has been added to
urb_dequeue.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
CC: Olav Kongas <ok@artecdesign.ee>
CC: Tony Olech <tony.olech@elandigitalsystems.com>
CC: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
-rw-r--r-- | drivers/usb/host/uhci-q.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 3bb908ca38e..bff200cb3d2 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -1376,7 +1376,6 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
1376 | } | 1376 | } |
1377 | 1377 | ||
1378 | static int uhci_urb_enqueue(struct usb_hcd *hcd, | 1378 | static int uhci_urb_enqueue(struct usb_hcd *hcd, |
1379 | struct usb_host_endpoint *hep, | ||
1380 | struct urb *urb, gfp_t mem_flags) | 1379 | struct urb *urb, gfp_t mem_flags) |
1381 | { | 1380 | { |
1382 | int ret; | 1381 | int ret; |
@@ -1387,19 +1386,19 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1387 | 1386 | ||
1388 | spin_lock_irqsave(&uhci->lock, flags); | 1387 | spin_lock_irqsave(&uhci->lock, flags); |
1389 | 1388 | ||
1390 | ret = urb->status; | 1389 | ret = usb_hcd_link_urb_to_ep(hcd, urb); |
1391 | if (ret != -EINPROGRESS) /* URB already unlinked! */ | 1390 | if (ret) |
1392 | goto done; | 1391 | goto done_not_linked; |
1393 | 1392 | ||
1394 | ret = -ENOMEM; | 1393 | ret = -ENOMEM; |
1395 | urbp = uhci_alloc_urb_priv(uhci, urb); | 1394 | urbp = uhci_alloc_urb_priv(uhci, urb); |
1396 | if (!urbp) | 1395 | if (!urbp) |
1397 | goto done; | 1396 | goto done; |
1398 | 1397 | ||
1399 | if (hep->hcpriv) | 1398 | if (urb->ep->hcpriv) |
1400 | qh = (struct uhci_qh *) hep->hcpriv; | 1399 | qh = urb->ep->hcpriv; |
1401 | else { | 1400 | else { |
1402 | qh = uhci_alloc_qh(uhci, urb->dev, hep); | 1401 | qh = uhci_alloc_qh(uhci, urb->dev, urb->ep); |
1403 | if (!qh) | 1402 | if (!qh) |
1404 | goto err_no_qh; | 1403 | goto err_no_qh; |
1405 | } | 1404 | } |
@@ -1440,27 +1439,29 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1440 | err_submit_failed: | 1439 | err_submit_failed: |
1441 | if (qh->state == QH_STATE_IDLE) | 1440 | if (qh->state == QH_STATE_IDLE) |
1442 | uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ | 1441 | uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ |
1443 | |||
1444 | err_no_qh: | 1442 | err_no_qh: |
1445 | uhci_free_urb_priv(uhci, urbp); | 1443 | uhci_free_urb_priv(uhci, urbp); |
1446 | |||
1447 | done: | 1444 | done: |
1445 | if (ret) | ||
1446 | usb_hcd_unlink_urb_from_ep(hcd, urb); | ||
1447 | done_not_linked: | ||
1448 | spin_unlock_irqrestore(&uhci->lock, flags); | 1448 | spin_unlock_irqrestore(&uhci->lock, flags); |
1449 | return ret; | 1449 | return ret; |
1450 | } | 1450 | } |
1451 | 1451 | ||
1452 | static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | 1452 | static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) |
1453 | { | 1453 | { |
1454 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 1454 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
1455 | unsigned long flags; | 1455 | unsigned long flags; |
1456 | struct urb_priv *urbp; | ||
1457 | struct uhci_qh *qh; | 1456 | struct uhci_qh *qh; |
1457 | int rc; | ||
1458 | 1458 | ||
1459 | spin_lock_irqsave(&uhci->lock, flags); | 1459 | spin_lock_irqsave(&uhci->lock, flags); |
1460 | urbp = urb->hcpriv; | 1460 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); |
1461 | if (!urbp) /* URB was never linked! */ | 1461 | if (rc) |
1462 | goto done; | 1462 | goto done; |
1463 | qh = urbp->qh; | 1463 | |
1464 | qh = ((struct urb_priv *) urb->hcpriv)->qh; | ||
1464 | 1465 | ||
1465 | /* Remove Isochronous TDs from the frame list ASAP */ | 1466 | /* Remove Isochronous TDs from the frame list ASAP */ |
1466 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { | 1467 | if (qh->type == USB_ENDPOINT_XFER_ISOC) { |
@@ -1477,7 +1478,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
1477 | 1478 | ||
1478 | done: | 1479 | done: |
1479 | spin_unlock_irqrestore(&uhci->lock, flags); | 1480 | spin_unlock_irqrestore(&uhci->lock, flags); |
1480 | return 0; | 1481 | return rc; |
1481 | } | 1482 | } |
1482 | 1483 | ||
1483 | /* | 1484 | /* |
@@ -1529,6 +1530,7 @@ __acquires(uhci->lock) | |||
1529 | } | 1530 | } |
1530 | 1531 | ||
1531 | uhci_free_urb_priv(uhci, urbp); | 1532 | uhci_free_urb_priv(uhci, urbp); |
1533 | usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb); | ||
1532 | 1534 | ||
1533 | spin_unlock(&uhci->lock); | 1535 | spin_unlock(&uhci->lock); |
1534 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); | 1536 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); |