41e310d89c0f03945c5397b2036acb01319ab43a
[openwrt/staging/xback.git] /
1 From 25f51b76f90f10f9bf2fbc05fc51cf685da7ccad Mon Sep 17 00:00:00 2001
2 From: Ben Hutchings <ben@decadent.org.uk>
3 Date: Wed, 31 Jul 2024 22:32:29 +0200
4 Subject: [PATCH] xhci-pci: Make xhci-pci-renesas a proper modular driver
5
6 If CONFIG_USB_XHCI_PCI_RENESAS is enabled, xhci-pci conditionally
7 calls into the xhci-pci-renesas module, which means both modules must
8 be loaded to use any xHCI PCI controller.
9
10 The MODULE_FIRMWARE declaration in the base xhci-pci module causes
11 initramfs-tools to check for and warn about missing firmware for the
12 Renesas xHCI controllers, when any xHCI PCI controller is present.
13 And because of the previous oddity, simply moving this declaration to
14 xhci-pci-renesas wouldn't help.
15
16 To fix this, reverse the relationship between the modules:
17
18 - Remove the quirk for the Renesas xHCIs, and the driver_data
19 structure used only for them
20 - In xhci-pci:
21 - Rename xhci_pci_probe() to xhci_pci_common_probe()
22 - Export xhci_pci_common_probe() and xhci_pci_remove()
23 - Use a new probe function that rejects the Renesas xHCIs and then
24 calls the common probe function
25 - In xhci-pci-renesas:
26 - Stop exporting renesas_xhci_check_request_fw()
27 - Add a probe function that calls renesas_xhci_check_request_fw()
28 followed by xhci_pci_common_probe()
29 - Add and register a new pci_driver matching only the Renesas xHCIs
30 and using its own probe function, but with other operations the
31 same as in xhci-pci
32 - Make CONFIG_USB_XHCI_PCI_RENESAS depend on CONFIG_USB_XHCI_PCI,
33 not the other way around
34
35 Finally, move the MODULE_FIRMWARE declaration to xhci-pci-renesas.
36
37 Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
38 Tested-by: Cyril Brulebois <cyril@debamax.com>
39 Link: https://lore.kernel.org/r/ZqqfXYRJf7kGaqus@decadent.org.uk
40 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
41 ---
42 drivers/usb/host/Kconfig | 2 +-
43 drivers/usb/host/xhci-pci-renesas.c | 48 ++++++++++++++++++++----
44 drivers/usb/host/xhci-pci.c | 57 ++++++++++-------------------
45 drivers/usb/host/xhci-pci.h | 19 +---------
46 drivers/usb/host/xhci.h | 2 +-
47 5 files changed, 64 insertions(+), 64 deletions(-)
48
49 --- a/drivers/usb/host/Kconfig
50 +++ b/drivers/usb/host/Kconfig
51 @@ -40,11 +40,11 @@ config USB_XHCI_DBGCAP
52 config USB_XHCI_PCI
53 tristate
54 depends on USB_PCI
55 - depends on USB_XHCI_PCI_RENESAS || !USB_XHCI_PCI_RENESAS
56 default y
57
58 config USB_XHCI_PCI_RENESAS
59 tristate "Support for additional Renesas xHCI controller with firmware"
60 + depends on USB_XHCI_PCI
61 help
62 Say 'Y' to enable the support for the Renesas xHCI controller with
63 firmware. Make sure you have the firmware for the device and
64 --- a/drivers/usb/host/xhci-pci-renesas.c
65 +++ b/drivers/usb/host/xhci-pci-renesas.c
66 @@ -51,6 +51,8 @@
67 #define RENESAS_CHIP_ERASE_RETRY 500000 /* 500000 * RENESAS_DELAY ~= 5s */
68 #define RENESAS_DELAY 10
69
70 +#define RENESAS_FW_NAME "renesas_usb_fw.mem"
71 +
72 static int renesas_fw_download_image(struct pci_dev *dev,
73 const u32 *fw, size_t step, bool rom)
74 {
75 @@ -574,12 +576,10 @@ exit:
76 return err;
77 }
78
79 -int renesas_xhci_check_request_fw(struct pci_dev *pdev,
80 - const struct pci_device_id *id)
81 +static int renesas_xhci_check_request_fw(struct pci_dev *pdev,
82 + const struct pci_device_id *id)
83 {
84 - struct xhci_driver_data *driver_data =
85 - (struct xhci_driver_data *)id->driver_data;
86 - const char *fw_name = driver_data->firmware;
87 + const char fw_name[] = RENESAS_FW_NAME;
88 const struct firmware *fw;
89 bool has_rom;
90 int err;
91 @@ -626,7 +626,41 @@ exit:
92 release_firmware(fw);
93 return err;
94 }
95 -EXPORT_SYMBOL_GPL(renesas_xhci_check_request_fw);
96
97 -MODULE_DESCRIPTION("Support for Renesas xHCI controller with firmware");
98 +static int
99 +xhci_pci_renesas_probe(struct pci_dev *dev, const struct pci_device_id *id)
100 +{
101 + int retval;
102 +
103 + retval = renesas_xhci_check_request_fw(dev, id);
104 + if (retval)
105 + return retval;
106 +
107 + return xhci_pci_common_probe(dev, id);
108 +}
109 +
110 +static const struct pci_device_id pci_ids[] = {
111 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) },
112 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) },
113 + { /* end: all zeroes */ }
114 +};
115 +MODULE_DEVICE_TABLE(pci, pci_ids);
116 +
117 +static struct pci_driver xhci_renesas_pci_driver = {
118 + .name = "xhci-pci-renesas",
119 + .id_table = pci_ids,
120 +
121 + .probe = xhci_pci_renesas_probe,
122 + .remove = xhci_pci_remove,
123 +
124 + .shutdown = usb_hcd_pci_shutdown,
125 + .driver = {
126 + .pm = pm_ptr(&usb_hcd_pci_pm_ops),
127 + },
128 +};
129 +module_pci_driver(xhci_renesas_pci_driver);
130 +
131 +MODULE_DESCRIPTION("Renesas xHCI PCI Host Controller Driver");
132 +MODULE_FIRMWARE(RENESAS_FW_NAME);
133 +MODULE_IMPORT_NS(xhci);
134 MODULE_LICENSE("GPL v2");
135 --- a/drivers/usb/host/xhci-pci.c
136 +++ b/drivers/usb/host/xhci-pci.c
137 @@ -310,15 +310,6 @@ static int xhci_pci_reinit(struct xhci_h
138 static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
139 {
140 struct pci_dev *pdev = to_pci_dev(dev);
141 - struct xhci_driver_data *driver_data;
142 - const struct pci_device_id *id;
143 -
144 - id = pci_match_id(to_pci_driver(pdev->dev.driver)->id_table, pdev);
145 -
146 - if (id && id->driver_data) {
147 - driver_data = (struct xhci_driver_data *)id->driver_data;
148 - xhci->quirks |= driver_data->quirks;
149 - }
150
151 /* Look for vendor-specific quirks */
152 if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
153 @@ -668,21 +659,13 @@ static int xhci_pci_update_hub_device(st
154 * We need to register our own PCI probe function (instead of the USB core's
155 * function) in order to create a second roothub under xHCI.
156 */
157 -static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
158 +int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
159 {
160 int retval;
161 struct xhci_hcd *xhci;
162 struct usb_hcd *hcd;
163 - struct xhci_driver_data *driver_data;
164 struct reset_control *reset;
165
166 - driver_data = (struct xhci_driver_data *)id->driver_data;
167 - if (driver_data && driver_data->quirks & XHCI_RENESAS_FW_QUIRK) {
168 - retval = renesas_xhci_check_request_fw(dev, id);
169 - if (retval)
170 - return retval;
171 - }
172 -
173 reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL);
174 if (IS_ERR(reset))
175 return PTR_ERR(reset);
176 @@ -747,8 +730,24 @@ put_runtime_pm:
177 pm_runtime_put_noidle(&dev->dev);
178 return retval;
179 }
180 +EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, xhci);
181 +
182 +static const struct pci_device_id pci_ids_reject[] = {
183 + /* handled by xhci-pci-renesas */
184 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) },
185 + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) },
186 + { /* end: all zeroes */ }
187 +};
188 +
189 +static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
190 +{
191 + if (pci_match_id(pci_ids_reject, dev))
192 + return -ENODEV;
193 +
194 + return xhci_pci_common_probe(dev, id);
195 +}
196
197 -static void xhci_pci_remove(struct pci_dev *dev)
198 +void xhci_pci_remove(struct pci_dev *dev)
199 {
200 struct xhci_hcd *xhci;
201 bool set_power_d3;
202 @@ -775,6 +774,7 @@ static void xhci_pci_remove(struct pci_d
203 if (set_power_d3)
204 pci_set_power_state(dev, PCI_D3hot);
205 }
206 +EXPORT_SYMBOL_NS_GPL(xhci_pci_remove, xhci);
207
208 /*
209 * In some Intel xHCI controllers, in order to get D3 working,
210 @@ -984,19 +984,8 @@ static void xhci_pci_shutdown(struct usb
211
212 /*-------------------------------------------------------------------------*/
213
214 -static const struct xhci_driver_data reneses_data = {
215 - .quirks = XHCI_RENESAS_FW_QUIRK,
216 - .firmware = "renesas_usb_fw.mem",
217 -};
218 -
219 /* PCI driver selection metadata; PCI hotplugging uses this */
220 static const struct pci_device_id pci_ids[] = {
221 - { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014),
222 - .driver_data = (unsigned long)&reneses_data,
223 - },
224 - { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015),
225 - .driver_data = (unsigned long)&reneses_data,
226 - },
227 /* handle any USB 3.0 xHCI controller */
228 { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_XHCI, ~0),
229 },
230 @@ -1004,14 +993,6 @@ static const struct pci_device_id pci_id
231 };
232 MODULE_DEVICE_TABLE(pci, pci_ids);
233
234 -/*
235 - * Without CONFIG_USB_XHCI_PCI_RENESAS renesas_xhci_check_request_fw() won't
236 - * load firmware, so don't encumber the xhci-pci driver with it.
237 - */
238 -#if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
239 -MODULE_FIRMWARE("renesas_usb_fw.mem");
240 -#endif
241 -
242 /* pci driver glue; this is a "new style" PCI driver module */
243 static struct pci_driver xhci_pci_driver = {
244 .name = hcd_name,
245 --- a/drivers/usb/host/xhci-pci.h
246 +++ b/drivers/usb/host/xhci-pci.h
247 @@ -4,22 +4,7 @@
248 #ifndef XHCI_PCI_H
249 #define XHCI_PCI_H
250
251 -#if IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS)
252 -int renesas_xhci_check_request_fw(struct pci_dev *dev,
253 - const struct pci_device_id *id);
254 -
255 -#else
256 -static int renesas_xhci_check_request_fw(struct pci_dev *dev,
257 - const struct pci_device_id *id)
258 -{
259 - return 0;
260 -}
261 -
262 -#endif
263 -
264 -struct xhci_driver_data {
265 - u64 quirks;
266 - const char *firmware;
267 -};
268 +int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id);
269 +void xhci_pci_remove(struct pci_dev *dev);
270
271 #endif
272 --- a/drivers/usb/host/xhci.h
273 +++ b/drivers/usb/host/xhci.h
274 @@ -1645,7 +1645,7 @@ struct xhci_hcd {
275 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
276 #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
277 #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
278 -#define XHCI_RENESAS_FW_QUIRK BIT_ULL(36)
279 +/* Reserved. It was XHCI_RENESAS_FW_QUIRK */
280 #define XHCI_SKIP_PHY_INIT BIT_ULL(37)
281 #define XHCI_DISABLE_SPARSE BIT_ULL(38)
282 #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39)