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/ohci-q.c | |
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/ohci-q.c')
-rw-r--r-- | drivers/usb/host/ohci-q.c | 38 |
1 files changed, 17 insertions, 21 deletions
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)) { |