drivers/usb/dwc2/hcd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/dwc2/hcd.c
Extension
.c
Size
167946 bytes
Lines
5998
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 wrapper_priv_data {
	struct dwc2_hsotg *hsotg;
};

/* Gets the dwc2_hsotg from a usb_hcd */
static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd)
{
	struct wrapper_priv_data *p;

	p = (struct wrapper_priv_data *)&hcd->hcd_priv;
	return p->hsotg;
}

/**
 * dwc2_host_get_tt_info() - Get the dwc2_tt associated with context
 *
 * This will get the dwc2_tt structure (and ttport) associated with the given
 * context (which is really just a struct urb pointer).
 *
 * The first time this is called for a given TT we allocate memory for our
 * structure.  When everyone is done and has called dwc2_host_put_tt_info()
 * then the refcount for the structure will go to 0 and we'll free it.
 *
 * @hsotg:     The HCD state structure for the DWC OTG controller.
 * @context:   The priv pointer from a struct dwc2_hcd_urb.
 * @mem_flags: Flags for allocating memory.
 * @ttport:    We'll return this device's port number here.  That's used to
 *             reference into the bitmap if we're on a multi_tt hub.
 *
 * Return: a pointer to a struct dwc2_tt.  Don't forget to call
 *         dwc2_host_put_tt_info()!  Returns NULL upon memory alloc failure.
 */

struct dwc2_tt *dwc2_host_get_tt_info(struct dwc2_hsotg *hsotg, void *context,
				      gfp_t mem_flags, int *ttport)
{
	struct urb *urb = context;
	struct dwc2_tt *dwc_tt = NULL;

	if (urb->dev->tt) {
		*ttport = urb->dev->ttport;

		dwc_tt = urb->dev->tt->hcpriv;
		if (!dwc_tt) {
			size_t bitmap_size;

			/*
			 * For single_tt we need one schedule.  For multi_tt
			 * we need one per port.
			 */
			bitmap_size = DWC2_ELEMENTS_PER_LS_BITMAP *
				      sizeof(dwc_tt->periodic_bitmaps[0]);
			if (urb->dev->tt->multi)
				bitmap_size *= urb->dev->tt->hub->maxchild;

			dwc_tt = kzalloc(sizeof(*dwc_tt) + bitmap_size,
					 mem_flags);
			if (!dwc_tt)
				return NULL;

			dwc_tt->usb_tt = urb->dev->tt;
			dwc_tt->usb_tt->hcpriv = dwc_tt;
		}

		dwc_tt->refcount++;
	}

	return dwc_tt;
}

/**
 * dwc2_host_put_tt_info() - Put the dwc2_tt from dwc2_host_get_tt_info()
 *
 * Frees resources allocated by dwc2_host_get_tt_info() if all current holders
 * of the structure are done.
 *
 * It's OK to call this with NULL.
 *
 * @hsotg:     The HCD state structure for the DWC OTG controller.
 * @dwc_tt:    The pointer returned by dwc2_host_get_tt_info.
 */
void dwc2_host_put_tt_info(struct dwc2_hsotg *hsotg, struct dwc2_tt *dwc_tt)
{
	/* Model kfree and make put of NULL a no-op */
	if (!dwc_tt)
		return;

	WARN_ON(dwc_tt->refcount < 1);

	dwc_tt->refcount--;

Annotation

Implementation Notes