aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-12-05 16:29:55 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-20 13:14:26 -0500
commit5f8364b7d63acdc2216ca0f7d0a8557c318479ea (patch)
tree01f4c0bf84d46659772a623dd591bba7e1f2b635
parentfe1ec341df1b510e5e614ccdad4a89273d6f6fe8 (diff)
UHCI: module parameter to ignore overcurrent changes
Certain boards seem to like to issue false overcurrent notifications, for example on ports that don't have anything connected to them. This looks like a hardware error, at the level of noise to those ports' overcurrent input signals (or non-debounced VBUS comparators). This surfaces to users as truly massive amounts of syslog spam from khubd (which is appropriate for real hardware problems, except for the volume from multiple ports). Using this new "ignore_oc" flag helps such systems work more sanely, by preventing such indications from getting to khubd (and spamming syslog). The downside is of course that true overcurrent errors will be masked; they'll appear as spontaneous disconnects, without the diagnostics that will let users troubleshoot issues like short-circuited cables. In addition, controllers with no devices attached will be forced to poll for new devices rather than relying on interrupts, since each overcurrent event would generate a new interrupt. This patch (as826) is essentially a copy of David Brownell's ignore_oc patch for ehci-hcd, ported to uhci-hcd. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--Documentation/kernel-parameters.txt8
-rw-r--r--drivers/usb/host/uhci-hcd.c13
-rw-r--r--drivers/usb/host/uhci-hub.c14
3 files changed, 32 insertions, 3 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ef69c75780bf..25d298517104 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1714,6 +1714,14 @@ and is between 256 and 4096 characters. It is defined in the file
1714 uart6850= [HW,OSS] 1714 uart6850= [HW,OSS]
1715 Format: <io>,<irq> 1715 Format: <io>,<irq>
1716 1716
1717 uhci-hcd.ignore_oc=
1718 [USB] Ignore overcurrent events (default N).
1719 Some badly-designed motherboards generate lots of
1720 bogus events, for ports that aren't wired to
1721 anything. Set this parameter to avoid log spamming.
1722 Note that genuine overcurrent events won't be
1723 reported either.
1724
1717 usbhid.mousepoll= 1725 usbhid.mousepoll=
1718 [USBHID] The interval which mice are to be polled at. 1726 [USBHID] The interval which mice are to be polled at.
1719 1727
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index e87692c31be4..acd101caeeeb 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
60Alan Stern" 60Alan Stern"
61#define DRIVER_DESC "USB Universal Host Controller Interface driver" 61#define DRIVER_DESC "USB Universal Host Controller Interface driver"
62 62
63/* for flakey hardware, ignore overcurrent indicators */
64static int ignore_oc;
65module_param(ignore_oc, bool, S_IRUGO);
66MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
67
63/* 68/*
64 * debug = 0, no debugging messages 69 * debug = 0, no debugging messages
65 * debug = 1, dump failed URBs except for stalls 70 * debug = 1, dump failed URBs except for stalls
@@ -169,6 +174,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
169{ 174{
170 int port; 175 int port;
171 176
177 /* If we have to ignore overcurrent events then almost by definition
178 * we can't depend on resume-detect interrupts. */
179 if (ignore_oc)
180 return 1;
181
172 switch (to_pci_dev(uhci_dev(uhci))->vendor) { 182 switch (to_pci_dev(uhci_dev(uhci))->vendor) {
173 default: 183 default:
174 break; 184 break;
@@ -921,7 +931,8 @@ static int __init uhci_hcd_init(void)
921{ 931{
922 int retval = -ENOMEM; 932 int retval = -ENOMEM;
923 933
924 printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); 934 printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
935 ignore_oc ? ", overcurrent ignored" : "");
925 936
926 if (usb_disabled()) 937 if (usb_disabled())
927 return -ENODEV; 938 return -ENODEV;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index f8347f1a10b6..bacc25c53ba3 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci)
52static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) 52static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
53{ 53{
54 int port; 54 int port;
55 int mask = RWC_BITS;
56
57 /* Some boards (both VIA and Intel apparently) report bogus
58 * overcurrent indications, causing massive log spam unless
59 * we completely ignore them. This doesn't seem to be a problem
60 * with the chipset so much as with the way it is connected on
61 * the motherboard; if the overcurrent input is left to float
62 * then it may constantly register false positives. */
63 if (ignore_oc)
64 mask &= ~USBPORTSC_OCC;
55 65
56 *buf = 0; 66 *buf = 0;
57 for (port = 0; port < uhci->rh_numports; ++port) { 67 for (port = 0; port < uhci->rh_numports; ++port) {
58 if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) || 68 if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
59 test_bit(port, &uhci->port_c_suspend)) 69 test_bit(port, &uhci->port_c_suspend))
60 *buf |= (1 << (port + 1)); 70 *buf |= (1 << (port + 1));
61 } 71 }
@@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
263 wPortChange |= USB_PORT_STAT_C_CONNECTION; 273 wPortChange |= USB_PORT_STAT_C_CONNECTION;
264 if (status & USBPORTSC_PEC) 274 if (status & USBPORTSC_PEC)
265 wPortChange |= USB_PORT_STAT_C_ENABLE; 275 wPortChange |= USB_PORT_STAT_C_ENABLE;
266 if (status & USBPORTSC_OCC) 276 if ((status & USBPORTSC_OCC) && !ignore_oc)
267 wPortChange |= USB_PORT_STAT_C_OVERCURRENT; 277 wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
268 278
269 if (test_bit(port, &uhci->port_c_suspend)) { 279 if (test_bit(port, &uhci->port_c_suspend)) {