USB: centralize -EREMOTEIO handling
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 21 Aug 2007 19:39:21 +0000 (15:39 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 12 Oct 2007 21:55:19 +0000 (14:55 -0700)
This patch (as969) continues the ongoing changes to the way HCDs
report URB statuses.  The programming interface has been simplified by
making usbcore responsible for clearing urb->hcpriv and for setting
-EREMOTEIO status when an URB with the URB_SHORT_NOT_OK flag ends up
as a short transfer.

By moving the work out of the HCDs, this removes a fair amount of
repeated code.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
CC: Olav Kongas <ok@artecdesign.ee>
CC: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
CC: Tony Olech <tony.olech@elandigitalsystems.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hcd.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/host/ehci-q.c
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/ohci-q.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-q.c

index a853f63..22a098b 100644 (file)
@@ -366,6 +366,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
        spin_unlock_irq(&hcd_root_hub_lock);
        if (status)
                return status;
+       urb->hcpriv = hcd;      /* Indicate it's queued */
 
        cmd = (struct usb_ctrlrequest *) urb->setup_packet;
        typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
@@ -579,7 +580,6 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
                        hcd->poll_pending = 0;
                        hcd->status_urb = NULL;
                        urb->status = 0;
-                       urb->hcpriv = NULL;
                        urb->actual_length = length;
                        memcpy(urb->transfer_buffer, buffer, length);
 
@@ -675,7 +675,6 @@ static int usb_rh_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        del_timer (&hcd->rh_timer);
                if (urb == hcd->status_urb) {
                        hcd->status_urb = NULL;
-                       urb->hcpriv = NULL;
                        usb_hcd_unlink_urb_from_ep(hcd, urb);
 
                        spin_unlock(&hcd_root_hub_lock);
@@ -1192,6 +1191,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
        if (unlikely(status)) {
                usbmon_urb_submit_error(&hcd->self, urb, status);
                unmap_urb_for_dma(hcd, urb);
+               urb->hcpriv = NULL;
                INIT_LIST_HEAD(&urb->urb_list);
                atomic_dec(&urb->use_count);
                if (urb->reject)
@@ -1265,6 +1265,11 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
        unmap_urb_for_dma(hcd, urb);
        usbmon_urb_complete (&hcd->self, urb);
        usb_unanchor_urb(urb);
+       urb->hcpriv = NULL;
+       if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
+                       urb->actual_length < urb->transfer_buffer_length &&
+                       !urb->status))
+               urb->status = -EREMOTEIO;
 
        /* pass ownership to the completion handler */
        urb->complete (urb);
index c441d10..0cb0325 100644 (file)
@@ -1099,8 +1099,7 @@ top:
                 *
                 * partially filling a buffer optionally blocks queue advances
                 * (so completion handlers can clean up the queue) but we don't
-                * need to emulate such data-in-flight.  so we only show part
-                * of the URB_SHORT_NOT_OK effect: completion status.
+                * need to emulate such data-in-flight.
                 */
                if (is_short) {
                        if (host_len == dev_len) {
@@ -1111,10 +1110,7 @@ top:
                                if (dev_len > host_len)
                                        maybe_set_status (urb, -EOVERFLOW);
                                else
-                                       maybe_set_status (urb,
-                                               (urb->transfer_flags
-                                                       & URB_SHORT_NOT_OK)
-                                               ? -EREMOTEIO : 0);
+                                       maybe_set_status (urb, 0);
                        } else if (!to_host) {
                                maybe_set_status (urb, 0);
                                if (host_len > dev_len)
@@ -1516,7 +1512,6 @@ restart:
                        continue;
 
 return_urb:
-               urb->hcpriv = NULL;
                list_del (&urbp->urbp_list);
                kfree (urbp);
                if (ep)
index 1da2de4..e80b5c4 100644 (file)
@@ -232,7 +232,6 @@ __acquires(ehci->lock)
        }
 
        spin_lock (&urb->lock);
-       urb->hcpriv = NULL;
        switch (urb->status) {
        case -EINPROGRESS:              /* success */
                urb->status = 0;
@@ -395,8 +394,10 @@ halt:
                /* remove it from the queue */
                spin_lock (&urb->lock);
                qtd_copy_status (ehci, urb, qtd->length, token);
-               do_status = (urb->status == -EREMOTEIO)
-                               && usb_pipecontrol (urb->pipe);
+               if (unlikely(urb->status == -EREMOTEIO)) {
+                       do_status = usb_pipecontrol(urb->pipe);
+                       urb->status = 0;
+               }
                spin_unlock (&urb->lock);
 
                if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
index f2b5d62..c2919db 100644 (file)
@@ -282,7 +282,6 @@ __releases(isp116x->lock) __acquires(isp116x->lock)
 {
        unsigned i;
 
-       urb->hcpriv = NULL;
        ep->error_count = 0;
 
        if (usb_pipecontrol(urb->pipe))
@@ -446,12 +445,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
                        if (PTD_GET_ACTIVE(ptd)
                            || (cc != TD_CC_NOERROR && cc < 0x0E))
                                break;
-                       if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
-                                       urb->actual_length <
-                                               urb->transfer_buffer_length)
-                               status = -EREMOTEIO;
-                       else
-                               status = 0;
+                       status = 0;
                        ep->nextpid = 0;
                        break;
                default:
index 889c072..8aad619 100644 (file)
@@ -43,21 +43,10 @@ __acquires(ohci->lock)
        // ASSERT (urb->hcpriv != 0);
 
        urb_free_priv (ohci, urb->hcpriv);
-       urb->hcpriv = NULL;
 
        spin_lock (&urb->lock);
        if (likely (urb->status == -EINPROGRESS))
                urb->status = 0;
-       /* report short control reads right even though the data TD always
-        * has TD_R set.  (much simpler, but creates the 1-td limit.)
-        */
-       if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
-                       && unlikely (usb_pipecontrol (urb->pipe))
-                       && urb->actual_length < urb->transfer_buffer_length
-                       && usb_pipein (urb->pipe)
-                       && urb->status == 0) {
-               urb->status = -EREMOTEIO;
-       }
        spin_unlock (&urb->lock);
 
        switch (usb_pipetype (urb->pipe)) {
index 49cf998..60248b0 100644 (file)
@@ -783,7 +783,6 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
 
                if (urb) {
                        urb->status = -ENODEV;
-                       urb->hcpriv = NULL;
                        usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
                                        urb);
 
@@ -1134,7 +1133,6 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
                if (usb_pipeisoc(urb->pipe))
                        urb->start_frame = r8a66597_get_frame(hcd);
 
-               urb->hcpriv = NULL;
                usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
 
                spin_unlock(&r8a66597->lock);
@@ -1202,9 +1200,6 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
                td->zero_packet = 1;
        if (rcv_len < bufsize) {
                td->short_packet = 1;
-               if (urb->transfer_buffer_length != urb->actual_length &&
-                   urb->transfer_flags & URB_SHORT_NOT_OK)
-                       status = -EREMOTEIO;
        }
        if (usb_pipeisoc(urb->pipe)) {
                urb->iso_frame_desc[td->iso_cnt].actual_length = size;
@@ -1214,7 +1209,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
        }
 
        /* check transfer finish */
-       if (check_transfer_finish(td, urb)) {
+       if (finish || check_transfer_finish(td, urb)) {
                pipe_stop(r8a66597, td->pipe);
                pipe_irq_disable(r8a66597, pipenum);
                finish = 1;
index 15a93f9..e90953a 100644 (file)
@@ -438,7 +438,6 @@ static void finish_request(
        spin_lock(&urb->lock);
        if (urb->status == -EINPROGRESS)
                urb->status = status;
-       urb->hcpriv = NULL;
        spin_unlock(&urb->lock);
 
        usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
@@ -545,17 +544,10 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
                        sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0),
                                        buf, len);
                        usb_dotoggle(udev, ep->epnum, 0);
-                       if (urb->actual_length == urb->transfer_buffer_length)
+                       if (urb->actual_length == urb->transfer_buffer_length
+                                       || len < ep->maxpacket)
                                urbstat = 0;
-                       else if (len < ep->maxpacket) {
-                               if (urb->transfer_flags & URB_SHORT_NOT_OK)
-                                       urbstat = -EREMOTEIO;
-                               else
-                                       urbstat = 0;
-                       }
-                       if (usb_pipecontrol(urb->pipe)
-                                       && (urbstat == -EREMOTEIO
-                                               || urbstat == 0)) {
+                       if (usb_pipecontrol(urb->pipe) && urbstat == 0) {
 
                                /* NOTE if the status stage STALLs (why?),
                                 * this reports the wrong urb status.
index c87660b..1381275 100644 (file)
@@ -519,7 +519,6 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
         struct usb_hcd *hcd = u132_to_hcd(u132);
         urb->error_count = 0;
         urb->status = status;
-        urb->hcpriv = NULL;
         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
         endp->queue_next += 1;
@@ -560,7 +559,6 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
         struct usb_hcd *hcd = u132_to_hcd(u132);
         urb->error_count = 0;
         urb->status = status;
-        urb->hcpriv = NULL;
         spin_lock_irqsave(&endp->queue_lock.slock, irqs);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
         endp->queue_next += 1;
@@ -2430,7 +2428,6 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
                         list_del(scan);
                         endp->queue_size -= 1;
                         urb->error_count = 0;
-                        urb->hcpriv = NULL;
                         usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else
@@ -2472,7 +2469,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
                         endp->edset_flush = 1;
                         u132_endp_queue_work(u132, endp, 0);
                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
-                        urb->hcpriv = NULL;
                         return 0;
                 } else {
                         spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
@@ -2517,7 +2513,6 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
                                         irqs);
                                 kfree(urbq);
                         } urb->error_count = 0;
-                        urb->hcpriv = NULL;
                         usb_hcd_giveback_urb(hcd, urb);
                         return 0;
                 } else if (list_empty(&endp->urb_more)) {
index 793a046..fbc3af3 100644 (file)
@@ -757,7 +757,6 @@ static void uhci_free_urb_priv(struct uhci_hcd *uhci,
                uhci_free_td(uhci, td);
        }
 
-       urbp->urb->hcpriv = NULL;
        kmem_cache_free(uhci_up_cachep, urbp);
 }
 
@@ -1494,13 +1493,6 @@ __acquires(uhci->lock)
                 * unlinked first.  Regardless, don't confuse people with a
                 * negative length. */
                urb->actual_length = max(urb->actual_length, 0);
-
-               /* Report erroneous short transfers */
-               if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
-                               urb->actual_length <
-                                       urb->transfer_buffer_length &&
-                               urb->status == 0))
-                       urb->status = -EREMOTEIO;
        }
 
        /* When giving back the first URB in an Isochronous queue,