platform_driver->suspend 和platform_driver-pm->suspend的区别分析

最近在看Linux电源管理模块,发现在platform_driver下有suspend/resume函数,在platform_driver->pm-下也有suspend/resume函数。下面分析一下他们的区别。

先看两段代码。

static const struct dev_pm_ops s_atc260x_irkeypad_pm_ops = {
	.suspend = atc260x_irkeypad_suspend,
	.resume = atc260x_irkeypad_resume,
};


static struct platform_driver atc260x_irkeypad_driver = {
	.driver = {
		.name = "atc260x-irkeypad",
		.owner = THIS_MODULE,
		.pm = &s_atc260x_irkeypad_pm_ops,
		.of_match_table = of_match_ptr(atc260x_irkey_of_match),
	},
	.probe = atc260x_irkeypad_probe,
	.remove = atc260x_irkeypad_remove,
	.shutdown = atc260x_irkeypad_shutdown,
};

static struct platform_driver atc260x_adckeypad_driver = {
	.driver = {
		.name = "atc260x-adckeypad",
		.owner = THIS_MODULE,
		.of_match_table = of_match_ptr(atc260x_adckey_of_match),
	},
	.probe = atc260x_adckeypad_probe,
	.remove = atc260x_adckeypad_remove,
	.suspend = atc260x_adckeypad_suspend,
	.resume = atc260x_adckeypad_resume,
};

其中我们可以看到这两个驱动程序中对电源管理的方式不太一样。
接着我们去看下Linux源代码中对platform_driver结构体的定义。


Platform_device.h (kernel\include\linux)

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
};

structDevice.h (kernel\include\linux)
 device_driver {
	const char		*name;
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_match_table;

	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};
在这platform_driver 和device_driver中都定义了probe remove等函数。其中device_driver结构体又包含在platform_driver中,至此还是不明白为什么这样做。
接着去看下platform_driver_register(struct platform_driver *drv) 函数吧。
Platform.c (kernel\drivers\base)

int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;
	if (drv->remove)
		drv->driver.remove = platform_drv_remove;
	if (drv->shutdown)
		drv->driver.shutdown = platform_drv_shutdown;

	return driver_register(&drv->driver);
}
是不是很有意思,这里你会发现,最后device_driver中的probe remove等又指向了platform_driver的probe remove。
具体看下两个结构中的probe定义
int (*probe)(struct platform_device *);
int (*probe) (struct device *dev);


我贴出来的两段代码,第一段使用platform_driver.suspend/resume的方式来做电源管理,第二段采用platform_driver.driver.pm.suspend/resume的方式来做电源管理。如果追溯.suspend何时被调用就会找到 platform_pm_suspend函数,


plaPlatform.c (kernel\drivers\base)
int platform_pm_suspend(struct device *dev)
{
	struct device_driver *drv = dev->driver;
	int ret = 0;

	if (!drv)
		return 0;

	if (drv->pm) {
		if (drv->pm->suspend)
			ret = drv->pm->suspend(dev);
	} else {
		ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
	}

	return ret;
}
可以发现,如果driver->pm为空的话就回去调用platform_legacy_suspend,如果不为空的话就调用driver->pm。
static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
{
	struct platform_driver *pdrv = to_platform_driver(dev->driver);
	struct platform_device *pdev = to_platform_device(dev);
	int ret = 0;

	if (dev->driver && pdrv->suspend)
		ret = pdrv->suspend(pdev, mesg);

	return ret;
}
platform_legacy_suspend则是去调用platform_driver中的suspend。


第二方式是一种比较旧的方式,建议使用最新的dev_pm_ops方式来进行电源管理。


参考:https://www.cnblogs.com/swnuwangyun/p/4233821.html

猜你喜欢

转载自blog.csdn.net/u012830148/article/details/78667420