1*b378d10eSskrll /* $NetBSD: dwc2_hcdqueue.c,v 1.16 2021/12/21 09:51:22 skrll Exp $ */
2244c883eSskrll
3970b0700Sskrll /*
4970b0700Sskrll * hcd_queue.c - DesignWare HS OTG Controller host queuing routines
5970b0700Sskrll *
6970b0700Sskrll * Copyright (C) 2004-2013 Synopsys, Inc.
7970b0700Sskrll *
8970b0700Sskrll * Redistribution and use in source and binary forms, with or without
9970b0700Sskrll * modification, are permitted provided that the following conditions
10970b0700Sskrll * are met:
11970b0700Sskrll * 1. Redistributions of source code must retain the above copyright
12970b0700Sskrll * notice, this list of conditions, and the following disclaimer,
13970b0700Sskrll * without modification.
14970b0700Sskrll * 2. Redistributions in binary form must reproduce the above copyright
15970b0700Sskrll * notice, this list of conditions and the following disclaimer in the
16970b0700Sskrll * documentation and/or other materials provided with the distribution.
17970b0700Sskrll * 3. The names of the above-listed copyright holders may not be used
18970b0700Sskrll * to endorse or promote products derived from this software without
19970b0700Sskrll * specific prior written permission.
20970b0700Sskrll *
21970b0700Sskrll * ALTERNATIVELY, this software may be distributed under the terms of the
22970b0700Sskrll * GNU General Public License ("GPL") as published by the Free Software
23970b0700Sskrll * Foundation; either version 2 of the License, or (at your option) any
24970b0700Sskrll * later version.
25970b0700Sskrll *
26970b0700Sskrll * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
27970b0700Sskrll * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
28970b0700Sskrll * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29970b0700Sskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30970b0700Sskrll * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31970b0700Sskrll * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32970b0700Sskrll * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33970b0700Sskrll * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34970b0700Sskrll * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35970b0700Sskrll * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36970b0700Sskrll * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37970b0700Sskrll */
38970b0700Sskrll
39970b0700Sskrll /*
40970b0700Sskrll * This file contains the functions to manage Queue Heads and Queue
41970b0700Sskrll * Transfer Descriptors for Host mode
42970b0700Sskrll */
43c8117e49Sskrll
44c8117e49Sskrll #include <sys/cdefs.h>
45*b378d10eSskrll __KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.16 2021/12/21 09:51:22 skrll Exp $");
46c8117e49Sskrll
47c8117e49Sskrll #include <sys/types.h>
48c8117e49Sskrll #include <sys/kmem.h>
49c8117e49Sskrll #include <sys/pool.h>
50c8117e49Sskrll
51c8117e49Sskrll #include <dev/usb/usb.h>
52c8117e49Sskrll #include <dev/usb/usbdi.h>
53c8117e49Sskrll #include <dev/usb/usbdivar.h>
54c8117e49Sskrll #include <dev/usb/usb_mem.h>
55c8117e49Sskrll
56c8117e49Sskrll #include <machine/param.h>
57c8117e49Sskrll
58970b0700Sskrll #include <linux/kernel.h>
59970b0700Sskrll
60c8117e49Sskrll #include <dwc2/dwc2.h>
61c8117e49Sskrll #include <dwc2/dwc2var.h>
62970b0700Sskrll
63c8117e49Sskrll #include "dwc2_core.h"
64c8117e49Sskrll #include "dwc2_hcd.h"
65c8117e49Sskrll
66c8117e49Sskrll static u32 dwc2_calc_bus_time(struct dwc2_hsotg *, int, int, int, int);
6746b04be8Ssimonb static void dwc2_wait_timer_fn(void *);
6846b04be8Ssimonb
6946b04be8Ssimonb /* If we get a NAK, wait this long before retrying */
7046b04be8Ssimonb #define DWC2_RETRY_WAIT_DELAY 1 /* msec */
71970b0700Sskrll
72970b0700Sskrll /**
73970b0700Sskrll * dwc2_qh_init() - Initializes a QH structure
74970b0700Sskrll *
75970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
76970b0700Sskrll * @qh: The QH to init
77970b0700Sskrll * @urb: Holds the information about the device/endpoint needed to initialize
78970b0700Sskrll * the QH
79970b0700Sskrll */
80970b0700Sskrll #define SCHEDULE_SLOP 10
dwc2_qh_init(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh,struct dwc2_hcd_urb * urb)81970b0700Sskrll static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
82970b0700Sskrll struct dwc2_hcd_urb *urb)
83970b0700Sskrll {
84970b0700Sskrll int dev_speed, hub_addr, hub_port;
85970b0700Sskrll
86970b0700Sskrll dev_vdbg(hsotg->dev, "%s()\n", __func__);
87970b0700Sskrll
88970b0700Sskrll /* Initialize QH */
8946b04be8Ssimonb qh->hsotg = hsotg;
9046b04be8Ssimonb /* XXX timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0); */
9146b04be8Ssimonb callout_init(&qh->wait_timer, 0);
9246b04be8Ssimonb callout_setfunc(&qh->wait_timer, dwc2_wait_timer_fn, qh);
93970b0700Sskrll qh->ep_type = dwc2_hcd_get_pipe_type(&urb->pipe_info);
94970b0700Sskrll qh->ep_is_in = dwc2_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0;
95970b0700Sskrll
96970b0700Sskrll qh->data_toggle = DWC2_HC_PID_DATA0;
97970b0700Sskrll qh->maxp = dwc2_hcd_get_mps(&urb->pipe_info);
98970b0700Sskrll INIT_LIST_HEAD(&qh->qtd_list);
99970b0700Sskrll INIT_LIST_HEAD(&qh->qh_list_entry);
100970b0700Sskrll
101970b0700Sskrll /* FS/LS Endpoint on HS Hub, NOT virtual root hub */
102970b0700Sskrll dev_speed = dwc2_host_get_speed(hsotg, urb->priv);
103970b0700Sskrll
104970b0700Sskrll dwc2_host_hub_info(hsotg, urb->priv, &hub_addr, &hub_port);
105df4a329dSskrll qh->nak_frame = 0xffff;
106970b0700Sskrll
107970b0700Sskrll if ((dev_speed == USB_SPEED_LOW || dev_speed == USB_SPEED_FULL) &&
108970b0700Sskrll hub_addr != 0 && hub_addr != 1) {
109970b0700Sskrll dev_vdbg(hsotg->dev,
110970b0700Sskrll "QH init: EP %d: TT found at hub addr %d, for port %d\n",
111970b0700Sskrll dwc2_hcd_get_ep_num(&urb->pipe_info), hub_addr,
112970b0700Sskrll hub_port);
113970b0700Sskrll qh->do_split = 1;
114970b0700Sskrll }
115970b0700Sskrll
116970b0700Sskrll if (qh->ep_type == USB_ENDPOINT_XFER_INT ||
117970b0700Sskrll qh->ep_type == USB_ENDPOINT_XFER_ISOC) {
118970b0700Sskrll /* Compute scheduling parameters once and save them */
119970b0700Sskrll u32 hprt, prtspd;
120970b0700Sskrll
121970b0700Sskrll /* Todo: Account for split transfers in the bus time */
122970b0700Sskrll int bytecount =
123970b0700Sskrll dwc2_hb_mult(qh->maxp) * dwc2_max_packet(qh->maxp);
124970b0700Sskrll
125c8117e49Sskrll qh->usecs = dwc2_calc_bus_time(hsotg, qh->do_split ?
126970b0700Sskrll USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
127970b0700Sskrll qh->ep_type == USB_ENDPOINT_XFER_ISOC,
128c8117e49Sskrll bytecount);
1295064f7beSskrll
1305064f7beSskrll /* Ensure frame_number corresponds to the reality */
1315064f7beSskrll hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
132970b0700Sskrll /* Start in a slightly future (micro)frame */
133970b0700Sskrll qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
134970b0700Sskrll SCHEDULE_SLOP);
135970b0700Sskrll qh->interval = urb->interval;
136970b0700Sskrll #if 0
137970b0700Sskrll /* Increase interrupt polling rate for debugging */
138970b0700Sskrll if (qh->ep_type == USB_ENDPOINT_XFER_INT)
139970b0700Sskrll qh->interval = 8;
140970b0700Sskrll #endif
141c8117e49Sskrll hprt = DWC2_READ_4(hsotg, HPRT0);
142cb22e524Sskrll prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
143970b0700Sskrll if (prtspd == HPRT0_SPD_HIGH_SPEED &&
144970b0700Sskrll (dev_speed == USB_SPEED_LOW ||
145970b0700Sskrll dev_speed == USB_SPEED_FULL)) {
146970b0700Sskrll qh->interval *= 8;
147970b0700Sskrll qh->sched_frame |= 0x7;
148970b0700Sskrll qh->start_split_frame = qh->sched_frame;
149970b0700Sskrll }
150970b0700Sskrll dev_dbg(hsotg->dev, "interval=%d\n", qh->interval);
151970b0700Sskrll }
152970b0700Sskrll
153970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH Initialized\n");
154970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - qh = %p\n", qh);
155970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Device Address = %d\n",
156970b0700Sskrll dwc2_hcd_get_dev_addr(&urb->pipe_info));
157970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Endpoint %d, %s\n",
158970b0700Sskrll dwc2_hcd_get_ep_num(&urb->pipe_info),
159970b0700Sskrll dwc2_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT");
160970b0700Sskrll
161970b0700Sskrll qh->dev_speed = dev_speed;
162970b0700Sskrll
163e4c22c37Sskrll #ifdef DWC2_DEBUG
164e4c22c37Sskrll const char *speed, *type;
165970b0700Sskrll switch (dev_speed) {
166970b0700Sskrll case USB_SPEED_LOW:
167970b0700Sskrll speed = "low";
168970b0700Sskrll break;
169970b0700Sskrll case USB_SPEED_FULL:
170970b0700Sskrll speed = "full";
171970b0700Sskrll break;
172970b0700Sskrll case USB_SPEED_HIGH:
173970b0700Sskrll speed = "high";
174970b0700Sskrll break;
175970b0700Sskrll default:
176970b0700Sskrll speed = "?";
177970b0700Sskrll break;
178970b0700Sskrll }
179970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Speed = %s\n", speed);
180970b0700Sskrll
181970b0700Sskrll switch (qh->ep_type) {
182970b0700Sskrll case USB_ENDPOINT_XFER_ISOC:
183970b0700Sskrll type = "isochronous";
184970b0700Sskrll break;
185970b0700Sskrll case USB_ENDPOINT_XFER_INT:
186970b0700Sskrll type = "interrupt";
187970b0700Sskrll break;
188970b0700Sskrll case USB_ENDPOINT_XFER_CONTROL:
189970b0700Sskrll type = "control";
190970b0700Sskrll break;
191970b0700Sskrll case USB_ENDPOINT_XFER_BULK:
192970b0700Sskrll type = "bulk";
193970b0700Sskrll break;
194970b0700Sskrll default:
195970b0700Sskrll type = "?";
196970b0700Sskrll break;
197970b0700Sskrll }
198970b0700Sskrll
199970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - Type = %s\n", type);
200e4c22c37Sskrll #endif
201970b0700Sskrll
202970b0700Sskrll if (qh->ep_type == USB_ENDPOINT_XFER_INT) {
203970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - usecs = %d\n",
204970b0700Sskrll qh->usecs);
205970b0700Sskrll dev_vdbg(hsotg->dev, "DWC OTG HCD QH - interval = %d\n",
206970b0700Sskrll qh->interval);
207970b0700Sskrll }
208970b0700Sskrll }
209970b0700Sskrll
210970b0700Sskrll /**
211970b0700Sskrll * dwc2_hcd_qh_create() - Allocates and initializes a QH
212970b0700Sskrll *
213970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
214970b0700Sskrll * @urb: Holds the information about the device/endpoint needed
215970b0700Sskrll * to initialize the QH
216cb22e524Sskrll * @mem_flags: Flag to do atomic allocation if needed
217970b0700Sskrll *
218970b0700Sskrll * Return: Pointer to the newly allocated QH, or NULL on error
219970b0700Sskrll */
dwc2_hcd_qh_create(struct dwc2_hsotg * hsotg,struct dwc2_hcd_urb * urb,gfp_t mem_flags)2209c7e1469Sskrll struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
221970b0700Sskrll struct dwc2_hcd_urb *urb,
222970b0700Sskrll gfp_t mem_flags)
223970b0700Sskrll {
224c8117e49Sskrll struct dwc2_softc *sc = hsotg->hsotg_sc;
225970b0700Sskrll struct dwc2_qh *qh;
226970b0700Sskrll
227970b0700Sskrll if (!urb->priv)
228970b0700Sskrll return NULL;
229970b0700Sskrll
230970b0700Sskrll /* Allocate memory */
231c8117e49Sskrll qh = pool_cache_get(sc->sc_qhpool, PR_NOWAIT);
232970b0700Sskrll if (!qh)
233970b0700Sskrll return NULL;
234970b0700Sskrll
235c8117e49Sskrll memset(qh, 0, sizeof(*qh));
236970b0700Sskrll dwc2_qh_init(hsotg, qh, urb);
237970b0700Sskrll
238970b0700Sskrll if (hsotg->core_params->dma_desc_enable > 0 &&
239970b0700Sskrll dwc2_hcd_qh_init_ddma(hsotg, qh, mem_flags) < 0) {
240970b0700Sskrll dwc2_hcd_qh_free(hsotg, qh);
241970b0700Sskrll return NULL;
242970b0700Sskrll }
243970b0700Sskrll
244970b0700Sskrll return qh;
245970b0700Sskrll }
246970b0700Sskrll
247970b0700Sskrll /**
248970b0700Sskrll * dwc2_hcd_qh_free() - Frees the QH
249970b0700Sskrll *
250970b0700Sskrll * @hsotg: HCD instance
251970b0700Sskrll * @qh: The QH to free
252970b0700Sskrll *
253970b0700Sskrll * QH should already be removed from the list. QTD list should already be empty
254970b0700Sskrll * if called from URB Dequeue.
255970b0700Sskrll *
256970b0700Sskrll * Must NOT be called with interrupt disabled or spinlock held
257970b0700Sskrll */
dwc2_hcd_qh_free(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)258970b0700Sskrll void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
259970b0700Sskrll {
260c8117e49Sskrll struct dwc2_softc *sc = hsotg->hsotg_sc;
26146b04be8Ssimonb
26246b04be8Ssimonb /*
26346b04be8Ssimonb * We don't have the lock so we can safely wait until the wait timer
26446b04be8Ssimonb * finishes. Of course, at this point in time we'd better have set
26546b04be8Ssimonb * wait_timer_active to false so if this timer was still pending it
26646b04be8Ssimonb * won't do anything anyway, but we want it to finish before we free
26746b04be8Ssimonb * memory.
26846b04be8Ssimonb */
26946b04be8Ssimonb /* XXX del_timer_sync(&qh->wait_timer); */
27046b04be8Ssimonb callout_destroy(&qh->wait_timer); /* XXX need to callout_halt() first? */
27146b04be8Ssimonb
2725064f7beSskrll if (qh->desc_list) {
273970b0700Sskrll dwc2_hcd_qh_free_ddma(hsotg, qh);
274970b0700Sskrll } else if (qh->dw_align_buf) {
275*b378d10eSskrll usb_freemem(&qh->dw_align_buf_usbdma);
2769c7e1469Sskrll qh->dw_align_buf_dma = (dma_addr_t)0;
277970b0700Sskrll }
278970b0700Sskrll
279c8117e49Sskrll pool_cache_put(sc->sc_qhpool, qh);
280970b0700Sskrll }
281970b0700Sskrll
282970b0700Sskrll /**
283970b0700Sskrll * dwc2_periodic_channel_available() - Checks that a channel is available for a
284970b0700Sskrll * periodic transfer
285970b0700Sskrll *
286970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
287970b0700Sskrll *
288cb22e524Sskrll * Return: 0 if successful, negative error code otherwise
289970b0700Sskrll */
dwc2_periodic_channel_available(struct dwc2_hsotg * hsotg)290970b0700Sskrll static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
291970b0700Sskrll {
292970b0700Sskrll /*
293cb22e524Sskrll * Currently assuming that there is a dedicated host channel for
294970b0700Sskrll * each periodic transaction plus at least one host channel for
295970b0700Sskrll * non-periodic transactions
296970b0700Sskrll */
297970b0700Sskrll int status;
298970b0700Sskrll int num_channels;
299970b0700Sskrll
300970b0700Sskrll num_channels = hsotg->core_params->host_channels;
301970b0700Sskrll if (hsotg->periodic_channels + hsotg->non_periodic_channels <
302970b0700Sskrll num_channels
303970b0700Sskrll && hsotg->periodic_channels < num_channels - 1) {
304970b0700Sskrll status = 0;
305970b0700Sskrll } else {
306970b0700Sskrll dev_dbg(hsotg->dev,
307970b0700Sskrll "%s: Total channels: %d, Periodic: %d, "
308970b0700Sskrll "Non-periodic: %d\n", __func__, num_channels,
309970b0700Sskrll hsotg->periodic_channels, hsotg->non_periodic_channels);
310970b0700Sskrll status = -ENOSPC;
311970b0700Sskrll }
312970b0700Sskrll
313970b0700Sskrll return status;
314970b0700Sskrll }
315970b0700Sskrll
316970b0700Sskrll /**
317970b0700Sskrll * dwc2_check_periodic_bandwidth() - Checks that there is sufficient bandwidth
318970b0700Sskrll * for the specified QH in the periodic schedule
319970b0700Sskrll *
320970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
321970b0700Sskrll * @qh: QH containing periodic bandwidth required
322970b0700Sskrll *
323970b0700Sskrll * Return: 0 if successful, negative error code otherwise
324970b0700Sskrll *
325970b0700Sskrll * For simplicity, this calculation assumes that all the transfers in the
326970b0700Sskrll * periodic schedule may occur in the same (micro)frame
327970b0700Sskrll */
dwc2_check_periodic_bandwidth(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)328970b0700Sskrll static int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg,
329970b0700Sskrll struct dwc2_qh *qh)
330970b0700Sskrll {
331970b0700Sskrll int status;
332970b0700Sskrll s16 max_claimed_usecs;
333970b0700Sskrll
334970b0700Sskrll status = 0;
335970b0700Sskrll
336970b0700Sskrll if (qh->dev_speed == USB_SPEED_HIGH || qh->do_split) {
337970b0700Sskrll /*
338970b0700Sskrll * High speed mode
339970b0700Sskrll * Max periodic usecs is 80% x 125 usec = 100 usec
340970b0700Sskrll */
341970b0700Sskrll max_claimed_usecs = 100 - qh->usecs;
342970b0700Sskrll } else {
343970b0700Sskrll /*
344970b0700Sskrll * Full speed mode
345970b0700Sskrll * Max periodic usecs is 90% x 1000 usec = 900 usec
346970b0700Sskrll */
347970b0700Sskrll max_claimed_usecs = 900 - qh->usecs;
348970b0700Sskrll }
349970b0700Sskrll
350970b0700Sskrll if (hsotg->periodic_usecs > max_claimed_usecs) {
351970b0700Sskrll dev_err(hsotg->dev,
352970b0700Sskrll "%s: already claimed usecs %d, required usecs %d\n",
353970b0700Sskrll __func__, hsotg->periodic_usecs, qh->usecs);
354970b0700Sskrll status = -ENOSPC;
355970b0700Sskrll }
356970b0700Sskrll
357970b0700Sskrll return status;
358970b0700Sskrll }
359970b0700Sskrll
360970b0700Sskrll /**
361970b0700Sskrll * Microframe scheduler
362970b0700Sskrll * track the total use in hsotg->frame_usecs
363970b0700Sskrll * keep each qh use in qh->frame_usecs
364970b0700Sskrll * when surrendering the qh then donate the time back
365970b0700Sskrll */
366970b0700Sskrll static const unsigned short max_uframe_usecs[] = {
367970b0700Sskrll 100, 100, 100, 100, 100, 100, 30, 0
368970b0700Sskrll };
369970b0700Sskrll
dwc2_hcd_init_usecs(struct dwc2_hsotg * hsotg)370970b0700Sskrll void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg)
371970b0700Sskrll {
372970b0700Sskrll int i;
373970b0700Sskrll
374970b0700Sskrll for (i = 0; i < 8; i++)
375970b0700Sskrll hsotg->frame_usecs[i] = max_uframe_usecs[i];
376970b0700Sskrll }
377970b0700Sskrll
dwc2_find_single_uframe(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)378970b0700Sskrll static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
379970b0700Sskrll {
380970b0700Sskrll unsigned short utime = qh->usecs;
381661a0168Sskrll int i;
382970b0700Sskrll
383661a0168Sskrll for (i = 0; i < 8; i++) {
384970b0700Sskrll /* At the start hsotg->frame_usecs[i] = max_uframe_usecs[i] */
385970b0700Sskrll if (utime <= hsotg->frame_usecs[i]) {
386970b0700Sskrll hsotg->frame_usecs[i] -= utime;
387970b0700Sskrll qh->frame_usecs[i] += utime;
388661a0168Sskrll return i;
389970b0700Sskrll }
390970b0700Sskrll }
391f913003cSskrll return -ENOSPC;
392970b0700Sskrll }
393970b0700Sskrll
394970b0700Sskrll /*
395970b0700Sskrll * use this for FS apps that can span multiple uframes
396970b0700Sskrll */
dwc2_find_multi_uframe(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)397970b0700Sskrll static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
398970b0700Sskrll {
399970b0700Sskrll unsigned short utime = qh->usecs;
400970b0700Sskrll unsigned short xtime;
401661a0168Sskrll int t_left;
402661a0168Sskrll int i;
403970b0700Sskrll int j;
404661a0168Sskrll int k;
405970b0700Sskrll
406661a0168Sskrll for (i = 0; i < 8; i++) {
407661a0168Sskrll if (hsotg->frame_usecs[i] <= 0)
408970b0700Sskrll continue;
409970b0700Sskrll
410970b0700Sskrll /*
411970b0700Sskrll * we need n consecutive slots so use j as a start slot
412970b0700Sskrll * j plus j+1 must be enough time (for now)
413970b0700Sskrll */
414970b0700Sskrll xtime = hsotg->frame_usecs[i];
415970b0700Sskrll for (j = i + 1; j < 8; j++) {
416970b0700Sskrll /*
417970b0700Sskrll * if we add this frame remaining time to xtime we may
418970b0700Sskrll * be OK, if not we need to test j for a complete frame
419970b0700Sskrll */
420970b0700Sskrll if (xtime + hsotg->frame_usecs[j] < utime) {
421970b0700Sskrll if (hsotg->frame_usecs[j] <
422661a0168Sskrll max_uframe_usecs[j])
423661a0168Sskrll continue;
424970b0700Sskrll }
425970b0700Sskrll if (xtime >= utime) {
426661a0168Sskrll t_left = utime;
427661a0168Sskrll for (k = i; k < 8; k++) {
428661a0168Sskrll t_left -= hsotg->frame_usecs[k];
429661a0168Sskrll if (t_left <= 0) {
430661a0168Sskrll qh->frame_usecs[k] +=
431661a0168Sskrll hsotg->frame_usecs[k]
432661a0168Sskrll + t_left;
433661a0168Sskrll hsotg->frame_usecs[k] = -t_left;
434661a0168Sskrll return i;
435661a0168Sskrll } else {
436661a0168Sskrll qh->frame_usecs[k] +=
437661a0168Sskrll hsotg->frame_usecs[k];
438661a0168Sskrll hsotg->frame_usecs[k] = 0;
439661a0168Sskrll }
440661a0168Sskrll }
441970b0700Sskrll }
442970b0700Sskrll /* add the frame time to x time */
443970b0700Sskrll xtime += hsotg->frame_usecs[j];
444970b0700Sskrll /* we must have a fully available next frame or break */
445970b0700Sskrll if (xtime < utime &&
446661a0168Sskrll hsotg->frame_usecs[j] == max_uframe_usecs[j])
447661a0168Sskrll continue;
448970b0700Sskrll }
449970b0700Sskrll }
450f913003cSskrll return -ENOSPC;
451970b0700Sskrll }
452970b0700Sskrll
dwc2_find_uframe(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)453970b0700Sskrll static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
454970b0700Sskrll {
455970b0700Sskrll int ret;
456970b0700Sskrll
457970b0700Sskrll if (qh->dev_speed == USB_SPEED_HIGH) {
458970b0700Sskrll /* if this is a hs transaction we need a full frame */
459970b0700Sskrll ret = dwc2_find_single_uframe(hsotg, qh);
460970b0700Sskrll } else {
461970b0700Sskrll /*
462970b0700Sskrll * if this is a fs transaction we may need a sequence
463970b0700Sskrll * of frames
464970b0700Sskrll */
465970b0700Sskrll ret = dwc2_find_multi_uframe(hsotg, qh);
466970b0700Sskrll }
467970b0700Sskrll return ret;
468970b0700Sskrll }
469970b0700Sskrll
470970b0700Sskrll /**
471970b0700Sskrll * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a
472970b0700Sskrll * host channel is large enough to handle the maximum data transfer in a single
473970b0700Sskrll * (micro)frame for a periodic transfer
474970b0700Sskrll *
475970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
476970b0700Sskrll * @qh: QH for a periodic endpoint
477970b0700Sskrll *
478970b0700Sskrll * Return: 0 if successful, negative error code otherwise
479970b0700Sskrll */
dwc2_check_max_xfer_size(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)480970b0700Sskrll static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg,
481970b0700Sskrll struct dwc2_qh *qh)
482970b0700Sskrll {
483970b0700Sskrll u32 max_xfer_size;
484970b0700Sskrll u32 max_channel_xfer_size;
485970b0700Sskrll int status = 0;
486970b0700Sskrll
487970b0700Sskrll max_xfer_size = dwc2_max_packet(qh->maxp) * dwc2_hb_mult(qh->maxp);
488970b0700Sskrll max_channel_xfer_size = hsotg->core_params->max_transfer_size;
489970b0700Sskrll
490970b0700Sskrll if (max_xfer_size > max_channel_xfer_size) {
491970b0700Sskrll dev_err(hsotg->dev,
492970b0700Sskrll "%s: Periodic xfer length %d > max xfer length for channel %d\n",
493970b0700Sskrll __func__, max_xfer_size, max_channel_xfer_size);
494970b0700Sskrll status = -ENOSPC;
495970b0700Sskrll }
496970b0700Sskrll
497970b0700Sskrll return status;
498970b0700Sskrll }
499970b0700Sskrll
500970b0700Sskrll /**
501970b0700Sskrll * dwc2_schedule_periodic() - Schedules an interrupt or isochronous transfer in
502970b0700Sskrll * the periodic schedule
503970b0700Sskrll *
504970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
505970b0700Sskrll * @qh: QH for the periodic transfer. The QH should already contain the
506970b0700Sskrll * scheduling information.
507970b0700Sskrll *
508970b0700Sskrll * Return: 0 if successful, negative error code otherwise
509970b0700Sskrll */
dwc2_schedule_periodic(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)510970b0700Sskrll static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
511970b0700Sskrll {
512970b0700Sskrll int status;
513970b0700Sskrll
514970b0700Sskrll if (hsotg->core_params->uframe_sched > 0) {
515970b0700Sskrll int frame = -1;
516970b0700Sskrll
517970b0700Sskrll status = dwc2_find_uframe(hsotg, qh);
518970b0700Sskrll if (status == 0)
519970b0700Sskrll frame = 7;
520970b0700Sskrll else if (status > 0)
521970b0700Sskrll frame = status - 1;
522970b0700Sskrll
523970b0700Sskrll /* Set the new frame up */
524f913003cSskrll if (frame >= 0) {
525970b0700Sskrll qh->sched_frame &= ~0x7;
526970b0700Sskrll qh->sched_frame |= (frame & 7);
527970b0700Sskrll }
528970b0700Sskrll
529f913003cSskrll if (status > 0)
530970b0700Sskrll status = 0;
531970b0700Sskrll } else {
532970b0700Sskrll status = dwc2_periodic_channel_available(hsotg);
533970b0700Sskrll if (status) {
534970b0700Sskrll dev_info(hsotg->dev,
535970b0700Sskrll "%s: No host channel available for periodic transfer\n",
536970b0700Sskrll __func__);
537970b0700Sskrll return status;
538970b0700Sskrll }
539970b0700Sskrll
540970b0700Sskrll status = dwc2_check_periodic_bandwidth(hsotg, qh);
541970b0700Sskrll }
542970b0700Sskrll
543970b0700Sskrll if (status) {
544970b0700Sskrll dev_dbg(hsotg->dev,
545970b0700Sskrll "%s: Insufficient periodic bandwidth for periodic transfer\n",
546970b0700Sskrll __func__);
547970b0700Sskrll return status;
548970b0700Sskrll }
549970b0700Sskrll
550970b0700Sskrll status = dwc2_check_max_xfer_size(hsotg, qh);
551970b0700Sskrll if (status) {
552970b0700Sskrll dev_dbg(hsotg->dev,
553970b0700Sskrll "%s: Channel max transfer size too small for periodic transfer\n",
554970b0700Sskrll __func__);
555970b0700Sskrll return status;
556970b0700Sskrll }
557970b0700Sskrll
558cb22e524Sskrll if (hsotg->core_params->dma_desc_enable > 0)
559970b0700Sskrll /* Don't rely on SOF and start in ready schedule */
560970b0700Sskrll list_add_tail(&qh->qh_list_entry, &hsotg->periodic_sched_ready);
561cb22e524Sskrll else
562970b0700Sskrll /* Always start in inactive schedule */
563970b0700Sskrll list_add_tail(&qh->qh_list_entry,
564970b0700Sskrll &hsotg->periodic_sched_inactive);
565970b0700Sskrll
566970b0700Sskrll if (hsotg->core_params->uframe_sched <= 0)
567970b0700Sskrll /* Reserve periodic channel */
568970b0700Sskrll hsotg->periodic_channels++;
569970b0700Sskrll
570970b0700Sskrll /* Update claimed usecs per (micro)frame */
571970b0700Sskrll hsotg->periodic_usecs += qh->usecs;
572970b0700Sskrll
573970b0700Sskrll return status;
574970b0700Sskrll }
575970b0700Sskrll
576970b0700Sskrll /**
577970b0700Sskrll * dwc2_deschedule_periodic() - Removes an interrupt or isochronous transfer
578970b0700Sskrll * from the periodic schedule
579970b0700Sskrll *
580970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
581970b0700Sskrll * @qh: QH for the periodic transfer
582970b0700Sskrll */
dwc2_deschedule_periodic(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)583970b0700Sskrll static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
584970b0700Sskrll struct dwc2_qh *qh)
585970b0700Sskrll {
586970b0700Sskrll int i;
587970b0700Sskrll
588970b0700Sskrll list_del_init(&qh->qh_list_entry);
589970b0700Sskrll
590970b0700Sskrll /* Update claimed usecs per (micro)frame */
591970b0700Sskrll hsotg->periodic_usecs -= qh->usecs;
592970b0700Sskrll
593970b0700Sskrll if (hsotg->core_params->uframe_sched > 0) {
594970b0700Sskrll for (i = 0; i < 8; i++) {
595970b0700Sskrll hsotg->frame_usecs[i] += qh->frame_usecs[i];
596970b0700Sskrll qh->frame_usecs[i] = 0;
597970b0700Sskrll }
598970b0700Sskrll } else {
599970b0700Sskrll /* Release periodic channel reservation */
600970b0700Sskrll hsotg->periodic_channels--;
601970b0700Sskrll }
602970b0700Sskrll }
603970b0700Sskrll
604970b0700Sskrll /**
60546b04be8Ssimonb * dwc2_wait_timer_fn() - Timer function to re-queue after waiting
60646b04be8Ssimonb *
60746b04be8Ssimonb * As per the spec, a NAK indicates that "a function is temporarily unable to
60846b04be8Ssimonb * transmit or receive data, but will eventually be able to do so without need
60946b04be8Ssimonb * of host intervention".
61046b04be8Ssimonb *
61146b04be8Ssimonb * That means that when we encounter a NAK we're supposed to retry.
61246b04be8Ssimonb *
61346b04be8Ssimonb * ...but if we retry right away (from the interrupt handler that saw the NAK)
61446b04be8Ssimonb * then we can end up with an interrupt storm (if the other side keeps NAKing
61546b04be8Ssimonb * us) because on slow enough CPUs it could take us longer to get out of the
61646b04be8Ssimonb * interrupt routine than it takes for the device to send another NAK. That
61746b04be8Ssimonb * leads to a constant stream of NAK interrupts and the CPU locks.
61846b04be8Ssimonb *
61946b04be8Ssimonb * ...so instead of retrying right away in the case of a NAK we'll set a timer
62046b04be8Ssimonb * to retry some time later. This function handles that timer and moves the
62146b04be8Ssimonb * qh back to the "inactive" list, then queues transactions.
62246b04be8Ssimonb *
62346b04be8Ssimonb * @t: Pointer to wait_timer in a qh.
62446b04be8Ssimonb */
dwc2_wait_timer_fn(void * arg)62546b04be8Ssimonb static void dwc2_wait_timer_fn(void *arg)
62646b04be8Ssimonb {
62746b04be8Ssimonb struct dwc2_qh *qh = arg;
62846b04be8Ssimonb struct dwc2_hsotg *hsotg = qh->hsotg;
62946b04be8Ssimonb unsigned long flags;
63046b04be8Ssimonb
63146b04be8Ssimonb spin_lock_irqsave(&hsotg->lock, flags);
63246b04be8Ssimonb
63346b04be8Ssimonb /*
63446b04be8Ssimonb * We'll set wait_timer_cancel to true if we want to cancel this
63546b04be8Ssimonb * operation in dwc2_hcd_qh_unlink().
63646b04be8Ssimonb */
63746b04be8Ssimonb if (!qh->wait_timer_cancel) {
63846b04be8Ssimonb enum dwc2_transaction_type tr_type;
63946b04be8Ssimonb
64046b04be8Ssimonb qh->want_wait = false;
64146b04be8Ssimonb
64246b04be8Ssimonb list_move(&qh->qh_list_entry,
64346b04be8Ssimonb &hsotg->non_periodic_sched_inactive);
64446b04be8Ssimonb
64546b04be8Ssimonb tr_type = dwc2_hcd_select_transactions(hsotg);
64646b04be8Ssimonb if (tr_type != DWC2_TRANSACTION_NONE)
64746b04be8Ssimonb dwc2_hcd_queue_transactions(hsotg, tr_type);
64846b04be8Ssimonb }
64946b04be8Ssimonb
65046b04be8Ssimonb spin_unlock_irqrestore(&hsotg->lock, flags);
65146b04be8Ssimonb }
65246b04be8Ssimonb
65346b04be8Ssimonb /**
654970b0700Sskrll * dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic
655970b0700Sskrll * schedule if it is not already in the schedule. If the QH is already in
656970b0700Sskrll * the schedule, no action is taken.
657970b0700Sskrll *
658970b0700Sskrll * @hsotg: The HCD state structure for the DWC OTG controller
659970b0700Sskrll * @qh: The QH to add
660970b0700Sskrll *
661970b0700Sskrll * Return: 0 if successful, negative error code otherwise
662970b0700Sskrll */
dwc2_hcd_qh_add(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)663970b0700Sskrll int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
664970b0700Sskrll {
665f913003cSskrll int status;
666970b0700Sskrll u32 intr_mask;
667970b0700Sskrll
668970b0700Sskrll if (dbg_qh(qh))
669970b0700Sskrll dev_vdbg(hsotg->dev, "%s()\n", __func__);
670970b0700Sskrll
671970b0700Sskrll if (!list_empty(&qh->qh_list_entry))
672970b0700Sskrll /* QH already in a schedule */
673f913003cSskrll return 0;
674970b0700Sskrll
6755064f7beSskrll if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
6765064f7beSskrll !hsotg->frame_number) {
6775064f7beSskrll dev_dbg(hsotg->dev,
6785064f7beSskrll "reset frame number counter\n");
6795064f7beSskrll qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
6805064f7beSskrll SCHEDULE_SLOP);
6815064f7beSskrll }
6825064f7beSskrll
683970b0700Sskrll /* Add the new QH to the appropriate schedule */
684970b0700Sskrll if (dwc2_qh_is_non_per(qh)) {
68546b04be8Ssimonb if (qh->want_wait) {
68646b04be8Ssimonb list_add_tail(&qh->qh_list_entry,
68746b04be8Ssimonb &hsotg->non_periodic_sched_waiting);
68846b04be8Ssimonb qh->wait_timer_cancel = false;
68946b04be8Ssimonb /* XXX mod_timer(&qh->wait_timer,
69046b04be8Ssimonb jiffies + DWC2_RETRY_WAIT_DELAY + 1); */
69146b04be8Ssimonb callout_schedule(&qh->wait_timer,
69246b04be8Ssimonb mstohz(DWC2_RETRY_WAIT_DELAY));
69346b04be8Ssimonb } else {
694970b0700Sskrll list_add_tail(&qh->qh_list_entry,
695970b0700Sskrll &hsotg->non_periodic_sched_inactive);
69646b04be8Ssimonb }
697f913003cSskrll return 0;
698f913003cSskrll }
6999c7e1469Sskrll
700970b0700Sskrll status = dwc2_schedule_periodic(hsotg, qh);
701f913003cSskrll if (status)
702f913003cSskrll return status;
703970b0700Sskrll if (!hsotg->periodic_qh_count) {
704c8117e49Sskrll intr_mask = DWC2_READ_4(hsotg, GINTMSK);
705970b0700Sskrll intr_mask |= GINTSTS_SOF;
706c8117e49Sskrll DWC2_WRITE_4(hsotg, GINTMSK, intr_mask);
707970b0700Sskrll }
708970b0700Sskrll hsotg->periodic_qh_count++;
709970b0700Sskrll
710f913003cSskrll return 0;
711970b0700Sskrll }
712970b0700Sskrll
713970b0700Sskrll /**
714970b0700Sskrll * dwc2_hcd_qh_unlink() - Removes a QH from either the non-periodic or periodic
715970b0700Sskrll * schedule. Memory is not freed.
716970b0700Sskrll *
717970b0700Sskrll * @hsotg: The HCD state structure
718970b0700Sskrll * @qh: QH to remove from schedule
719970b0700Sskrll */
dwc2_hcd_qh_unlink(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh)720970b0700Sskrll void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
721970b0700Sskrll {
722970b0700Sskrll u32 intr_mask;
723970b0700Sskrll
724970b0700Sskrll dev_vdbg(hsotg->dev, "%s()\n", __func__);
725970b0700Sskrll
72646b04be8Ssimonb /* If the wait_timer is pending, this will stop it from acting */
72746b04be8Ssimonb qh->wait_timer_cancel = true;
72846b04be8Ssimonb
729970b0700Sskrll if (list_empty(&qh->qh_list_entry))
730970b0700Sskrll /* QH is not in a schedule */
731970b0700Sskrll return;
732970b0700Sskrll
733970b0700Sskrll if (dwc2_qh_is_non_per(qh)) {
734970b0700Sskrll if (hsotg->non_periodic_qh_ptr == &qh->qh_list_entry)
735970b0700Sskrll hsotg->non_periodic_qh_ptr =
736970b0700Sskrll hsotg->non_periodic_qh_ptr->next;
737970b0700Sskrll list_del_init(&qh->qh_list_entry);
738f913003cSskrll return;
739f913003cSskrll }
7409c7e1469Sskrll
741970b0700Sskrll dwc2_deschedule_periodic(hsotg, qh);
742970b0700Sskrll hsotg->periodic_qh_count--;
743970b0700Sskrll if (!hsotg->periodic_qh_count) {
744c8117e49Sskrll intr_mask = DWC2_READ_4(hsotg, GINTMSK);
745970b0700Sskrll intr_mask &= ~GINTSTS_SOF;
746c8117e49Sskrll DWC2_WRITE_4(hsotg, GINTMSK, intr_mask);
747970b0700Sskrll }
748970b0700Sskrll }
749970b0700Sskrll
750970b0700Sskrll /*
751970b0700Sskrll * Schedule the next continuing periodic split transfer
752970b0700Sskrll */
dwc2_sched_periodic_split(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh,u16 frame_number,int sched_next_periodic_split)753970b0700Sskrll static void dwc2_sched_periodic_split(struct dwc2_hsotg *hsotg,
754970b0700Sskrll struct dwc2_qh *qh, u16 frame_number,
755970b0700Sskrll int sched_next_periodic_split)
756970b0700Sskrll {
757970b0700Sskrll u16 incr;
758970b0700Sskrll
759970b0700Sskrll if (sched_next_periodic_split) {
760970b0700Sskrll qh->sched_frame = frame_number;
761970b0700Sskrll incr = dwc2_frame_num_inc(qh->start_split_frame, 1);
762970b0700Sskrll if (dwc2_frame_num_le(frame_number, incr)) {
763970b0700Sskrll /*
764970b0700Sskrll * Allow one frame to elapse after start split
765970b0700Sskrll * microframe before scheduling complete split, but
766970b0700Sskrll * DON'T if we are doing the next start split in the
767970b0700Sskrll * same frame for an ISOC out
768970b0700Sskrll */
769970b0700Sskrll if (qh->ep_type != USB_ENDPOINT_XFER_ISOC ||
770970b0700Sskrll qh->ep_is_in != 0) {
771970b0700Sskrll qh->sched_frame =
772970b0700Sskrll dwc2_frame_num_inc(qh->sched_frame, 1);
773970b0700Sskrll }
774970b0700Sskrll }
775970b0700Sskrll } else {
776970b0700Sskrll qh->sched_frame = dwc2_frame_num_inc(qh->start_split_frame,
777970b0700Sskrll qh->interval);
778970b0700Sskrll if (dwc2_frame_num_le(qh->sched_frame, frame_number))
779970b0700Sskrll qh->sched_frame = frame_number;
780970b0700Sskrll qh->sched_frame |= 0x7;
781970b0700Sskrll qh->start_split_frame = qh->sched_frame;
782970b0700Sskrll }
783970b0700Sskrll }
784970b0700Sskrll
785970b0700Sskrll /*
786970b0700Sskrll * Deactivates a QH. For non-periodic QHs, removes the QH from the active
787970b0700Sskrll * non-periodic schedule. The QH is added to the inactive non-periodic
788970b0700Sskrll * schedule if any QTDs are still attached to the QH.
789970b0700Sskrll *
790970b0700Sskrll * For periodic QHs, the QH is removed from the periodic queued schedule. If
791970b0700Sskrll * there are any QTDs still attached to the QH, the QH is added to either the
792970b0700Sskrll * periodic inactive schedule or the periodic ready schedule and its next
793970b0700Sskrll * scheduled frame is calculated. The QH is placed in the ready schedule if
794970b0700Sskrll * the scheduled frame has been reached already. Otherwise it's placed in the
795970b0700Sskrll * inactive schedule. If there are no QTDs attached to the QH, the QH is
796970b0700Sskrll * completely removed from the periodic schedule.
797970b0700Sskrll */
dwc2_hcd_qh_deactivate(struct dwc2_hsotg * hsotg,struct dwc2_qh * qh,int sched_next_periodic_split)798970b0700Sskrll void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
799970b0700Sskrll int sched_next_periodic_split)
800970b0700Sskrll {
801f913003cSskrll u16 frame_number;
802f913003cSskrll
803970b0700Sskrll if (dbg_qh(qh))
804970b0700Sskrll dev_vdbg(hsotg->dev, "%s()\n", __func__);
805970b0700Sskrll
806970b0700Sskrll if (dwc2_qh_is_non_per(qh)) {
807970b0700Sskrll dwc2_hcd_qh_unlink(hsotg, qh);
808970b0700Sskrll if (!list_empty(&qh->qtd_list))
80946b04be8Ssimonb /* Add back to inactive/waiting non-periodic schedule */
810970b0700Sskrll dwc2_hcd_qh_add(hsotg, qh);
811f913003cSskrll return;
812f913003cSskrll }
813f913003cSskrll
814f913003cSskrll frame_number = dwc2_hcd_get_frame_number(hsotg);
815970b0700Sskrll
816970b0700Sskrll if (qh->do_split) {
817970b0700Sskrll dwc2_sched_periodic_split(hsotg, qh, frame_number,
818970b0700Sskrll sched_next_periodic_split);
819970b0700Sskrll } else {
820970b0700Sskrll qh->sched_frame = dwc2_frame_num_inc(qh->sched_frame,
821970b0700Sskrll qh->interval);
822970b0700Sskrll if (dwc2_frame_num_le(qh->sched_frame, frame_number))
823970b0700Sskrll qh->sched_frame = frame_number;
824970b0700Sskrll }
825970b0700Sskrll
826970b0700Sskrll if (list_empty(&qh->qtd_list)) {
827970b0700Sskrll dwc2_hcd_qh_unlink(hsotg, qh);
828f913003cSskrll return;
829f913003cSskrll }
830970b0700Sskrll /*
831970b0700Sskrll * Remove from periodic_sched_queued and move to
832970b0700Sskrll * appropriate queue
833970b0700Sskrll */
834970b0700Sskrll if ((hsotg->core_params->uframe_sched > 0 &&
835f913003cSskrll dwc2_frame_num_le(qh->sched_frame, frame_number)) ||
836f913003cSskrll (hsotg->core_params->uframe_sched <= 0 &&
837cb22e524Sskrll qh->sched_frame == frame_number))
838f913003cSskrll list_move(&qh->qh_list_entry, &hsotg->periodic_sched_ready);
839cb22e524Sskrll else
840f913003cSskrll list_move(&qh->qh_list_entry, &hsotg->periodic_sched_inactive);
841970b0700Sskrll }
842970b0700Sskrll
843970b0700Sskrll /**
844970b0700Sskrll * dwc2_hcd_qtd_init() - Initializes a QTD structure
845970b0700Sskrll *
846970b0700Sskrll * @qtd: The QTD to initialize
847970b0700Sskrll * @urb: The associated URB
848970b0700Sskrll */
dwc2_hcd_qtd_init(struct dwc2_qtd * qtd,struct dwc2_hcd_urb * urb)849970b0700Sskrll void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
850970b0700Sskrll {
851970b0700Sskrll qtd->urb = urb;
852970b0700Sskrll if (dwc2_hcd_get_pipe_type(&urb->pipe_info) ==
853970b0700Sskrll USB_ENDPOINT_XFER_CONTROL) {
854970b0700Sskrll /*
855970b0700Sskrll * The only time the QTD data toggle is used is on the data
856970b0700Sskrll * phase of control transfers. This phase always starts with
857970b0700Sskrll * DATA1.
858970b0700Sskrll */
859970b0700Sskrll qtd->data_toggle = DWC2_HC_PID_DATA1;
860970b0700Sskrll qtd->control_phase = DWC2_CONTROL_SETUP;
861970b0700Sskrll }
862970b0700Sskrll
863970b0700Sskrll /* Start split */
864970b0700Sskrll qtd->complete_split = 0;
865970b0700Sskrll qtd->isoc_split_pos = DWC2_HCSPLT_XACTPOS_ALL;
866970b0700Sskrll qtd->isoc_split_offset = 0;
867970b0700Sskrll qtd->in_process = 0;
868970b0700Sskrll
869970b0700Sskrll /* Store the qtd ptr in the urb to reference the QTD */
870970b0700Sskrll urb->qtd = qtd;
871970b0700Sskrll }
872970b0700Sskrll
873970b0700Sskrll /**
874970b0700Sskrll * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
8759c7e1469Sskrll * Caller must hold driver lock.
876970b0700Sskrll *
877970b0700Sskrll * @hsotg: The DWC HCD structure
878970b0700Sskrll * @qtd: The QTD to add
8799c7e1469Sskrll * @qh: Queue head to add qtd to
880970b0700Sskrll *
881970b0700Sskrll * Return: 0 if successful, negative error code otherwise
882970b0700Sskrll *
8839c7e1469Sskrll * If the QH to which the QTD is added is not currently scheduled, it is placed
8849c7e1469Sskrll * into the proper schedule based on its EP type.
885970b0700Sskrll */
dwc2_hcd_qtd_add(struct dwc2_hsotg * hsotg,struct dwc2_qtd * qtd,struct dwc2_qh * qh)886970b0700Sskrll int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
8879c7e1469Sskrll struct dwc2_qh *qh)
888970b0700Sskrll {
8899c7e1469Sskrll
890e58cc73eSuebayasi KASSERT(mutex_owned(&hsotg->lock));
891970b0700Sskrll int retval;
892970b0700Sskrll
8939c7e1469Sskrll if (unlikely(!qh)) {
8949c7e1469Sskrll dev_err(hsotg->dev, "%s: Invalid QH\n", __func__);
8959c7e1469Sskrll retval = -EINVAL;
8969c7e1469Sskrll goto fail;
897970b0700Sskrll }
898970b0700Sskrll
8999c7e1469Sskrll retval = dwc2_hcd_qh_add(hsotg, qh);
900970b0700Sskrll if (retval)
901970b0700Sskrll goto fail;
902970b0700Sskrll
9039c7e1469Sskrll qtd->qh = qh;
9049c7e1469Sskrll list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
905970b0700Sskrll
906970b0700Sskrll return 0;
907970b0700Sskrll fail:
908970b0700Sskrll return retval;
909970b0700Sskrll }
910c8117e49Sskrll
dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg * hsotg,struct dwc2_qtd * qtd,struct dwc2_qh * qh)911c8117e49Sskrll void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
912c8117e49Sskrll struct dwc2_qtd *qtd,
913c8117e49Sskrll struct dwc2_qh *qh)
914c8117e49Sskrll {
915c8117e49Sskrll struct dwc2_softc *sc = hsotg->hsotg_sc;
916c8117e49Sskrll
917c8117e49Sskrll list_del_init(&qtd->qtd_list_entry);
918c8117e49Sskrll pool_cache_put(sc->sc_qtdpool, qtd);
919c8117e49Sskrll }
920c8117e49Sskrll
921c8117e49Sskrll #define BITSTUFFTIME(bytecount) ((8 * 7 * (bytecount)) / 6)
922c8117e49Sskrll #define HS_HOST_DELAY 5 /* nanoseconds */
923c8117e49Sskrll #define FS_LS_HOST_DELAY 1000 /* nanoseconds */
924c8117e49Sskrll #define HUB_LS_SETUP 333 /* nanoseconds */
925c8117e49Sskrll
dwc2_calc_bus_time(struct dwc2_hsotg * hsotg,int speed,int is_in,int is_isoc,int bytecount)926c8117e49Sskrll static u32 dwc2_calc_bus_time(struct dwc2_hsotg *hsotg, int speed, int is_in,
927c8117e49Sskrll int is_isoc, int bytecount)
928c8117e49Sskrll {
929c8117e49Sskrll unsigned long retval;
930c8117e49Sskrll
931c8117e49Sskrll switch (speed) {
932c8117e49Sskrll case USB_SPEED_HIGH:
933c8117e49Sskrll if (is_isoc)
934c8117e49Sskrll retval =
935c8117e49Sskrll ((38 * 8 * 2083) +
936c8117e49Sskrll (2083 * (3 + BITSTUFFTIME(bytecount)))) / 1000 +
937c8117e49Sskrll HS_HOST_DELAY;
938c8117e49Sskrll else
939c8117e49Sskrll retval =
940c8117e49Sskrll ((55 * 8 * 2083) +
941c8117e49Sskrll (2083 * (3 + BITSTUFFTIME(bytecount)))) / 1000 +
942c8117e49Sskrll HS_HOST_DELAY;
943c8117e49Sskrll break;
944c8117e49Sskrll case USB_SPEED_FULL:
945c8117e49Sskrll if (is_isoc) {
946c8117e49Sskrll retval =
947c8117e49Sskrll (8354 * (31 + 10 * BITSTUFFTIME(bytecount))) / 1000;
948c8117e49Sskrll if (is_in)
949c8117e49Sskrll retval = 7268 + FS_LS_HOST_DELAY + retval;
950c8117e49Sskrll else
951c8117e49Sskrll retval = 6265 + FS_LS_HOST_DELAY + retval;
952c8117e49Sskrll } else {
953c8117e49Sskrll retval =
954c8117e49Sskrll (8354 * (31 + 10 * BITSTUFFTIME(bytecount))) / 1000;
955c8117e49Sskrll retval = 9107 + FS_LS_HOST_DELAY + retval;
956c8117e49Sskrll }
957c8117e49Sskrll break;
958c8117e49Sskrll case USB_SPEED_LOW:
959c8117e49Sskrll if (is_in) {
960c8117e49Sskrll retval =
961c8117e49Sskrll (67667 * (31 + 10 * BITSTUFFTIME(bytecount))) /
962c8117e49Sskrll 1000;
963c8117e49Sskrll retval =
964c8117e49Sskrll 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
965c8117e49Sskrll retval;
966c8117e49Sskrll } else {
967c8117e49Sskrll retval =
968c8117e49Sskrll (66700 * (31 + 10 * BITSTUFFTIME(bytecount))) /
969c8117e49Sskrll 1000;
970c8117e49Sskrll retval =
971c8117e49Sskrll 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY +
972c8117e49Sskrll retval;
973c8117e49Sskrll }
974c8117e49Sskrll break;
975c8117e49Sskrll default:
976c8117e49Sskrll dev_warn(hsotg->dev, "Unknown device speed\n");
977c8117e49Sskrll retval = -1;
978c8117e49Sskrll }
979c8117e49Sskrll
980c8117e49Sskrll return NS_TO_US(retval);
981c8117e49Sskrll }
982