aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-08-24 15:40:34 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:21 -0400
commit55d8496837cf124f68656e4242a5e20eb592fd54 (patch)
treea188b3630a20cf7098833a95124e01ed438f3b7c /drivers
parent14c04c0f88f228fee1f412be91d6edcb935c78aa (diff)
USB: reorganize urb->status use in ohci-hcd
This patch (as975) reorganizes the way ohci-hcd sets urb->status. It now keeps the information in a local variable until the last moment. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: David Brownell <david-b@pacbell.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ohci-dbg.c8
-rw-r--r--drivers/usb/host/ohci-hcd.c15
-rw-r--r--drivers/usb/host/ohci-q.c38
3 files changed, 28 insertions, 33 deletions
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index f61c6cdd06f2..ebab5ce8f5ce 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -24,7 +24,7 @@
24 * small: 0) header + data packets 1) just header 24 * small: 0) header + data packets 1) just header
25 */ 25 */
26static void __maybe_unused 26static void __maybe_unused
27urb_print (struct urb * urb, char * str, int small) 27urb_print(struct urb * urb, char * str, int small, int status)
28{ 28{
29 unsigned int pipe= urb->pipe; 29 unsigned int pipe= urb->pipe;
30 30
@@ -34,7 +34,7 @@ urb_print (struct urb * urb, char * str, int small)
34 } 34 }
35 35
36#ifndef OHCI_VERBOSE_DEBUG 36#ifndef OHCI_VERBOSE_DEBUG
37 if (urb->status != 0) 37 if (status != 0)
38#endif 38#endif
39 dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", 39 dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
40 str, 40 str,
@@ -46,7 +46,7 @@ urb_print (struct urb * urb, char * str, int small)
46 urb->transfer_flags, 46 urb->transfer_flags,
47 urb->actual_length, 47 urb->actual_length,
48 urb->transfer_buffer_length, 48 urb->transfer_buffer_length,
49 urb->status); 49 status);
50 50
51#ifdef OHCI_VERBOSE_DEBUG 51#ifdef OHCI_VERBOSE_DEBUG
52 if (!small) { 52 if (!small) {
@@ -66,7 +66,7 @@ urb_print (struct urb * urb, char * str, int small)
66 urb->transfer_buffer_length: urb->actual_length; 66 urb->transfer_buffer_length: urb->actual_length;
67 for (i = 0; i < 16 && i < len; i++) 67 for (i = 0; i < 16 && i < len; i++)
68 printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); 68 printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
69 printk ("%s stat:%d\n", i < len? "...": "", urb->status); 69 printk ("%s stat:%d\n", i < len? "...": "", status);
70 } 70 }
71 } 71 }
72#endif 72#endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 6b06ab69938f..f7c6ced2bc03 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -129,7 +129,7 @@ static int ohci_urb_enqueue (
129 int retval = 0; 129 int retval = 0;
130 130
131#ifdef OHCI_VERBOSE_DEBUG 131#ifdef OHCI_VERBOSE_DEBUG
132 urb_print (urb, "SUB", usb_pipein (pipe)); 132 urb_print(urb, "SUB", usb_pipein(pipe), -EINPROGRESS);
133#endif 133#endif
134 134
135 /* every endpoint has a ed, locate and maybe (re)initialize it */ 135 /* every endpoint has a ed, locate and maybe (re)initialize it */
@@ -240,8 +240,8 @@ fail:
240} 240}
241 241
242/* 242/*
243 * decouple the URB from the HC queues (TDs, urb_priv); it's 243 * decouple the URB from the HC queues (TDs, urb_priv).
244 * already marked using urb->status. reporting is always done 244 * reporting is always done
245 * asynchronously, and we might be dealing with an urb that's 245 * asynchronously, and we might be dealing with an urb that's
246 * partially transferred, or an ED with other urbs being unlinked. 246 * partially transferred, or an ED with other urbs being unlinked.
247 */ 247 */
@@ -252,7 +252,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
252 int rc; 252 int rc;
253 253
254#ifdef OHCI_VERBOSE_DEBUG 254#ifdef OHCI_VERBOSE_DEBUG
255 urb_print (urb, "UNLINK", 1); 255 urb_print(urb, "UNLINK", 1, status);
256#endif 256#endif
257 257
258 spin_lock_irqsave (&ohci->lock, flags); 258 spin_lock_irqsave (&ohci->lock, flags);
@@ -277,7 +277,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
277 * any more ... just clean up every urb's memory. 277 * any more ... just clean up every urb's memory.
278 */ 278 */
279 if (urb->hcpriv) 279 if (urb->hcpriv)
280 finish_urb (ohci, urb); 280 finish_urb(ohci, urb, status);
281 } 281 }
282 spin_unlock_irqrestore (&ohci->lock, flags); 282 spin_unlock_irqrestore (&ohci->lock, flags);
283 return rc; 283 return rc;
@@ -927,9 +927,8 @@ static int ohci_restart (struct ohci_hcd *ohci)
927 ed, ed->state); 927 ed, ed->state);
928 } 928 }
929 929
930 spin_lock (&urb->lock); 930 if (!urb->unlinked)
931 urb->status = -ESHUTDOWN; 931 urb->unlinked = -ESHUTDOWN;
932 spin_unlock (&urb->lock);
933 } 932 }
934 finish_unlinks (ohci, 0); 933 finish_unlinks (ohci, 0);
935 spin_unlock_irq(&ohci->lock); 934 spin_unlock_irq(&ohci->lock);
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 860e55ff67a1..13d31edd1a86 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -36,18 +36,15 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
36 * PRECONDITION: ohci lock held, irqs blocked. 36 * PRECONDITION: ohci lock held, irqs blocked.
37 */ 37 */
38static void 38static void
39finish_urb (struct ohci_hcd *ohci, struct urb *urb) 39finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
40__releases(ohci->lock) 40__releases(ohci->lock)
41__acquires(ohci->lock) 41__acquires(ohci->lock)
42{ 42{
43 // ASSERT (urb->hcpriv != 0); 43 // ASSERT (urb->hcpriv != 0);
44 44
45 urb_free_priv (ohci, urb->hcpriv); 45 urb_free_priv (ohci, urb->hcpriv);
46 46 if (likely(status == -EINPROGRESS))
47 spin_lock (&urb->lock); 47 status = 0;
48 if (likely (urb->status == -EINPROGRESS))
49 urb->status = 0;
50 spin_unlock (&urb->lock);
51 48
52 switch (usb_pipetype (urb->pipe)) { 49 switch (usb_pipetype (urb->pipe)) {
53 case PIPE_ISOCHRONOUS: 50 case PIPE_ISOCHRONOUS:
@@ -59,12 +56,13 @@ __acquires(ohci->lock)
59 } 56 }
60 57
61#ifdef OHCI_VERBOSE_DEBUG 58#ifdef OHCI_VERBOSE_DEBUG
62 urb_print (urb, "RET", usb_pipeout (urb->pipe)); 59 urb_print(urb, "RET", usb_pipeout (urb->pipe), status);
63#endif 60#endif
64 61
65 /* urb->complete() can reenter this HCD */ 62 /* urb->complete() can reenter this HCD */
66 usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb); 63 usb_hcd_unlink_urb_from_ep(ohci_to_hcd(ohci), urb);
67 spin_unlock (&ohci->lock); 64 spin_unlock (&ohci->lock);
65 urb->status = status;
68 usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb); 66 usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb);
69 spin_lock (&ohci->lock); 67 spin_lock (&ohci->lock);
70 68
@@ -702,19 +700,18 @@ static void td_submit_urb (
702 * Done List handling functions 700 * Done List handling functions
703 *-------------------------------------------------------------------------*/ 701 *-------------------------------------------------------------------------*/
704 702
705/* calculate transfer length/status and update the urb 703/* calculate transfer length/status and update the urb */
706 * PRECONDITION: irqsafe (only for urb->status locking) 704static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td)
707 */
708static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
709{ 705{
710 u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO); 706 u32 tdINFO = hc32_to_cpup (ohci, &td->hwINFO);
711 int cc = 0; 707 int cc = 0;
708 int status = -EINPROGRESS;
712 709
713 list_del (&td->td_list); 710 list_del (&td->td_list);
714 711
715 /* ISO ... drivers see per-TD length/status */ 712 /* ISO ... drivers see per-TD length/status */
716 if (tdINFO & TD_ISO) { 713 if (tdINFO & TD_ISO) {
717 u16 tdPSW = ohci_hwPSW (ohci, td, 0); 714 u16 tdPSW = ohci_hwPSW(ohci, td, 0);
718 int dlen = 0; 715 int dlen = 0;
719 716
720 /* NOTE: assumes FC in tdINFO == 0, and that 717 /* NOTE: assumes FC in tdINFO == 0, and that
@@ -723,7 +720,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
723 720
724 cc = (tdPSW >> 12) & 0xF; 721 cc = (tdPSW >> 12) & 0xF;
725 if (tdINFO & TD_CC) /* hc didn't touch? */ 722 if (tdINFO & TD_CC) /* hc didn't touch? */
726 return; 723 return status;
727 724
728 if (usb_pipeout (urb->pipe)) 725 if (usb_pipeout (urb->pipe))
729 dlen = urb->iso_frame_desc [td->index].length; 726 dlen = urb->iso_frame_desc [td->index].length;
@@ -756,11 +753,8 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
756 if (cc == TD_DATAUNDERRUN 753 if (cc == TD_DATAUNDERRUN
757 && !(urb->transfer_flags & URB_SHORT_NOT_OK)) 754 && !(urb->transfer_flags & URB_SHORT_NOT_OK))
758 cc = TD_CC_NOERROR; 755 cc = TD_CC_NOERROR;
759 if (cc != TD_CC_NOERROR && cc < 0x0E) { 756 if (cc != TD_CC_NOERROR && cc < 0x0E)
760 spin_lock (&urb->lock); 757 status = cc_to_error[cc];
761 urb->status = cc_to_error[cc];
762 spin_unlock (&urb->lock);
763 }
764 758
765 /* count all non-empty packets except control SETUP packet */ 759 /* count all non-empty packets except control SETUP packet */
766 if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) { 760 if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) {
@@ -779,6 +773,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
779 urb->actual_length, 773 urb->actual_length,
780 urb->transfer_buffer_length); 774 urb->transfer_buffer_length);
781 } 775 }
776 return status;
782} 777}
783 778
784/*-------------------------------------------------------------------------*/ 779/*-------------------------------------------------------------------------*/
@@ -979,7 +974,7 @@ rescan_this:
979 /* if URB is done, clean up */ 974 /* if URB is done, clean up */
980 if (urb_priv->td_cnt == urb_priv->length) { 975 if (urb_priv->td_cnt == urb_priv->length) {
981 modified = completed = 1; 976 modified = completed = 1;
982 finish_urb (ohci, urb); 977 finish_urb(ohci, urb, 0);
983 } 978 }
984 } 979 }
985 if (completed && !list_empty (&ed->td_list)) 980 if (completed && !list_empty (&ed->td_list))
@@ -1062,14 +1057,15 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
1062 struct urb *urb = td->urb; 1057 struct urb *urb = td->urb;
1063 urb_priv_t *urb_priv = urb->hcpriv; 1058 urb_priv_t *urb_priv = urb->hcpriv;
1064 struct ed *ed = td->ed; 1059 struct ed *ed = td->ed;
1060 int status;
1065 1061
1066 /* update URB's length and status from TD */ 1062 /* update URB's length and status from TD */
1067 td_done(ohci, urb, td); 1063 status = td_done(ohci, urb, td);
1068 urb_priv->td_cnt++; 1064 urb_priv->td_cnt++;
1069 1065
1070 /* If all this urb's TDs are done, call complete() */ 1066 /* If all this urb's TDs are done, call complete() */
1071 if (urb_priv->td_cnt == urb_priv->length) 1067 if (urb_priv->td_cnt == urb_priv->length)
1072 finish_urb(ohci, urb); 1068 finish_urb(ohci, urb, status);
1073 1069
1074 /* clean schedule: unlink EDs that are no longer busy */ 1070 /* clean schedule: unlink EDs that are no longer busy */
1075 if (list_empty(&ed->td_list)) { 1071 if (list_empty(&ed->td_list)) {