最近在看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
今天的文章platform_driver->suspend 和platform_driver-pm->suspend的区别分析分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/26202.html