f5bf467154a426707cacbba64a4c7709ba5cc428
[openwrt/staging/nbd.git] /
1 From d4806e4f103895387dc679fe53e1f4a5d41391bf Mon Sep 17 00:00:00 2001
2 From: Peter Chen <peter.chen@nxp.com>
3 Date: Thu, 18 Jan 2018 11:03:24 +0800
4 Subject: [PATCH] MLK-17380-3 usb: move EH SINGLE_STEP_SET_FEATURE implement to
5 core
6
7 Since other USB 2.0 host may need it, like USB2 for XHCI. We move
8 this design to HCD core.
9
10 Acked-by: Jun Li <jun.li@nxp.com>
11 Signed-off-by: Peter Chen <peter.chen@nxp.com>
12 (cherry picked from commit 035a27e1a3088261f40f77534aaccfe5825c2f96)
13 ---
14 drivers/usb/core/hcd.c | 134 ++++++++++++++++++++++++++++++++++++++++++
15 drivers/usb/host/ehci-hcd.c | 4 ++
16 drivers/usb/host/ehci-hub.c | 139 --------------------------------------------
17 drivers/usb/host/ehci-q.c | 2 +-
18 include/linux/usb/hcd.h | 13 ++++-
19 5 files changed, 151 insertions(+), 141 deletions(-)
20
21 --- a/drivers/usb/core/hcd.c
22 +++ b/drivers/usb/core/hcd.c
23 @@ -2104,6 +2104,140 @@ int usb_hcd_get_frame_number (struct usb
24 }
25
26 /*-------------------------------------------------------------------------*/
27 +#ifdef CONFIG_USB_HCD_TEST_MODE
28 +
29 +static void usb_ehset_completion(struct urb *urb)
30 +{
31 + struct completion *done = urb->context;
32 +
33 + complete(done);
34 +}
35 +/*
36 + * Allocate and initialize a control URB. This request will be used by the
37 + * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages
38 + * of the GetDescriptor request are sent 15 seconds after the SETUP stage.
39 + * Return NULL if failed.
40 + */
41 +static struct urb *request_single_step_set_feature_urb(
42 + struct usb_device *udev,
43 + void *dr,
44 + void *buf,
45 + struct completion *done
46 +) {
47 + struct urb *urb;
48 + struct usb_hcd *hcd = bus_to_hcd(udev->bus);
49 + struct usb_host_endpoint *ep;
50 +
51 + urb = usb_alloc_urb(0, GFP_KERNEL);
52 + if (!urb)
53 + return NULL;
54 +
55 + urb->pipe = usb_rcvctrlpipe(udev, 0);
56 + ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
57 + [usb_pipeendpoint(urb->pipe)];
58 + if (!ep) {
59 + usb_free_urb(urb);
60 + return NULL;
61 + }
62 +
63 + urb->ep = ep;
64 + urb->dev = udev;
65 + urb->setup_packet = (void *)dr;
66 + urb->transfer_buffer = buf;
67 + urb->transfer_buffer_length = USB_DT_DEVICE_SIZE;
68 + urb->complete = usb_ehset_completion;
69 + urb->status = -EINPROGRESS;
70 + urb->actual_length = 0;
71 + urb->transfer_flags = URB_DIR_IN;
72 + usb_get_urb(urb);
73 + atomic_inc(&urb->use_count);
74 + atomic_inc(&urb->dev->urbnum);
75 + urb->setup_dma = dma_map_single(
76 + hcd->self.sysdev,
77 + urb->setup_packet,
78 + sizeof(struct usb_ctrlrequest),
79 + DMA_TO_DEVICE);
80 + urb->transfer_dma = dma_map_single(
81 + hcd->self.sysdev,
82 + urb->transfer_buffer,
83 + urb->transfer_buffer_length,
84 + DMA_FROM_DEVICE);
85 + urb->context = done;
86 + return urb;
87 +}
88 +
89 +int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
90 +{
91 + int retval = -ENOMEM;
92 + struct usb_ctrlrequest *dr;
93 + struct urb *urb;
94 + struct usb_device *udev;
95 + struct usb_device_descriptor *buf;
96 + DECLARE_COMPLETION_ONSTACK(done);
97 +
98 + /* Obtain udev of the rhub's child port */
99 + udev = usb_hub_find_child(hcd->self.root_hub, port);
100 + if (!udev) {
101 + dev_err(hcd->self.controller, "No device attached to the RootHub\n");
102 + return -ENODEV;
103 + }
104 + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
105 + if (!buf)
106 + return -ENOMEM;
107 +
108 + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
109 + if (!dr) {
110 + kfree(buf);
111 + return -ENOMEM;
112 + }
113 +
114 + /* Fill Setup packet for GetDescriptor */
115 + dr->bRequestType = USB_DIR_IN;
116 + dr->bRequest = USB_REQ_GET_DESCRIPTOR;
117 + dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8);
118 + dr->wIndex = 0;
119 + dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE);
120 + urb = request_single_step_set_feature_urb(udev, dr, buf, &done);
121 + if (!urb)
122 + goto cleanup;
123 +
124 + /* Submit just the SETUP stage */
125 + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 1);
126 + if (retval)
127 + goto out1;
128 + if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
129 + usb_kill_urb(urb);
130 + retval = -ETIMEDOUT;
131 + dev_err(hcd->self.controller,
132 + "%s SETUP stage timed out on ep0\n", __func__);
133 + goto out1;
134 + }
135 + msleep(15 * 1000);
136 +
137 + /* Complete remaining DATA and STATUS stages using the same URB */
138 + urb->status = -EINPROGRESS;
139 + usb_get_urb(urb);
140 + atomic_inc(&urb->use_count);
141 + atomic_inc(&urb->dev->urbnum);
142 + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0);
143 + if (!retval && !wait_for_completion_timeout(&done,
144 + msecs_to_jiffies(2000))) {
145 + usb_kill_urb(urb);
146 + retval = -ETIMEDOUT;
147 + dev_err(hcd->self.controller,
148 + "%s IN stage timed out on ep0\n", __func__);
149 + }
150 +out1:
151 + usb_free_urb(urb);
152 +cleanup:
153 + kfree(dr);
154 + kfree(buf);
155 + return retval;
156 +}
157 +EXPORT_SYMBOL_GPL(ehset_single_step_set_feature);
158 +#endif /* CONFIG_USB_HCD_TEST_MODE */
159 +
160 +/*-------------------------------------------------------------------------*/
161
162 #ifdef CONFIG_PM
163
164 --- a/drivers/usb/host/ehci-hcd.c
165 +++ b/drivers/usb/host/ehci-hcd.c
166 @@ -1254,6 +1254,10 @@ static const struct hc_driver ehci_hc_dr
167 * device support
168 */
169 .free_dev = ehci_remove_device,
170 +#ifdef CONFIG_USB_HCD_TEST_MODE
171 + /* EH SINGLE_STEP_SET_FEATURE test support */
172 + .submit_single_step_set_feature = ehci_submit_single_step_set_feature,
173 +#endif
174 };
175
176 void ehci_init_driver(struct hc_driver *drv,
177 --- a/drivers/usb/host/ehci-hub.c
178 +++ b/drivers/usb/host/ehci-hub.c
179 @@ -727,145 +727,6 @@ ehci_hub_descriptor (
180 }
181
182 /*-------------------------------------------------------------------------*/
183 -#ifdef CONFIG_USB_HCD_TEST_MODE
184 -
185 -#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06
186 -
187 -static void usb_ehset_completion(struct urb *urb)
188 -{
189 - struct completion *done = urb->context;
190 -
191 - complete(done);
192 -}
193 -static int submit_single_step_set_feature(
194 - struct usb_hcd *hcd,
195 - struct urb *urb,
196 - int is_setup
197 -);
198 -
199 -/*
200 - * Allocate and initialize a control URB. This request will be used by the
201 - * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages
202 - * of the GetDescriptor request are sent 15 seconds after the SETUP stage.
203 - * Return NULL if failed.
204 - */
205 -static struct urb *request_single_step_set_feature_urb(
206 - struct usb_device *udev,
207 - void *dr,
208 - void *buf,
209 - struct completion *done
210 -) {
211 - struct urb *urb;
212 - struct usb_hcd *hcd = bus_to_hcd(udev->bus);
213 - struct usb_host_endpoint *ep;
214 -
215 - urb = usb_alloc_urb(0, GFP_KERNEL);
216 - if (!urb)
217 - return NULL;
218 -
219 - urb->pipe = usb_rcvctrlpipe(udev, 0);
220 - ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
221 - [usb_pipeendpoint(urb->pipe)];
222 - if (!ep) {
223 - usb_free_urb(urb);
224 - return NULL;
225 - }
226 -
227 - urb->ep = ep;
228 - urb->dev = udev;
229 - urb->setup_packet = (void *)dr;
230 - urb->transfer_buffer = buf;
231 - urb->transfer_buffer_length = USB_DT_DEVICE_SIZE;
232 - urb->complete = usb_ehset_completion;
233 - urb->status = -EINPROGRESS;
234 - urb->actual_length = 0;
235 - urb->transfer_flags = URB_DIR_IN;
236 - usb_get_urb(urb);
237 - atomic_inc(&urb->use_count);
238 - atomic_inc(&urb->dev->urbnum);
239 - urb->setup_dma = dma_map_single(
240 - hcd->self.sysdev,
241 - urb->setup_packet,
242 - sizeof(struct usb_ctrlrequest),
243 - DMA_TO_DEVICE);
244 - urb->transfer_dma = dma_map_single(
245 - hcd->self.sysdev,
246 - urb->transfer_buffer,
247 - urb->transfer_buffer_length,
248 - DMA_FROM_DEVICE);
249 - urb->context = done;
250 - return urb;
251 -}
252 -
253 -static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
254 -{
255 - int retval = -ENOMEM;
256 - struct usb_ctrlrequest *dr;
257 - struct urb *urb;
258 - struct usb_device *udev;
259 - struct ehci_hcd *ehci = hcd_to_ehci(hcd);
260 - struct usb_device_descriptor *buf;
261 - DECLARE_COMPLETION_ONSTACK(done);
262 -
263 - /* Obtain udev of the rhub's child port */
264 - udev = usb_hub_find_child(hcd->self.root_hub, port);
265 - if (!udev) {
266 - ehci_err(ehci, "No device attached to the RootHub\n");
267 - return -ENODEV;
268 - }
269 - buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
270 - if (!buf)
271 - return -ENOMEM;
272 -
273 - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
274 - if (!dr) {
275 - kfree(buf);
276 - return -ENOMEM;
277 - }
278 -
279 - /* Fill Setup packet for GetDescriptor */
280 - dr->bRequestType = USB_DIR_IN;
281 - dr->bRequest = USB_REQ_GET_DESCRIPTOR;
282 - dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8);
283 - dr->wIndex = 0;
284 - dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE);
285 - urb = request_single_step_set_feature_urb(udev, dr, buf, &done);
286 - if (!urb)
287 - goto cleanup;
288 -
289 - /* Submit just the SETUP stage */
290 - retval = submit_single_step_set_feature(hcd, urb, 1);
291 - if (retval)
292 - goto out1;
293 - if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
294 - usb_kill_urb(urb);
295 - retval = -ETIMEDOUT;
296 - ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__);
297 - goto out1;
298 - }
299 - msleep(15 * 1000);
300 -
301 - /* Complete remaining DATA and STATUS stages using the same URB */
302 - urb->status = -EINPROGRESS;
303 - usb_get_urb(urb);
304 - atomic_inc(&urb->use_count);
305 - atomic_inc(&urb->dev->urbnum);
306 - retval = submit_single_step_set_feature(hcd, urb, 0);
307 - if (!retval && !wait_for_completion_timeout(&done,
308 - msecs_to_jiffies(2000))) {
309 - usb_kill_urb(urb);
310 - retval = -ETIMEDOUT;
311 - ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__);
312 - }
313 -out1:
314 - usb_free_urb(urb);
315 -cleanup:
316 - kfree(dr);
317 - kfree(buf);
318 - return retval;
319 -}
320 -#endif /* CONFIG_USB_HCD_TEST_MODE */
321 -/*-------------------------------------------------------------------------*/
322
323 int ehci_hub_control(
324 struct usb_hcd *hcd,
325 --- a/drivers/usb/host/ehci-q.c
326 +++ b/drivers/usb/host/ehci-q.c
327 @@ -1165,7 +1165,7 @@ submit_async (
328 * performed; TRUE - SETUP and FALSE - IN+STATUS
329 * Returns 0 if success
330 */
331 -static int submit_single_step_set_feature(
332 +static int ehci_submit_single_step_set_feature(
333 struct usb_hcd *hcd,
334 struct urb *urb,
335 int is_setup
336 --- a/include/linux/usb/hcd.h
337 +++ b/include/linux/usb/hcd.h
338 @@ -409,7 +409,10 @@ struct hc_driver {
339 int (*find_raw_port_number)(struct usb_hcd *, int);
340 /* Call for power on/off the port if necessary */
341 int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable);
342 -
343 + /* Call for SINGLE_STEP_SET_FEATURE Test for USB2 EH certification */
344 +#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06
345 + int (*submit_single_step_set_feature)(struct usb_hcd *,
346 + struct urb *, int);
347 };
348
349 static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
350 @@ -474,6 +477,14 @@ int usb_hcd_setup_local_mem(struct usb_h
351
352 struct platform_device;
353 extern void usb_hcd_platform_shutdown(struct platform_device *dev);
354 +#ifdef CONFIG_USB_HCD_TEST_MODE
355 +extern int ehset_single_step_set_feature(struct usb_hcd *hcd, int port);
356 +#else
357 +static inline int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
358 +{
359 + return 0;
360 +}
361 +#endif /* CONFIG_USB_HCD_TEST_MODE */
362
363 #ifdef CONFIG_USB_PCI
364 struct pci_dev;