diff options
| author | David Brownell <david-b@pacbell.net> | 2005-05-07 16:21:50 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-06-27 17:43:55 -0400 |
| commit | d49d431744007cec0ee1a3ade96f9e0f100c7907 (patch) | |
| tree | 4ed2f01c98b8fdf0ecd7a92d61f7c1af8beb58a2 | |
| parent | 9198769363d4dc1d63d49ecb2e2b189aceb42d94 (diff) | |
[PATCH] USB: misc ehci updates
Various minor EHCI updates
* Dump some more info in the debug dumps, notably the product
description (e.g. chip vendor), BIOS handhake flags, and
debug port status (when it's not managed by the HCD).
* Minor updates to the BIOS handoff code: always flag the HCD
as owned by Linux (in case BIOS doesn't grab it "early"),
and on the buggy-BIOS path always match the "early handoff"
code and forcibly disable SMI IRQs.
* For the disabled 64bit DMA support, there's now a constant
to use for the mask; use it.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/usb/host/ehci-dbg.c | 59 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 27 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 2 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 2 |
4 files changed, 70 insertions, 20 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 2ff11d53567b..50cb01831075 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
| @@ -254,7 +254,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | return scnprintf (buf, len, | 256 | return scnprintf (buf, len, |
| 257 | "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s", | 257 | "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", |
| 258 | label, label [0] ? " " : "", port, status, | 258 | label, label [0] ? " " : "", port, status, |
| 259 | (status & PORT_POWER) ? " POWER" : "", | 259 | (status & PORT_POWER) ? " POWER" : "", |
| 260 | (status & PORT_OWNER) ? " OWNER" : "", | 260 | (status & PORT_OWNER) ? " OWNER" : "", |
| @@ -644,9 +644,11 @@ show_registers (struct class_device *class_dev, char *buf) | |||
| 644 | if (bus->controller->power.power_state) { | 644 | if (bus->controller->power.power_state) { |
| 645 | size = scnprintf (next, size, | 645 | size = scnprintf (next, size, |
| 646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 646 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
| 647 | "%s\n" | ||
| 647 | "SUSPENDED (no register access)\n", | 648 | "SUSPENDED (no register access)\n", |
| 648 | hcd->self.controller->bus->name, | 649 | hcd->self.controller->bus->name, |
| 649 | hcd->self.controller->bus_id); | 650 | hcd->self.controller->bus_id, |
| 651 | hcd->product_desc); | ||
| 650 | goto done; | 652 | goto done; |
| 651 | } | 653 | } |
| 652 | 654 | ||
| @@ -654,13 +656,53 @@ show_registers (struct class_device *class_dev, char *buf) | |||
| 654 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 656 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); |
| 655 | temp = scnprintf (next, size, | 657 | temp = scnprintf (next, size, |
| 656 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 658 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
| 659 | "%s\n" | ||
| 657 | "EHCI %x.%02x, hcd state %d\n", | 660 | "EHCI %x.%02x, hcd state %d\n", |
| 658 | hcd->self.controller->bus->name, | 661 | hcd->self.controller->bus->name, |
| 659 | hcd->self.controller->bus_id, | 662 | hcd->self.controller->bus_id, |
| 663 | hcd->product_desc, | ||
| 660 | i >> 8, i & 0x0ff, hcd->state); | 664 | i >> 8, i & 0x0ff, hcd->state); |
| 661 | size -= temp; | 665 | size -= temp; |
| 662 | next += temp; | 666 | next += temp; |
| 663 | 667 | ||
| 668 | #ifdef CONFIG_PCI | ||
| 669 | /* EHCI 0.96 and later may have "extended capabilities" */ | ||
| 670 | if (hcd->self.controller->bus == &pci_bus_type) { | ||
| 671 | struct pci_dev *pdev; | ||
| 672 | u32 offset, cap, cap2; | ||
| 673 | unsigned count = 256/4; | ||
| 674 | |||
| 675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
| 676 | offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | ||
| 677 | while (offset && count--) { | ||
| 678 | pci_read_config_dword (pdev, offset, &cap); | ||
| 679 | switch (cap & 0xff) { | ||
| 680 | case 1: | ||
| 681 | temp = scnprintf (next, size, | ||
| 682 | "ownership %08x%s%s\n", cap, | ||
| 683 | (cap & (1 << 24)) ? " linux" : "", | ||
| 684 | (cap & (1 << 16)) ? " firmware" : ""); | ||
| 685 | size -= temp; | ||
| 686 | next += temp; | ||
| 687 | |||
| 688 | offset += 4; | ||
| 689 | pci_read_config_dword (pdev, offset, &cap2); | ||
| 690 | temp = scnprintf (next, size, | ||
| 691 | "SMI sts/enable 0x%08x\n", cap2); | ||
| 692 | size -= temp; | ||
| 693 | next += temp; | ||
| 694 | break; | ||
| 695 | case 0: /* illegal reserved capability */ | ||
| 696 | cap = 0; | ||
| 697 | /* FALLTHROUGH */ | ||
| 698 | default: /* unknown */ | ||
| 699 | break; | ||
| 700 | } | ||
| 701 | temp = (cap >> 8) & 0xff; | ||
| 702 | } | ||
| 703 | } | ||
| 704 | #endif | ||
| 705 | |||
| 664 | // FIXME interpret both types of params | 706 | // FIXME interpret both types of params |
| 665 | i = readl (&ehci->caps->hcs_params); | 707 | i = readl (&ehci->caps->hcs_params); |
| 666 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); | 708 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); |
| @@ -696,12 +738,19 @@ show_registers (struct class_device *class_dev, char *buf) | |||
| 696 | size -= temp; | 738 | size -= temp; |
| 697 | next += temp; | 739 | next += temp; |
| 698 | 740 | ||
| 699 | for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) { | 741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { |
| 700 | temp = dbg_port_buf (scratch, sizeof scratch, label, i + 1, | 742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, |
| 701 | readl (&ehci->regs->port_status [i])); | 743 | readl (&ehci->regs->port_status [i - 1])); |
| 702 | temp = scnprintf (next, size, fmt, temp, scratch); | 744 | temp = scnprintf (next, size, fmt, temp, scratch); |
| 703 | size -= temp; | 745 | size -= temp; |
| 704 | next += temp; | 746 | next += temp; |
| 747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { | ||
| 748 | temp = scnprintf (next, size, | ||
| 749 | " debug control %08x\n", | ||
| 750 | readl (&ehci->debug->control)); | ||
| 751 | size -= temp; | ||
| 752 | next += temp; | ||
| 753 | } | ||
| 705 | } | 754 | } |
| 706 | 755 | ||
| 707 | if (ehci->reclaim) { | 756 | if (ehci->reclaim) { |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 527abc693b17..35248a37b717 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -304,30 +304,31 @@ static void ehci_watchdog (unsigned long param) | |||
| 304 | */ | 304 | */ |
| 305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) | 305 | static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap) |
| 306 | { | 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 */ | ||
| 307 | if (cap & (1 << 16)) { | 313 | if (cap & (1 << 16)) { |
| 308 | int msec = 5000; | 314 | int msec = 5000; |
| 309 | struct pci_dev *pdev = | ||
| 310 | to_pci_dev(ehci_to_hcd(ehci)->self.controller); | ||
| 311 | 315 | ||
| 312 | /* request handoff to OS */ | ||
| 313 | cap |= 1 << 24; | ||
| 314 | pci_write_config_dword(pdev, where, cap); | ||
| 315 | |||
| 316 | /* and wait a while for it to happen */ | ||
| 317 | do { | 316 | do { |
| 318 | msleep(10); | 317 | msleep(10); |
| 319 | msec -= 10; | 318 | msec -= 10; |
| 320 | pci_read_config_dword(pdev, where, &cap); | 319 | pci_read_config_dword(pdev, where, &cap); |
| 321 | } while ((cap & (1 << 16)) && msec); | 320 | } while ((cap & (1 << 16)) && msec); |
| 322 | if (cap & (1 << 16)) { | 321 | if (cap & (1 << 16)) { |
| 323 | ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", | 322 | ehci_err(ehci, "BIOS handoff failed (%d, %08x)\n", |
| 324 | where, cap); | 323 | where, cap); |
| 325 | // some BIOS versions seem buggy... | 324 | // some BIOS versions seem buggy... |
| 326 | // return 1; | 325 | // return 1; |
| 327 | ehci_warn (ehci, "continuing after BIOS bug...\n"); | 326 | ehci_warn (ehci, "continuing after BIOS bug...\n"); |
| 328 | return 0; | 327 | /* disable all SMIs, and clear "BIOS owns" flag */ |
| 329 | } | 328 | pci_write_config_dword(pdev, where + 4, 0); |
| 330 | ehci_dbg (ehci, "BIOS handoff succeeded\n"); | 329 | pci_write_config_byte(pdev, where + 2, 0); |
| 330 | } else | ||
| 331 | ehci_dbg(ehci, "BIOS handoff succeeded\n"); | ||
| 331 | } | 332 | } |
| 332 | return 0; | 333 | return 0; |
| 333 | } | 334 | } |
| @@ -586,8 +587,8 @@ static int ehci_start (struct usb_hcd *hcd) | |||
| 586 | writel (0, &ehci->regs->segment); | 587 | writel (0, &ehci->regs->segment); |
| 587 | #if 0 | 588 | #if 0 |
| 588 | // this is deeply broken on almost all architectures | 589 | // this is deeply broken on almost all architectures |
| 589 | if (!pci_set_dma_mask (to_pci_dev(hcd->self.controller), 0xffffffffffffffffULL)) | 590 | if (!dma_set_mask (hcd->self.controller, DMA_64BIT_MASK)) |
| 590 | ehci_info (ehci, "enabled 64bit PCI DMA\n"); | 591 | ehci_info (ehci, "enabled 64bit DMA\n"); |
| 591 | #endif | 592 | #endif |
| 592 | } | 593 | } |
| 593 | 594 | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d7b4f7939ded..36cc1f2218d5 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 7df9b9af54f6..45d89a7083b1 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2001-2002 by David Brownell | 2 | * Copyright (C) 2001-2004 by David Brownell |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
