On Mon, 24 Jun 2013, Ming Lei wrote:

> This patch implements the mechanism of giveback of URB in
> tasklet context, so that hardware interrupt handling time for
> usb host controller can be saved much, and HCD interrupt handling
> can be simplified.

Changes from v1 to v2?


> +static void usb_giveback_urb_bh(unsigned long param)
> +{
> +     struct giveback_urb_bh *bh = (struct giveback_urb_bh *)param;
> +     unsigned long flags;
> +     struct list_head local_list;
> +
> +     spin_lock_irqsave(&bh->lock, flags);
> +     bh->running = 1;
> + restart:
> +     list_replace_init(&bh->head, &local_list);
> +     spin_unlock_irqrestore(&bh->lock, flags);

Tasklet routines are always called with interrupts enabled, right?  
Therefore you don't need to use the "flags" argument here or below.

> @@ -1667,25 +1721,40 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
>   */
>  void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
>  {
> -     urb->hcpriv = NULL;
> -     if (unlikely(urb->unlinked))
> -             status = urb->unlinked;
> -     else if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
> -                     urb->actual_length < urb->transfer_buffer_length &&
> -                     !status))
> -             status = -EREMOTEIO;
> +     struct giveback_urb_bh *bh;
> +     bool sched, high_prio_bh;
>  
> -     unmap_urb_for_dma(hcd, urb);
> -     usbmon_urb_complete(&hcd->self, urb, status);
> -     usb_unanchor_urb(urb);
> +     /* pass status to tasklet via unlinked */
> +     if (likely(!urb->unlinked))
> +             urb->unlinked = status;
>  
> -     /* pass ownership to the completion handler */
> -     urb->status = status;
> -     urb->complete (urb);
> -     atomic_dec (&urb->use_count);
> -     if (unlikely(atomic_read(&urb->reject)))
> -             wake_up (&usb_kill_urb_queue);
> -     usb_put_urb (urb);
> +     if (!hcd_giveback_urb_in_bh(hcd) && !is_root_hub(urb->dev)) {
> +             __usb_hcd_giveback_urb(urb);
> +             return;
> +     }
> +
> +     if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe)) {
> +             bh = &hcd->high_prio_bh;
> +             high_prio_bh = 1;
> +     } else {
> +             bh = &hcd->low_prio_bh;
> +             high_prio_bh = 0;
> +     }

Bool values should be assigned "true" or "false", not "1" or "0".

> +
> +     spin_lock(&bh->lock);
> +     list_add_tail(&urb->urb_list, &bh->head);
> +     if (bh->running)
> +             sched = 0;
> +     else
> +             sched = 1;
> +     spin_unlock(&bh->lock);

How about calling this variable "running" instead of "sched"?  Then you 
could just say:

        running = bh->running;

with no "if" statement.

> +
> +     if (!sched)
> +             ;
> +     else if (high_prio_bh)
> +             tasklet_hi_schedule(&bh->bh);
> +     else
> +             tasklet_schedule(&bh->bh);
>  }
>  EXPORT_SYMBOL_GPL(usb_hcd_giveback_urb);
>  
> @@ -2307,6 +2376,42 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
>  
>  /*-------------------------------------------------------------------------*/
>  
> +static void __init_giveback_urb_bh(struct giveback_urb_bh *bh)
> +{
> +
> +     spin_lock_init(&bh->lock);
> +     INIT_LIST_HEAD(&bh->head);
> +     tasklet_init(&bh->bh, usb_giveback_urb_bh, (unsigned long)bh);
> +}
> +
> +static void init_giveback_urb_bh(struct usb_hcd *hcd)
> +{
> +     if (!hcd_giveback_urb_in_bh(hcd))
> +             return;

As you mentioned, there's not much point in skipping this code when
it's not needed.  In fact, you could just put the two lines below
directly into usb_create_shared_hcd(), and get rid of the "__" from the
beginning of the name.

> +
> +     __init_giveback_urb_bh(&hcd->high_prio_bh);
> +     __init_giveback_urb_bh(&hcd->low_prio_bh);
> +}
> +
> +static void exit_giveback_urb_bh(struct usb_hcd *hcd)
> +{
> +     if (!hcd_giveback_urb_in_bh(hcd))
> +             return;
> +
> +     /*
> +      * tasklet_kill() isn't needed here because:
> +      * - driver's disconnec() called from usb_disconnect() should

Misspelled "disconnect".

> +      *   make sure its URBs are completed during the disconnect()
> +      *   callback
> +      *
> +      * - it is too late to run complete() here since driver may have
> +      *   been removed already now
> +      *
> +      * Using tasklet to run URB's complete() doesn't change this
> +      * behavior of usbcore.
> +      */
> +}

Why have a separate subroutine for doing nothing?  Simply put this 
comment directly into usb_remove_hcd().  (And you can remove the last 
two lines of the comment; they don't make sense in this context.)

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to