/* Some drivers think it's safe to schedule isochronous transfers more than 256 * ms into the future (partly as a result of an old bug in the scheduling * code). In an attempt to avoid trouble, we will use a minimum scheduling * length of 512 frames instead of 256.
*/ #define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */
/* for link power management(LPM) feature */ staticunsignedint hird;
module_param(hird, int, S_IRUGO);
MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
/* check the values in the HCSPARAMS register (host controller _Structural_ * parameters) see EHCI spec, Table 2-4 for each value
*/ staticvoid dbg_hcs_params(struct fotg210_hcd *fotg210, char *label)
{
u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
/* check the values in the HCCPARAMS register (host controller _Capability_ * parameters) see EHCI Spec, Table 2-5 for each value
*/ staticvoid dbg_hcc_params(struct fotg210_hcd *fotg210, char *label)
{
u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
if (v & QTD_STS_ACTIVE) return'*'; if (v & QTD_STS_HALT) return'-'; if (!IS_SHORT_READ(v)) return' '; /* tries to advance through hw_alt_next */ return'/';
}
/* dumps a snapshot of the async schedule. * usually empty except for long-term bulk reads, or head. * one QH per line, and TDs we know about
*/
spin_lock_irqsave(&fotg210->lock, flags); for (qh = fotg210->async->qh_next.qh; size > 0 && qh;
qh = qh->qh_next.qh)
qh_lines(fotg210, qh, &next, &size); if (fotg210->async_unlink && size > 0) {
temp = scnprintf(next, size, "\nunlink =\n");
size -= temp;
next += temp;
/* count tds, get ep direction */
list_for_each_entry(qtd, &qh->qtd_list, qtd_list) {
temp++; switch ((hc32_to_cpu(fotg210, qtd->hw_token) >> 8) & 0x03) { case 0:
type = "out"; continue; case 1:
type = "in"; continue;
}
}
/* dump a snapshot of the periodic schedule. * iso changes, interrupt usually doesn't.
*/
spin_lock_irqsave(&fotg210->lock, flags); for (i = 0; i < fotg210->periodic_size; i++) {
p = fotg210->pshadow[i]; if (likely(!p.ptr)) continue;
/* handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read * @mask: bits to look at in result of read * @done: value of those bits when handshake succeeds * @usec: timeout in microseconds * * Returns negative errno, or zero on success * * Success happens when the "mask" bits have the specified value (hardware * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). * * That last failure should_only happen in cases like physical cardbus eject * before driver shutdown. But it also seems to be caused by bugs in cardbus * bridge shutdown: shutting down the bridge before the devices using it.
*/ staticint handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
u32 mask, u32 done, int usec)
{
u32 result; int ret;
ret = readl_poll_timeout_atomic(ptr, result,
((result & mask) == done ||
result == U32_MAX), 1, usec); if (result == U32_MAX) /* card removed */ return -ENODEV;
return ret;
}
/* Force HC to halt state from unknown (EHCI spec section 2.3). * Must be called with interrupts enabled and the lock not held.
*/ staticint fotg210_halt(struct fotg210_hcd *fotg210)
{
u32 temp;
spin_lock_irq(&fotg210->lock);
/* disable any irqs left enabled by previous code */
fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
/* * This routine gets called during probe before fotg210->command * has been initialized, so we can't rely on its value.
*/
fotg210->command &= ~CMD_RUN;
temp = fotg210_readl(fotg210, &fotg210->regs->command);
temp &= ~(CMD_RUN | CMD_IAAD);
fotg210_writel(fotg210, temp, &fotg210->regs->command);
/* Reset a non-running (STS_HALT == 1) controller. * Must be called with interrupts enabled and the lock not held.
*/ staticint fotg210_reset(struct fotg210_hcd *fotg210)
{ int retval;
u32 command = fotg210_readl(fotg210, &fotg210->regs->command);
/* If the EHCI debug controller is active, special care must be * taken before and after a host controller reset
*/ if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210)))
fotg210->debug = NULL;
/* Idle the controller (turn off the schedules). * Must be called with interrupts enabled and the lock not held.
*/ staticvoid fotg210_quiesce(struct fotg210_hcd *fotg210)
{
u32 temp;
if (fotg210->rh_state != FOTG210_RH_RUNNING) return;
/* wait for any schedule enables/disables to take effect */
temp = (fotg210->command << 10) & (STS_ASS | STS_PSS);
handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp,
16 * 125);
/* then disable anything that's still active */
spin_lock_irq(&fotg210->lock);
fotg210->command &= ~(CMD_ASE | CMD_PSE);
fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
spin_unlock_irq(&fotg210->lock);
/* hardware can take 16 microframes to turn off ... */
handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0,
16 * 125);
}
/* Set a bit in the USBCMD register */ staticvoid fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit)
{
fotg210->command |= bit;
fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command);
/* EHCI timer support... Now using hrtimers. * * Lots of different events are triggered from fotg210->hrtimer. Whenever * the timer routine runs, it checks each possible event; events that are * currently enabled and whose expiration time has passed get handled. * The set of enabled events is stored as a collection of bitflags in * fotg210->enabled_hrtimer_events, and they are numbered in order of * increasing delay values (ranging between 1 ms and 100 ms). * * Rather than implementing a sorted list or tree of all pending events, * we keep track only of the lowest-numbered pending event, in * fotg210->next_hrtimer_event. Whenever fotg210->hrtimer gets restarted, its * expiration time is set to the timeout value for this event. * * As a result, events might not get handled right away; the actual delay * could be anywhere up to twice the requested delay. This doesn't * matter, because none of the events are especially time-critical. The * ones that matter most all have a delay of 1 ms, so they will be * handled after 2 ms at most, which is okay. In addition to this, we * allow for an expiration range of 1 ms.
*/
/* Delay lengths for the hrtimer event types. * Keep this list sorted by delay length, in the same order as * the event types indexed by enum fotg210_hrtimer_event in fotg210.h.
*/ staticunsigned event_delays_ns[] = {
1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_ASS */
1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_PSS */
1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_DEAD */
1125 * NSEC_PER_USEC, /* FOTG210_HRTIMER_UNLINK_INTR */
2 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_FREE_ITDS */
6 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_ASYNC_UNLINKS */
10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IAA_WATCHDOG */
10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_PERIODIC */
15 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_ASYNC */
100 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IO_WATCHDOG */
};
/* Poll again later, but give up after about 20 ms */ if (fotg210->ASS_poll_count++ < 20) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS, true); return;
}
fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n",
want, actual);
}
fotg210->ASS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ if (want == 0) { /* Stopped */ if (fotg210->async_count > 0)
fotg210_set_command_bit(fotg210, CMD_ASE);
/* Turn off the schedule after a while */
fotg210_enable_event(fotg210,
FOTG210_HRTIMER_DISABLE_ASYNC, true);
}
}
}
/* Turn off the async schedule after a brief delay */ staticvoid fotg210_disable_ASE(struct fotg210_hcd *fotg210)
{
fotg210_clear_command_bit(fotg210, CMD_ASE);
}
/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ staticvoid fotg210_poll_PSS(struct fotg210_hcd *fotg210)
{ unsigned actual, want;
/* Don't do anything if the controller isn't running (e.g., died) */ if (fotg210->rh_state != FOTG210_RH_RUNNING) return;
/* Poll again later, but give up after about 20 ms */ if (fotg210->PSS_poll_count++ < 20) {
fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS, true); return;
}
fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
want, actual);
}
fotg210->PSS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */ if (want == 0) { /* Stopped */ if (fotg210->periodic_count > 0)
fotg210_set_command_bit(fotg210, CMD_PSE);
/* Turn off the schedule after a while */
fotg210_enable_event(fotg210,
FOTG210_HRTIMER_DISABLE_PERIODIC, true);
}
}
}
/* Turn off the periodic schedule after a brief delay */ staticvoid fotg210_disable_PSE(struct fotg210_hcd *fotg210)
{
fotg210_clear_command_bit(fotg210, CMD_PSE);
}
/* Poll the STS_HALT status bit; see when a dead controller stops */ staticvoid fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
{ if (!(fotg210_readl(fotg210, &fotg210->regs->status) & STS_HALT)) {
/* Give up after a few milliseconds */ if (fotg210->died_poll_count++ < 5) { /* Try again later */
fotg210_enable_event(fotg210,
FOTG210_HRTIMER_POLL_DEAD, true); return;
}
fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n");
}
/* Clean up the mess */
fotg210->rh_state = FOTG210_RH_HALTED;
fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
fotg210_work(fotg210);
end_unlink_async(fotg210);
/* Not in process context, so don't try to reset the controller */
}
/* Handle unlinked interrupt QHs once they are gone from the hardware */ staticvoid fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
{ bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
/* * Process all the QHs on the intr_unlink list that were added * before the current unlink cycle began. The list is in * temporal order, so stop when we reach the first entry in the * current cycle. But if the root hub isn't running then * process all the QHs on the list.
*/
fotg210->intr_unlinking = true; while (fotg210->intr_unlink) { struct fotg210_qh *qh = fotg210->intr_unlink;
/* Wait for controller to stop using old iTDs and siTDs */ staticvoid end_free_itds(struct fotg210_hcd *fotg210)
{ struct fotg210_itd *itd, *n;
if (fotg210->rh_state < FOTG210_RH_RUNNING)
fotg210->last_itd_to_free = NULL;
list_for_each_entry_safe(itd, n, &fotg210->cached_itd_list, itd_list) {
list_del(&itd->itd_list);
dma_pool_free(fotg210->itd_pool, itd, itd->itd_dma); if (itd == fotg210->last_itd_to_free) break;
}
if (!list_empty(&fotg210->cached_itd_list))
start_free_itds(fotg210);
}
/* Handle lost (or very late) IAA interrupts */ staticvoid fotg210_iaa_watchdog(struct fotg210_hcd *fotg210)
{ if (fotg210->rh_state != FOTG210_RH_RUNNING) return;
/* * Lost IAA irqs wedge things badly; seen first with a vt8235. * So we need this watchdog, but must protect it against both * (a) SMP races against real IAA firing and retriggering, and * (b) clean HC shutdown, when IAA watchdog was pending.
*/ if (fotg210->async_iaa) {
u32 cmd, status;
/* If we get here, IAA is *REALLY* late. It's barely * conceivable that the system is so busy that CMD_IAAD * is still legitimately set, so let's be sure it's * clear before we read STS_IAA. (The HC should clear * CMD_IAAD when it sets STS_IAA.)
*/
cmd = fotg210_readl(fotg210, &fotg210->regs->command);
/* * If IAA is set here it either legitimately triggered * after the watchdog timer expired (_way_ late, so we'll * still count it as lost) ... or a silicon erratum: * - VIA seems to set IAA without triggering the IRQ; * - IAAD potentially cleared without setting IAA.
*/
status = fotg210_readl(fotg210, &fotg210->regs->status); if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
INCR(fotg210->stats.lost_iaa);
fotg210_writel(fotg210, STS_IAA,
&fotg210->regs->status);
}
/* Enable the I/O watchdog, if appropriate */ staticvoid turn_on_io_watchdog(struct fotg210_hcd *fotg210)
{ /* Not needed if the controller isn't running or it's already enabled */ if (fotg210->rh_state != FOTG210_RH_RUNNING ||
(fotg210->enabled_hrtimer_events &
BIT(FOTG210_HRTIMER_IO_WATCHDOG))) return;
/* * Isochronous transfers always need the watchdog. * For other sorts we use it only if the flag is set.
*/ if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog &&
fotg210->async_count + fotg210->intr_count > 0))
fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG, true);
}
/* Handler functions for the hrtimer event types. * Keep this array in the same order as the event types indexed by * enum fotg210_hrtimer_event in fotg210.h.
*/ staticvoid (*event_handlers[])(struct fotg210_hcd *) = {
fotg210_poll_ASS, /* FOTG210_HRTIMER_POLL_ASS */
fotg210_poll_PSS, /* FOTG210_HRTIMER_POLL_PSS */
fotg210_handle_controller_death, /* FOTG210_HRTIMER_POLL_DEAD */
fotg210_handle_intr_unlinks, /* FOTG210_HRTIMER_UNLINK_INTR */
end_free_itds, /* FOTG210_HRTIMER_FREE_ITDS */
unlink_empty_async, /* FOTG210_HRTIMER_ASYNC_UNLINKS */
fotg210_iaa_watchdog, /* FOTG210_HRTIMER_IAA_WATCHDOG */
fotg210_disable_PSE, /* FOTG210_HRTIMER_DISABLE_PERIODIC */
fotg210_disable_ASE, /* FOTG210_HRTIMER_DISABLE_ASYNC */
fotg210_work, /* FOTG210_HRTIMER_IO_WATCHDOG */
};
/* * Check each pending event. If its time has expired, handle * the event; otherwise re-enable it.
*/
now = ktime_get();
for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) { if (ktime_compare(now, fotg210->hr_timeouts[e]) >= 0)
event_handlers[e](fotg210); else
fotg210_enable_event(fotg210, e, false);
}
staticint check_reset_complete(struct fotg210_hcd *fotg210, int index,
u32 __iomem *status_reg, int port_status)
{ if (!(port_status & PORT_CONNECT)) return port_status;
/* if reset finished and it's still not enabled -- handoff */ if (!(port_status & PORT_PE)) /* with integrated TT, there's nobody to hand it to! */
fotg210_dbg(fotg210, "Failed to enable port %d on root hub TT\n",
index + 1); else
fotg210_dbg(fotg210, "port %d reset complete, port enabled\n",
index + 1);
return port_status;
}
/* build "status change" packet (one or two bytes) from HC registers */
/* * Return status information even for ports with OWNER set. * Otherwise hub_wq wouldn't see the disconnect event when a * high-speed device is switched over to the companion * controller by the user.
*/
/* * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. * HCS_INDICATOR may say we can change LEDs to off/amber/green. * (track current state ourselves) ... blink for diagnostics, * power, "this is the one", etc. EHCI spec supports this.
*/
spin_lock_irqsave(&fotg210->lock, flags); switch (typeReq) { case ClearHubFeature: switch (wValue) { case C_HUB_LOCAL_POWER: case C_HUB_OVER_CURRENT: /* no hub-wide feature/status flags */ break; default: goto error;
} break; case ClearPortFeature: if (!wIndex || wIndex > ports) goto error;
wIndex--;
temp = fotg210_readl(fotg210, status_reg);
temp &= ~PORT_RWC_BITS;
/* * Even if OWNER is set, so the port is owned by the * companion controller, hub_wq needs to be able to clear * the port-change status bits (especially * USB_PORT_STAT_C_CONNECTION).
*/
switch (wValue) { case USB_PORT_FEAT_ENABLE:
fotg210_writel(fotg210, temp & ~PORT_PE, status_reg); break; case USB_PORT_FEAT_C_ENABLE:
fotg210_writel(fotg210, temp | PORT_PEC, status_reg); break; case USB_PORT_FEAT_SUSPEND: if (temp & PORT_RESET) goto error; if (!(temp & PORT_SUSPEND)) break; if ((temp & PORT_PE) == 0) goto error;
/* resume signaling for 20 msec */
fotg210_writel(fotg210, temp | PORT_RESUME, status_reg);
fotg210->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(USB_RESUME_TIMEOUT); break; case USB_PORT_FEAT_C_SUSPEND:
clear_bit(wIndex, &fotg210->port_c_suspend); break; case USB_PORT_FEAT_C_CONNECTION:
fotg210_writel(fotg210, temp | PORT_CSC, status_reg); break; case USB_PORT_FEAT_C_OVER_CURRENT:
fotg210_writel(fotg210, temp | OTGISR_OVC,
&fotg210->regs->otgisr); break; case USB_PORT_FEAT_C_RESET: /* GetPortStatus clears reset */ break; default: goto error;
}
fotg210_readl(fotg210, &fotg210->regs->command); break; case GetHubDescriptor:
fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *)
buf); break; case GetHubStatus: /* no hub-wide feature/status flags */
memset(buf, 0, 4); /*cpu_to_le32s ((u32 *) buf); */ break; case GetPortStatus: if (!wIndex || wIndex > ports) goto error;
wIndex--;
status = 0;
temp = fotg210_readl(fotg210, status_reg);
/* wPortChange bits */ if (temp & PORT_CSC)
status |= USB_PORT_STAT_C_CONNECTION << 16; if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;
temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/* whoever resumes must GetPortStatus to complete it!! */ if (temp & PORT_RESUME) {
/* Remote Wakeup received? */ if (!fotg210->reset_done[wIndex]) { /* resume signaling for 20 msec */
fotg210->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20); /* check the port again */
mod_timer(&fotg210_to_hcd(fotg210)->rh_timer,
fotg210->reset_done[wIndex]);
}
/* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) &&
test_bit(wIndex, &fotg210->companion_ports)) {
temp &= ~PORT_RWC_BITS;
fotg210_writel(fotg210, temp, status_reg);
fotg210_dbg(fotg210, "port %d --> companion\n",
wIndex + 1);
temp = fotg210_readl(fotg210, status_reg);
}
/* * Even if OWNER is set, there's no harm letting hub_wq * see the wPortStatus values (they should all be 0 except * for PORT_POWER anyway).
*/
if (temp & PORT_CONNECT) {
status |= USB_PORT_STAT_CONNECTION;
status |= fotg210_port_speed(fotg210, temp);
} if (temp & PORT_PE)
status |= USB_PORT_STAT_ENABLE;
/* maybe the port was unsuspended without our knowledge */ if (temp & (PORT_SUSPEND|PORT_RESUME)) {
status |= USB_PORT_STAT_SUSPEND;
} elseif (test_bit(wIndex, &fotg210->suspended_ports)) {
clear_bit(wIndex, &fotg210->suspended_ports);
clear_bit(wIndex, &fotg210->resuming_ports);
fotg210->reset_done[wIndex] = 0; if (temp & PORT_PE)
set_bit(wIndex, &fotg210->port_c_suspend);
}
temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_OVERCURRENT; if (temp & PORT_RESET)
status |= USB_PORT_STAT_RESET; if (test_bit(wIndex, &fotg210->port_c_suspend))
status |= USB_PORT_STAT_C_SUSPEND << 16;
if (status & ~0xffff) /* only if wPortChange is interesting */
dbg_port(fotg210, "GetStatus", wIndex + 1, temp);
put_unaligned_le32(status, buf); break; case SetHubFeature: switch (wValue) { case C_HUB_LOCAL_POWER: case C_HUB_OVER_CURRENT: /* no hub-wide feature/status flags */ break; default: goto error;
} break; case SetPortFeature:
selector = wIndex >> 8;
wIndex &= 0xff;
/* After above check the port must be connected. * Set appropriate bit thus could put phy into low power * mode if we have hostpc feature
*/
fotg210_writel(fotg210, temp | PORT_SUSPEND,
status_reg);
set_bit(wIndex, &fotg210->suspended_ports); break; case USB_PORT_FEAT_RESET: if (temp & PORT_RESUME) goto error; /* line status bits may report this as low speed, * which can be fine if this root hub has a * transaction translator built in.
*/
fotg210_dbg(fotg210, "port %d reset\n", wIndex + 1);
temp |= PORT_RESET;
temp &= ~PORT_PE;
/* * caller must wait, then call GetPortStatus * usb 2.0 spec says 50 ms resets on root
*/
fotg210->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(50);
fotg210_writel(fotg210, temp, status_reg); break;
/* For downstream facing ports (these): one hub port is put * into test mode according to USB2 11.24.2.13, then the hub * must be reset (which for root hub now means rmmod+modprobe, * or else system reboot). See EHCI 2.3.9 and 4.14 for info * about the EHCI-specific stuff.
*/ case USB_PORT_FEAT_TEST: if (!selector || selector > 5) goto error;
spin_unlock_irqrestore(&fotg210->lock, flags);
fotg210_quiesce(fotg210);
spin_lock_irqsave(&fotg210->lock, flags);
/* Put all enabled ports into suspend */
temp = fotg210_readl(fotg210, status_reg) &
~PORT_RWC_BITS; if (temp & PORT_PE)
fotg210_writel(fotg210, temp | PORT_SUSPEND,
status_reg);
/* There's basically three types of memory: * - data used only by the HCD ... kmalloc is fine * - async and periodic schedules, shared by HC and HCD ... these * need to use dma_pool or dma_alloc_coherent * - driver buffers, read/written by HC ... single shot DMA mapped * * There's also "register" data (e.g. PCI or SOC), which is memory mapped. * No memory seen by this driver is pageable.
*/
/* Allocate the key transfer structures from the previously allocated pool */ staticinlinevoid fotg210_qtd_init(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t dma)
{
memset(qtd, 0, sizeof(*qtd));
qtd->qtd_dma = dma;
qtd->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT);
qtd->hw_next = FOTG210_LIST_END(fotg210);
qtd->hw_alt_next = FOTG210_LIST_END(fotg210);
INIT_LIST_HEAD(&qtd->qtd_list);
}
/* The queue heads and transfer descriptors are managed from pools tied * to each of the "per device" structures. * This is the initialisation and cleanup code.
*/
for (i = 0; i < fotg210->periodic_size; i++)
fotg210->periodic[i] = FOTG210_LIST_END(fotg210);
/* software shadow of hardware table */
fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *),
flags); if (fotg210->pshadow != NULL) return 0;
fail:
fotg210_dbg(fotg210, "couldn't init memory\n");
fotg210_mem_cleanup(fotg210); return -ENOMEM;
} /* EHCI hardware queue manipulation ... the core. QH/QTD manipulation. * * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned * buffers needed for the larger number). We use one QH per endpoint, queue * multiple urbs (all three types) per endpoint. URBs may need several qtds. * * ISO traffic uses "ISO TD" (itd) records, and (along with * interrupts) needs careful scheduling. Performance improvements can be * an ongoing challenge. That's in "ehci-sched.c". * * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, * or otherwise through transaction translators (TTs) in USB 2.0 hubs using * (b) special fields in qh entries or (c) split iso entries. TTs will * buffer low/full speed data so the host collects it at high speed.
*/
/* fill a qtd, returning how much of the buffer we were able to queue up */ staticint qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd,
dma_addr_t buf, size_t len, int token, int maxpacket)
{ int i, count;
u64 addr = buf;
/* one buffer entry per 4K ... first might be short or unaligned */
qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr);
qtd->hw_buf_hi[0] = cpu_to_hc32(fotg210, (u32)(addr >> 32));
count = 0x1000 - (buf & 0x0fff); /* rest of that page */ if (likely(len < count)) /* ... iff needed */
count = len; else {
buf += 0x1000;
buf &= ~0x0fff;
/* per-qtd limit: from 16K to 20K (best alignment) */ for (i = 1; count < len && i < 5; i++) {
addr = buf;
qtd->hw_buf[i] = cpu_to_hc32(fotg210, (u32)addr);
qtd->hw_buf_hi[i] = cpu_to_hc32(fotg210,
(u32)(addr >> 32));
buf += 0x1000; if ((count + 0x1000) < len)
count += 0x1000; else
count = len;
}
/* short packets may only terminate transfers */ if (count != len)
count -= (count % maxpacket);
}
qtd->hw_token = cpu_to_hc32(fotg210, (count << 16) | token);
qtd->length = count;
/* Except for control endpoints, we make hardware maintain data * toggle (like OHCI) ... here (re)initialize the toggle in the QH, * and set the pseudo-toggle in udev. Only usb_clear_halt() will * ever clear it.
*/ if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) { unsigned is_out, epnum;
/* if it weren't for a common silicon quirk (writing the dummy into the qh * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault * recovery (including urb dequeue) would need software changes to a QH...
*/ staticvoid qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{ struct fotg210_qtd *qtd;
if (list_empty(&qh->qtd_list))
qtd = qh->dummy; else {
qtd = list_entry(qh->qtd_list.next, struct fotg210_qtd, qtd_list); /* * first qtd may already be partially processed. * If we come here during unlink, the QH overlay region * might have reference to the just unlinked qtd. The * qtd is updated in qh_completions(). Update the QH * overlay here.
*/ if (cpu_to_hc32(fotg210, qtd->qtd_dma) == qh->hw->hw_current) {
qh->hw->hw_qtd_next = qtd->hw_next;
qtd = NULL;
}
}
/* If an async split transaction gets an error or is unlinked, * the TT buffer may be left in an indeterminate state. We * have to clear the TT buffer. * * Note: this routine is never called for Isochronous transfers.
*/ if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { struct usb_device *tt = urb->dev->tt->hub;
if (urb->dev->tt->hub !=
fotg210_to_hcd(fotg210)->self.root_hub) { if (usb_hub_clear_tt_buffer(urb) == 0)
qh->clearing_tt = 1;
}
}
}
staticint qtd_copy_status(struct fotg210_hcd *fotg210, struct urb *urb,
size_t length, u32 token)
{ int status = -EINPROGRESS;
/* count IN/OUT bytes, not SETUP (even short packets) */ if (likely(QTD_PID(token) != 2))
urb->actual_length += length - QTD_LENGTH(token);
/* don't modify error codes */ if (unlikely(urb->unlinked)) return status;
/* force cleanup after short read; not always an error */ if (unlikely(IS_SHORT_READ(token)))
status = -EREMOTEIO;
/* serious "can't proceed" faults reported by the hardware */ if (token & QTD_STS_HALT) { if (token & QTD_STS_BABBLE) { /* FIXME "must" disable babbling device's port too */
status = -EOVERFLOW; /* CERR nonzero + halt --> stall */
} elseif (QTD_CERR(token)) {
status = -EPIPE;
/* In theory, more than one of the following bits can be set * since they are sticky and the transaction is retried. * Which to test first is rather arbitrary.
*/
} elseif (token & QTD_STS_MMF) { /* fs/ls interrupt xfer missed the complete-split */
status = -EPROTO;
} elseif (token & QTD_STS_DBE) {
status = (QTD_PID(token) == 1) /* IN ? */
? -ENOSR /* hc couldn't read data */
: -ECOMM; /* hc couldn't write data */
} elseif (token & QTD_STS_XACT) { /* timeout, bad CRC, wrong PID, etc */
fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n",
urb->dev->devpath,
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out");
status = -EPROTO;
} else { /* unknown */
status = -EPROTO;
}
if (unlikely(urb->unlinked)) {
INCR(fotg210->stats.unlink);
} else { /* report non-error and short read status as zero */ if (status == -EINPROGRESS || status == -EREMOTEIO)
status = 0;
INCR(fotg210->stats.complete);
}
/* Process and free completed qtds for a qh, returning URBs to drivers. * Chases up to qh->hw_current. Returns number of completions called, * indicating how much "real" work we did.
*/ staticunsigned qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
{ struct fotg210_qtd *last, *end = qh->dummy; struct fotg210_qtd *qtd, *tmp; int last_status; int stopped; unsigned count = 0;
u8 state; struct fotg210_qh_hw *hw = qh->hw;
if (unlikely(list_empty(&qh->qtd_list))) return count;
/* completions (or tasks on other cpus) must never clobber HALT * till we've gone through and cleaned everything up, even when * they add urbs to this qh's queue or mark them for unlinking. * * NOTE: unlinking expects to be done in queue order. * * It's a bug for qh->qh_state to be anything other than * QH_STATE_IDLE, unless our caller is scan_async() or * scan_intr().
*/
state = qh->qh_state;
qh->qh_state = QH_STATE_COMPLETING;
stopped = (state == QH_STATE_IDLE);
rescan:
last = NULL;
last_status = -EINPROGRESS;
qh->needs_rescan = 0;
/* remove de-activated QTDs from front of queue. * after faults (including short reads), cleanup this urb * then let the queue advance. * if queue is stopped, handles unlinks.
*/
list_for_each_entry_safe(qtd, tmp, &qh->qtd_list, qtd_list) { struct urb *urb;
u32 token = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.