Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xhci-pci: Make xhci-pci-renesas a proper modular driver

If CONFIG_USB_XHCI_PCI_RENESAS is enabled, xhci-pci conditionally
calls into the xhci-pci-renesas module, which means both modules must
be loaded to use any xHCI PCI controller.

The MODULE_FIRMWARE declaration in the base xhci-pci module causes
initramfs-tools to check for and warn about missing firmware for the
Renesas xHCI controllers, when any xHCI PCI controller is present.
And because of the previous oddity, simply moving this declaration to
xhci-pci-renesas wouldn't help.

To fix this, reverse the relationship between the modules:

- Remove the quirk for the Renesas xHCIs, and the driver_data
structure used only for them
- In xhci-pci:
- Rename xhci_pci_probe() to xhci_pci_common_probe()
- Export xhci_pci_common_probe() and xhci_pci_remove()
- Use a new probe function that rejects the Renesas xHCIs and then
calls the common probe function
- In xhci-pci-renesas:
- Stop exporting renesas_xhci_check_request_fw()
- Add a probe function that calls renesas_xhci_check_request_fw()
followed by xhci_pci_common_probe()
- Add and register a new pci_driver matching only the Renesas xHCIs
and using its own probe function, but with other operations the
same as in xhci-pci
- Make CONFIG_USB_XHCI_PCI_RENESAS depend on CONFIG_USB_XHCI_PCI,
not the other way around

Finally, move the MODULE_FIRMWARE declaration to xhci-pci-renesas.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Tested-by: Cyril Brulebois <cyril@debamax.com>
Link: https://lore.kernel.org/r/ZqqfXYRJf7kGaqus@decadent.org.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ben Hutchings and committed by
Greg Kroah-Hartman
25f51b76 f3586024

+64 -64
+1 -1
drivers/usb/host/Kconfig
··· 40 40 config USB_XHCI_PCI 41 41 tristate 42 42 depends on USB_PCI 43 - depends on USB_XHCI_PCI_RENESAS || !USB_XHCI_PCI_RENESAS 44 43 default y 45 44 46 45 config USB_XHCI_PCI_RENESAS 47 46 tristate "Support for additional Renesas xHCI controller with firmware" 47 + depends on USB_XHCI_PCI 48 48 help 49 49 Say 'Y' to enable the support for the Renesas xHCI controller with 50 50 firmware. Make sure you have the firmware for the device and
+41 -7
drivers/usb/host/xhci-pci-renesas.c
··· 50 50 #define RENESAS_RETRY 10000 51 51 #define RENESAS_DELAY 10 52 52 53 + #define RENESAS_FW_NAME "renesas_usb_fw.mem" 54 + 53 55 static int renesas_fw_download_image(struct pci_dev *dev, 54 56 const u32 *fw, size_t step, bool rom) 55 57 { ··· 575 573 return err; 576 574 } 577 575 578 - int renesas_xhci_check_request_fw(struct pci_dev *pdev, 579 - const struct pci_device_id *id) 576 + static int renesas_xhci_check_request_fw(struct pci_dev *pdev, 577 + const struct pci_device_id *id) 580 578 { 581 - struct xhci_driver_data *driver_data = 582 - (struct xhci_driver_data *)id->driver_data; 583 - const char *fw_name = driver_data->firmware; 579 + const char fw_name[] = RENESAS_FW_NAME; 584 580 const struct firmware *fw; 585 581 bool has_rom; 586 582 int err; ··· 625 625 release_firmware(fw); 626 626 return err; 627 627 } 628 - EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw); 629 628 630 - MODULE_DESCRIPTION("Support for Renesas xHCI controller with firmware"); 629 + static int 630 + xhci_pci_renesas_probe(struct pci_dev *dev, const struct pci_device_id *id) 631 + { 632 + int retval; 633 + 634 + retval = renesas_xhci_check_request_fw(dev, id); 635 + if (retval) 636 + return retval; 637 + 638 + return xhci_pci_common_probe(dev, id); 639 + } 640 + 641 + static const struct pci_device_id pci_ids[] = { 642 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, 643 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, 644 + { /* end: all zeroes */ } 645 + }; 646 + MODULE_DEVICE_TABLE(pci, pci_ids); 647 + 648 + static struct pci_driver xhci_renesas_pci_driver = { 649 + .name = "xhci-pci-renesas", 650 + .id_table = pci_ids, 651 + 652 + .probe = xhci_pci_renesas_probe, 653 + .remove = xhci_pci_remove, 654 + 655 + .shutdown = usb_hcd_pci_shutdown, 656 + .driver = { 657 + .pm = pm_ptr(&usb_hcd_pci_pm_ops), 658 + }, 659 + }; 660 + module_pci_driver(xhci_renesas_pci_driver); 661 + 662 + MODULE_DESCRIPTION("Renesas xHCI PCI Host Controller Driver"); 663 + MODULE_FIRMWARE(RENESAS_FW_NAME); 664 + MODULE_IMPORT_NS(xhci); 631 665 MODULE_LICENSE("GPL v2");
+19 -38
drivers/usb/host/xhci-pci.c
··· 235 235 static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) 236 236 { 237 237 struct pci_dev *pdev = to_pci_dev(dev); 238 - struct xhci_driver_data *driver_data; 239 - const struct pci_device_id *id; 240 - 241 - id = pci_match_id(to_pci_driver(pdev->dev.driver)->id_table, pdev); 242 - 243 - if (id && id->driver_data) { 244 - driver_data = (struct xhci_driver_data *)id->driver_data; 245 - xhci->quirks |= driver_data->quirks; 246 - } 247 238 248 239 /* Look for vendor-specific quirks */ 249 240 if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && ··· 563 572 * We need to register our own PCI probe function (instead of the USB core's 564 573 * function) in order to create a second roothub under xHCI. 565 574 */ 566 - static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 575 + int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id) 567 576 { 568 577 int retval; 569 578 struct xhci_hcd *xhci; 570 579 struct usb_hcd *hcd; 571 - struct xhci_driver_data *driver_data; 572 580 struct reset_control *reset; 573 - 574 - driver_data = (struct xhci_driver_data *)id->driver_data; 575 - if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) { 576 - retval = renesas_xhci_check_request_fw(dev, id); 577 - if (retval) 578 - return retval; 579 - } 580 581 581 582 reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL); 582 583 if (IS_ERR(reset)) ··· 634 651 pm_runtime_put_noidle(&dev->dev); 635 652 return retval; 636 653 } 654 + EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, xhci); 637 655 638 - static void xhci_pci_remove(struct pci_dev *dev) 656 + static const struct pci_device_id pci_ids_reject[] = { 657 + /* handled by xhci-pci-renesas */ 658 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, 659 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, 660 + { /* end: all zeroes */ } 661 + }; 662 + 663 + static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 664 + { 665 + if (pci_match_id(pci_ids_reject, dev)) 666 + return -ENODEV; 667 + 668 + return xhci_pci_common_probe(dev, id); 669 + } 670 + 671 + void xhci_pci_remove(struct pci_dev *dev) 639 672 { 640 673 struct xhci_hcd *xhci; 641 674 ··· 674 675 675 676 usb_hcd_pci_remove(dev); 676 677 } 678 + EXPORT_SYMBOL_NS_GPL(xhci_pci_remove, xhci); 677 679 678 680 /* 679 681 * In some Intel xHCI controllers, in order to get D3 working, ··· 882 882 883 883 /*-------------------------------------------------------------------------*/ 884 884 885 - static const struct xhci_driver_data reneses_data = { 886 - .quirks = XHCI_RENESAS_FW_QUIRK, 887 - .firmware = "renesas_usb_fw.mem", 888 - }; 889 - 890 885 /* PCI driver selection metadata; PCI hotplugging uses this */ 891 886 static const struct pci_device_id pci_ids[] = { 892 - { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014), 893 - .driver_data = (unsigned long)&reneses_data, 894 - }, 895 - { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015), 896 - .driver_data = (unsigned long)&reneses_data, 897 - }, 898 887 /* handle any USB 3.0 xHCI controller */ 899 888 { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0), 900 889 }, 901 890 { /* end: all zeroes */ } 902 891 }; 903 892 MODULE_DEVICE_TABLE(pci, pci_ids); 904 - 905 - /* 906 - * Without CONFIG_USB_XHCI_PCI_RENESAS renesas_xhci_check_request_fw() won't 907 - * load firmware, so don't encumber the xhci-pci driver with it. 908 - */ 909 - #if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) 910 - MODULE_FIRMWARE("renesas_usb_fw.mem"); 911 - #endif 912 893 913 894 /* pci driver glue; this is a "new style" PCI driver module */ 914 895 static struct pci_driver xhci_pci_driver = {
+2 -17
drivers/usb/host/xhci-pci.h
··· 4 4 #ifndef XHCI_PCI_H 5 5 #define XHCI_PCI_H 6 6 7 - #if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) 8 - int renesas_xhci_check_request_fw(struct pci_dev *dev, 9 - const struct pci_device_id *id); 10 - 11 - #else 12 - static int renesas_xhci_check_request_fw(struct pci_dev *dev, 13 - const struct pci_device_id *id) 14 - { 15 - return 0; 16 - } 17 - 18 - #endif 19 - 20 - struct xhci_driver_data { 21 - u64 quirks; 22 - const char *firmware; 23 - }; 7 + int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id); 8 + void xhci_pci_remove(struct pci_dev *dev); 24 9 25 10 #endif
+1 -1
drivers/usb/host/xhci.h
··· 1616 1616 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) 1617 1617 #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) 1618 1618 #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) 1619 - #define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) 1619 + /* Reserved. It was XHCI_RENESAS_FW_QUIRK */ 1620 1620 #define XHCI_SKIP_PHY_INIT BIT_ULL(37) 1621 1621 #define XHCI_DISABLE_SPARSE BIT_ULL(38) 1622 1622 #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)