linux/drivers/usb/dwc2/hcd_queue.c

// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
 * hcd_queue.c - DesignWare HS OTG Controller host queuing routines
 *
 * Copyright (C) 2004-2013 Synopsys, Inc.
 */

/*
 * This file contains the functions to manage Queue Heads and Queue
 * Transfer Descriptors for Host mode
 */
#include <linux/gcd.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/seq_buf.h>
#include <linux/slab.h>
#include <linux/usb.h>

#include <linux/usb/hcd.h>
#include <linux/usb/ch11.h>

#include "core.h"
#include "hcd.h"

/* Wait this long before releasing periodic reservation */
#define DWC2_UNRESERVE_DELAY

/* If we get a NAK, wait this long before retrying */
#define DWC2_RETRY_WAIT_DELAY

/**
 * dwc2_periodic_channel_available() - Checks that a channel is available for a
 * periodic transfer
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 *
 * Return: 0 if successful, negative error code otherwise
 */
static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
{}

/**
 * dwc2_check_periodic_bandwidth() - Checks that there is sufficient bandwidth
 * for the specified QH in the periodic schedule
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH containing periodic bandwidth required
 *
 * Return: 0 if successful, negative error code otherwise
 *
 * For simplicity, this calculation assumes that all the transfers in the
 * periodic schedule may occur in the same (micro)frame
 */
static int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg,
					 struct dwc2_qh *qh)
{}

/**
 * pmap_schedule() - Schedule time in a periodic bitmap (pmap).
 *
 * @map:             The bitmap representing the schedule; will be updated
 *                   upon success.
 * @bits_per_period: The schedule represents several periods.  This is how many
 *                   bits are in each period.  It's assumed that the beginning
 *                   of the schedule will repeat after its end.
 * @periods_in_map:  The number of periods in the schedule.
 * @num_bits:        The number of bits we need per period we want to reserve
 *                   in this function call.
 * @interval:        How often we need to be scheduled for the reservation this
 *                   time.  1 means every period.  2 means every other period.
 *                   ...you get the picture?
 * @start:           The bit number to start at.  Normally 0.  Must be within
 *                   the interval or we return failure right away.
 * @only_one_period: Normally we'll allow picking a start anywhere within the
 *                   first interval, since we can still make all repetition
 *                   requirements by doing that.  However, if you pass true
 *                   here then we'll return failure if we can't fit within
 *                   the period that "start" is in.
 *
 * The idea here is that we want to schedule time for repeating events that all
 * want the same resource.  The resource is divided into fixed-sized periods
 * and the events want to repeat every "interval" periods.  The schedule
 * granularity is one bit.
 *
 * To keep things "simple", we'll represent our schedule with a bitmap that
 * contains a fixed number of periods.  This gets rid of a lot of complexity
 * but does mean that we need to handle things specially (and non-ideally) if
 * the number of the periods in the schedule doesn't match well with the
 * intervals that we're trying to schedule.
 *
 * Here's an explanation of the scheme we'll implement, assuming 8 periods.
 * - If interval is 1, we need to take up space in each of the 8
 *   periods we're scheduling.  Easy.
 * - If interval is 2, we need to take up space in half of the
 *   periods.  Again, easy.
 * - If interval is 3, we actually need to fall back to interval 1.
 *   Why?  Because we might need time in any period.  AKA for the
 *   first 8 periods, we'll be in slot 0, 3, 6.  Then we'll be
 *   in slot 1, 4, 7.  Then we'll be in 2, 5.  Then we'll be back to
 *   0, 3, and 6.  Since we could be in any frame we need to reserve
 *   for all of them.  Sucks, but that's what you gotta do.  Note that
 *   if we were instead scheduling 8 * 3 = 24 we'd do much better, but
 *   then we need more memory and time to do scheduling.
 * - If interval is 4, easy.
 * - If interval is 5, we again need interval 1.  The schedule will be
 *   0, 5, 2, 7, 4, 1, 6, 3, 0
 * - If interval is 6, we need interval 2.  0, 6, 4, 2.
 * - If interval is 7, we need interval 1.
 * - If interval is 8, we need interval 8.
 *
 * If you do the math, you'll see that we need to pretend that interval is
 * equal to the greatest_common_divisor(interval, periods_in_map).
 *
 * Note that at the moment this function tends to front-pack the schedule.
 * In some cases that's really non-ideal (it's hard to schedule things that
 * need to repeat every period).  In other cases it's perfect (you can easily
 * schedule bigger, less often repeating things).
 *
 * Here's the algorithm in action (8 periods, 5 bits per period):
 *  |**   |     |**   |     |**   |     |**   |     |   OK 2 bits, intv 2 at 0
 *  |*****|  ***|*****|  ***|*****|  ***|*****|  ***|   OK 3 bits, intv 3 at 2
 *  |*****|* ***|*****|  ***|*****|* ***|*****|  ***|   OK 1 bits, intv 4 at 5
 *  |**   |*    |**   |     |**   |*    |**   |     | Remv 3 bits, intv 3 at 2
 *  |***  |*    |***  |     |***  |*    |***  |     |   OK 1 bits, intv 6 at 2
 *  |**** |*  * |**** |   * |**** |*  * |**** |   * |   OK 1 bits, intv 1 at 3
 *  |**** |**** |**** | *** |**** |**** |**** | *** |   OK 2 bits, intv 2 at 6
 *  |*****|*****|*****| ****|*****|*****|*****| ****|   OK 1 bits, intv 1 at 4
 *  |*****|*****|*****| ****|*****|*****|*****| ****| FAIL 1 bits, intv 1
 *  |  ***|*****|  ***| ****|  ***|*****|  ***| ****| Remv 2 bits, intv 2 at 0
 *  |  ***| ****|  ***| ****|  ***| ****|  ***| ****| Remv 1 bits, intv 4 at 5
 *  |   **| ****|   **| ****|   **| ****|   **| ****| Remv 1 bits, intv 6 at 2
 *  |    *| ** *|    *| ** *|    *| ** *|    *| ** *| Remv 1 bits, intv 1 at 3
 *  |    *|    *|    *|    *|    *|    *|    *|    *| Remv 2 bits, intv 2 at 6
 *  |     |     |     |     |     |     |     |     | Remv 1 bits, intv 1 at 4
 *  |**   |     |**   |     |**   |     |**   |     |   OK 2 bits, intv 2 at 0
 *  |***  |     |**   |     |***  |     |**   |     |   OK 1 bits, intv 4 at 2
 *  |*****|     |** **|     |*****|     |** **|     |   OK 2 bits, intv 2 at 3
 *  |*****|*    |** **|     |*****|*    |** **|     |   OK 1 bits, intv 4 at 5
 *  |*****|***  |** **| **  |*****|***  |** **| **  |   OK 2 bits, intv 2 at 6
 *  |*****|*****|** **| ****|*****|*****|** **| ****|   OK 2 bits, intv 2 at 8
 *  |*****|*****|*****| ****|*****|*****|*****| ****|   OK 1 bits, intv 4 at 12
 *
 * This function is pretty generic and could be easily abstracted if anything
 * needed similar scheduling.
 *
 * Returns either -ENOSPC or a >= 0 start bit which should be passed to the
 * unschedule routine.  The map bitmap will be updated on a non-error result.
 */
static int pmap_schedule(unsigned long *map, int bits_per_period,
			 int periods_in_map, int num_bits,
			 int interval, int start, bool only_one_period)
{}

/**
 * pmap_unschedule() - Undo work done by pmap_schedule()
 *
 * @map:             See pmap_schedule().
 * @bits_per_period: See pmap_schedule().
 * @periods_in_map:  See pmap_schedule().
 * @num_bits:        The number of bits that was passed to schedule.
 * @interval:        The interval that was passed to schedule.
 * @start:           The return value from pmap_schedule().
 */
static void pmap_unschedule(unsigned long *map, int bits_per_period,
			    int periods_in_map, int num_bits,
			    int interval, int start)
{}

/**
 * dwc2_get_ls_map() - Get the map used for the given qh
 *
 * @hsotg: The HCD state structure for the DWC OTG controller.
 * @qh:    QH for the periodic transfer.
 *
 * We'll always get the periodic map out of our TT.  Note that even if we're
 * running the host straight in low speed / full speed mode it appears as if
 * a TT is allocated for us, so we'll use it.  If that ever changes we can
 * add logic here to get a map out of "hsotg" if !qh->do_split.
 *
 * Returns: the map or NULL if a map couldn't be found.
 */
static unsigned long *dwc2_get_ls_map(struct dwc2_hsotg *hsotg,
				      struct dwc2_qh *qh)
{}

#ifdef DWC2_PRINT_SCHEDULE
/*
 * pmap_print() - Print the given periodic map
 *
 * Will attempt to print out the periodic schedule.
 *
 * @map:             See pmap_schedule().
 * @bits_per_period: See pmap_schedule().
 * @periods_in_map:  See pmap_schedule().
 * @period_name:     The name of 1 period, like "uFrame"
 * @units:           The name of the units, like "us".
 * @print_fn:        The function to call for printing.
 * @print_data:      Opaque data to pass to the print function.
 */
static void pmap_print(unsigned long *map, int bits_per_period,
		       int periods_in_map, const char *period_name,
		       const char *units,
		       void (*print_fn)(const char *str, void *data),
		       void *print_data)
{
	int period;

	for (period = 0; period < periods_in_map; period++) {
		DECLARE_SEQ_BUF(buf, 64);
		int period_start = period * bits_per_period;
		int period_end = period_start + bits_per_period;
		int start = 0;
		int count = 0;
		bool printed = false;
		int i;

		for (i = period_start; i < period_end + 1; i++) {
			/* Handle case when ith bit is set */
			if (i < period_end &&
			    bitmap_find_next_zero_area(map, i + 1,
						       i, 1, 0) != i) {
				if (count == 0)
					start = i - period_start;
				count++;
				continue;
			}

			/* ith bit isn't set; don't care if count == 0 */
			if (count == 0)
				continue;

			if (!printed)
				seq_buf_printf(&buf, "%s %d: ",
					       period_name, period);
			else
				seq_buf_puts(&buf, ", ");
			printed = true;

			seq_buf_printf(&buf, "%d %s -%3d %s", start,
				       units, start + count - 1, units);
			count = 0;
		}

		if (printed)
			print_fn(seq_buf_str(&buf), print_data);
	}
}

struct dwc2_qh_print_data {
	struct dwc2_hsotg *hsotg;
	struct dwc2_qh *qh;
};

/**
 * dwc2_qh_print() - Helper function for dwc2_qh_schedule_print()
 *
 * @str:  The string to print
 * @data: A pointer to a struct dwc2_qh_print_data
 */
static void dwc2_qh_print(const char *str, void *data)
{
	struct dwc2_qh_print_data *print_data = data;

	dwc2_sch_dbg(print_data->hsotg, "QH=%p ...%s\n", print_data->qh, str);
}

/**
 * dwc2_qh_schedule_print() - Print the periodic schedule
 *
 * @hsotg: The HCD state structure for the DWC OTG controller.
 * @qh:    QH to print.
 */
static void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
				   struct dwc2_qh *qh)
{
	struct dwc2_qh_print_data print_data = { hsotg, qh };
	int i;

	/*
	 * The printing functions are quite slow and inefficient.
	 * If we don't have tracing turned on, don't run unless the special
	 * define is turned on.
	 */

	if (qh->schedule_low_speed) {
		unsigned long *map = dwc2_get_ls_map(hsotg, qh);

		dwc2_sch_dbg(hsotg, "QH=%p LS/FS trans: %d=>%d us @ %d us",
			     qh, qh->device_us,
			     DWC2_ROUND_US_TO_SLICE(qh->device_us),
			     DWC2_US_PER_SLICE * qh->ls_start_schedule_slice);

		if (map) {
			dwc2_sch_dbg(hsotg,
				     "QH=%p Whole low/full speed map %p now:\n",
				     qh, map);
			pmap_print(map, DWC2_LS_PERIODIC_SLICES_PER_FRAME,
				   DWC2_LS_SCHEDULE_FRAMES, "Frame ", "slices",
				   dwc2_qh_print, &print_data);
		}
	}

	for (i = 0; i < qh->num_hs_transfers; i++) {
		struct dwc2_hs_transfer_time *trans_time = qh->hs_transfers + i;
		int uframe = trans_time->start_schedule_us /
			     DWC2_HS_PERIODIC_US_PER_UFRAME;
		int rel_us = trans_time->start_schedule_us %
			     DWC2_HS_PERIODIC_US_PER_UFRAME;

		dwc2_sch_dbg(hsotg,
			     "QH=%p HS trans #%d: %d us @ uFrame %d + %d us\n",
			     qh, i, trans_time->duration_us, uframe, rel_us);
	}
	if (qh->num_hs_transfers) {
		dwc2_sch_dbg(hsotg, "QH=%p Whole high speed map now:\n", qh);
		pmap_print(hsotg->hs_periodic_bitmap,
			   DWC2_HS_PERIODIC_US_PER_UFRAME,
			   DWC2_HS_SCHEDULE_UFRAMES, "uFrame", "us",
			   dwc2_qh_print, &print_data);
	}
}
#else
static inline void dwc2_qh_schedule_print(struct dwc2_hsotg *hsotg,
					  struct dwc2_qh *qh) {};
#endif

/**
 * dwc2_ls_pmap_schedule() - Schedule a low speed QH
 *
 * @hsotg:        The HCD state structure for the DWC OTG controller.
 * @qh:           QH for the periodic transfer.
 * @search_slice: We'll start trying to schedule at the passed slice.
 *                Remember that slices are the units of the low speed
 *                schedule (think 25us or so).
 *
 * Wraps pmap_schedule() with the right parameters for low speed scheduling.
 *
 * Normally we schedule low speed devices on the map associated with the TT.
 *
 * Returns: 0 for success or an error code.
 */
static int dwc2_ls_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
				 int search_slice)
{}

/**
 * dwc2_ls_pmap_unschedule() - Undo work done by dwc2_ls_pmap_schedule()
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static void dwc2_ls_pmap_unschedule(struct dwc2_hsotg *hsotg,
				    struct dwc2_qh *qh)
{}

/**
 * dwc2_hs_pmap_schedule - Schedule in the main high speed schedule
 *
 * This will schedule something on the main dwc2 schedule.
 *
 * We'll start looking in qh->hs_transfers[index].start_schedule_us.  We'll
 * update this with the result upon success.  We also use the duration from
 * the same structure.
 *
 * @hsotg:           The HCD state structure for the DWC OTG controller.
 * @qh:              QH for the periodic transfer.
 * @only_one_period: If true we will limit ourselves to just looking at
 *                   one period (aka one 100us chunk).  This is used if we have
 *                   already scheduled something on the low speed schedule and
 *                   need to find something that matches on the high speed one.
 * @index:           The index into qh->hs_transfers that we're working with.
 *
 * Returns: 0 for success or an error code.  Upon success the
 *          dwc2_hs_transfer_time specified by "index" will be updated.
 */
static int dwc2_hs_pmap_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
				 bool only_one_period, int index)
{}

/**
 * dwc2_hs_pmap_unschedule() - Undo work done by dwc2_hs_pmap_schedule()
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 * @index:       Transfer index
 */
static void dwc2_hs_pmap_unschedule(struct dwc2_hsotg *hsotg,
				    struct dwc2_qh *qh, int index)
{}

/**
 * dwc2_uframe_schedule_split - Schedule a QH for a periodic split xfer.
 *
 * This is the most complicated thing in USB.  We have to find matching time
 * in both the global high speed schedule for the port and the low speed
 * schedule for the TT associated with the given device.
 *
 * Being here means that the host must be running in high speed mode and the
 * device is in low or full speed mode (and behind a hub).
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static int dwc2_uframe_schedule_split(struct dwc2_hsotg *hsotg,
				      struct dwc2_qh *qh)
{}

/**
 * dwc2_uframe_schedule_hs - Schedule a QH for a periodic high speed xfer.
 *
 * Basically this just wraps dwc2_hs_pmap_schedule() to provide a clean
 * interface.
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static int dwc2_uframe_schedule_hs(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_uframe_schedule_ls - Schedule a QH for a periodic low/full speed xfer.
 *
 * Basically this just wraps dwc2_ls_pmap_schedule() to provide a clean
 * interface.
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static int dwc2_uframe_schedule_ls(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_uframe_schedule - Schedule a QH for a periodic xfer.
 *
 * Calls one of the 3 sub-function depending on what type of transfer this QH
 * is for.  Also adds some printing.
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static int dwc2_uframe_schedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_uframe_unschedule - Undoes dwc2_uframe_schedule().
 *
 * @hsotg:       The HCD state structure for the DWC OTG controller.
 * @qh:          QH for the periodic transfer.
 */
static void dwc2_uframe_unschedule(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_pick_first_frame() - Choose 1st frame for qh that's already scheduled
 *
 * Takes a qh that has already been scheduled (which means we know we have the
 * bandwdith reserved for us) and set the next_active_frame and the
 * start_active_frame.
 *
 * This is expected to be called on qh's that weren't previously actively
 * running.  It just picks the next frame that we can fit into without any
 * thought about the past.
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH for a periodic endpoint
 *
 */
static void dwc2_pick_first_frame(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_do_reserve() - Make a periodic reservation
 *
 * Try to allocate space in the periodic schedule.  Depending on parameters
 * this might use the microframe scheduler or the dumb scheduler.
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH for the periodic transfer.
 *
 * Returns: 0 upon success; error upon failure.
 */
static int dwc2_do_reserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_do_unreserve() - Actually release the periodic reservation
 *
 * This function actually releases the periodic bandwidth that was reserved
 * by the given qh.
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH for the periodic transfer.
 */
static void dwc2_do_unreserve(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_unreserve_timer_fn() - Timer function to release periodic reservation
 *
 * According to the kernel doc for usb_submit_urb() (specifically the part about
 * "Reserved Bandwidth Transfers"), we need to keep a reservation active as
 * long as a device driver keeps submitting.  Since we're using HCD_BH to give
 * back the URB we need to give the driver a little bit of time before we
 * release the reservation.  This worker is called after the appropriate
 * delay.
 *
 * @t: Address to a qh unreserve_work.
 */
static void dwc2_unreserve_timer_fn(struct timer_list *t)
{}

/**
 * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a
 * host channel is large enough to handle the maximum data transfer in a single
 * (micro)frame for a periodic transfer
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH for a periodic endpoint
 *
 * Return: 0 if successful, negative error code otherwise
 */
static int dwc2_check_max_xfer_size(struct dwc2_hsotg *hsotg,
				    struct dwc2_qh *qh)
{}

/**
 * dwc2_schedule_periodic() - Schedules an interrupt or isochronous transfer in
 * the periodic schedule
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    QH for the periodic transfer. The QH should already contain the
 *         scheduling information.
 *
 * Return: 0 if successful, negative error code otherwise
 */
static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_deschedule_periodic() - Removes an interrupt or isochronous transfer
 * from the periodic schedule
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:	   QH for the periodic transfer
 */
static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
				     struct dwc2_qh *qh)
{}

/**
 * dwc2_wait_timer_fn() - Timer function to re-queue after waiting
 *
 * As per the spec, a NAK indicates that "a function is temporarily unable to
 * transmit or receive data, but will eventually be able to do so without need
 * of host intervention".
 *
 * That means that when we encounter a NAK we're supposed to retry.
 *
 * ...but if we retry right away (from the interrupt handler that saw the NAK)
 * then we can end up with an interrupt storm (if the other side keeps NAKing
 * us) because on slow enough CPUs it could take us longer to get out of the
 * interrupt routine than it takes for the device to send another NAK.  That
 * leads to a constant stream of NAK interrupts and the CPU locks.
 *
 * ...so instead of retrying right away in the case of a NAK we'll set a timer
 * to retry some time later.  This function handles that timer and moves the
 * qh back to the "inactive" list, then queues transactions.
 *
 * @t: Pointer to wait_timer in a qh.
 *
 * Return: HRTIMER_NORESTART to not automatically restart this timer.
 */
static enum hrtimer_restart dwc2_wait_timer_fn(struct hrtimer *t)
{}

/**
 * dwc2_qh_init() - Initializes a QH structure
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    The QH to init
 * @urb:   Holds the information about the device/endpoint needed to initialize
 *         the QH
 * @mem_flags: Flags for allocating memory.
 */
static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
			 struct dwc2_hcd_urb *urb, gfp_t mem_flags)
{}

/**
 * dwc2_hcd_qh_create() - Allocates and initializes a QH
 *
 * @hsotg:        The HCD state structure for the DWC OTG controller
 * @urb:          Holds the information about the device/endpoint needed
 *                to initialize the QH
 * @mem_flags:   Flags for allocating memory.
 *
 * Return: Pointer to the newly allocated QH, or NULL on error
 */
struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
				   struct dwc2_hcd_urb *urb,
					  gfp_t mem_flags)
{}

/**
 * dwc2_hcd_qh_free() - Frees the QH
 *
 * @hsotg: HCD instance
 * @qh:    The QH to free
 *
 * QH should already be removed from the list. QTD list should already be empty
 * if called from URB Dequeue.
 *
 * Must NOT be called with interrupt disabled or spinlock held
 */
void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_hcd_qh_add() - Adds a QH to either the non periodic or periodic
 * schedule if it is not already in the schedule. If the QH is already in
 * the schedule, no action is taken.
 *
 * @hsotg: The HCD state structure for the DWC OTG controller
 * @qh:    The QH to add
 *
 * Return: 0 if successful, negative error code otherwise
 */
int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_hcd_qh_unlink() - Removes a QH from either the non-periodic or periodic
 * schedule. Memory is not freed.
 *
 * @hsotg: The HCD state structure
 * @qh:    QH to remove from schedule
 */
void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{}

/**
 * dwc2_next_for_periodic_split() - Set next_active_frame midway thru a split.
 *
 * This is called for setting next_active_frame for periodic splits for all but
 * the first packet of the split.  Confusing?  I thought so...
 *
 * Periodic splits are single low/full speed transfers that we end up splitting
 * up into several high speed transfers.  They always fit into one full (1 ms)
 * frame but might be split over several microframes (125 us each).  We to put
 * each of the parts on a very specific high speed frame.
 *
 * This function figures out where the next active uFrame needs to be.
 *
 * @hsotg:        The HCD state structure
 * @qh:           QH for the periodic transfer.
 * @frame_number: The current frame number.
 *
 * Return: number missed by (or 0 if we didn't miss).
 */
static int dwc2_next_for_periodic_split(struct dwc2_hsotg *hsotg,
					struct dwc2_qh *qh, u16 frame_number)
{}

/**
 * dwc2_next_periodic_start() - Set next_active_frame for next transfer start
 *
 * This is called for setting next_active_frame for a periodic transfer for
 * all cases other than midway through a periodic split.  This will also update
 * start_active_frame.
 *
 * Since we _always_ keep start_active_frame as the start of the previous
 * transfer this is normally pretty easy: we just add our interval to
 * start_active_frame and we've got our answer.
 *
 * The tricks come into play if we miss.  In that case we'll look for the next
 * slot we can fit into.
 *
 * @hsotg:        The HCD state structure
 * @qh:           QH for the periodic transfer.
 * @frame_number: The current frame number.
 *
 * Return: number missed by (or 0 if we didn't miss).
 */
static int dwc2_next_periodic_start(struct dwc2_hsotg *hsotg,
				    struct dwc2_qh *qh, u16 frame_number)
{}

/*
 * Deactivates a QH. For non-periodic QHs, removes the QH from the active
 * non-periodic schedule. The QH is added to the inactive non-periodic
 * schedule if any QTDs are still attached to the QH.
 *
 * For periodic QHs, the QH is removed from the periodic queued schedule. If
 * there are any QTDs still attached to the QH, the QH is added to either the
 * periodic inactive schedule or the periodic ready schedule and its next
 * scheduled frame is calculated. The QH is placed in the ready schedule if
 * the scheduled frame has been reached already. Otherwise it's placed in the
 * inactive schedule. If there are no QTDs attached to the QH, the QH is
 * completely removed from the periodic schedule.
 */
void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
			    int sched_next_periodic_split)
{}

/**
 * dwc2_hcd_qtd_init() - Initializes a QTD structure
 *
 * @qtd: The QTD to initialize
 * @urb: The associated URB
 */
void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb)
{}

/**
 * dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
 *			Caller must hold driver lock.
 *
 * @hsotg:        The DWC HCD structure
 * @qtd:          The QTD to add
 * @qh:           Queue head to add qtd to
 *
 * Return: 0 if successful, negative error code otherwise
 *
 * If the QH to which the QTD is added is not currently scheduled, it is placed
 * into the proper schedule based on its EP type.
 */
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
		     struct dwc2_qh *qh)
{}