diff options
Diffstat (limited to 'drivers/usb/host')
26 files changed, 1038 insertions, 830 deletions
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 350d14fc1cc9..58321d3f314c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | # | 1 | # |
| 2 | # Makefile for USB Host Controller Driver | 2 | # Makefile for USB Host Controller Drivers |
| 3 | # framework and drivers | ||
| 4 | # | 3 | # |
| 5 | 4 | ||
| 5 | obj-$(CONFIG_PCI) += pci-quirks.o | ||
| 6 | |||
| 6 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 7 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
| 7 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 8 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
| 8 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 9 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f5eb9e7b5b18..af3c05eb86fc 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -182,6 +182,9 @@ static int ehci_halt (struct ehci_hcd *ehci) | |||
| 182 | { | 182 | { |
| 183 | u32 temp = readl (&ehci->regs->status); | 183 | u32 temp = readl (&ehci->regs->status); |
| 184 | 184 | ||
| 185 | /* disable any irqs left enabled by previous code */ | ||
| 186 | writel (0, &ehci->regs->intr_enable); | ||
| 187 | |||
| 185 | if ((temp & STS_HALT) != 0) | 188 | if ((temp & STS_HALT) != 0) |
| 186 | return 0; | 189 | return 0; |
| 187 | 190 | ||
| @@ -297,50 +300,17 @@ static void ehci_watchdog (unsigned long param) | |||
| 297 | spin_unlock_irqrestore (&ehci->lock, flags); | 300 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 298 | } | 301 | } |
| 299 | 302 | ||
| 300 | #ifdef CONFIG_PCI | 303 | /* Reboot notifiers kick in for silicon on any bus (not just pci, etc). |
| 301 | 304 | * This forcibly disables dma and IRQs, helping kexec and other cases | |
| 302 | /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... | 305 | * where the next system software may expect clean state. |
| 303 | * off the controller (maybe it can boot from highspeed USB disks). | ||
| 304 | */ | 306 | */ |
| 305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) | ||
| 306 | { | ||
| 307 | struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
| 308 | |||
| 309 | /* always say Linux will own the hardware */ | ||
| 310 | pci_write_config_byte(pdev, where + 3, 1); | ||
| 311 | |||
| 312 | /* maybe wait a while for BIOS to respond */ | ||
| 313 | if (cap & (1 << 16)) { | ||
| 314 | int msec = 5000; | ||
| 315 | |||
| 316 | do { | ||
| 317 | msleep(10); | ||
| 318 | msec -= 10; | ||
| 319 | pci_read_config_dword(pdev, where, &cap); | ||
| 320 | } while ((cap & (1 << 16)) && msec); | ||
| 321 | if (cap & (1 << 16)) { | ||
| 322 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", | ||
| 323 | where, cap); | ||
| 324 | // some BIOS versions seem buggy... | ||
| 325 | // return 1; | ||
| 326 | ehci_warn (ehci, "continuing after BIOS bug...\n"); | ||
| 327 | /* disable all SMIs, and clear "BIOS owns" flag */ | ||
| 328 | pci_write_config_dword(pdev, where + 4, 0); | ||
| 329 | pci_write_config_byte(pdev, where + 2, 0); | ||
| 330 | } else | ||
| 331 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
| 332 | } | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | #endif | ||
| 337 | |||
| 338 | static int | 307 | static int |
| 339 | ehci_reboot (struct notifier_block *self, unsigned long code, void *null) | 308 | ehci_reboot (struct notifier_block *self, unsigned long code, void *null) |
| 340 | { | 309 | { |
| 341 | struct ehci_hcd *ehci; | 310 | struct ehci_hcd *ehci; |
| 342 | 311 | ||
| 343 | ehci = container_of (self, struct ehci_hcd, reboot_notifier); | 312 | ehci = container_of (self, struct ehci_hcd, reboot_notifier); |
| 313 | (void) ehci_halt (ehci); | ||
| 344 | 314 | ||
| 345 | /* make BIOS/etc use companion controller during reboot */ | 315 | /* make BIOS/etc use companion controller during reboot */ |
| 346 | writel (0, &ehci->regs->configured_flag); | 316 | writel (0, &ehci->regs->configured_flag); |
| @@ -363,156 +333,90 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
| 363 | msleep(20); | 333 | msleep(20); |
| 364 | } | 334 | } |
| 365 | 335 | ||
| 336 | /*-------------------------------------------------------------------------*/ | ||
| 337 | |||
| 338 | /* | ||
| 339 | * ehci_work is called from some interrupts, timers, and so on. | ||
| 340 | * it calls driver completion functions, after dropping ehci->lock. | ||
| 341 | */ | ||
| 342 | static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) | ||
| 343 | { | ||
| 344 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | ||
| 345 | if (ehci->reclaim_ready) | ||
| 346 | end_unlink_async (ehci, regs); | ||
| 347 | |||
| 348 | /* another CPU may drop ehci->lock during a schedule scan while | ||
| 349 | * it reports urb completions. this flag guards against bogus | ||
| 350 | * attempts at re-entrant schedule scanning. | ||
| 351 | */ | ||
| 352 | if (ehci->scanning) | ||
| 353 | return; | ||
| 354 | ehci->scanning = 1; | ||
| 355 | scan_async (ehci, regs); | ||
| 356 | if (ehci->next_uframe != -1) | ||
| 357 | scan_periodic (ehci, regs); | ||
| 358 | ehci->scanning = 0; | ||
| 366 | 359 | ||
| 367 | /* called by khubd or root hub init threads */ | 360 | /* the IO watchdog guards against hardware or driver bugs that |
| 361 | * misplace IRQs, and should let us run completely without IRQs. | ||
| 362 | * such lossage has been observed on both VT6202 and VT8235. | ||
| 363 | */ | ||
| 364 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && | ||
| 365 | (ehci->async->qh_next.ptr != NULL || | ||
| 366 | ehci->periodic_sched != 0)) | ||
| 367 | timer_action (ehci, TIMER_IO_WATCHDOG); | ||
| 368 | } | ||
| 368 | 369 | ||
| 369 | static int ehci_hc_reset (struct usb_hcd *hcd) | 370 | static void ehci_stop (struct usb_hcd *hcd) |
| 370 | { | 371 | { |
| 371 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 372 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 372 | u32 temp; | ||
| 373 | unsigned count = 256/4; | ||
| 374 | 373 | ||
| 375 | spin_lock_init (&ehci->lock); | 374 | ehci_dbg (ehci, "stop\n"); |
| 376 | 375 | ||
| 377 | ehci->caps = hcd->regs; | 376 | /* Turn off port power on all root hub ports. */ |
| 378 | ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); | 377 | ehci_port_power (ehci, 0); |
| 379 | dbg_hcs_params (ehci, "reset"); | ||
| 380 | dbg_hcc_params (ehci, "reset"); | ||
| 381 | 378 | ||
| 382 | /* cache this readonly data; minimize chip reads */ | 379 | /* no more interrupts ... */ |
| 383 | ehci->hcs_params = readl (&ehci->caps->hcs_params); | 380 | del_timer_sync (&ehci->watchdog); |
| 384 | 381 | ||
| 385 | #ifdef CONFIG_PCI | 382 | spin_lock_irq(&ehci->lock); |
| 386 | if (hcd->self.controller->bus == &pci_bus_type) { | 383 | if (HC_IS_RUNNING (hcd->state)) |
| 387 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 384 | ehci_quiesce (ehci); |
| 388 | 385 | ||
| 389 | switch (pdev->vendor) { | 386 | ehci_reset (ehci); |
| 390 | case PCI_VENDOR_ID_TDI: | 387 | writel (0, &ehci->regs->intr_enable); |
| 391 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | 388 | spin_unlock_irq(&ehci->lock); |
| 392 | ehci->is_tdi_rh_tt = 1; | ||
| 393 | tdi_reset (ehci); | ||
| 394 | } | ||
| 395 | break; | ||
| 396 | case PCI_VENDOR_ID_AMD: | ||
| 397 | /* AMD8111 EHCI doesn't work, according to AMD errata */ | ||
| 398 | if (pdev->device == 0x7463) { | ||
| 399 | ehci_info (ehci, "ignoring AMD8111 (errata)\n"); | ||
| 400 | return -EIO; | ||
| 401 | } | ||
| 402 | break; | ||
| 403 | case PCI_VENDOR_ID_NVIDIA: | ||
| 404 | /* NVidia reports that certain chips don't handle | ||
| 405 | * QH, ITD, or SITD addresses above 2GB. (But TD, | ||
| 406 | * data buffer, and periodic schedule are normal.) | ||
| 407 | */ | ||
| 408 | switch (pdev->device) { | ||
| 409 | case 0x003c: /* MCP04 */ | ||
| 410 | case 0x005b: /* CK804 */ | ||
| 411 | case 0x00d8: /* CK8 */ | ||
| 412 | case 0x00e8: /* CK8S */ | ||
| 413 | if (pci_set_consistent_dma_mask(pdev, | ||
| 414 | DMA_31BIT_MASK) < 0) | ||
| 415 | ehci_warn (ehci, "can't enable NVidia " | ||
| 416 | "workaround for >2GB RAM\n"); | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | 389 | ||
| 422 | /* optional debug port, normally in the first BAR */ | 390 | /* let companion controllers work when we aren't */ |
| 423 | temp = pci_find_capability (pdev, 0x0a); | 391 | writel (0, &ehci->regs->configured_flag); |
| 424 | if (temp) { | 392 | unregister_reboot_notifier (&ehci->reboot_notifier); |
| 425 | pci_read_config_dword(pdev, temp, &temp); | ||
| 426 | temp >>= 16; | ||
| 427 | if ((temp & (3 << 13)) == (1 << 13)) { | ||
| 428 | temp &= 0x1fff; | ||
| 429 | ehci->debug = hcd->regs + temp; | ||
| 430 | temp = readl (&ehci->debug->control); | ||
| 431 | ehci_info (ehci, "debug port %d%s\n", | ||
| 432 | HCS_DEBUG_PORT(ehci->hcs_params), | ||
| 433 | (temp & DBGP_ENABLED) | ||
| 434 | ? " IN USE" | ||
| 435 | : ""); | ||
| 436 | if (!(temp & DBGP_ENABLED)) | ||
| 437 | ehci->debug = NULL; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | 393 | ||
| 441 | temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | 394 | remove_debug_files (ehci); |
| 442 | } else | ||
| 443 | temp = 0; | ||
| 444 | |||
| 445 | /* EHCI 0.96 and later may have "extended capabilities" */ | ||
| 446 | while (temp && count--) { | ||
| 447 | u32 cap; | ||
| 448 | |||
| 449 | pci_read_config_dword (to_pci_dev(hcd->self.controller), | ||
| 450 | temp, &cap); | ||
| 451 | ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); | ||
| 452 | switch (cap & 0xff) { | ||
| 453 | case 1: /* BIOS/SMM/... handoff */ | ||
| 454 | if (bios_handoff (ehci, temp, cap) != 0) | ||
| 455 | return -EOPNOTSUPP; | ||
| 456 | break; | ||
| 457 | case 0: /* illegal reserved capability */ | ||
| 458 | ehci_warn (ehci, "illegal capability!\n"); | ||
| 459 | cap = 0; | ||
| 460 | /* FALLTHROUGH */ | ||
| 461 | default: /* unknown */ | ||
| 462 | break; | ||
| 463 | } | ||
| 464 | temp = (cap >> 8) & 0xff; | ||
| 465 | } | ||
| 466 | if (!count) { | ||
| 467 | ehci_err (ehci, "bogus capabilities ... PCI problems!\n"); | ||
| 468 | return -EIO; | ||
| 469 | } | ||
| 470 | if (ehci_is_TDI(ehci)) | ||
| 471 | ehci_reset (ehci); | ||
| 472 | #endif | ||
| 473 | 395 | ||
| 474 | ehci_port_power (ehci, 0); | 396 | /* root hub is shut down separately (first, when possible) */ |
| 397 | spin_lock_irq (&ehci->lock); | ||
| 398 | if (ehci->async) | ||
| 399 | ehci_work (ehci, NULL); | ||
| 400 | spin_unlock_irq (&ehci->lock); | ||
| 401 | ehci_mem_cleanup (ehci); | ||
| 475 | 402 | ||
| 476 | /* at least the Genesys GL880S needs fixup here */ | 403 | #ifdef EHCI_STATS |
| 477 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); | 404 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", |
| 478 | temp &= 0x0f; | 405 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, |
| 479 | if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { | 406 | ehci->stats.lost_iaa); |
| 480 | ehci_dbg (ehci, "bogus port configuration: " | 407 | ehci_dbg (ehci, "complete %ld unlink %ld\n", |
| 481 | "cc=%d x pcc=%d < ports=%d\n", | 408 | ehci->stats.complete, ehci->stats.unlink); |
| 482 | HCS_N_CC(ehci->hcs_params), | ||
| 483 | HCS_N_PCC(ehci->hcs_params), | ||
| 484 | HCS_N_PORTS(ehci->hcs_params)); | ||
| 485 | |||
| 486 | #ifdef CONFIG_PCI | ||
| 487 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 488 | struct pci_dev *pdev; | ||
| 489 | |||
| 490 | pdev = to_pci_dev(hcd->self.controller); | ||
| 491 | switch (pdev->vendor) { | ||
| 492 | case 0x17a0: /* GENESYS */ | ||
| 493 | /* GL880S: should be PORTS=2 */ | ||
| 494 | temp |= (ehci->hcs_params & ~0xf); | ||
| 495 | ehci->hcs_params = temp; | ||
| 496 | break; | ||
| 497 | case PCI_VENDOR_ID_NVIDIA: | ||
| 498 | /* NF4: should be PCC=10 */ | ||
| 499 | break; | ||
| 500 | } | ||
| 501 | } | ||
| 502 | #endif | 409 | #endif |
| 503 | } | ||
| 504 | 410 | ||
| 505 | /* force HC to halt state */ | 411 | dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); |
| 506 | return ehci_halt (ehci); | ||
| 507 | } | 412 | } |
| 508 | 413 | ||
| 509 | static int ehci_start (struct usb_hcd *hcd) | 414 | static int ehci_run (struct usb_hcd *hcd) |
| 510 | { | 415 | { |
| 511 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 416 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 512 | u32 temp; | 417 | u32 temp; |
| 513 | int retval; | 418 | int retval; |
| 514 | u32 hcc_params; | 419 | u32 hcc_params; |
| 515 | u8 sbrn = 0; | ||
| 516 | int first; | 420 | int first; |
| 517 | 421 | ||
| 518 | /* skip some things on restart paths */ | 422 | /* skip some things on restart paths */ |
| @@ -551,27 +455,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
| 551 | } | 455 | } |
| 552 | writel (ehci->periodic_dma, &ehci->regs->frame_list); | 456 | writel (ehci->periodic_dma, &ehci->regs->frame_list); |
| 553 | 457 | ||
| 554 | #ifdef CONFIG_PCI | ||
| 555 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 556 | struct pci_dev *pdev; | ||
| 557 | u16 port_wake; | ||
| 558 | |||
| 559 | pdev = to_pci_dev(hcd->self.controller); | ||
| 560 | |||
| 561 | /* Serial Bus Release Number is at PCI 0x60 offset */ | ||
| 562 | pci_read_config_byte(pdev, 0x60, &sbrn); | ||
| 563 | |||
| 564 | /* port wake capability, reported by boot firmware */ | ||
| 565 | pci_read_config_word(pdev, 0x62, &port_wake); | ||
| 566 | hcd->can_wakeup = (port_wake & 1) != 0; | ||
| 567 | |||
| 568 | /* help hc dma work well with cachelines */ | ||
| 569 | retval = pci_set_mwi(pdev); | ||
| 570 | if (retval) | ||
| 571 | ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); | ||
| 572 | } | ||
| 573 | #endif | ||
| 574 | |||
| 575 | /* | 458 | /* |
| 576 | * dedicate a qh for the async ring head, since we couldn't unlink | 459 | * dedicate a qh for the async ring head, since we couldn't unlink |
| 577 | * a 'real' qh without stopping the async schedule [4.8]. use it | 460 | * a 'real' qh without stopping the async schedule [4.8]. use it |
| @@ -667,7 +550,7 @@ static int ehci_start (struct usb_hcd *hcd) | |||
| 667 | temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 550 | temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); |
| 668 | ehci_info (ehci, | 551 | ehci_info (ehci, |
| 669 | "USB %x.%x %s, EHCI %x.%02x, driver %s\n", | 552 | "USB %x.%x %s, EHCI %x.%02x, driver %s\n", |
| 670 | ((sbrn & 0xf0)>>4), (sbrn & 0x0f), | 553 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), |
| 671 | first ? "initialized" : "restarted", | 554 | first ? "initialized" : "restarted", |
| 672 | temp >> 8, temp & 0xff, DRIVER_VERSION); | 555 | temp >> 8, temp & 0xff, DRIVER_VERSION); |
| 673 | 556 | ||
| @@ -679,188 +562,6 @@ static int ehci_start (struct usb_hcd *hcd) | |||
| 679 | return 0; | 562 | return 0; |
| 680 | } | 563 | } |
| 681 | 564 | ||
| 682 | /* always called by thread; normally rmmod */ | ||
| 683 | |||
| 684 | static void ehci_stop (struct usb_hcd *hcd) | ||
| 685 | { | ||
| 686 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 687 | |||
| 688 | ehci_dbg (ehci, "stop\n"); | ||
| 689 | |||
| 690 | /* Turn off port power on all root hub ports. */ | ||
| 691 | ehci_port_power (ehci, 0); | ||
| 692 | |||
| 693 | /* no more interrupts ... */ | ||
| 694 | del_timer_sync (&ehci->watchdog); | ||
| 695 | |||
| 696 | spin_lock_irq(&ehci->lock); | ||
| 697 | if (HC_IS_RUNNING (hcd->state)) | ||
| 698 | ehci_quiesce (ehci); | ||
| 699 | |||
| 700 | ehci_reset (ehci); | ||
| 701 | writel (0, &ehci->regs->intr_enable); | ||
| 702 | spin_unlock_irq(&ehci->lock); | ||
| 703 | |||
| 704 | /* let companion controllers work when we aren't */ | ||
| 705 | writel (0, &ehci->regs->configured_flag); | ||
| 706 | unregister_reboot_notifier (&ehci->reboot_notifier); | ||
| 707 | |||
| 708 | remove_debug_files (ehci); | ||
| 709 | |||
| 710 | /* root hub is shut down separately (first, when possible) */ | ||
| 711 | spin_lock_irq (&ehci->lock); | ||
| 712 | if (ehci->async) | ||
| 713 | ehci_work (ehci, NULL); | ||
| 714 | spin_unlock_irq (&ehci->lock); | ||
| 715 | ehci_mem_cleanup (ehci); | ||
| 716 | |||
| 717 | #ifdef EHCI_STATS | ||
| 718 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | ||
| 719 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | ||
| 720 | ehci->stats.lost_iaa); | ||
| 721 | ehci_dbg (ehci, "complete %ld unlink %ld\n", | ||
| 722 | ehci->stats.complete, ehci->stats.unlink); | ||
| 723 | #endif | ||
| 724 | |||
| 725 | dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); | ||
| 726 | } | ||
| 727 | |||
| 728 | static int ehci_get_frame (struct usb_hcd *hcd) | ||
| 729 | { | ||
| 730 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 731 | return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; | ||
| 732 | } | ||
| 733 | |||
| 734 | /*-------------------------------------------------------------------------*/ | ||
| 735 | |||
| 736 | #ifdef CONFIG_PM | ||
| 737 | |||
| 738 | /* suspend/resume, section 4.3 */ | ||
| 739 | |||
| 740 | /* These routines rely on the bus (pci, platform, etc) | ||
| 741 | * to handle powerdown and wakeup, and currently also on | ||
| 742 | * transceivers that don't need any software attention to set up | ||
| 743 | * the right sort of wakeup. | ||
| 744 | */ | ||
| 745 | |||
| 746 | static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message) | ||
| 747 | { | ||
| 748 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 749 | |||
| 750 | if (time_before (jiffies, ehci->next_statechange)) | ||
| 751 | msleep (100); | ||
| 752 | |||
| 753 | #ifdef CONFIG_USB_SUSPEND | ||
| 754 | (void) usb_suspend_device (hcd->self.root_hub, message); | ||
| 755 | #else | ||
| 756 | usb_lock_device (hcd->self.root_hub); | ||
| 757 | (void) ehci_hub_suspend (hcd); | ||
| 758 | usb_unlock_device (hcd->self.root_hub); | ||
| 759 | #endif | ||
| 760 | |||
| 761 | // save (PCI) FLADJ in case of Vaux power loss | ||
| 762 | // ... we'd only use it to handle clock skew | ||
| 763 | |||
| 764 | return 0; | ||
| 765 | } | ||
| 766 | |||
| 767 | static int ehci_resume (struct usb_hcd *hcd) | ||
| 768 | { | ||
| 769 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 770 | unsigned port; | ||
| 771 | struct usb_device *root = hcd->self.root_hub; | ||
| 772 | int retval = -EINVAL; | ||
| 773 | |||
| 774 | // maybe restore (PCI) FLADJ | ||
| 775 | |||
| 776 | if (time_before (jiffies, ehci->next_statechange)) | ||
| 777 | msleep (100); | ||
| 778 | |||
| 779 | /* If any port is suspended (or owned by the companion), | ||
| 780 | * we know we can/must resume the HC (and mustn't reset it). | ||
| 781 | */ | ||
| 782 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { | ||
| 783 | u32 status; | ||
| 784 | port--; | ||
| 785 | status = readl (&ehci->regs->port_status [port]); | ||
| 786 | if (!(status & PORT_POWER)) | ||
| 787 | continue; | ||
| 788 | if (status & (PORT_SUSPEND | PORT_OWNER)) { | ||
| 789 | down (&hcd->self.root_hub->serialize); | ||
| 790 | retval = ehci_hub_resume (hcd); | ||
| 791 | up (&hcd->self.root_hub->serialize); | ||
| 792 | break; | ||
| 793 | } | ||
| 794 | if (!root->children [port]) | ||
| 795 | continue; | ||
| 796 | dbg_port (ehci, __FUNCTION__, port + 1, status); | ||
| 797 | usb_set_device_state (root->children[port], | ||
| 798 | USB_STATE_NOTATTACHED); | ||
| 799 | } | ||
| 800 | |||
| 801 | /* Else reset, to cope with power loss or flush-to-storage | ||
| 802 | * style "resume" having activated BIOS during reboot. | ||
| 803 | */ | ||
| 804 | if (port == 0) { | ||
| 805 | (void) ehci_halt (ehci); | ||
| 806 | (void) ehci_reset (ehci); | ||
| 807 | (void) ehci_hc_reset (hcd); | ||
| 808 | |||
| 809 | /* emptying the schedule aborts any urbs */ | ||
| 810 | spin_lock_irq (&ehci->lock); | ||
| 811 | if (ehci->reclaim) | ||
| 812 | ehci->reclaim_ready = 1; | ||
| 813 | ehci_work (ehci, NULL); | ||
| 814 | spin_unlock_irq (&ehci->lock); | ||
| 815 | |||
| 816 | /* restart; khubd will disconnect devices */ | ||
| 817 | retval = ehci_start (hcd); | ||
| 818 | |||
| 819 | /* here we "know" root ports should always stay powered; | ||
| 820 | * but some controllers may lose all power. | ||
| 821 | */ | ||
| 822 | ehci_port_power (ehci, 1); | ||
| 823 | } | ||
| 824 | |||
| 825 | return retval; | ||
| 826 | } | ||
| 827 | |||
| 828 | #endif | ||
| 829 | |||
| 830 | /*-------------------------------------------------------------------------*/ | ||
| 831 | |||
| 832 | /* | ||
| 833 | * ehci_work is called from some interrupts, timers, and so on. | ||
| 834 | * it calls driver completion functions, after dropping ehci->lock. | ||
| 835 | */ | ||
| 836 | static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) | ||
| 837 | { | ||
| 838 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | ||
| 839 | if (ehci->reclaim_ready) | ||
| 840 | end_unlink_async (ehci, regs); | ||
| 841 | |||
| 842 | /* another CPU may drop ehci->lock during a schedule scan while | ||
| 843 | * it reports urb completions. this flag guards against bogus | ||
| 844 | * attempts at re-entrant schedule scanning. | ||
| 845 | */ | ||
| 846 | if (ehci->scanning) | ||
| 847 | return; | ||
| 848 | ehci->scanning = 1; | ||
| 849 | scan_async (ehci, regs); | ||
| 850 | if (ehci->next_uframe != -1) | ||
| 851 | scan_periodic (ehci, regs); | ||
| 852 | ehci->scanning = 0; | ||
| 853 | |||
| 854 | /* the IO watchdog guards against hardware or driver bugs that | ||
| 855 | * misplace IRQs, and should let us run completely without IRQs. | ||
| 856 | * such lossage has been observed on both VT6202 and VT8235. | ||
| 857 | */ | ||
| 858 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && | ||
| 859 | (ehci->async->qh_next.ptr != NULL || | ||
| 860 | ehci->periodic_sched != 0)) | ||
| 861 | timer_action (ehci, TIMER_IO_WATCHDOG); | ||
| 862 | } | ||
| 863 | |||
| 864 | /*-------------------------------------------------------------------------*/ | 565 | /*-------------------------------------------------------------------------*/ |
| 865 | 566 | ||
| 866 | static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) | 567 | static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) |
| @@ -1171,106 +872,24 @@ done: | |||
| 1171 | return; | 872 | return; |
| 1172 | } | 873 | } |
| 1173 | 874 | ||
| 1174 | /*-------------------------------------------------------------------------*/ | 875 | static int ehci_get_frame (struct usb_hcd *hcd) |
| 1175 | 876 | { | |
| 1176 | static const struct hc_driver ehci_driver = { | 877 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 1177 | .description = hcd_name, | 878 | return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; |
| 1178 | .product_desc = "EHCI Host Controller", | 879 | } |
| 1179 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 1180 | |||
| 1181 | /* | ||
| 1182 | * generic hardware linkage | ||
| 1183 | */ | ||
| 1184 | .irq = ehci_irq, | ||
| 1185 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 1186 | |||
| 1187 | /* | ||
| 1188 | * basic lifecycle operations | ||
| 1189 | */ | ||
| 1190 | .reset = ehci_hc_reset, | ||
| 1191 | .start = ehci_start, | ||
| 1192 | #ifdef CONFIG_PM | ||
| 1193 | .suspend = ehci_suspend, | ||
| 1194 | .resume = ehci_resume, | ||
| 1195 | #endif | ||
| 1196 | .stop = ehci_stop, | ||
| 1197 | |||
| 1198 | /* | ||
| 1199 | * managing i/o requests and associated device resources | ||
| 1200 | */ | ||
| 1201 | .urb_enqueue = ehci_urb_enqueue, | ||
| 1202 | .urb_dequeue = ehci_urb_dequeue, | ||
| 1203 | .endpoint_disable = ehci_endpoint_disable, | ||
| 1204 | |||
| 1205 | /* | ||
| 1206 | * scheduling support | ||
| 1207 | */ | ||
| 1208 | .get_frame_number = ehci_get_frame, | ||
| 1209 | |||
| 1210 | /* | ||
| 1211 | * root hub support | ||
| 1212 | */ | ||
| 1213 | .hub_status_data = ehci_hub_status_data, | ||
| 1214 | .hub_control = ehci_hub_control, | ||
| 1215 | .hub_suspend = ehci_hub_suspend, | ||
| 1216 | .hub_resume = ehci_hub_resume, | ||
| 1217 | }; | ||
| 1218 | 880 | ||
| 1219 | /*-------------------------------------------------------------------------*/ | 881 | /*-------------------------------------------------------------------------*/ |
| 1220 | 882 | ||
| 1221 | /* EHCI 1.0 doesn't require PCI */ | ||
| 1222 | |||
| 1223 | #ifdef CONFIG_PCI | ||
| 1224 | |||
| 1225 | /* PCI driver selection metadata; PCI hotplugging uses this */ | ||
| 1226 | static const struct pci_device_id pci_ids [] = { { | ||
| 1227 | /* handle any USB 2.0 EHCI controller */ | ||
| 1228 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), | ||
| 1229 | .driver_data = (unsigned long) &ehci_driver, | ||
| 1230 | }, | ||
| 1231 | { /* end: all zeroes */ } | ||
| 1232 | }; | ||
| 1233 | MODULE_DEVICE_TABLE (pci, pci_ids); | ||
| 1234 | |||
| 1235 | /* pci driver glue; this is a "new style" PCI driver module */ | ||
| 1236 | static struct pci_driver ehci_pci_driver = { | ||
| 1237 | .name = (char *) hcd_name, | ||
| 1238 | .id_table = pci_ids, | ||
| 1239 | |||
| 1240 | .probe = usb_hcd_pci_probe, | ||
| 1241 | .remove = usb_hcd_pci_remove, | ||
| 1242 | |||
| 1243 | #ifdef CONFIG_PM | ||
| 1244 | .suspend = usb_hcd_pci_suspend, | ||
| 1245 | .resume = usb_hcd_pci_resume, | ||
| 1246 | #endif | ||
| 1247 | }; | ||
| 1248 | |||
| 1249 | #endif /* PCI */ | ||
| 1250 | |||
| 1251 | |||
| 1252 | #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC | 883 | #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC |
| 1253 | 884 | ||
| 1254 | MODULE_DESCRIPTION (DRIVER_INFO); | 885 | MODULE_DESCRIPTION (DRIVER_INFO); |
| 1255 | MODULE_AUTHOR (DRIVER_AUTHOR); | 886 | MODULE_AUTHOR (DRIVER_AUTHOR); |
| 1256 | MODULE_LICENSE ("GPL"); | 887 | MODULE_LICENSE ("GPL"); |
| 1257 | 888 | ||
| 1258 | static int __init init (void) | 889 | #ifdef CONFIG_PCI |
| 1259 | { | 890 | #include "ehci-pci.c" |
| 1260 | if (usb_disabled()) | 891 | #endif |
| 1261 | return -ENODEV; | ||
| 1262 | |||
| 1263 | pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | ||
| 1264 | hcd_name, | ||
| 1265 | sizeof (struct ehci_qh), sizeof (struct ehci_qtd), | ||
| 1266 | sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); | ||
| 1267 | |||
| 1268 | return pci_register_driver (&ehci_pci_driver); | ||
| 1269 | } | ||
| 1270 | module_init (init); | ||
| 1271 | 892 | ||
| 1272 | static void __exit cleanup (void) | 893 | #if !defined(CONFIG_PCI) |
| 1273 | { | 894 | #error "missing bus glue for ehci-hcd" |
| 1274 | pci_unregister_driver (&ehci_pci_driver); | 895 | #endif |
| 1275 | } | ||
| 1276 | module_exit (cleanup); | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 18d3f2270316..88cb4ada686e 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #ifdef CONFIG_PM | 31 | #ifdef CONFIG_PM |
| 32 | 32 | ||
| 33 | static int ehci_hub_suspend (struct usb_hcd *hcd) | 33 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
| 34 | { | 34 | { |
| 35 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 35 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 36 | int port; | 36 | int port; |
| @@ -83,7 +83,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd) | |||
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | /* caller has locked the root hub, and should reset/reinit on error */ | 85 | /* caller has locked the root hub, and should reset/reinit on error */ |
| 86 | static int ehci_hub_resume (struct usb_hcd *hcd) | 86 | static int ehci_bus_resume (struct usb_hcd *hcd) |
| 87 | { | 87 | { |
| 88 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 88 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
| 89 | u32 temp; | 89 | u32 temp; |
| @@ -159,8 +159,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd) | |||
| 159 | 159 | ||
| 160 | #else | 160 | #else |
| 161 | 161 | ||
| 162 | #define ehci_hub_suspend NULL | 162 | #define ehci_bus_suspend NULL |
| 163 | #define ehci_hub_resume NULL | 163 | #define ehci_bus_resume NULL |
| 164 | 164 | ||
| 165 | #endif /* CONFIG_PM */ | 165 | #endif /* CONFIG_PM */ |
| 166 | 166 | ||
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c new file mode 100644 index 000000000000..145008853966 --- /dev/null +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -0,0 +1,415 @@ | |||
| 1 | /* | ||
| 2 | * EHCI HCD (Host Controller Driver) PCI Bus Glue. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2000-2004 by David Brownell | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| 13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software Foundation, | ||
| 18 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef CONFIG_PCI | ||
| 22 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." | ||
| 23 | #endif | ||
| 24 | |||
| 25 | /*-------------------------------------------------------------------------*/ | ||
| 26 | |||
| 27 | /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... | ||
| 28 | * off the controller (maybe it can boot from highspeed USB disks). | ||
| 29 | */ | ||
| 30 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) | ||
| 31 | { | ||
| 32 | struct pci_dev *pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
| 33 | |||
| 34 | /* always say Linux will own the hardware */ | ||
| 35 | pci_write_config_byte(pdev, where + 3, 1); | ||
| 36 | |||
| 37 | /* maybe wait a while for BIOS to respond */ | ||
| 38 | if (cap & (1 << 16)) { | ||
| 39 | int msec = 5000; | ||
| 40 | |||
| 41 | do { | ||
| 42 | msleep(10); | ||
| 43 | msec -= 10; | ||
| 44 | pci_read_config_dword(pdev, where, &cap); | ||
| 45 | } while ((cap & (1 << 16)) && msec); | ||
| 46 | if (cap & (1 << 16)) { | ||
| 47 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", | ||
| 48 | where, cap); | ||
| 49 | // some BIOS versions seem buggy... | ||
| 50 | // return 1; | ||
| 51 | ehci_warn (ehci, "continuing after BIOS bug...\n"); | ||
| 52 | /* disable all SMIs, and clear "BIOS owns" flag */ | ||
| 53 | pci_write_config_dword(pdev, where + 4, 0); | ||
| 54 | pci_write_config_byte(pdev, where + 2, 0); | ||
| 55 | } else | ||
| 56 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
| 57 | } | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* called by khubd or root hub init threads */ | ||
| 62 | static int ehci_pci_reset (struct usb_hcd *hcd) | ||
| 63 | { | ||
| 64 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 65 | u32 temp; | ||
| 66 | unsigned count = 256/4; | ||
| 67 | |||
| 68 | spin_lock_init (&ehci->lock); | ||
| 69 | |||
| 70 | ehci->caps = hcd->regs; | ||
| 71 | ehci->regs = hcd->regs + HC_LENGTH (readl (&ehci->caps->hc_capbase)); | ||
| 72 | dbg_hcs_params (ehci, "reset"); | ||
| 73 | dbg_hcc_params (ehci, "reset"); | ||
| 74 | |||
| 75 | /* cache this readonly data; minimize chip reads */ | ||
| 76 | ehci->hcs_params = readl (&ehci->caps->hcs_params); | ||
| 77 | |||
| 78 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 79 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
| 80 | |||
| 81 | switch (pdev->vendor) { | ||
| 82 | case PCI_VENDOR_ID_TDI: | ||
| 83 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | ||
| 84 | ehci->is_tdi_rh_tt = 1; | ||
| 85 | tdi_reset (ehci); | ||
| 86 | } | ||
| 87 | break; | ||
| 88 | case PCI_VENDOR_ID_AMD: | ||
| 89 | /* AMD8111 EHCI doesn't work, according to AMD errata */ | ||
| 90 | if (pdev->device == 0x7463) { | ||
| 91 | ehci_info (ehci, "ignoring AMD8111 (errata)\n"); | ||
| 92 | return -EIO; | ||
| 93 | } | ||
| 94 | break; | ||
| 95 | case PCI_VENDOR_ID_NVIDIA: | ||
| 96 | /* NVidia reports that certain chips don't handle | ||
| 97 | * QH, ITD, or SITD addresses above 2GB. (But TD, | ||
| 98 | * data buffer, and periodic schedule are normal.) | ||
| 99 | */ | ||
| 100 | switch (pdev->device) { | ||
| 101 | case 0x003c: /* MCP04 */ | ||
| 102 | case 0x005b: /* CK804 */ | ||
| 103 | case 0x00d8: /* CK8 */ | ||
| 104 | case 0x00e8: /* CK8S */ | ||
| 105 | if (pci_set_consistent_dma_mask(pdev, | ||
| 106 | DMA_31BIT_MASK) < 0) | ||
| 107 | ehci_warn (ehci, "can't enable NVidia " | ||
| 108 | "workaround for >2GB RAM\n"); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | |||
| 114 | /* optional debug port, normally in the first BAR */ | ||
| 115 | temp = pci_find_capability (pdev, 0x0a); | ||
| 116 | if (temp) { | ||
| 117 | pci_read_config_dword(pdev, temp, &temp); | ||
| 118 | temp >>= 16; | ||
| 119 | if ((temp & (3 << 13)) == (1 << 13)) { | ||
| 120 | temp &= 0x1fff; | ||
| 121 | ehci->debug = hcd->regs + temp; | ||
| 122 | temp = readl (&ehci->debug->control); | ||
| 123 | ehci_info (ehci, "debug port %d%s\n", | ||
| 124 | HCS_DEBUG_PORT(ehci->hcs_params), | ||
| 125 | (temp & DBGP_ENABLED) | ||
| 126 | ? " IN USE" | ||
| 127 | : ""); | ||
| 128 | if (!(temp & DBGP_ENABLED)) | ||
| 129 | ehci->debug = NULL; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | ||
| 134 | } else | ||
| 135 | temp = 0; | ||
| 136 | |||
| 137 | /* EHCI 0.96 and later may have "extended capabilities" */ | ||
| 138 | while (temp && count--) { | ||
| 139 | u32 cap; | ||
| 140 | |||
| 141 | pci_read_config_dword (to_pci_dev(hcd->self.controller), | ||
| 142 | temp, &cap); | ||
| 143 | ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); | ||
| 144 | switch (cap & 0xff) { | ||
| 145 | case 1: /* BIOS/SMM/... handoff */ | ||
| 146 | if (bios_handoff (ehci, temp, cap) != 0) | ||
| 147 | return -EOPNOTSUPP; | ||
| 148 | break; | ||
| 149 | case 0: /* illegal reserved capability */ | ||
| 150 | ehci_warn (ehci, "illegal capability!\n"); | ||
| 151 | cap = 0; | ||
| 152 | /* FALLTHROUGH */ | ||
| 153 | default: /* unknown */ | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | temp = (cap >> 8) & 0xff; | ||
| 157 | } | ||
| 158 | if (!count) { | ||
| 159 | ehci_err (ehci, "bogus capabilities ... PCI problems!\n"); | ||
| 160 | return -EIO; | ||
| 161 | } | ||
| 162 | if (ehci_is_TDI(ehci)) | ||
| 163 | ehci_reset (ehci); | ||
| 164 | |||
| 165 | ehci_port_power (ehci, 0); | ||
| 166 | |||
| 167 | /* at least the Genesys GL880S needs fixup here */ | ||
| 168 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); | ||
| 169 | temp &= 0x0f; | ||
| 170 | if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { | ||
| 171 | ehci_dbg (ehci, "bogus port configuration: " | ||
| 172 | "cc=%d x pcc=%d < ports=%d\n", | ||
| 173 | HCS_N_CC(ehci->hcs_params), | ||
| 174 | HCS_N_PCC(ehci->hcs_params), | ||
| 175 | HCS_N_PORTS(ehci->hcs_params)); | ||
| 176 | |||
| 177 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 178 | struct pci_dev *pdev; | ||
| 179 | |||
| 180 | pdev = to_pci_dev(hcd->self.controller); | ||
| 181 | switch (pdev->vendor) { | ||
| 182 | case 0x17a0: /* GENESYS */ | ||
| 183 | /* GL880S: should be PORTS=2 */ | ||
| 184 | temp |= (ehci->hcs_params & ~0xf); | ||
| 185 | ehci->hcs_params = temp; | ||
| 186 | break; | ||
| 187 | case PCI_VENDOR_ID_NVIDIA: | ||
| 188 | /* NF4: should be PCC=10 */ | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | /* force HC to halt state */ | ||
| 195 | return ehci_halt (ehci); | ||
| 196 | } | ||
| 197 | |||
| 198 | static int ehci_pci_start (struct usb_hcd *hcd) | ||
| 199 | { | ||
| 200 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 201 | int result = 0; | ||
| 202 | |||
| 203 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 204 | struct pci_dev *pdev; | ||
| 205 | u16 port_wake; | ||
| 206 | |||
| 207 | pdev = to_pci_dev(hcd->self.controller); | ||
| 208 | |||
| 209 | /* Serial Bus Release Number is at PCI 0x60 offset */ | ||
| 210 | pci_read_config_byte(pdev, 0x60, &ehci->sbrn); | ||
| 211 | |||
| 212 | /* port wake capability, reported by boot firmware */ | ||
| 213 | pci_read_config_word(pdev, 0x62, &port_wake); | ||
| 214 | hcd->can_wakeup = (port_wake & 1) != 0; | ||
| 215 | |||
| 216 | /* help hc dma work well with cachelines */ | ||
| 217 | result = pci_set_mwi(pdev); | ||
| 218 | if (result) | ||
| 219 | ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); | ||
| 220 | } | ||
| 221 | |||
| 222 | return ehci_run (hcd); | ||
| 223 | } | ||
| 224 | |||
| 225 | /* always called by thread; normally rmmod */ | ||
| 226 | |||
| 227 | static void ehci_pci_stop (struct usb_hcd *hcd) | ||
| 228 | { | ||
| 229 | ehci_stop (hcd); | ||
| 230 | } | ||
| 231 | |||
| 232 | /*-------------------------------------------------------------------------*/ | ||
| 233 | |||
| 234 | #ifdef CONFIG_PM | ||
| 235 | |||
| 236 | /* suspend/resume, section 4.3 */ | ||
| 237 | |||
| 238 | /* These routines rely on the bus (pci, platform, etc) | ||
| 239 | * to handle powerdown and wakeup, and currently also on | ||
| 240 | * transceivers that don't need any software attention to set up | ||
| 241 | * the right sort of wakeup. | ||
| 242 | */ | ||
| 243 | |||
| 244 | static int ehci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | ||
| 245 | { | ||
| 246 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 247 | |||
| 248 | if (time_before (jiffies, ehci->next_statechange)) | ||
| 249 | msleep (100); | ||
| 250 | |||
| 251 | #ifdef CONFIG_USB_SUSPEND | ||
| 252 | (void) usb_suspend_device (hcd->self.root_hub); | ||
| 253 | #else | ||
| 254 | usb_lock_device (hcd->self.root_hub); | ||
| 255 | (void) ehci_bus_suspend (hcd); | ||
| 256 | usb_unlock_device (hcd->self.root_hub); | ||
| 257 | #endif | ||
| 258 | |||
| 259 | // save (PCI) FLADJ in case of Vaux power loss | ||
| 260 | // ... we'd only use it to handle clock skew | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int ehci_pci_resume (struct usb_hcd *hcd) | ||
| 266 | { | ||
| 267 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | ||
| 268 | unsigned port; | ||
| 269 | struct usb_device *root = hcd->self.root_hub; | ||
| 270 | int retval = -EINVAL; | ||
| 271 | |||
| 272 | // maybe restore (PCI) FLADJ | ||
| 273 | |||
| 274 | if (time_before (jiffies, ehci->next_statechange)) | ||
| 275 | msleep (100); | ||
| 276 | |||
| 277 | /* If any port is suspended (or owned by the companion), | ||
| 278 | * we know we can/must resume the HC (and mustn't reset it). | ||
| 279 | */ | ||
| 280 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { | ||
| 281 | u32 status; | ||
| 282 | port--; | ||
| 283 | status = readl (&ehci->regs->port_status [port]); | ||
| 284 | if (!(status & PORT_POWER)) | ||
| 285 | continue; | ||
| 286 | if (status & (PORT_SUSPEND | PORT_OWNER)) { | ||
| 287 | down (&hcd->self.root_hub->serialize); | ||
| 288 | retval = ehci_bus_resume (hcd); | ||
| 289 | up (&hcd->self.root_hub->serialize); | ||
| 290 | break; | ||
| 291 | } | ||
| 292 | if (!root->children [port]) | ||
| 293 | continue; | ||
| 294 | dbg_port (ehci, __FUNCTION__, port + 1, status); | ||
| 295 | usb_set_device_state (root->children[port], | ||
| 296 | USB_STATE_NOTATTACHED); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Else reset, to cope with power loss or flush-to-storage | ||
| 300 | * style "resume" having activated BIOS during reboot. | ||
| 301 | */ | ||
| 302 | if (port == 0) { | ||
| 303 | (void) ehci_halt (ehci); | ||
| 304 | (void) ehci_reset (ehci); | ||
| 305 | (void) ehci_pci_reset (hcd); | ||
| 306 | |||
| 307 | /* emptying the schedule aborts any urbs */ | ||
| 308 | spin_lock_irq (&ehci->lock); | ||
| 309 | if (ehci->reclaim) | ||
| 310 | ehci->reclaim_ready = 1; | ||
| 311 | ehci_work (ehci, NULL); | ||
| 312 | spin_unlock_irq (&ehci->lock); | ||
| 313 | |||
| 314 | /* restart; khubd will disconnect devices */ | ||
| 315 | retval = ehci_run (hcd); | ||
| 316 | |||
| 317 | /* here we "know" root ports should always stay powered; | ||
| 318 | * but some controllers may lose all power. | ||
| 319 | */ | ||
| 320 | ehci_port_power (ehci, 1); | ||
| 321 | } | ||
| 322 | |||
| 323 | return retval; | ||
| 324 | } | ||
| 325 | #endif | ||
| 326 | |||
| 327 | static const struct hc_driver ehci_pci_hc_driver = { | ||
| 328 | .description = hcd_name, | ||
| 329 | .product_desc = "EHCI Host Controller", | ||
| 330 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
| 331 | |||
| 332 | /* | ||
| 333 | * generic hardware linkage | ||
| 334 | */ | ||
| 335 | .irq = ehci_irq, | ||
| 336 | .flags = HCD_MEMORY | HCD_USB2, | ||
| 337 | |||
| 338 | /* | ||
| 339 | * basic lifecycle operations | ||
| 340 | */ | ||
| 341 | .reset = ehci_pci_reset, | ||
| 342 | .start = ehci_pci_start, | ||
| 343 | #ifdef CONFIG_PM | ||
| 344 | .suspend = ehci_pci_suspend, | ||
| 345 | .resume = ehci_pci_resume, | ||
| 346 | #endif | ||
| 347 | .stop = ehci_pci_stop, | ||
| 348 | |||
| 349 | /* | ||
| 350 | * managing i/o requests and associated device resources | ||
| 351 | */ | ||
| 352 | .urb_enqueue = ehci_urb_enqueue, | ||
| 353 | .urb_dequeue = ehci_urb_dequeue, | ||
| 354 | .endpoint_disable = ehci_endpoint_disable, | ||
| 355 | |||
| 356 | /* | ||
| 357 | * scheduling support | ||
| 358 | */ | ||
| 359 | .get_frame_number = ehci_get_frame, | ||
| 360 | |||
| 361 | /* | ||
| 362 | * root hub support | ||
| 363 | */ | ||
| 364 | .hub_status_data = ehci_hub_status_data, | ||
| 365 | .hub_control = ehci_hub_control, | ||
| 366 | .bus_suspend = ehci_bus_suspend, | ||
| 367 | .bus_resume = ehci_bus_resume, | ||
| 368 | }; | ||
| 369 | |||
| 370 | /*-------------------------------------------------------------------------*/ | ||
| 371 | |||
| 372 | /* PCI driver selection metadata; PCI hotplugging uses this */ | ||
| 373 | static const struct pci_device_id pci_ids [] = { { | ||
| 374 | /* handle any USB 2.0 EHCI controller */ | ||
| 375 | PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0), | ||
| 376 | .driver_data = (unsigned long) &ehci_pci_hc_driver, | ||
| 377 | }, | ||
| 378 | { /* end: all zeroes */ } | ||
| 379 | }; | ||
| 380 | MODULE_DEVICE_TABLE (pci, pci_ids); | ||
| 381 | |||
| 382 | /* pci driver glue; this is a "new style" PCI driver module */ | ||
| 383 | static struct pci_driver ehci_pci_driver = { | ||
| 384 | .name = (char *) hcd_name, | ||
| 385 | .id_table = pci_ids, | ||
| 386 | .owner = THIS_MODULE, | ||
| 387 | |||
| 388 | .probe = usb_hcd_pci_probe, | ||
| 389 | .remove = usb_hcd_pci_remove, | ||
| 390 | |||
| 391 | #ifdef CONFIG_PM | ||
| 392 | .suspend = usb_hcd_pci_suspend, | ||
| 393 | .resume = usb_hcd_pci_resume, | ||
| 394 | #endif | ||
| 395 | }; | ||
| 396 | |||
| 397 | static int __init ehci_hcd_pci_init (void) | ||
| 398 | { | ||
| 399 | if (usb_disabled()) | ||
| 400 | return -ENODEV; | ||
| 401 | |||
| 402 | pr_debug ("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", | ||
| 403 | hcd_name, | ||
| 404 | sizeof (struct ehci_qh), sizeof (struct ehci_qtd), | ||
| 405 | sizeof (struct ehci_itd), sizeof (struct ehci_sitd)); | ||
| 406 | |||
| 407 | return pci_register_driver (&ehci_pci_driver); | ||
| 408 | } | ||
| 409 | module_init (ehci_hcd_pci_init); | ||
| 410 | |||
| 411 | static void __exit ehci_hcd_pci_cleanup (void) | ||
| 412 | { | ||
| 413 | pci_unregister_driver (&ehci_pci_driver); | ||
| 414 | } | ||
| 415 | module_exit (ehci_hcd_pci_cleanup); | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index f34a0516d35f..18e257c2bdb5 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
| @@ -97,6 +97,7 @@ struct ehci_hcd { /* one per controller */ | |||
| 97 | #else | 97 | #else |
| 98 | # define COUNT(x) do {} while (0) | 98 | # define COUNT(x) do {} while (0) |
| 99 | #endif | 99 | #endif |
| 100 | u8 sbrn; /* packed release number */ | ||
| 100 | }; | 101 | }; |
| 101 | 102 | ||
| 102 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ | 103 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 642f35068ce2..ddb8fc591466 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
| @@ -638,7 +638,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 638 | + msecs_to_jiffies(20) + 1); | 638 | + msecs_to_jiffies(20) + 1); |
| 639 | if (intstat & HCINT_RD) { | 639 | if (intstat & HCINT_RD) { |
| 640 | DBG("---- remote wakeup\n"); | 640 | DBG("---- remote wakeup\n"); |
| 641 | schedule_work(&isp116x->rh_resume); | 641 | usb_hcd_resume_root_hub(hcd); |
| 642 | ret = IRQ_HANDLED; | 642 | ret = IRQ_HANDLED; |
| 643 | } | 643 | } |
| 644 | irqstat &= ~HCuPINT_OPR; | 644 | irqstat &= ~HCuPINT_OPR; |
| @@ -1160,7 +1160,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd, | |||
| 1160 | 1160 | ||
| 1161 | #ifdef CONFIG_PM | 1161 | #ifdef CONFIG_PM |
| 1162 | 1162 | ||
| 1163 | static int isp116x_hub_suspend(struct usb_hcd *hcd) | 1163 | static int isp116x_bus_suspend(struct usb_hcd *hcd) |
| 1164 | { | 1164 | { |
| 1165 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1165 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
| 1166 | unsigned long flags; | 1166 | unsigned long flags; |
| @@ -1200,7 +1200,7 @@ static int isp116x_hub_suspend(struct usb_hcd *hcd) | |||
| 1200 | return ret; | 1200 | return ret; |
| 1201 | } | 1201 | } |
| 1202 | 1202 | ||
| 1203 | static int isp116x_hub_resume(struct usb_hcd *hcd) | 1203 | static int isp116x_bus_resume(struct usb_hcd *hcd) |
| 1204 | { | 1204 | { |
| 1205 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1205 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
| 1206 | u32 val; | 1206 | u32 val; |
| @@ -1263,21 +1263,11 @@ static int isp116x_hub_resume(struct usb_hcd *hcd) | |||
| 1263 | return 0; | 1263 | return 0; |
| 1264 | } | 1264 | } |
| 1265 | 1265 | ||
| 1266 | static void isp116x_rh_resume(void *_hcd) | ||
| 1267 | { | ||
| 1268 | struct usb_hcd *hcd = _hcd; | ||
| 1269 | |||
| 1270 | usb_resume_device(hcd->self.root_hub); | ||
| 1271 | } | ||
| 1272 | 1266 | ||
| 1273 | #else | 1267 | #else |
| 1274 | 1268 | ||
| 1275 | #define isp116x_hub_suspend NULL | 1269 | #define isp116x_bus_suspend NULL |
| 1276 | #define isp116x_hub_resume NULL | 1270 | #define isp116x_bus_resume NULL |
| 1277 | |||
| 1278 | static void isp116x_rh_resume(void *_hcd) | ||
| 1279 | { | ||
| 1280 | } | ||
| 1281 | 1271 | ||
| 1282 | #endif | 1272 | #endif |
| 1283 | 1273 | ||
| @@ -1636,8 +1626,8 @@ static struct hc_driver isp116x_hc_driver = { | |||
| 1636 | 1626 | ||
| 1637 | .hub_status_data = isp116x_hub_status_data, | 1627 | .hub_status_data = isp116x_hub_status_data, |
| 1638 | .hub_control = isp116x_hub_control, | 1628 | .hub_control = isp116x_hub_control, |
| 1639 | .hub_suspend = isp116x_hub_suspend, | 1629 | .bus_suspend = isp116x_bus_suspend, |
| 1640 | .hub_resume = isp116x_hub_resume, | 1630 | .bus_resume = isp116x_bus_resume, |
| 1641 | }; | 1631 | }; |
| 1642 | 1632 | ||
| 1643 | /*----------------------------------------------------------------*/ | 1633 | /*----------------------------------------------------------------*/ |
| @@ -1732,7 +1722,6 @@ static int __init isp116x_probe(struct device *dev) | |||
| 1732 | isp116x->addr_reg = addr_reg; | 1722 | isp116x->addr_reg = addr_reg; |
| 1733 | spin_lock_init(&isp116x->lock); | 1723 | spin_lock_init(&isp116x->lock); |
| 1734 | INIT_LIST_HEAD(&isp116x->async); | 1724 | INIT_LIST_HEAD(&isp116x->async); |
| 1735 | INIT_WORK(&isp116x->rh_resume, isp116x_rh_resume, hcd); | ||
| 1736 | isp116x->board = dev->platform_data; | 1725 | isp116x->board = dev->platform_data; |
| 1737 | 1726 | ||
| 1738 | if (!isp116x->board) { | 1727 | if (!isp116x->board) { |
| @@ -1777,16 +1766,10 @@ static int __init isp116x_probe(struct device *dev) | |||
| 1777 | static int isp116x_suspend(struct device *dev, pm_message_t state) | 1766 | static int isp116x_suspend(struct device *dev, pm_message_t state) |
| 1778 | { | 1767 | { |
| 1779 | int ret = 0; | 1768 | int ret = 0; |
| 1780 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 1781 | 1769 | ||
| 1782 | VDBG("%s: state %x\n", __func__, state); | 1770 | VDBG("%s: state %x\n", __func__, state); |
| 1783 | 1771 | ||
| 1784 | ret = usb_suspend_device(hcd->self.root_hub, state); | 1772 | dev->power.power_state = state; |
| 1785 | if (!ret) { | ||
| 1786 | dev->power.power_state = state; | ||
| 1787 | INFO("%s suspended\n", hcd_name); | ||
| 1788 | } else | ||
| 1789 | ERR("%s suspend failed\n", hcd_name); | ||
| 1790 | 1773 | ||
| 1791 | return ret; | 1774 | return ret; |
| 1792 | } | 1775 | } |
| @@ -1797,15 +1780,11 @@ static int isp116x_suspend(struct device *dev, pm_message_t state) | |||
| 1797 | static int isp116x_resume(struct device *dev) | 1780 | static int isp116x_resume(struct device *dev) |
| 1798 | { | 1781 | { |
| 1799 | int ret = 0; | 1782 | int ret = 0; |
| 1800 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 1801 | 1783 | ||
| 1802 | VDBG("%s: state %x\n", __func__, dev->power.power_state); | 1784 | VDBG("%s: state %x\n", __func__, dev->power.power_state); |
| 1803 | 1785 | ||
| 1804 | ret = usb_resume_device(hcd->self.root_hub); | 1786 | dev->power.power_state = PMSG_ON; |
| 1805 | if (!ret) { | 1787 | |
| 1806 | dev->power.power_state = PMSG_ON; | ||
| 1807 | VDBG("%s resumed\n", (char *)hcd_name); | ||
| 1808 | } | ||
| 1809 | return ret; | 1788 | return ret; |
| 1810 | } | 1789 | } |
| 1811 | 1790 | ||
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index 58873470dcf5..c6fec96785fe 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h | |||
| @@ -253,7 +253,6 @@ static const int cc_to_error[16] = { | |||
| 253 | 253 | ||
| 254 | struct isp116x { | 254 | struct isp116x { |
| 255 | spinlock_t lock; | 255 | spinlock_t lock; |
| 256 | struct work_struct rh_resume; | ||
| 257 | 256 | ||
| 258 | void __iomem *addr_reg; | 257 | void __iomem *addr_reg; |
| 259 | void __iomem *data_reg; | 258 | void __iomem *data_reg; |
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 3981bf15c8c7..a277e258eb6c 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
| @@ -214,6 +214,11 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { | |||
| 214 | */ | 214 | */ |
| 215 | .hub_status_data = ohci_hub_status_data, | 215 | .hub_status_data = ohci_hub_status_data, |
| 216 | .hub_control = ohci_hub_control, | 216 | .hub_control = ohci_hub_control, |
| 217 | #ifdef CONFIG_PM | ||
| 218 | .bus_suspend = ohci_bus_suspend, | ||
| 219 | .bus_resume = ohci_bus_resume, | ||
| 220 | #endif | ||
| 221 | .start_port_reset = ohci_start_port_reset, | ||
| 217 | }; | 222 | }; |
| 218 | 223 | ||
| 219 | /*-------------------------------------------------------------------------*/ | 224 | /*-------------------------------------------------------------------------*/ |
| @@ -259,6 +264,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev) | |||
| 259 | 264 | ||
| 260 | static struct device_driver ohci_hcd_au1xxx_driver = { | 265 | static struct device_driver ohci_hcd_au1xxx_driver = { |
| 261 | .name = "au1xxx-ohci", | 266 | .name = "au1xxx-ohci", |
| 267 | .owner = THIS_MODULE, | ||
| 262 | .bus = &platform_bus_type, | 268 | .bus = &platform_bus_type, |
| 263 | .probe = ohci_hcd_au1xxx_drv_probe, | 269 | .probe = ohci_hcd_au1xxx_drv_probe, |
| 264 | .remove = ohci_hcd_au1xxx_drv_remove, | 270 | .remove = ohci_hcd_au1xxx_drv_remove, |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 7924c74f958e..7bfffcbbd226 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
| @@ -193,10 +193,6 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) | |||
| 193 | 193 | ||
| 194 | maybe_print_eds (controller, "donehead", | 194 | maybe_print_eds (controller, "donehead", |
| 195 | ohci_readl (controller, ®s->donehead), next, size); | 195 | ohci_readl (controller, ®s->donehead), next, size); |
| 196 | |||
| 197 | /* broken fminterval means traffic won't flow! */ | ||
| 198 | ohci_dbg (controller, "fminterval %08x\n", | ||
| 199 | ohci_readl (controller, ®s->fminterval)); | ||
| 200 | } | 196 | } |
| 201 | 197 | ||
| 202 | #define dbg_port_sw(hc,num,value,next,size) \ | 198 | #define dbg_port_sw(hc,num,value,next,size) \ |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index f8da8c7af7c6..5c0c6c8a7a82 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
| @@ -723,7 +723,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
| 723 | ohci_vdbg (ohci, "resume detect\n"); | 723 | ohci_vdbg (ohci, "resume detect\n"); |
| 724 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); | 724 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); |
| 725 | if (hcd->state != HC_STATE_QUIESCING) | 725 | if (hcd->state != HC_STATE_QUIESCING) |
| 726 | schedule_work(&ohci->rh_resume); | 726 | usb_hcd_resume_root_hub(hcd); |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | if (ints & OHCI_INTR_WDH) { | 729 | if (ints & OHCI_INTR_WDH) { |
| @@ -791,7 +791,7 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
| 791 | 791 | ||
| 792 | /* must not be called from interrupt context */ | 792 | /* must not be called from interrupt context */ |
| 793 | 793 | ||
| 794 | #if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) | 794 | #ifdef CONFIG_PM |
| 795 | 795 | ||
| 796 | static int ohci_restart (struct ohci_hcd *ohci) | 796 | static int ohci_restart (struct ohci_hcd *ohci) |
| 797 | { | 797 | { |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index ce7b28da7a15..e01e77bc324b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | /*-------------------------------------------------------------------------*/ | 37 | /*-------------------------------------------------------------------------*/ |
| 38 | 38 | ||
| 39 | #if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) | 39 | #ifdef CONFIG_PM |
| 40 | 40 | ||
| 41 | #define OHCI_SCHED_ENABLES \ | 41 | #define OHCI_SCHED_ENABLES \ |
| 42 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) | 42 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) |
| @@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *); | |||
| 45 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); | 45 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); |
| 46 | static int ohci_restart (struct ohci_hcd *ohci); | 46 | static int ohci_restart (struct ohci_hcd *ohci); |
| 47 | 47 | ||
| 48 | static int ohci_hub_suspend (struct usb_hcd *hcd) | 48 | static int ohci_bus_suspend (struct usb_hcd *hcd) |
| 49 | { | 49 | { |
| 50 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 50 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 51 | int status = 0; | 51 | int status = 0; |
| @@ -73,7 +73,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
| 73 | ohci_dbg (ohci, "suspend root hub\n"); | 73 | ohci_dbg (ohci, "suspend root hub\n"); |
| 74 | 74 | ||
| 75 | /* First stop any processing */ | 75 | /* First stop any processing */ |
| 76 | hcd->state = HC_STATE_QUIESCING; | ||
| 77 | if (ohci->hc_control & OHCI_SCHED_ENABLES) { | 76 | if (ohci->hc_control & OHCI_SCHED_ENABLES) { |
| 78 | int limit; | 77 | int limit; |
| 79 | 78 | ||
| @@ -108,7 +107,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
| 108 | else | 107 | else |
| 109 | ohci->hc_control &= ~OHCI_CTRL_RWE; | 108 | ohci->hc_control &= ~OHCI_CTRL_RWE; |
| 110 | 109 | ||
| 111 | /* Suspend hub */ | 110 | /* Suspend hub ... this is the "global (to this bus) suspend" mode, |
| 111 | * which doesn't imply ports will first be individually suspended. | ||
| 112 | */ | ||
| 112 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | 113 | ohci->hc_control &= ~OHCI_CTRL_HCFS; |
| 113 | ohci->hc_control |= OHCI_USB_SUSPEND; | 114 | ohci->hc_control |= OHCI_USB_SUSPEND; |
| 114 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 115 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
| @@ -118,8 +119,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd) | |||
| 118 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); | 119 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); |
| 119 | 120 | ||
| 120 | done: | 121 | done: |
| 122 | /* external suspend vs self autosuspend ... same effect */ | ||
| 121 | if (status == 0) | 123 | if (status == 0) |
| 122 | hcd->state = HC_STATE_SUSPENDED; | 124 | usb_hcd_suspend_root_hub(hcd); |
| 123 | spin_unlock_irqrestore (&ohci->lock, flags); | 125 | spin_unlock_irqrestore (&ohci->lock, flags); |
| 124 | return status; | 126 | return status; |
| 125 | } | 127 | } |
| @@ -133,7 +135,7 @@ static inline struct ed *find_head (struct ed *ed) | |||
| 133 | } | 135 | } |
| 134 | 136 | ||
| 135 | /* caller has locked the root hub */ | 137 | /* caller has locked the root hub */ |
| 136 | static int ohci_hub_resume (struct usb_hcd *hcd) | 138 | static int ohci_bus_resume (struct usb_hcd *hcd) |
| 137 | { | 139 | { |
| 138 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 140 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 139 | u32 temp, enables; | 141 | u32 temp, enables; |
| @@ -146,7 +148,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
| 146 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 148 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
| 147 | 149 | ||
| 148 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { | 150 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { |
| 149 | /* this can happen after suspend-to-disk */ | 151 | /* this can happen after resuming a swsusp snapshot */ |
| 150 | if (hcd->state == HC_STATE_RESUMING) { | 152 | if (hcd->state == HC_STATE_RESUMING) { |
| 151 | ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", | 153 | ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", |
| 152 | ohci->hc_control); | 154 | ohci->hc_control); |
| @@ -169,11 +171,12 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
| 169 | ohci_info (ohci, "wakeup\n"); | 171 | ohci_info (ohci, "wakeup\n"); |
| 170 | break; | 172 | break; |
| 171 | case OHCI_USB_OPER: | 173 | case OHCI_USB_OPER: |
| 172 | ohci_dbg (ohci, "already resumed\n"); | 174 | /* this can happen after resuming a swsusp snapshot */ |
| 173 | status = 0; | 175 | ohci_dbg (ohci, "snapshot resume? reinit\n"); |
| 176 | status = -EBUSY; | ||
| 174 | break; | 177 | break; |
| 175 | default: /* RESET, we lost power */ | 178 | default: /* RESET, we lost power */ |
| 176 | ohci_dbg (ohci, "root hub hardware reset\n"); | 179 | ohci_dbg (ohci, "lost power\n"); |
| 177 | status = -EBUSY; | 180 | status = -EBUSY; |
| 178 | } | 181 | } |
| 179 | spin_unlock_irq (&ohci->lock); | 182 | spin_unlock_irq (&ohci->lock); |
| @@ -198,8 +201,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | /* Some controllers (lucent erratum) need extra-long delays */ | 203 | /* Some controllers (lucent erratum) need extra-long delays */ |
| 201 | hcd->state = HC_STATE_RESUMING; | 204 | msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); |
| 202 | mdelay (20 /* usb 11.5.1.10 */ + 15); | ||
| 203 | 205 | ||
| 204 | temp = ohci_readl (ohci, &ohci->regs->control); | 206 | temp = ohci_readl (ohci, &ohci->regs->control); |
| 205 | temp &= OHCI_CTRL_HCFS; | 207 | temp &= OHCI_CTRL_HCFS; |
| @@ -273,28 +275,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
| 273 | (void) ohci_readl (ohci, &ohci->regs->control); | 275 | (void) ohci_readl (ohci, &ohci->regs->control); |
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | hcd->state = HC_STATE_RUNNING; | ||
| 277 | return 0; | 278 | return 0; |
| 278 | } | 279 | } |
| 279 | 280 | ||
| 280 | static void ohci_rh_resume (void *_hcd) | 281 | #endif /* CONFIG_PM */ |
| 281 | { | ||
| 282 | struct usb_hcd *hcd = _hcd; | ||
| 283 | |||
| 284 | usb_lock_device (hcd->self.root_hub); | ||
| 285 | (void) ohci_hub_resume (hcd); | ||
| 286 | usb_unlock_device (hcd->self.root_hub); | ||
| 287 | } | ||
| 288 | |||
| 289 | #else | ||
| 290 | |||
| 291 | static void ohci_rh_resume (void *_hcd) | ||
| 292 | { | ||
| 293 | struct ohci_hcd *ohci = hcd_to_ohci (_hcd); | ||
| 294 | ohci_dbg(ohci, "rh_resume ??\n"); | ||
| 295 | } | ||
| 296 | |||
| 297 | #endif /* CONFIG_USB_SUSPEND || CONFIG_PM */ | ||
| 298 | 282 | ||
| 299 | /*-------------------------------------------------------------------------*/ | 283 | /*-------------------------------------------------------------------------*/ |
| 300 | 284 | ||
| @@ -367,7 +351,6 @@ done: | |||
| 367 | #ifdef CONFIG_PM | 351 | #ifdef CONFIG_PM |
| 368 | /* save power by suspending idle root hubs; | 352 | /* save power by suspending idle root hubs; |
| 369 | * INTR_RD wakes us when there's work | 353 | * INTR_RD wakes us when there's work |
| 370 | * NOTE: if we can do this, we don't need a root hub timer! | ||
| 371 | */ | 354 | */ |
| 372 | if (can_suspend | 355 | if (can_suspend |
| 373 | && !changed | 356 | && !changed |
| @@ -379,8 +362,7 @@ done: | |||
| 379 | && usb_trylock_device (hcd->self.root_hub) | 362 | && usb_trylock_device (hcd->self.root_hub) |
| 380 | ) { | 363 | ) { |
| 381 | ohci_vdbg (ohci, "autosuspend\n"); | 364 | ohci_vdbg (ohci, "autosuspend\n"); |
| 382 | (void) ohci_hub_suspend (hcd); | 365 | (void) ohci_bus_suspend (hcd); |
| 383 | hcd->state = HC_STATE_RUNNING; | ||
| 384 | usb_unlock_device (hcd->self.root_hub); | 366 | usb_unlock_device (hcd->self.root_hub); |
| 385 | } | 367 | } |
| 386 | #endif | 368 | #endif |
| @@ -554,7 +536,7 @@ static int ohci_hub_control ( | |||
| 554 | temp = RH_PS_POCI; | 536 | temp = RH_PS_POCI; |
| 555 | if ((ohci->hc_control & OHCI_CTRL_HCFS) | 537 | if ((ohci->hc_control & OHCI_CTRL_HCFS) |
| 556 | != OHCI_USB_OPER) | 538 | != OHCI_USB_OPER) |
| 557 | schedule_work (&ohci->rh_resume); | 539 | usb_hcd_resume_root_hub(hcd); |
| 558 | break; | 540 | break; |
| 559 | case USB_PORT_FEAT_C_SUSPEND: | 541 | case USB_PORT_FEAT_C_SUSPEND: |
| 560 | temp = RH_PS_PSSC; | 542 | temp = RH_PS_PSSC; |
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 859aca7be753..238fa4ade615 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c | |||
| @@ -193,6 +193,11 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { | |||
| 193 | */ | 193 | */ |
| 194 | .hub_status_data = ohci_hub_status_data, | 194 | .hub_status_data = ohci_hub_status_data, |
| 195 | .hub_control = ohci_hub_control, | 195 | .hub_control = ohci_hub_control, |
| 196 | #ifdef CONFIG_PM | ||
| 197 | .bus_suspend = ohci_bus_suspend, | ||
| 198 | .bus_resume = ohci_bus_resume, | ||
| 199 | #endif | ||
| 200 | .start_port_reset = ohci_start_port_reset, | ||
| 196 | }; | 201 | }; |
| 197 | 202 | ||
| 198 | /*-------------------------------------------------------------------------*/ | 203 | /*-------------------------------------------------------------------------*/ |
| @@ -239,6 +244,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct device *dev) | |||
| 239 | 244 | ||
| 240 | static struct device_driver ohci_hcd_lh7a404_driver = { | 245 | static struct device_driver ohci_hcd_lh7a404_driver = { |
| 241 | .name = "lh7a404-ohci", | 246 | .name = "lh7a404-ohci", |
| 247 | .owner = THIS_MODULE, | ||
| 242 | .bus = &platform_bus_type, | 248 | .bus = &platform_bus_type, |
| 243 | .probe = ohci_hcd_lh7a404_drv_probe, | 249 | .probe = ohci_hcd_lh7a404_drv_probe, |
| 244 | .remove = ohci_hcd_lh7a404_drv_remove, | 250 | .remove = ohci_hcd_lh7a404_drv_remove, |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index 9fb83dfb1eb4..bfbe328a4788 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
| @@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
| 28 | ohci->next_statechange = jiffies; | 28 | ohci->next_statechange = jiffies; |
| 29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
| 30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
| 31 | INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci)); | ||
| 32 | ohci->reboot_notifier.notifier_call = ohci_reboot; | 31 | ohci->reboot_notifier.notifier_call = ohci_reboot; |
| 33 | } | 32 | } |
| 34 | 33 | ||
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index a574216625a0..45efeed1fcc3 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
| @@ -420,9 +420,9 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
| 420 | */ | 420 | */ |
| 421 | .hub_status_data = ohci_hub_status_data, | 421 | .hub_status_data = ohci_hub_status_data, |
| 422 | .hub_control = ohci_hub_control, | 422 | .hub_control = ohci_hub_control, |
| 423 | #ifdef CONFIG_USB_SUSPEND | 423 | #ifdef CONFIG_PM |
| 424 | .hub_suspend = ohci_hub_suspend, | 424 | .bus_suspend = ohci_bus_suspend, |
| 425 | .hub_resume = ohci_hub_resume, | 425 | .bus_resume = ohci_bus_resume, |
| 426 | #endif | 426 | #endif |
| 427 | .start_port_reset = ohci_start_port_reset, | 427 | .start_port_reset = ohci_start_port_reset, |
| 428 | }; | 428 | }; |
| @@ -458,41 +458,29 @@ static int ohci_hcd_omap_drv_remove(struct device *dev) | |||
| 458 | static int ohci_omap_suspend(struct device *dev, pm_message_t message) | 458 | static int ohci_omap_suspend(struct device *dev, pm_message_t message) |
| 459 | { | 459 | { |
| 460 | struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); | 460 | struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); |
| 461 | int status = -EINVAL; | 461 | |
| 462 | 462 | if (time_before(jiffies, ohci->next_statechange)) | |
| 463 | down(&ohci_to_hcd(ohci)->self.root_hub->serialize); | 463 | msleep(5); |
| 464 | status = ohci_hub_suspend(ohci_to_hcd(ohci)); | 464 | ohci->next_statechange = jiffies; |
| 465 | if (status == 0) { | 465 | |
| 466 | omap_ohci_clock_power(0); | 466 | omap_ohci_clock_power(0); |
| 467 | ohci_to_hcd(ohci)->self.root_hub->state = | 467 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; |
| 468 | USB_STATE_SUSPENDED; | 468 | dev->power.power_state = PMSG_SUSPEND; |
| 469 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; | 469 | return 0; |
| 470 | dev->power.power_state = PMSG_SUSPEND; | ||
| 471 | } | ||
| 472 | up(&ohci_to_hcd(ohci)->self.root_hub->serialize); | ||
| 473 | return status; | ||
| 474 | } | 470 | } |
| 475 | 471 | ||
| 476 | static int ohci_omap_resume(struct device *dev) | 472 | static int ohci_omap_resume(struct device *dev) |
| 477 | { | 473 | { |
| 478 | struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); | 474 | struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev)); |
| 479 | int status = 0; | ||
| 480 | 475 | ||
| 481 | if (time_before(jiffies, ohci->next_statechange)) | 476 | if (time_before(jiffies, ohci->next_statechange)) |
| 482 | msleep(5); | 477 | msleep(5); |
| 483 | ohci->next_statechange = jiffies; | 478 | ohci->next_statechange = jiffies; |
| 479 | |||
| 484 | omap_ohci_clock_power(1); | 480 | omap_ohci_clock_power(1); |
| 485 | #ifdef CONFIG_USB_SUSPEND | 481 | dev->power.power_state = PMSG_ON; |
| 486 | /* get extra cleanup even if remote wakeup isn't in use */ | 482 | usb_hcd_resume_root_hub(dev_get_drvdata(dev)); |
| 487 | status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub); | 483 | return 0; |
| 488 | #else | ||
| 489 | down(&ohci_to_hcd(ohci)->self.root_hub->serialize); | ||
| 490 | status = ohci_hub_resume(ohci_to_hcd(ohci)); | ||
| 491 | up(&ohci_to_hcd(ohci)->self.root_hub->serialize); | ||
| 492 | #endif | ||
| 493 | if (status == 0) | ||
| 494 | dev->power.power_state = PMSG_ON; | ||
| 495 | return status; | ||
| 496 | } | 484 | } |
| 497 | 485 | ||
| 498 | #endif | 486 | #endif |
| @@ -504,6 +492,7 @@ static int ohci_omap_resume(struct device *dev) | |||
| 504 | */ | 492 | */ |
| 505 | static struct device_driver ohci_hcd_omap_driver = { | 493 | static struct device_driver ohci_hcd_omap_driver = { |
| 506 | .name = "ohci", | 494 | .name = "ohci", |
| 495 | .owner = THIS_MODULE, | ||
| 507 | .bus = &platform_bus_type, | 496 | .bus = &platform_bus_type, |
| 508 | .probe = ohci_hcd_omap_drv_probe, | 497 | .probe = ohci_hcd_omap_drv_probe, |
| 509 | .remove = ohci_hcd_omap_drv_remove, | 498 | .remove = ohci_hcd_omap_drv_remove, |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index eede6be098d2..bf1d5ab4aa3a 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
| @@ -112,23 +112,13 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
| 112 | 112 | ||
| 113 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | 113 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) |
| 114 | { | 114 | { |
| 115 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 115 | /* root hub was already suspended */ |
| 116 | |||
| 117 | /* suspend root hub, hoping it keeps power during suspend */ | ||
| 118 | if (time_before (jiffies, ohci->next_statechange)) | ||
| 119 | msleep (100); | ||
| 120 | |||
| 121 | #ifdef CONFIG_USB_SUSPEND | ||
| 122 | (void) usb_suspend_device (hcd->self.root_hub, message); | ||
| 123 | #else | ||
| 124 | usb_lock_device (hcd->self.root_hub); | ||
| 125 | (void) ohci_hub_suspend (hcd); | ||
| 126 | usb_unlock_device (hcd->self.root_hub); | ||
| 127 | #endif | ||
| 128 | 116 | ||
| 129 | /* let things settle down a bit */ | 117 | /* FIXME these PMAC things get called in the wrong places. ASIC |
| 130 | msleep (100); | 118 | * clocks should be turned off AFTER entering D3, and on BEFORE |
| 131 | 119 | * trying to enter D0. Evidently the PCI layer doesn't currently | |
| 120 | * provide the right sort of platform hooks for this ... | ||
| 121 | */ | ||
| 132 | #ifdef CONFIG_PPC_PMAC | 122 | #ifdef CONFIG_PPC_PMAC |
| 133 | if (_machine == _MACH_Pmac) { | 123 | if (_machine == _MACH_Pmac) { |
| 134 | struct device_node *of_node; | 124 | struct device_node *of_node; |
| @@ -145,9 +135,6 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
| 145 | 135 | ||
| 146 | static int ohci_pci_resume (struct usb_hcd *hcd) | 136 | static int ohci_pci_resume (struct usb_hcd *hcd) |
| 147 | { | 137 | { |
| 148 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
| 149 | int retval = 0; | ||
| 150 | |||
| 151 | #ifdef CONFIG_PPC_PMAC | 138 | #ifdef CONFIG_PPC_PMAC |
| 152 | if (_machine == _MACH_Pmac) { | 139 | if (_machine == _MACH_Pmac) { |
| 153 | struct device_node *of_node; | 140 | struct device_node *of_node; |
| @@ -159,19 +146,8 @@ static int ohci_pci_resume (struct usb_hcd *hcd) | |||
| 159 | } | 146 | } |
| 160 | #endif /* CONFIG_PPC_PMAC */ | 147 | #endif /* CONFIG_PPC_PMAC */ |
| 161 | 148 | ||
| 162 | /* resume root hub */ | 149 | usb_hcd_resume_root_hub(hcd); |
| 163 | if (time_before (jiffies, ohci->next_statechange)) | 150 | return 0; |
| 164 | msleep (100); | ||
| 165 | #ifdef CONFIG_USB_SUSPEND | ||
| 166 | /* get extra cleanup even if remote wakeup isn't in use */ | ||
| 167 | retval = usb_resume_device (hcd->self.root_hub); | ||
| 168 | #else | ||
| 169 | usb_lock_device (hcd->self.root_hub); | ||
| 170 | retval = ohci_hub_resume (hcd); | ||
| 171 | usb_unlock_device (hcd->self.root_hub); | ||
| 172 | #endif | ||
| 173 | |||
| 174 | return retval; | ||
| 175 | } | 151 | } |
| 176 | 152 | ||
| 177 | #endif /* CONFIG_PM */ | 153 | #endif /* CONFIG_PM */ |
| @@ -218,9 +194,9 @@ static const struct hc_driver ohci_pci_hc_driver = { | |||
| 218 | */ | 194 | */ |
| 219 | .hub_status_data = ohci_hub_status_data, | 195 | .hub_status_data = ohci_hub_status_data, |
| 220 | .hub_control = ohci_hub_control, | 196 | .hub_control = ohci_hub_control, |
| 221 | #ifdef CONFIG_USB_SUSPEND | 197 | #ifdef CONFIG_PM |
| 222 | .hub_suspend = ohci_hub_suspend, | 198 | .bus_suspend = ohci_bus_suspend, |
| 223 | .hub_resume = ohci_hub_resume, | 199 | .bus_resume = ohci_bus_resume, |
| 224 | #endif | 200 | #endif |
| 225 | .start_port_reset = ohci_start_port_reset, | 201 | .start_port_reset = ohci_start_port_reset, |
| 226 | }; | 202 | }; |
| @@ -240,6 +216,7 @@ MODULE_DEVICE_TABLE (pci, pci_ids); | |||
| 240 | static struct pci_driver ohci_pci_driver = { | 216 | static struct pci_driver ohci_pci_driver = { |
| 241 | .name = (char *) hcd_name, | 217 | .name = (char *) hcd_name, |
| 242 | .id_table = pci_ids, | 218 | .id_table = pci_ids, |
| 219 | .owner = THIS_MODULE, | ||
| 243 | 220 | ||
| 244 | .probe = usb_hcd_pci_probe, | 221 | .probe = usb_hcd_pci_probe, |
| 245 | .remove = usb_hcd_pci_remove, | 222 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 251533363028..4832e57ae579 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
| @@ -163,9 +163,9 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { | |||
| 163 | */ | 163 | */ |
| 164 | .hub_status_data = ohci_hub_status_data, | 164 | .hub_status_data = ohci_hub_status_data, |
| 165 | .hub_control = ohci_hub_control, | 165 | .hub_control = ohci_hub_control, |
| 166 | #ifdef CONFIG_USB_SUSPEND | 166 | #ifdef CONFIG_PM |
| 167 | .hub_suspend = ohci_hub_suspend, | 167 | .bus_suspend = ohci_bus_suspend, |
| 168 | .hub_resume = ohci_hub_resume, | 168 | .bus_resume = ohci_bus_resume, |
| 169 | #endif | 169 | #endif |
| 170 | .start_port_reset = ohci_start_port_reset, | 170 | .start_port_reset = ohci_start_port_reset, |
| 171 | }; | 171 | }; |
| @@ -193,10 +193,11 @@ static int ohci_hcd_ppc_soc_drv_remove(struct device *dev) | |||
| 193 | 193 | ||
| 194 | static struct device_driver ohci_hcd_ppc_soc_driver = { | 194 | static struct device_driver ohci_hcd_ppc_soc_driver = { |
| 195 | .name = "ppc-soc-ohci", | 195 | .name = "ppc-soc-ohci", |
| 196 | .owner = THIS_MODULE, | ||
| 196 | .bus = &platform_bus_type, | 197 | .bus = &platform_bus_type, |
| 197 | .probe = ohci_hcd_ppc_soc_drv_probe, | 198 | .probe = ohci_hcd_ppc_soc_drv_probe, |
| 198 | .remove = ohci_hcd_ppc_soc_drv_remove, | 199 | .remove = ohci_hcd_ppc_soc_drv_remove, |
| 199 | #if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) | 200 | #ifdef CONFIG_PM |
| 200 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ | 201 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ |
| 201 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ | 202 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ |
| 202 | #endif | 203 | #endif |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index f042261ecb8e..d287dcccd415 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
| @@ -278,10 +278,11 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { | |||
| 278 | */ | 278 | */ |
| 279 | .hub_status_data = ohci_hub_status_data, | 279 | .hub_status_data = ohci_hub_status_data, |
| 280 | .hub_control = ohci_hub_control, | 280 | .hub_control = ohci_hub_control, |
| 281 | #ifdef CONFIG_USB_SUSPEND | 281 | #ifdef CONFIG_PM |
| 282 | .hub_suspend = ohci_hub_suspend, | 282 | .bus_suspend = ohci_bus_suspend, |
| 283 | .hub_resume = ohci_hub_resume, | 283 | .bus_resume = ohci_bus_resume, |
| 284 | #endif | 284 | #endif |
| 285 | .start_port_reset = ohci_start_port_reset, | ||
| 285 | }; | 286 | }; |
| 286 | 287 | ||
| 287 | /*-------------------------------------------------------------------------*/ | 288 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index da7d5478f74d..fab420a2ce71 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
| @@ -448,11 +448,11 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { | |||
| 448 | */ | 448 | */ |
| 449 | .hub_status_data = ohci_s3c2410_hub_status_data, | 449 | .hub_status_data = ohci_s3c2410_hub_status_data, |
| 450 | .hub_control = ohci_s3c2410_hub_control, | 450 | .hub_control = ohci_s3c2410_hub_control, |
| 451 | 451 | #ifdef CONFIG_PM | |
| 452 | #if defined(CONFIG_USB_SUSPEND) && 0 | 452 | .bus_suspend = ohci_bus_suspend, |
| 453 | .hub_suspend = ohci_hub_suspend, | 453 | .bus_resume = ohci_bus_resume, |
| 454 | .hub_resume = ohci_hub_resume, | ||
| 455 | #endif | 454 | #endif |
| 455 | .start_port_reset = ohci_start_port_reset, | ||
| 456 | }; | 456 | }; |
| 457 | 457 | ||
| 458 | /* device driver */ | 458 | /* device driver */ |
| @@ -474,6 +474,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct device *dev) | |||
| 474 | 474 | ||
| 475 | static struct device_driver ohci_hcd_s3c2410_driver = { | 475 | static struct device_driver ohci_hcd_s3c2410_driver = { |
| 476 | .name = "s3c2410-ohci", | 476 | .name = "s3c2410-ohci", |
| 477 | .owner = THIS_MODULE, | ||
| 477 | .bus = &platform_bus_type, | 478 | .bus = &platform_bus_type, |
| 478 | .probe = ohci_hcd_s3c2410_drv_probe, | 479 | .probe = ohci_hcd_s3c2410_drv_probe, |
| 479 | .remove = ohci_hcd_s3c2410_drv_remove, | 480 | .remove = ohci_hcd_s3c2410_drv_remove, |
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 814d2be4ee7b..fb3221ebbb29 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c | |||
| @@ -235,10 +235,11 @@ static const struct hc_driver ohci_sa1111_hc_driver = { | |||
| 235 | */ | 235 | */ |
| 236 | .hub_status_data = ohci_hub_status_data, | 236 | .hub_status_data = ohci_hub_status_data, |
| 237 | .hub_control = ohci_hub_control, | 237 | .hub_control = ohci_hub_control, |
| 238 | #ifdef CONFIG_USB_SUSPEND | 238 | #ifdef CONFIG_PM |
| 239 | .hub_suspend = ohci_hub_suspend, | 239 | .bus_suspend = ohci_bus_suspend, |
| 240 | .hub_resume = ohci_hub_resume, | 240 | .bus_resume = ohci_bus_resume, |
| 241 | #endif | 241 | #endif |
| 242 | .start_port_reset = ohci_start_port_reset, | ||
| 242 | }; | 243 | }; |
| 243 | 244 | ||
| 244 | /*-------------------------------------------------------------------------*/ | 245 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 8a9b9d9209e9..caacf14371f5 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
| @@ -389,7 +389,6 @@ struct ohci_hcd { | |||
| 389 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |
| 390 | u32 fminterval; /* saved register */ | 390 | u32 fminterval; /* saved register */ |
| 391 | 391 | ||
| 392 | struct work_struct rh_resume; | ||
| 393 | struct notifier_block reboot_notifier; | 392 | struct notifier_block reboot_notifier; |
| 394 | 393 | ||
| 395 | unsigned long flags; /* for HC bugs */ | 394 | unsigned long flags; /* for HC bugs */ |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c new file mode 100644 index 000000000000..b7fd3f644e1e --- /dev/null +++ b/drivers/usb/host/pci-quirks.c | |||
| @@ -0,0 +1,296 @@ | |||
| 1 | /* | ||
| 2 | * This file contains code to reset and initialize USB host controllers. | ||
| 3 | * Some of it includes work-arounds for PCI hardware and BIOS quirks. | ||
| 4 | * It may need to run early during booting -- before USB would normally | ||
| 5 | * initialize -- to ensure that Linux doesn't use any legacy modes. | ||
| 6 | * | ||
| 7 | * Copyright (c) 1999 Martin Mares <mj@ucw.cz> | ||
| 8 | * (and others) | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/config.h> | ||
| 12 | #ifdef CONFIG_USB_DEBUG | ||
| 13 | #define DEBUG | ||
| 14 | #else | ||
| 15 | #undef DEBUG | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #include <linux/types.h> | ||
| 19 | #include <linux/kernel.h> | ||
| 20 | #include <linux/pci.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/acpi.h> | ||
| 24 | |||
| 25 | |||
| 26 | #define UHCI_USBLEGSUP 0xc0 /* legacy support */ | ||
| 27 | #define UHCI_USBCMD 0 /* command register */ | ||
| 28 | #define UHCI_USBINTR 4 /* interrupt register */ | ||
| 29 | #define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ | ||
| 30 | #define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ | ||
| 31 | #define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ | ||
| 32 | #define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ | ||
| 33 | #define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ | ||
| 34 | #define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */ | ||
| 35 | #define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */ | ||
| 36 | |||
| 37 | #define OHCI_CONTROL 0x04 | ||
| 38 | #define OHCI_CMDSTATUS 0x08 | ||
| 39 | #define OHCI_INTRSTATUS 0x0c | ||
| 40 | #define OHCI_INTRENABLE 0x10 | ||
| 41 | #define OHCI_INTRDISABLE 0x14 | ||
| 42 | #define OHCI_OCR (1 << 3) /* ownership change request */ | ||
| 43 | #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ | ||
| 44 | #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ | ||
| 45 | #define OHCI_INTR_OC (1 << 30) /* ownership change */ | ||
| 46 | |||
| 47 | #define EHCI_HCC_PARAMS 0x08 /* extended capabilities */ | ||
| 48 | #define EHCI_USBCMD 0 /* command register */ | ||
| 49 | #define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ | ||
| 50 | #define EHCI_USBSTS 4 /* status register */ | ||
| 51 | #define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ | ||
| 52 | #define EHCI_USBINTR 8 /* interrupt register */ | ||
| 53 | #define EHCI_USBLEGSUP 0 /* legacy support register */ | ||
| 54 | #define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ | ||
| 55 | #define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ | ||
| 56 | #define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ | ||
| 57 | #define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ | ||
| 58 | |||
| 59 | |||
| 60 | /* | ||
| 61 | * Make sure the controller is completely inactive, unable to | ||
| 62 | * generate interrupts or do DMA. | ||
| 63 | */ | ||
| 64 | void uhci_reset_hc(struct pci_dev *pdev, unsigned long base) | ||
| 65 | { | ||
| 66 | /* Turn off PIRQ enable and SMI enable. (This also turns off the | ||
| 67 | * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. | ||
| 68 | */ | ||
| 69 | pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC); | ||
| 70 | |||
| 71 | /* Reset the HC - this will force us to get a | ||
| 72 | * new notification of any already connected | ||
| 73 | * ports due to the virtual disconnect that it | ||
| 74 | * implies. | ||
| 75 | */ | ||
| 76 | outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD); | ||
| 77 | mb(); | ||
| 78 | udelay(5); | ||
| 79 | if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET) | ||
| 80 | dev_warn(&pdev->dev, "HCRESET not completed yet!\n"); | ||
| 81 | |||
| 82 | /* Just to be safe, disable interrupt requests and | ||
| 83 | * make sure the controller is stopped. | ||
| 84 | */ | ||
| 85 | outw(0, base + UHCI_USBINTR); | ||
| 86 | outw(0, base + UHCI_USBCMD); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(uhci_reset_hc); | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Initialize a controller that was newly discovered or has just been | ||
| 92 | * resumed. In either case we can't be sure of its previous state. | ||
| 93 | * | ||
| 94 | * Returns: 1 if the controller was reset, 0 otherwise. | ||
| 95 | */ | ||
| 96 | int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) | ||
| 97 | { | ||
| 98 | u16 legsup; | ||
| 99 | unsigned int cmd, intr; | ||
| 100 | |||
| 101 | /* | ||
| 102 | * When restarting a suspended controller, we expect all the | ||
| 103 | * settings to be the same as we left them: | ||
| 104 | * | ||
| 105 | * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; | ||
| 106 | * Controller is stopped and configured with EGSM set; | ||
| 107 | * No interrupts enabled except possibly Resume Detect. | ||
| 108 | * | ||
| 109 | * If any of these conditions are violated we do a complete reset. | ||
| 110 | */ | ||
| 111 | pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup); | ||
| 112 | if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { | ||
| 113 | dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n", | ||
| 114 | __FUNCTION__, legsup); | ||
| 115 | goto reset_needed; | ||
| 116 | } | ||
| 117 | |||
| 118 | cmd = inw(base + UHCI_USBCMD); | ||
| 119 | if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || | ||
| 120 | !(cmd & UHCI_USBCMD_EGSM)) { | ||
| 121 | dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n", | ||
| 122 | __FUNCTION__, cmd); | ||
| 123 | goto reset_needed; | ||
| 124 | } | ||
| 125 | |||
| 126 | intr = inw(base + UHCI_USBINTR); | ||
| 127 | if (intr & (~UHCI_USBINTR_RESUME)) { | ||
| 128 | dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n", | ||
| 129 | __FUNCTION__, intr); | ||
| 130 | goto reset_needed; | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | |||
| 134 | reset_needed: | ||
| 135 | dev_dbg(&pdev->dev, "Performing full reset\n"); | ||
| 136 | uhci_reset_hc(pdev, base); | ||
| 137 | return 1; | ||
| 138 | } | ||
| 139 | EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); | ||
| 140 | |||
| 141 | static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) | ||
| 142 | { | ||
| 143 | unsigned long base = 0; | ||
| 144 | int i; | ||
| 145 | |||
| 146 | for (i = 0; i < PCI_ROM_RESOURCE; i++) | ||
| 147 | if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { | ||
| 148 | base = pci_resource_start(pdev, i); | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (base) | ||
| 153 | uhci_check_and_reset_hc(pdev, base); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | ||
| 157 | { | ||
| 158 | void __iomem *base; | ||
| 159 | int wait_time; | ||
| 160 | u32 control; | ||
| 161 | |||
| 162 | base = ioremap_nocache(pci_resource_start(pdev, 0), | ||
| 163 | pci_resource_len(pdev, 0)); | ||
| 164 | if (base == NULL) return; | ||
| 165 | |||
| 166 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ | ||
| 167 | #ifndef __hppa__ | ||
| 168 | control = readl(base + OHCI_CONTROL); | ||
| 169 | if (control & OHCI_CTRL_IR) { | ||
| 170 | wait_time = 500; /* arbitrary; 5 seconds */ | ||
| 171 | writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); | ||
| 172 | writel(OHCI_OCR, base + OHCI_CMDSTATUS); | ||
| 173 | while (wait_time > 0 && | ||
| 174 | readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { | ||
| 175 | wait_time -= 10; | ||
| 176 | msleep(10); | ||
| 177 | } | ||
| 178 | if (wait_time <= 0) | ||
| 179 | printk(KERN_WARNING "%s %s: early BIOS handoff " | ||
| 180 | "failed (BIOS bug ?)\n", | ||
| 181 | pdev->dev.bus_id, "OHCI"); | ||
| 182 | |||
| 183 | /* reset controller, preserving RWC */ | ||
| 184 | writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); | ||
| 185 | } | ||
| 186 | #endif | ||
| 187 | |||
| 188 | /* | ||
| 189 | * disable interrupts | ||
| 190 | */ | ||
| 191 | writel(~(u32)0, base + OHCI_INTRDISABLE); | ||
| 192 | writel(~(u32)0, base + OHCI_INTRSTATUS); | ||
| 193 | |||
| 194 | iounmap(base); | ||
| 195 | } | ||
| 196 | |||
| 197 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | ||
| 198 | { | ||
| 199 | int wait_time, delta; | ||
| 200 | void __iomem *base, *op_reg_base; | ||
| 201 | u32 hcc_params, val, temp; | ||
| 202 | u8 cap_length; | ||
| 203 | |||
| 204 | base = ioremap_nocache(pci_resource_start(pdev, 0), | ||
| 205 | pci_resource_len(pdev, 0)); | ||
| 206 | if (base == NULL) return; | ||
| 207 | |||
| 208 | cap_length = readb(base); | ||
| 209 | op_reg_base = base + cap_length; | ||
| 210 | hcc_params = readl(base + EHCI_HCC_PARAMS); | ||
| 211 | hcc_params = (hcc_params >> 8) & 0xff; | ||
| 212 | if (hcc_params) { | ||
| 213 | pci_read_config_dword(pdev, | ||
| 214 | hcc_params + EHCI_USBLEGSUP, | ||
| 215 | &val); | ||
| 216 | if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) { | ||
| 217 | /* | ||
| 218 | * Ok, BIOS is in smm mode, try to hand off... | ||
| 219 | */ | ||
| 220 | pci_read_config_dword(pdev, | ||
| 221 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 222 | &temp); | ||
| 223 | pci_write_config_dword(pdev, | ||
| 224 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 225 | temp | EHCI_USBLEGCTLSTS_SOOE); | ||
| 226 | val |= EHCI_USBLEGSUP_OS; | ||
| 227 | pci_write_config_dword(pdev, | ||
| 228 | hcc_params + EHCI_USBLEGSUP, | ||
| 229 | val); | ||
| 230 | |||
| 231 | wait_time = 500; | ||
| 232 | do { | ||
| 233 | msleep(10); | ||
| 234 | wait_time -= 10; | ||
| 235 | pci_read_config_dword(pdev, | ||
| 236 | hcc_params + EHCI_USBLEGSUP, | ||
| 237 | &val); | ||
| 238 | } while (wait_time && (val & EHCI_USBLEGSUP_BIOS)); | ||
| 239 | if (!wait_time) { | ||
| 240 | /* | ||
| 241 | * well, possibly buggy BIOS... | ||
| 242 | */ | ||
| 243 | printk(KERN_WARNING "%s %s: early BIOS handoff " | ||
| 244 | "failed (BIOS bug ?)\n", | ||
| 245 | pdev->dev.bus_id, "EHCI"); | ||
| 246 | pci_write_config_dword(pdev, | ||
| 247 | hcc_params + EHCI_USBLEGSUP, | ||
| 248 | EHCI_USBLEGSUP_OS); | ||
| 249 | pci_write_config_dword(pdev, | ||
| 250 | hcc_params + EHCI_USBLEGCTLSTS, | ||
| 251 | 0); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | /* | ||
| 257 | * halt EHCI & disable its interrupts in any case | ||
| 258 | */ | ||
| 259 | val = readl(op_reg_base + EHCI_USBSTS); | ||
| 260 | if ((val & EHCI_USBSTS_HALTED) == 0) { | ||
| 261 | val = readl(op_reg_base + EHCI_USBCMD); | ||
| 262 | val &= ~EHCI_USBCMD_RUN; | ||
| 263 | writel(val, op_reg_base + EHCI_USBCMD); | ||
| 264 | |||
| 265 | wait_time = 2000; | ||
| 266 | delta = 100; | ||
| 267 | do { | ||
| 268 | writel(0x3f, op_reg_base + EHCI_USBSTS); | ||
| 269 | udelay(delta); | ||
| 270 | wait_time -= delta; | ||
| 271 | val = readl(op_reg_base + EHCI_USBSTS); | ||
| 272 | if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | } while (wait_time > 0); | ||
| 276 | } | ||
| 277 | writel(0, op_reg_base + EHCI_USBINTR); | ||
| 278 | writel(0x3f, op_reg_base + EHCI_USBSTS); | ||
| 279 | |||
| 280 | iounmap(base); | ||
| 281 | |||
| 282 | return; | ||
| 283 | } | ||
| 284 | |||
| 285 | |||
| 286 | |||
| 287 | static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) | ||
| 288 | { | ||
| 289 | if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) | ||
| 290 | quirk_usb_handoff_uhci(pdev); | ||
| 291 | else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) | ||
| 292 | quirk_usb_handoff_ohci(pdev); | ||
| 293 | else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI) | ||
| 294 | quirk_usb_disable_ehci(pdev); | ||
| 295 | } | ||
| 296 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); | ||
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index b5e7a478bc01..40169d9cf2b1 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
| @@ -1363,7 +1363,7 @@ error: | |||
| 1363 | #ifdef CONFIG_PM | 1363 | #ifdef CONFIG_PM |
| 1364 | 1364 | ||
| 1365 | static int | 1365 | static int |
| 1366 | sl811h_hub_suspend(struct usb_hcd *hcd) | 1366 | sl811h_bus_suspend(struct usb_hcd *hcd) |
| 1367 | { | 1367 | { |
| 1368 | // SOFs off | 1368 | // SOFs off |
| 1369 | DBG("%s\n", __FUNCTION__); | 1369 | DBG("%s\n", __FUNCTION__); |
| @@ -1371,7 +1371,7 @@ sl811h_hub_suspend(struct usb_hcd *hcd) | |||
| 1371 | } | 1371 | } |
| 1372 | 1372 | ||
| 1373 | static int | 1373 | static int |
| 1374 | sl811h_hub_resume(struct usb_hcd *hcd) | 1374 | sl811h_bus_resume(struct usb_hcd *hcd) |
| 1375 | { | 1375 | { |
| 1376 | // SOFs on | 1376 | // SOFs on |
| 1377 | DBG("%s\n", __FUNCTION__); | 1377 | DBG("%s\n", __FUNCTION__); |
| @@ -1380,8 +1380,8 @@ sl811h_hub_resume(struct usb_hcd *hcd) | |||
| 1380 | 1380 | ||
| 1381 | #else | 1381 | #else |
| 1382 | 1382 | ||
| 1383 | #define sl811h_hub_suspend NULL | 1383 | #define sl811h_bus_suspend NULL |
| 1384 | #define sl811h_hub_resume NULL | 1384 | #define sl811h_bus_resume NULL |
| 1385 | 1385 | ||
| 1386 | #endif | 1386 | #endif |
| 1387 | 1387 | ||
| @@ -1623,8 +1623,8 @@ static struct hc_driver sl811h_hc_driver = { | |||
| 1623 | */ | 1623 | */ |
| 1624 | .hub_status_data = sl811h_hub_status_data, | 1624 | .hub_status_data = sl811h_hub_status_data, |
| 1625 | .hub_control = sl811h_hub_control, | 1625 | .hub_control = sl811h_hub_control, |
| 1626 | .hub_suspend = sl811h_hub_suspend, | 1626 | .bus_suspend = sl811h_bus_suspend, |
| 1627 | .hub_resume = sl811h_hub_resume, | 1627 | .bus_resume = sl811h_bus_resume, |
| 1628 | }; | 1628 | }; |
| 1629 | 1629 | ||
| 1630 | /*-------------------------------------------------------------------------*/ | 1630 | /*-------------------------------------------------------------------------*/ |
| @@ -1791,7 +1791,7 @@ sl811h_suspend(struct device *dev, pm_message_t state) | |||
| 1791 | int retval = 0; | 1791 | int retval = 0; |
| 1792 | 1792 | ||
| 1793 | if (state.event == PM_EVENT_FREEZE) | 1793 | if (state.event == PM_EVENT_FREEZE) |
| 1794 | retval = sl811h_hub_suspend(hcd); | 1794 | retval = sl811h_bus_suspend(hcd); |
| 1795 | else if (state.event == PM_EVENT_SUSPEND) | 1795 | else if (state.event == PM_EVENT_SUSPEND) |
| 1796 | port_power(sl811, 0); | 1796 | port_power(sl811, 0); |
| 1797 | if (retval == 0) | 1797 | if (retval == 0) |
| @@ -1816,7 +1816,7 @@ sl811h_resume(struct device *dev) | |||
| 1816 | } | 1816 | } |
| 1817 | 1817 | ||
| 1818 | dev->power.power_state = PMSG_ON; | 1818 | dev->power.power_state = PMSG_ON; |
| 1819 | return sl811h_hub_resume(hcd); | 1819 | return sl811h_bus_resume(hcd); |
| 1820 | } | 1820 | } |
| 1821 | 1821 | ||
| 1822 | #else | 1822 | #else |
| @@ -1831,6 +1831,7 @@ sl811h_resume(struct device *dev) | |||
| 1831 | struct device_driver sl811h_driver = { | 1831 | struct device_driver sl811h_driver = { |
| 1832 | .name = (char *) hcd_name, | 1832 | .name = (char *) hcd_name, |
| 1833 | .bus = &platform_bus_type, | 1833 | .bus = &platform_bus_type, |
| 1834 | .owner = THIS_MODULE, | ||
| 1834 | 1835 | ||
| 1835 | .probe = sl811h_probe, | 1836 | .probe = sl811h_probe, |
| 1836 | .remove = __devexit_p(sl811h_remove), | 1837 | .remove = __devexit_p(sl811h_remove), |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 4538a98b6f9d..151154df37fa 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
| @@ -348,7 +348,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu | |||
| 348 | 348 | ||
| 349 | if (urbp->urb->status != -EINPROGRESS) | 349 | if (urbp->urb->status != -EINPROGRESS) |
| 350 | out += sprintf(out, "Status=%d ", urbp->urb->status); | 350 | out += sprintf(out, "Status=%d ", urbp->urb->status); |
| 351 | //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime); | ||
| 352 | //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); | 351 | //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); |
| 353 | 352 | ||
| 354 | count = 0; | 353 | count = 0; |
| @@ -446,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
| 446 | out += sprintf(out, "Frame List\n"); | 445 | out += sprintf(out, "Frame List\n"); |
| 447 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { | 446 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { |
| 448 | int shown = 0; | 447 | int shown = 0; |
| 449 | td = uhci->fl->frame_cpu[i]; | 448 | td = uhci->frame_cpu[i]; |
| 450 | if (!td) | 449 | if (!td) |
| 451 | continue; | 450 | continue; |
| 452 | 451 | ||
| 453 | if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { | 452 | if (td->dma_handle != (dma_addr_t)uhci->frame[i]) { |
| 454 | show_frame_num(); | 453 | show_frame_num(); |
| 455 | out += sprintf(out, " frame list does not match td->dma_handle!\n"); | 454 | out += sprintf(out, " frame list does not match td->dma_handle!\n"); |
| 456 | } | 455 | } |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0c024898cbea..15e0a511069b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -101,37 +101,16 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
| 101 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
| 102 | #include "uhci-hub.c" | 102 | #include "uhci-hub.c" |
| 103 | 103 | ||
| 104 | extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
| 105 | extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
| 106 | |||
| 104 | /* | 107 | /* |
| 105 | * Make sure the controller is completely inactive, unable to | 108 | * Finish up a host controller reset and update the recorded state. |
| 106 | * generate interrupts or do DMA. | ||
| 107 | */ | 109 | */ |
| 108 | static void reset_hc(struct uhci_hcd *uhci) | 110 | static void finish_reset(struct uhci_hcd *uhci) |
| 109 | { | 111 | { |
| 110 | int port; | 112 | int port; |
| 111 | 113 | ||
| 112 | /* Turn off PIRQ enable and SMI enable. (This also turns off the | ||
| 113 | * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. | ||
| 114 | */ | ||
| 115 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
| 116 | USBLEGSUP_RWC); | ||
| 117 | |||
| 118 | /* Reset the HC - this will force us to get a | ||
| 119 | * new notification of any already connected | ||
| 120 | * ports due to the virtual disconnect that it | ||
| 121 | * implies. | ||
| 122 | */ | ||
| 123 | outw(USBCMD_HCRESET, uhci->io_addr + USBCMD); | ||
| 124 | mb(); | ||
| 125 | udelay(5); | ||
| 126 | if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) | ||
| 127 | dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n"); | ||
| 128 | |||
| 129 | /* Just to be safe, disable interrupt requests and | ||
| 130 | * make sure the controller is stopped. | ||
| 131 | */ | ||
| 132 | outw(0, uhci->io_addr + USBINTR); | ||
| 133 | outw(0, uhci->io_addr + USBCMD); | ||
| 134 | |||
| 135 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect | 114 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect |
| 136 | * bits in the port status and control registers. | 115 | * bits in the port status and control registers. |
| 137 | * We have to clear them by hand. | 116 | * We have to clear them by hand. |
| @@ -153,7 +132,8 @@ static void reset_hc(struct uhci_hcd *uhci) | |||
| 153 | */ | 132 | */ |
| 154 | static void hc_died(struct uhci_hcd *uhci) | 133 | static void hc_died(struct uhci_hcd *uhci) |
| 155 | { | 134 | { |
| 156 | reset_hc(uhci); | 135 | uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); |
| 136 | finish_reset(uhci); | ||
| 157 | uhci->hc_inaccessible = 1; | 137 | uhci->hc_inaccessible = 1; |
| 158 | } | 138 | } |
| 159 | 139 | ||
| @@ -163,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci) | |||
| 163 | */ | 143 | */ |
| 164 | static void check_and_reset_hc(struct uhci_hcd *uhci) | 144 | static void check_and_reset_hc(struct uhci_hcd *uhci) |
| 165 | { | 145 | { |
| 166 | u16 legsup; | 146 | if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr)) |
| 167 | unsigned int cmd, intr; | 147 | finish_reset(uhci); |
| 168 | |||
| 169 | /* | ||
| 170 | * When restarting a suspended controller, we expect all the | ||
| 171 | * settings to be the same as we left them: | ||
| 172 | * | ||
| 173 | * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; | ||
| 174 | * Controller is stopped and configured with EGSM set; | ||
| 175 | * No interrupts enabled except possibly Resume Detect. | ||
| 176 | * | ||
| 177 | * If any of these conditions are violated we do a complete reset. | ||
| 178 | */ | ||
| 179 | pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup); | ||
| 180 | if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) { | ||
| 181 | dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n", | ||
| 182 | __FUNCTION__, legsup); | ||
| 183 | goto reset_needed; | ||
| 184 | } | ||
| 185 | |||
| 186 | cmd = inw(uhci->io_addr + USBCMD); | ||
| 187 | if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) { | ||
| 188 | dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n", | ||
| 189 | __FUNCTION__, cmd); | ||
| 190 | goto reset_needed; | ||
| 191 | } | ||
| 192 | |||
| 193 | intr = inw(uhci->io_addr + USBINTR); | ||
| 194 | if (intr & (~USBINTR_RESUME)) { | ||
| 195 | dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n", | ||
| 196 | __FUNCTION__, intr); | ||
| 197 | goto reset_needed; | ||
| 198 | } | ||
| 199 | return; | ||
| 200 | |||
| 201 | reset_needed: | ||
| 202 | dev_dbg(uhci_dev(uhci), "Performing full reset\n"); | ||
| 203 | reset_hc(uhci); | ||
| 204 | } | 148 | } |
| 205 | 149 | ||
| 206 | /* | 150 | /* |
| @@ -212,13 +156,13 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
| 212 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); | 156 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); |
| 213 | 157 | ||
| 214 | /* Store the frame list base address */ | 158 | /* Store the frame list base address */ |
| 215 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); | 159 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); |
| 216 | 160 | ||
| 217 | /* Set the current frame number */ | 161 | /* Set the current frame number */ |
| 218 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 162 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); |
| 219 | 163 | ||
| 220 | /* Mark controller as running before we enable interrupts */ | 164 | /* Mark controller as not halted before we enable interrupts */ |
| 221 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 165 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; |
| 222 | mb(); | 166 | mb(); |
| 223 | 167 | ||
| 224 | /* Enable PIRQ */ | 168 | /* Enable PIRQ */ |
| @@ -319,6 +263,7 @@ __acquires(uhci->lock) | |||
| 319 | 263 | ||
| 320 | static void start_rh(struct uhci_hcd *uhci) | 264 | static void start_rh(struct uhci_hcd *uhci) |
| 321 | { | 265 | { |
| 266 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | ||
| 322 | uhci->is_stopped = 0; | 267 | uhci->is_stopped = 0; |
| 323 | smp_wmb(); | 268 | smp_wmb(); |
| 324 | 269 | ||
| @@ -437,36 +382,21 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
| 437 | int i; | 382 | int i; |
| 438 | 383 | ||
| 439 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 384 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
| 440 | if (uhci->skelqh[i]) { | 385 | uhci_free_qh(uhci, uhci->skelqh[i]); |
| 441 | uhci_free_qh(uhci, uhci->skelqh[i]); | ||
| 442 | uhci->skelqh[i] = NULL; | ||
| 443 | } | ||
| 444 | 386 | ||
| 445 | if (uhci->term_td) { | 387 | uhci_free_td(uhci, uhci->term_td); |
| 446 | uhci_free_td(uhci, uhci->term_td); | ||
| 447 | uhci->term_td = NULL; | ||
| 448 | } | ||
| 449 | 388 | ||
| 450 | if (uhci->qh_pool) { | 389 | dma_pool_destroy(uhci->qh_pool); |
| 451 | dma_pool_destroy(uhci->qh_pool); | ||
| 452 | uhci->qh_pool = NULL; | ||
| 453 | } | ||
| 454 | 390 | ||
| 455 | if (uhci->td_pool) { | 391 | dma_pool_destroy(uhci->td_pool); |
| 456 | dma_pool_destroy(uhci->td_pool); | ||
| 457 | uhci->td_pool = NULL; | ||
| 458 | } | ||
| 459 | 392 | ||
| 460 | if (uhci->fl) { | 393 | kfree(uhci->frame_cpu); |
| 461 | dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | ||
| 462 | uhci->fl, uhci->fl->dma_handle); | ||
| 463 | uhci->fl = NULL; | ||
| 464 | } | ||
| 465 | 394 | ||
| 466 | if (uhci->dentry) { | 395 | dma_free_coherent(uhci_dev(uhci), |
| 467 | debugfs_remove(uhci->dentry); | 396 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
| 468 | uhci->dentry = NULL; | 397 | uhci->frame, uhci->frame_dma_handle); |
| 469 | } | 398 | |
| 399 | debugfs_remove(uhci->dentry); | ||
| 470 | } | 400 | } |
| 471 | 401 | ||
| 472 | static int uhci_reset(struct usb_hcd *hcd) | 402 | static int uhci_reset(struct usb_hcd *hcd) |
| @@ -545,7 +475,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 545 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 475 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| 546 | int retval = -EBUSY; | 476 | int retval = -EBUSY; |
| 547 | int i; | 477 | int i; |
| 548 | dma_addr_t dma_handle; | ||
| 549 | struct dentry *dentry; | 478 | struct dentry *dentry; |
| 550 | 479 | ||
| 551 | hcd->uses_new_polling = 1; | 480 | hcd->uses_new_polling = 1; |
| @@ -579,17 +508,23 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 579 | 508 | ||
| 580 | init_waitqueue_head(&uhci->waitqh); | 509 | init_waitqueue_head(&uhci->waitqh); |
| 581 | 510 | ||
| 582 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 511 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), |
| 583 | &dma_handle, 0); | 512 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
| 584 | if (!uhci->fl) { | 513 | &uhci->frame_dma_handle, 0); |
| 514 | if (!uhci->frame) { | ||
| 585 | dev_err(uhci_dev(uhci), "unable to allocate " | 515 | dev_err(uhci_dev(uhci), "unable to allocate " |
| 586 | "consistent memory for frame list\n"); | 516 | "consistent memory for frame list\n"); |
| 587 | goto err_alloc_fl; | 517 | goto err_alloc_frame; |
| 588 | } | 518 | } |
| 519 | memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame)); | ||
| 589 | 520 | ||
| 590 | memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); | 521 | uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), |
| 591 | 522 | GFP_KERNEL); | |
| 592 | uhci->fl->dma_handle = dma_handle; | 523 | if (!uhci->frame_cpu) { |
| 524 | dev_err(uhci_dev(uhci), "unable to allocate " | ||
| 525 | "memory for frame pointers\n"); | ||
| 526 | goto err_alloc_frame_cpu; | ||
| 527 | } | ||
| 593 | 528 | ||
| 594 | uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), | 529 | uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), |
| 595 | sizeof(struct uhci_td), 16, 0); | 530 | sizeof(struct uhci_td), 16, 0); |
| @@ -672,7 +607,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 672 | irq = 7; | 607 | irq = 7; |
| 673 | 608 | ||
| 674 | /* Only place we don't use the frame list routines */ | 609 | /* Only place we don't use the frame list routines */ |
| 675 | uhci->fl->frame[i] = UHCI_PTR_QH | | 610 | uhci->frame[i] = UHCI_PTR_QH | |
| 676 | cpu_to_le32(uhci->skelqh[irq]->dma_handle); | 611 | cpu_to_le32(uhci->skelqh[irq]->dma_handle); |
| 677 | } | 612 | } |
| 678 | 613 | ||
| @@ -690,31 +625,29 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 690 | * error exits: | 625 | * error exits: |
| 691 | */ | 626 | */ |
| 692 | err_alloc_skelqh: | 627 | err_alloc_skelqh: |
| 693 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 628 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { |
| 694 | if (uhci->skelqh[i]) { | 629 | if (uhci->skelqh[i]) |
| 695 | uhci_free_qh(uhci, uhci->skelqh[i]); | 630 | uhci_free_qh(uhci, uhci->skelqh[i]); |
| 696 | uhci->skelqh[i] = NULL; | 631 | } |
| 697 | } | ||
| 698 | 632 | ||
| 699 | uhci_free_td(uhci, uhci->term_td); | 633 | uhci_free_td(uhci, uhci->term_td); |
| 700 | uhci->term_td = NULL; | ||
| 701 | 634 | ||
| 702 | err_alloc_term_td: | 635 | err_alloc_term_td: |
| 703 | dma_pool_destroy(uhci->qh_pool); | 636 | dma_pool_destroy(uhci->qh_pool); |
| 704 | uhci->qh_pool = NULL; | ||
| 705 | 637 | ||
| 706 | err_create_qh_pool: | 638 | err_create_qh_pool: |
| 707 | dma_pool_destroy(uhci->td_pool); | 639 | dma_pool_destroy(uhci->td_pool); |
| 708 | uhci->td_pool = NULL; | ||
| 709 | 640 | ||
| 710 | err_create_td_pool: | 641 | err_create_td_pool: |
| 711 | dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 642 | kfree(uhci->frame_cpu); |
| 712 | uhci->fl, uhci->fl->dma_handle); | 643 | |
| 713 | uhci->fl = NULL; | 644 | err_alloc_frame_cpu: |
| 645 | dma_free_coherent(uhci_dev(uhci), | ||
| 646 | UHCI_NUMFRAMES * sizeof(*uhci->frame), | ||
| 647 | uhci->frame, uhci->frame_dma_handle); | ||
| 714 | 648 | ||
| 715 | err_alloc_fl: | 649 | err_alloc_frame: |
| 716 | debugfs_remove(uhci->dentry); | 650 | debugfs_remove(uhci->dentry); |
| 717 | uhci->dentry = NULL; | ||
| 718 | 651 | ||
| 719 | err_create_debug_entry: | 652 | err_create_debug_entry: |
| 720 | return retval; | 653 | return retval; |
| @@ -726,7 +659,7 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
| 726 | 659 | ||
| 727 | spin_lock_irq(&uhci->lock); | 660 | spin_lock_irq(&uhci->lock); |
| 728 | if (!uhci->hc_inaccessible) | 661 | if (!uhci->hc_inaccessible) |
| 729 | reset_hc(uhci); | 662 | hc_died(uhci); |
| 730 | uhci_scan_schedule(uhci, NULL); | 663 | uhci_scan_schedule(uhci, NULL); |
| 731 | spin_unlock_irq(&uhci->lock); | 664 | spin_unlock_irq(&uhci->lock); |
| 732 | 665 | ||
| @@ -774,14 +707,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
| 774 | if (uhci->hc_inaccessible) /* Dead or already suspended */ | 707 | if (uhci->hc_inaccessible) /* Dead or already suspended */ |
| 775 | goto done; | 708 | goto done; |
| 776 | 709 | ||
| 777 | #ifndef CONFIG_USB_SUSPEND | ||
| 778 | /* Otherwise this would never happen */ | ||
| 779 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | ||
| 780 | #endif | ||
| 781 | |||
| 782 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { | 710 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
| 783 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); | 711 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); |
| 784 | hcd->state = HC_STATE_RUNNING; | ||
| 785 | rc = -EBUSY; | 712 | rc = -EBUSY; |
| 786 | goto done; | 713 | goto done; |
| 787 | }; | 714 | }; |
| @@ -820,10 +747,6 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
| 820 | check_and_reset_hc(uhci); | 747 | check_and_reset_hc(uhci); |
| 821 | configure_hc(uhci); | 748 | configure_hc(uhci); |
| 822 | 749 | ||
| 823 | #ifndef CONFIG_USB_SUSPEND | ||
| 824 | /* Otherwise this would never happen */ | ||
| 825 | wakeup_rh(uhci); | ||
| 826 | #endif | ||
| 827 | if (uhci->rh_state == UHCI_RH_RESET) | 750 | if (uhci->rh_state == UHCI_RH_RESET) |
| 828 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | 751 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
| 829 | 752 | ||
| @@ -881,8 +804,8 @@ static const struct hc_driver uhci_driver = { | |||
| 881 | #ifdef CONFIG_PM | 804 | #ifdef CONFIG_PM |
| 882 | .suspend = uhci_suspend, | 805 | .suspend = uhci_suspend, |
| 883 | .resume = uhci_resume, | 806 | .resume = uhci_resume, |
| 884 | .hub_suspend = uhci_rh_suspend, | 807 | .bus_suspend = uhci_rh_suspend, |
| 885 | .hub_resume = uhci_rh_resume, | 808 | .bus_resume = uhci_rh_resume, |
| 886 | #endif | 809 | #endif |
| 887 | .stop = uhci_stop, | 810 | .stop = uhci_stop, |
| 888 | 811 | ||
| @@ -908,6 +831,7 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); | |||
| 908 | static struct pci_driver uhci_pci_driver = { | 831 | static struct pci_driver uhci_pci_driver = { |
| 909 | .name = (char *)hcd_name, | 832 | .name = (char *)hcd_name, |
| 910 | .id_table = uhci_pci_ids, | 833 | .id_table = uhci_pci_ids, |
| 834 | .owner = THIS_MODULE, | ||
| 911 | 835 | ||
| 912 | .probe = usb_hcd_pci_probe, | 836 | .probe = usb_hcd_pci_probe, |
| 913 | .remove = usb_hcd_pci_remove, | 837 | .remove = usb_hcd_pci_remove, |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 282f40b75881..e576db57a926 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT) | 7 | #define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT) |
| 8 | #define PIPE_DEVEP_MASK 0x0007ff00 | 8 | #define PIPE_DEVEP_MASK 0x0007ff00 |
| 9 | 9 | ||
| 10 | |||
| 10 | /* | 11 | /* |
| 11 | * Universal Host Controller Interface data structures and defines | 12 | * Universal Host Controller Interface data structures and defines |
| 12 | */ | 13 | */ |
| @@ -82,15 +83,10 @@ | |||
| 82 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ | 83 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ |
| 83 | #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ | 84 | #define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ |
| 84 | 85 | ||
| 85 | struct uhci_frame_list { | ||
| 86 | __le32 frame[UHCI_NUMFRAMES]; | ||
| 87 | |||
| 88 | void *frame_cpu[UHCI_NUMFRAMES]; | ||
| 89 | |||
| 90 | dma_addr_t dma_handle; | ||
| 91 | }; | ||
| 92 | 86 | ||
| 93 | struct urb_priv; | 87 | /* |
| 88 | * Queue Headers | ||
| 89 | */ | ||
| 94 | 90 | ||
| 95 | /* | 91 | /* |
| 96 | * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is | 92 | * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is |
| @@ -116,13 +112,13 @@ struct uhci_qh { | |||
| 116 | 112 | ||
| 117 | struct urb_priv *urbp; | 113 | struct urb_priv *urbp; |
| 118 | 114 | ||
| 119 | struct list_head list; /* P: uhci->frame_list_lock */ | 115 | struct list_head list; |
| 120 | struct list_head remove_list; /* P: uhci->remove_list_lock */ | 116 | struct list_head remove_list; |
| 121 | } __attribute__((aligned(16))); | 117 | } __attribute__((aligned(16))); |
| 122 | 118 | ||
| 123 | /* | 119 | /* |
| 124 | * We need a special accessor for the element pointer because it is | 120 | * We need a special accessor for the element pointer because it is |
| 125 | * subject to asynchronous updates by the controller | 121 | * subject to asynchronous updates by the controller. |
| 126 | */ | 122 | */ |
| 127 | static __le32 inline qh_element(struct uhci_qh *qh) { | 123 | static __le32 inline qh_element(struct uhci_qh *qh) { |
| 128 | __le32 element = qh->element; | 124 | __le32 element = qh->element; |
| @@ -131,6 +127,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) { | |||
| 131 | return element; | 127 | return element; |
| 132 | } | 128 | } |
| 133 | 129 | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Transfer Descriptors | ||
| 133 | */ | ||
| 134 | |||
| 134 | /* | 135 | /* |
| 135 | * for TD <status>: | 136 | * for TD <status>: |
| 136 | */ | 137 | */ |
| @@ -183,17 +184,10 @@ static __le32 inline qh_element(struct uhci_qh *qh) { | |||
| 183 | * | 184 | * |
| 184 | * That's silly, the hardware doesn't care. The hardware only cares that | 185 | * That's silly, the hardware doesn't care. The hardware only cares that |
| 185 | * the hardware words are 16-byte aligned, and we can have any amount of | 186 | * the hardware words are 16-byte aligned, and we can have any amount of |
| 186 | * sw space after the TD entry as far as I can tell. | 187 | * sw space after the TD entry. |
| 187 | * | ||
| 188 | * But let's just go with the documentation, at least for 32-bit machines. | ||
| 189 | * On 64-bit machines we probably want to take advantage of the fact that | ||
| 190 | * hw doesn't really care about the size of the sw-only area. | ||
| 191 | * | ||
| 192 | * Alas, not anymore, we have more than 4 words for software, woops. | ||
| 193 | * Everything still works tho, surprise! -jerdfelt | ||
| 194 | * | 188 | * |
| 195 | * td->link points to either another TD (not necessarily for the same urb or | 189 | * td->link points to either another TD (not necessarily for the same urb or |
| 196 | * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs) | 190 | * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs). |
| 197 | */ | 191 | */ |
| 198 | struct uhci_td { | 192 | struct uhci_td { |
| 199 | /* Hardware fields */ | 193 | /* Hardware fields */ |
| @@ -205,18 +199,16 @@ struct uhci_td { | |||
| 205 | /* Software fields */ | 199 | /* Software fields */ |
| 206 | dma_addr_t dma_handle; | 200 | dma_addr_t dma_handle; |
| 207 | 201 | ||
| 208 | struct urb *urb; | 202 | struct list_head list; |
| 209 | 203 | struct list_head remove_list; | |
| 210 | struct list_head list; /* P: urb->lock */ | ||
| 211 | struct list_head remove_list; /* P: uhci->td_remove_list_lock */ | ||
| 212 | 204 | ||
| 213 | int frame; /* for iso: what frame? */ | 205 | int frame; /* for iso: what frame? */ |
| 214 | struct list_head fl_list; /* P: uhci->frame_list_lock */ | 206 | struct list_head fl_list; |
| 215 | } __attribute__((aligned(16))); | 207 | } __attribute__((aligned(16))); |
| 216 | 208 | ||
| 217 | /* | 209 | /* |
| 218 | * We need a special accessor for the control/status word because it is | 210 | * We need a special accessor for the control/status word because it is |
| 219 | * subject to asynchronous updates by the controller | 211 | * subject to asynchronous updates by the controller. |
| 220 | */ | 212 | */ |
| 221 | static u32 inline td_status(struct uhci_td *td) { | 213 | static u32 inline td_status(struct uhci_td *td) { |
| 222 | __le32 status = td->status; | 214 | __le32 status = td->status; |
| @@ -227,6 +219,10 @@ static u32 inline td_status(struct uhci_td *td) { | |||
| 227 | 219 | ||
| 228 | 220 | ||
| 229 | /* | 221 | /* |
| 222 | * Skeleton Queue Headers | ||
| 223 | */ | ||
| 224 | |||
| 225 | /* | ||
| 230 | * The UHCI driver places Interrupt, Control and Bulk into QH's both | 226 | * The UHCI driver places Interrupt, Control and Bulk into QH's both |
| 231 | * to group together TD's for one transfer, and also to faciliate queuing | 227 | * to group together TD's for one transfer, and also to faciliate queuing |
| 232 | * of URB's. To make it easy to insert entries into the schedule, we have | 228 | * of URB's. To make it easy to insert entries into the schedule, we have |
| @@ -256,15 +252,15 @@ static u32 inline td_status(struct uhci_td *td) { | |||
| 256 | * | 252 | * |
| 257 | * The terminating QH is used for 2 reasons: | 253 | * The terminating QH is used for 2 reasons: |
| 258 | * - To place a terminating TD which is used to workaround a PIIX bug | 254 | * - To place a terminating TD which is used to workaround a PIIX bug |
| 259 | * (see Intel errata for explanation) | 255 | * (see Intel errata for explanation), and |
| 260 | * - To loop back to the full-speed control queue for full-speed bandwidth | 256 | * - To loop back to the full-speed control queue for full-speed bandwidth |
| 261 | * reclamation | 257 | * reclamation. |
| 262 | * | 258 | * |
| 263 | * Isochronous transfers are stored before the start of the skeleton | 259 | * Isochronous transfers are stored before the start of the skeleton |
| 264 | * schedule and don't use QH's. While the UHCI spec doesn't forbid the | 260 | * schedule and don't use QH's. While the UHCI spec doesn't forbid the |
| 265 | * use of QH's for Isochronous, it doesn't use them either. Since we don't | 261 | * use of QH's for Isochronous, it doesn't use them either. And the spec |
| 266 | * need to use them either, we follow the spec diagrams in hope that it'll | 262 | * says that queues never advance on an error completion status, which |
| 267 | * be more compatible with future UHCI implementations. | 263 | * makes them totally unsuitable for Isochronous transfers. |
| 268 | */ | 264 | */ |
| 269 | 265 | ||
| 270 | #define UHCI_NUM_SKELQH 12 | 266 | #define UHCI_NUM_SKELQH 12 |
| @@ -314,8 +310,13 @@ static inline int __interval_to_skel(int interval) | |||
| 314 | return 0; /* int128 for 128-255 ms (Max.) */ | 310 | return 0; /* int128 for 128-255 ms (Max.) */ |
| 315 | } | 311 | } |
| 316 | 312 | ||
| 313 | |||
| 314 | /* | ||
| 315 | * The UHCI controller and root hub | ||
| 316 | */ | ||
| 317 | |||
| 317 | /* | 318 | /* |
| 318 | * States for the root hub. | 319 | * States for the root hub: |
| 319 | * | 320 | * |
| 320 | * To prevent "bouncing" in the presence of electrical noise, | 321 | * To prevent "bouncing" in the presence of electrical noise, |
| 321 | * when there are no devices attached we delay for 1 second in the | 322 | * when there are no devices attached we delay for 1 second in the |
| @@ -326,7 +327,7 @@ static inline int __interval_to_skel(int interval) | |||
| 326 | */ | 327 | */ |
| 327 | enum uhci_rh_state { | 328 | enum uhci_rh_state { |
| 328 | /* In the following states the HC must be halted. | 329 | /* In the following states the HC must be halted. |
| 329 | * These two must come first */ | 330 | * These two must come first. */ |
| 330 | UHCI_RH_RESET, | 331 | UHCI_RH_RESET, |
| 331 | UHCI_RH_SUSPENDED, | 332 | UHCI_RH_SUSPENDED, |
| 332 | 333 | ||
| @@ -338,13 +339,13 @@ enum uhci_rh_state { | |||
| 338 | UHCI_RH_SUSPENDING, | 339 | UHCI_RH_SUSPENDING, |
| 339 | 340 | ||
| 340 | /* In the following states it's an error if the HC is halted. | 341 | /* In the following states it's an error if the HC is halted. |
| 341 | * These two must come last */ | 342 | * These two must come last. */ |
| 342 | UHCI_RH_RUNNING, /* The normal state */ | 343 | UHCI_RH_RUNNING, /* The normal state */ |
| 343 | UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ | 344 | UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ |
| 344 | }; | 345 | }; |
| 345 | 346 | ||
| 346 | /* | 347 | /* |
| 347 | * This describes the full uhci information. | 348 | * The full UHCI controller information: |
| 348 | */ | 349 | */ |
| 349 | struct uhci_hcd { | 350 | struct uhci_hcd { |
| 350 | 351 | ||
| @@ -361,7 +362,11 @@ struct uhci_hcd { | |||
| 361 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ | 362 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ |
| 362 | 363 | ||
| 363 | spinlock_t lock; | 364 | spinlock_t lock; |
| 364 | struct uhci_frame_list *fl; /* P: uhci->lock */ | 365 | |
| 366 | dma_addr_t frame_dma_handle; /* Hardware frame list */ | ||
| 367 | __le32 *frame; | ||
| 368 | void **frame_cpu; /* CPU's frame list */ | ||
| 369 | |||
| 365 | int fsbr; /* Full-speed bandwidth reclamation */ | 370 | int fsbr; /* Full-speed bandwidth reclamation */ |
| 366 | unsigned long fsbrtimeout; /* FSBR delay */ | 371 | unsigned long fsbrtimeout; /* FSBR delay */ |
| 367 | 372 | ||
| @@ -385,22 +390,22 @@ struct uhci_hcd { | |||
| 385 | unsigned long ports_timeout; /* Time to stop signalling */ | 390 | unsigned long ports_timeout; /* Time to stop signalling */ |
| 386 | 391 | ||
| 387 | /* Main list of URB's currently controlled by this HC */ | 392 | /* Main list of URB's currently controlled by this HC */ |
| 388 | struct list_head urb_list; /* P: uhci->lock */ | 393 | struct list_head urb_list; |
| 389 | 394 | ||
| 390 | /* List of QH's that are done, but waiting to be unlinked (race) */ | 395 | /* List of QH's that are done, but waiting to be unlinked (race) */ |
| 391 | struct list_head qh_remove_list; /* P: uhci->lock */ | 396 | struct list_head qh_remove_list; |
| 392 | unsigned int qh_remove_age; /* Age in frames */ | 397 | unsigned int qh_remove_age; /* Age in frames */ |
| 393 | 398 | ||
| 394 | /* List of TD's that are done, but waiting to be freed (race) */ | 399 | /* List of TD's that are done, but waiting to be freed (race) */ |
| 395 | struct list_head td_remove_list; /* P: uhci->lock */ | 400 | struct list_head td_remove_list; |
| 396 | unsigned int td_remove_age; /* Age in frames */ | 401 | unsigned int td_remove_age; /* Age in frames */ |
| 397 | 402 | ||
| 398 | /* List of asynchronously unlinked URB's */ | 403 | /* List of asynchronously unlinked URB's */ |
| 399 | struct list_head urb_remove_list; /* P: uhci->lock */ | 404 | struct list_head urb_remove_list; |
| 400 | unsigned int urb_remove_age; /* Age in frames */ | 405 | unsigned int urb_remove_age; /* Age in frames */ |
| 401 | 406 | ||
| 402 | /* List of URB's awaiting completion callback */ | 407 | /* List of URB's awaiting completion callback */ |
| 403 | struct list_head complete_list; /* P: uhci->lock */ | 408 | struct list_head complete_list; |
| 404 | 409 | ||
| 405 | int rh_numports; /* Number of root-hub ports */ | 410 | int rh_numports; /* Number of root-hub ports */ |
| 406 | 411 | ||
| @@ -419,13 +424,17 @@ static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci) | |||
| 419 | 424 | ||
| 420 | #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) | 425 | #define uhci_dev(u) (uhci_to_hcd(u)->self.controller) |
| 421 | 426 | ||
| 427 | |||
| 428 | /* | ||
| 429 | * Private per-URB data | ||
| 430 | */ | ||
| 422 | struct urb_priv { | 431 | struct urb_priv { |
| 423 | struct list_head urb_list; | 432 | struct list_head urb_list; |
| 424 | 433 | ||
| 425 | struct urb *urb; | 434 | struct urb *urb; |
| 426 | 435 | ||
| 427 | struct uhci_qh *qh; /* QH for this URB */ | 436 | struct uhci_qh *qh; /* QH for this URB */ |
| 428 | struct list_head td_list; /* P: urb->lock */ | 437 | struct list_head td_list; |
| 429 | 438 | ||
| 430 | unsigned fsbr : 1; /* URB turned on FSBR */ | 439 | unsigned fsbr : 1; /* URB turned on FSBR */ |
| 431 | unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ | 440 | unsigned fsbr_timeout : 1; /* URB timed out on FSBR */ |
| @@ -434,12 +443,12 @@ struct urb_priv { | |||
| 434 | /* a control transfer, retrigger */ | 443 | /* a control transfer, retrigger */ |
| 435 | /* the status phase */ | 444 | /* the status phase */ |
| 436 | 445 | ||
| 437 | unsigned long inserttime; /* In jiffies */ | ||
| 438 | unsigned long fsbrtime; /* In jiffies */ | 446 | unsigned long fsbrtime; /* In jiffies */ |
| 439 | 447 | ||
| 440 | struct list_head queue_list; /* P: uhci->frame_list_lock */ | 448 | struct list_head queue_list; |
| 441 | }; | 449 | }; |
| 442 | 450 | ||
| 451 | |||
| 443 | /* | 452 | /* |
| 444 | * Locking in uhci.c | 453 | * Locking in uhci.c |
| 445 | * | 454 | * |
| @@ -459,6 +468,5 @@ struct urb_priv { | |||
| 459 | 468 | ||
| 460 | #define PCI_VENDOR_ID_GENESYS 0x17a0 | 469 | #define PCI_VENDOR_ID_GENESYS 0x17a0 |
| 461 | #define PCI_DEVICE_ID_GL880S_UHCI 0x8083 | 470 | #define PCI_DEVICE_ID_GL880S_UHCI 0x8083 |
| 462 | #define PCI_DEVICE_ID_GL880S_EHCI 0x8084 | ||
| 463 | 471 | ||
| 464 | #endif | 472 | #endif |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 4e0fbe2c1a9a..7e46887d9e12 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
| @@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, | |||
| 89 | td->frame = framenum; | 89 | td->frame = framenum; |
| 90 | 90 | ||
| 91 | /* Is there a TD already mapped there? */ | 91 | /* Is there a TD already mapped there? */ |
| 92 | if (uhci->fl->frame_cpu[framenum]) { | 92 | if (uhci->frame_cpu[framenum]) { |
| 93 | struct uhci_td *ftd, *ltd; | 93 | struct uhci_td *ftd, *ltd; |
| 94 | 94 | ||
| 95 | ftd = uhci->fl->frame_cpu[framenum]; | 95 | ftd = uhci->frame_cpu[framenum]; |
| 96 | ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); | 96 | ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); |
| 97 | 97 | ||
| 98 | list_add_tail(&td->fl_list, &ftd->fl_list); | 98 | list_add_tail(&td->fl_list, &ftd->fl_list); |
| @@ -101,29 +101,32 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, | |||
| 101 | wmb(); | 101 | wmb(); |
| 102 | ltd->link = cpu_to_le32(td->dma_handle); | 102 | ltd->link = cpu_to_le32(td->dma_handle); |
| 103 | } else { | 103 | } else { |
| 104 | td->link = uhci->fl->frame[framenum]; | 104 | td->link = uhci->frame[framenum]; |
| 105 | wmb(); | 105 | wmb(); |
| 106 | uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); | 106 | uhci->frame[framenum] = cpu_to_le32(td->dma_handle); |
| 107 | uhci->fl->frame_cpu[framenum] = td; | 107 | uhci->frame_cpu[framenum] = td; |
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) | 111 | static inline void uhci_remove_td_frame_list(struct uhci_hcd *uhci, |
| 112 | struct uhci_td *td) | ||
| 112 | { | 113 | { |
| 113 | /* If it's not inserted, don't remove it */ | 114 | /* If it's not inserted, don't remove it */ |
| 114 | if (td->frame == -1 && list_empty(&td->fl_list)) | 115 | if (td->frame == -1) { |
| 116 | WARN_ON(!list_empty(&td->fl_list)); | ||
| 115 | return; | 117 | return; |
| 118 | } | ||
| 116 | 119 | ||
| 117 | if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { | 120 | if (uhci->frame_cpu[td->frame] == td) { |
| 118 | if (list_empty(&td->fl_list)) { | 121 | if (list_empty(&td->fl_list)) { |
| 119 | uhci->fl->frame[td->frame] = td->link; | 122 | uhci->frame[td->frame] = td->link; |
| 120 | uhci->fl->frame_cpu[td->frame] = NULL; | 123 | uhci->frame_cpu[td->frame] = NULL; |
| 121 | } else { | 124 | } else { |
| 122 | struct uhci_td *ntd; | 125 | struct uhci_td *ntd; |
| 123 | 126 | ||
| 124 | ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); | 127 | ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); |
| 125 | uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); | 128 | uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle); |
| 126 | uhci->fl->frame_cpu[td->frame] = ntd; | 129 | uhci->frame_cpu[td->frame] = ntd; |
| 127 | } | 130 | } |
| 128 | } else { | 131 | } else { |
| 129 | struct uhci_td *ptd; | 132 | struct uhci_td *ptd; |
| @@ -132,13 +135,20 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) | |||
| 132 | ptd->link = td->link; | 135 | ptd->link = td->link; |
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | wmb(); | ||
| 136 | td->link = UHCI_PTR_TERM; | ||
| 137 | |||
| 138 | list_del_init(&td->fl_list); | 138 | list_del_init(&td->fl_list); |
| 139 | td->frame = -1; | 139 | td->frame = -1; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static void unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) | ||
| 143 | { | ||
| 144 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; | ||
| 145 | struct uhci_td *td; | ||
| 146 | |||
| 147 | list_for_each_entry(td, &urbp->td_list, list) | ||
| 148 | uhci_remove_td_frame_list(uhci, td); | ||
| 149 | wmb(); | ||
| 150 | } | ||
| 151 | |||
| 142 | /* | 152 | /* |
| 143 | * Inserts a td list into qh. | 153 | * Inserts a td list into qh. |
| 144 | */ | 154 | */ |
| @@ -443,7 +453,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u | |||
| 443 | 453 | ||
| 444 | memset((void *)urbp, 0, sizeof(*urbp)); | 454 | memset((void *)urbp, 0, sizeof(*urbp)); |
| 445 | 455 | ||
| 446 | urbp->inserttime = jiffies; | ||
| 447 | urbp->fsbrtime = jiffies; | 456 | urbp->fsbrtime = jiffies; |
| 448 | urbp->urb = urb; | 457 | urbp->urb = urb; |
| 449 | 458 | ||
| @@ -462,8 +471,6 @@ static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) | |||
| 462 | { | 471 | { |
| 463 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; | 472 | struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; |
| 464 | 473 | ||
| 465 | td->urb = urb; | ||
| 466 | |||
| 467 | list_add_tail(&td->list, &urbp->td_list); | 474 | list_add_tail(&td->list, &urbp->td_list); |
| 468 | } | 475 | } |
| 469 | 476 | ||
| @@ -473,8 +480,6 @@ static void uhci_remove_td_from_urb(struct uhci_td *td) | |||
| 473 | return; | 480 | return; |
| 474 | 481 | ||
| 475 | list_del_init(&td->list); | 482 | list_del_init(&td->list); |
| 476 | |||
| 477 | td->urb = NULL; | ||
| 478 | } | 483 | } |
| 479 | 484 | ||
| 480 | static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) | 485 | static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) |
| @@ -503,7 +508,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) | |||
| 503 | 508 | ||
| 504 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { | 509 | list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { |
| 505 | uhci_remove_td_from_urb(td); | 510 | uhci_remove_td_from_urb(td); |
| 506 | uhci_remove_td(uhci, td); | ||
| 507 | list_add(&td->remove_list, &uhci->td_remove_list); | 511 | list_add(&td->remove_list, &uhci->td_remove_list); |
| 508 | } | 512 | } |
| 509 | 513 | ||
| @@ -1073,6 +1077,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1073 | struct uhci_td *td; | 1077 | struct uhci_td *td; |
| 1074 | int i, ret, frame; | 1078 | int i, ret, frame; |
| 1075 | int status, destination; | 1079 | int status, destination; |
| 1080 | struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; | ||
| 1076 | 1081 | ||
| 1077 | status = TD_CTRL_ACTIVE | TD_CTRL_IOS; | 1082 | status = TD_CTRL_ACTIVE | TD_CTRL_IOS; |
| 1078 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); | 1083 | destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); |
| @@ -1081,11 +1086,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1081 | if (ret) | 1086 | if (ret) |
| 1082 | return ret; | 1087 | return ret; |
| 1083 | 1088 | ||
| 1084 | frame = urb->start_frame; | 1089 | for (i = 0; i < urb->number_of_packets; i++) { |
| 1085 | for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) { | ||
| 1086 | if (!urb->iso_frame_desc[i].length) | ||
| 1087 | continue; | ||
| 1088 | |||
| 1089 | td = uhci_alloc_td(uhci); | 1090 | td = uhci_alloc_td(uhci); |
| 1090 | if (!td) | 1091 | if (!td) |
| 1091 | return -ENOMEM; | 1092 | return -ENOMEM; |
| @@ -1096,8 +1097,12 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1096 | 1097 | ||
| 1097 | if (i + 1 >= urb->number_of_packets) | 1098 | if (i + 1 >= urb->number_of_packets) |
| 1098 | td->status |= cpu_to_le32(TD_CTRL_IOC); | 1099 | td->status |= cpu_to_le32(TD_CTRL_IOC); |
| 1100 | } | ||
| 1099 | 1101 | ||
| 1102 | frame = urb->start_frame; | ||
| 1103 | list_for_each_entry(td, &urbp->td_list, list) { | ||
| 1100 | uhci_insert_td_frame_list(uhci, td, frame); | 1104 | uhci_insert_td_frame_list(uhci, td, frame); |
| 1105 | frame += urb->interval; | ||
| 1101 | } | 1106 | } |
| 1102 | 1107 | ||
| 1103 | return -EINPROGRESS; | 1108 | return -EINPROGRESS; |
| @@ -1110,7 +1115,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1110 | int status; | 1115 | int status; |
| 1111 | int i, ret = 0; | 1116 | int i, ret = 0; |
| 1112 | 1117 | ||
| 1113 | urb->actual_length = 0; | 1118 | urb->actual_length = urb->error_count = 0; |
| 1114 | 1119 | ||
| 1115 | i = 0; | 1120 | i = 0; |
| 1116 | list_for_each_entry(td, &urbp->td_list, list) { | 1121 | list_for_each_entry(td, &urbp->td_list, list) { |
| @@ -1134,6 +1139,7 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) | |||
| 1134 | 1139 | ||
| 1135 | i++; | 1140 | i++; |
| 1136 | } | 1141 | } |
| 1142 | unlink_isochronous_tds(uhci, urb); | ||
| 1137 | 1143 | ||
| 1138 | return ret; | 1144 | return ret; |
| 1139 | } | 1145 | } |
| @@ -1366,6 +1372,8 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | |||
| 1366 | goto done; | 1372 | goto done; |
| 1367 | list_del_init(&urbp->urb_list); | 1373 | list_del_init(&urbp->urb_list); |
| 1368 | 1374 | ||
| 1375 | if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) | ||
| 1376 | unlink_isochronous_tds(uhci, urb); | ||
| 1369 | uhci_unlink_generic(uhci, urb); | 1377 | uhci_unlink_generic(uhci, urb); |
| 1370 | 1378 | ||
| 1371 | uhci_get_current_frame_number(uhci); | 1379 | uhci_get_current_frame_number(uhci); |
