Re: OHCI_QUIRK_SHUTDOWN checked against PCI device ID

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

 



Ok,works for my NVIDA board.
The /sys-files contain 1 at startup (matching blacklist)

# find /sys | grep shutdown_quirk
/sys/devices/pci0000:00/0000:00:02.0/shutdown_quirk
/sys/devices/pci0000:00/0000:00:04.0/shutdown_quirk
# find /sys | grep shutdown_quir | xargs cat
1
1

But I had to change a bit because I use a Ubuntu/Lucid 2.6.32 backport
kernel in which kstrtoint is missing. OK this does not really check the
integer value but also works for 0 or 1 as input:

static ssize_t store_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)));

    if (*buf == '1')
        ohci->flags |= OHCI_QUIRK_SHUTDOWN;
    else if (*buf == '0')
        ohci->flags &= ~OHCI_QUIRK_SHUTDOWN;
    else
        return -ERANGE;
    return count;
}


Am 19.10.2011 22:21, schrieb Alan Stern:
> You should use Reply-To-All so that your messages get sent to the 
> mailing list as well as to me.

Sorry....

> 
> 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