linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: <gregkh@suse.de>
To: rjw@sisk.pl, akpm@linux-foundation.org, astarikovskiy@suse.de,
	benh@kernel.crashing.org, david-b@pacbell.net, greg@kroah.com,
	gregkh@suse.de, jbarnes@virtuousgeek.org, lenb@kernel.org
Subject: patch pm-new-suspend-and-hibernation-callbacks-for-pci-bus-type.patch added to gregkh-2.6 tree
Date: Tue, 15 Apr 2008 12:27:31 -0700	[thread overview]
Message-ID: <12082876512459@kroah.org> (raw)
In-Reply-To: <200804131534.52548.rjw@sisk.pl>


This is a note to let you know that I've just added the patch titled

     Subject: PM: New suspend and hibernation callbacks for PCI bus type

to my gregkh-2.6 tree.  Its filename is

     pm-new-suspend-and-hibernation-callbacks-for-pci-bus-type.patch

This tree can be found at 
    http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/


>From rjw@sisk.pl  Tue Apr 15 12:21:43 2008
From: "Rafael J. Wysocki" <rjw@sisk.pl>
Date: Sun, 13 Apr 2008 15:34:51 +0200
Subject: PM: New suspend and hibernation callbacks for PCI bus type
To: Greg KH <greg@kroah.com>
Cc: pm list <linux-pm@lists.linux-foundation.org>, ACPI Devel Maling List <linux-acpi@vger.kernel.org>, Alan Stern <stern@rowland.harvard.edu>, Len Brown <lenb@kernel.org>, LKML <linux-kernel@vger.kernel.org>, Alexey Starikovskiy <astarikovskiy@suse.de>, David Brownell <david-b@pacbell.net>, Pavel Machek <pavel@ucw.cz>, Benjamin Herrenschmidt <benh@kernel.crashing.org>, Oliver Neukum <oliver@neukum.org>, Nigel Cunningham <ncunningham@crca.org.au>, Jesse Barnes <jbarnes@virtuousgeek.org>, Andrew Morton <akpm@linux-foundation.org>
Message-ID: <200804131534.52548.rjw@sisk.pl>
Content-Disposition: inline


From: Rafael J. Wysocki <rjw@sisk.pl>

Implement new suspend and hibernation callbacks for the PCI bus type.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 drivers/pci/pci-driver.c |  372 ++++++++++++++++++++++++++++++++++++++++++-----
 include/linux/pci.h      |    2 
 2 files changed, 335 insertions(+), 39 deletions(-)

--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -271,7 +271,55 @@ static int pci_device_remove(struct devi
 	return 0;
 }
 
-static int pci_device_suspend(struct device * dev, pm_message_t state)
+static void pci_device_shutdown(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+
+	if (drv && drv->shutdown)
+		drv->shutdown(pci_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+/*
+ * Default "suspend" method for devices that have no driver provided suspend,
+ * or not even a driver at all.
+ */
+static void pci_default_pm_suspend(struct pci_dev *pci_dev)
+{
+	pci_save_state(pci_dev);
+	/*
+	 * mark its power state as "unknown", since we don't know if
+	 * e.g. the BIOS will change its device state when we suspend.
+	 */
+	if (pci_dev->current_state == PCI_D0)
+		pci_dev->current_state = PCI_UNKNOWN;
+}
+
+/*
+ * Default "resume" method for devices that have no driver provided resume,
+ * or not even a driver at all.
+ */
+static int pci_default_pm_resume(struct pci_dev *pci_dev)
+{
+	int retval = 0;
+
+	/* restore the PCI config space */
+	pci_restore_state(pci_dev);
+	/* if the device was enabled before suspend, reenable */
+	retval = pci_reenable_device(pci_dev);
+	/*
+	 * if the device was busmaster before the suspend, make it busmaster
+	 * again
+	 */
+	if (pci_dev->is_busmaster)
+		pci_set_master(pci_dev);
+
+	return retval;
+}
+
+static int pci_legacy_suspend(struct device *dev, pm_message_t state)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
@@ -281,18 +329,12 @@ static int pci_device_suspend(struct dev
 		i = drv->suspend(pci_dev, state);
 		suspend_report_result(drv->suspend, i);
 	} else {
-		pci_save_state(pci_dev);
-		/*
-		 * mark its power state as "unknown", since we don't know if
-		 * e.g. the BIOS will change its device state when we suspend.
-		 */
-		if (pci_dev->current_state == PCI_D0)
-			pci_dev->current_state = PCI_UNKNOWN;
+		pci_default_pm_suspend(pci_dev);
 	}
 	return i;
 }
 
-static int pci_device_suspend_late(struct device * dev, pm_message_t state)
+static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
@@ -305,26 +347,7 @@ static int pci_device_suspend_late(struc
 	return i;
 }
 
-/*
- * Default resume method for devices that have no driver provided resume,
- * or not even a driver at all.
- */
-static int pci_default_resume(struct pci_dev *pci_dev)
-{
-	int retval = 0;
-
-	/* restore the PCI config space */
-	pci_restore_state(pci_dev);
-	/* if the device was enabled before suspend, reenable */
-	retval = pci_reenable_device(pci_dev);
-	/* if the device was busmaster before the suspend, make it busmaster again */
-	if (pci_dev->is_busmaster)
-		pci_set_master(pci_dev);
-
-	return retval;
-}
-
-static int pci_device_resume(struct device * dev)
+static int pci_legacy_resume(struct device *dev)
 {
 	int error;
 	struct pci_dev * pci_dev = to_pci_dev(dev);
@@ -333,11 +356,11 @@ static int pci_device_resume(struct devi
 	if (drv && drv->resume)
 		error = drv->resume(pci_dev);
 	else
-		error = pci_default_resume(pci_dev);
+		error = pci_default_pm_resume(pci_dev);
 	return error;
 }
 
-static int pci_device_resume_early(struct device * dev)
+static int pci_legacy_resume_early(struct device *dev)
 {
 	int error = 0;
 	struct pci_dev * pci_dev = to_pci_dev(dev);
@@ -350,15 +373,288 @@ static int pci_device_resume_early(struc
 	return error;
 }
 
-static void pci_device_shutdown(struct device *dev)
+static int pci_pm_prepare(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm && drv->pm->prepare)
+		error = drv->pm->prepare(dev);
+
+	return error;
+}
+
+static void pci_pm_complete(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+
+	if (drv && drv->pm && drv->pm->complete)
+		drv->pm->complete(dev);
+}
+
+#ifdef CONFIG_SUSPEND
+
+static int pci_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct device_driver *drv = dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->suspend) {
+			error = drv->pm->suspend(dev);
+			suspend_report_result(drv->pm->suspend, error);
+		} else {
+			pci_default_pm_suspend(pci_dev);
+		}
+	} else {
+		error = pci_legacy_suspend(dev, PMSG_SUSPEND);
+	}
+
+	return error;
+}
+
+static int pci_pm_suspend_noirq(struct device *dev)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
 
-	if (drv && drv->shutdown)
-		drv->shutdown(pci_dev);
+	if (drv && drv->pm) {
+		if (drv->pm->suspend_noirq) {
+			error = drv->pm->suspend_noirq(dev);
+			suspend_report_result(drv->pm->suspend_noirq, error);
+		}
+	} else {
+		error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
+	}
+
+	return error;
+}
+
+static int pci_pm_resume(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct device_driver *drv = dev->driver;
+	int error;
+
+	if (drv && drv->pm) {
+		error = drv->pm->resume ? drv->pm->resume(dev) :
+			pci_default_pm_resume(pci_dev);
+	} else {
+		error = pci_legacy_resume(dev);
+	}
+
+	return error;
 }
 
+static int pci_pm_resume_noirq(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
+
+	pci_fixup_device(pci_fixup_resume, pci_dev);
+
+	if (drv && drv->pm) {
+		if (drv->pm->resume_noirq)
+			error = drv->pm->resume_noirq(dev);
+	} else {
+		error = pci_legacy_resume_early(dev);
+	}
+
+	return error;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define pci_pm_suspend		NULL
+#define pci_pm_suspend_noirq	NULL
+#define pci_pm_resume		NULL
+#define pci_pm_resume_noirq	NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATION
+
+static int pci_pm_freeze(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct device_driver *drv = dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->freeze) {
+			error = drv->pm->freeze(dev);
+			suspend_report_result(drv->pm->freeze, error);
+		} else {
+			pci_default_pm_suspend(pci_dev);
+		}
+	} else {
+		error = pci_legacy_suspend(dev, PMSG_FREEZE);
+	}
+
+	return error;
+}
+
+static int pci_pm_freeze_noirq(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->freeze_noirq) {
+			error = drv->pm->freeze_noirq(dev);
+			suspend_report_result(drv->pm->freeze_noirq, error);
+		}
+	} else {
+		error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
+	}
+
+	return error;
+}
+
+static int pci_pm_thaw(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->thaw)
+			error =  drv->pm->thaw(dev);
+	} else {
+		error = pci_legacy_resume(dev);
+	}
+
+	return error;
+}
+
+static int pci_pm_thaw_noirq(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->thaw_noirq)
+			error = drv->pm->thaw_noirq(dev);
+	} else {
+		error = pci_legacy_resume_early(dev);
+	}
+
+	return error;
+}
+
+static int pci_pm_poweroff(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->poweroff) {
+			error = drv->pm->poweroff(dev);
+			suspend_report_result(drv->pm->poweroff, error);
+		}
+	} else {
+		error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
+	}
+
+	return error;
+}
+
+static int pci_pm_poweroff_noirq(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
+
+	if (drv && drv->pm) {
+		if (drv->pm->poweroff_noirq) {
+			error = drv->pm->poweroff_noirq(dev);
+			suspend_report_result(drv->pm->poweroff_noirq, error);
+		}
+	} else {
+		error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
+	}
+
+	return error;
+}
+
+static int pci_pm_restore(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct device_driver *drv = dev->driver;
+	int error;
+
+	if (drv && drv->pm) {
+		error = drv->pm->restore ? drv->pm->restore(dev) :
+			pci_default_pm_resume(pci_dev);
+	} else {
+		error = pci_legacy_resume(dev);
+	}
+
+	return error;
+}
+
+static int pci_pm_restore_noirq(struct device *dev)
+{
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct pci_driver *drv = pci_dev->driver;
+	int error = 0;
+
+	pci_fixup_device(pci_fixup_resume, pci_dev);
+
+	if (drv && drv->pm) {
+		if (drv->pm->restore_noirq)
+			error = drv->pm->restore_noirq(dev);
+	} else {
+		error = pci_legacy_resume_early(dev);
+	}
+
+	return error;
+}
+
+#else /* !CONFIG_HIBERNATION */
+
+#define pci_pm_freeze		NULL
+#define pci_pm_freeze_noirq	NULL
+#define pci_pm_thaw		NULL
+#define pci_pm_thaw_noirq	NULL
+#define pci_pm_poweroff		NULL
+#define pci_pm_poweroff_noirq	NULL
+#define pci_pm_restore		NULL
+#define pci_pm_restore_noirq	NULL
+
+#endif /* !CONFIG_HIBERNATION */
+
+struct pm_ext_ops pci_pm_ops = {
+	.base = {
+		.prepare = pci_pm_prepare,
+		.complete = pci_pm_complete,
+		.suspend = pci_pm_suspend,
+		.resume = pci_pm_resume,
+		.freeze = pci_pm_freeze,
+		.thaw = pci_pm_thaw,
+		.poweroff = pci_pm_poweroff,
+		.restore = pci_pm_restore,
+	},
+	.suspend_noirq = pci_pm_suspend_noirq,
+	.resume_noirq = pci_pm_resume_noirq,
+	.freeze_noirq = pci_pm_freeze_noirq,
+	.thaw_noirq = pci_pm_thaw_noirq,
+	.poweroff_noirq = pci_pm_poweroff_noirq,
+	.restore_noirq = pci_pm_restore_noirq,
+};
+
+#define PCI_PM_OPS_PTR	&pci_pm_ops
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define PCI_PM_OPS_PTR	NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 /**
  * __pci_register_driver - register a new pci driver
  * @drv: the driver structure to register
@@ -381,6 +677,9 @@ int __pci_register_driver(struct pci_dri
 	drv->driver.owner = owner;
 	drv->driver.mod_name = mod_name;
 
+	if (drv->pm)
+		drv->driver.pm = &drv->pm->base;
+
 	spin_lock_init(&drv->dynids.lock);
 	INIT_LIST_HEAD(&drv->dynids.list);
 
@@ -506,12 +805,9 @@ struct bus_type pci_bus_type = {
 	.uevent		= pci_uevent,
 	.probe		= pci_device_probe,
 	.remove		= pci_device_remove,
-	.suspend	= pci_device_suspend,
-	.suspend_late	= pci_device_suspend_late,
-	.resume_early	= pci_device_resume_early,
-	.resume		= pci_device_resume,
 	.shutdown	= pci_device_shutdown,
 	.dev_attrs	= pci_dev_attrs,
+	.pm		= PCI_PM_OPS_PTR,
 };
 
 static int __init pci_driver_init(void)
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -388,7 +388,7 @@ struct pci_driver {
 	int  (*resume_early) (struct pci_dev *dev);
 	int  (*resume) (struct pci_dev *dev);	                /* Device woken up */
 	void (*shutdown) (struct pci_dev *dev);
-
+	struct pm_ext_ops *pm;
 	struct pci_error_handlers *err_handler;
 	struct device_driver	driver;
 	struct pci_dynids dynids;


Patches currently in gregkh-2.6 which might be from rjw@sisk.pl are

driver-core/pm-remove-legacy-pm.patch
driver-core/power_state-remove-it-from-driver-core.patch
driver-core/pm-handle-device-registrations-during-suspend-resume.patch
driver-core/pm-convert-wakeup-flag-accessors-to-inline-functions.patch
driver-core/driver-core-call-device_pm_add-after-bus_add_device-in-device_add.patch
driver-core/pm-remove-destroy_suspended_device.patch
driver-core/pm-fix-misuse-of-wakeup-flag-accessors-in-serial-core.patch
driver-core/pm-make-wakeup-flags-available-whenever-config_pm-is-set.patch
driver-core/pm-introduce-new-top-level-suspend-and-hibernation-callbacks.patch
driver-core/pm-new-suspend-and-hibernation-callbacks-for-pci-bus-type.patch
driver-core/pm-new-suspend-and-hibernation-callbacks-for-platform-bus-type.patch

  reply	other threads:[~2008-04-15 19:28 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-03 23:11 [PATCH 0/3] PM: New suspend and hibernation callbacks Rafael J. Wysocki
2008-04-03 23:12 ` [PATCH 1/3] PM: Introduce new top level suspend and hibernation callbacks (rev. 7) Rafael J. Wysocki
2008-04-12  0:23   ` Greg KH
2008-04-13 13:31     ` Rafael J. Wysocki
2008-04-13 13:33       ` [PATCH 1/3] PM: Introduce new top level suspend and hibernation callbacks (rev. 8) Rafael J. Wysocki
2008-04-13 21:05         ` Benjamin Herrenschmidt
2008-04-13 21:39           ` Rafael J. Wysocki
2008-04-13 22:10             ` Benjamin Herrenschmidt
2008-04-13 22:27               ` Rafael J. Wysocki
2008-04-13 22:47                 ` Benjamin Herrenschmidt
2008-04-13 23:08                   ` Rafael J. Wysocki
2008-04-13 23:46                     ` Benjamin Herrenschmidt
2008-04-14  0:31                       ` Rafael J. Wysocki
2008-04-14  0:46                         ` Benjamin Herrenschmidt
2008-04-14  1:09                           ` Rafael J. Wysocki
2008-04-14  3:23                             ` Benjamin Herrenschmidt
2008-04-14  6:43                               ` Oliver Neukum
2008-04-14  7:23                                 ` Benjamin Herrenschmidt
2008-04-14  7:37                                   ` Oliver Neukum
2008-04-14  7:50                                     ` Benjamin Herrenschmidt
2008-04-14 12:11                               ` Rafael J. Wysocki
2008-04-14 15:13                                 ` Alan Stern
2008-04-14 20:48                                   ` Benjamin Herrenschmidt
2008-04-14 14:49                               ` Alan Stern
2008-04-14 20:41                                 ` Oliver Neukum
2008-04-14  1:37                           ` Nigel Cunningham
2008-04-14 12:25                             ` Rafael J. Wysocki
2008-04-13 23:11                   ` Nigel Cunningham
2008-04-13 23:17                     ` Rafael J. Wysocki
2008-04-13 23:29                       ` Nigel Cunningham
2008-04-13 23:23                     ` Alan Stern
2008-04-13 23:33                       ` Rafael J. Wysocki
2008-04-13 23:49                         ` Benjamin Herrenschmidt
2008-04-13 23:48                       ` Benjamin Herrenschmidt
2008-04-14  0:07                         ` Rafael J. Wysocki
2008-04-14  0:40                           ` Benjamin Herrenschmidt
2008-04-14  0:59                             ` Rafael J. Wysocki
2008-04-14  0:43                           ` Benjamin Herrenschmidt
2008-04-14  0:50                             ` Rafael J. Wysocki
2008-04-14  4:47                   ` David Brownell
2008-04-14 12:34                     ` Rafael J. Wysocki
2008-04-14 14:51                     ` Alan Stern
2008-04-14 20:47                       ` Benjamin Herrenschmidt
2008-04-14 21:21                       ` Pavel Machek
2008-04-14 10:55                   ` Pavel Machek
2008-04-14 20:45                     ` Benjamin Herrenschmidt
2008-04-14 20:56                       ` Rafael J. Wysocki
2008-04-15 19:27         ` patch pm-introduce-new-top-level-suspend-and-hibernation-callbacks.patch added to gregkh-2.6 tree gregkh
2008-04-13 13:33       ` [PATCH 2/3] PM: New suspend and hibernation callbacks for platform bus type (rev. 3) Rafael J. Wysocki
2008-04-15 19:27         ` patch pm-new-suspend-and-hibernation-callbacks-for-platform-bus-type.patch added to gregkh-2.6 tree gregkh
2008-04-13 13:34       ` [PATCH 3/3] PM: New suspend and hibernation callbacks for PCI bus type (rev. 4) Rafael J. Wysocki
2008-04-15 19:27         ` gregkh [this message]
2008-04-29 22:26         ` PM: New suspend and hibernation callbacks for PCI bus type Greg KH
2008-04-30 12:09           ` Rafael J. Wysocki
2008-05-07  5:08             ` patch pm-new-suspend-and-hibernation-callbacks-for-pci-bus-type.patch added to gregkh-2.6 tree gregkh
2008-04-03 23:13 ` [PATCH 2/3] PM: New suspend and hibernation callbacks for platform bus type (rev. 3) Rafael J. Wysocki
2008-04-03 23:15 ` [PATCH 3/3] PM: New suspend and hibernation callbacks for PCI " Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=12082876512459@kroah.org \
    --to=gregkh@suse.de \
    --cc=akpm@linux-foundation.org \
    --cc=astarikovskiy@suse.de \
    --cc=benh@kernel.crashing.org \
    --cc=david-b@pacbell.net \
    --cc=greg@kroah.com \
    --cc=jbarnes@virtuousgeek.org \
    --cc=lenb@kernel.org \
    --cc=rjw@sisk.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).