13 years C/C++/C# programing, focus on embedded and mobile device development.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

我们看到很多驱动中都没有设置shutdown回调函数,只提供了probe和remove回调函数:

static struct platform_driver wm8400_codec_driver = {
    .driver = {
           .name = "wm8400-codec",
           .owner = THIS_MODULE,
           },
    .probe = wm8400_probe,
    .remove = __devexit_p(wm8400_remove),
};
static struct platform_driver pcm3008_codec_driver = {
    .probe        = pcm3008_codec_probe,
    .remove        = __devexit_p(pcm3008_codec_remove),
    .driver        = {
        .name    = "pcm3008-codec",
        .owner    = THIS_MODULE,
    },
};

但是platform_driver中是有shutdown字段的,http://www.makelinux.net/ldd3/chp-14-sect-4 中有如下的描述:

Once again, several of the structure's fields have been omitted (see <linux/device.h> for the full story). Here, name is the name of the driver (it shows up in sysfs), bus is the type of bus this driver works with, kobj is the inevitable kobject, devices is a list of all devices currently bound to this driver, probe is a function called to query the existence of a specific device (and whether this driver can work with it), remove is called when the device is removed from the system, and shutdown is called at shutdown time to quiesce the device.

“quiesce” 说的也不太明确,我的猜测是:比如系统中有一个大功率的设备,在“软关机”的时候,会调用这个函数,可以在这个函数中切断这个设备的电源,从而省电。因为软关机后,机器本身是还有电的,并没有拔电源。

在内核中找了一个例子drivers/char/sonypi.c:

static struct platform_driver sonypi_driver = {
    .driver        = {
        .name    = "sonypi",
        .owner    = THIS_MODULE,
    },
    .probe        = sonypi_probe,
    .remove        = __devexit_p(sonypi_remove),
    .shutdown    = sonypi_shutdown,
    .suspend    = sonypi_suspend,
    .resume        = sonypi_resume,
};

其remove, shutdown, suspend的实现都差不多,就是禁用设备:

static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
{
    old_camera_power = sonypi_device.camera_power;
    sonypi_disable();

    return 0;
}
static void sonypi_shutdown(struct platform_device *dev)
{
    sonypi_disable();
}
static int __devexit sonypi_remove(struct platform_device *dev)
{
    sonypi_disable();

    synchronize_irq(sonypi_device.irq);
    flush_work_sync(&sonypi_device.input_work);

    if (useinput) {
        input_unregister_device(sonypi_device.input_key_dev);
        input_unregister_device(sonypi_device.input_jog_dev);
        kfifo_free(&sonypi_device.input_fifo);
    }

    misc_deregister(&sonypi_misc_device);

    free_irq(sonypi_device.irq, sonypi_irq);
    release_region(sonypi_device.ioport1, sonypi_device.region_size);

    if (sonypi_device.dev) {
        pci_disable_device(sonypi_device.dev);
        pci_dev_put(sonypi_device.dev);
    }

    kfifo_free(&sonypi_device.fifo);

    return 0;
}


三个函数都调用了sony_disable函数,remove做了更多的清理工作。

有一个驱动更绝drivers/char/ps3flash.c,其remove和shudown函数是公用的。

static struct ps3_system_bus_driver ps3flash = {
    .match_id    = PS3_MATCH_ID_STOR_FLASH,
    .core.name    = DEVICE_NAME,
    .core.owner    = THIS_MODULE,
    .probe        = ps3flash_probe,
    .remove        = ps3flash_remove,
    .shutdown    = ps3flash_remove,
};

难怪大部分的驱动都不提供这个shutdown函数,一方面是确实没有必要,另一方面关机后就什么都不管了:)

看了另外一篇文章后,补充一点:

shutdown: 彻底关电

suspend:休眠,可能是低功耗状态

resume:唤醒

 

posted on 2015-01-19 14:11  woaiusd  阅读(3094)  评论(0编辑  收藏  举报