On Saturday 09 December 2006 12:26 am, Benjamin Herrenschmidt wrote:
> This patch applies David Brownell's suggestion for reworking the
> OHCI quirk mecanism via a table of PCI IDs. It adapts the existing
> quirks to use that mecanism.
"mechanism". :)
Thanks for doing this.
> This also moves the quirks to reset() as suggested by the comment
> in there. This is necessary as we need to have the endian properly
> set before we try to init the controller.
>
> Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
Acked-by: David Brownell <[EMAIL PROTECTED]>
>
> drivers/usb/host/ohci-pci.c | 173
> +++++++++++++++++++++++++++-----------------
> 1 file changed, 110 insertions(+), 63 deletions(-)
>
> Index: linux-work/drivers/usb/host/ohci-pci.c
> ===================================================================
> --- linux-work.orig/drivers/usb/host/ohci-pci.c 2006-12-09
> 19:14:30.000000000 +1100
> +++ linux-work/drivers/usb/host/ohci-pci.c 2006-12-09 19:23:37.000000000
> +1100
> @@ -20,79 +20,128 @@
>
> /*-------------------------------------------------------------------------*/
>
> -static int
> -ohci_pci_reset (struct usb_hcd *hcd)
> +/* AMD 756, for most chips (early revs), corrupts register
> + * values on read ... so enable the vendor workaround.
> + */
> +static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd)
> {
> struct ohci_hcd *ohci = hcd_to_ohci (hcd);
>
> - ohci_hcd_init (ohci);
> - return ohci_init (ohci);
> + ohci->flags = OHCI_QUIRK_AMD756;
> + ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
> +
> + /* also erratum 10 (suspend/resume issues) */
> + device_init_wakeup(&hcd->self.root_hub->dev, 0);
> +
> + return 0;
> }
>
> -static int __devinit
> -ohci_pci_start (struct usb_hcd *hcd)
> +/* Apple's OHCI driver has a lot of bizarre workarounds
> + * for this chip. Evidently control and bulk lists
> + * can get confused. (B&W G3 models, and ...)
> + */
> +static int __devinit ohci_quirk_opti(struct usb_hcd *hcd)
> {
> struct ohci_hcd *ohci = hcd_to_ohci (hcd);
> - int ret;
>
> - /* REVISIT this whole block should move to reset(), which handles
> - * all the other one-time init.
> + ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n");
> +
> + return 0;
> +}
> +
> +/* Check for NSC87560. We have to look at the bridge (fn1) to
> + * identify the USB (fn2). This quirk might apply to more or
> + * even all NSC stuff.
> + */
> +static int __devinit ohci_quirk_ns(struct usb_hcd *hcd)
> +{
> + struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
> + struct pci_dev *b;
> +
> + b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
> + if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
> + && b->vendor == PCI_VENDOR_ID_NS) {
> + struct ohci_hcd *ohci = hcd_to_ohci (hcd);
> +
> + ohci->flags |= OHCI_QUIRK_SUPERIO;
> + ohci_dbg (ohci, "Using NSC SuperIO setup\n");
> + }
> + pci_dev_put(b);
> +
> + return 0;
> +}
> +
> +/* Check for Compaq's ZFMicro chipset, which needs short
> + * delays before control or bulk queues get re-activated
> + * in finish_unlinks()
> + */
> +static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
> +{
> + struct ohci_hcd *ohci = hcd_to_ohci (hcd);
> +
> + ohci->flags |= OHCI_QUIRK_ZFMICRO;
> + ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n");
> +
> + return 0;
> +}
> +
> +
> +/* List of quirks for OHCI */
> +static const struct pci_device_id ohci_pci_quirks[] = {
> + {
> + PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c),
> + .driver_data = (unsigned long)ohci_quirk_amd756,
> + },
> + {
> + PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861),
> + .driver_data = (unsigned long)ohci_quirk_opti,
> + },
> + {
> + PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID),
> + .driver_data = (unsigned long)ohci_quirk_ns,
> + },
> + {
> + PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
> + .driver_data = (unsigned long)ohci_quirk_zfmicro,
> + },
> + /* FIXME for some of the early AMD 760 southbridges, OHCI
> + * won't work at all. blacklist them.
> */
> - if (hcd->self.controller) {
> - struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
> + {},
> +};
>
> - /* AMD 756, for most chips (early revs), corrupts register
> - * values on read ... so enable the vendor workaround.
> - */
> - if (pdev->vendor == PCI_VENDOR_ID_AMD
> - && pdev->device == 0x740c) {
> - ohci->flags = OHCI_QUIRK_AMD756;
> - ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
> - /* also erratum 10 (suspend/resume issues) */
> - device_init_wakeup(&hcd->self.root_hub->dev, 0);
> - }
> +static int ohci_pci_reset (struct usb_hcd *hcd)
> +{
> + struct ohci_hcd *ohci = hcd_to_ohci (hcd);
> + int ret = 0;
>
> - /* FIXME for some of the early AMD 760 southbridges, OHCI
> - * won't work at all. blacklist them.
> - */
> + if (hcd->self.controller) {
> + struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
> + const struct pci_device_id *quirk_id;
>
> - /* Apple's OHCI driver has a lot of bizarre workarounds
> - * for this chip. Evidently control and bulk lists
> - * can get confused. (B&W G3 models, and ...)
> - */
> - else if (pdev->vendor == PCI_VENDOR_ID_OPTI
> - && pdev->device == 0xc861) {
> - ohci_dbg (ohci,
> - "WARNING: OPTi workarounds unavailable\n");
> + quirk_id = pci_match_id(ohci_pci_quirks, pdev);
> + if (quirk_id != NULL) {
> + int (*quirk)(struct ohci_hcd *ohci);
> + quirk = (void *)quirk_id->driver_data;
> + ret = quirk(ohci);
> }
> + }
> + if (ret == 0) {
> + ohci_hcd_init (ohci);
> + return ohci_init (ohci);
> + }
> + return ret;
> +}
>
> - /* Check for NSC87560. We have to look at the bridge (fn1) to
> - * identify the USB (fn2). This quirk might apply to more or
> - * even all NSC stuff.
> - */
> - else if (pdev->vendor == PCI_VENDOR_ID_NS) {
> - struct pci_dev *b;
>
> - b = pci_get_slot (pdev->bus,
> - PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
> - if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
> - && b->vendor == PCI_VENDOR_ID_NS) {
> - ohci->flags |= OHCI_QUIRK_SUPERIO;
> - ohci_dbg (ohci, "Using NSC SuperIO setup\n");
> - }
> - pci_dev_put(b);
> - }
> +static int __devinit ohci_pci_start (struct usb_hcd *hcd)
> +{
> + struct ohci_hcd *ohci = hcd_to_ohci (hcd);
> + int ret;
>
> - /* Check for Compaq's ZFMicro chipset, which needs short
> - * delays before control or bulk queues get re-activated
> - * in finish_unlinks()
> - */
> - else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ
> - && pdev->device == 0xa0f8) {
> - ohci->flags |= OHCI_QUIRK_ZFMICRO;
> - ohci_dbg (ohci,
> - "enabled Compaq ZFMicro chipset quirk\n");
> - }
> +#ifdef CONFIG_PM /* avoid warnings about unused pdev */
> + if (hcd->self.controller) {
> + struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
>
> /* RWC may not be set for add-in PCI cards, since boot
> * firmware probably ignored them. This transfers PCI
> @@ -101,16 +150,14 @@
> if (device_may_wakeup(&pdev->dev))
> ohci->hc_control |= OHCI_CTRL_RWC;
> }
> +#endif /* CONFIG_PM */
>
> - /* NOTE: there may have already been a first reset, to
> - * keep bios/smm irqs from making trouble
> - */
> - if ((ret = ohci_run (ohci)) < 0) {
> + ret = ohci_run (ohci);
> + if (ret < 0) {
> ohci_err (ohci, "can't start\n");
> ohci_stop (hcd);
> - return ret;
> }
> - return 0;
> + return ret;
> }
>
> #ifdef CONFIG_PM
>
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel