Skip to content

Commit

Permalink
musb_host: simplify check for active URB
Browse files Browse the repository at this point in the history
The existance of the scheduling list shouldn't matter in
determining whether there's currectly an URB executing on a
hardware endpoint. What should actually matter is the 'in_qh'
or 'out_qh' fields of the 'struct musb_hw_ep' -- those are
set in musb_start_urb() and cleared in musb_giveback() when
the endpoint's URB list drains. Hence we should be able to
replace the big *switch* statements in musb_urb_dequeue()
and musb_h_disable() with mere musb_ep_get_qh() calls...

While at it, do some more changes:

 - add 'is_in' variable to musb_urb_dequeue();

 - remove the unnecessary 'epnum' variable from musb_h_disable();

 - fix the comment style in the vicinity.

This is a minor shrink of source and object code.

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Sergei Shtylyov authored and Greg Kroah-Hartman committed Jun 16, 2009
1 parent 3e5c6dc commit 22a0d6f
Showing 1 changed file with 14 additions and 58 deletions.
72 changes: 14 additions & 58 deletions drivers/usb/musb/musb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -2089,14 +2089,14 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
struct musb *musb = hcd_to_musb(hcd);
struct musb_qh *qh;
struct list_head *sched;
unsigned long flags;
int is_in = usb_pipein(urb->pipe);
int ret;

DBG(4, "urb=%p, dev%d ep%d%s\n", urb,
usb_pipedevice(urb->pipe),
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out");
is_in ? "in" : "out");

spin_lock_irqsave(&musb->lock, flags);
ret = usb_hcd_check_unlink_urb(hcd, urb, status);
Expand All @@ -2107,45 +2107,23 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
if (!qh)
goto done;

/* Any URB not actively programmed into endpoint hardware can be
/*
* Any URB not actively programmed into endpoint hardware can be
* immediately given back; that's any URB not at the head of an
* endpoint queue, unless someday we get real DMA queues. And even
* if it's at the head, it might not be known to the hardware...
*
* Otherwise abort current transfer, pending dma, etc.; urb->status
* Otherwise abort current transfer, pending DMA, etc.; urb->status
* has already been updated. This is a synchronous abort; it'd be
* OK to hold off until after some IRQ, though.
*
* NOTE: qh is invalid unless !list_empty(&hep->urb_list)
*/
if (!qh->is_ready || urb->urb_list.prev != &qh->hep->urb_list)
ret = -EINPROGRESS;
else {
switch (qh->type) {
case USB_ENDPOINT_XFER_CONTROL:
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
if (qh->mux == 1) {
if (usb_pipein(urb->pipe))
sched = &musb->in_bulk;
else
sched = &musb->out_bulk;
break;
}
default:
/* REVISIT when we get a schedule tree, periodic
* transfers won't always be at the head of a
* singleton queue...
*/
sched = NULL;
break;
}
}

/* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
if (ret < 0 || (sched && qh != first_qh(sched))) {
if (!qh->is_ready
|| urb->urb_list.prev != &qh->hep->urb_list
|| musb_ep_get_qh(qh->hw_ep, is_in) != qh) {
int ready = qh->is_ready;

ret = 0;
qh->is_ready = 0;
__musb_giveback(musb, urb, 0);
qh->is_ready = ready;
Expand All @@ -2169,45 +2147,23 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
static void
musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
{
u8 epnum = hep->desc.bEndpointAddress;
u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN;
unsigned long flags;
struct musb *musb = hcd_to_musb(hcd);
u8 is_in = epnum & USB_DIR_IN;
struct musb_qh *qh;
struct urb *urb;
struct list_head *sched;

spin_lock_irqsave(&musb->lock, flags);

qh = hep->hcpriv;
if (qh == NULL)
goto exit;

switch (qh->type) {
case USB_ENDPOINT_XFER_CONTROL:
sched = &musb->control;
break;
case USB_ENDPOINT_XFER_BULK:
if (qh->mux == 1) {
if (is_in)
sched = &musb->in_bulk;
else
sched = &musb->out_bulk;
break;
}
default:
/* REVISIT when we get a schedule tree, periodic transfers
* won't always be at the head of a singleton queue...
*/
sched = NULL;
break;
}

/* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
/* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */

/* kick first urb off the hardware, if needed */
/* Kick the first URB off the hardware, if needed */
qh->is_ready = 0;
if (!sched || qh == first_qh(sched)) {
if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) {
urb = next_urb(qh);

/* make software (then hardware) stop ASAP */
Expand Down

0 comments on commit 22a0d6f

Please sign in to comment.