drivers/usb/host/fhci-sched.c

Source file repositories/reference/linux-study-clean/drivers/usb/host/fhci-sched.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/host/fhci-sched.c
Extension
.c
Size
24007 bytes
Lines
892
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

if (ed->td_list.next->next != &ed->td_list) {
			struct td *td_next =
			    list_entry(ed->td_list.next->next, struct td,
				       node);

			td_next->start_frame = usb->actual_frame->frame_num;
		}
		td->actual_len = trans_len;
		td_done = true;
	} else if ((td->status & USB_TD_ERROR) &&
			!(td->status & USB_TD_TX_ER_NAK)) {
		/*
		 * There was an error on the transaction (but not NAK).
		 * If it is fatal error (data underrun, stall, bad pid or 3
		 * errors exceeded), mark this TD as done.
		 */
		if ((td->status & USB_TD_RX_DATA_UNDERUN) ||
				(td->status & USB_TD_TX_ER_STALL) ||
				(td->status & USB_TD_RX_ER_PID) ||
				(++td->error_cnt >= 3)) {
			ed->state = FHCI_ED_HALTED;
			td_done = true;

			if (td->status & USB_TD_RX_DATA_UNDERUN) {
				fhci_dbg(usb->fhci, "td err fu\n");
				td->toggle = !td->toggle;
				td->actual_len += trans_len;
			} else {
				fhci_dbg(usb->fhci, "td err f!u\n");
			}
		} else {
			fhci_dbg(usb->fhci, "td err !f\n");
			/* it is not a fatal error -retry this transaction */
			td->nak_cnt = 0;
			td->error_cnt++;
			td->status = USB_TD_OK;
		}
	} else if (td->status & USB_TD_TX_ER_NAK) {
		/* there was a NAK response */
		fhci_vdbg(usb->fhci, "td nack\n");
		td->nak_cnt++;
		td->error_cnt = 0;
		td->status = USB_TD_OK;
	} else {
		/* there was no error on transaction */
		td->error_cnt = 0;
		td->nak_cnt = 0;
		td->toggle = !td->toggle;
		td->actual_len += trans_len;

		if (td->len == td->actual_len)
			td_done = true;
	}

	if (td_done)
		fhci_move_td_from_ed_to_done_list(usb, ed);
}

/*
 * Flush all transmitted packets from BDs
 * This routine is called when disabling the USB port to flush all
 * transmissions that are already scheduled in the BDs
 */
void fhci_flush_all_transmissions(struct fhci_usb *usb)
{
	u8 mode;
	struct td *td;

	mode = in_8(&usb->fhci->regs->usb_usmod);
	clrbits8(&usb->fhci->regs->usb_usmod, USB_MODE_EN);

	fhci_flush_bds(usb);

	while ((td = fhci_peek_td_from_frame(usb->actual_frame)) != NULL) {
		struct packet *pkt = td->pkt;

		pkt->status = USB_TD_TX_ER_TIMEOUT;
		fhci_transaction_confirm(usb, pkt);
	}

	usb->actual_frame->frame_status = FRAME_END_TRANSMISSION;

	/* reset the event register */
	out_be16(&usb->fhci->regs->usb_usber, 0xffff);
	/* enable the USB controller */
	out_8(&usb->fhci->regs->usb_usmod, mode | USB_MODE_EN);
}

/*
 * This function forms the packet and transmit the packet. This function

Annotation

Implementation Notes