diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-04-09 17:24:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 17:43:42 -0400 |
commit | 014e73c99aa408f3766afe8d11a1caa3a708b736 (patch) | |
tree | de7080493008eff560003364e6d88ad242014471 /drivers/usb/host/uhci-hcd.c | |
parent | 72ebddb59a644732ff0240cdf5d216952a2b0c6b (diff) |
[PATCH] USB UHCI: subroutine reordering
This patch moves a few subroutines around in the uhci-hcd source file.
Nothing else is changed.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 287 |
1 files changed, 143 insertions, 144 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 49bd83ee0c75..8b6c87ef486b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -90,7 +90,6 @@ static char *errbuf; | |||
90 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ | 90 | static kmem_cache_t *uhci_up_cachep; /* urb_priv */ |
91 | 91 | ||
92 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 92 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
93 | static void hc_state_transitions(struct uhci_hcd *uhci); | ||
94 | 93 | ||
95 | /* If a transfer is still active after this much time, turn off FSBR */ | 94 | /* If a transfer is still active after this much time, turn off FSBR */ |
96 | #define IDLE_TIMEOUT msecs_to_jiffies(50) | 95 | #define IDLE_TIMEOUT msecs_to_jiffies(50) |
@@ -105,96 +104,43 @@ static void hc_state_transitions(struct uhci_hcd *uhci); | |||
105 | #include "uhci-debug.c" | 104 | #include "uhci-debug.c" |
106 | #include "uhci-q.c" | 105 | #include "uhci-q.c" |
107 | 106 | ||
108 | static int init_stall_timer(struct usb_hcd *hcd); | 107 | static int ports_active(struct uhci_hcd *uhci) |
109 | |||
110 | static void stall_callback(unsigned long ptr) | ||
111 | { | ||
112 | struct usb_hcd *hcd = (struct usb_hcd *)ptr; | ||
113 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
114 | struct urb_priv *up; | ||
115 | unsigned long flags; | ||
116 | |||
117 | spin_lock_irqsave(&uhci->lock, flags); | ||
118 | uhci_scan_schedule(uhci, NULL); | ||
119 | |||
120 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | ||
121 | struct urb *u = up->urb; | ||
122 | |||
123 | spin_lock(&u->lock); | ||
124 | |||
125 | /* Check if the FSBR timed out */ | ||
126 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
127 | uhci_fsbr_timeout(uhci, u); | ||
128 | |||
129 | spin_unlock(&u->lock); | ||
130 | } | ||
131 | |||
132 | /* Really disable FSBR */ | ||
133 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
134 | uhci->fsbrtimeout = 0; | ||
135 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
136 | } | ||
137 | |||
138 | /* Poll for and perform state transitions */ | ||
139 | hc_state_transitions(uhci); | ||
140 | if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) | ||
141 | uhci_check_ports(uhci); | ||
142 | |||
143 | init_stall_timer(hcd); | ||
144 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
145 | } | ||
146 | |||
147 | static int init_stall_timer(struct usb_hcd *hcd) | ||
148 | { | 108 | { |
149 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 109 | unsigned long io_addr = uhci->io_addr; |
110 | int connection = 0; | ||
111 | int i; | ||
150 | 112 | ||
151 | init_timer(&uhci->stall_timer); | 113 | for (i = 0; i < uhci->rh_numports; i++) |
152 | uhci->stall_timer.function = stall_callback; | 114 | connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); |
153 | uhci->stall_timer.data = (unsigned long)hcd; | ||
154 | uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100); | ||
155 | add_timer(&uhci->stall_timer); | ||
156 | 115 | ||
157 | return 0; | 116 | return connection; |
158 | } | 117 | } |
159 | 118 | ||
160 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 119 | static int suspend_allowed(struct uhci_hcd *uhci) |
161 | { | 120 | { |
162 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
163 | unsigned long io_addr = uhci->io_addr; | 121 | unsigned long io_addr = uhci->io_addr; |
164 | unsigned short status; | 122 | int i; |
165 | 123 | ||
166 | /* | 124 | if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) |
167 | * Read the interrupt status, and write it back to clear the | 125 | return 1; |
168 | * interrupt cause. Contrary to the UHCI specification, the | 126 | |
169 | * "HC Halted" status bit is persistent: it is RO, not R/WC. | 127 | /* Some of Intel's USB controllers have a bug that causes false |
128 | * resume indications if any port has an over current condition. | ||
129 | * To prevent problems, we will not allow a global suspend if | ||
130 | * any ports are OC. | ||
131 | * | ||
132 | * Some motherboards using Intel's chipsets (but not using all | ||
133 | * the USB ports) appear to hardwire the over current inputs active | ||
134 | * to disable the USB ports. | ||
170 | */ | 135 | */ |
171 | status = inw(io_addr + USBSTS); | ||
172 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ | ||
173 | return IRQ_NONE; | ||
174 | outw(status, io_addr + USBSTS); /* Clear it */ | ||
175 | 136 | ||
176 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | 137 | /* check for over current condition on any port */ |
177 | if (status & USBSTS_HSE) | 138 | for (i = 0; i < uhci->rh_numports; i++) { |
178 | dev_err(uhci_dev(uhci), "host system error, " | 139 | if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) |
179 | "PCI problems?\n"); | 140 | return 0; |
180 | if (status & USBSTS_HCPE) | ||
181 | dev_err(uhci_dev(uhci), "host controller process " | ||
182 | "error, something bad happened!\n"); | ||
183 | if ((status & USBSTS_HCH) && uhci->state > 0) { | ||
184 | dev_err(uhci_dev(uhci), "host controller halted, " | ||
185 | "very bad!\n"); | ||
186 | /* FIXME: Reset the controller, fix the offending TD */ | ||
187 | } | ||
188 | } | 141 | } |
189 | 142 | ||
190 | if (status & USBSTS_RD) | 143 | return 1; |
191 | uhci->resume_detect = 1; | ||
192 | |||
193 | spin_lock(&uhci->lock); | ||
194 | uhci_scan_schedule(uhci, regs); | ||
195 | spin_unlock(&uhci->lock); | ||
196 | |||
197 | return IRQ_HANDLED; | ||
198 | } | 144 | } |
199 | 145 | ||
200 | static void reset_hc(struct uhci_hcd *uhci) | 146 | static void reset_hc(struct uhci_hcd *uhci) |
@@ -276,43 +222,46 @@ static void wakeup_hc(struct uhci_hcd *uhci) | |||
276 | } | 222 | } |
277 | } | 223 | } |
278 | 224 | ||
279 | static int ports_active(struct uhci_hcd *uhci) | 225 | static int start_hc(struct uhci_hcd *uhci) |
280 | { | 226 | { |
281 | unsigned long io_addr = uhci->io_addr; | 227 | unsigned long io_addr = uhci->io_addr; |
282 | int connection = 0; | 228 | int timeout = 10; |
283 | int i; | ||
284 | |||
285 | for (i = 0; i < uhci->rh_numports; i++) | ||
286 | connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); | ||
287 | 229 | ||
288 | return connection; | 230 | /* |
289 | } | 231 | * Reset the HC - this will force us to get a |
232 | * new notification of any already connected | ||
233 | * ports due to the virtual disconnect that it | ||
234 | * implies. | ||
235 | */ | ||
236 | outw(USBCMD_HCRESET, io_addr + USBCMD); | ||
237 | while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { | ||
238 | if (--timeout < 0) { | ||
239 | dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); | ||
240 | return -ETIMEDOUT; | ||
241 | } | ||
242 | msleep(1); | ||
243 | } | ||
290 | 244 | ||
291 | static int suspend_allowed(struct uhci_hcd *uhci) | 245 | /* Mark controller as running before we enable interrupts */ |
292 | { | 246 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; |
293 | unsigned long io_addr = uhci->io_addr; | ||
294 | int i; | ||
295 | 247 | ||
296 | if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) | 248 | /* Turn on PIRQ and all interrupts */ |
297 | return 1; | 249 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, |
250 | USBLEGSUP_DEFAULT); | ||
251 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, | ||
252 | io_addr + USBINTR); | ||
298 | 253 | ||
299 | /* Some of Intel's USB controllers have a bug that causes false | 254 | /* Start at frame 0 */ |
300 | * resume indications if any port has an over current condition. | 255 | outw(0, io_addr + USBFRNUM); |
301 | * To prevent problems, we will not allow a global suspend if | 256 | outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); |
302 | * any ports are OC. | ||
303 | * | ||
304 | * Some motherboards using Intel's chipsets (but not using all | ||
305 | * the USB ports) appear to hardwire the over current inputs active | ||
306 | * to disable the USB ports. | ||
307 | */ | ||
308 | 257 | ||
309 | /* check for over current condition on any port */ | 258 | /* Run and mark it configured with a 64-byte max packet */ |
310 | for (i = 0; i < uhci->rh_numports; i++) { | 259 | uhci->state = UHCI_RUNNING_GRACE; |
311 | if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) | 260 | uhci->state_end = jiffies + HZ; |
312 | return 0; | 261 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); |
313 | } | 262 | uhci->is_stopped = 0; |
314 | 263 | ||
315 | return 1; | 264 | return 0; |
316 | } | 265 | } |
317 | 266 | ||
318 | static void hc_state_transitions(struct uhci_hcd *uhci) | 267 | static void hc_state_transitions(struct uhci_hcd *uhci) |
@@ -353,56 +302,106 @@ static void hc_state_transitions(struct uhci_hcd *uhci) | |||
353 | } | 302 | } |
354 | } | 303 | } |
355 | 304 | ||
356 | /* | 305 | static int init_stall_timer(struct usb_hcd *hcd); |
357 | * Store the current frame number in uhci->frame_number if the controller | 306 | |
358 | * is runnning | 307 | static void stall_callback(unsigned long ptr) |
359 | */ | ||
360 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
361 | { | 308 | { |
362 | if (!uhci->is_stopped) | 309 | struct usb_hcd *hcd = (struct usb_hcd *)ptr; |
363 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | 310 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
311 | struct urb_priv *up; | ||
312 | unsigned long flags; | ||
313 | |||
314 | spin_lock_irqsave(&uhci->lock, flags); | ||
315 | uhci_scan_schedule(uhci, NULL); | ||
316 | |||
317 | list_for_each_entry(up, &uhci->urb_list, urb_list) { | ||
318 | struct urb *u = up->urb; | ||
319 | |||
320 | spin_lock(&u->lock); | ||
321 | |||
322 | /* Check if the FSBR timed out */ | ||
323 | if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) | ||
324 | uhci_fsbr_timeout(uhci, u); | ||
325 | |||
326 | spin_unlock(&u->lock); | ||
327 | } | ||
328 | |||
329 | /* Really disable FSBR */ | ||
330 | if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { | ||
331 | uhci->fsbrtimeout = 0; | ||
332 | uhci->skel_term_qh->link = UHCI_PTR_TERM; | ||
333 | } | ||
334 | |||
335 | /* Poll for and perform state transitions */ | ||
336 | hc_state_transitions(uhci); | ||
337 | if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) | ||
338 | uhci_check_ports(uhci); | ||
339 | |||
340 | init_stall_timer(hcd); | ||
341 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
364 | } | 342 | } |
365 | 343 | ||
366 | static int start_hc(struct uhci_hcd *uhci) | 344 | static int init_stall_timer(struct usb_hcd *hcd) |
367 | { | 345 | { |
346 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
347 | |||
348 | init_timer(&uhci->stall_timer); | ||
349 | uhci->stall_timer.function = stall_callback; | ||
350 | uhci->stall_timer.data = (unsigned long)hcd; | ||
351 | uhci->stall_timer.expires = jiffies + msecs_to_jiffies(100); | ||
352 | add_timer(&uhci->stall_timer); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | ||
358 | { | ||
359 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | ||
368 | unsigned long io_addr = uhci->io_addr; | 360 | unsigned long io_addr = uhci->io_addr; |
369 | int timeout = 10; | 361 | unsigned short status; |
370 | 362 | ||
371 | /* | 363 | /* |
372 | * Reset the HC - this will force us to get a | 364 | * Read the interrupt status, and write it back to clear the |
373 | * new notification of any already connected | 365 | * interrupt cause. Contrary to the UHCI specification, the |
374 | * ports due to the virtual disconnect that it | 366 | * "HC Halted" status bit is persistent: it is RO, not R/WC. |
375 | * implies. | ||
376 | */ | 367 | */ |
377 | outw(USBCMD_HCRESET, io_addr + USBCMD); | 368 | status = inw(io_addr + USBSTS); |
378 | while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { | 369 | if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ |
379 | if (--timeout < 0) { | 370 | return IRQ_NONE; |
380 | dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); | 371 | outw(status, io_addr + USBSTS); /* Clear it */ |
381 | return -ETIMEDOUT; | 372 | |
373 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | ||
374 | if (status & USBSTS_HSE) | ||
375 | dev_err(uhci_dev(uhci), "host system error, " | ||
376 | "PCI problems?\n"); | ||
377 | if (status & USBSTS_HCPE) | ||
378 | dev_err(uhci_dev(uhci), "host controller process " | ||
379 | "error, something bad happened!\n"); | ||
380 | if ((status & USBSTS_HCH) && uhci->state > 0) { | ||
381 | dev_err(uhci_dev(uhci), "host controller halted, " | ||
382 | "very bad!\n"); | ||
383 | /* FIXME: Reset the controller, fix the offending TD */ | ||
382 | } | 384 | } |
383 | msleep(1); | ||
384 | } | 385 | } |
385 | 386 | ||
386 | /* Mark controller as running before we enable interrupts */ | 387 | if (status & USBSTS_RD) |
387 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 388 | uhci->resume_detect = 1; |
388 | |||
389 | /* Turn on PIRQ and all interrupts */ | ||
390 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
391 | USBLEGSUP_DEFAULT); | ||
392 | outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, | ||
393 | io_addr + USBINTR); | ||
394 | 389 | ||
395 | /* Start at frame 0 */ | 390 | spin_lock(&uhci->lock); |
396 | outw(0, io_addr + USBFRNUM); | 391 | uhci_scan_schedule(uhci, regs); |
397 | outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); | 392 | spin_unlock(&uhci->lock); |
398 | 393 | ||
399 | /* Run and mark it configured with a 64-byte max packet */ | 394 | return IRQ_HANDLED; |
400 | uhci->state = UHCI_RUNNING_GRACE; | 395 | } |
401 | uhci->state_end = jiffies + HZ; | ||
402 | outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); | ||
403 | uhci->is_stopped = 0; | ||
404 | 396 | ||
405 | return 0; | 397 | /* |
398 | * Store the current frame number in uhci->frame_number if the controller | ||
399 | * is runnning | ||
400 | */ | ||
401 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | ||
402 | { | ||
403 | if (!uhci->is_stopped) | ||
404 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | ||
406 | } | 405 | } |
407 | 406 | ||
408 | /* | 407 | /* |