Re: USB modem device not working.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 25 Oct 2011, OBD wrote:

> On 24 October 2011 19:42, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> > I'd say the problem is in the controller. �What output do you get from
> > "lspci" and "lspci -n"?
> 
> 
> Here are the two lspci outputs,
> 
> 
> # lspci
...
> 00:02.0 USB Controller: nVidia Corporation MCP67 OHCI USB 1.1
> Controller (rev a2)
> 00:02.1 USB Controller: nVidia Corporation MCP67 EHCI USB 2.0
> Controller (rev a2)
> 00:04.0 USB Controller: nVidia Corporation MCP67 OHCI USB 1.1
> Controller (rev a2)
> 00:04.1 USB Controller: nVidia Corporation MCP67 EHCI USB 2.0
> Controller (rev a2)
...

> # lspci -n
...
> 00:02.0 0c03: 10de:055e (rev a2)
> 00:02.1 0c03: 10de:055f (rev a2)
> 00:04.0 0c03: 10de:055e (rev a2)
> 00:04.1 0c03: 10de:055f (rev a2)
...

Aha!  OHCI controllers from NVIDIA are known to have some weird bugs.  
The kernel tries to work around them, but it doesn't always do a 
perfect job.

Below is a patch you can try out.  It won't fix the problem directly, 
but it will create two new sysfs files for you.  After you boot the new 
kernel, but before attaching the modem, look at:

	/sys/bus/pci/devices/0000:00:02.0/shutdown_quirk
	/sys/bus/pci/devices/0000:00:04.0/shutdown_quirk

I expect each of them will contain a 0.  Try writing a 1 into each and 
then see how the modem behaves.

Alan Stern



Index: usb-3.1/drivers/usb/host/ohci-pci.c
===================================================================
--- usb-3.1.orig/drivers/usb/host/ohci-pci.c
+++ usb-3.1/drivers/usb/host/ohci-pci.c
@@ -175,7 +175,46 @@ static int ohci_quirk_amd700(struct usb_
 	return 0;
 }
 
-/* nVidia controllers continue to drive Reset signalling on the bus
+/* Control the OHCI_QUIRK_SHUTDOWN setting */
+static ssize_t show_shutdown_quirk(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(bus_to_hcd(dev_get_drvdata(dev)));
+
+	return sprintf(buf, "%d\n", !!(ohci->flags & OHCI_QUIRK_SHUTDOWN));
+}
+
+static ssize_t store_shutdown_quirk(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct ohci_hcd *ohci = hcd_to_ohci(bus_to_hcd(dev_get_drvdata(dev)));
+	int v, rc;
+
+	rc = kstrtoint(buf, 0, &v);
+	if (rc)
+		return rc;
+	if (v == 1)
+		ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+	else if (v == 0)
+		ohci->flags &= ~OHCI_QUIRK_SHUTDOWN;
+	else
+		return -ERANGE;
+	return count;
+}
+static DEVICE_ATTR(shutdown_quirk, 0644, show_shutdown_quirk,
+		store_shutdown_quirk);
+
+/*
+ * NVIDIA product IDs not identified correctly by the code below.
+ * Keep this list sorted in numeric order.
+ */
+static u16 nvidia_blacklist[] = {
+	0x077b, 0x077d,		/* MCP78S */
+	0			/* Terminating entry */
+};
+
+/*
+ * Some NVIDIA controllers continue to drive Reset signalling on the bus
  * even after system shutdown, wasting power.  This flag tells the
  * shutdown routine to leave the controller OPERATIONAL instead of RESET.
  */
@@ -183,18 +222,28 @@ static int ohci_quirk_nvidia_shutdown(st
 {
 	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	u16 *p;
 
-	/* Evidently nVidia fixed their later hardware; this is a guess at
+	/* Evidently NVIDIA fixed their later hardware; this is a guess at
 	 * the changeover point.
 	 */
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB		0x026d
 
-	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
+	if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB)
 		ohci->flags |= OHCI_QUIRK_SHUTDOWN;
-		ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
+
+	/* Check against the blacklist */
+	for (p = nvidia_blacklist; *p; ++p) {
+		if (*p == pdev->device) {
+			ohci->flags ^= OHCI_QUIRK_SHUTDOWN;
+			break;
+		}
 	}
+	if (ohci->flags & OHCI_QUIRK_SHUTDOWN)
+		ohci_dbg(ohci, "enabled NVIDIA shutdown quirk\n");
 
-	return 0;
+	return device_create_file(hcd->self.controller,
+			&dev_attr_shutdown_quirk);
 }
 
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
@@ -322,6 +371,12 @@ static int __devinit ohci_pci_start (str
 	return ret;
 }
 
+static void ohci_pci_stop(struct usb_hcd *hcd)
+{
+	device_remove_file(hcd->self.controller, &dev_attr_shutdown_quirk);
+	ohci_stop(hcd);
+}
+
 #ifdef	CONFIG_PM
 
 static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
@@ -387,7 +442,7 @@ static const struct hc_driver ohci_pci_h
 	 */
 	.reset =		ohci_pci_reset,
 	.start =		ohci_pci_start,
-	.stop =			ohci_stop,
+	.stop =			ohci_pci_stop,
 	.shutdown =		ohci_shutdown,
 
 #ifdef	CONFIG_PM

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux