Technical content of this one seems fine, but there are lots of Documentation/CodingStyle issues level to resolve.
> patch 1: This patch slightly refactors isoch stream cleanup such that > stream state is more persistent; it is instantiated at first transfer > and not released until endpoint shutdown. This is to give isoch transfers > something persistent to associate with bandwidth budget reservations > later. Umm, and it also reworks ehci_endpoint_disable() for all endpoint types. Which I actually like, but it came as a big surprise given that comment. If I were nitpicky I'd ask you to split this in two; but I won't. :) I'm thinking what I'd rather see is a re-issue of this patch, rather than a separate patch to fix issues here. That way, what goes upstream will be appropriately clean/correct. See below for comments. - Dave > +#define EHCI_EP_QH(x) (((x)->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) > \ > + != USB_ENDPOINT_XFER_ISOC ? (x)->hcpriv : NULL) > +#define EHCI_EP_STREAM(x) (((x)->desc.bmAttributes & \ > + USB_ENDPOINT_XFERTYPE_MASK) == \ > + USB_ENDPOINT_XFER_ISOC ? (x)->hcpriv : NULL) Hmm, usb_endpoint_xfer_isoc(&x->desc) would look cleaner; I'm not entirely sure why those predicates aren't inlined. In this context I think you're probably right to insist on an inlined version, but I would actually rather see those as inline functions rather than macros. > + > +/*-------------------------------------------------------------------------*/ > + > #ifdef CONFIG_USB_EHCI_ROOT_HUB_TT > > /* > diff -rup a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c > --- a/drivers/usb/host/ehci-hcd.c 2006-09-27 20:07:29.000000000 -0400 > +++ b/drivers/usb/host/ehci-hcd.c 2006-09-27 20:59:41.000000000 -0400 > @@ -835,63 +835,80 @@ ehci_endpoint_disable (struct usb_hcd *h > struct ehci_hcd *ehci = hcd_to_ehci (hcd); > unsigned long flags; > struct ehci_qh *qh, *tmp; > + struct ehci_iso_stream *iso; > > /* ASSERT: any requests/urbs are being unlinked */ > /* ASSERT: nobody can be submitting urbs for this any more */ > > -rescan: > spin_lock_irqsave (&ehci->lock, flags); > - qh = ep->hcpriv; > - if (!qh) > - goto done; > + iso = EHCI_EP_STREAM(ep); > > - /* endpoints can be iso streams. for now, we don't > - * accelerate iso completions ... so spin a while. > - */ > - if (qh->hw_info1 == 0) { > - ehci_vdbg (ehci, "iso delay\n"); > - goto idle_timeout; > - } > + if (iso){ Use "if (iso) {" instead ... one espace before such brackets. > + /* for now, we don't accelerate iso completions ... so spin > + a while. */ > + "a while" is not as useful as "until the only reference is from udev->ep_*[]". Comment style should be /* just one line */ or /* line 1 * line 2..n-1 */ ... and you should never add end-of-line whitespace. > + while(iso->refcount>1){ Use "while () {" not "while(){" ... it's not a function call. In fact, while (iso->refcount > 1) { ... you're not including whitespace which you _should_ include, and (elsewhere) are adding whitespace you should not include. > + spin_unlock_irqrestore (&ehci->lock, flags); > + schedule_timeout_uninterruptible(1); > + spin_lock_irqsave (&ehci->lock, flags); > + } > > - if (!HC_IS_RUNNING (hcd->state)) > - qh->qh_state = QH_STATE_IDLE; > - switch (qh->qh_state) { > - case QH_STATE_LINKED: > - for (tmp = ehci->async->qh_next.qh; > - tmp && tmp != qh; > - tmp = tmp->qh_next.qh) > - continue; > - /* periodic qh self-unlinks on empty */ > - if (!tmp) > - goto nogood; > - unlink_async (ehci, qh); > - /* FALL THROUGH */ > - case QH_STATE_UNLINK: /* wait for hw to finish? */ > - case QH_STATE_UNLINK_WAIT: > -idle_timeout: > + /* we want to be sure completions deref the stream to 1, > + then we finally pull the plug here */ > + iso_stream_put(ehci,iso); > + ep->hcpriv = NULL; > spin_unlock_irqrestore (&ehci->lock, flags); > - schedule_timeout_uninterruptible(1); > - goto rescan; > - case QH_STATE_IDLE: /* fully unlinked */ > - if (list_empty (&qh->qtd_list)) { > - qh_put (qh); > + return; > + } > + > + while ( (qh = EHCI_EP_QH(ep)) ){ > + Please don't add end-of-line whitespace ... or blank lines right at the top of code blocks. Also while ((qh = ...) != NULL) { Your whitespace usage _really_ needs to obey standard kernel coding style. > + if (!HC_IS_RUNNING (hcd->state)) > + qh->qh_state = QH_STATE_IDLE; > + switch (qh->qh_state) { > + case QH_STATE_LINKED: > + for (tmp = ehci->async->qh_next.qh; > + tmp && tmp != qh; > + tmp = tmp->qh_next.qh) > + continue; > + > + /* periodic qh self-unlinks on empty */ > + if (!tmp) goto error; if (!tmp) goto error; ... as it was previously ... > + unlink_async (ehci, qh); > + /* FALL THROUGH */ > + > + case QH_STATE_UNLINK: /* wait for hw to finish? */ > + case QH_STATE_UNLINK_WAIT: > + No blank line there please > + spin_unlock_irqrestore (&ehci->lock, flags); > + schedule_timeout_uninterruptible(1); > + spin_lock_irqsave (&ehci->lock, flags); > break; > + > + case QH_STATE_IDLE: /* fully unlinked */ > + No blank line there please > + if (list_empty (&qh->qtd_list)) { > + qh_put (qh); > + ep->hcpriv = NULL; > + break; > + } > + /* else FALL THROUGH */ > + default: > + goto error; > } > - /* else FALL THROUGH */ > - default: > -nogood: > - /* caller was supposed to have unlinked any requests; > - * that's not our job. just leak this memory. > - */ > - ehci_err (ehci, "qh %p (#%02x) state %d%s\n", > - qh, ep->desc.bEndpointAddress, qh->qh_state, > - list_empty (&qh->qtd_list) ? "" : "(has tds)"); > - break; > } > - ep->hcpriv = NULL; > -done: > + > spin_unlock_irqrestore (&ehci->lock, flags); > return; > + > +error: > + /* caller was supposed to have unlinked any requests; > + * that's not our job. just leak this memory. > + */ > + ehci_err (ehci, "qh %p (#%02x) state %d%s\n", > + qh, ep->desc.bEndpointAddress, qh->qh_state, > + list_empty (&qh->qtd_list) ? "" : "(has tds)"); > + ep->hcpriv = NULL; > } > > static int ehci_get_frame (struct usb_hcd *hcd) > diff -rup a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c > --- a/drivers/usb/host/ehci-sched.c 2006-09-27 20:07:29.000000000 -0400 > +++ b/drivers/usb/host/ehci-sched.c 2006-09-27 20:59:41.000000000 -0400 > @@ -959,10 +959,14 @@ iso_stream_put(struct ehci_hcd *ehci, st > { > stream->refcount--; > > - /* free whenever just a dev->ep reference remains. > - * not like a QH -- no persistent state (toggle, halt) > - */ > - if (stream->refcount == 1) { > + /* don't free on last descriptor; free when endpoint disable > + finally releases last refcount. Although it is technically > + broken for an endpoint driver to submit its streaming > + descriptors such that a new one appears after the old one > + ends, it is only punishing the users to insist on breaking > + these drivers when it's not necessary to do so. This saves > + substantial overhead in that case.*/ The comment should be corrected, both for content and style. In this case I'd suggest /* if refcount == 1 this is just from udev->ep_{in,out}[]; * we can at least avoid reallocating this stream's memory, and * the previously budgeted bandwidth may still be available. */ > + if (stream->refcount == 0) { > int is_in; > > // BUG_ON (!list_empty(&stream->td_list)); > ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel