Re: OHCI_QUIRK_SHUTDOWN checked against PCI device ID

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

 



You should use Reply-To-All so that your messages get sent to the 
mailing list as well as to me.

On Tue, 18 Oct 2011, Arno Augustin wrote:

> Hi Alan,
> 
> thank's for your answer :-)
> Yes, I think without having detailed information about nvidia
> controllers a sysfs attribute would be the best way to deal with the
> problem.
> But even if the kernel checks device IDs itself it would be more
> flexible to have the ability to write the ohci flags via sysfs....

Well, here's a patch that adds both a blacklist and a sysfs file called
shutdown_quirk in the directories for the OHCI controller devices.

I can't test it very well because I don't have NVIDIA hardware.

Alan Stern



 drivers/usb/host/ohci-pci.c |   67 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 61 insertions(+), 6 deletions(-)

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