Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 1048 → Rev 1049

/shark/trunk/drivers/usb/host/ehci-sched.c
1,1123 → 1,1123
/*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* this file is part of ehci-hcd.c */
 
/*-------------------------------------------------------------------------*/
 
/*
* EHCI scheduled transaction support: interrupt, iso, split iso
* These are called "periodic" transactions in the EHCI spec.
*
* Note that for interrupt transfers, the QH/QTD manipulation is shared
* with the "asynchronous" transaction support (control/bulk transfers).
* The only real difference is in how interrupt transfers are scheduled.
* We get some funky API restrictions from the current URB model, which
* works notably better for reading transfers than for writing. (And
* which accordingly needs to change before it'll work inside devices,
* or with "USB On The Go" additions to USB 2.0 ...)
*/
 
static int ehci_get_frame (struct usb_hcd *hcd);
 
/*-------------------------------------------------------------------------*/
 
/*
* periodic_next_shadow - return "next" pointer on shadow list
* @periodic: host pointer to qh/itd/sitd
* @tag: hardware tag for type of this record
*/
static union ehci_shadow *
periodic_next_shadow (union ehci_shadow *periodic, int tag)
{
switch (tag) {
case Q_TYPE_QH:
return &periodic->qh->qh_next;
case Q_TYPE_FSTN:
return &periodic->fstn->fstn_next;
case Q_TYPE_ITD:
return &periodic->itd->itd_next;
#ifdef have_split_iso
case Q_TYPE_SITD:
return &periodic->sitd->sitd_next;
#endif /* have_split_iso */
}
dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
// BUG ();
return 0;
}
 
/* returns true after successful unlink */
/* caller must hold ehci->lock */
static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
{
union ehci_shadow *prev_p = &ehci->pshadow [frame];
u32 *hw_p = &ehci->periodic [frame];
union ehci_shadow here = *prev_p;
union ehci_shadow *next_p;
 
/* find predecessor of "ptr"; hw and shadow lists are in sync */
while (here.ptr && here.ptr != ptr) {
prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
hw_p = &here.qh->hw_next;
here = *prev_p;
}
/* an interrupt entry (at list end) could have been shared */
if (!here.ptr) {
dbg ("entry %p no longer on frame [%d]", ptr, frame);
return 0;
}
// vdbg ("periodic unlink %p from frame %d", ptr, frame);
 
/* update hardware list ... HC may still know the old structure, so
* don't change hw_next until it'll have purged its cache
*/
next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
*hw_p = here.qh->hw_next;
 
/* unlink from shadow list; HCD won't see old structure again */
*prev_p = *next_p;
next_p->ptr = 0;
 
return 1;
}
 
/* how many of the uframe's 125 usecs are allocated? */
static unsigned short
periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
{
u32 *hw_p = &ehci->periodic [frame];
union ehci_shadow *q = &ehci->pshadow [frame];
unsigned usecs = 0;
 
while (q->ptr) {
switch (Q_NEXT_TYPE (*hw_p)) {
case Q_TYPE_QH:
/* is it in the S-mask? */
if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
usecs += q->qh->usecs;
/* ... or C-mask? */
if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
usecs += q->qh->c_usecs;
q = &q->qh->qh_next;
break;
case Q_TYPE_FSTN:
/* for "save place" FSTNs, count the relevant INTR
* bandwidth from the previous frame
*/
if (q->fstn->hw_prev != EHCI_LIST_END) {
dbg ("not counting FSTN bandwidth yet ...");
}
q = &q->fstn->fstn_next;
break;
case Q_TYPE_ITD:
/* NOTE the "one uframe per itd" policy */
if (q->itd->hw_transaction [uframe] != 0)
usecs += q->itd->usecs;
q = &q->itd->itd_next;
break;
#ifdef have_split_iso
case Q_TYPE_SITD:
temp = q->sitd->hw_fullspeed_ep &
__constant_cpu_to_le32 (1 << 31);
 
// FIXME: this doesn't count data bytes right...
 
/* is it in the S-mask? (count SPLIT, DATA) */
if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
if (temp)
usecs += HS_USECS (188);
else
usecs += HS_USECS (1);
}
 
/* ... C-mask? (count CSPLIT, DATA) */
if (q->sitd->hw_uframe &
cpu_to_le32 (1 << (8 + uframe))) {
if (temp)
usecs += HS_USECS (0);
else
usecs += HS_USECS (188);
}
q = &q->sitd->sitd_next;
break;
#endif /* have_split_iso */
default:
BUG ();
}
}
#ifdef DEBUG
if (usecs > 100)
err ("overallocated uframe %d, periodic is %d usecs",
frame * 8 + uframe, usecs);
#endif
return usecs;
}
 
/*-------------------------------------------------------------------------*/
 
static int enable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
int status;
 
/* did clearing PSE did take effect yet?
* takes effect only at frame boundaries...
*/
status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
ehci->hcd.state = USB_STATE_HALT;
return status;
}
 
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
ehci->hcd.state = USB_STATE_RUNNING;
 
/* make sure ehci_work scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
% (ehci->periodic_size << 3);
return 0;
}
 
static int disable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
int status;
 
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
ehci->hcd.state = USB_STATE_HALT;
return status;
}
 
cmd = readl (&ehci->regs->command) & ~CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... */
 
ehci->next_uframe = -1;
return 0;
}
 
/*-------------------------------------------------------------------------*/
 
// FIXME microframe periods not yet handled
 
static void intr_deschedule (
struct ehci_hcd *ehci,
struct ehci_qh *qh,
int wait
) {
int status;
unsigned frame = qh->start;
 
do {
periodic_unlink (ehci, frame, qh);
qh_put (ehci, qh);
frame += qh->period;
} while (frame < ehci->periodic_size);
 
qh->qh_state = QH_STATE_UNLINK;
qh->qh_next.ptr = 0;
ehci->periodic_sched--;
 
/* maybe turn off periodic schedule */
if (!ehci->periodic_sched)
status = disable_periodic (ehci);
else {
status = 0;
vdbg ("periodic schedule still enabled");
}
 
/*
* If the hc may be looking at this qh, then delay a uframe
* (yeech!) to be sure it's done.
* No other threads may be mucking with this qh.
*/
if (((ehci_get_frame (&ehci->hcd) - frame) % qh->period) == 0) {
if (wait) {
udelay (125);
qh->hw_next = EHCI_LIST_END;
} else {
/* we may not be IDLE yet, but if the qh is empty
* the race is very short. then if qh also isn't
* rescheduled soon, it won't matter. otherwise...
*/
vdbg ("intr_deschedule...");
}
} else
qh->hw_next = EHCI_LIST_END;
 
qh->qh_state = QH_STATE_IDLE;
 
/* update per-qh bandwidth utilization (for usbfs) */
hcd_to_bus (&ehci->hcd)->bandwidth_allocated -=
(qh->usecs + qh->c_usecs) / qh->period;
 
dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d",
qh, qh->period, frame,
atomic_read (&qh->refcount), ehci->periodic_sched);
}
 
static int check_period (
struct ehci_hcd *ehci,
unsigned frame,
unsigned uframe,
unsigned period,
unsigned usecs
) {
/* complete split running into next frame?
* given FSTN support, we could sometimes check...
*/
if (uframe >= 8)
return 0;
 
/*
* 80% periodic == 100 usec/uframe available
* convert "usecs we need" to "max already claimed"
*/
usecs = 100 - usecs;
 
do {
int claimed;
 
// FIXME delete when intr_submit handles non-empty queues
// this gives us a one intr/frame limit (vs N/uframe)
// ... and also lets us avoid tracking split transactions
// that might collide at a given TT/hub.
if (ehci->pshadow [frame].ptr)
return 0;
 
claimed = periodic_usecs (ehci, frame, uframe);
if (claimed > usecs)
return 0;
 
// FIXME update to handle sub-frame periods
} while ((frame += period) < ehci->periodic_size);
 
// success!
return 1;
}
 
static int check_intr_schedule (
struct ehci_hcd *ehci,
unsigned frame,
unsigned uframe,
const struct ehci_qh *qh,
u32 *c_maskp
)
{
int retval = -ENOSPC;
 
if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
goto done;
if (!qh->c_usecs) {
retval = 0;
*c_maskp = cpu_to_le32 (0);
goto done;
}
 
/* This is a split transaction; check the bandwidth available for
* the completion too. Check both worst and best case gaps: worst
* case is SPLIT near uframe end, and CSPLIT near start ... best is
* vice versa. Difference can be almost two uframe times, but we
* reserve unnecessary bandwidth (waste it) this way. (Actually
* even better cases exist, like immediate device NAK.)
*
* FIXME don't even bother unless we know this TT is idle in that
* range of uframes ... for now, check_period() allows only one
* interrupt transfer per frame, so needn't check "TT busy" status
* when scheduling a split (QH, SITD, or FSTN).
*
* FIXME ehci 0.96 and above can use FSTNs
*/
if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
qh->period, qh->c_usecs))
goto done;
if (!check_period (ehci, frame, uframe + qh->gap_uf,
qh->period, qh->c_usecs))
goto done;
 
*c_maskp = cpu_to_le32 (0x03 << (8 + uframe + qh->gap_uf));
retval = 0;
done:
return retval;
}
 
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
int status;
unsigned uframe;
u32 c_mask;
unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
 
qh->hw_next = EHCI_LIST_END;
frame = qh->start;
 
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
uframe = 0;
c_mask = 0;
status = -ENOSPC;
}
 
/* else scan the schedule to find a group of slots such that all
* uframes have enough periodic bandwidth available.
*/
if (status) {
frame = qh->period - 1;
do {
for (uframe = 0; uframe < 8; uframe++) {
status = check_intr_schedule (ehci,
frame, uframe, qh,
&c_mask);
if (status == 0)
break;
}
} while (status && frame--);
if (status)
goto done;
qh->start = frame;
 
/* reset S-frame and (maybe) C-frame masks */
qh->hw_info2 &= ~0xffff;
qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
} else
dbg ("reused previous qh %p schedule", qh);
 
/* stuff into the periodic schedule */
qh->qh_state = QH_STATE_LINKED;
dbg ("scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)",
qh, qh->usecs, qh->c_usecs,
qh->period, frame, uframe, qh->gap_uf);
do {
if (unlikely (ehci->pshadow [frame].ptr != 0)) {
 
// FIXME -- just link toward the end, before any qh with a shorter period,
// AND accommodate it already having been linked here (after some other qh)
// AS WELL AS updating the schedule checking logic
 
BUG ();
} else {
ehci->pshadow [frame].qh = qh_get (qh);
ehci->periodic [frame] =
QH_NEXT (qh->qh_dma);
}
wmb ();
frame += qh->period;
} while (frame < ehci->periodic_size);
 
/* update per-qh bandwidth for usbfs */
hcd_to_bus (&ehci->hcd)->bandwidth_allocated +=
(qh->usecs + qh->c_usecs) / qh->period;
 
/* maybe enable periodic schedule processing */
if (!ehci->periodic_sched++)
status = enable_periodic (ehci);
done:
return status;
}
 
static int intr_submit (
struct ehci_hcd *ehci,
struct urb *urb,
struct list_head *qtd_list,
int mem_flags
) {
unsigned epnum;
unsigned long flags;
struct ehci_qh *qh;
struct hcd_dev *dev;
int is_input;
int status = 0;
struct list_head empty;
 
/* get endpoint and transfer/schedule data */
epnum = usb_pipeendpoint (urb->pipe);
is_input = usb_pipein (urb->pipe);
if (is_input)
epnum |= 0x10;
 
spin_lock_irqsave (&ehci->lock, flags);
dev = (struct hcd_dev *)urb->dev->hcpriv;
 
/* get qh and force any scheduling errors */
INIT_LIST_HEAD (&empty);
qh = qh_append_tds (ehci, urb, &empty, epnum, &dev->ep [epnum]);
if (qh == 0) {
status = -ENOMEM;
goto done;
}
if (qh->qh_state == QH_STATE_IDLE) {
if ((status = qh_schedule (ehci, qh)) != 0)
goto done;
}
 
/* then queue the urb's tds to the qh */
qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
BUG_ON (qh == 0);
 
/* ... update usbfs periodic stats */
hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++;
 
done:
spin_unlock_irqrestore (&ehci->lock, flags);
if (status)
qtd_list_free (ehci, urb, qtd_list);
 
return status;
}
 
static unsigned
intr_complete (
struct ehci_hcd *ehci,
unsigned frame,
struct ehci_qh *qh,
struct pt_regs *regs
) {
unsigned count;
 
/* nothing to report? */
if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
!= 0))
return 0;
if (unlikely (list_empty (&qh->qtd_list))) {
dbg ("intr qh %p no TDs?", qh);
return 0;
}
/* handle any completions */
count = qh_completions (ehci, qh, regs);
 
if (unlikely (list_empty (&qh->qtd_list)))
intr_deschedule (ehci, qh, 0);
 
return count;
}
 
/*-------------------------------------------------------------------------*/
 
static void
itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
{
struct ehci_itd *first_itd = urb->hcpriv;
 
while (!list_empty (&first_itd->itd_list)) {
struct ehci_itd *itd;
 
itd = list_entry (
first_itd->itd_list.next,
struct ehci_itd, itd_list);
list_del (&itd->itd_list);
pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
}
pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma);
urb->hcpriv = 0;
}
 
static int
itd_fill (
struct ehci_hcd *ehci,
struct ehci_itd *itd,
struct urb *urb,
unsigned index, // urb->iso_frame_desc [index]
dma_addr_t dma // mapped transfer buffer
) {
u64 temp;
u32 buf1;
unsigned i, epnum, maxp, multi;
unsigned length;
int is_input;
 
itd->hw_next = EHCI_LIST_END;
itd->urb = urb;
itd->index = index;
 
/* tell itd about its transfer buffer, max 2 pages */
length = urb->iso_frame_desc [index].length;
dma += urb->iso_frame_desc [index].offset;
temp = dma & ~0x0fff;
for (i = 0; i < 2; i++) {
itd->hw_bufp [i] = cpu_to_le32 ((u32) temp);
itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32));
temp += 0x1000;
}
itd->buf_dma = dma;
 
/*
* this might be a "high bandwidth" highspeed endpoint,
* as encoded in the ep descriptor's maxpacket field
*/
epnum = usb_pipeendpoint (urb->pipe);
is_input = usb_pipein (urb->pipe);
if (is_input) {
maxp = urb->dev->epmaxpacketin [epnum];
buf1 = (1 << 11);
} else {
maxp = urb->dev->epmaxpacketout [epnum];
buf1 = 0;
}
buf1 |= (maxp & 0x03ff);
multi = 1;
multi += (maxp >> 11) & 0x03;
maxp &= 0x03ff;
maxp *= multi;
 
/* transfer can't fit in any uframe? */
if (length < 0 || maxp < length) {
dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)",
length, maxp, urb, index,
urb->iso_frame_desc [index].length);
return -ENOSPC;
}
itd->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 1, length);
 
/* "plus" info in low order bits of buffer pointers */
itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum);
itd->hw_bufp [1] |= cpu_to_le32 (buf1);
itd->hw_bufp [2] |= cpu_to_le32 (multi);
 
/* figure hw_transaction[] value (it's scheduled later) */
itd->transaction = EHCI_ISOC_ACTIVE;
itd->transaction |= dma & 0x0fff; /* offset; buffer=0 */
if ((index + 1) == urb->number_of_packets)
itd->transaction |= EHCI_ITD_IOC; /* end-of-urb irq */
itd->transaction |= length << 16;
cpu_to_le32s (&itd->transaction);
 
return 0;
}
 
static int
itd_urb_transaction (
struct ehci_hcd *ehci,
struct urb *urb,
int mem_flags
) {
int frame_index;
struct ehci_itd *first_itd, *itd;
int status;
dma_addr_t itd_dma;
 
/* allocate/init ITDs */
for (frame_index = 0, first_itd = 0;
frame_index < urb->number_of_packets;
frame_index++) {
itd = pci_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma);
if (!itd) {
status = -ENOMEM;
goto fail;
}
memset (itd, 0, sizeof *itd);
itd->itd_dma = itd_dma;
 
status = itd_fill (ehci, itd, urb, frame_index,
urb->transfer_dma);
if (status != 0)
goto fail;
 
if (first_itd)
list_add_tail (&itd->itd_list,
&first_itd->itd_list);
else {
INIT_LIST_HEAD (&itd->itd_list);
urb->hcpriv = first_itd = itd;
}
}
urb->error_count = 0;
return 0;
 
fail:
if (urb->hcpriv)
itd_free_list (ehci, urb);
return status;
}
 
/*-------------------------------------------------------------------------*/
 
static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{
/* always prepend ITD/SITD ... only QH tree is order-sensitive */
itd->itd_next = ehci->pshadow [frame];
itd->hw_next = ehci->periodic [frame];
ehci->pshadow [frame].itd = itd;
ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
}
 
/*
* return zero on success, else -errno
* - start holds first uframe to start scheduling into
* - max is the first uframe it's NOT (!) OK to start scheduling into
* math to be done modulo "mod" (ehci->periodic_size << 3)
*/
static int get_iso_range (
struct ehci_hcd *ehci,
struct urb *urb,
unsigned *start,
unsigned *max,
unsigned mod
) {
struct list_head *lh;
struct hcd_dev *dev = urb->dev->hcpriv;
int last = -1;
unsigned now, span, end;
 
span = urb->interval * urb->number_of_packets;
 
/* first see if we know when the next transfer SHOULD happen */
list_for_each (lh, &dev->urb_list) {
struct urb *u;
struct ehci_itd *itd;
unsigned s;
 
u = list_entry (lh, struct urb, urb_list);
if (u == urb || u->pipe != urb->pipe)
continue;
if (u->interval != urb->interval) { /* must not change! */
dbg ("urb %p interval %d ... != %p interval %d",
u, u->interval, urb, urb->interval);
return -EINVAL;
}
/* URB for this endpoint... covers through when? */
itd = urb->hcpriv;
s = itd->uframe + u->interval * u->number_of_packets;
if (last < 0)
last = s;
else {
/*
* So far we can only queue two ISO URBs...
*
* FIXME do interval math, figure out whether
* this URB is "before" or not ... also, handle
* the case where the URB might have completed,
* but hasn't yet been processed.
*/
dbg ("NYET: queue >2 URBs per ISO endpoint");
return -EDOM;
}
}
 
/* calculate the legal range [start,max) */
now = readl (&ehci->regs->frame_index) + 1; /* next uframe */
if (!ehci->periodic_sched)
now += 8; /* startup delay */
now %= mod;
end = now + mod;
if (last < 0) {
*start = now + ehci->i_thresh + /* paranoia */ 1;
*max = end - span;
if (*max < *start + 1)
*max = *start + 1;
} else {
*start = last % mod;
*max = (last + 1) % mod;
}
 
/* explicit start frame? */
if (!(urb->transfer_flags & URB_ISO_ASAP)) {
unsigned temp;
 
/* sanity check: must be in range */
urb->start_frame %= ehci->periodic_size;
temp = urb->start_frame << 3;
if (temp < *start)
temp += mod;
if (temp > *max)
return -EDOM;
 
/* use that explicit start frame */
*start = urb->start_frame << 3;
temp += 8;
if (temp < *max)
*max = temp;
}
 
// FIXME minimize wraparound to "now" ... insist max+span
// (and start+span) remains a few frames short of "end"
 
*max %= ehci->periodic_size;
if ((*start + span) < end)
return 0;
return -EFBIG;
}
 
static int
itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
{
unsigned start, max, i;
int status;
unsigned mod = ehci->periodic_size << 3;
 
for (i = 0; i < urb->number_of_packets; i++) {
urb->iso_frame_desc [i].status = -EINPROGRESS;
urb->iso_frame_desc [i].actual_length = 0;
}
 
if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0)
return status;
 
do {
unsigned uframe;
unsigned usecs;
struct ehci_itd *itd;
 
/* check schedule: enough space? */
itd = urb->hcpriv;
uframe = start;
for (i = 0, uframe = start;
i < urb->number_of_packets;
i++, uframe += urb->interval) {
uframe %= mod;
 
/* can't commit more than 80% periodic == 100 usec */
if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
> (100 - itd->usecs)) {
itd = 0;
break;
}
itd = list_entry (itd->itd_list.next,
struct ehci_itd, itd_list);
}
if (!itd)
continue;
/* that's where we'll schedule this! */
itd = urb->hcpriv;
urb->start_frame = start >> 3;
vdbg ("ISO urb %p (%d packets period %d) starting %d.%d",
urb, urb->number_of_packets, urb->interval,
urb->start_frame, start & 0x7);
for (i = 0, uframe = start, usecs = 0;
i < urb->number_of_packets;
i++, uframe += urb->interval) {
uframe %= mod;
 
itd->uframe = uframe;
itd->hw_transaction [uframe & 0x07] = itd->transaction;
itd_link (ehci, (uframe >> 3) % ehci->periodic_size,
itd);
wmb ();
usecs += itd->usecs;
 
itd = list_entry (itd->itd_list.next,
struct ehci_itd, itd_list);
}
 
/* update bandwidth utilization records (for usbfs)
*
* FIXME This claims each URB queued to an endpoint, as if
* transfers were concurrent, not sequential. So bandwidth
* typically gets double-billed ... comes from tying it to
* URBs rather than endpoints in the schedule. Luckily we
* don't use this usbfs data for serious decision making.
*/
usecs /= urb->number_of_packets;
usecs /= urb->interval;
usecs >>= 3;
if (usecs < 1)
usecs = 1;
usb_claim_bandwidth (urb->dev, urb, usecs, 1);
 
/* maybe enable periodic schedule processing */
if (!ehci->periodic_sched++) {
if ((status = enable_periodic (ehci)) != 0) {
// FIXME deschedule right away
err ("itd_schedule, enable = %d", status);
}
}
 
return 0;
 
} while ((start = ++start % mod) != max);
 
/* no room in the schedule */
dbg ("urb %p, CAN'T SCHEDULE", urb);
return -ENOSPC;
}
 
/*-------------------------------------------------------------------------*/
 
#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 
static unsigned
itd_complete (
struct ehci_hcd *ehci,
struct ehci_itd *itd,
unsigned uframe,
struct pt_regs *regs
) {
struct urb *urb = itd->urb;
struct usb_iso_packet_descriptor *desc;
u32 t;
 
/* update status for this uframe's transfers */
desc = &urb->iso_frame_desc [itd->index];
 
t = itd->hw_transaction [uframe];
itd->hw_transaction [uframe] = 0;
if (t & EHCI_ISOC_ACTIVE)
desc->status = -EXDEV;
else if (t & ISO_ERRS) {
urb->error_count++;
if (t & EHCI_ISOC_BUF_ERR)
desc->status = usb_pipein (urb->pipe)
? -ENOSR /* couldn't read */
: -ECOMM; /* couldn't write */
else if (t & EHCI_ISOC_BABBLE)
desc->status = -EOVERFLOW;
else /* (t & EHCI_ISOC_XACTERR) */
desc->status = -EPROTO;
 
/* HC need not update length with this error */
if (!(t & EHCI_ISOC_BABBLE))
desc->actual_length += EHCI_ITD_LENGTH (t);
} else {
desc->status = 0;
desc->actual_length += EHCI_ITD_LENGTH (t);
}
 
vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d",
itd, urb, itd->index + 1, urb->number_of_packets,
t, desc->status, desc->actual_length);
 
/* handle completion now? */
if ((itd->index + 1) != urb->number_of_packets)
return 0;
 
/*
* Always give the urb back to the driver ... expect it to submit
* a new urb (or resubmit this), and to have another already queued
* when un-interrupted transfers are needed.
*
* NOTE that for now we don't accelerate ISO unlinks; they just
* happen according to the current schedule. Means a delay of
* up to about a second (max).
*/
itd_free_list (ehci, urb);
if (urb->status == -EINPROGRESS)
urb->status = 0;
 
/* complete() can reenter this HCD */
spin_unlock (&ehci->lock);
usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
spin_lock (&ehci->lock);
 
/* defer stopping schedule; completion can submit */
ehci->periodic_sched--;
if (!ehci->periodic_sched)
(void) disable_periodic (ehci);
 
return 1;
}
 
/*-------------------------------------------------------------------------*/
 
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
{
int status;
unsigned long flags;
 
dbg ("itd_submit urb %p", urb);
 
/* allocate ITDs w/o locking anything */
status = itd_urb_transaction (ehci, urb, mem_flags);
if (status < 0)
return status;
 
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
status = itd_schedule (ehci, urb);
spin_unlock_irqrestore (&ehci->lock, flags);
if (status < 0)
itd_free_list (ehci, urb);
 
return status;
}
 
#ifdef have_split_iso
 
/*-------------------------------------------------------------------------*/
 
/*
* "Split ISO TDs" ... used for USB 1.1 devices going through
* the TTs in USB 2.0 hubs.
*
* FIXME not yet implemented
*/
 
#endif /* have_split_iso */
 
/*-------------------------------------------------------------------------*/
 
static void
scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
{
unsigned frame, clock, now_uframe, mod;
unsigned count = 0;
 
mod = ehci->periodic_size << 3;
 
/*
* When running, scan from last scan point up to "now"
* else clean up by scanning everything that's left.
* Touches as few pages as possible: cache-friendly.
* Don't scan ISO entries more than once, though.
*/
frame = ehci->next_uframe >> 3;
if (HCD_IS_RUNNING (ehci->hcd.state))
now_uframe = readl (&ehci->regs->frame_index);
else
now_uframe = (frame << 3) - 1;
now_uframe %= mod;
clock = now_uframe >> 3;
 
for (;;) {
union ehci_shadow q, *q_p;
u32 type, *hw_p;
unsigned uframes;
 
restart:
/* scan schedule to _before_ current frame index */
if (frame == clock)
uframes = now_uframe & 0x07;
else
uframes = 8;
 
q_p = &ehci->pshadow [frame];
hw_p = &ehci->periodic [frame];
q.ptr = q_p->ptr;
type = Q_NEXT_TYPE (*hw_p);
 
/* scan each element in frame's queue for completions */
while (q.ptr != 0) {
int last;
unsigned uf;
union ehci_shadow temp;
 
switch (type) {
case Q_TYPE_QH:
last = (q.qh->hw_next == EHCI_LIST_END);
temp = q.qh->qh_next;
type = Q_NEXT_TYPE (q.qh->hw_next);
count += intr_complete (ehci, frame,
qh_get (q.qh), regs);
qh_put (ehci, q.qh);
q = temp;
break;
case Q_TYPE_FSTN:
last = (q.fstn->hw_next == EHCI_LIST_END);
/* for "save place" FSTNs, look at QH entries
* in the previous frame for completions.
*/
if (q.fstn->hw_prev != EHCI_LIST_END) {
dbg ("ignoring completions from FSTNs");
}
type = Q_NEXT_TYPE (q.fstn->hw_next);
q = q.fstn->fstn_next;
break;
case Q_TYPE_ITD:
last = (q.itd->hw_next == EHCI_LIST_END);
 
/* Unlink each (S)ITD we see, since the ISO
* URB model forces constant rescheduling.
* That complicates sharing uframes in ITDs,
* and means we need to skip uframes the HC
* hasn't yet processed.
*/
for (uf = 0; uf < uframes; uf++) {
if (q.itd->hw_transaction [uf] != 0) {
temp = q;
*q_p = q.itd->itd_next;
*hw_p = q.itd->hw_next;
type = Q_NEXT_TYPE (*hw_p);
 
/* might free q.itd ... */
count += itd_complete (ehci,
temp.itd, uf, regs);
break;
}
}
/* we might skip this ITD's uframe ... */
if (uf == uframes) {
q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next;
type = Q_NEXT_TYPE (q.itd->hw_next);
}
 
q = *q_p;
break;
#ifdef have_split_iso
case Q_TYPE_SITD:
last = (q.sitd->hw_next == EHCI_LIST_END);
sitd_complete (ehci, q.sitd);
type = Q_NEXT_TYPE (q.sitd->hw_next);
 
// FIXME unlink SITD after split completes
q = q.sitd->sitd_next;
break;
#endif /* have_split_iso */
default:
dbg ("corrupt type %d frame %d shadow %p",
type, frame, q.ptr);
// BUG ();
last = 1;
q.ptr = 0;
}
 
/* did completion remove an interior q entry? */
if (unlikely (q.ptr == 0 && !last))
goto restart;
}
 
/* stop when we catch up to the HC */
 
// FIXME: this assumes we won't get lapped when
// latencies climb; that should be rare, but...
// detect it, and just go all the way around.
// FLR might help detect this case, so long as latencies
// don't exceed periodic_size msec (default 1.024 sec).
 
// FIXME: likewise assumes HC doesn't halt mid-scan
 
if (frame == clock) {
unsigned now;
 
if (!HCD_IS_RUNNING (ehci->hcd.state))
break;
ehci->next_uframe = now_uframe;
now = readl (&ehci->regs->frame_index) % mod;
if (now_uframe == now)
break;
 
/* rescan the rest of this frame, then ... */
now_uframe = now;
clock = now_uframe >> 3;
} else
frame = (frame + 1) % ehci->periodic_size;
}
}
/*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
 
/* this file is part of ehci-hcd.c */
 
/*-------------------------------------------------------------------------*/
 
/*
* EHCI scheduled transaction support: interrupt, iso, split iso
* These are called "periodic" transactions in the EHCI spec.
*
* Note that for interrupt transfers, the QH/QTD manipulation is shared
* with the "asynchronous" transaction support (control/bulk transfers).
* The only real difference is in how interrupt transfers are scheduled.
* We get some funky API restrictions from the current URB model, which
* works notably better for reading transfers than for writing. (And
* which accordingly needs to change before it'll work inside devices,
* or with "USB On The Go" additions to USB 2.0 ...)
*/
 
static int ehci_get_frame (struct usb_hcd *hcd);
 
/*-------------------------------------------------------------------------*/
 
/*
* periodic_next_shadow - return "next" pointer on shadow list
* @periodic: host pointer to qh/itd/sitd
* @tag: hardware tag for type of this record
*/
static union ehci_shadow *
periodic_next_shadow (union ehci_shadow *periodic, int tag)
{
switch (tag) {
case Q_TYPE_QH:
return &periodic->qh->qh_next;
case Q_TYPE_FSTN:
return &periodic->fstn->fstn_next;
case Q_TYPE_ITD:
return &periodic->itd->itd_next;
#ifdef have_split_iso
case Q_TYPE_SITD:
return &periodic->sitd->sitd_next;
#endif /* have_split_iso */
}
dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
// BUG ();
return 0;
}
 
/* returns true after successful unlink */
/* caller must hold ehci->lock */
static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
{
union ehci_shadow *prev_p = &ehci->pshadow [frame];
u32 *hw_p = &ehci->periodic [frame];
union ehci_shadow here = *prev_p;
union ehci_shadow *next_p;
 
/* find predecessor of "ptr"; hw and shadow lists are in sync */
while (here.ptr && here.ptr != ptr) {
prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
hw_p = &here.qh->hw_next;
here = *prev_p;
}
/* an interrupt entry (at list end) could have been shared */
if (!here.ptr) {
dbg ("entry %p no longer on frame [%d]", ptr, frame);
return 0;
}
// vdbg ("periodic unlink %p from frame %d", ptr, frame);
 
/* update hardware list ... HC may still know the old structure, so
* don't change hw_next until it'll have purged its cache
*/
next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
*hw_p = here.qh->hw_next;
 
/* unlink from shadow list; HCD won't see old structure again */
*prev_p = *next_p;
next_p->ptr = 0;
 
return 1;
}
 
/* how many of the uframe's 125 usecs are allocated? */
static unsigned short
periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
{
u32 *hw_p = &ehci->periodic [frame];
union ehci_shadow *q = &ehci->pshadow [frame];
unsigned usecs = 0;
 
while (q->ptr) {
switch (Q_NEXT_TYPE (*hw_p)) {
case Q_TYPE_QH:
/* is it in the S-mask? */
if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
usecs += q->qh->usecs;
/* ... or C-mask? */
if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
usecs += q->qh->c_usecs;
q = &q->qh->qh_next;
break;
case Q_TYPE_FSTN:
/* for "save place" FSTNs, count the relevant INTR
* bandwidth from the previous frame
*/
if (q->fstn->hw_prev != EHCI_LIST_END) {
dbg ("not counting FSTN bandwidth yet ...");
}
q = &q->fstn->fstn_next;
break;
case Q_TYPE_ITD:
/* NOTE the "one uframe per itd" policy */
if (q->itd->hw_transaction [uframe] != 0)
usecs += q->itd->usecs;
q = &q->itd->itd_next;
break;
#ifdef have_split_iso
case Q_TYPE_SITD:
temp = q->sitd->hw_fullspeed_ep &
__constant_cpu_to_le32 (1 << 31);
 
// FIXME: this doesn't count data bytes right...
 
/* is it in the S-mask? (count SPLIT, DATA) */
if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
if (temp)
usecs += HS_USECS (188);
else
usecs += HS_USECS (1);
}
 
/* ... C-mask? (count CSPLIT, DATA) */
if (q->sitd->hw_uframe &
cpu_to_le32 (1 << (8 + uframe))) {
if (temp)
usecs += HS_USECS (0);
else
usecs += HS_USECS (188);
}
q = &q->sitd->sitd_next;
break;
#endif /* have_split_iso */
default:
BUG ();
}
}
#ifdef DEBUG
if (usecs > 100)
err ("overallocated uframe %d, periodic is %d usecs",
frame * 8 + uframe, usecs);
#endif
return usecs;
}
 
/*-------------------------------------------------------------------------*/
 
static int enable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
int status;
 
/* did clearing PSE did take effect yet?
* takes effect only at frame boundaries...
*/
status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
ehci->hcd.state = USB_STATE_HALT;
return status;
}
 
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
ehci->hcd.state = USB_STATE_RUNNING;
 
/* make sure ehci_work scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
% (ehci->periodic_size << 3);
return 0;
}
 
static int disable_periodic (struct ehci_hcd *ehci)
{
u32 cmd;
int status;
 
/* did setting PSE not take effect yet?
* takes effect only at frame boundaries...
*/
status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
ehci->hcd.state = USB_STATE_HALT;
return status;
}
 
cmd = readl (&ehci->regs->command) & ~CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... */
 
ehci->next_uframe = -1;
return 0;
}
 
/*-------------------------------------------------------------------------*/
 
// FIXME microframe periods not yet handled
 
static void intr_deschedule (
struct ehci_hcd *ehci,
struct ehci_qh *qh,
int wait
) {
int status;
unsigned frame = qh->start;
 
do {
periodic_unlink (ehci, frame, qh);
qh_put (ehci, qh);
frame += qh->period;
} while (frame < ehci->periodic_size);
 
qh->qh_state = QH_STATE_UNLINK;
qh->qh_next.ptr = 0;
ehci->periodic_sched--;
 
/* maybe turn off periodic schedule */
if (!ehci->periodic_sched)
status = disable_periodic (ehci);
else {
status = 0;
vdbg ("periodic schedule still enabled");
}
 
/*
* If the hc may be looking at this qh, then delay a uframe
* (yeech!) to be sure it's done.
* No other threads may be mucking with this qh.
*/
if (((ehci_get_frame (&ehci->hcd) - frame) % qh->period) == 0) {
if (wait) {
udelay (125);
qh->hw_next = EHCI_LIST_END;
} else {
/* we may not be IDLE yet, but if the qh is empty
* the race is very short. then if qh also isn't
* rescheduled soon, it won't matter. otherwise...
*/
vdbg ("intr_deschedule...");
}
} else
qh->hw_next = EHCI_LIST_END;
 
qh->qh_state = QH_STATE_IDLE;
 
/* update per-qh bandwidth utilization (for usbfs) */
hcd_to_bus (&ehci->hcd)->bandwidth_allocated -=
(qh->usecs + qh->c_usecs) / qh->period;
 
dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d",
qh, qh->period, frame,
atomic_read (&qh->refcount), ehci->periodic_sched);
}
 
static int check_period (
struct ehci_hcd *ehci,
unsigned frame,
unsigned uframe,
unsigned period,
unsigned usecs
) {
/* complete split running into next frame?
* given FSTN support, we could sometimes check...
*/
if (uframe >= 8)
return 0;
 
/*
* 80% periodic == 100 usec/uframe available
* convert "usecs we need" to "max already claimed"
*/
usecs = 100 - usecs;
 
do {
int claimed;
 
// FIXME delete when intr_submit handles non-empty queues
// this gives us a one intr/frame limit (vs N/uframe)
// ... and also lets us avoid tracking split transactions
// that might collide at a given TT/hub.
if (ehci->pshadow [frame].ptr)
return 0;
 
claimed = periodic_usecs (ehci, frame, uframe);
if (claimed > usecs)
return 0;
 
// FIXME update to handle sub-frame periods
} while ((frame += period) < ehci->periodic_size);
 
// success!
return 1;
}
 
static int check_intr_schedule (
struct ehci_hcd *ehci,
unsigned frame,
unsigned uframe,
const struct ehci_qh *qh,
u32 *c_maskp
)
{
int retval = -ENOSPC;
 
if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
goto done;
if (!qh->c_usecs) {
retval = 0;
*c_maskp = cpu_to_le32 (0);
goto done;
}
 
/* This is a split transaction; check the bandwidth available for
* the completion too. Check both worst and best case gaps: worst
* case is SPLIT near uframe end, and CSPLIT near start ... best is
* vice versa. Difference can be almost two uframe times, but we
* reserve unnecessary bandwidth (waste it) this way. (Actually
* even better cases exist, like immediate device NAK.)
*
* FIXME don't even bother unless we know this TT is idle in that
* range of uframes ... for now, check_period() allows only one
* interrupt transfer per frame, so needn't check "TT busy" status
* when scheduling a split (QH, SITD, or FSTN).
*
* FIXME ehci 0.96 and above can use FSTNs
*/
if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
qh->period, qh->c_usecs))
goto done;
if (!check_period (ehci, frame, uframe + qh->gap_uf,
qh->period, qh->c_usecs))
goto done;
 
*c_maskp = cpu_to_le32 (0x03 << (8 + uframe + qh->gap_uf));
retval = 0;
done:
return retval;
}
 
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
int status;
unsigned uframe;
u32 c_mask;
unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
 
qh->hw_next = EHCI_LIST_END;
frame = qh->start;
 
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
uframe = ffs (le32_to_cpup (&qh->hw_info2) & 0x00ff);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
uframe = 0;
c_mask = 0;
status = -ENOSPC;
}
 
/* else scan the schedule to find a group of slots such that all
* uframes have enough periodic bandwidth available.
*/
if (status) {
frame = qh->period - 1;
do {
for (uframe = 0; uframe < 8; uframe++) {
status = check_intr_schedule (ehci,
frame, uframe, qh,
&c_mask);
if (status == 0)
break;
}
} while (status && frame--);
if (status)
goto done;
qh->start = frame;
 
/* reset S-frame and (maybe) C-frame masks */
qh->hw_info2 &= ~0xffff;
qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
} else
dbg ("reused previous qh %p schedule", qh);
 
/* stuff into the periodic schedule */
qh->qh_state = QH_STATE_LINKED;
dbg ("scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)",
qh, qh->usecs, qh->c_usecs,
qh->period, frame, uframe, qh->gap_uf);
do {
if (unlikely (ehci->pshadow [frame].ptr != 0)) {
 
// FIXME -- just link toward the end, before any qh with a shorter period,
// AND accommodate it already having been linked here (after some other qh)
// AS WELL AS updating the schedule checking logic
 
BUG ();
} else {
ehci->pshadow [frame].qh = qh_get (qh);
ehci->periodic [frame] =
QH_NEXT (qh->qh_dma);
}
wmb ();
frame += qh->period;
} while (frame < ehci->periodic_size);
 
/* update per-qh bandwidth for usbfs */
hcd_to_bus (&ehci->hcd)->bandwidth_allocated +=
(qh->usecs + qh->c_usecs) / qh->period;
 
/* maybe enable periodic schedule processing */
if (!ehci->periodic_sched++)
status = enable_periodic (ehci);
done:
return status;
}
 
static int intr_submit (
struct ehci_hcd *ehci,
struct urb *urb,
struct list_head *qtd_list,
int mem_flags
) {
unsigned epnum;
unsigned long flags;
struct ehci_qh *qh;
struct hcd_dev *dev;
int is_input;
int status = 0;
struct list_head empty;
 
/* get endpoint and transfer/schedule data */
epnum = usb_pipeendpoint (urb->pipe);
is_input = usb_pipein (urb->pipe);
if (is_input)
epnum |= 0x10;
 
spin_lock_irqsave (&ehci->lock, flags);
dev = (struct hcd_dev *)urb->dev->hcpriv;
 
/* get qh and force any scheduling errors */
INIT_LIST_HEAD (&empty);
qh = qh_append_tds (ehci, urb, &empty, epnum, &dev->ep [epnum]);
if (qh == 0) {
status = -ENOMEM;
goto done;
}
if (qh->qh_state == QH_STATE_IDLE) {
if ((status = qh_schedule (ehci, qh)) != 0)
goto done;
}
 
/* then queue the urb's tds to the qh */
qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
BUG_ON (qh == 0);
 
/* ... update usbfs periodic stats */
hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++;
 
done:
spin_unlock_irqrestore (&ehci->lock, flags);
if (status)
qtd_list_free (ehci, urb, qtd_list);
 
return status;
}
 
static unsigned
intr_complete (
struct ehci_hcd *ehci,
unsigned frame,
struct ehci_qh *qh,
struct pt_regs *regs
) {
unsigned count;
 
/* nothing to report? */
if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE))
!= 0))
return 0;
if (unlikely (list_empty (&qh->qtd_list))) {
dbg ("intr qh %p no TDs?", qh);
return 0;
}
/* handle any completions */
count = qh_completions (ehci, qh, regs);
 
if (unlikely (list_empty (&qh->qtd_list)))
intr_deschedule (ehci, qh, 0);
 
return count;
}
 
/*-------------------------------------------------------------------------*/
 
static void
itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
{
struct ehci_itd *first_itd = urb->hcpriv;
 
while (!list_empty (&first_itd->itd_list)) {
struct ehci_itd *itd;
 
itd = list_entry (
first_itd->itd_list.next,
struct ehci_itd, itd_list);
list_del (&itd->itd_list);
pci_pool_free (ehci->itd_pool, itd, itd->itd_dma);
}
pci_pool_free (ehci->itd_pool, first_itd, first_itd->itd_dma);
urb->hcpriv = 0;
}
 
static int
itd_fill (
struct ehci_hcd *ehci,
struct ehci_itd *itd,
struct urb *urb,
unsigned index, // urb->iso_frame_desc [index]
dma_addr_t dma // mapped transfer buffer
) {
u64 temp;
u32 buf1;
unsigned i, epnum, maxp, multi;
unsigned length;
int is_input;
 
itd->hw_next = EHCI_LIST_END;
itd->urb = urb;
itd->index = index;
 
/* tell itd about its transfer buffer, max 2 pages */
length = urb->iso_frame_desc [index].length;
dma += urb->iso_frame_desc [index].offset;
temp = dma & ~0x0fff;
for (i = 0; i < 2; i++) {
itd->hw_bufp [i] = cpu_to_le32 ((u32) temp);
itd->hw_bufp_hi [i] = cpu_to_le32 ((u32)(temp >> 32));
temp += 0x1000;
}
itd->buf_dma = dma;
 
/*
* this might be a "high bandwidth" highspeed endpoint,
* as encoded in the ep descriptor's maxpacket field
*/
epnum = usb_pipeendpoint (urb->pipe);
is_input = usb_pipein (urb->pipe);
if (is_input) {
maxp = urb->dev->epmaxpacketin [epnum];
buf1 = (1 << 11);
} else {
maxp = urb->dev->epmaxpacketout [epnum];
buf1 = 0;
}
buf1 |= (maxp & 0x03ff);
multi = 1;
multi += (maxp >> 11) & 0x03;
maxp &= 0x03ff;
maxp *= multi;
 
/* transfer can't fit in any uframe? */
if (length < 0 || maxp < length) {
dbg ("BAD iso packet: %d bytes, max %d, urb %p [%d] (of %d)",
length, maxp, urb, index,
urb->iso_frame_desc [index].length);
return -ENOSPC;
}
itd->usecs = usb_calc_bus_time (USB_SPEED_HIGH, is_input, 1, length);
 
/* "plus" info in low order bits of buffer pointers */
itd->hw_bufp [0] |= cpu_to_le32 ((epnum << 8) | urb->dev->devnum);
itd->hw_bufp [1] |= cpu_to_le32 (buf1);
itd->hw_bufp [2] |= cpu_to_le32 (multi);
 
/* figure hw_transaction[] value (it's scheduled later) */
itd->transaction = EHCI_ISOC_ACTIVE;
itd->transaction |= dma & 0x0fff; /* offset; buffer=0 */
if ((index + 1) == urb->number_of_packets)
itd->transaction |= EHCI_ITD_IOC; /* end-of-urb irq */
itd->transaction |= length << 16;
cpu_to_le32s (&itd->transaction);
 
return 0;
}
 
static int
itd_urb_transaction (
struct ehci_hcd *ehci,
struct urb *urb,
int mem_flags
) {
int frame_index;
struct ehci_itd *first_itd, *itd;
int status;
dma_addr_t itd_dma;
 
/* allocate/init ITDs */
for (frame_index = 0, first_itd = 0;
frame_index < urb->number_of_packets;
frame_index++) {
itd = pci_pool_alloc_usb (ehci->itd_pool, mem_flags, &itd_dma);
if (!itd) {
status = -ENOMEM;
goto fail;
}
memset (itd, 0, sizeof *itd);
itd->itd_dma = itd_dma;
 
status = itd_fill (ehci, itd, urb, frame_index,
urb->transfer_dma);
if (status != 0)
goto fail;
 
if (first_itd)
list_add_tail (&itd->itd_list,
&first_itd->itd_list);
else {
INIT_LIST_HEAD (&itd->itd_list);
urb->hcpriv = first_itd = itd;
}
}
urb->error_count = 0;
return 0;
 
fail:
if (urb->hcpriv)
itd_free_list (ehci, urb);
return status;
}
 
/*-------------------------------------------------------------------------*/
 
static inline void
itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
{
/* always prepend ITD/SITD ... only QH tree is order-sensitive */
itd->itd_next = ehci->pshadow [frame];
itd->hw_next = ehci->periodic [frame];
ehci->pshadow [frame].itd = itd;
ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
}
 
/*
* return zero on success, else -errno
* - start holds first uframe to start scheduling into
* - max is the first uframe it's NOT (!) OK to start scheduling into
* math to be done modulo "mod" (ehci->periodic_size << 3)
*/
static int get_iso_range (
struct ehci_hcd *ehci,
struct urb *urb,
unsigned *start,
unsigned *max,
unsigned mod
) {
struct list_head *lh;
struct hcd_dev *dev = urb->dev->hcpriv;
int last = -1;
unsigned now, span, end;
 
span = urb->interval * urb->number_of_packets;
 
/* first see if we know when the next transfer SHOULD happen */
list_for_each (lh, &dev->urb_list) {
struct urb *u;
struct ehci_itd *itd;
unsigned s;
 
u = list_entry (lh, struct urb, urb_list);
if (u == urb || u->pipe != urb->pipe)
continue;
if (u->interval != urb->interval) { /* must not change! */
dbg ("urb %p interval %d ... != %p interval %d",
u, u->interval, urb, urb->interval);
return -EINVAL;
}
/* URB for this endpoint... covers through when? */
itd = urb->hcpriv;
s = itd->uframe + u->interval * u->number_of_packets;
if (last < 0)
last = s;
else {
/*
* So far we can only queue two ISO URBs...
*
* FIXME do interval math, figure out whether
* this URB is "before" or not ... also, handle
* the case where the URB might have completed,
* but hasn't yet been processed.
*/
dbg ("NYET: queue >2 URBs per ISO endpoint");
return -EDOM;
}
}
 
/* calculate the legal range [start,max) */
now = readl (&ehci->regs->frame_index) + 1; /* next uframe */
if (!ehci->periodic_sched)
now += 8; /* startup delay */
now %= mod;
end = now + mod;
if (last < 0) {
*start = now + ehci->i_thresh + /* paranoia */ 1;
*max = end - span;
if (*max < *start + 1)
*max = *start + 1;
} else {
*start = last % mod;
*max = (last + 1) % mod;
}
 
/* explicit start frame? */
if (!(urb->transfer_flags & URB_ISO_ASAP)) {
unsigned temp;
 
/* sanity check: must be in range */
urb->start_frame %= ehci->periodic_size;
temp = urb->start_frame << 3;
if (temp < *start)
temp += mod;
if (temp > *max)
return -EDOM;
 
/* use that explicit start frame */
*start = urb->start_frame << 3;
temp += 8;
if (temp < *max)
*max = temp;
}
 
// FIXME minimize wraparound to "now" ... insist max+span
// (and start+span) remains a few frames short of "end"
 
*max %= ehci->periodic_size;
if ((*start + span) < end)
return 0;
return -EFBIG;
}
 
static int
itd_schedule (struct ehci_hcd *ehci, struct urb *urb)
{
unsigned start, max, i;
int status;
unsigned mod = ehci->periodic_size << 3;
 
for (i = 0; i < urb->number_of_packets; i++) {
urb->iso_frame_desc [i].status = -EINPROGRESS;
urb->iso_frame_desc [i].actual_length = 0;
}
 
if ((status = get_iso_range (ehci, urb, &start, &max, mod)) != 0)
return status;
 
do {
unsigned uframe;
unsigned usecs;
struct ehci_itd *itd;
 
/* check schedule: enough space? */
itd = urb->hcpriv;
uframe = start;
for (i = 0, uframe = start;
i < urb->number_of_packets;
i++, uframe += urb->interval) {
uframe %= mod;
 
/* can't commit more than 80% periodic == 100 usec */
if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
> (100 - itd->usecs)) {
itd = 0;
break;
}
itd = list_entry (itd->itd_list.next,
struct ehci_itd, itd_list);
}
if (!itd)
continue;
/* that's where we'll schedule this! */
itd = urb->hcpriv;
urb->start_frame = start >> 3;
vdbg ("ISO urb %p (%d packets period %d) starting %d.%d",
urb, urb->number_of_packets, urb->interval,
urb->start_frame, start & 0x7);
for (i = 0, uframe = start, usecs = 0;
i < urb->number_of_packets;
i++, uframe += urb->interval) {
uframe %= mod;
 
itd->uframe = uframe;
itd->hw_transaction [uframe & 0x07] = itd->transaction;
itd_link (ehci, (uframe >> 3) % ehci->periodic_size,
itd);
wmb ();
usecs += itd->usecs;
 
itd = list_entry (itd->itd_list.next,
struct ehci_itd, itd_list);
}
 
/* update bandwidth utilization records (for usbfs)
*
* FIXME This claims each URB queued to an endpoint, as if
* transfers were concurrent, not sequential. So bandwidth
* typically gets double-billed ... comes from tying it to
* URBs rather than endpoints in the schedule. Luckily we
* don't use this usbfs data for serious decision making.
*/
usecs /= urb->number_of_packets;
usecs /= urb->interval;
usecs >>= 3;
if (usecs < 1)
usecs = 1;
usb_claim_bandwidth (urb->dev, urb, usecs, 1);
 
/* maybe enable periodic schedule processing */
if (!ehci->periodic_sched++) {
if ((status = enable_periodic (ehci)) != 0) {
// FIXME deschedule right away
err ("itd_schedule, enable = %d", status);
}
}
 
return 0;
 
} while ((start = ++start % mod) != max);
 
/* no room in the schedule */
dbg ("urb %p, CAN'T SCHEDULE", urb);
return -ENOSPC;
}
 
/*-------------------------------------------------------------------------*/
 
#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR)
 
static unsigned
itd_complete (
struct ehci_hcd *ehci,
struct ehci_itd *itd,
unsigned uframe,
struct pt_regs *regs
) {
struct urb *urb = itd->urb;
struct usb_iso_packet_descriptor *desc;
u32 t;
 
/* update status for this uframe's transfers */
desc = &urb->iso_frame_desc [itd->index];
 
t = itd->hw_transaction [uframe];
itd->hw_transaction [uframe] = 0;
if (t & EHCI_ISOC_ACTIVE)
desc->status = -EXDEV;
else if (t & ISO_ERRS) {
urb->error_count++;
if (t & EHCI_ISOC_BUF_ERR)
desc->status = usb_pipein (urb->pipe)
? -ENOSR /* couldn't read */
: -ECOMM; /* couldn't write */
else if (t & EHCI_ISOC_BABBLE)
desc->status = -EOVERFLOW;
else /* (t & EHCI_ISOC_XACTERR) */
desc->status = -EPROTO;
 
/* HC need not update length with this error */
if (!(t & EHCI_ISOC_BABBLE))
desc->actual_length += EHCI_ITD_LENGTH (t);
} else {
desc->status = 0;
desc->actual_length += EHCI_ITD_LENGTH (t);
}
 
vdbg ("itd %p urb %p packet %d/%d trans %x status %d len %d",
itd, urb, itd->index + 1, urb->number_of_packets,
t, desc->status, desc->actual_length);
 
/* handle completion now? */
if ((itd->index + 1) != urb->number_of_packets)
return 0;
 
/*
* Always give the urb back to the driver ... expect it to submit
* a new urb (or resubmit this), and to have another already queued
* when un-interrupted transfers are needed.
*
* NOTE that for now we don't accelerate ISO unlinks; they just
* happen according to the current schedule. Means a delay of
* up to about a second (max).
*/
itd_free_list (ehci, urb);
if (urb->status == -EINPROGRESS)
urb->status = 0;
 
/* complete() can reenter this HCD */
spin_unlock (&ehci->lock);
usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
spin_lock (&ehci->lock);
 
/* defer stopping schedule; completion can submit */
ehci->periodic_sched--;
if (!ehci->periodic_sched)
(void) disable_periodic (ehci);
 
return 1;
}
 
/*-------------------------------------------------------------------------*/
 
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
{
int status;
unsigned long flags;
 
dbg ("itd_submit urb %p", urb);
 
/* allocate ITDs w/o locking anything */
status = itd_urb_transaction (ehci, urb, mem_flags);
if (status < 0)
return status;
 
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
status = itd_schedule (ehci, urb);
spin_unlock_irqrestore (&ehci->lock, flags);
if (status < 0)
itd_free_list (ehci, urb);
 
return status;
}
 
#ifdef have_split_iso
 
/*-------------------------------------------------------------------------*/
 
/*
* "Split ISO TDs" ... used for USB 1.1 devices going through
* the TTs in USB 2.0 hubs.
*
* FIXME not yet implemented
*/
 
#endif /* have_split_iso */
 
/*-------------------------------------------------------------------------*/
 
static void
scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
{
unsigned frame, clock, now_uframe, mod;
unsigned count = 0;
 
mod = ehci->periodic_size << 3;
 
/*
* When running, scan from last scan point up to "now"
* else clean up by scanning everything that's left.
* Touches as few pages as possible: cache-friendly.
* Don't scan ISO entries more than once, though.
*/
frame = ehci->next_uframe >> 3;
if (HCD_IS_RUNNING (ehci->hcd.state))
now_uframe = readl (&ehci->regs->frame_index);
else
now_uframe = (frame << 3) - 1;
now_uframe %= mod;
clock = now_uframe >> 3;
 
for (;;) {
union ehci_shadow q, *q_p;
u32 type, *hw_p;
unsigned uframes;
 
restart:
/* scan schedule to _before_ current frame index */
if (frame == clock)
uframes = now_uframe & 0x07;
else
uframes = 8;
 
q_p = &ehci->pshadow [frame];
hw_p = &ehci->periodic [frame];
q.ptr = q_p->ptr;
type = Q_NEXT_TYPE (*hw_p);
 
/* scan each element in frame's queue for completions */
while (q.ptr != 0) {
int last;
unsigned uf;
union ehci_shadow temp;
 
switch (type) {
case Q_TYPE_QH:
last = (q.qh->hw_next == EHCI_LIST_END);
temp = q.qh->qh_next;
type = Q_NEXT_TYPE (q.qh->hw_next);
count += intr_complete (ehci, frame,
qh_get (q.qh), regs);
qh_put (ehci, q.qh);
q = temp;
break;
case Q_TYPE_FSTN:
last = (q.fstn->hw_next == EHCI_LIST_END);
/* for "save place" FSTNs, look at QH entries
* in the previous frame for completions.
*/
if (q.fstn->hw_prev != EHCI_LIST_END) {
dbg ("ignoring completions from FSTNs");
}
type = Q_NEXT_TYPE (q.fstn->hw_next);
q = q.fstn->fstn_next;
break;
case Q_TYPE_ITD:
last = (q.itd->hw_next == EHCI_LIST_END);
 
/* Unlink each (S)ITD we see, since the ISO
* URB model forces constant rescheduling.
* That complicates sharing uframes in ITDs,
* and means we need to skip uframes the HC
* hasn't yet processed.
*/
for (uf = 0; uf < uframes; uf++) {
if (q.itd->hw_transaction [uf] != 0) {
temp = q;
*q_p = q.itd->itd_next;
*hw_p = q.itd->hw_next;
type = Q_NEXT_TYPE (*hw_p);
 
/* might free q.itd ... */
count += itd_complete (ehci,
temp.itd, uf, regs);
break;
}
}
/* we might skip this ITD's uframe ... */
if (uf == uframes) {
q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next;
type = Q_NEXT_TYPE (q.itd->hw_next);
}
 
q = *q_p;
break;
#ifdef have_split_iso
case Q_TYPE_SITD:
last = (q.sitd->hw_next == EHCI_LIST_END);
sitd_complete (ehci, q.sitd);
type = Q_NEXT_TYPE (q.sitd->hw_next);
 
// FIXME unlink SITD after split completes
q = q.sitd->sitd_next;
break;
#endif /* have_split_iso */
default:
dbg ("corrupt type %d frame %d shadow %p",
type, frame, q.ptr);
// BUG ();
last = 1;
q.ptr = 0;
}
 
/* did completion remove an interior q entry? */
if (unlikely (q.ptr == 0 && !last))
goto restart;
}
 
/* stop when we catch up to the HC */
 
// FIXME: this assumes we won't get lapped when
// latencies climb; that should be rare, but...
// detect it, and just go all the way around.
// FLR might help detect this case, so long as latencies
// don't exceed periodic_size msec (default 1.024 sec).
 
// FIXME: likewise assumes HC doesn't halt mid-scan
 
if (frame == clock) {
unsigned now;
 
if (!HCD_IS_RUNNING (ehci->hcd.state))
break;
ehci->next_uframe = now_uframe;
now = readl (&ehci->regs->frame_index) % mod;
if (now_uframe == now)
break;
 
/* rescan the rest of this frame, then ... */
now_uframe = now;
clock = now_uframe >> 3;
} else
frame = (frame + 1) % ehci->periodic_size;
}
}