1

モジュールのロード中にGPIOピンをオンにする簡単なLinuxカーネルドライバーを作成しようとしています。モジュールのロードは機能しますが、rmmodを呼び出してモジュールを削除すると、次のエラーが発生します。

sudo rmmod psctl
[13051.599199] ------------[ cut here ]------------
[13051.608758] WARNING: at drivers/base/core.c:196 device_release+0x78/0x84()
[13051.620581] Device 'psctl.0' does not have a release() function, it is broken and must be fixed.
[13051.637898] Modules linked in: psctl(O-) tmp102 hwmon nfsd rtc_ds1307 i2c_dev snd_bcm2835 snd_pcm snd_page_alloc snd_seq snd_seq_device snd_timer snd spidev leds_gpio led_class spi_bcm2708 i2c_bcm2708 [last unloaded: psctl]
[13051.670268] [<c0013f64>] (unwind_backtrace+0x0/0xf0) from [<c001e80c>] (warn_slowpath_common+0x4c/0x64)
[13051.688743] [<c001e80c>] (warn_slowpath_common+0x4c/0x64) from [<c001e8b8>] (warn_slowpath_fmt+0x30/0x40)
[13051.707217] [<c001e8b8>] (warn_slowpath_fmt+0x30/0x40) from [<c0239240>] (device_release+0x78/0x84)
[13051.725132] [<c0239240>] (device_release+0x78/0x84) from [<c01f4ad8>] (kobject_release+0x50/0x84)
[13051.742880] [<c01f4ad8>] (kobject_release+0x50/0x84) from [<bf0e6064>] (gpiotest_exit+0x10/0x2c [psctl])
[13051.761326] [<bf0e6064>] (gpiotest_exit+0x10/0x2c [psctl]) from [<c005e140>] (sys_delete_module+0x1b4/0x240)
[13051.780050] [<c005e140>] (sys_delete_module+0x1b4/0x240) from [<c000dae0>] (ret_fast_syscall+0x0/0x30)
[13051.798205] ---[ end trace 2eaa6df2dbf1f2e2 ]---
[13051.810083] psctl: Unloaded module

これは何を意味するのでしょうか?drivers / base / core.cを調べましたが、kobjectとkobj_typeのどちらにもリリースメソッドが関連付けられていないようです(またはkobjにkobj_typeが設定されていません)。私は自分でリリース方法を設定することになっていますか、それとも私がこれを設定するために私が行っていない何かがありますか?

モジュールのコードは次のとおりです。

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/slab.h>
    #include <linux/device.h>
    #include <linux/types.h>
    #include <linux/fs.h>
    #include <linux/platform_device.h>

    #define AUTHOR "Xian Stannard <xian@xianic.net>"
    #define DESCRIPTION "Simple GPIO driver as proof of concept"
    #define VERSION "0.1"
    #define DRIVER_NAME "psctl"
    #define OUT_GPIO 18

    #define MPRINT(level, fmt, args...) printk(level DRIVER_NAME ": " fmt "\n", ## args)

    struct ps_data_struct {
        int out_gpio;
    };

    static int ps_probe(struct platform_device *pdev) {
        struct ps_data_struct *data = pdev->dev.platform_data;

        if(data == NULL)
            MPRINT(KERN_DEBUG, "No platform data");
        else {
            MPRINT(KERN_DEBUG, "Has platform data: gpio %d", data->out_gpio);
        }

        return -ENODEV;
    }

    static int __exit ps_remove(struct platform_device *dev) {
        MPRINT(KERN_DEBUG, "Remove");
        return 0;
    }

    static void ps_release(struct device* dev) {
        MPRINT(KERN_DEBUG, "Release");
    }

    static struct ps_data_struct ps_data = {
        .out_gpio = OUT_GPIO
    };

    static struct platform_driver ps_driver = {
        .driver = {
            .name = DRIVER_NAME,
            .owner = THIS_MODULE
        },
        .probe = ps_probe,
        .remove = __exit_p(ps_remove)
    };

    static struct platform_device ps_device = {
        .name = DRIVER_NAME,
        .id = 0,
        .dev = {
            .platform_data = &ps_data
        }
    };

    static int __init gpiotest_init(void) {
        int retval = 0;

        retval = platform_driver_register(&ps_driver);
        if(retval != 0) {
            MPRINT(KERN_ERR, "Could not register driver");
            goto drvreg;
        }

        retval = platform_device_register(&ps_device);
        if(retval != 0) {
            MPRINT(KERN_ERR, "Could not create device");
            goto devreg;
        }

        MPRINT(KERN_INFO, "Loaded module");
        return 0;

    devreg:
        platform_driver_unregister(&ps_driver);

    drvreg:
        MPRINT(KERN_ERR, "Module load failed with error code %d", retval);
        return retval;
    }

    static void __exit gpiotest_exit(void) {
        platform_device_unregister(&ps_device);
        platform_driver_unregister(&ps_driver);
        MPRINT(KERN_INFO, "Unloaded module");
    }

    module_init(gpiotest_init);
    module_exit(gpiotest_exit);

    MODULE_AUTHOR(AUTHOR);
    MODULE_DESCRIPTION(DESCRIPTION);
    MODULE_VERSION(VERSION);
    MODULE_LICENSE("GPL");
4

2 に答える 2

5

platform_device_register()デバイスを登録するために使用すると思いますpdev->dev->releaseが、初期化されていないため、このデバイスを削除しようとすると、OOPS メッセージが出力されます。この問題を解決するには、次の 2 つの解決策があります。

  1. platform_device_alloc()とを使用しplatform_device_add()てデバイスを登録する。

  2. ps_device.dev.releaseを使用することを主張する場合は、自分自身を初期化しますplatform_device_register()

于 2013-03-23T10:22:16.937 に答える