Re: [RFC] xHCI: synchronize interrupts in xhci_suspend()

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

 



On Mon, Dec 06, 2010 at 06:22:19PM +0800, Andiry Xu wrote:
> Matthew,
> 
> Can you help to test if this patch fix your xhci suspend and remove issue? Thanks.

Andiry,

This code doesn't change the code in the USB core that synchronizes the
legacy PCI interrupts.  So if you have to fall back to MSI, then
pci_dev->irq is equal to your MSI irq, and suspend_common() will
synchronize the irq a second time after xhci_suspend() is called.  Maybe
suspend_common() should only call synchronize_irq() if pci_dev->irq is
the same as hcd->irq?

Also, what happens if you free the legacy IRQ, set up MSI-X, and then
the USB core tries to synchronize pci_dev->irq?  Is pci_dev->irq still
set to the legacy IRQ that the driver freed?  If so, we're possibly
synchronizing someone else's IRQ.

Sarah Sharp

> From: Andiry Xu <andiry.xu@xxxxxxx>
> Date: Mon, 6 Dec 2010 16:58:16 +0800
> Subject: [PATCH] xHCI: synchronize interrupts in xhci_suspend()
> 
> Matthew Garrett reports a interrupt double free in xHCI code when the
> host is suspended and then the card removed.
> 
> Synchronize the interrupts instead of free them in xhci_suspned().
> 
> Reported-by: Matthew Garrett <mjg@xxxxxxxxxx>
> Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx>
> ---
>  drivers/usb/host/xhci.c |   37 +++++++++----------------------------
>  1 files changed, 9 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 45e4a31..41a9225 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -646,7 +646,9 @@ int xhci_suspend(struct xhci_hcd *xhci)
>  {
>  	int			rc = 0;
>  	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
> +	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
>  	u32			command;
> +	int			i;
>  
>  	spin_lock_irq(&xhci->lock);
>  	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
> @@ -678,9 +680,14 @@ int xhci_suspend(struct xhci_hcd *xhci)
>  		return -ETIMEDOUT;
>  	}
>  	/* step 5: remove core well power */
> -	xhci_cleanup_msix(xhci);
>  	spin_unlock_irq(&xhci->lock);
>  
> +	if (xhci->msix_entries) {
> +		for (i = 0; i < xhci->msix_count; i++)
> +			synchronize_irq(xhci->msix_entries[i].vector);
> +	} else if (pdev->irq >= 0)
> +		synchronize_irq(pdev->irq);
> +
>  	return rc;
>  }
>  
> @@ -694,7 +701,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
>  {
>  	u32			command, temp = 0;
>  	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
> -	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
>  	int	old_state, retval;
>  
>  	old_state = hcd->state;
> @@ -729,8 +735,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
>  		xhci_dbg(xhci, "Stop HCD\n");
>  		xhci_halt(xhci);
>  		xhci_reset(xhci);
> -		if (hibernated)
> -			xhci_cleanup_msix(xhci);
> +		xhci_cleanup_msix(xhci);
>  		spin_unlock_irq(&xhci->lock);
>  
>  #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
> @@ -765,30 +770,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
>  		return retval;
>  	}
>  
> -	spin_unlock_irq(&xhci->lock);
> -	/* Re-setup MSI-X */
> -	if (hcd->irq)
> -		free_irq(hcd->irq, hcd);
> -	hcd->irq = -1;
> -
> -	retval = xhci_setup_msix(xhci);
> -	if (retval)
> -		/* fall back to msi*/
> -		retval = xhci_setup_msi(xhci);
> -
> -	if (retval) {
> -		/* fall back to legacy interrupt*/
> -		retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
> -					hcd->irq_descr, hcd);
> -		if (retval) {
> -			xhci_err(xhci, "request interrupt %d failed\n",
> -					pdev->irq);
> -			return retval;
> -		}
> -		hcd->irq = pdev->irq;
> -	}
> -
> -	spin_lock_irq(&xhci->lock);
>  	/* step 4: set Run/Stop bit */
>  	command = xhci_readl(xhci, &xhci->op_regs->command);
>  	command |= CMD_RUN;
> -- 
> 1.7.0.4
> 
> 
> 
--
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