Re: [PATCH] usb: hcd: allow wakeups while suspended for Moorestown

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 7 Apr 2011 16:57:11 -0700
Greg KH <greg@xxxxxxxxx> wrote:

> On Thu, Apr 07, 2011 at 03:34:59PM -0700, Greg KH wrote:
> > On Thu, Apr 07, 2011 at 02:54:39PM -0700, Kristen Carlson Accardi wrote:
> > > On Thu, 7 Apr 2011 13:35:02 -0700
> > > Greg KH <greg@xxxxxxxxx> wrote:
> > > 
> > > > On Thu, Apr 07, 2011 at 09:56:54AM -0700, Kristen Carlson Accardi wrote:
> > > > > > Have you made timing/performance studies, comparing (for example) USB 
> > > > > > disk throughput with and without threaded interrupts?
> > > > > >
> > > > > 
> > > > > I could never do this with all the different types of hw.  I suggest
> > > > > that if you decide to move to a threaded irq you have a long period of
> > > > > testing time where people can determine whether or not it impacts
> > > > > performance on their own hw.  Just from googling I can see that tglx
> > > > > did some performance analysis, but you'd have to ask him what the
> > > > > findings were.
> > > > 
> > > > I asked him about this an hour ago, and he found that he got a
> > > > performance increase in USB throughput switching to threaded irqs,
> > > > especially for usb-storage devices.
> > > > 
> > > > So I'm all for it now, send me the patch and let's see what breaks :)
> > > > 
> > > > thanks,
> > > > 
> > > > greg k-h
> > > 
> > > I sent him an email to see if he'll submit the patches he's been
> > > testing with -- I figured it'd be better to use those since he's
> > > got time on them already.
> > 
> > Yes, it turns out that your patch will not work properly on some
> > hardware in the first place, so his changes are needed.  I see him
> > working on them right now in front of me in the conference meeting we
> > are currently sitting in...
> 
> Here's Thomas's first cut at doing this, totally untested and written
> during a legal track at the LF Collab summit.
> 
> Kristen, can you take this and test and see if it works for you?
> 
> thanks,
> 
> greg k-h
> 
> 
> Subject: usb.patch
> From: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> Date: Thu, 07 Apr 2011 23:35:16 +0200
> 
> Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> ---
>  drivers/usb/core/hcd.c      |   42 ++++++++++++++++++++----------------------
>  drivers/usb/host/ehci-hcd.c |   33 +++++++++++++++++++++++++++------
>  drivers/usb/host/ehci-pci.c |    1 +
>  include/linux/usb/hcd.h     |    1 +
>  4 files changed, 49 insertions(+), 28 deletions(-)
> 
> Index: linux-2.6/drivers/usb/core/hcd.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/core/hcd.c
> +++ linux-2.6/drivers/usb/core/hcd.c
> @@ -2111,34 +2111,36 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
>  irqreturn_t usb_hcd_irq (int irq, void *__hcd)
>  {
>  	struct usb_hcd		*hcd = __hcd;
> -	unsigned long		flags;
>  	irqreturn_t		rc;
>  
> -	/* IRQF_DISABLED doesn't work correctly with shared IRQs
> -	 * when the first handler doesn't use it.  So let's just
> -	 * assume it's never used.
> -	 */
> -	local_irq_save(flags);
> -
>  	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
>  		rc = IRQ_NONE;
> -	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
> -		rc = IRQ_NONE;
>  	} else {
> +		rc = hcd->driver->irq(hcd);
> +		if (rc == IRQ_NONE)
> +			return rc;
> +
>  		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
>  		if (hcd->shared_hcd)
>  			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
>  
>  		if (unlikely(hcd->state == HC_STATE_HALT))
>  			usb_hc_died(hcd);
> -		rc = IRQ_HANDLED;
>  	}
> -
> -	local_irq_restore(flags);
>  	return rc;
>  }
>  EXPORT_SYMBOL_GPL(usb_hcd_irq);
>  
> +irqreturn_t usb_hcd_thread_irq (int irq, void *__hcd)
> +{
> +	struct usb_hcd		*hcd = __hcd;
> +
> +	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
> +		return IRQ_NONE;
> +
> +	return hcd->driver->threaded_irq(hcd);
> +}
> +
>  /*-------------------------------------------------------------------------*/
>  
>  /**
> @@ -2189,7 +2191,7 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
>  /**
>   * usb_create_shared_hcd - create and initialize an HCD structure
>   * @driver: HC driver that will use this hcd
> - * @dev: device for this HC, stored in hcd->self.controller
> +s * @dev: device for this HC, stored in hcd->self.controller
>   * @bus_name: value to store in hcd->self.bus_name
>   * @primary_hcd: a pointer to the usb_hcd structure that is sharing the
>   *              PCI device.  Only allocate certain resources for the primary HCD
> @@ -2323,17 +2325,13 @@ static int usb_hcd_request_irqs(struct u
>  
>  	if (hcd->driver->irq) {
>  
> -		/* IRQF_DISABLED doesn't work as advertised when used together
> -		 * with IRQF_SHARED. As usb_hcd_irq() will always disable
> -		 * interrupts we can remove it here.
> -		 */
> -		if (irqflags & IRQF_SHARED)
> -			irqflags &= ~IRQF_DISABLED;
> -
>  		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
>  				hcd->driver->description, hcd->self.busnum);
> -		retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
> -				hcd->irq_descr, hcd);
> +
> +		retval = request_threaded_irq(irqnum,
> +				hcd->driver->irq ? &usb_hcd_irq : NULL,
> +				hcd->driver->threaded_irq ? &usb_hcd_thread_irq : NULL,
> +				irqflags, hcd->irq_descr, hcd);
>  		if (retval != 0) {
>  			dev_err(hcd->self.controller,
>  					"request interrupt %d failed\n",
> Index: linux-2.6/drivers/usb/host/ehci-hcd.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/host/ehci-hcd.c
> +++ linux-2.6/drivers/usb/host/ehci-hcd.c
> @@ -764,10 +764,35 @@ static int ehci_run (struct usb_hcd *hcd
>  static irqreturn_t ehci_irq (struct usb_hcd *hcd)
>  {
>  	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
> +	u32			status;
> +
> +	spin_lock(&ehci->lock);
> +
> +	status = ehci_readl(ehci, &ehci->regs->status);
> +	if (status & INTR_MASK)
> +		ehci_writel(ehci, 0, &ehci->regs->intr_enable);
> +
> +	spin_unlock(&ehci->lock);
> +
> +	return status & INTR_MASK ? IRQ_WAKE_THREAD : IRQ_NONE;
> +}
> +
> +static irqreturn_t ehci_thread_irq (struct usb_hcd *hcd)
> +{
> +	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
>  	u32			status, masked_status, pcd_status = 0, cmd;
>  	int			bh;
>  
> -	spin_lock (&ehci->lock);
> +	/*
> +	 * The scope of this lock wants to be reduced to protect the
> +	 * status register access. Serializiation at the thread level
> +	 * should simply use a mutex, which is not simple either as
> +	 * you have to deal with the watchdog timer stuff. Needs some
> +	 * thought. Making it spin_lock_bh() now should be fine. We
> +	 * just need to disable interrupts right before we write the
> +	 * interrupt mask register.
> +	 */
> +	spin_lock_irq(&ehci->lock);
>  
>  	status = ehci_readl(ehci, &ehci->regs->status);
>  
> @@ -778,10 +803,6 @@ static irqreturn_t ehci_irq (struct usb_
>  	}
>  
>  	masked_status = status & INTR_MASK;
> -	if (!masked_status) {		/* irq sharing? */
> -		spin_unlock(&ehci->lock);
> -		return IRQ_NONE;
> -	}
>  
>  	/* clear (just) interrupts */
>  	ehci_writel(ehci, masked_status, &ehci->regs->status);
> @@ -881,7 +902,7 @@ dead:
>  
>  	if (bh)
>  		ehci_work (ehci);
> -	spin_unlock (&ehci->lock);
> +	spin_unlock_irq (&ehci->lock);
>  	if (pcd_status)
>  		usb_hcd_poll_rh_status(hcd);
>  	return IRQ_HANDLED;
> Index: linux-2.6/drivers/usb/host/ehci-pci.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/host/ehci-pci.c
> +++ linux-2.6/drivers/usb/host/ehci-pci.c
> @@ -430,6 +430,7 @@ static const struct hc_driver ehci_pci_h
>  	 * generic hardware linkage
>  	 */
>  	.irq =			ehci_irq,
> +	.threaded_irq =		ehci_thread_irq,
>  	.flags =		HCD_MEMORY | HCD_USB2,
>  
>  	/*
> Index: linux-2.6/include/linux/usb/hcd.h
> ===================================================================
> --- linux-2.6.orig/include/linux/usb/hcd.h
> +++ linux-2.6/include/linux/usb/hcd.h
> @@ -207,6 +207,7 @@ struct hc_driver {
>  
>  	/* irq handler */
>  	irqreturn_t	(*irq) (struct usb_hcd *hcd);
> +	irqreturn_t	(*threaded_irq) (struct usb_hcd *hcd);
>  
>  	int	flags;
>  #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */

as a quick glance it seems like I can work with it - I'll give it
a test tomorrow am on our platform.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux