diff options
author | Douglas Anderson <dianders@chromium.org> | 2016-01-28 21:20:05 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@kernel.org> | 2016-03-04 08:14:43 -0500 |
commit | b951c6c7f875d2c72c6e16a4d5fa810cbb33ae32 (patch) | |
tree | dec3c2260fb804209b0b57fef87361c8f1427e33 | |
parent | ced9eee1229db3bbe683ae17e0a91a8642382a39 (diff) |
usb: dwc2: host: Reorder things in hcd_queue.c
This no-op change just reorders a few functions in hcd_queue.c in order
to prepare for future changes. Motivations here:
The functions dwc2_hcd_qh_free() and dwc2_hcd_qh_create() are exported
functions. They are not called within the file. That means that they
should be near the bottom so that they can easily call static helpers.
The function dwc2_qh_init() is only called by dwc2_hcd_qh_create() and
should move near the bottom with it.
The only reason that the dwc2_unreserve_timer_fn() timer function (and
its subroutine dwc2_do_unreserve()) were so high in the file was that
they needed to be above dwc2_qh_init(). Now that dwc2_qh_init() has
been moved down it can be moved down a bit. A later patch will split
the reserve code out of dwc2_schedule_periodic() and the reserve
function should be near the unreserve function. The reserve function
needs to be below dwc2_find_uframe() since it calls that.
Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
-rw-r--r-- | drivers/usb/dwc2/hcd_queue.c | 578 |
1 files changed, 289 insertions, 289 deletions
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 39f4de6279f8..8a2067bc1e62 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c | |||
@@ -57,295 +57,6 @@ | |||
57 | #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) | 57 | #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * dwc2_do_unreserve() - Actually release the periodic reservation | ||
61 | * | ||
62 | * This function actually releases the periodic bandwidth that was reserved | ||
63 | * by the given qh. | ||
64 | * | ||
65 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
66 | * @qh: QH for the periodic transfer. | ||
67 | */ | ||
68 | static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | ||
69 | { | ||
70 | assert_spin_locked(&hsotg->lock); | ||
71 | |||
72 | WARN_ON(!qh->unreserve_pending); | ||
73 | |||
74 | /* No more unreserve pending--we're doing it */ | ||
75 | qh->unreserve_pending = false; | ||
76 | |||
77 | if (WARN_ON(!list_empty(&qh->qh_list_entry))) | ||
78 | list_del_init(&qh->qh_list_entry); | ||
79 | |||
80 | /* Update claimed usecs per (micro)frame */ | ||
81 | hsotg->periodic_usecs -= qh->host_us; | ||
82 | |||
83 | if (hsotg->core_params->uframe_sched > 0) { | ||
84 | int i; | ||
85 | |||
86 | for (i = 0; i < 8; i++) { | ||
87 | hsotg->frame_usecs[i] += qh->frame_usecs[i]; | ||
88 | qh->frame_usecs[i] = 0; | ||
89 | } | ||
90 | } else { | ||
91 | /* Release periodic channel reservation */ | ||
92 | hsotg->periodic_channels--; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * dwc2_unreserve_timer_fn() - Timer function to release periodic reservation | ||
98 | * | ||
99 | * According to the kernel doc for usb_submit_urb() (specifically the part about | ||
100 | * "Reserved Bandwidth Transfers"), we need to keep a reservation active as | ||
101 | * long as a device driver keeps submitting. Since we're using HCD_BH to give | ||
102 | * back the URB we need to give the driver a little bit of time before we | ||
103 | * release the reservation. This worker is called after the appropriate | ||
104 | * delay. | ||
105 | * | ||
106 | * @work: Pointer to a qh unreserve_work. | ||
107 | */ | ||
108 | static void dwc2_unreserve_timer_fn(unsigned long data) | ||
109 | { | ||
110 | struct dwc2_qh *qh = (struct dwc2_qh *)data; | ||
111 | struct dwc2_hsotg *hsotg = qh->hsotg; | ||
112 | unsigned long flags; | ||
113 | |||
114 | /* | ||
115 | * Wait for the lock, or for us to be scheduled again. We | ||
116 | * could be scheduled again if: | ||
117 | * - We started executing but didn't get the lock yet. | ||
118 | * - A new reservation came in, but cancel didn't take effect | ||
119 | * because we already started executing. | ||
120 | * - The timer has been kicked again. | ||
121 | * In that case cancel and wait for the next call. | ||
122 | */ | ||
123 | while (!spin_trylock_irqsave(&hsotg->lock, flags)) { | ||
124 | if (timer_pending(&qh->unreserve_timer)) | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Might be no more unreserve pending if: | ||
130 | * - We started executing but didn't get the lock yet. | ||
131 | * - A new reservation came in, but cancel didn't take effect | ||
132 | * because we already started executing. | ||
133 | * | ||
134 | * We can't put this in the loop above because unreserve_pending needs | ||
135 | * to be accessed under lock, so we can only check it once we got the | ||
136 | * lock. | ||
137 | */ | ||
138 | if (qh->unreserve_pending) | ||
139 | dwc2_do_unreserve(hsotg, qh); | ||
140 | |||
141 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * dwc2_qh_init() - Initializes a QH structure | ||
146 | * | ||
147 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
148 | * @qh: The QH to init | ||
149 | * @urb: Holds the information about the device/endpoint needed to initialize | ||
150 | * the QH | ||
151 | */ | ||
152 | #define SCHEDULE_SLOP 10 | ||
153 | static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | ||
154 | struct dwc2_hcd_urb *urb) | ||
155 | { | ||
156 | int dev_speed, hub_addr, hub_port; | ||
157 | char *speed, *type; | ||
158 | |||
159 | dev_vdbg(hsotg->dev, "%s()\n", __func__); | ||
160 | |||
161 | /* Initialize QH */ | ||
162 | qh->hsotg = hsotg; | ||
163 | setup_timer(&qh->unreserve_timer, dwc2_unreserve_timer_fn, | ||
164 | (unsigned long)qh); | ||
165 | qh->ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info); | ||
166 | qh->ep_is_in = dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; | ||
167 | |||
168 | qh->data_toggle = DWC2_HC_PID_DATA0; | ||
169 | qh->maxp = dwc2_hcd_get_mps(&urb->pipe_info); | ||
170 | INIT_LIST_HEAD(&qh->qtd_list); | ||
171 | INIT_LIST_HEAD(&qh->qh_list_entry); | ||
172 | |||
173 | /* FS/LS Endpoint on HS Hub, NOT virtual root hub */ | ||
174 | dev_speed = dwc2_host_get_speed(hsotg, urb->priv); | ||
175 | |||
176 | dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port); | ||
177 | |||
178 | if ((dev_speed == USB_SPEED_LOW || dev_speed == USB_SPEED_FULL) && | ||
179 | hub_addr != 0 && hub_addr != 1) { | ||
180 | dev_vdbg(hsotg->dev, | ||
181 | "QH init: EP %d: TT found at hub addr %d, for port %d\n", | ||
182 | dwc2_hcd_get_ep_num(&urb->pipe_info), hub_addr, | ||
183 | hub_port); | ||
184 | qh->do_split = 1; | ||
185 | } | ||
186 | |||
187 | if (qh->ep_type == USB_ENDPOINT_XFER_INT || | ||
188 | qh->ep_type == USB_ENDPOINT_XFER_ISOC) { | ||
189 | /* Compute scheduling parameters once and save them */ | ||
190 | u32 hprt, prtspd; | ||
191 | |||
192 | /* Todo: Account for split transfers in the bus time */ | ||
193 | int bytecount = | ||
194 | dwc2_hb_mult(qh->maxp) * dwc2_max_packet(qh->maxp); | ||
195 | |||
196 | qh->host_us = NS_TO_US(usb_calc_bus_time(qh->do_split ? | ||
197 | USB_SPEED_HIGH : dev_speed, qh->ep_is_in, | ||
198 | qh->ep_type == USB_ENDPOINT_XFER_ISOC, | ||
199 | bytecount)); | ||
200 | |||
201 | /* Ensure frame_number corresponds to the reality */ | ||
202 | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); | ||
203 | /* Start in a slightly future (micro)frame */ | ||
204 | qh->next_active_frame = dwc2_frame_num_inc(hsotg->frame_number, | ||
205 | SCHEDULE_SLOP); | ||
206 | qh->host_interval = urb->interval; | ||
207 | dwc2_sch_dbg(hsotg, "QH=%p init nxt=%04x, fn=%04x, int=%#x\n", | ||
208 | qh, qh->next_active_frame, hsotg->frame_number, | ||
209 | qh->host_interval); | ||
210 | #if 0 | ||
211 | /* Increase interrupt polling rate for debugging */ | ||
212 | if (qh->ep_type == USB_ENDPOINT_XFER_INT) | ||
213 | qh->host_interval = 8; | ||
214 | #endif | ||
215 | hprt = dwc2_readl(hsotg->regs + HPRT0); | ||
216 | prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; | ||
217 | if (prtspd == HPRT0_SPD_HIGH_SPEED && | ||
218 | (dev_speed == USB_SPEED_LOW || | ||
219 | dev_speed == USB_SPEED_FULL)) { | ||
220 | qh->host_interval *= 8; | ||
221 | qh->next_active_frame |= 0x7; | ||
222 | qh->start_split_frame = qh->next_active_frame; | ||
223 | dwc2_sch_dbg(hsotg, | ||
224 | "QH=%p init*8 nxt=%04x, fn=%04x, int=%#x\n", | ||
225 | qh, qh->next_active_frame, | ||
226 | hsotg->frame_number, qh->host_interval); | ||
227 | |||
228 | } | ||
229 | dev_dbg(hsotg->dev, "interval=%d\n", qh->host_interval); | ||
230 | } | ||
231 | |||
232 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH Initialized\n"); | ||
233 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - qh = %p\n", qh); | ||
234 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Device Address = %d\n", | ||
235 | dwc2_hcd_get_dev_addr(&urb->pipe_info)); | ||
236 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Endpoint %d, %s\n", | ||
237 | dwc2_hcd_get_ep_num(&urb->pipe_info), | ||
238 | dwc2_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); | ||
239 | |||
240 | qh->dev_speed = dev_speed; | ||
241 | |||
242 | switch (dev_speed) { | ||
243 | case USB_SPEED_LOW: | ||
244 | speed = "low"; | ||
245 | break; | ||
246 | case USB_SPEED_FULL: | ||
247 | speed = "full"; | ||
248 | break; | ||
249 | case USB_SPEED_HIGH: | ||
250 | speed = "high"; | ||
251 | break; | ||
252 | default: | ||
253 | speed = "?"; | ||
254 | break; | ||
255 | } | ||
256 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Speed = %s\n", speed); | ||
257 | |||
258 | switch (qh->ep_type) { | ||
259 | case USB_ENDPOINT_XFER_ISOC: | ||
260 | type = "isochronous"; | ||
261 | break; | ||
262 | case USB_ENDPOINT_XFER_INT: | ||
263 | type = "interrupt"; | ||
264 | break; | ||
265 | case USB_ENDPOINT_XFER_CONTROL: | ||
266 | type = "control"; | ||
267 | break; | ||
268 | case USB_ENDPOINT_XFER_BULK: | ||
269 | type = "bulk"; | ||
270 | break; | ||
271 | default: | ||
272 | type = "?"; | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Type = %s\n", type); | ||
277 | |||
278 | if (qh->ep_type == USB_ENDPOINT_XFER_INT) { | ||
279 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - usecs = %d\n", | ||
280 | qh->host_us); | ||
281 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - interval = %d\n", | ||
282 | qh->host_interval); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * dwc2_hcd_qh_create() - Allocates and initializes a QH | ||
288 | * | ||
289 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
290 | * @urb: Holds the information about the device/endpoint needed | ||
291 | * to initialize the QH | ||
292 | * @atomic_alloc: Flag to do atomic allocation if needed | ||
293 | * | ||
294 | * Return: Pointer to the newly allocated QH, or NULL on error | ||
295 | */ | ||
296 | struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, | ||
297 | struct dwc2_hcd_urb *urb, | ||
298 | gfp_t mem_flags) | ||
299 | { | ||
300 | struct dwc2_qh *qh; | ||
301 | |||
302 | if (!urb->priv) | ||
303 | return NULL; | ||
304 | |||
305 | /* Allocate memory */ | ||
306 | qh = kzalloc(sizeof(*qh), mem_flags); | ||
307 | if (!qh) | ||
308 | return NULL; | ||
309 | |||
310 | dwc2_qh_init(hsotg, qh, urb); | ||
311 | |||
312 | if (hsotg->core_params->dma_desc_enable > 0 && | ||
313 | dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) { | ||
314 | dwc2_hcd_qh_free(hsotg, qh); | ||
315 | return NULL; | ||
316 | } | ||
317 | |||
318 | return qh; | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * dwc2_hcd_qh_free() - Frees the QH | ||
323 | * | ||
324 | * @hsotg: HCD instance | ||
325 | * @qh: The QH to free | ||
326 | * | ||
327 | * QH should already be removed from the list. QTD list should already be empty | ||
328 | * if called from URB Dequeue. | ||
329 | * | ||
330 | * Must NOT be called with interrupt disabled or spinlock held | ||
331 | */ | ||
332 | void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | ||
333 | { | ||
334 | /* Make sure any unreserve work is finished. */ | ||
335 | if (del_timer_sync(&qh->unreserve_timer)) { | ||
336 | unsigned long flags; | ||
337 | |||
338 | spin_lock_irqsave(&hsotg->lock, flags); | ||
339 | dwc2_do_unreserve(hsotg, qh); | ||
340 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
341 | } | ||
342 | |||
343 | if (qh->desc_list) | ||
344 | dwc2_hcd_qh_free_ddma(hsotg, qh); | ||
345 | kfree(qh); | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * dwc2_periodic_channel_available() - Checks that a channel is available for a | 60 | * dwc2_periodic_channel_available() - Checks that a channel is available for a |
350 | * periodic transfer | 61 | * periodic transfer |
351 | * | 62 | * |
@@ -534,6 +245,91 @@ static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | |||
534 | } | 245 | } |
535 | 246 | ||
536 | /** | 247 | /** |
248 | * dwc2_do_unreserve() - Actually release the periodic reservation | ||
249 | * | ||
250 | * This function actually releases the periodic bandwidth that was reserved | ||
251 | * by the given qh. | ||
252 | * | ||
253 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
254 | * @qh: QH for the periodic transfer. | ||
255 | */ | ||
256 | static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | ||
257 | { | ||
258 | assert_spin_locked(&hsotg->lock); | ||
259 | |||
260 | WARN_ON(!qh->unreserve_pending); | ||
261 | |||
262 | /* No more unreserve pending--we're doing it */ | ||
263 | qh->unreserve_pending = false; | ||
264 | |||
265 | if (WARN_ON(!list_empty(&qh->qh_list_entry))) | ||
266 | list_del_init(&qh->qh_list_entry); | ||
267 | |||
268 | /* Update claimed usecs per (micro)frame */ | ||
269 | hsotg->periodic_usecs -= qh->host_us; | ||
270 | |||
271 | if (hsotg->core_params->uframe_sched > 0) { | ||
272 | int i; | ||
273 | |||
274 | for (i = 0; i < 8; i++) { | ||
275 | hsotg->frame_usecs[i] += qh->frame_usecs[i]; | ||
276 | qh->frame_usecs[i] = 0; | ||
277 | } | ||
278 | } else { | ||
279 | /* Release periodic channel reservation */ | ||
280 | hsotg->periodic_channels--; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * dwc2_unreserve_timer_fn() - Timer function to release periodic reservation | ||
286 | * | ||
287 | * According to the kernel doc for usb_submit_urb() (specifically the part about | ||
288 | * "Reserved Bandwidth Transfers"), we need to keep a reservation active as | ||
289 | * long as a device driver keeps submitting. Since we're using HCD_BH to give | ||
290 | * back the URB we need to give the driver a little bit of time before we | ||
291 | * release the reservation. This worker is called after the appropriate | ||
292 | * delay. | ||
293 | * | ||
294 | * @work: Pointer to a qh unreserve_work. | ||
295 | */ | ||
296 | static void dwc2_unreserve_timer_fn(unsigned long data) | ||
297 | { | ||
298 | struct dwc2_qh *qh = (struct dwc2_qh *)data; | ||
299 | struct dwc2_hsotg *hsotg = qh->hsotg; | ||
300 | unsigned long flags; | ||
301 | |||
302 | /* | ||
303 | * Wait for the lock, or for us to be scheduled again. We | ||
304 | * could be scheduled again if: | ||
305 | * - We started executing but didn't get the lock yet. | ||
306 | * - A new reservation came in, but cancel didn't take effect | ||
307 | * because we already started executing. | ||
308 | * - The timer has been kicked again. | ||
309 | * In that case cancel and wait for the next call. | ||
310 | */ | ||
311 | while (!spin_trylock_irqsave(&hsotg->lock, flags)) { | ||
312 | if (timer_pending(&qh->unreserve_timer)) | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * Might be no more unreserve pending if: | ||
318 | * - We started executing but didn't get the lock yet. | ||
319 | * - A new reservation came in, but cancel didn't take effect | ||
320 | * because we already started executing. | ||
321 | * | ||
322 | * We can't put this in the loop above because unreserve_pending needs | ||
323 | * to be accessed under lock, so we can only check it once we got the | ||
324 | * lock. | ||
325 | */ | ||
326 | if (qh->unreserve_pending) | ||
327 | dwc2_do_unreserve(hsotg, qh); | ||
328 | |||
329 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
330 | } | ||
331 | |||
332 | /** | ||
537 | * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a | 333 | * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a |
538 | * host channel is large enough to handle the maximum data transfer in a single | 334 | * host channel is large enough to handle the maximum data transfer in a single |
539 | * (micro)frame for a periodic transfer | 335 | * (micro)frame for a periodic transfer |
@@ -695,6 +491,210 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, | |||
695 | } | 491 | } |
696 | 492 | ||
697 | /** | 493 | /** |
494 | * dwc2_qh_init() - Initializes a QH structure | ||
495 | * | ||
496 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
497 | * @qh: The QH to init | ||
498 | * @urb: Holds the information about the device/endpoint needed to initialize | ||
499 | * the QH | ||
500 | */ | ||
501 | #define SCHEDULE_SLOP 10 | ||
502 | static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | ||
503 | struct dwc2_hcd_urb *urb) | ||
504 | { | ||
505 | int dev_speed, hub_addr, hub_port; | ||
506 | char *speed, *type; | ||
507 | |||
508 | dev_vdbg(hsotg->dev, "%s()\n", __func__); | ||
509 | |||
510 | /* Initialize QH */ | ||
511 | qh->hsotg = hsotg; | ||
512 | setup_timer(&qh->unreserve_timer, dwc2_unreserve_timer_fn, | ||
513 | (unsigned long)qh); | ||
514 | qh->ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info); | ||
515 | qh->ep_is_in = dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; | ||
516 | |||
517 | qh->data_toggle = DWC2_HC_PID_DATA0; | ||
518 | qh->maxp = dwc2_hcd_get_mps(&urb->pipe_info); | ||
519 | INIT_LIST_HEAD(&qh->qtd_list); | ||
520 | INIT_LIST_HEAD(&qh->qh_list_entry); | ||
521 | |||
522 | /* FS/LS Endpoint on HS Hub, NOT virtual root hub */ | ||
523 | dev_speed = dwc2_host_get_speed(hsotg, urb->priv); | ||
524 | |||
525 | dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port); | ||
526 | |||
527 | if ((dev_speed == USB_SPEED_LOW || dev_speed == USB_SPEED_FULL) && | ||
528 | hub_addr != 0 && hub_addr != 1) { | ||
529 | dev_vdbg(hsotg->dev, | ||
530 | "QH init: EP %d: TT found at hub addr %d, for port %d\n", | ||
531 | dwc2_hcd_get_ep_num(&urb->pipe_info), hub_addr, | ||
532 | hub_port); | ||
533 | qh->do_split = 1; | ||
534 | } | ||
535 | |||
536 | if (qh->ep_type == USB_ENDPOINT_XFER_INT || | ||
537 | qh->ep_type == USB_ENDPOINT_XFER_ISOC) { | ||
538 | /* Compute scheduling parameters once and save them */ | ||
539 | u32 hprt, prtspd; | ||
540 | |||
541 | /* Todo: Account for split transfers in the bus time */ | ||
542 | int bytecount = | ||
543 | dwc2_hb_mult(qh->maxp) * dwc2_max_packet(qh->maxp); | ||
544 | |||
545 | qh->host_us = NS_TO_US(usb_calc_bus_time(qh->do_split ? | ||
546 | USB_SPEED_HIGH : dev_speed, qh->ep_is_in, | ||
547 | qh->ep_type == USB_ENDPOINT_XFER_ISOC, | ||
548 | bytecount)); | ||
549 | |||
550 | /* Ensure frame_number corresponds to the reality */ | ||
551 | hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg); | ||
552 | /* Start in a slightly future (micro)frame */ | ||
553 | qh->next_active_frame = dwc2_frame_num_inc(hsotg->frame_number, | ||
554 | SCHEDULE_SLOP); | ||
555 | qh->host_interval = urb->interval; | ||
556 | dwc2_sch_dbg(hsotg, "QH=%p init nxt=%04x, fn=%04x, int=%#x\n", | ||
557 | qh, qh->next_active_frame, hsotg->frame_number, | ||
558 | qh->host_interval); | ||
559 | #if 0 | ||
560 | /* Increase interrupt polling rate for debugging */ | ||
561 | if (qh->ep_type == USB_ENDPOINT_XFER_INT) | ||
562 | qh->host_interval = 8; | ||
563 | #endif | ||
564 | hprt = dwc2_readl(hsotg->regs + HPRT0); | ||
565 | prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT; | ||
566 | if (prtspd == HPRT0_SPD_HIGH_SPEED && | ||
567 | (dev_speed == USB_SPEED_LOW || | ||
568 | dev_speed == USB_SPEED_FULL)) { | ||
569 | qh->host_interval *= 8; | ||
570 | qh->next_active_frame |= 0x7; | ||
571 | qh->start_split_frame = qh->next_active_frame; | ||
572 | dwc2_sch_dbg(hsotg, | ||
573 | "QH=%p init*8 nxt=%04x, fn=%04x, int=%#x\n", | ||
574 | qh, qh->next_active_frame, | ||
575 | hsotg->frame_number, qh->host_interval); | ||
576 | |||
577 | } | ||
578 | dev_dbg(hsotg->dev, "interval=%d\n", qh->host_interval); | ||
579 | } | ||
580 | |||
581 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH Initialized\n"); | ||
582 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - qh = %p\n", qh); | ||
583 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Device Address = %d\n", | ||
584 | dwc2_hcd_get_dev_addr(&urb->pipe_info)); | ||
585 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Endpoint %d, %s\n", | ||
586 | dwc2_hcd_get_ep_num(&urb->pipe_info), | ||
587 | dwc2_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); | ||
588 | |||
589 | qh->dev_speed = dev_speed; | ||
590 | |||
591 | switch (dev_speed) { | ||
592 | case USB_SPEED_LOW: | ||
593 | speed = "low"; | ||
594 | break; | ||
595 | case USB_SPEED_FULL: | ||
596 | speed = "full"; | ||
597 | break; | ||
598 | case USB_SPEED_HIGH: | ||
599 | speed = "high"; | ||
600 | break; | ||
601 | default: | ||
602 | speed = "?"; | ||
603 | break; | ||
604 | } | ||
605 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Speed = %s\n", speed); | ||
606 | |||
607 | switch (qh->ep_type) { | ||
608 | case USB_ENDPOINT_XFER_ISOC: | ||
609 | type = "isochronous"; | ||
610 | break; | ||
611 | case USB_ENDPOINT_XFER_INT: | ||
612 | type = "interrupt"; | ||
613 | break; | ||
614 | case USB_ENDPOINT_XFER_CONTROL: | ||
615 | type = "control"; | ||
616 | break; | ||
617 | case USB_ENDPOINT_XFER_BULK: | ||
618 | type = "bulk"; | ||
619 | break; | ||
620 | default: | ||
621 | type = "?"; | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Type = %s\n", type); | ||
626 | |||
627 | if (qh->ep_type == USB_ENDPOINT_XFER_INT) { | ||
628 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - usecs = %d\n", | ||
629 | qh->host_us); | ||
630 | dev_vdbg(hsotg->dev, "DWC OTG HCD QH - interval = %d\n", | ||
631 | qh->host_interval); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | /** | ||
636 | * dwc2_hcd_qh_create() - Allocates and initializes a QH | ||
637 | * | ||
638 | * @hsotg: The HCD state structure for the DWC OTG controller | ||
639 | * @urb: Holds the information about the device/endpoint needed | ||
640 | * to initialize the QH | ||
641 | * @atomic_alloc: Flag to do atomic allocation if needed | ||
642 | * | ||
643 | * Return: Pointer to the newly allocated QH, or NULL on error | ||
644 | */ | ||
645 | struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, | ||
646 | struct dwc2_hcd_urb *urb, | ||
647 | gfp_t mem_flags) | ||
648 | { | ||
649 | struct dwc2_qh *qh; | ||
650 | |||
651 | if (!urb->priv) | ||
652 | return NULL; | ||
653 | |||
654 | /* Allocate memory */ | ||
655 | qh = kzalloc(sizeof(*qh), mem_flags); | ||
656 | if (!qh) | ||
657 | return NULL; | ||
658 | |||
659 | dwc2_qh_init(hsotg, qh, urb); | ||
660 | |||
661 | if (hsotg->core_params->dma_desc_enable > 0 && | ||
662 | dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) { | ||
663 | dwc2_hcd_qh_free(hsotg, qh); | ||
664 | return NULL; | ||
665 | } | ||
666 | |||
667 | return qh; | ||
668 | } | ||
669 | |||
670 | /** | ||
671 | * dwc2_hcd_qh_free() - Frees the QH | ||
672 | * | ||
673 | * @hsotg: HCD instance | ||
674 | * @qh: The QH to free | ||
675 | * | ||
676 | * QH should already be removed from the list. QTD list should already be empty | ||
677 | * if called from URB Dequeue. | ||
678 | * | ||
679 | * Must NOT be called with interrupt disabled or spinlock held | ||
680 | */ | ||
681 | void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | ||
682 | { | ||
683 | /* Make sure any unreserve work is finished. */ | ||
684 | if (del_timer_sync(&qh->unreserve_timer)) { | ||
685 | unsigned long flags; | ||
686 | |||
687 | spin_lock_irqsave(&hsotg->lock, flags); | ||
688 | dwc2_do_unreserve(hsotg, qh); | ||
689 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
690 | } | ||
691 | |||
692 | if (qh->desc_list) | ||
693 | dwc2_hcd_qh_free_ddma(hsotg, qh); | ||
694 | kfree(qh); | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic | 698 | * dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic |
699 | * schedule if it is not already in the schedule. If the QH is already in | 699 | * schedule if it is not already in the schedule. If the QH is already in |
700 | * the schedule, no action is taken. | 700 | * the schedule, no action is taken. |