Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adf09493 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Greg Kroah-Hartman
Browse files

PM: Simplify the new suspend/hibernation framework for devices



PM: Simplify the new suspend/hibernation framework for devices

Following the discussion at the Kernel Summit, simplify the new
device PM framework by merging 'struct pm_ops' and
'struct pm_ext_ops' and removing pointers to 'struct pm_ext_ops'
from 'struct platform_driver' and 'struct pci_driver'.

After this change, the suspend/hibernation callbacks will only
reside in 'struct device_driver' as well as at the bus type/
device class/device type level.  Accordingly, PCI and platform
device drivers are now expected to put their suspend/hibernation
callbacks into the 'struct device_driver' embedded in
'struct pci_driver' or 'struct platform_driver', respectively.

Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@suse.cz>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 238c6d54
Loading
Loading
Loading
Loading
+60 −55
Original line number Diff line number Diff line
@@ -503,8 +503,6 @@ int platform_driver_register(struct platform_driver *drv)
		drv->driver.suspend = platform_drv_suspend;
	if (drv->resume)
		drv->driver.resume = platform_drv_resume;
	if (drv->pm)
		drv->driver.pm = &drv->pm->base;
	return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -686,7 +684,10 @@ static int platform_pm_suspend(struct device *dev)
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (drv && drv->pm) {
	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->suspend)
			ret = drv->pm->suspend(dev);
	} else {
@@ -698,16 +699,15 @@ static int platform_pm_suspend(struct device *dev)

static int platform_pm_suspend_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->suspend_noirq)
			ret = pdrv->pm->suspend_noirq(dev);
	if (drv->pm) {
		if (drv->pm->suspend_noirq)
			ret = drv->pm->suspend_noirq(dev);
	} else {
		ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
	}
@@ -720,7 +720,10 @@ static int platform_pm_resume(struct device *dev)
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (drv && drv->pm) {
	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->resume)
			ret = drv->pm->resume(dev);
	} else {
@@ -732,16 +735,15 @@ static int platform_pm_resume(struct device *dev)

static int platform_pm_resume_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->resume_noirq)
			ret = pdrv->pm->resume_noirq(dev);
	if (drv->pm) {
		if (drv->pm->resume_noirq)
			ret = drv->pm->resume_noirq(dev);
	} else {
		ret = platform_legacy_resume_early(dev);
	}
@@ -780,16 +782,15 @@ static int platform_pm_freeze(struct device *dev)

static int platform_pm_freeze_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->freeze_noirq)
			ret = pdrv->pm->freeze_noirq(dev);
	if (drv->pm) {
		if (drv->pm->freeze_noirq)
			ret = drv->pm->freeze_noirq(dev);
	} else {
		ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
	}
@@ -802,7 +803,10 @@ static int platform_pm_thaw(struct device *dev)
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (drv && drv->pm) {
	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->thaw)
			ret = drv->pm->thaw(dev);
	} else {
@@ -814,16 +818,15 @@ static int platform_pm_thaw(struct device *dev)

static int platform_pm_thaw_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->thaw_noirq)
			ret = pdrv->pm->thaw_noirq(dev);
	if (drv->pm) {
		if (drv->pm->thaw_noirq)
			ret = drv->pm->thaw_noirq(dev);
	} else {
		ret = platform_legacy_resume_early(dev);
	}
@@ -836,7 +839,10 @@ static int platform_pm_poweroff(struct device *dev)
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (drv && drv->pm) {
	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->poweroff)
			ret = drv->pm->poweroff(dev);
	} else {
@@ -848,16 +854,15 @@ static int platform_pm_poweroff(struct device *dev)

static int platform_pm_poweroff_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->poweroff_noirq)
			ret = pdrv->pm->poweroff_noirq(dev);
	if (drv->pm) {
		if (drv->pm->poweroff_noirq)
			ret = drv->pm->poweroff_noirq(dev);
	} else {
		ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
	}
@@ -870,7 +875,10 @@ static int platform_pm_restore(struct device *dev)
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (drv && drv->pm) {
	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->restore)
			ret = drv->pm->restore(dev);
	} else {
@@ -882,16 +890,15 @@ static int platform_pm_restore(struct device *dev)

static int platform_pm_restore_noirq(struct device *dev)
{
	struct platform_driver *pdrv;
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!dev->driver)
	if (!drv)
		return 0;

	pdrv = to_platform_driver(dev->driver);
	if (pdrv->pm) {
		if (pdrv->pm->restore_noirq)
			ret = pdrv->pm->restore_noirq(dev);
	if (drv->pm) {
		if (drv->pm->restore_noirq)
			ret = drv->pm->restore_noirq(dev);
	} else {
		ret = platform_legacy_resume_early(dev);
	}
@@ -912,8 +919,7 @@ static int platform_pm_restore_noirq(struct device *dev)

#endif /* !CONFIG_HIBERNATION */

static struct pm_ext_ops platform_pm_ops = {
	.base = {
static struct dev_pm_ops platform_dev_pm_ops = {
	.prepare = platform_pm_prepare,
	.complete = platform_pm_complete,
	.suspend = platform_pm_suspend,
@@ -922,7 +928,6 @@ static struct pm_ext_ops platform_pm_ops = {
	.thaw = platform_pm_thaw,
	.poweroff = platform_pm_poweroff,
	.restore = platform_pm_restore,
	},
	.suspend_noirq = platform_pm_suspend_noirq,
	.resume_noirq = platform_pm_resume_noirq,
	.freeze_noirq = platform_pm_freeze_noirq,
@@ -931,7 +936,7 @@ static struct pm_ext_ops platform_pm_ops = {
	.restore_noirq = platform_pm_restore_noirq,
};

#define PLATFORM_PM_OPS_PTR	&platform_pm_ops
#define PLATFORM_PM_OPS_PTR	(&platform_dev_pm_ops)

#else /* !CONFIG_PM_SLEEP */

+10 −9
Original line number Diff line number Diff line
@@ -112,7 +112,8 @@ void device_pm_remove(struct device *dev)
 *	@ops:	PM operations to choose from.
 *	@state:	PM transition of the system being carried out.
 */
static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
static int pm_op(struct device *dev, struct dev_pm_ops *ops,
			pm_message_t state)
{
	int error = 0;

@@ -174,7 +175,7 @@ static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
 *	The operation is executed with interrupts disabled by the only remaining
 *	functional CPU in the system.
 */
static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops,
static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops,
			pm_message_t state)
{
	int error = 0;
@@ -354,7 +355,7 @@ static int resume_device(struct device *dev, pm_message_t state)
	if (dev->bus) {
		if (dev->bus->pm) {
			pm_dev_dbg(dev, state, "");
			error = pm_op(dev, &dev->bus->pm->base, state);
			error = pm_op(dev, dev->bus->pm, state);
		} else if (dev->bus->resume) {
			pm_dev_dbg(dev, state, "legacy ");
			error = dev->bus->resume(dev);
@@ -451,9 +452,9 @@ static void complete_device(struct device *dev, pm_message_t state)
		dev->type->pm->complete(dev);
	}

	if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) {
	if (dev->bus && dev->bus->pm && dev->bus->pm->complete) {
		pm_dev_dbg(dev, state, "completing ");
		dev->bus->pm->base.complete(dev);
		dev->bus->pm->complete(dev);
	}

	up(&dev->sem);
@@ -624,7 +625,7 @@ static int suspend_device(struct device *dev, pm_message_t state)
	if (dev->bus) {
		if (dev->bus->pm) {
			pm_dev_dbg(dev, state, "");
			error = pm_op(dev, &dev->bus->pm->base, state);
			error = pm_op(dev, dev->bus->pm, state);
		} else if (dev->bus->suspend) {
			pm_dev_dbg(dev, state, "legacy ");
			error = dev->bus->suspend(dev, state);
@@ -685,10 +686,10 @@ static int prepare_device(struct device *dev, pm_message_t state)

	down(&dev->sem);

	if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) {
	if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
		pm_dev_dbg(dev, state, "preparing ");
		error = dev->bus->pm->base.prepare(dev);
		suspend_report_result(dev->bus->pm->base.prepare, error);
		error = dev->bus->pm->prepare(dev);
		suspend_report_result(dev->bus->pm->prepare, error);
		if (error)
			goto End;
	}
+18 −28
Original line number Diff line number Diff line
@@ -433,8 +433,7 @@ static int pci_pm_suspend(struct device *dev)

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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	if (drv && drv->pm) {
@@ -469,11 +468,10 @@ static int pci_pm_resume(struct device *dev)

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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	pci_fixup_device(pci_fixup_resume_early, pci_dev);
	pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));

	if (drv && drv->pm) {
		if (drv->pm->resume_noirq)
@@ -519,8 +517,7 @@ static int pci_pm_freeze(struct device *dev)

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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	if (drv && drv->pm) {
@@ -553,15 +550,14 @@ static int pci_pm_thaw(struct device *dev)

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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	if (drv && drv->pm) {
		if (drv->pm->thaw_noirq)
			error = drv->pm->thaw_noirq(dev);
	} else {
		pci_fixup_device(pci_fixup_resume_early, pci_dev);
		pci_fixup_device(pci_fixup_resume_early, to_pci_dev(dev));
		error = pci_legacy_resume_early(dev);
	}

@@ -589,8 +585,7 @@ static int pci_pm_poweroff(struct device *dev)

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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	if (drv && drv->pm) {
@@ -625,7 +620,7 @@ static int pci_pm_restore(struct device *dev)
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;
	struct device_driver *drv = dev->driver;
	int error = 0;

	pci_fixup_device(pci_fixup_resume, pci_dev);
@@ -654,8 +649,7 @@ static int pci_pm_restore_noirq(struct device *dev)

#endif /* !CONFIG_HIBERNATION */

struct pm_ext_ops pci_pm_ops = {
	.base = {
struct dev_pm_ops pci_dev_pm_ops = {
	.prepare = pci_pm_prepare,
	.complete = pci_pm_complete,
	.suspend = pci_pm_suspend,
@@ -664,7 +658,6 @@ struct pm_ext_ops pci_pm_ops = {
	.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,
@@ -673,7 +666,7 @@ struct pm_ext_ops pci_pm_ops = {
	.restore_noirq = pci_pm_restore_noirq,
};

#define PCI_PM_OPS_PTR	&pci_pm_ops
#define PCI_PM_OPS_PTR	(&pci_dev_pm_ops)

#else /* !CONFIG_PM_SLEEP */

@@ -703,9 +696,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
	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);

+2 −2
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@ static int usb_dev_restore(struct device *dev)
	return usb_resume(dev);
}

static struct pm_ops usb_device_pm_ops = {
static struct dev_pm_ops usb_device_pm_ops = {
	.prepare =	usb_dev_prepare,
	.complete =	usb_dev_complete,
	.suspend =	usb_dev_suspend,
@@ -301,7 +301,7 @@ static struct pm_ops usb_device_pm_ops = {

#define ksuspend_usb_init()	0
#define ksuspend_usb_cleanup()	do {} while (0)
#define usb_device_pm_ops	(*(struct pm_ops *)0)
#define usb_device_pm_ops	(*(struct dev_pm_ops *)0)

#endif	/* CONFIG_PM */

+4 −4
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ struct bus_type {
	int (*resume_early)(struct device *dev);
	int (*resume)(struct device *dev);

	struct pm_ext_ops *pm;
	struct dev_pm_ops *pm;

	struct bus_type_private *p;
};
@@ -133,7 +133,7 @@ struct device_driver {
	int (*resume) (struct device *dev);
	struct attribute_group **groups;

	struct pm_ops *pm;
	struct dev_pm_ops *pm;

	struct driver_private *p;
};
@@ -198,7 +198,7 @@ struct class {
	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	struct pm_ops *pm;
	struct dev_pm_ops *pm;
	struct class_private *p;
};

@@ -291,7 +291,7 @@ struct device_type {
	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	struct pm_ops *pm;
	struct dev_pm_ops *pm;
};

/* interface for exporting device attributes */
Loading