]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Copyright (c) 2000-2004 by David Brownell | |
53bd6a60 | 3 | * |
1da177e4 LT |
4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | |
6 | * Free Software Foundation; either version 2 of the License, or (at your | |
7 | * option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but | |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
11 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 | * for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software Foundation, | |
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 | */ | |
18 | ||
1da177e4 LT |
19 | #include <linux/module.h> |
20 | #include <linux/pci.h> | |
21 | #include <linux/dmapool.h> | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/delay.h> | |
24 | #include <linux/ioport.h> | |
25 | #include <linux/sched.h> | |
26 | #include <linux/slab.h> | |
27 | #include <linux/smp_lock.h> | |
28 | #include <linux/errno.h> | |
29 | #include <linux/init.h> | |
30 | #include <linux/timer.h> | |
31 | #include <linux/list.h> | |
32 | #include <linux/interrupt.h> | |
33 | #include <linux/reboot.h> | |
34 | #include <linux/usb.h> | |
35 | #include <linux/moduleparam.h> | |
36 | #include <linux/dma-mapping.h> | |
37 | ||
38 | #include "../core/hcd.h" | |
39 | ||
40 | #include <asm/byteorder.h> | |
41 | #include <asm/io.h> | |
42 | #include <asm/irq.h> | |
43 | #include <asm/system.h> | |
44 | #include <asm/unaligned.h> | |
48fda451 IK |
45 | #ifdef CONFIG_PPC_PS3 |
46 | #include <asm/firmware.h> | |
47 | #endif | |
1da177e4 LT |
48 | |
49 | ||
50 | /*-------------------------------------------------------------------------*/ | |
51 | ||
52 | /* | |
53 | * EHCI hc_driver implementation ... experimental, incomplete. | |
54 | * Based on the final 1.0 register interface specification. | |
55 | * | |
56 | * USB 2.0 shows up in upcoming www.pcmcia.org technology. | |
57 | * First was PCMCIA, like ISA; then CardBus, which is PCI. | |
58 | * Next comes "CardBay", using USB 2.0 signals. | |
59 | * | |
60 | * Contains additional contributions by Brad Hards, Rory Bolt, and others. | |
61 | * Special thanks to Intel and VIA for providing host controllers to | |
62 | * test this driver on, and Cypress (including In-System Design) for | |
63 | * providing early devices for those host controllers to talk to! | |
64 | * | |
65 | * HISTORY: | |
66 | * | |
67 | * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db) | |
68 | * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net) | |
69 | * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka, | |
70 | * <sojkam@centrum.cz>, updates by DB). | |
71 | * | |
72 | * 2002-11-29 Correct handling for hw async_next register. | |
73 | * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared; | |
74 | * only scheduling is different, no arbitrary limitations. | |
75 | * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support, | |
53bd6a60 | 76 | * clean up HC run state handshaking. |
1da177e4 LT |
77 | * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts |
78 | * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other | |
79 | * missing pieces: enabling 64bit dma, handoff from BIOS/SMM. | |
80 | * 2002-05-07 Some error path cleanups to report better errors; wmb(); | |
81 | * use non-CVS version id; better iso bandwidth claim. | |
82 | * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on | |
83 | * errors in submit path. Bugfixes to interrupt scheduling/processing. | |
84 | * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift | |
85 | * more checking to generic hcd framework (db). Make it work with | |
86 | * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt). | |
87 | * 2002-01-14 Minor cleanup; version synch. | |
88 | * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers. | |
89 | * 2002-01-04 Control/Bulk queuing behaves. | |
90 | * | |
91 | * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. | |
92 | * 2001-June Works with usb-storage and NEC EHCI on 2.4 | |
93 | */ | |
94 | ||
95 | #define DRIVER_VERSION "10 Dec 2004" | |
96 | #define DRIVER_AUTHOR "David Brownell" | |
97 | #define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" | |
98 | ||
99 | static const char hcd_name [] = "ehci_hcd"; | |
100 | ||
101 | ||
102 | #undef EHCI_VERBOSE_DEBUG | |
103 | #undef EHCI_URB_TRACE | |
104 | ||
105 | #ifdef DEBUG | |
106 | #define EHCI_STATS | |
107 | #endif | |
108 | ||
109 | /* magic numbers that can affect system performance */ | |
110 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | |
111 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | |
112 | #define EHCI_TUNE_RL_TT 0 | |
113 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | |
114 | #define EHCI_TUNE_MULT_TT 1 | |
115 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | |
116 | ||
64f89798 | 117 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ |
1da177e4 LT |
118 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
119 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | |
120 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | |
121 | ||
122 | /* Initial IRQ latency: faster than hw default */ | |
123 | static int log2_irq_thresh = 0; // 0 to 6 | |
124 | module_param (log2_irq_thresh, int, S_IRUGO); | |
125 | MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); | |
126 | ||
127 | /* initial park setting: slower than hw default */ | |
128 | static unsigned park = 0; | |
129 | module_param (park, uint, S_IRUGO); | |
130 | MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); | |
131 | ||
93f1a47c DB |
132 | /* for flakey hardware, ignore overcurrent indicators */ |
133 | static int ignore_oc = 0; | |
134 | module_param (ignore_oc, bool, S_IRUGO); | |
135 | MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); | |
136 | ||
1da177e4 LT |
137 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) |
138 | ||
139 | /*-------------------------------------------------------------------------*/ | |
140 | ||
141 | #include "ehci.h" | |
142 | #include "ehci-dbg.c" | |
143 | ||
144 | /*-------------------------------------------------------------------------*/ | |
145 | ||
146 | /* | |
147 | * handshake - spin reading hc until handshake completes or fails | |
148 | * @ptr: address of hc register to be read | |
149 | * @mask: bits to look at in result of read | |
150 | * @done: value of those bits when handshake succeeds | |
151 | * @usec: timeout in microseconds | |
152 | * | |
153 | * Returns negative errno, or zero on success | |
154 | * | |
155 | * Success happens when the "mask" bits have the specified value (hardware | |
156 | * handshake done). There are two failure modes: "usec" have passed (major | |
157 | * hardware flakeout), or the register reads as all-ones (hardware removed). | |
158 | * | |
159 | * That last failure should_only happen in cases like physical cardbus eject | |
160 | * before driver shutdown. But it also seems to be caused by bugs in cardbus | |
161 | * bridge shutdown: shutting down the bridge before the devices using it. | |
162 | */ | |
083522d7 BH |
163 | static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, |
164 | u32 mask, u32 done, int usec) | |
1da177e4 LT |
165 | { |
166 | u32 result; | |
167 | ||
168 | do { | |
083522d7 | 169 | result = ehci_readl(ehci, ptr); |
1da177e4 LT |
170 | if (result == ~(u32)0) /* card removed */ |
171 | return -ENODEV; | |
172 | result &= mask; | |
173 | if (result == done) | |
174 | return 0; | |
175 | udelay (1); | |
176 | usec--; | |
177 | } while (usec > 0); | |
178 | return -ETIMEDOUT; | |
179 | } | |
180 | ||
181 | /* force HC to halt state from unknown (EHCI spec section 2.3) */ | |
182 | static int ehci_halt (struct ehci_hcd *ehci) | |
183 | { | |
083522d7 | 184 | u32 temp = ehci_readl(ehci, &ehci->regs->status); |
1da177e4 | 185 | |
72f30b6f | 186 | /* disable any irqs left enabled by previous code */ |
083522d7 | 187 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
72f30b6f | 188 | |
1da177e4 LT |
189 | if ((temp & STS_HALT) != 0) |
190 | return 0; | |
191 | ||
083522d7 | 192 | temp = ehci_readl(ehci, &ehci->regs->command); |
1da177e4 | 193 | temp &= ~CMD_RUN; |
083522d7 BH |
194 | ehci_writel(ehci, temp, &ehci->regs->command); |
195 | return handshake (ehci, &ehci->regs->status, | |
196 | STS_HALT, STS_HALT, 16 * 125); | |
1da177e4 LT |
197 | } |
198 | ||
199 | /* put TDI/ARC silicon into EHCI mode */ | |
200 | static void tdi_reset (struct ehci_hcd *ehci) | |
201 | { | |
202 | u32 __iomem *reg_ptr; | |
203 | u32 tmp; | |
204 | ||
205 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); | |
083522d7 | 206 | tmp = ehci_readl(ehci, reg_ptr); |
1da177e4 | 207 | tmp |= 0x3; |
083522d7 | 208 | ehci_writel(ehci, tmp, reg_ptr); |
1da177e4 LT |
209 | } |
210 | ||
211 | /* reset a non-running (STS_HALT == 1) controller */ | |
212 | static int ehci_reset (struct ehci_hcd *ehci) | |
213 | { | |
214 | int retval; | |
083522d7 | 215 | u32 command = ehci_readl(ehci, &ehci->regs->command); |
1da177e4 LT |
216 | |
217 | command |= CMD_RESET; | |
218 | dbg_cmd (ehci, "reset", command); | |
083522d7 | 219 | ehci_writel(ehci, command, &ehci->regs->command); |
1da177e4 LT |
220 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
221 | ehci->next_statechange = jiffies; | |
083522d7 BH |
222 | retval = handshake (ehci, &ehci->regs->command, |
223 | CMD_RESET, 0, 250 * 1000); | |
1da177e4 LT |
224 | |
225 | if (retval) | |
226 | return retval; | |
227 | ||
228 | if (ehci_is_TDI(ehci)) | |
229 | tdi_reset (ehci); | |
230 | ||
231 | return retval; | |
232 | } | |
233 | ||
234 | /* idle the controller (from running) */ | |
235 | static void ehci_quiesce (struct ehci_hcd *ehci) | |
236 | { | |
237 | u32 temp; | |
238 | ||
239 | #ifdef DEBUG | |
240 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | |
241 | BUG (); | |
242 | #endif | |
243 | ||
244 | /* wait for any schedule enables/disables to take effect */ | |
083522d7 | 245 | temp = ehci_readl(ehci, &ehci->regs->command) << 10; |
1da177e4 | 246 | temp &= STS_ASS | STS_PSS; |
083522d7 | 247 | if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, |
1da177e4 LT |
248 | temp, 16 * 125) != 0) { |
249 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | |
250 | return; | |
251 | } | |
252 | ||
253 | /* then disable anything that's still active */ | |
083522d7 | 254 | temp = ehci_readl(ehci, &ehci->regs->command); |
1da177e4 | 255 | temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); |
083522d7 | 256 | ehci_writel(ehci, temp, &ehci->regs->command); |
1da177e4 LT |
257 | |
258 | /* hardware can take 16 microframes to turn off ... */ | |
083522d7 | 259 | if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, |
1da177e4 LT |
260 | 0, 16 * 125) != 0) { |
261 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | |
262 | return; | |
263 | } | |
264 | } | |
265 | ||
266 | /*-------------------------------------------------------------------------*/ | |
267 | ||
7d12e780 | 268 | static void ehci_work(struct ehci_hcd *ehci); |
1da177e4 LT |
269 | |
270 | #include "ehci-hub.c" | |
271 | #include "ehci-mem.c" | |
272 | #include "ehci-q.c" | |
273 | #include "ehci-sched.c" | |
274 | ||
275 | /*-------------------------------------------------------------------------*/ | |
276 | ||
64f89798 | 277 | static void ehci_watchdog (unsigned long param) |
1da177e4 LT |
278 | { |
279 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | |
280 | unsigned long flags; | |
281 | ||
282 | spin_lock_irqsave (&ehci->lock, flags); | |
283 | ||
64f89798 | 284 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ |
1da177e4 | 285 | if (ehci->reclaim) { |
083522d7 | 286 | u32 status = ehci_readl(ehci, &ehci->regs->status); |
1da177e4 LT |
287 | if (status & STS_IAA) { |
288 | ehci_vdbg (ehci, "lost IAA\n"); | |
289 | COUNT (ehci->stats.lost_iaa); | |
083522d7 | 290 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); |
64f89798 | 291 | ehci->reclaim_ready = 1; |
1da177e4 LT |
292 | } |
293 | } | |
294 | ||
64f89798 | 295 | /* stop async processing after it's idled a bit */ |
1da177e4 | 296 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) |
26f953fd | 297 | start_unlink_async (ehci, ehci->async); |
1da177e4 LT |
298 | |
299 | /* ehci could run by timer, without IRQs ... */ | |
7d12e780 | 300 | ehci_work (ehci); |
1da177e4 LT |
301 | |
302 | spin_unlock_irqrestore (&ehci->lock, flags); | |
303 | } | |
304 | ||
8903795a AS |
305 | /* On some systems, leaving remote wakeup enabled prevents system shutdown. |
306 | * The firmware seems to think that powering off is a wakeup event! | |
307 | * This routine turns off remote wakeup and everything else, on all ports. | |
308 | */ | |
309 | static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) | |
310 | { | |
311 | int port = HCS_N_PORTS(ehci->hcs_params); | |
312 | ||
313 | while (port--) | |
314 | ehci_writel(ehci, PORT_RWC_BITS, | |
315 | &ehci->regs->port_status[port]); | |
316 | } | |
317 | ||
64a21d02 | 318 | /* ehci_shutdown kick in for silicon on any bus (not just pci, etc). |
72f30b6f DB |
319 | * This forcibly disables dma and IRQs, helping kexec and other cases |
320 | * where the next system software may expect clean state. | |
321 | */ | |
64a21d02 AG |
322 | static void |
323 | ehci_shutdown (struct usb_hcd *hcd) | |
1da177e4 | 324 | { |
64a21d02 | 325 | struct ehci_hcd *ehci; |
1da177e4 | 326 | |
64a21d02 | 327 | ehci = hcd_to_ehci (hcd); |
72f30b6f | 328 | (void) ehci_halt (ehci); |
8903795a | 329 | ehci_turn_off_all_ports(ehci); |
1da177e4 LT |
330 | |
331 | /* make BIOS/etc use companion controller during reboot */ | |
083522d7 | 332 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
8903795a AS |
333 | |
334 | /* unblock posted writes */ | |
335 | ehci_readl(ehci, &ehci->regs->configured_flag); | |
1da177e4 LT |
336 | } |
337 | ||
56c1e26d DB |
338 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) |
339 | { | |
340 | unsigned port; | |
341 | ||
342 | if (!HCS_PPC (ehci->hcs_params)) | |
343 | return; | |
344 | ||
345 | ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down"); | |
346 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) | |
347 | (void) ehci_hub_control(ehci_to_hcd(ehci), | |
348 | is_on ? SetPortFeature : ClearPortFeature, | |
349 | USB_PORT_FEAT_POWER, | |
350 | port--, NULL, 0); | |
351 | msleep(20); | |
352 | } | |
353 | ||
7ff71d6a | 354 | /*-------------------------------------------------------------------------*/ |
1da177e4 | 355 | |
7ff71d6a MP |
356 | /* |
357 | * ehci_work is called from some interrupts, timers, and so on. | |
358 | * it calls driver completion functions, after dropping ehci->lock. | |
359 | */ | |
7d12e780 | 360 | static void ehci_work (struct ehci_hcd *ehci) |
7ff71d6a MP |
361 | { |
362 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | |
64f89798 GKH |
363 | if (ehci->reclaim_ready) |
364 | end_unlink_async (ehci); | |
7ff71d6a MP |
365 | |
366 | /* another CPU may drop ehci->lock during a schedule scan while | |
367 | * it reports urb completions. this flag guards against bogus | |
368 | * attempts at re-entrant schedule scanning. | |
369 | */ | |
370 | if (ehci->scanning) | |
371 | return; | |
372 | ehci->scanning = 1; | |
7d12e780 | 373 | scan_async (ehci); |
7ff71d6a | 374 | if (ehci->next_uframe != -1) |
7d12e780 | 375 | scan_periodic (ehci); |
7ff71d6a MP |
376 | ehci->scanning = 0; |
377 | ||
378 | /* the IO watchdog guards against hardware or driver bugs that | |
379 | * misplace IRQs, and should let us run completely without IRQs. | |
380 | * such lossage has been observed on both VT6202 and VT8235. | |
381 | */ | |
382 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && | |
383 | (ehci->async->qh_next.ptr != NULL || | |
384 | ehci->periodic_sched != 0)) | |
385 | timer_action (ehci, TIMER_IO_WATCHDOG); | |
386 | } | |
1da177e4 | 387 | |
7ff71d6a | 388 | static void ehci_stop (struct usb_hcd *hcd) |
1da177e4 LT |
389 | { |
390 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
1da177e4 | 391 | |
7ff71d6a | 392 | ehci_dbg (ehci, "stop\n"); |
1da177e4 | 393 | |
7ff71d6a MP |
394 | /* Turn off port power on all root hub ports. */ |
395 | ehci_port_power (ehci, 0); | |
1da177e4 | 396 | |
7ff71d6a MP |
397 | /* no more interrupts ... */ |
398 | del_timer_sync (&ehci->watchdog); | |
56c1e26d | 399 | |
7ff71d6a MP |
400 | spin_lock_irq(&ehci->lock); |
401 | if (HC_IS_RUNNING (hcd->state)) | |
402 | ehci_quiesce (ehci); | |
1da177e4 | 403 | |
7ff71d6a | 404 | ehci_reset (ehci); |
083522d7 | 405 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
7ff71d6a | 406 | spin_unlock_irq(&ehci->lock); |
1da177e4 | 407 | |
7ff71d6a | 408 | /* let companion controllers work when we aren't */ |
083522d7 | 409 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
56c1e26d | 410 | |
57e06c11 | 411 | remove_companion_file(ehci); |
7ff71d6a | 412 | remove_debug_files (ehci); |
1da177e4 | 413 | |
7ff71d6a MP |
414 | /* root hub is shut down separately (first, when possible) */ |
415 | spin_lock_irq (&ehci->lock); | |
416 | if (ehci->async) | |
7d12e780 | 417 | ehci_work (ehci); |
7ff71d6a MP |
418 | spin_unlock_irq (&ehci->lock); |
419 | ehci_mem_cleanup (ehci); | |
1da177e4 | 420 | |
7ff71d6a MP |
421 | #ifdef EHCI_STATS |
422 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | |
423 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | |
424 | ehci->stats.lost_iaa); | |
425 | ehci_dbg (ehci, "complete %ld unlink %ld\n", | |
426 | ehci->stats.complete, ehci->stats.unlink); | |
1da177e4 | 427 | #endif |
1da177e4 | 428 | |
083522d7 BH |
429 | dbg_status (ehci, "ehci_stop completed", |
430 | ehci_readl(ehci, &ehci->regs->status)); | |
1da177e4 LT |
431 | } |
432 | ||
18807521 DB |
433 | /* one-time init, only for memory state */ |
434 | static int ehci_init(struct usb_hcd *hcd) | |
1da177e4 | 435 | { |
18807521 | 436 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1da177e4 | 437 | u32 temp; |
1da177e4 LT |
438 | int retval; |
439 | u32 hcc_params; | |
18807521 DB |
440 | |
441 | spin_lock_init(&ehci->lock); | |
442 | ||
443 | init_timer(&ehci->watchdog); | |
444 | ehci->watchdog.function = ehci_watchdog; | |
445 | ehci->watchdog.data = (unsigned long) ehci; | |
1da177e4 LT |
446 | |
447 | /* | |
448 | * hw default: 1K periodic list heads, one per frame. | |
449 | * periodic_size can shrink by USBCMD update if hcc_params allows. | |
450 | */ | |
451 | ehci->periodic_size = DEFAULT_I_TDPS; | |
18807521 | 452 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) |
1da177e4 LT |
453 | return retval; |
454 | ||
455 | /* controllers may cache some of the periodic schedule ... */ | |
083522d7 | 456 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
53bd6a60 | 457 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache |
1da177e4 LT |
458 | ehci->i_thresh = 8; |
459 | else // N microframes cached | |
18807521 | 460 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
1da177e4 LT |
461 | |
462 | ehci->reclaim = NULL; | |
64f89798 | 463 | ehci->reclaim_ready = 0; |
1da177e4 LT |
464 | ehci->next_uframe = -1; |
465 | ||
1da177e4 LT |
466 | /* |
467 | * dedicate a qh for the async ring head, since we couldn't unlink | |
468 | * a 'real' qh without stopping the async schedule [4.8]. use it | |
469 | * as the 'reclamation list head' too. | |
470 | * its dummy is used in hw_alt_next of many tds, to prevent the qh | |
471 | * from automatically advancing to the next td after short reads. | |
472 | */ | |
18807521 DB |
473 | ehci->async->qh_next.qh = NULL; |
474 | ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma); | |
475 | ehci->async->hw_info1 = cpu_to_le32(QH_HEAD); | |
476 | ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT); | |
477 | ehci->async->hw_qtd_next = EHCI_LIST_END; | |
478 | ehci->async->qh_state = QH_STATE_LINKED; | |
479 | ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma); | |
1da177e4 LT |
480 | |
481 | /* clear interrupt enables, set irq latency */ | |
482 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | |
483 | log2_irq_thresh = 0; | |
484 | temp = 1 << (16 + log2_irq_thresh); | |
485 | if (HCC_CANPARK(hcc_params)) { | |
486 | /* HW default park == 3, on hardware that supports it (like | |
487 | * NVidia and ALI silicon), maximizes throughput on the async | |
488 | * schedule by avoiding QH fetches between transfers. | |
489 | * | |
490 | * With fast usb storage devices and NForce2, "park" seems to | |
491 | * make problems: throughput reduction (!), data errors... | |
492 | */ | |
493 | if (park) { | |
18807521 | 494 | park = min(park, (unsigned) 3); |
1da177e4 LT |
495 | temp |= CMD_PARK; |
496 | temp |= park << 8; | |
497 | } | |
18807521 | 498 | ehci_dbg(ehci, "park %d\n", park); |
1da177e4 | 499 | } |
18807521 | 500 | if (HCC_PGM_FRAMELISTLEN(hcc_params)) { |
1da177e4 LT |
501 | /* periodic schedule size can be smaller than default */ |
502 | temp &= ~(3 << 2); | |
503 | temp |= (EHCI_TUNE_FLS << 2); | |
504 | switch (EHCI_TUNE_FLS) { | |
505 | case 0: ehci->periodic_size = 1024; break; | |
506 | case 1: ehci->periodic_size = 512; break; | |
507 | case 2: ehci->periodic_size = 256; break; | |
18807521 | 508 | default: BUG(); |
1da177e4 LT |
509 | } |
510 | } | |
18807521 DB |
511 | ehci->command = temp; |
512 | ||
18807521 DB |
513 | return 0; |
514 | } | |
515 | ||
516 | /* start HC running; it's halted, ehci_init() has been run (once) */ | |
517 | static int ehci_run (struct usb_hcd *hcd) | |
518 | { | |
519 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
520 | int retval; | |
521 | u32 temp; | |
522 | u32 hcc_params; | |
523 | ||
1d619f12 MT |
524 | hcd->uses_new_polling = 1; |
525 | hcd->poll_rh = 0; | |
526 | ||
18807521 DB |
527 | /* EHCI spec section 4.1 */ |
528 | if ((retval = ehci_reset(ehci)) != 0) { | |
18807521 DB |
529 | ehci_mem_cleanup(ehci); |
530 | return retval; | |
531 | } | |
083522d7 BH |
532 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); |
533 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); | |
18807521 DB |
534 | |
535 | /* | |
536 | * hcc_params controls whether ehci->regs->segment must (!!!) | |
537 | * be used; it constrains QH/ITD/SITD and QTD locations. | |
538 | * pci_pool consistent memory always uses segment zero. | |
539 | * streaming mappings for I/O buffers, like pci_map_single(), | |
540 | * can return segments above 4GB, if the device allows. | |
541 | * | |
542 | * NOTE: the dma mask is visible through dma_supported(), so | |
543 | * drivers can pass this info along ... like NETIF_F_HIGHDMA, | |
544 | * Scsi_Host.highmem_io, and so forth. It's readonly to all | |
545 | * host side drivers though. | |
546 | */ | |
083522d7 | 547 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
18807521 | 548 | if (HCC_64BIT_ADDR(hcc_params)) { |
083522d7 | 549 | ehci_writel(ehci, 0, &ehci->regs->segment); |
18807521 DB |
550 | #if 0 |
551 | // this is deeply broken on almost all architectures | |
552 | if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK)) | |
553 | ehci_info(ehci, "enabled 64bit DMA\n"); | |
554 | #endif | |
555 | } | |
556 | ||
557 | ||
1da177e4 LT |
558 | // Philips, Intel, and maybe others need CMD_RUN before the |
559 | // root hub will detect new devices (why?); NEC doesn't | |
18807521 DB |
560 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); |
561 | ehci->command |= CMD_RUN; | |
083522d7 | 562 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
18807521 | 563 | dbg_cmd (ehci, "init", ehci->command); |
1da177e4 | 564 | |
1da177e4 LT |
565 | /* |
566 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | |
567 | * are explicitly handed to companion controller(s), so no TT is | |
568 | * involved with the root hub. (Except where one is integrated, | |
569 | * and there's no companion controller unless maybe for USB OTG.) | |
570 | */ | |
1da177e4 | 571 | hcd->state = HC_STATE_RUNNING; |
083522d7 BH |
572 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
573 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | |
1da177e4 | 574 | |
083522d7 | 575 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
1da177e4 | 576 | ehci_info (ehci, |
93f1a47c | 577 | "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", |
7ff71d6a | 578 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), |
93f1a47c DB |
579 | temp >> 8, temp & 0xff, DRIVER_VERSION, |
580 | ignore_oc ? ", overcurrent ignored" : ""); | |
1da177e4 | 581 | |
083522d7 BH |
582 | ehci_writel(ehci, INTR_MASK, |
583 | &ehci->regs->intr_enable); /* Turn On Interrupts */ | |
1da177e4 | 584 | |
18807521 DB |
585 | /* GRR this is run-once init(), being done every time the HC starts. |
586 | * So long as they're part of class devices, we can't do it init() | |
587 | * since the class device isn't created that early. | |
588 | */ | |
589 | create_debug_files(ehci); | |
57e06c11 | 590 | create_companion_file(ehci); |
1da177e4 LT |
591 | |
592 | return 0; | |
593 | } | |
594 | ||
1da177e4 LT |
595 | /*-------------------------------------------------------------------------*/ |
596 | ||
7d12e780 | 597 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) |
1da177e4 LT |
598 | { |
599 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
1d619f12 | 600 | u32 status, pcd_status = 0; |
1da177e4 LT |
601 | int bh; |
602 | ||
603 | spin_lock (&ehci->lock); | |
604 | ||
083522d7 | 605 | status = ehci_readl(ehci, &ehci->regs->status); |
1da177e4 LT |
606 | |
607 | /* e.g. cardbus physical eject */ | |
608 | if (status == ~(u32) 0) { | |
609 | ehci_dbg (ehci, "device removed\n"); | |
610 | goto dead; | |
611 | } | |
612 | ||
613 | status &= INTR_MASK; | |
614 | if (!status) { /* irq sharing? */ | |
615 | spin_unlock(&ehci->lock); | |
616 | return IRQ_NONE; | |
617 | } | |
618 | ||
619 | /* clear (just) interrupts */ | |
083522d7 BH |
620 | ehci_writel(ehci, status, &ehci->regs->status); |
621 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ | |
1da177e4 LT |
622 | bh = 0; |
623 | ||
624 | #ifdef EHCI_VERBOSE_DEBUG | |
625 | /* unrequested/ignored: Frame List Rollover */ | |
626 | dbg_status (ehci, "irq", status); | |
627 | #endif | |
628 | ||
629 | /* INT, ERR, and IAA interrupt rates can be throttled */ | |
630 | ||
631 | /* normal [4.15.1.2] or error [4.15.1.1] completion */ | |
632 | if (likely ((status & (STS_INT|STS_ERR)) != 0)) { | |
633 | if (likely ((status & STS_ERR) == 0)) | |
634 | COUNT (ehci->stats.normal); | |
635 | else | |
636 | COUNT (ehci->stats.error); | |
637 | bh = 1; | |
638 | } | |
639 | ||
640 | /* complete the unlinking of some qh [4.15.2.3] */ | |
641 | if (status & STS_IAA) { | |
642 | COUNT (ehci->stats.reclaim); | |
64f89798 | 643 | ehci->reclaim_ready = 1; |
1da177e4 LT |
644 | bh = 1; |
645 | } | |
646 | ||
647 | /* remote wakeup [4.3.1] */ | |
d97cc2f2 | 648 | if (status & STS_PCD) { |
1da177e4 | 649 | unsigned i = HCS_N_PORTS (ehci->hcs_params); |
1d619f12 | 650 | pcd_status = status; |
1da177e4 LT |
651 | |
652 | /* resume root hub? */ | |
083522d7 | 653 | if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN)) |
8c03356a | 654 | usb_hcd_resume_root_hub(hcd); |
1da177e4 LT |
655 | |
656 | while (i--) { | |
083522d7 BH |
657 | int pstatus = ehci_readl(ehci, |
658 | &ehci->regs->port_status [i]); | |
b972b68c DB |
659 | |
660 | if (pstatus & PORT_OWNER) | |
1da177e4 | 661 | continue; |
b972b68c | 662 | if (!(pstatus & PORT_RESUME) |
1da177e4 LT |
663 | || ehci->reset_done [i] != 0) |
664 | continue; | |
665 | ||
666 | /* start 20 msec resume signaling from this port, | |
667 | * and make khubd collect PORT_STAT_C_SUSPEND to | |
668 | * stop that signaling. | |
669 | */ | |
670 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | |
1da177e4 LT |
671 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); |
672 | } | |
673 | } | |
674 | ||
675 | /* PCI errors [4.15.2.4] */ | |
676 | if (unlikely ((status & STS_FATAL) != 0)) { | |
677 | /* bogus "fatal" IRQs appear on some chips... why? */ | |
083522d7 BH |
678 | status = ehci_readl(ehci, &ehci->regs->status); |
679 | dbg_cmd (ehci, "fatal", ehci_readl(ehci, | |
680 | &ehci->regs->command)); | |
1da177e4 LT |
681 | dbg_status (ehci, "fatal", status); |
682 | if (status & STS_HALT) { | |
683 | ehci_err (ehci, "fatal error\n"); | |
684 | dead: | |
685 | ehci_reset (ehci); | |
083522d7 | 686 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
1da177e4 LT |
687 | /* generic layer kills/unlinks all urbs, then |
688 | * uses ehci_stop to clean up the rest | |
689 | */ | |
690 | bh = 1; | |
691 | } | |
692 | } | |
693 | ||
694 | if (bh) | |
7d12e780 | 695 | ehci_work (ehci); |
1da177e4 | 696 | spin_unlock (&ehci->lock); |
1d619f12 MT |
697 | if (pcd_status & STS_PCD) |
698 | usb_hcd_poll_rh_status(hcd); | |
1da177e4 LT |
699 | return IRQ_HANDLED; |
700 | } | |
701 | ||
702 | /*-------------------------------------------------------------------------*/ | |
703 | ||
704 | /* | |
705 | * non-error returns are a promise to giveback() the urb later | |
706 | * we drop ownership so next owner (or urb unlink) can get it | |
707 | * | |
708 | * urb + dev is in hcd.self.controller.urb_list | |
709 | * we're queueing TDs onto software and hardware lists | |
710 | * | |
711 | * hcd-specific init for hcpriv hasn't been done yet | |
712 | * | |
713 | * NOTE: control, bulk, and interrupt share the same code to append TDs | |
714 | * to a (possibly active) QH, and the same QH scanning code. | |
715 | */ | |
716 | static int ehci_urb_enqueue ( | |
717 | struct usb_hcd *hcd, | |
718 | struct usb_host_endpoint *ep, | |
719 | struct urb *urb, | |
55016f10 | 720 | gfp_t mem_flags |
1da177e4 LT |
721 | ) { |
722 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
723 | struct list_head qtd_list; | |
724 | ||
725 | INIT_LIST_HEAD (&qtd_list); | |
726 | ||
727 | switch (usb_pipetype (urb->pipe)) { | |
728 | // case PIPE_CONTROL: | |
729 | // case PIPE_BULK: | |
730 | default: | |
731 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) | |
732 | return -ENOMEM; | |
733 | return submit_async (ehci, ep, urb, &qtd_list, mem_flags); | |
734 | ||
735 | case PIPE_INTERRUPT: | |
736 | if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) | |
737 | return -ENOMEM; | |
738 | return intr_submit (ehci, ep, urb, &qtd_list, mem_flags); | |
739 | ||
740 | case PIPE_ISOCHRONOUS: | |
741 | if (urb->dev->speed == USB_SPEED_HIGH) | |
742 | return itd_submit (ehci, urb, mem_flags); | |
743 | else | |
744 | return sitd_submit (ehci, urb, mem_flags); | |
745 | } | |
746 | } | |
747 | ||
748 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |
749 | { | |
64f89798 GKH |
750 | /* if we need to use IAA and it's busy, defer */ |
751 | if (qh->qh_state == QH_STATE_LINKED | |
752 | && ehci->reclaim | |
753 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { | |
1da177e4 LT |
754 | struct ehci_qh *last; |
755 | ||
756 | for (last = ehci->reclaim; | |
757 | last->reclaim; | |
758 | last = last->reclaim) | |
759 | continue; | |
760 | qh->qh_state = QH_STATE_UNLINK_WAIT; | |
761 | last->reclaim = qh; | |
762 | ||
64f89798 GKH |
763 | /* bypass IAA if the hc can't care */ |
764 | } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) | |
765 | end_unlink_async (ehci); | |
766 | ||
767 | /* something else might have unlinked the qh by now */ | |
768 | if (qh->qh_state == QH_STATE_LINKED) | |
1da177e4 LT |
769 | start_unlink_async (ehci, qh); |
770 | } | |
771 | ||
772 | /* remove from hardware lists | |
773 | * completions normally happen asynchronously | |
774 | */ | |
775 | ||
776 | static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |
777 | { | |
778 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
779 | struct ehci_qh *qh; | |
780 | unsigned long flags; | |
781 | ||
782 | spin_lock_irqsave (&ehci->lock, flags); | |
783 | switch (usb_pipetype (urb->pipe)) { | |
784 | // case PIPE_CONTROL: | |
785 | // case PIPE_BULK: | |
786 | default: | |
787 | qh = (struct ehci_qh *) urb->hcpriv; | |
788 | if (!qh) | |
789 | break; | |
64f89798 | 790 | unlink_async (ehci, qh); |
1da177e4 LT |
791 | break; |
792 | ||
793 | case PIPE_INTERRUPT: | |
794 | qh = (struct ehci_qh *) urb->hcpriv; | |
795 | if (!qh) | |
796 | break; | |
797 | switch (qh->qh_state) { | |
798 | case QH_STATE_LINKED: | |
799 | intr_deschedule (ehci, qh); | |
800 | /* FALL THROUGH */ | |
801 | case QH_STATE_IDLE: | |
7d12e780 | 802 | qh_completions (ehci, qh); |
1da177e4 LT |
803 | break; |
804 | default: | |
805 | ehci_dbg (ehci, "bogus qh %p state %d\n", | |
806 | qh, qh->qh_state); | |
807 | goto done; | |
808 | } | |
809 | ||
810 | /* reschedule QH iff another request is queued */ | |
811 | if (!list_empty (&qh->qtd_list) | |
812 | && HC_IS_RUNNING (hcd->state)) { | |
813 | int status; | |
814 | ||
815 | status = qh_schedule (ehci, qh); | |
816 | spin_unlock_irqrestore (&ehci->lock, flags); | |
817 | ||
818 | if (status != 0) { | |
819 | // shouldn't happen often, but ... | |
820 | // FIXME kill those tds' urbs | |
821 | err ("can't reschedule qh %p, err %d", | |
822 | qh, status); | |
823 | } | |
824 | return status; | |
825 | } | |
826 | break; | |
827 | ||
828 | case PIPE_ISOCHRONOUS: | |
829 | // itd or sitd ... | |
830 | ||
831 | // wait till next completion, do it then. | |
832 | // completion irqs can wait up to 1024 msec, | |
833 | break; | |
834 | } | |
835 | done: | |
836 | spin_unlock_irqrestore (&ehci->lock, flags); | |
837 | return 0; | |
838 | } | |
839 | ||
840 | /*-------------------------------------------------------------------------*/ | |
841 | ||
842 | // bulk qh holds the data toggle | |
843 | ||
844 | static void | |
845 | ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) | |
846 | { | |
847 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
848 | unsigned long flags; | |
849 | struct ehci_qh *qh, *tmp; | |
850 | ||
851 | /* ASSERT: any requests/urbs are being unlinked */ | |
852 | /* ASSERT: nobody can be submitting urbs for this any more */ | |
853 | ||
854 | rescan: | |
855 | spin_lock_irqsave (&ehci->lock, flags); | |
856 | qh = ep->hcpriv; | |
857 | if (!qh) | |
858 | goto done; | |
859 | ||
860 | /* endpoints can be iso streams. for now, we don't | |
861 | * accelerate iso completions ... so spin a while. | |
862 | */ | |
863 | if (qh->hw_info1 == 0) { | |
864 | ehci_vdbg (ehci, "iso delay\n"); | |
865 | goto idle_timeout; | |
866 | } | |
867 | ||
868 | if (!HC_IS_RUNNING (hcd->state)) | |
869 | qh->qh_state = QH_STATE_IDLE; | |
870 | switch (qh->qh_state) { | |
871 | case QH_STATE_LINKED: | |
872 | for (tmp = ehci->async->qh_next.qh; | |
873 | tmp && tmp != qh; | |
874 | tmp = tmp->qh_next.qh) | |
875 | continue; | |
876 | /* periodic qh self-unlinks on empty */ | |
877 | if (!tmp) | |
878 | goto nogood; | |
879 | unlink_async (ehci, qh); | |
880 | /* FALL THROUGH */ | |
881 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | |
882 | idle_timeout: | |
883 | spin_unlock_irqrestore (&ehci->lock, flags); | |
22c43863 | 884 | schedule_timeout_uninterruptible(1); |
1da177e4 LT |
885 | goto rescan; |
886 | case QH_STATE_IDLE: /* fully unlinked */ | |
887 | if (list_empty (&qh->qtd_list)) { | |
888 | qh_put (qh); | |
889 | break; | |
890 | } | |
891 | /* else FALL THROUGH */ | |
892 | default: | |
893 | nogood: | |
894 | /* caller was supposed to have unlinked any requests; | |
895 | * that's not our job. just leak this memory. | |
896 | */ | |
897 | ehci_err (ehci, "qh %p (#%02x) state %d%s\n", | |
898 | qh, ep->desc.bEndpointAddress, qh->qh_state, | |
899 | list_empty (&qh->qtd_list) ? "" : "(has tds)"); | |
900 | break; | |
901 | } | |
902 | ep->hcpriv = NULL; | |
903 | done: | |
904 | spin_unlock_irqrestore (&ehci->lock, flags); | |
905 | return; | |
906 | } | |
907 | ||
7ff71d6a MP |
908 | static int ehci_get_frame (struct usb_hcd *hcd) |
909 | { | |
910 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | |
083522d7 BH |
911 | return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) % |
912 | ehci->periodic_size; | |
7ff71d6a | 913 | } |
1da177e4 LT |
914 | |
915 | /*-------------------------------------------------------------------------*/ | |
916 | ||
1da177e4 LT |
917 | #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC |
918 | ||
919 | MODULE_DESCRIPTION (DRIVER_INFO); | |
920 | MODULE_AUTHOR (DRIVER_AUTHOR); | |
921 | MODULE_LICENSE ("GPL"); | |
922 | ||
7ff71d6a MP |
923 | #ifdef CONFIG_PCI |
924 | #include "ehci-pci.c" | |
01cced25 | 925 | #define PCI_DRIVER ehci_pci_driver |
7ff71d6a | 926 | #endif |
1da177e4 | 927 | |
a11570f2 | 928 | #ifdef CONFIG_MPC834x |
80cb9aee | 929 | #include "ehci-fsl.c" |
01cced25 | 930 | #define PLATFORM_DRIVER ehci_fsl_driver |
80cb9aee RV |
931 | #endif |
932 | ||
dfbaa7d8 | 933 | #ifdef CONFIG_SOC_AU1200 |
76fa9a24 | 934 | #include "ehci-au1xxx.c" |
01cced25 | 935 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
76fa9a24 JC |
936 | #endif |
937 | ||
ad75a410 GL |
938 | #ifdef CONFIG_PPC_PS3 |
939 | #include "ehci-ps3.c" | |
940 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver | |
941 | #endif | |
942 | ||
943 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | |
944 | !defined(PS3_SYSTEM_BUS_DRIVER) | |
7ff71d6a MP |
945 | #error "missing bus glue for ehci-hcd" |
946 | #endif | |
01cced25 KG |
947 | |
948 | static int __init ehci_hcd_init(void) | |
949 | { | |
950 | int retval = 0; | |
951 | ||
952 | pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | |
953 | hcd_name, | |
954 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | |
955 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | |
956 | ||
957 | #ifdef PLATFORM_DRIVER | |
958 | retval = platform_driver_register(&PLATFORM_DRIVER); | |
959 | if (retval < 0) | |
960 | return retval; | |
961 | #endif | |
962 | ||
963 | #ifdef PCI_DRIVER | |
964 | retval = pci_register_driver(&PCI_DRIVER); | |
965 | if (retval < 0) { | |
966 | #ifdef PLATFORM_DRIVER | |
967 | platform_driver_unregister(&PLATFORM_DRIVER); | |
968 | #endif | |
ad75a410 GL |
969 | return retval; |
970 | } | |
971 | #endif | |
972 | ||
973 | #ifdef PS3_SYSTEM_BUS_DRIVER | |
48fda451 IK |
974 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { |
975 | retval = ps3_system_bus_driver_register( | |
976 | &PS3_SYSTEM_BUS_DRIVER); | |
977 | if (retval < 0) { | |
ad75a410 | 978 | #ifdef PLATFORM_DRIVER |
48fda451 | 979 | platform_driver_unregister(&PLATFORM_DRIVER); |
ad75a410 GL |
980 | #endif |
981 | #ifdef PCI_DRIVER | |
48fda451 | 982 | pci_unregister_driver(&PCI_DRIVER); |
ad75a410 | 983 | #endif |
48fda451 IK |
984 | return retval; |
985 | } | |
01cced25 KG |
986 | } |
987 | #endif | |
988 | ||
989 | return retval; | |
990 | } | |
991 | module_init(ehci_hcd_init); | |
992 | ||
993 | static void __exit ehci_hcd_cleanup(void) | |
994 | { | |
995 | #ifdef PLATFORM_DRIVER | |
996 | platform_driver_unregister(&PLATFORM_DRIVER); | |
997 | #endif | |
998 | #ifdef PCI_DRIVER | |
999 | pci_unregister_driver(&PCI_DRIVER); | |
1000 | #endif | |
ad75a410 | 1001 | #ifdef PS3_SYSTEM_BUS_DRIVER |
48fda451 IK |
1002 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) |
1003 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | |
ad75a410 | 1004 | #endif |
01cced25 KG |
1005 | } |
1006 | module_exit(ehci_hcd_cleanup); | |
1007 |