drivers/usb/host/sl811-hcd.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/host/sl811-hcd.c
Extension
.c
Size
46569 bytes
Lines
1800
Domain
Driver Families
Bucket
drivers/usb
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (control & SL11H_HCTLMASK_PREAMBLE) {
			/* also note erratum 1: some hubs won't work */
			fclock -= 800;
		}
		fclock -= ep->maxpacket << 8;

		/* erratum 2: AFTERSOF only works for fullspeed */
		if (fclock < 0) {
			if (ep->period)
				sl811->stat_overrun++;
			sofirq_on(sl811);
			return NULL;
		}
	} else {
		fclock -= 12000 / 19;	/* 19 64byte packets/msec */
		if (fclock < 0) {
			if (ep->period)
				sl811->stat_overrun++;
			control |= SL11H_HCTLMASK_AFTERSOF;

		/* throttle bulk/control irq noise */
		} else if (ep->nak_count)
			control |= SL11H_HCTLMASK_AFTERSOF;
	}


	switch (ep->nextpid) {
	case USB_PID_IN:
		in_packet(sl811, ep, urb, bank, control);
		break;
	case USB_PID_OUT:
		out_packet(sl811, ep, urb, bank, control);
		break;
	case USB_PID_SETUP:
		setup_packet(sl811, ep, urb, bank, control);
		break;
	case USB_PID_ACK:		/* for control status */
		status_packet(sl811, ep, urb, bank, control);
		break;
	default:
		dev_dbg(sl811_to_hcd(sl811)->self.controller,
			"bad ep%p pid %02x\n", ep, ep->nextpid);
		ep = NULL;
	}
	return ep;
}

#define MIN_JIFFIES	((msecs_to_jiffies(2) > 1) ? msecs_to_jiffies(2) : 2)

static inline void start_transfer(struct sl811 *sl811)
{
	if (sl811->port1 & USB_PORT_STAT_SUSPEND)
		return;
	if (sl811->active_a == NULL) {
		sl811->active_a = start(sl811, SL811_EP_A(SL811_HOST_BUF));
		if (sl811->active_a != NULL)
			sl811->jiffies_a = jiffies + MIN_JIFFIES;
	}
#ifdef USE_B
	if (sl811->active_b == NULL) {
		sl811->active_b = start(sl811, SL811_EP_B(SL811_HOST_BUF));
		if (sl811->active_b != NULL)
			sl811->jiffies_b = jiffies + MIN_JIFFIES;
	}
#endif
}

static void finish_request(
	struct sl811		*sl811,
	struct sl811h_ep	*ep,
	struct urb		*urb,
	int			status
) __releases(sl811->lock) __acquires(sl811->lock)
{
	unsigned		i;

	if (usb_pipecontrol(urb->pipe))
		ep->nextpid = USB_PID_SETUP;

	usb_hcd_unlink_urb_from_ep(sl811_to_hcd(sl811), urb);
	spin_unlock(&sl811->lock);
	usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, status);
	spin_lock(&sl811->lock);

	/* leave active endpoints in the schedule */
	if (!list_empty(&ep->hep->urb_list))
		return;

	/* async deschedule? */
	if (!list_empty(&ep->schedule)) {

Annotation

Implementation Notes