This patch starts decoupling xhci core from PCI. Although we still have a lot to do, this shows how things will look like after the conversion is finished. Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- drivers/usb/host/Makefile | 7 ++- drivers/usb/host/xhci-pci.c | 144 ++++++++++++++++++++++++++----------------- drivers/usb/host/xhci.c | 22 +++---- drivers/usb/host/xhci.h | 6 -- 4 files changed, 102 insertions(+), 77 deletions(-) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 624a362..92357af 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -11,7 +11,7 @@ fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o -xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o +xhci-hcd-y := xhci.o xhci-mem.o xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o obj-$(CONFIG_USB_WHCI_HCD) += whci/ @@ -26,6 +26,11 @@ obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o + +ifneq ($(CONFIG_PCI),) + obj-$(CONFIG_USB_XHCI_HCD) += xhci-pci.o +endif + obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index da7bde8..7128306 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -22,6 +22,7 @@ #include <linux/pci.h> #include <linux/slab.h> +#include <linux/platform_device.h> #include "xhci.h" @@ -32,7 +33,10 @@ #define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_DEVICE_ID_ASROCK_P67 0x7023 -static const char hcd_name[] = "xhci_hcd"; +struct xhci_pci { + struct device *dev; + struct platform_device *xhci; +}; /* called after powerup, by probe or system-pm "wakeup" */ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) @@ -149,80 +153,104 @@ error: static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int retval; - struct xhci_hcd *xhci; - const struct hc_driver *driver; - struct usb_hcd *hcd; - struct xhci_platform_data *data; + struct xhci_platform_data *data; + struct xhci_pci *glue; + struct platform_device *xhci; + struct resource res[2]; + int ret = -ENOMEM; data = (struct xhci_platform_data *) id->driver_data; - driver = data->driver; - - /* Register the USB 2.0 roothub. - * FIXME: USB core must know to register the USB 2.0 roothub first. - * This is sort of silly, because we could just set the HCD driver flags - * to say USB 2.0, but I'm not sure what the implications would be in - * the other parts of the HCD code. - */ - retval = usb_hcd_pci_probe(dev, id); - if (retval) - return retval; + glue = kzalloc(sizeof(*glue), GFP_KERNEL); + if (!glue) { + dev_err(&dev->dev, "failed to allocate glue\n"); + goto err0; + } - /* USB 2.0 roothub is stored in the PCI device now. */ - hcd = dev_get_drvdata(&dev->dev); - xhci = hcd_to_xhci(hcd); + ret = pci_enable_device(dev); + if (ret) { + dev_err(&dev->dev, "failed to enable pci device\n"); + goto err1; + } /* Quirk on revision 0 of Fresco Logic's PDK */ if (dev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && dev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { - if (dev->revision == 0x0) { + if (dev->revision == 0x0) data->quirks |= XHCI_RESET_EP_QUIRK; - xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" - " endpoint cmd after reset endpoint\n"); - } } - xhci->quirks = data->quirks; - xhci->limit_active_eps = data->limit_active_eps; + pci_set_power_state(dev, PCI_D0); + pci_set_master(dev); - xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, - pci_name(dev), hcd); - if (!xhci->shared_hcd) { - retval = -ENOMEM; - goto dealloc_usb2_hcd; + xhci = platform_device_alloc("xhci-pci", -1); + if (!xhci) { + dev_err(&dev->dev, "couldn't allocate xhci device\n"); + goto err2; } - /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) - * is called by usb_add_hcd(). - */ - *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; + pci_set_drvdata(dev, glue); + + memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); + + res[0].start = pci_resource_start(dev, 0); + res[0].end = pci_resource_end(dev, 0); + res[0].name = "xhci"; + res[0].flags = IORESOURCE_MEM; + res[1].start = dev->irq; + res[1].name = "xhci"; + res[1].flags = IORESOURCE_IRQ; + + ret = platform_device_add_resources(xhci, res, ARRAY_SIZE(res)); + if (ret) { + dev_err(&dev->dev, "couldn't add resources to xhci device\n"); + goto err3; + } + + dma_set_coherent_mask(&xhci->dev, dev->dev.coherent_dma_mask); + + xhci->dev.dma_mask = dev->dev.dma_mask; + xhci->dev.dma_parms = dev->dev.dma_parms; + xhci->dev.parent = &dev->dev; + glue->dev = &dev->dev; + glue->xhci = xhci; + + ret = platform_device_add_data(xhci, data, sizeof(*data)); + if (ret) { + dev_err(&dev->dev, "failed to add platform data\n"); + goto err3; + } + + ret = platform_device_add(xhci); + if (ret) { + dev_err(&dev->dev, "failed to register xhci device\n"); + goto err3; + } - retval = usb_add_hcd(xhci->shared_hcd, dev->irq, - IRQF_DISABLED | IRQF_SHARED); - if (retval) - goto put_usb3_hcd; - /* Roothub already marked as USB 3.0 speed */ return 0; -put_usb3_hcd: - usb_put_hcd(xhci->shared_hcd); -dealloc_usb2_hcd: - usb_hcd_pci_remove(dev); - return retval; +err3: + pci_set_drvdata(dev, NULL); + platform_device_put(xhci); + +err2: + pci_disable_device(dev); + +err1: + kfree(glue); + +err0: + return ret; } static void xhci_pci_remove(struct pci_dev *dev) { - struct xhci_hcd *xhci; + struct xhci_pci *glue = pci_get_drvdata(dev); - xhci = hcd_to_xhci(pci_get_drvdata(dev)); - if (xhci->shared_hcd) { - usb_remove_hcd(xhci->shared_hcd); - usb_put_hcd(xhci->shared_hcd); - } - usb_hcd_pci_remove(dev); - kfree(xhci); + platform_device_unregister(glue->xhci); + pci_set_drvdata(dev, NULL); + pci_disable_device(dev); + kfree(glue); } #ifdef CONFIG_PM @@ -271,7 +299,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) #endif /* CONFIG_PM */ static const struct hc_driver xhci_pci_hc_driver = { - .description = hcd_name, + .description = "xhci-pci", .product_desc = "xHCI Host Controller", .hcd_priv_size = sizeof(struct xhci_hcd *), @@ -393,7 +421,7 @@ MODULE_DEVICE_TABLE(pci, pci_ids); /* pci driver glue; this is a "new style" PCI driver module */ static struct pci_driver xhci_pci_driver = { - .name = (char *) hcd_name, + .name = "xhci-pci", .id_table = pci_ids, .probe = xhci_pci_probe, @@ -408,12 +436,14 @@ static struct pci_driver xhci_pci_driver = { #endif }; -int xhci_register_pci(void) +static int xhci_register_pci(void) { return pci_register_driver(&xhci_pci_driver); } +module_init(xhci_register_pci); -void xhci_unregister_pci(void) +static void xhci_unregister_pci(void) { pci_unregister_driver(&xhci_pci_driver); } +module_exit(xhci_unregister_pci); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7ef32c8..08b64ef 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3166,26 +3166,25 @@ static int __devexit xhci_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id xhci_id_table[] __devinitconst = { + { + .name = "xhci-pci", + }, + { }, /* Terminating Entry */ +}; +MODULE_DEVICE_TABLE(platform, xhci_id_table); + static struct platform_driver xhci_driver = { .probe = xhci_probe, .remove = __devexit_p(xhci_remove), .driver = { .name = "xhci", }, + .id_table = xhci_id_table, }; static int __init xhci_hcd_init(void) { -#ifdef CONFIG_PCI - int retval = 0; - - retval = xhci_register_pci(); - - if (retval < 0) { - printk(KERN_DEBUG "Problem registering PCI driver."); - return retval; - } -#endif /* * Check the compiler generated sizes of structures that must be laid * out in specific ways for hardware access. @@ -3211,9 +3210,6 @@ module_init(xhci_hcd_init); static void __exit xhci_hcd_cleanup(void) { -#ifdef CONFIG_PCI - xhci_unregister_pci(); -#endif platform_driver_unregister(&xhci_driver); } module_exit(xhci_hcd_cleanup); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 1065018..16e08ed 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1481,12 +1481,6 @@ void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv); void xhci_free_command(struct xhci_hcd *xhci, struct xhci_command *command); -#ifdef CONFIG_PCI -/* xHCI PCI glue */ -int xhci_register_pci(void); -void xhci_unregister_pci(void); -#endif - /* xHCI host controller glue */ void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); -- 1.7.6 -- 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