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

usb: host: move EH SINGLE_STEP_SET_FEATURE implementation to core

It is needed at USB Certification test for Embedded Host 2.0, and
the detail is at CH6.4.1.1 of On-The-Go and Embedded Host Supplement
to the USB Revision 2.0 Specification. Since other USB 2.0 capable
host like XHCI also need it, so move it to HCD core.

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Link: https://lore.kernel.org/r/1620452039-11694-1-git-send-email-jun.li@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Peter Chen and committed by
Greg Kroah-Hartman
cbbc07e1 9e8d268f

+151 -141
+134
drivers/usb/core/hcd.c
··· 2111 2111 } 2112 2112 2113 2113 /*-------------------------------------------------------------------------*/ 2114 + #ifdef CONFIG_USB_HCD_TEST_MODE 2115 + 2116 + static void usb_ehset_completion(struct urb *urb) 2117 + { 2118 + struct completion *done = urb->context; 2119 + 2120 + complete(done); 2121 + } 2122 + /* 2123 + * Allocate and initialize a control URB. This request will be used by the 2124 + * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages 2125 + * of the GetDescriptor request are sent 15 seconds after the SETUP stage. 2126 + * Return NULL if failed. 2127 + */ 2128 + static struct urb *request_single_step_set_feature_urb( 2129 + struct usb_device *udev, 2130 + void *dr, 2131 + void *buf, 2132 + struct completion *done) 2133 + { 2134 + struct urb *urb; 2135 + struct usb_hcd *hcd = bus_to_hcd(udev->bus); 2136 + struct usb_host_endpoint *ep; 2137 + 2138 + urb = usb_alloc_urb(0, GFP_KERNEL); 2139 + if (!urb) 2140 + return NULL; 2141 + 2142 + urb->pipe = usb_rcvctrlpipe(udev, 0); 2143 + ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) 2144 + [usb_pipeendpoint(urb->pipe)]; 2145 + if (!ep) { 2146 + usb_free_urb(urb); 2147 + return NULL; 2148 + } 2149 + 2150 + urb->ep = ep; 2151 + urb->dev = udev; 2152 + urb->setup_packet = (void *)dr; 2153 + urb->transfer_buffer = buf; 2154 + urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; 2155 + urb->complete = usb_ehset_completion; 2156 + urb->status = -EINPROGRESS; 2157 + urb->actual_length = 0; 2158 + urb->transfer_flags = URB_DIR_IN; 2159 + usb_get_urb(urb); 2160 + atomic_inc(&urb->use_count); 2161 + atomic_inc(&urb->dev->urbnum); 2162 + urb->setup_dma = dma_map_single( 2163 + hcd->self.sysdev, 2164 + urb->setup_packet, 2165 + sizeof(struct usb_ctrlrequest), 2166 + DMA_TO_DEVICE); 2167 + urb->transfer_dma = dma_map_single( 2168 + hcd->self.sysdev, 2169 + urb->transfer_buffer, 2170 + urb->transfer_buffer_length, 2171 + DMA_FROM_DEVICE); 2172 + urb->context = done; 2173 + return urb; 2174 + } 2175 + 2176 + int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) 2177 + { 2178 + int retval = -ENOMEM; 2179 + struct usb_ctrlrequest *dr; 2180 + struct urb *urb; 2181 + struct usb_device *udev; 2182 + struct usb_device_descriptor *buf; 2183 + DECLARE_COMPLETION_ONSTACK(done); 2184 + 2185 + /* Obtain udev of the rhub's child port */ 2186 + udev = usb_hub_find_child(hcd->self.root_hub, port); 2187 + if (!udev) { 2188 + dev_err(hcd->self.controller, "No device attached to the RootHub\n"); 2189 + return -ENODEV; 2190 + } 2191 + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); 2192 + if (!buf) 2193 + return -ENOMEM; 2194 + 2195 + dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 2196 + if (!dr) { 2197 + kfree(buf); 2198 + return -ENOMEM; 2199 + } 2200 + 2201 + /* Fill Setup packet for GetDescriptor */ 2202 + dr->bRequestType = USB_DIR_IN; 2203 + dr->bRequest = USB_REQ_GET_DESCRIPTOR; 2204 + dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); 2205 + dr->wIndex = 0; 2206 + dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); 2207 + urb = request_single_step_set_feature_urb(udev, dr, buf, &done); 2208 + if (!urb) 2209 + goto cleanup; 2210 + 2211 + /* Submit just the SETUP stage */ 2212 + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 1); 2213 + if (retval) 2214 + goto out1; 2215 + if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { 2216 + usb_kill_urb(urb); 2217 + retval = -ETIMEDOUT; 2218 + dev_err(hcd->self.controller, 2219 + "%s SETUP stage timed out on ep0\n", __func__); 2220 + goto out1; 2221 + } 2222 + msleep(15 * 1000); 2223 + 2224 + /* Complete remaining DATA and STATUS stages using the same URB */ 2225 + urb->status = -EINPROGRESS; 2226 + usb_get_urb(urb); 2227 + atomic_inc(&urb->use_count); 2228 + atomic_inc(&urb->dev->urbnum); 2229 + retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0); 2230 + if (!retval && !wait_for_completion_timeout(&done, 2231 + msecs_to_jiffies(2000))) { 2232 + usb_kill_urb(urb); 2233 + retval = -ETIMEDOUT; 2234 + dev_err(hcd->self.controller, 2235 + "%s IN stage timed out on ep0\n", __func__); 2236 + } 2237 + out1: 2238 + usb_free_urb(urb); 2239 + cleanup: 2240 + kfree(dr); 2241 + kfree(buf); 2242 + return retval; 2243 + } 2244 + EXPORT_SYMBOL_GPL(ehset_single_step_set_feature); 2245 + #endif /* CONFIG_USB_HCD_TEST_MODE */ 2246 + 2247 + /*-------------------------------------------------------------------------*/ 2114 2248 2115 2249 #ifdef CONFIG_PM 2116 2250
+4
drivers/usb/host/ehci-hcd.c
··· 1238 1238 * device support 1239 1239 */ 1240 1240 .free_dev = ehci_remove_device, 1241 + #ifdef CONFIG_USB_HCD_TEST_MODE 1242 + /* EH SINGLE_STEP_SET_FEATURE test support */ 1243 + .submit_single_step_set_feature = ehci_submit_single_step_set_feature, 1244 + #endif 1241 1245 }; 1242 1246 1243 1247 void ehci_init_driver(struct hc_driver *drv,
-139
drivers/usb/host/ehci-hub.c
··· 727 727 } 728 728 729 729 /*-------------------------------------------------------------------------*/ 730 - #ifdef CONFIG_USB_HCD_TEST_MODE 731 - 732 - #define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06 733 - 734 - static void usb_ehset_completion(struct urb *urb) 735 - { 736 - struct completion *done = urb->context; 737 - 738 - complete(done); 739 - } 740 - static int submit_single_step_set_feature( 741 - struct usb_hcd *hcd, 742 - struct urb *urb, 743 - int is_setup 744 - ); 745 - 746 - /* 747 - * Allocate and initialize a control URB. This request will be used by the 748 - * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages 749 - * of the GetDescriptor request are sent 15 seconds after the SETUP stage. 750 - * Return NULL if failed. 751 - */ 752 - static struct urb *request_single_step_set_feature_urb( 753 - struct usb_device *udev, 754 - void *dr, 755 - void *buf, 756 - struct completion *done 757 - ) { 758 - struct urb *urb; 759 - struct usb_hcd *hcd = bus_to_hcd(udev->bus); 760 - struct usb_host_endpoint *ep; 761 - 762 - urb = usb_alloc_urb(0, GFP_KERNEL); 763 - if (!urb) 764 - return NULL; 765 - 766 - urb->pipe = usb_rcvctrlpipe(udev, 0); 767 - ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) 768 - [usb_pipeendpoint(urb->pipe)]; 769 - if (!ep) { 770 - usb_free_urb(urb); 771 - return NULL; 772 - } 773 - 774 - urb->ep = ep; 775 - urb->dev = udev; 776 - urb->setup_packet = (void *)dr; 777 - urb->transfer_buffer = buf; 778 - urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; 779 - urb->complete = usb_ehset_completion; 780 - urb->status = -EINPROGRESS; 781 - urb->actual_length = 0; 782 - urb->transfer_flags = URB_DIR_IN; 783 - usb_get_urb(urb); 784 - atomic_inc(&urb->use_count); 785 - atomic_inc(&urb->dev->urbnum); 786 - urb->setup_dma = dma_map_single( 787 - hcd->self.sysdev, 788 - urb->setup_packet, 789 - sizeof(struct usb_ctrlrequest), 790 - DMA_TO_DEVICE); 791 - urb->transfer_dma = dma_map_single( 792 - hcd->self.sysdev, 793 - urb->transfer_buffer, 794 - urb->transfer_buffer_length, 795 - DMA_FROM_DEVICE); 796 - urb->context = done; 797 - return urb; 798 - } 799 - 800 - static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) 801 - { 802 - int retval = -ENOMEM; 803 - struct usb_ctrlrequest *dr; 804 - struct urb *urb; 805 - struct usb_device *udev; 806 - struct ehci_hcd *ehci = hcd_to_ehci(hcd); 807 - struct usb_device_descriptor *buf; 808 - DECLARE_COMPLETION_ONSTACK(done); 809 - 810 - /* Obtain udev of the rhub's child port */ 811 - udev = usb_hub_find_child(hcd->self.root_hub, port); 812 - if (!udev) { 813 - ehci_err(ehci, "No device attached to the RootHub\n"); 814 - return -ENODEV; 815 - } 816 - buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); 817 - if (!buf) 818 - return -ENOMEM; 819 - 820 - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); 821 - if (!dr) { 822 - kfree(buf); 823 - return -ENOMEM; 824 - } 825 - 826 - /* Fill Setup packet for GetDescriptor */ 827 - dr->bRequestType = USB_DIR_IN; 828 - dr->bRequest = USB_REQ_GET_DESCRIPTOR; 829 - dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); 830 - dr->wIndex = 0; 831 - dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); 832 - urb = request_single_step_set_feature_urb(udev, dr, buf, &done); 833 - if (!urb) 834 - goto cleanup; 835 - 836 - /* Submit just the SETUP stage */ 837 - retval = submit_single_step_set_feature(hcd, urb, 1); 838 - if (retval) 839 - goto out1; 840 - if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { 841 - usb_kill_urb(urb); 842 - retval = -ETIMEDOUT; 843 - ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__); 844 - goto out1; 845 - } 846 - msleep(15 * 1000); 847 - 848 - /* Complete remaining DATA and STATUS stages using the same URB */ 849 - urb->status = -EINPROGRESS; 850 - usb_get_urb(urb); 851 - atomic_inc(&urb->use_count); 852 - atomic_inc(&urb->dev->urbnum); 853 - retval = submit_single_step_set_feature(hcd, urb, 0); 854 - if (!retval && !wait_for_completion_timeout(&done, 855 - msecs_to_jiffies(2000))) { 856 - usb_kill_urb(urb); 857 - retval = -ETIMEDOUT; 858 - ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__); 859 - } 860 - out1: 861 - usb_free_urb(urb); 862 - cleanup: 863 - kfree(dr); 864 - kfree(buf); 865 - return retval; 866 - } 867 - #endif /* CONFIG_USB_HCD_TEST_MODE */ 868 - /*-------------------------------------------------------------------------*/ 869 730 870 731 int ehci_hub_control( 871 732 struct usb_hcd *hcd,
+1 -1
drivers/usb/host/ehci-q.c
··· 1165 1165 * performed; TRUE - SETUP and FALSE - IN+STATUS 1166 1166 * Returns 0 if success 1167 1167 */ 1168 - static int submit_single_step_set_feature( 1168 + static int ehci_submit_single_step_set_feature( 1169 1169 struct usb_hcd *hcd, 1170 1170 struct urb *urb, 1171 1171 int is_setup
+12 -1
include/linux/usb/hcd.h
··· 409 409 int (*find_raw_port_number)(struct usb_hcd *, int); 410 410 /* Call for power on/off the port if necessary */ 411 411 int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable); 412 - 412 + /* Call for SINGLE_STEP_SET_FEATURE Test for USB2 EH certification */ 413 + #define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06 414 + int (*submit_single_step_set_feature)(struct usb_hcd *, 415 + struct urb *, int); 413 416 }; 414 417 415 418 static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd) ··· 477 474 478 475 struct platform_device; 479 476 extern void usb_hcd_platform_shutdown(struct platform_device *dev); 477 + #ifdef CONFIG_USB_HCD_TEST_MODE 478 + extern int ehset_single_step_set_feature(struct usb_hcd *hcd, int port); 479 + #else 480 + static inline int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) 481 + { 482 + return 0; 483 + } 484 + #endif /* CONFIG_USB_HCD_TEST_MODE */ 480 485 481 486 #ifdef CONFIG_USB_PCI 482 487 struct pci_dev;