[RFC][PATCH] PCI: Make new suspend-resume callbacks carry out core operations

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

 



Hi Len,

The patch below adds the callbacks that save/restore the standard PCI config
registers, change the power state of the device etc. to the new suspend-resume
callbacks (which are not yet used by device drivers), so that the drivers don't
have to worry about these operations.

The saving and restoring of the standard PCI config registers is done with
interrupts off, the other things are done with interrupts enabled.

The patch should apply to the current linux-next tree.

Please have a look.

Thanks,
Rafael

---
 drivers/pci/pci-driver.c |   40 +++++++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 13 deletions(-)

Index: linux-2.6/drivers/pci/pci-driver.c
===================================================================
--- linux-2.6.orig/drivers/pci/pci-driver.c
+++ linux-2.6/drivers/pci/pci-driver.c
@@ -435,10 +435,13 @@ static int pci_pm_suspend(struct device 
 	int error = 0;
 
 	if (drv && drv->pm) {
-		if (drv->pm->suspend) {
+		if (drv->pm->suspend)
 			error = drv->pm->suspend(dev);
-			suspend_report_result(drv->pm->suspend, error);
+		if (!error) {
+			pci_disable_device(pci_dev);
+			error = pci_prepare_to_sleep(pci_dev);
 		}
+		suspend_report_result(drv->pm->suspend, error);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
 		error = pci_legacy_suspend(dev, PMSG_SUSPEND);
 	}
@@ -454,10 +457,11 @@ static int pci_pm_suspend_noirq(struct d
 	int error = 0;
 
 	if (drv && drv->pm) {
-		if (drv->pm->suspend_noirq) {
+		if (drv->pm->suspend_noirq)
 			error = drv->pm->suspend_noirq(dev);
-			suspend_report_result(drv->pm->suspend_noirq, error);
-		}
+		if (!error)
+			pci_save_state(pci_dev);
+		suspend_report_result(drv->pm->suspend_noirq, error);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
 		error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
 	} else {
@@ -476,6 +480,7 @@ static int pci_pm_resume(struct device *
 	pci_fixup_device(pci_fixup_resume, pci_dev);
 
 	if (drv && drv->pm) {
+		pci_enable_device(pci_dev);
 		if (drv->pm->resume)
 			error = drv->pm->resume(dev);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
@@ -496,6 +501,7 @@ static int pci_pm_resume_noirq(struct de
 	pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
 
 	if (drv && drv->pm) {
+		pci_restore_state(pci_dev);
 		if (drv->pm->resume_noirq)
 			error = drv->pm->resume_noirq(dev);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
@@ -525,10 +531,11 @@ static int pci_pm_freeze(struct device *
 	int error = 0;
 
 	if (drv && drv->pm) {
-		if (drv->pm->freeze) {
+		if (drv->pm->freeze)
 			error = drv->pm->freeze(dev);
-			suspend_report_result(drv->pm->freeze, error);
-		}
+		if (!error)
+			pci_disable_device(pci_dev);
+		suspend_report_result(drv->pm->freeze, error);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
 		error = pci_legacy_suspend(dev, PMSG_FREEZE);
 		pci_fixup_device(pci_fixup_suspend, pci_dev);
@@ -544,10 +551,11 @@ static int pci_pm_freeze_noirq(struct de
 	int error = 0;
 
 	if (drv && drv->pm) {
-		if (drv->pm->freeze_noirq) {
+		if (drv->pm->freeze_noirq)
 			error = drv->pm->freeze_noirq(dev);
-			suspend_report_result(drv->pm->freeze_noirq, error);
-		}
+		if (!error)
+			pci_save_state(pci_dev);
+		suspend_report_result(drv->pm->freeze_noirq, error);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
 		error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
 	} else {
@@ -564,6 +572,7 @@ static int pci_pm_thaw(struct device *de
 	int error = 0;
 
 	if (drv && drv->pm) {
+		pci_enable_device(pci_dev);
 		if (drv->pm->thaw)
 			error =  drv->pm->thaw(dev);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
@@ -600,10 +609,13 @@ static int pci_pm_poweroff(struct device
 	pci_fixup_device(pci_fixup_suspend, pci_dev);
 
 	if (drv && drv->pm) {
-		if (drv->pm->poweroff) {
+		if (drv->pm->poweroff)
 			error = drv->pm->poweroff(dev);
-			suspend_report_result(drv->pm->poweroff, error);
+		if (!error) {
+			pci_disable_device(pci_dev);
+			error = pci_prepare_to_sleep(pci_dev);
 		}
+		suspend_report_result(drv->pm->poweroff, error);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
 		error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
 	}
@@ -635,6 +647,7 @@ static int pci_pm_restore(struct device 
 	int error = 0;
 
 	if (drv && drv->pm) {
+		pci_enable_device(pci_dev);
 		if (drv->pm->restore)
 			error = drv->pm->restore(dev);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
@@ -656,6 +669,7 @@ static int pci_pm_restore_noirq(struct d
 	pci_fixup_device(pci_fixup_resume, pci_dev);
 
 	if (drv && drv->pm) {
+		pci_restore_state(pci_dev);
 		if (drv->pm->restore_noirq)
 			error = drv->pm->restore_noirq(dev);
 	} else if (pci_has_legacy_pm_support(pci_dev)) {
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux