diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-08-24 15:40:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:55:21 -0400 |
commit | 55d8496837cf124f68656e4242a5e20eb592fd54 (patch) | |
tree | a188b3630a20cf7098833a95124e01ed438f3b7c /drivers/usb/host | |
parent | 14c04c0f88f228fee1f412be91d6edcb935c78aa (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/usb/host')
-rw-r--r-- | drivers/usb/host/ohci-dbg.c | 8 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 15 | ||||
-rw-r--r-- | drivers/usb/host/ohci-q.c | 38 |
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 | */ |
26 | static void __maybe_unused | 26 | static void __maybe_unused |
27 | urb_print (struct urb * urb, char * str, int small) | 27 | urb_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 | */ |
38 | static void | 38 | static void |
39 | finish_urb (struct ohci_hcd *ohci, struct urb *urb) | 39 | finish_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) | 704 | static int td_done(struct ohci_hcd *ohci, struct urb *urb, struct td *td) |
707 | */ | ||
708 | static 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)) { |