aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-q.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/uhci-q.c')
-rw-r--r--drivers/usb/host/uhci-q.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 3bb908ca38e9..bff200cb3d2e 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
1378static int uhci_urb_enqueue(struct usb_hcd *hcd, 1378static 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,
1440err_submit_failed: 1439err_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
1444err_no_qh: 1442err_no_qh:
1445 uhci_free_urb_priv(uhci, urbp); 1443 uhci_free_urb_priv(uhci, urbp);
1446
1447done: 1444done:
1445 if (ret)
1446 usb_hcd_unlink_urb_from_ep(hcd, urb);
1447done_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
1452static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 1452static 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
1478done: 1479done:
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);