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
7 Since other USB 2.0 host may need it, like USB2 for XHCI. We move
8 this design to HCD core.
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)
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(-)
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
26 /*-------------------------------------------------------------------------*/
27 +#ifdef CONFIG_USB_HCD_TEST_MODE
29 +static void usb_ehset_completion(struct urb *urb)
31 + struct completion *done = urb->context;
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.
41 +static struct urb *request_single_step_set_feature_urb(
42 + struct usb_device *udev,
45 + struct completion *done
48 + struct usb_hcd *hcd = bus_to_hcd(udev->bus);
49 + struct usb_host_endpoint *ep;
51 + urb = usb_alloc_urb(0, GFP_KERNEL);
55 + urb->pipe = usb_rcvctrlpipe(udev, 0);
56 + ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
57 + [usb_pipeendpoint(urb->pipe)];
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;
73 + atomic_inc(&urb->use_count);
74 + atomic_inc(&urb->dev->urbnum);
75 + urb->setup_dma = dma_map_single(
78 + sizeof(struct usb_ctrlrequest),
80 + urb->transfer_dma = dma_map_single(
82 + urb->transfer_buffer,
83 + urb->transfer_buffer_length,
85 + urb->context = done;
89 +int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
91 + int retval = -ENOMEM;
92 + struct usb_ctrlrequest *dr;
94 + struct usb_device *udev;
95 + struct usb_device_descriptor *buf;
96 + DECLARE_COMPLETION_ONSTACK(done);
98 + /* Obtain udev of the rhub's child port */
99 + udev = usb_hub_find_child(hcd->self.root_hub, port);
101 + dev_err(hcd->self.controller, "No device attached to the RootHub\n");
104 + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
108 + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
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);
119 + dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE);
120 + urb = request_single_step_set_feature_urb(udev, dr, buf, &done);
124 + /* Submit just the SETUP stage */
125 + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 1);
128 + if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
130 + retval = -ETIMEDOUT;
131 + dev_err(hcd->self.controller,
132 + "%s SETUP stage timed out on ep0\n", __func__);
137 + /* Complete remaining DATA and STATUS stages using the same URB */
138 + urb->status = -EINPROGRESS;
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))) {
146 + retval = -ETIMEDOUT;
147 + dev_err(hcd->self.controller,
148 + "%s IN stage timed out on ep0\n", __func__);
157 +EXPORT_SYMBOL_GPL(ehset_single_step_set_feature);
158 +#endif /* CONFIG_USB_HCD_TEST_MODE */
160 +/*-------------------------------------------------------------------------*/
164 --- a/drivers/usb/host/ehci-hcd.c
165 +++ b/drivers/usb/host/ehci-hcd.c
166 @@ -1232,6 +1232,10 @@ static const struct hc_driver ehci_hc_dr
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,
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 @@ -725,145 +725,6 @@ ehci_hub_descriptor (
182 /*-------------------------------------------------------------------------*/
183 -#ifdef CONFIG_USB_HCD_TEST_MODE
185 -#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06
187 -static void usb_ehset_completion(struct urb *urb)
189 - struct completion *done = urb->context;
193 -static int submit_single_step_set_feature(
194 - struct usb_hcd *hcd,
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.
205 -static struct urb *request_single_step_set_feature_urb(
206 - struct usb_device *udev,
209 - struct completion *done
212 - struct usb_hcd *hcd = bus_to_hcd(udev->bus);
213 - struct usb_host_endpoint *ep;
215 - urb = usb_alloc_urb(0, GFP_KERNEL);
219 - urb->pipe = usb_rcvctrlpipe(udev, 0);
220 - ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out)
221 - [usb_pipeendpoint(urb->pipe)];
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;
237 - atomic_inc(&urb->use_count);
238 - atomic_inc(&urb->dev->urbnum);
239 - urb->setup_dma = dma_map_single(
242 - sizeof(struct usb_ctrlrequest),
244 - urb->transfer_dma = dma_map_single(
246 - urb->transfer_buffer,
247 - urb->transfer_buffer_length,
249 - urb->context = done;
253 -static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
255 - int retval = -ENOMEM;
256 - struct usb_ctrlrequest *dr;
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);
263 - /* Obtain udev of the rhub's child port */
264 - udev = usb_hub_find_child(hcd->self.root_hub, port);
266 - ehci_err(ehci, "No device attached to the RootHub\n");
269 - buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL);
273 - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
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);
284 - dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE);
285 - urb = request_single_step_set_feature_urb(udev, dr, buf, &done);
289 - /* Submit just the SETUP stage */
290 - retval = submit_single_step_set_feature(hcd, urb, 1);
293 - if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) {
295 - retval = -ETIMEDOUT;
296 - ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__);
301 - /* Complete remaining DATA and STATUS stages using the same URB */
302 - urb->status = -EINPROGRESS;
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))) {
310 - retval = -ETIMEDOUT;
311 - ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__);
320 -#endif /* CONFIG_USB_HCD_TEST_MODE */
321 -/*-------------------------------------------------------------------------*/
323 int ehci_hub_control(
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
331 -static int submit_single_step_set_feature(
332 +static int ehci_submit_single_step_set_feature(
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);
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);
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
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);
357 +static inline int ehset_single_step_set_feature(struct usb_hcd *hcd, int port)
361 +#endif /* CONFIG_USB_HCD_TEST_MODE */
363 #ifdef CONFIG_USB_PCI