dev/watchdog和dev/watchdog0 是同一个设备

来源:互联网 发布:微赢专业数据代理平台 编辑:程序博客网 时间:2024/06/11 09:33
dev/watchdog 下会有watchdog 和 watchdog0等等。这里先给出结论watchdog和watchdog0代表的是同一个硬件,即使他们的字符设备的major和minor 不一样
linux-hice:~ # ls /dev/watchdog
watchdog   watchdog0  watchdog1  


linux-hice:/dev # ls -al | grep watchdog
crw-------   1 root root     10, 130 Jun  7 04:38 watchdog
crw-------   1 root root    252,   0 Jun  7 04:38 watchdog0
crw-------   1 root root    252,   1 Jun  7 04:38 watchdog1

一般在watchdog的probe函数中都会调用watchdog_register_device 来在dev下注册设备,就是如上面的/dev/watchdog等
watchdog_register_device->__watchdog_register_device->watchdog_dev_register
int watchdog_dev_register(struct watchdog_device *wdd)
{
    struct device *dev;
    dev_t devno;
    int ret;

    devno = MKDEV(MAJOR(watchdog_devt), wdd->id);

    ret = watchdog_cdev_register(wdd, devno);
    if (ret)
        return ret;
//这里就注册dev/watchdog0
    dev = device_create_with_groups(&watchdog_class, wdd->parent,
                    devno, wdd, wdd->groups,
                    "watchdog%d", wdd->id);
    if (IS_ERR(dev)) {
        watchdog_cdev_unregister(wdd);
        return PTR_ERR(dev);
    }

    ret = watchdog_register_pretimeout(wdd);
    if (ret) {
        device_destroy(&watchdog_class, devno);
        watchdog_cdev_unregister(wdd);
    }

    return ret;
}

static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno)
{
    struct watchdog_core_data *wd_data;
    int err;

    wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL);
    if (!wd_data)
        return -ENOMEM;
    kref_init(&wd_data->kref);
    mutex_init(&wd_data->lock);

    wd_data->wdd = wdd;
    wdd->wd_data = wd_data;

    if (!watchdog_wq)
        return -ENODEV;

    INIT_DELAYED_WORK(&wd_data->work, watchdog_ping_work);
//如果id是0的话,就调用misc_register 来注册/dev/watchdog,注意这个/dev/watchdog 对应的watchdog_device *wdd 和调用cdev_add 添加的字符设备用的同一个watchdog_device *wdd,所以才说他们对应的是同一个hw,以上层应用不管是打开dev/watchdog还是dev/watchdog0 都是一样的.
    if (wdd->id == 0) {
        old_wd_data = wd_data;
        watchdog_miscdev.parent = wdd->parent;
        err = misc_register(&watchdog_miscdev);
        if (err != 0) {
            pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
                wdd->info->identity, WATCHDOG_MINOR, err);
            if (err == -EBUSY)
                pr_err("%s: a legacy watchdog module is probably present.\n",
                    wdd->info->identity);
            old_wd_data = NULL;
            kfree(wd_data);
            return err;
        }
    }

    /* Fill in the data structures */
    cdev_init(&wd_data->cdev, &watchdog_fops);
    wd_data->cdev.owner = wdd->ops->owner;

    /* Add the device */
    err = cdev_add(&wd_data->cdev, devno, 1);
    if (err) {
        pr_err("watchdog%d unable to add device %d:%d\n",
            wdd->id,  MAJOR(watchdog_devt), wdd->id);
        if (wdd->id == 0) {
            misc_deregister(&watchdog_miscdev);
            old_wd_data = NULL;
            kref_put(&wd_data->kref, watchdog_core_data_release);
        }
        return err;
    }

    /* Record time of most recent heartbeat as 'just before now'. */
    wd_data->last_hw_keepalive = jiffies - 1;

    /*
     * If the watchdog is running, prevent its driver from being unloaded,
     * and schedule an immediate ping.
     */
    if (watchdog_hw_running(wdd)) {
        __module_get(wdd->ops->owner);
        kref_get(&wd_data->kref);
        queue_delayed_work(watchdog_wq, &wd_data->work, 0);
    }

    return 0;
}
之所以要注册/dev/watchog 是为来兼容老的接口
原创粉丝点击