Re: [linux-pm] ehci_hcd related S3 lockup on ASUS laptops, again

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

 



On Tue, Apr 17, 2012 at 12:58:03PM -0400, Alan Stern wrote:
> > > 	1. This change in hcd-pci.c:
> > > +	pci_dev->current_state = PCI_UNKNOWN;
> > It locks up if this line is removed.
> 
> Very bizarre indeed.  All right, leave that line in place and try 
> removing the other changes, one at a time.  In fact, let's add one more 
> thing to remove from the patch
> 
> > > 	2. This change in ehci-pci.c:
> > > +	ehci_silence_controller(ehci);
> > > 
> > > 	3. This change in hcd-pci.c:
> > > +	pci_disable_device(pci_dev);
> > > 
> > > 	4. This change in hcd-pci.c:
> > > +	iounmap(hcd->regs);
> > > 
> > > 	5. This change in hcd-pci.c:
> > > +	free_irq(hcd->irq, hcd);
> > > 
> > > 	6. This change in hcd-pci.c:
> > > -	pci_disable_device(pci_dev);
> > > +	pci_disable_enabled_device(pci_dev);
> > > 
> > > 	7. This change in ehci-pci.c:
> > > -	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
> 
> 	8. This change in ehci-pci.c:
> +	ehci_reset(ehci);
> 
> If you manage to reach the end of this list, you'll essentially be
> doing a normal suspend (except for the PCI_UNKNOWN part).
It works without changes #2..8. I'm attaching the resulting patch.

-- 
WBR, wRAR
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6b54b23..8a9edf4 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -713,6 +713,8 @@ static int pci_pm_suspend_noirq(struct device *dev)
 
 	if (!pm) {
 		pci_save_state(pci_dev);
+		pci_prepare_to_sleep(pci_dev);
+		pci_pm_set_unknown_state(pci_dev);
 		return 0;
 	}
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8156744..3111105 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1348,6 +1348,7 @@ void pci_disable_enabled_device(struct pci_dev *dev)
 	if (pci_is_enabled(dev))
 		do_pci_disable_device(dev);
 }
+EXPORT_SYMBOL(pci_disable_enabled_device);
 
 /**
  * pci_disable_device - Disable PCI device after use
@@ -1710,6 +1711,7 @@ pci_power_t pci_target_state(struct pci_dev *dev)
  */
 int pci_prepare_to_sleep(struct pci_dev *dev)
 {
+	pci_power_t cur_state = dev->current_state;
 	pci_power_t target_state = pci_target_state(dev);
 	int error;
 
@@ -1723,6 +1725,8 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
 	if (error)
 		pci_enable_wake(dev, target_state, false);
 
+	dev_info(&dev->dev, "cur %d target %d error %d\n", cur_state,
+			target_state, error);
 	return error;
 }
 
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 622b4a4..d7dc939 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -381,6 +381,8 @@ static int check_root_hub_suspended(struct device *dev)
 }
 
 #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME)
+extern void pci_disable_enabled_device(struct pci_dev *);
+
 static int suspend_common(struct device *dev, bool do_wakeup)
 {
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
@@ -427,12 +429,18 @@ static int suspend_common(struct device *dev, bool do_wakeup)
 	if (!hcd->msix_enabled)
 		synchronize_irq(pci_dev->irq);
 
+//	free_irq(hcd->irq, hcd); // 5
+//	iounmap(hcd->regs); // 4
+//	pci_disable_device(pci_dev); // 3
+
 	/* Downstream ports from this root hub should already be quiesced, so
 	 * there will be no DMA activity.  Now we can shut down the upstream
 	 * link (except maybe for PME# resume signaling).  We'll enter a
 	 * low power state during suspend_noirq, if the hardware allows.
 	 */
+//	pci_disable_enabled_device(pci_dev); // 6
 	pci_disable_device(pci_dev);
+	pci_dev->current_state = PCI_UNKNOWN; // 1
 	return retval;
 }
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 01bb7241d..5fbfc3e 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -342,7 +342,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 	 * mark HW unaccessible.  The PM and USB cores make sure that
 	 * the root hub is either suspended or stopped.
 	 */
-	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
+	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); // 7
 	spin_lock_irqsave (&ehci->lock, flags);
 	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
@@ -350,6 +350,9 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	spin_unlock_irqrestore (&ehci->lock, flags);
 
+//	ehci_silence_controller(ehci); // 2
+//	ehci_reset(ehci); // 8
+
 	// could save FLADJ in case of Vaux power loss
 	// ... we'd only use it to handle clock skew
 

Attachment: signature.asc
Description: Digital signature


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

  Powered by Linux