820-usb-0014-MLK-17380-3-usb-move-EH-SINGLE_STEP_SET_FEATURE-impl.patch 10 KB

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