From eb23105462304fd35571fd0cab1de7aec79a9ec5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 21 Aug 2007 15:40:36 -0400 Subject: USB: add urb->unlinked field This patch (as970) adds a new urb->unlinked field, which is used to store the status of unlinked URBs since we can't use urb->status for that purpose any more. To help simplify the HCDs, usbcore will check urb->unlinked before calling the completion handler; if the value is set it will automatically override the status reported by the HCD. Signed-off-by: Alan Stern CC: David Brownell CC: Olav Kongas CC: Yoshihiro Shimoda CC: Tony Olech Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 19 +++--- drivers/usb/gadget/dummy_hcd.c | 8 +-- drivers/usb/host/ehci-q.c | 29 ++++------ drivers/usb/host/isp116x-hcd.c | 5 +- drivers/usb/host/ohci-q.c | 5 +- drivers/usb/host/r8a66597-hcd.c | 24 +++----- drivers/usb/host/sl811-hcd.c | 5 +- drivers/usb/host/u132-hcd.c | 124 ++++++++++++++++++++-------------------- drivers/usb/host/uhci-debug.c | 4 +- drivers/usb/host/uhci-q.c | 9 +-- include/linux/usb.h | 1 + 11 files changed, 108 insertions(+), 125 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 22a098b..ec17fc4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -532,8 +532,7 @@ error: /* any errors get returned through the urb completion */ spin_lock_irq(&hcd_root_hub_lock); - if (urb->status == -EINPROGRESS) - urb->status = status; + urb->status = status; usb_hcd_unlink_urb_from_ep(hcd, urb); /* This peculiar use of spinlocks echoes what real HC drivers do. @@ -1024,6 +1023,7 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb) switch (hcd->state) { case HC_STATE_RUNNING: case HC_STATE_RESUMING: + urb->unlinked = 0; list_add_tail(&urb->urb_list, &urb->ep->urb_list); break; default: @@ -1071,9 +1071,9 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, /* Any status except -EINPROGRESS means something already started to * unlink this URB from the hardware. So there's no more work to do. */ - if (urb->status != -EINPROGRESS) + if (urb->unlinked) return -EBUSY; - urb->status = status; + urb->unlinked = status; /* IRQ setup can easily be broken so that USB controllers * never get completion IRQs ... maybe even the ones we need to @@ -1259,6 +1259,10 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) * (and is done using urb->hcpriv). It also released all HCD locks; * the device driver won't cause problems if it frees, modifies, * or resubmits this URB. + * + * If @urb was unlinked, the value of @urb->status will be overridden by + * @urb->unlinked. Erroneous short transfers are detected in case + * the HCD hasn't checked for them. */ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) { @@ -1266,7 +1270,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) usbmon_urb_complete (&hcd->self, urb); usb_unanchor_urb(urb); urb->hcpriv = NULL; - if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && + if (unlikely(urb->unlinked)) + urb->status = urb->unlinked; + else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && urb->actual_length < urb->transfer_buffer_length && !urb->status)) urb->status = -EREMOTEIO; @@ -1305,8 +1311,7 @@ rescan: list_for_each_entry (urb, &ep->urb_list, urb_list) { int is_in; - /* the urb may already have been unlinked */ - if (urb->status != -EINPROGRESS) + if (urb->unlinked) continue; usb_get_urb (urb); is_in = usb_urb_dir_in(urb); diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 0cb0325..f2b124c 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1029,8 +1029,7 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void maybe_set_status (struct urb *urb, int status) { spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = status; + urb->status = status; spin_unlock (&urb->lock); } @@ -1257,10 +1256,9 @@ restart: int type; urb = urbp->urb; - if (urb->status != -EINPROGRESS) { - /* likely it was just unlinked */ + if (urb->unlinked) goto return_urb; - } else if (dum->rh_state != DUMMY_RH_RUNNING) + else if (dum->rh_state != DUMMY_RH_RUNNING) continue; type = usb_pipetype (urb->pipe); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index e80b5c4..a8f5408 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -151,7 +151,7 @@ static void qtd_copy_status ( urb->actual_length += length - QTD_LENGTH (token); /* don't modify error codes */ - if (unlikely (urb->status != -EINPROGRESS)) + if (unlikely(urb->unlinked)) return; /* force cleanup after short read; not always an error */ @@ -232,21 +232,14 @@ __acquires(ehci->lock) } spin_lock (&urb->lock); - switch (urb->status) { - case -EINPROGRESS: /* success */ - urb->status = 0; - default: /* fault */ - COUNT (ehci->stats.complete); - break; - case -EREMOTEIO: /* fault or normal */ - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + if (unlikely(urb->unlinked)) { + COUNT(ehci->stats.unlink); + } else { + if (likely(urb->status == -EINPROGRESS || + (urb->status == -EREMOTEIO && + !(urb->transfer_flags & URB_SHORT_NOT_OK)))) urb->status = 0; - COUNT (ehci->stats.complete); - break; - case -ECONNRESET: /* canceled */ - case -ENOENT: - COUNT (ehci->stats.unlink); - break; + COUNT(ehci->stats.complete); } spin_unlock (&urb->lock); @@ -364,7 +357,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * for the urb faulted (including short read) or * its urb was canceled. we may patch qh or qtds. */ - if (likely (urb->status == -EINPROGRESS)) + if (likely(urb->status == -EINPROGRESS && + !urb->unlinked)) continue; /* issue status after short control reads */ @@ -395,7 +389,8 @@ halt: spin_lock (&urb->lock); qtd_copy_status (ehci, urb, qtd->length, token); if (unlikely(urb->status == -EREMOTEIO)) { - do_status = usb_pipecontrol(urb->pipe); + do_status = (!urb->unlinked && + usb_pipecontrol(urb->pipe)); urb->status = 0; } spin_unlock (&urb->lock); diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index c2919db..35b3507 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -455,11 +455,10 @@ static void postproc_atl_queue(struct isp116x *isp116x) done: if (status != -EINPROGRESS) { spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = status; + urb->status = status; spin_unlock(&urb->lock); } - if (urb->status != -EINPROGRESS) + if (urb->status != -EINPROGRESS || urb->unlinked) finish_request(isp116x, ep, urb); } } diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 8aad619..3c793fa 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -758,8 +758,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) cc = TD_CC_NOERROR; if (cc != TD_CC_NOERROR && cc < 0x0E) { spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = cc_to_error [cc]; + urb->status = cc_to_error[cc]; spin_unlock (&urb->lock); } @@ -972,7 +971,7 @@ rescan_this: urb = td->urb; urb_priv = td->urb->hcpriv; - if (urb->status == -EINPROGRESS) { + if (!urb->unlinked) { prev = &td->hwNextTD; continue; } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 60248b0..98b9e05 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1118,7 +1118,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock) r8a66597->timeout_map &= ~(1 << pipenum); if (likely(td)) { - if (td->set_address && urb->status != 0) + if (td->set_address && (urb->status != 0 || urb->unlinked)) r8a66597->address_map &= ~(1 << urb->setup_packet[2]); pipe_toggle_save(r8a66597, td->pipe, urb); @@ -1225,8 +1225,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) } if (finish && pipenum != 0) { - if (td->urb->status == -EINPROGRESS) - td->urb->status = status; + td->urb->status = status; finish_request(r8a66597, td, pipenum, urb); } } @@ -1308,32 +1307,24 @@ static void check_next_phase(struct r8a66597 *r8a66597) switch (td->type) { case USB_PID_IN: case USB_PID_OUT: - if (urb->status != -EINPROGRESS) { - finish = 1; - break; - } if (check_transfer_finish(td, urb)) td->type = USB_PID_ACK; break; case USB_PID_SETUP: - if (urb->status != -EINPROGRESS) - finish = 1; - else if (urb->transfer_buffer_length == urb->actual_length) { + if (urb->transfer_buffer_length == urb->actual_length) td->type = USB_PID_ACK; - urb->status = 0; - } else if (usb_pipeout(urb->pipe)) + else if (usb_pipeout(urb->pipe)) td->type = USB_PID_OUT; else td->type = USB_PID_IN; break; case USB_PID_ACK: finish = 1; - if (urb->status == -EINPROGRESS) - urb->status = 0; + urb->status = 0; break; } - if (finish) + if (finish || urb->unlinked) finish_request(r8a66597, td, 0, urb); else start_transfer(r8a66597, td); @@ -1418,8 +1409,7 @@ static void irq_pipe_empty(struct r8a66597 *r8a66597) if ((tmp & INBUFM) == 0) { disable_irq_empty(r8a66597, pipenum); pipe_irq_disable(r8a66597, pipenum); - if (td->urb->status == -EINPROGRESS) - td->urb->status = 0; + td->urb->status = 0; finish_request(r8a66597, td, pipenum, td->urb); } } diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e90953a..f0fa941 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -436,8 +436,7 @@ static void finish_request( ep->nextpid = USB_PID_SETUP; spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = status; + urb->status = status; spin_unlock(&urb->lock); usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb); @@ -598,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank) bank, status, ep, urbstat); } - if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)) + if (urb && (urbstat != -EINPROGRESS || urb->unlinked)) finish_request(sl811, ep, urb, urbstat); } diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 1381275..db800a4 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -645,12 +645,12 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { struct u132_ring *ring = endp->ring; u8 *u = urb->transfer_buffer + urb->actual_length; u8 *b = buf; @@ -716,8 +716,8 @@ static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf, return; } } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -744,12 +744,12 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { struct u132_ring *ring = endp->ring; urb->actual_length += len; endp->toggle_bits = toggle_bits; @@ -768,8 +768,8 @@ static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf, return; } } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -797,12 +797,12 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { struct u132_ring *ring = endp->ring; u8 *u = urb->transfer_buffer + urb->actual_length; u8 *b = buf; @@ -871,8 +871,8 @@ static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf, return; } } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -898,18 +898,18 @@ static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, 0); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -936,12 +936,12 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { struct u132_ring *ring = endp->ring; u8 *u = urb->transfer_buffer; u8 *b = buf; @@ -980,8 +980,8 @@ static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf, return; } } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1007,18 +1007,18 @@ static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, 0); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1045,12 +1045,12 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { if (usb_pipein(urb->pipe)) { int retval; struct u132_ring *ring = endp->ring; @@ -1077,8 +1077,8 @@ static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf, return; } } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1106,20 +1106,20 @@ static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { u132->addr[0].address = 0; endp->usb_addr = udev->usb_addr; up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, 0); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1145,12 +1145,12 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { int retval; struct u132_ring *ring = endp->ring; up(&u132->scheduler_lock); @@ -1162,8 +1162,8 @@ static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb, u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1189,18 +1189,18 @@ static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, 0); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1227,12 +1227,12 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { int retval; struct u132_ring *ring = endp->ring; u8 *u = urb->transfer_buffer; @@ -1251,8 +1251,8 @@ static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -1279,12 +1279,12 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; - } else if (urb->status == -EINPROGRESS) { + } else if (!urb->unlinked) { int retval; struct u132_ring *ring = endp->ring; up(&u132->scheduler_lock); @@ -1296,8 +1296,8 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else { - dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" - "s=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p " + "unlinked=%d\n", urb, urb->unlinked); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; @@ -2279,8 +2279,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, , u132->going); return -ENODEV; } else if (u132->going > 0) { - dev_err(&u132->platform_dev->dev, "device is being removed urb=" - "%p status=%d\n", urb, urb->status); + dev_err(&u132->platform_dev->dev, "device is being removed " + "urb=%p\n", urb); return -ESHUTDOWN; } else { u8 usb_addr = usb_pipedevice(urb->pipe); diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 1497371..20cc58b 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -120,8 +120,8 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); - if (urbp->urb->status != -EINPROGRESS) - out += sprintf(out, " Status=%d", urbp->urb->status); + if (urbp->urb->unlinked) + out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); out += sprintf(out, "\n"); i = nactive = ninactive = 0; diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index fbc3af3..bab5672 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1557,15 +1557,12 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) break; spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) /* Not dequeued */ - urb->status = status; - else - status = ECONNRESET; /* Not -ECONNRESET */ + urb->status = status; spin_unlock(&urb->lock); /* Dequeued but completed URBs can't be given back unless * the QH is stopped or has finished unlinking. */ - if (status == ECONNRESET) { + if (urb->unlinked) { if (QH_FINISHED_UNLINKING(qh)) qh->is_stopped = 1; else if (!qh->is_stopped) @@ -1588,7 +1585,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) restart: list_for_each_entry(urbp, &qh->queue, node) { urb = urbp->urb; - if (urb->status != -EINPROGRESS) { + if (urb->unlinked) { /* Fix up the TD links and save the toggles for * non-Isochronous queues. For Isochronous queues, diff --git a/include/linux/usb.h b/include/linux/usb.h index 92d63c6..5c7b790 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1245,6 +1245,7 @@ struct urb void *hcpriv; /* private data for host controller */ atomic_t use_count; /* concurrent submissions counter */ u8 reject; /* submissions will fail */ + int unlinked; /* unlink error code */ /* public: documented fields in the urb that can be used by drivers */ struct list_head urb_list; /* list head for use by the urb's -- cgit v1.1