drivers/usb/dwc2/hcd_queue.c

Source file repositories/reference/linux-study-clean/drivers/usb/dwc2/hcd_queue.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/dwc2/hcd_queue.c
Extension
.c
Size
63870 bytes
Lines
2033
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

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.

Annotation

Implementation Notes