79a53d8012546840489b25e15ddcb7103b4e683b
[openwrt.git] / target / linux / adm5120 / patches-2.6.24 / 914-usb_reorganize_urb_status_use.patch
1 Index: linux-2.6.24/drivers/usb/host/adm5120-dbg.c
2 ===================================================================
3 --- linux-2.6.24.orig/drivers/usb/host/adm5120-dbg.c
4 +++ linux-2.6.24/drivers/usb/host/adm5120-dbg.c
5 @@ -82,7 +82,7 @@ static inline char *td_togglestring(u32 
6   * small: 0) header + data packets 1) just header
7   */
8  static void __attribute__((unused))
9 -urb_print(struct admhcd *ahcd, struct urb *urb, char *str, int small)
10 +urb_print(struct admhcd *ahcd, struct urb *urb, char *str, int small, int status)
11  {
12         unsigned int pipe = urb->pipe;
13  
14 @@ -92,7 +92,7 @@ urb_print(struct admhcd *ahcd, struct ur
15         }
16  
17  #ifndef        ADMHC_VERBOSE_DEBUG
18 -       if (urb->status != 0)
19 +       if (status != 0)
20  #endif
21         admhc_dbg(ahcd, "URB-%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d "
22                         "stat=%d\n",
23 @@ -105,7 +105,7 @@ urb_print(struct admhcd *ahcd, struct ur
24                         urb->transfer_flags,
25                         urb->actual_length,
26                         urb->transfer_buffer_length,
27 -                       urb->status);
28 +                       status);
29  
30  #ifdef ADMHC_VERBOSE_DEBUG
31         if (!small) {
32 @@ -125,7 +125,7 @@ urb_print(struct admhcd *ahcd, struct ur
33                                                 urb->transfer_buffer_length: urb->actual_length;
34                         for (i = 0; i < 16 && i < len; i++)
35                                 printk(" %02x", ((__u8 *)urb->transfer_buffer)[i]);
36 -                       printk("%s stat:%d\n", i < len? "...": "", urb->status);
37 +                       printk("%s stat:%d\n", i < len? "...": "", status);
38                 }
39         }
40  #endif /* ADMHC_VERBOSE_DEBUG */
41 Index: linux-2.6.24/drivers/usb/host/adm5120-hcd.c
42 ===================================================================
43 --- linux-2.6.24.orig/drivers/usb/host/adm5120-hcd.c
44 +++ linux-2.6.24/drivers/usb/host/adm5120-hcd.c
45 @@ -96,7 +96,7 @@ static int admhc_urb_enqueue(struct usb_
46  
47  #ifdef ADMHC_VERBOSE_DEBUG
48         spin_lock_irqsave(&ahcd->lock, flags);
49 -       urb_print(ahcd, urb, "ENQEUE", usb_pipein(pipe));
50 +       urb_print(ahcd, urb, "ENQEUE", usb_pipein(pipe), -EINPROGRESS);
51         spin_unlock_irqrestore(&ahcd->lock, flags);
52  #endif
53  
54 @@ -208,8 +208,8 @@ fail:
55  }
56  
57  /*
58 - * decouple the URB from the HC queues (TDs, urb_priv); it's
59 - * already marked using urb->status.  reporting is always done
60 + * decouple the URB from the HC queues (TDs, urb_priv);
61 + * reporting is always done
62   * asynchronously, and we might be dealing with an urb that's
63   * partially transferred, or an ED with other urbs being unlinked.
64   */
65 @@ -223,7 +223,7 @@ static int admhc_urb_dequeue(struct usb_
66         spin_lock_irqsave(&ahcd->lock, flags);
67  
68  #ifdef ADMHC_VERBOSE_DEBUG
69 -       urb_print(ahcd, urb, "DEQUEUE", 1);
70 +       urb_print(ahcd, urb, "DEQUEUE", 1, status);
71  #endif
72         ret = usb_hcd_check_unlink_urb(hcd, urb, status);
73         if (ret) {
74 @@ -247,7 +247,7 @@ static int admhc_urb_dequeue(struct usb_
75                  * any more ... just clean up every urb's memory.
76                  */
77                 if (urb->hcpriv)
78 -                       finish_urb(ahcd, urb);
79 +                       finish_urb(ahcd, urb, status);
80         }
81         spin_unlock_irqrestore(&ahcd->lock, flags);
82  
83 Index: linux-2.6.24/drivers/usb/host/adm5120-pm.c
84 ===================================================================
85 --- linux-2.6.24.orig/drivers/usb/host/adm5120-pm.c
86 +++ linux-2.6.24/drivers/usb/host/adm5120-pm.c
87 @@ -383,9 +383,8 @@ static int admhc_restart(struct admhcd *
88                                         ed, ed->state);
89                 }
90  
91 -               spin_lock(&urb->lock);
92 -               urb->status = -ESHUTDOWN;
93 -               spin_unlock(&urb->lock);
94 +               if (!urb->unlinked)
95 +                       urb->unlinked = -ESHUTDOWN;
96         }
97         finish_unlinks(ahcd, 0);
98         spin_unlock_irq(&ahcd->lock);
99 Index: linux-2.6.24/drivers/usb/host/adm5120-q.c
100 ===================================================================
101 --- linux-2.6.24.orig/drivers/usb/host/adm5120-q.c
102 +++ linux-2.6.24/drivers/usb/host/adm5120-q.c
103 @@ -23,16 +23,14 @@
104   * PRECONDITION:  ahcd lock held, irqs blocked.
105   */
106  static void
107 -finish_urb(struct admhcd *ahcd, struct urb *urb)
108 +finish_urb(struct admhcd *ahcd, struct urb *urb, int status)
109  __releases(ahcd->lock)
110  __acquires(ahcd->lock)
111  {
112         urb_priv_free(ahcd, urb->hcpriv);
113  
114 -       spin_lock(&urb->lock);
115 -       if (likely(urb->status == -EINPROGRESS))
116 -               urb->status = 0;
117 -       spin_unlock(&urb->lock);
118 +       if (likely(status == -EINPROGRESS))
119 +               status = 0;
120  
121         switch (usb_pipetype(urb->pipe)) {
122         case PIPE_ISOCHRONOUS:
123 @@ -44,12 +42,13 @@ __acquires(ahcd->lock)
124         }
125  
126  #ifdef ADMHC_VERBOSE_DEBUG
127 -       urb_print(ahcd, urb, "RET", usb_pipeout (urb->pipe));
128 +       urb_print(ahcd, urb, "RET", usb_pipeout (urb->pipe), status);
129  #endif
130  
131         /* urb->complete() can reenter this HCD */
132         usb_hcd_unlink_urb_from_ep(admhcd_to_hcd(ahcd), urb);
133         spin_unlock(&ahcd->lock);
134 +       urb->status = status;
135         usb_hcd_giveback_urb(admhcd_to_hcd(ahcd), urb);
136         spin_lock(&ahcd->lock);
137  }
138 @@ -557,9 +556,7 @@ static void td_submit_urb(struct admhcd 
139   * Done List handling functions
140   *-------------------------------------------------------------------------*/
141  
142 -/* calculate transfer length/status and update the urb
143 - * PRECONDITION:  irqsafe (only for urb->status locking)
144 - */
145 +/* calculate transfer length/status and update the urb */
146  static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)
147  {
148         struct urb_priv *urb_priv = urb->hcpriv;
149 @@ -568,6 +565,7 @@ static int td_done(struct admhcd *ahcd, 
150         u32     tdDBP;
151         int     type = usb_pipetype(urb->pipe);
152         int     cc;
153 +       int     status = -EINPROGRESS;
154  
155         info = hc32_to_cpup(ahcd, &td->hwINFO);
156         tdDBP = hc32_to_cpup(ahcd, &td->hwDBP);
157 @@ -582,10 +580,9 @@ static int td_done(struct admhcd *ahcd, 
158                 /* NOTE:  assumes FC in tdINFO == 0, and that
159                  * only the first of 0..MAXPSW psws is used.
160                  */
161 -#if 0
162 -               if (tdINFO & TD_CC)     /* hc didn't touch? */
163 -                       return;
164 -#endif
165 +               if (info & TD_CC)       /* hc didn't touch? */
166 +                       return status;
167 +
168                 if (usb_pipeout(urb->pipe))
169                         dlen = urb->iso_frame_desc[td->index].length;
170                 else {
171 @@ -614,11 +611,9 @@ static int td_done(struct admhcd *ahcd, 
172                                 && !(urb->transfer_flags & URB_SHORT_NOT_OK))
173                         cc = TD_CC_NOERROR;
174  
175 -               if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0) {
176 -                       spin_lock(&urb->lock);
177 -                       urb->status = cc_to_error[cc];
178 -                       spin_unlock(&urb->lock);
179 -               }
180 +               if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0)
181 +                       status = cc_to_error[cc];
182 +
183  
184                 /* count all non-empty packets except control SETUP packet */
185                 if ((type != PIPE_CONTROL || td->index != 0) && tdDBP != 0) {
186 @@ -636,7 +631,7 @@ static int td_done(struct admhcd *ahcd, 
187         list_del(&td->td_list);
188         urb_priv->td_idx++;
189  
190 -       return cc;
191 +       return status;
192  }
193  
194  /*-------------------------------------------------------------------------*/
195 @@ -771,6 +766,7 @@ rescan_this:
196                         struct urb      *urb;
197                         struct urb_priv *urb_priv;
198                         __hc32          savebits;
199 +                       int             status;
200  
201                         td = list_entry(entry, struct td, td_list);
202                         urb = td->urb;
203 @@ -792,12 +788,12 @@ rescan_this:
204  #ifdef ADMHC_VERBOSE_DEBUG
205                         urb_print(ahcd, urb, "PARTIAL", 0);
206  #endif
207 -                       td_done(ahcd, urb, td);
208 +                       status = td_done(ahcd, urb, td);
209  
210                         /* if URB is done, clean up */
211                         if (urb_priv->td_idx == urb_priv->td_cnt) {
212                                 modified = completed = 1;
213 -                               finish_urb(ahcd, urb);
214 +                               finish_urb(ahcd, urb, status);
215                         }
216                 }
217                 if (completed && !list_empty(&ed->td_list))
218 @@ -895,13 +891,13 @@ static void ed_update(struct admhcd *ahc
219                 struct td *td = list_entry(entry, struct td, td_list);
220                 struct urb *urb = td->urb;
221                 struct urb_priv *urb_priv = urb->hcpriv;
222 -               int cc;
223 +               int status;
224  
225                 if (hc32_to_cpup(ahcd, &td->hwINFO) & TD_OWN)
226                         break;
227  
228                 /* update URB's length and status from TD */
229 -               cc = td_done(ahcd, urb, td);
230 +               status = td_done(ahcd, urb, td);
231                 if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td))
232                         ed_unhalt(ahcd, ed, urb);
233  
234 @@ -910,7 +906,7 @@ static void ed_update(struct admhcd *ahc
235  
236                 /* If all this urb's TDs are done, call complete() */
237                 if (urb_priv->td_idx == urb_priv->td_cnt)
238 -                       finish_urb(ahcd, urb);
239 +                       finish_urb(ahcd, urb, status);
240  
241                 /* clean schedule:  unlink EDs that are no longer busy */
242                 if (list_empty(&ed->td_list)) {