fcad77c1ebd836fb33e4b952487358fba29fdf07
[openwrt/staging/xback.git] /
1 From 6a313b6072925ab757688328b9f91b16d5a39bb3 Mon Sep 17 00:00:00 2001
2 From: Peter Chen <peter.chen@nxp.com>
3 Date: Fri, 9 Feb 2018 10:11:32 +0800
4 Subject: [PATCH] MLK-17380-4 usb: host: xhci: add EH SINGLE_STEP_SET_FEATURE
5 Test for USB2
6
7 This function is similar with EHCI's, but implemented using XHCI.
8 The USB2 host needs to send SETUP packet first, then wait 15
9 seconds before DATA (IN) + STATUS stage.
10
11 It is needed at USB Certification test for Embedded Host 2.0, and
12 the detail is at CH6.4.1.1 of On-The-Go and Embedded Host Supplement
13 to the USB Revision 2.0 Specification
14
15 Acked-by: Jun Li <jun.li@nxp.com>
16 Signed-off-by: Peter Chen <peter.chen@nxp.com>
17 (cherry picked from commit 8d46e3bca527a5d899446d3858274fb5cbab1a1e)
18 ---
19 drivers/usb/host/xhci-hub.c | 9 ++++
20 drivers/usb/host/xhci-ring.c | 123 +++++++++++++++++++++++++++++++++++++++++++
21 drivers/usb/host/xhci.c | 1 +
22 drivers/usb/host/xhci.h | 10 ++++
23 4 files changed, 143 insertions(+)
24
25 --- a/drivers/usb/host/xhci-hub.c
26 +++ b/drivers/usb/host/xhci-hub.c
27 @@ -1420,6 +1420,15 @@ int xhci_hub_control(struct usb_hcd *hcd
28 /* 4.19.6 Port Test Modes (USB2 Test Mode) */
29 if (hcd->speed != HCD_USB2)
30 goto error;
31 +#ifdef CONFIG_USB_HCD_TEST_MODE
32 + if (test_mode == EHSET_TEST_SINGLE_STEP_SET_FEATURE) {
33 + spin_unlock_irqrestore(&xhci->lock, flags);
34 + retval = ehset_single_step_set_feature(hcd,
35 + wIndex + 1);
36 + spin_lock_irqsave(&xhci->lock, flags);
37 + break;
38 + }
39 +#endif
40 if (test_mode > TEST_FORCE_EN || test_mode < TEST_J)
41 goto error;
42 retval = xhci_enter_test_mode(xhci, test_mode, wIndex,
43 --- a/drivers/usb/host/xhci-ring.c
44 +++ b/drivers/usb/host/xhci-ring.c
45 @@ -3624,6 +3624,129 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
46 return 0;
47 }
48
49 +#ifdef CONFIG_USB_HCD_TEST_MODE
50 +/*
51 + * This function prepare TRBs and submits them for the
52 + * SINGLE_STEP_SET_FEATURE Test.
53 + * This is done in two parts: first SETUP req for GetDesc is sent then
54 + * 15 seconds later, the IN stage for GetDesc starts to req data from dev
55 + *
56 + * is_setup : argument decides which of the two stage needs to be
57 + * performed; TRUE - SETUP and FALSE - IN+STATUS
58 + * Returns 0 if success
59 + */
60 +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
61 + struct urb *urb, int is_setup)
62 +{
63 + int slot_id;
64 + unsigned int ep_index;
65 + struct xhci_ring *ep_ring;
66 + int ret;
67 + struct usb_ctrlrequest *setup;
68 + struct xhci_generic_trb *start_trb;
69 + int start_cycle;
70 + u32 field, length_field, remainder;
71 + struct urb_priv *urb_priv;
72 + struct xhci_td *td;
73 + struct xhci_hcd *xhci = hcd_to_xhci(hcd);
74 +
75 + /* urb_priv will be free after transcation has completed */
76 + urb_priv = kzalloc(sizeof(struct urb_priv) +
77 + sizeof(struct xhci_td), GFP_KERNEL);
78 + if (!urb_priv)
79 + return -ENOMEM;
80 +
81 + td = &urb_priv->td[0];
82 + urb_priv->num_tds = 1;
83 + urb_priv->num_tds_done = 0;
84 + urb->hcpriv = urb_priv;
85 +
86 + ep_ring = xhci_urb_to_transfer_ring(xhci, urb);
87 + if (!ep_ring) {
88 + ret = -EINVAL;
89 + goto free_priv;
90 + }
91 +
92 + slot_id = urb->dev->slot_id;
93 + ep_index = xhci_get_endpoint_index(&urb->ep->desc);
94 +
95 + setup = (struct usb_ctrlrequest *) urb->setup_packet;
96 + if (is_setup) {
97 + ret = prepare_transfer(xhci, xhci->devs[slot_id],
98 + ep_index, urb->stream_id,
99 + 1, urb, 0, GFP_KERNEL);
100 + if (ret < 0)
101 + goto free_priv;
102 +
103 + start_trb = &ep_ring->enqueue->generic;
104 + start_cycle = ep_ring->cycle_state;
105 + /* Save the DMA address of the last TRB in the TD */
106 + td->last_trb = ep_ring->enqueue;
107 + field = TRB_IOC | TRB_IDT | TRB_TYPE(TRB_SETUP) | start_cycle;
108 + /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
109 + if ((xhci->hci_version >= 0x100) ||
110 + (xhci->quirks & XHCI_MTK_HOST))
111 + field |= TRB_TX_TYPE(TRB_DATA_IN);
112 +
113 + queue_trb(xhci, ep_ring, false,
114 + setup->bRequestType | setup->bRequest << 8 |
115 + le16_to_cpu(setup->wValue) << 16,
116 + le16_to_cpu(setup->wIndex) |
117 + le16_to_cpu(setup->wLength) << 16,
118 + TRB_LEN(8) | TRB_INTR_TARGET(0),
119 + /* Immediate data in pointer */
120 + field);
121 + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
122 + start_cycle, start_trb);
123 + return 0;
124 + }
125 +
126 + ret = prepare_transfer(xhci, xhci->devs[slot_id],
127 + ep_index, urb->stream_id,
128 + 2, urb, 0, GFP_KERNEL);
129 + if (ret < 0)
130 + goto free_priv;
131 +
132 + start_trb = &ep_ring->enqueue->generic;
133 + start_cycle = ep_ring->cycle_state;
134 + field = TRB_ISP | TRB_TYPE(TRB_DATA);
135 +
136 + remainder = xhci_td_remainder(xhci, 0,
137 + urb->transfer_buffer_length,
138 + urb->transfer_buffer_length,
139 + urb, 1);
140 +
141 + length_field = TRB_LEN(urb->transfer_buffer_length) |
142 + TRB_TD_SIZE(remainder) |
143 + TRB_INTR_TARGET(0);
144 +
145 + if (urb->transfer_buffer_length > 0) {
146 + field |= TRB_DIR_IN;
147 + queue_trb(xhci, ep_ring, true,
148 + lower_32_bits(urb->transfer_dma),
149 + upper_32_bits(urb->transfer_dma),
150 + length_field,
151 + field | ep_ring->cycle_state);
152 + }
153 +
154 + td->last_trb = ep_ring->enqueue;
155 + field = TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state;
156 + queue_trb(xhci, ep_ring, false,
157 + 0,
158 + 0,
159 + TRB_INTR_TARGET(0),
160 + field);
161 +
162 + giveback_first_trb(xhci, slot_id, ep_index, 0,
163 + start_cycle, start_trb);
164 +
165 + return 0;
166 +free_priv:
167 + xhci_urb_free_priv(urb_priv);
168 + return ret;
169 +}
170 +#endif /* CONFIG_USB_HCD_TEST_MODE */
171 +
172 /*
173 * The transfer burst count field of the isochronous TRB defines the number of
174 * bursts that are required to move all packets in this TD. Only SuperSpeed
175 --- a/drivers/usb/host/xhci.c
176 +++ b/drivers/usb/host/xhci.c
177 @@ -5385,6 +5385,7 @@ static const struct hc_driver xhci_hc_dr
178 .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
179 .find_raw_port_number = xhci_find_raw_port_number,
180 .clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
181 + .submit_single_step_set_feature = xhci_submit_single_step_set_feature,
182 };
183
184 void xhci_init_driver(struct hc_driver *drv,
185 --- a/drivers/usb/host/xhci.h
186 +++ b/drivers/usb/host/xhci.h
187 @@ -2154,6 +2154,16 @@ int xhci_find_raw_port_number(struct usb
188 struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
189
190 void xhci_hc_died(struct xhci_hcd *xhci);
191 +#ifdef CONFIG_USB_HCD_TEST_MODE
192 +int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
193 + struct urb *urb, int is_setup);
194 +#else
195 +static inline int xhci_submit_single_step_set_feature(struct usb_hcd *hcd,
196 + struct urb *urb, int is_setup)
197 +{
198 + return 0;
199 +}
200 +#endif
201
202 #ifdef CONFIG_PM
203 int xhci_bus_suspend(struct usb_hcd *hcd);