staging: octeon-usb: use usb_hcd_link_urb_to_ep()
authorAaro Koskinen <aaro.koskinen@iki.fi>
Sun, 29 Jun 2014 19:52:53 +0000 (22:52 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 Jul 2014 23:39:22 +0000 (16:39 -0700)
The driver did not use link_urb_to_ep() / unlink_urb_from_ep(). This
caused odd behaviour in some error recovery situations, all requests
would start to fail after the first failure.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/octeon-usb/octeon-hcd.c

index fca4d3407eb64be829b46a96462a3b19f75ad5ed..ab237c5b61b517b9101eff4c65f4af0817c12275 100644 (file)
@@ -2230,6 +2230,7 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb,
                urb->status = -EPROTO;
                break;
        }
+       usb_hcd_unlink_urb_from_ep(octeon_to_hcd(priv), urb);
        spin_unlock(&priv->lock);
        usb_hcd_giveback_urb(octeon_to_hcd(priv), urb, urb->status);
        spin_lock(&priv->lock);
@@ -3291,10 +3292,17 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
        unsigned long flags;
        struct cvmx_usb_iso_packet *iso_packet;
        struct usb_host_endpoint *ep = urb->ep;
+       int rc;
 
        urb->status = 0;
        spin_lock_irqsave(&priv->lock, flags);
 
+       rc = usb_hcd_link_urb_to_ep(hcd, urb);
+       if (rc) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return rc;
+       }
+
        if (!ep->hcpriv) {
                enum cvmx_usb_transfer transfer_type;
                enum cvmx_usb_speed speed;
@@ -3370,6 +3378,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
                                           >> 11) & 0x3,
                                          split_device, split_port);
                if (!pipe) {
+                       usb_hcd_unlink_urb_from_ep(hcd, urb);
                        spin_unlock_irqrestore(&priv->lock, flags);
                        dev_dbg(dev, "Failed to create pipe\n");
                        return -ENOMEM;
@@ -3440,6 +3449,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
                break;
        }
        if (!transaction) {
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
                spin_unlock_irqrestore(&priv->lock, flags);
                dev_dbg(dev, "Failed to submit\n");
                return -ENOMEM;
@@ -3455,18 +3465,24 @@ static int octeon_usb_urb_dequeue(struct usb_hcd *hcd,
 {
        struct octeon_hcd *priv = hcd_to_octeon(hcd);
        unsigned long flags;
+       int rc;
 
        if (!urb->dev)
                return -EINVAL;
 
        spin_lock_irqsave(&priv->lock, flags);
 
+       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
+       if (rc)
+               goto out;
+
        urb->status = status;
        cvmx_usb_cancel(&priv->usb, urb->ep->hcpriv, urb->hcpriv);
 
+out:
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       return 0;
+       return rc;
 }
 
 static void octeon_usb_endpoint_disable(struct usb_hcd *hcd,