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 /drivers/usb/host | |
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>
Diffstat (limited to 'drivers/usb/host')
-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 |