X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fehci-sched.c;h=3cdfb95c3800774431d2c9a032e47abc114391e9;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=0000c460850ba48c7dcfc2cd0d5919713b8115be;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 0000c4608..3cdfb95c3 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 by David Brownell + * Copyright (c) 2001-2004 by David Brownell * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers * * This program is free software; you can redistribute it and/or modify it @@ -59,39 +59,28 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag) } } -/* returns true after successful unlink */ /* caller must hold ehci->lock */ -static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) +static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) { union ehci_shadow *prev_p = &ehci->pshadow [frame]; __le32 *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; + hw_p = here.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); + if (!here.ptr) + return; - /* update hardware list ... HC may still know the old structure, so - * don't change hw_next until it'll have purged its cache + /* update shadow and hardware lists ... the old "next" pointers + * from ptr may still be in use, the caller updates them. */ - 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 = NULL; - - return 1; + *prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p)); + *hw_p = *here.hw_next; } /* how many of the uframe's 125 usecs are allocated? */ @@ -114,7 +103,8 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) hw_p = &q->qh->hw_next; q = &q->qh->qh_next; break; - case Q_TYPE_FSTN: + // case Q_TYPE_FSTN: + default: /* for "save place" FSTNs, count the relevant INTR * bandwidth from the previous frame */ @@ -149,13 +139,11 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) hw_p = &q->sitd->hw_next; q = &q->sitd->sitd_next; break; - default: - BUG (); } } #ifdef DEBUG if (usecs > 100) - err ("overallocated uframe %d, periodic is %d usecs", + ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", frame * 8 + uframe, usecs); #endif return usecs; @@ -261,14 +249,14 @@ static int enable_periodic (struct ehci_hcd *ehci) */ status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); if (status != 0) { - ehci->hcd.state = USB_STATE_HALT; + ehci_to_hcd(ehci)->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; + ehci_to_hcd(ehci)->state = USB_STATE_RUNNING; /* make sure ehci_work scans these */ ehci->next_uframe = readl (&ehci->regs->frame_index) @@ -286,7 +274,7 @@ static int disable_periodic (struct ehci_hcd *ehci) */ status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); if (status != 0) { - ehci->hcd.state = USB_STATE_HALT; + ehci_to_hcd(ehci)->state = USB_STATE_HALT; return status; } @@ -300,64 +288,143 @@ static int disable_periodic (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ -// FIXME microframe periods not yet handled +/* periodic schedule slots have iso tds (normal or split) first, then a + * sparse tree for active interrupt transfers. + * + * this just links in a qh; caller guarantees uframe masks are set right. + * no FSTN support (yet; ehci 0.96+) + */ +static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + unsigned i; + unsigned period = qh->period; -static void intr_deschedule ( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - int wait -) { - int status; - unsigned frame = qh->start; + dev_dbg (&qh->dev->dev, + "link qh%d-%04x/%p start %d [%d/%d us]\n", + period, le32_to_cpup (&qh->hw_info2) & 0xffff, + qh, qh->start, qh->usecs, qh->c_usecs); - do { - periodic_unlink (ehci, frame, qh); - qh_put (qh); - frame += qh->period; - } while (frame < ehci->periodic_size); + /* high bandwidth, or otherwise every microframe */ + if (period == 0) + period = 1; + + for (i = qh->start; i < ehci->periodic_size; i += period) { + union ehci_shadow *prev = &ehci->pshadow [i]; + u32 *hw_p = &ehci->periodic [i]; + union ehci_shadow here = *prev; + u32 type = 0; + + /* skip the iso nodes at list head */ + while (here.ptr) { + type = Q_NEXT_TYPE (*hw_p); + if (type == Q_TYPE_QH) + break; + prev = periodic_next_shadow (prev, type); + hw_p = &here.qh->hw_next; + here = *prev; + } + + /* sorting each branch by period (slow-->fast) + * enables sharing interior tree nodes + */ + while (here.ptr && qh != here.qh) { + if (qh->period > here.qh->period) + break; + prev = &here.qh->qh_next; + hw_p = &here.qh->hw_next; + here = *prev; + } + /* link in this qh, unless some earlier pass did that */ + if (qh != here.qh) { + qh->qh_next = here; + if (here.qh) + qh->hw_next = *hw_p; + wmb (); + prev->qh = qh; + *hw_p = QH_NEXT (qh->qh_dma); + } + } + qh->qh_state = QH_STATE_LINKED; + qh_get (qh); + + /* update per-qh bandwidth for usbfs */ + ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + /* maybe enable periodic schedule processing */ + if (!ehci->periodic_sched++) + return enable_periodic (ehci); + + return 0; +} + +static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + unsigned i; + unsigned period; + + // FIXME: + // IF this isn't high speed + // and this qh is active in the current uframe + // (and overlay token SplitXstate is false?) + // THEN + // qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */); + + /* high bandwidth, or otherwise part of every microframe */ + if ((period = qh->period) == 0) + period = 1; + + for (i = qh->start; i < ehci->periodic_size; i += period) + periodic_unlink (ehci, i, qh); + + /* update per-qh bandwidth for usbfs */ + ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + + dev_dbg (&qh->dev->dev, + "unlink qh%d-%04x/%p start %d [%d/%d us]\n", + qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff, + qh, qh->start, qh->usecs, qh->c_usecs); + + /* qh->qh_next still "live" to HC */ qh->qh_state = QH_STATE_UNLINK; qh->qh_next.ptr = NULL; - ehci->periodic_sched--; + qh_put (qh); /* maybe turn off periodic schedule */ + ehci->periodic_sched--; if (!ehci->periodic_sched) - status = disable_periodic (ehci); - else { - status = 0; - vdbg ("periodic schedule still enabled"); - } + (void) disable_periodic (ehci); +} - /* - * 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; +static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) +{ + unsigned wait; - qh->qh_state = QH_STATE_IDLE; + qh_unlink_periodic (ehci, qh); - /* update per-qh bandwidth utilization (for usbfs) */ - hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= - (qh->usecs + qh->c_usecs) / qh->period; + /* simple/paranoid: always delay, expecting the HC needs to read + * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and + * expect khubd to clean up after any CSPLITs we won't issue. + * active high speed queues may need bigger delays... + */ + if (list_empty (&qh->qtd_list) + || (__constant_cpu_to_le32 (0x0ff << 8) + & qh->hw_info2) != 0) + wait = 2; + else + wait = 55; /* worst case: 3 * 1024 */ - dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d", - qh, qh->period, frame, - atomic_read (&qh->kref.refcount), ehci->periodic_sched); + udelay (wait); + qh->qh_state = QH_STATE_IDLE; + qh->hw_next = EHCI_LIST_END; + wmb (); } +/*-------------------------------------------------------------------------*/ + static int check_period ( struct ehci_hcd *ehci, unsigned frame, @@ -365,6 +432,8 @@ static int check_period ( unsigned period, unsigned usecs ) { + int claimed; + /* complete split running into next frame? * given FSTN support, we could sometimes check... */ @@ -377,22 +446,26 @@ static int check_period ( */ 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; + /* we "know" 2 and 4 uframe intervals were rejected; so + * for period 0, check _every_ microframe in the schedule. + */ + if (unlikely (period == 0)) { + do { + for (uframe = 0; uframe < 7; uframe++) { + claimed = periodic_usecs (ehci, frame, uframe); + if (claimed > usecs) + return 0; + } + } while ((frame += 1) < ehci->periodic_size); -// FIXME update to handle sub-frame periods - } while ((frame += period) < ehci->periodic_size); + /* just check the specified uframe, at that period */ + } else { + do { + claimed = periodic_usecs (ehci, frame, uframe); + if (claimed > usecs) + return 0; + } while ((frame += period) < ehci->periodic_size); + } // success! return 1; @@ -407,6 +480,10 @@ static int check_intr_schedule ( ) { int retval = -ENOSPC; + u8 mask; + + if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ + goto done; if (!check_period (ehci, frame, uframe, qh->period, qh->usecs)) goto done; @@ -416,33 +493,33 @@ static int check_intr_schedule ( 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 + /* Make sure this tt's buffer is also available for CSPLITs. + * We pessimize a bit; probably the typical full speed case + * doesn't need the second CSPLIT. + * + * NOTE: both SPLIT and CSPLIT could be checked in just + * one smart pass... */ - 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; + mask = 0x03 << (uframe + qh->gap_uf); + *c_maskp = cpu_to_le32 (mask << 8); - *c_maskp = cpu_to_le32 (0x03 << (8 + uframe + qh->gap_uf)); - retval = 0; + mask |= 1 << uframe; + if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) { + 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; + retval = 0; + } done: return retval; } +/* "first fit" scheduling policy used the first time through, + * or when the previous schedule slot can't be re-used. + */ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) { int status; @@ -450,6 +527,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) __le32 c_mask; unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + qh_refresh(ehci, qh); qh->hw_next = EHCI_LIST_END; frame = qh->start; @@ -468,61 +546,46 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) * 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--); + /* "normal" case, uframing flexible except with splits */ + if (qh->period) { + 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--); + + /* qh->period == 0 means every uframe */ + } else { + frame = 0; + status = check_intr_schedule (ehci, 0, 0, qh, &c_mask); + } if (status) goto done; qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff); - qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask; + qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff); + qh->hw_info2 |= qh->period + ? cpu_to_le32 (1 << uframe) + : __constant_cpu_to_le32 (0xff); + qh->hw_info2 |= c_mask; } else - dbg ("reused previous qh %p schedule", qh); + ehci_dbg (ehci, "reused qh %p schedule\n", 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); + status = qh_link_periodic (ehci, qh); done: return status; } static int intr_submit ( struct ehci_hcd *ehci, + struct usb_host_endpoint *ep, struct urb *urb, struct list_head *qtd_list, int mem_flags @@ -530,24 +593,18 @@ static int intr_submit ( 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; + epnum = ep->desc.bEndpointAddress; 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) { + qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); + if (qh == NULL) { status = -ENOMEM; goto done; } @@ -557,11 +614,11 @@ static int intr_submit ( } /* 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); + qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); + BUG_ON (qh == NULL); /* ... update usbfs periodic stats */ - hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++; + ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; done: spin_unlock_irqrestore (&ehci->lock, flags); @@ -581,7 +638,7 @@ iso_stream_alloc (int mem_flags) struct ehci_iso_stream *stream; stream = kmalloc(sizeof *stream, mem_flags); - if (likely (stream != 0)) { + if (likely (stream != NULL)) { memset (stream, 0, sizeof(*stream)); INIT_LIST_HEAD(&stream->td_list); INIT_LIST_HEAD(&stream->free_list); @@ -612,11 +669,10 @@ iso_stream_init ( */ epnum = usb_pipeendpoint (pipe); is_input = usb_pipein (pipe) ? USB_DIR_IN : 0; + maxp = usb_maxpacket(dev, pipe, !is_input); if (is_input) { - maxp = dev->epmaxpacketin [epnum]; buf1 = (1 << 11); } else { - maxp = dev->epmaxpacketout [epnum]; buf1 = 0; } @@ -688,7 +744,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) */ if (stream->refcount == 1) { int is_in; - struct hcd_dev *dev = stream->udev->hcpriv; // BUG_ON (!list_empty(&stream->td_list)); @@ -718,7 +773,7 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; stream->bEndpointAddress &= 0x0f; - dev->ep[is_in + stream->bEndpointAddress] = NULL; + stream->ep->hcpriv = NULL; if (stream->rescheduled) { ehci_info (ehci, "ep%d%s-iso rescheduled " @@ -736,7 +791,7 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) static inline struct ehci_iso_stream * iso_stream_get (struct ehci_iso_stream *stream) { - if (likely (stream != 0)) + if (likely (stream != NULL)) stream->refcount++; return stream; } @@ -745,24 +800,25 @@ static struct ehci_iso_stream * iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) { unsigned epnum; - struct hcd_dev *dev; struct ehci_iso_stream *stream; + struct usb_host_endpoint *ep; unsigned long flags; epnum = usb_pipeendpoint (urb->pipe); if (usb_pipein(urb->pipe)) - epnum += 0x10; + ep = urb->dev->ep_in[epnum]; + else + ep = urb->dev->ep_out[epnum]; spin_lock_irqsave (&ehci->lock, flags); + stream = ep->hcpriv; - dev = (struct hcd_dev *)urb->dev->hcpriv; - stream = dev->ep [epnum]; - - if (unlikely (stream == 0)) { + if (unlikely (stream == NULL)) { stream = iso_stream_alloc(GFP_ATOMIC); - if (likely (stream != 0)) { + if (likely (stream != NULL)) { /* dev->ep owns the initial refcount */ - dev->ep[epnum] = stream; + ep->hcpriv = stream; + stream->ep = ep; iso_stream_init(stream, urb->dev, urb->pipe, urb->interval); } @@ -770,8 +826,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) /* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */ } else if (unlikely (stream->hw_info1 != 0)) { ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", - urb->dev->devpath, epnum & 0x0f, - (epnum & 0x10) ? "in" : "out"); + urb->dev->devpath, epnum, + usb_pipein(urb->pipe) ? "in" : "out"); stream = NULL; } @@ -784,7 +840,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) /*-------------------------------------------------------------------------*/ -/* ehci_iso_sched ops can be shared, ITD-only, or SITD-only */ +/* ehci_iso_sched ops can be ITD-only or SITD-only */ static struct ehci_iso_sched * iso_sched_alloc (unsigned packets, int mem_flags) @@ -794,7 +850,7 @@ iso_sched_alloc (unsigned packets, int mem_flags) size += packets * sizeof (struct ehci_iso_packet); iso_sched = kmalloc (size, mem_flags); - if (likely (iso_sched != 0)) { + if (likely (iso_sched != NULL)) { memset(iso_sched, 0, size); INIT_LIST_HEAD (&iso_sched->td_list); } @@ -871,7 +927,7 @@ itd_urb_transaction ( unsigned long flags; sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (sched == 0)) + if (unlikely (sched == NULL)) return -ENOMEM; itd_sched_init (sched, stream, urb); @@ -905,8 +961,9 @@ itd_urb_transaction ( spin_lock_irqsave (&ehci->lock, flags); } - if (unlikely (0 == itd)) { + if (unlikely (NULL == itd)) { iso_sched_free (stream, sched); + spin_unlock_irqrestore (&ehci->lock, flags); return -ENOMEM; } memset (itd, 0, sizeof *itd); @@ -1201,7 +1258,7 @@ itd_link_urb ( next_uframe = stream->next_uframe % mod; if (unlikely (list_empty(&stream->td_list))) { - hcd_to_bus (&ehci->hcd)->bandwidth_allocated + ehci_to_hcd(ehci)->self.bandwidth_allocated += stream->bandwidth; ehci_vdbg (ehci, "schedule devp %s ep%d%s-iso period %d start %d.%d\n", @@ -1211,7 +1268,7 @@ itd_link_urb ( next_uframe >> 3, next_uframe & 0x7); stream->start = jiffies; } - hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++; + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill iTDs uframe by uframe */ for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) { @@ -1333,10 +1390,10 @@ itd_complete ( ehci->periodic_sched--; if (unlikely (!ehci->periodic_sched)) (void) disable_periodic (ehci); - hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--; + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (unlikely (list_empty (&stream->td_list))) { - hcd_to_bus (&ehci->hcd)->bandwidth_allocated + ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, "deschedule devp %s ep%d%s-iso\n", @@ -1359,7 +1416,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) /* Get iso_stream head */ stream = iso_stream_find (ehci, urb); - if (unlikely (stream == 0)) { + if (unlikely (stream == NULL)) { ehci_dbg (ehci, "can't get iso stream\n"); return -ENOMEM; } @@ -1473,7 +1530,7 @@ sitd_urb_transaction ( unsigned long flags; iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (iso_sched == 0) + if (iso_sched == NULL) return -ENOMEM; sitd_sched_init (iso_sched, stream, urb); @@ -1586,7 +1643,7 @@ sitd_link_urb ( if (list_empty(&stream->td_list)) { /* usbfs ignores TT bandwidth */ - hcd_to_bus (&ehci->hcd)->bandwidth_allocated + ehci_to_hcd(ehci)->self.bandwidth_allocated += stream->bandwidth; ehci_vdbg (ehci, "sched dev%s ep%d%s-iso [%d] %dms/%04x\n", @@ -1596,7 +1653,7 @@ sitd_link_urb ( stream->interval, le32_to_cpu (stream->splits)); stream->start = jiffies; } - hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++; + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; /* fill sITDs frame by frame */ for (packet = 0, sitd = NULL; @@ -1696,10 +1753,10 @@ sitd_complete ( ehci->periodic_sched--; if (!ehci->periodic_sched) (void) disable_periodic (ehci); - hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--; + ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (list_empty (&stream->td_list)) { - hcd_to_bus (&ehci->hcd)->bandwidth_allocated + ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, "deschedule devp %s ep%d%s-iso\n", @@ -1727,7 +1784,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) /* Get iso_stream head */ stream = iso_stream_find (ehci, urb); - if (stream == 0) { + if (stream == NULL) { ehci_dbg (ehci, "can't get iso stream\n"); return -ENOMEM; } @@ -1803,7 +1860,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs) * Touches as few pages as possible: cache-friendly. */ now_uframe = ehci->next_uframe; - if (HCD_IS_RUNNING (ehci->hcd.state)) + if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) clock = readl (&ehci->regs->frame_index); else clock = now_uframe + mod - 1; @@ -1832,10 +1889,12 @@ restart: type = Q_NEXT_TYPE (*hw_p); modified = 0; - while (q.ptr != 0) { + while (q.ptr != NULL) { unsigned uf; union ehci_shadow temp; + int live; + live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state); switch (type) { case Q_TYPE_QH: /* handle any completions */ @@ -1844,7 +1903,7 @@ restart: q = q.qh->qh_next; modified = qh_completions (ehci, temp.qh, regs); if (unlikely (list_empty (&temp.qh->qtd_list))) - intr_deschedule (ehci, temp.qh, 0); + intr_deschedule (ehci, temp.qh); qh_put (temp.qh); break; case Q_TYPE_FSTN: @@ -1860,7 +1919,7 @@ restart: case Q_TYPE_ITD: /* skip itds for later in the frame */ rmb (); - for (uf = uframes; uf < 8; uf++) { + for (uf = live ? uframes : 8; uf < 8; uf++) { if (0 == (q.itd->hw_transaction [uf] & ITD_ACTIVE)) continue; @@ -1884,7 +1943,8 @@ restart: q = *q_p; break; case Q_TYPE_SITD: - if (q.sitd->hw_results & SITD_ACTIVE) { + if ((q.sitd->hw_results & SITD_ACTIVE) + && live) { q_p = &q.sitd->sitd_next; hw_p = &q.sitd->hw_next; type = Q_NEXT_TYPE (q.sitd->hw_next); @@ -1923,7 +1983,7 @@ restart: if (now_uframe == clock) { unsigned now; - if (!HCD_IS_RUNNING (ehci->hcd.state)) + if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) break; ehci->next_uframe = now_uframe; now = readl (&ehci->regs->frame_index) % mod;