Search code examples
clinux-kernellinux-device-driverembedded-linux

How to initialize device's class when register device in linux-6.0


I register bus, driver and device, and I want to register a class, then I initialize device's class before register device, that emit a error: "don't try to register things with the same name in the same directory". I think the code is OK, and if I not to initialize device's class, that is OK, and it works well. But now I want to create a class to go for it. Can you give me some suggestions?

The code is this:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>           
#include <linux/device.h>
#include <linux/device/driver.h>
#include <linux/kobject.h>  
#include <linux/sysfs.h>   

static struct class test_class = {
    .name = "mytest_class",
    .owner = THIS_MODULE,
};


static int bus_match(struct device *dev, struct device_driver *drv)
{
    printk(KERN_INFO"In %s \n", __func__);
    //match by driver name and device name
    return (strcmp(dev_name(dev), drv->name) == 0);
}

static int bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
    int ret=1;
    printk(KERN_INFO "%s hotplug\n", dev_name(dev));
    ret = add_uevent_var(env, "THIS_TEST=%s", dev_name(dev));
    if(ret)
    {
        return ret;
    }
    return add_uevent_var(env, "EVENT=%s", "change");
}

static int bus_probe(struct device *dev)
{
    return dev->driver->probe(dev);
    return 0;
}

static void bus_remove(struct device *dev)
{
    dev->driver->remove(dev);
}

struct bus_type bus_test =
{
    .name  = "bus-test",
    .match = bus_match,
    .uevent= bus_uevent,
    .probe = bus_probe,
    .remove= bus_remove,
};
EXPORT_SYMBOL(bus_test);

static int driver_probe(struct device *dev)
{
    printk(KERN_INFO "driver probe!\n");
    return 0;
}

static int driver_remove(struct device *dev)
{
    printk(KERN_INFO "driver remove!\n");
    return 0;
}

static struct device_driver driver_test=
{
    .name = "driver_test",
    .bus  = &bus_test,
    .probe = driver_probe,
    .remove = driver_remove,
};

static void dev_test_release(struct device *dev)
{
    printk(KERN_INFO "device release!\n");
}

static struct device dev_test = {
    .init_name  = "driver_test",
    .bus        = &bus_test,
    .release    = dev_test_release,
};

static int __init init_driver_test(void)
{
    int ret = 0;
    printk(KERN_INFO "init module!\n");
    ret = bus_register(&bus_test);
    if (ret) {
        printk(KERN_ERR "bus register error!\n");
        return ret;
    }
    ret = class_register(&test_class);
    if (ret) {
        printk(KERN_ERR "class register error!\n");
        return ret;
    }
    dev_test.class      = &test_class,
    dev_test.devt=MKDEV(100, 1);
    ret = device_register(&dev_test);
    if(ret)
    {
        printk(KERN_ERR "device register error!\n");
        return ret;       
    }
    ret = driver_register(&driver_test);
    if (ret) {
        printk(KERN_ERR "driver register error!\n");
        return ret;
    }
    return ret;
}

static void __exit exit_driver_test(void)
{
    driver_unregister(&driver_test);
    device_unregister(&dev_test);
    class_unregister(&test_class);
    bus_unregister(&bus_test);
    printk(KERN_INFO "exit module!\n");
}
module_init(init_driver_test);
module_exit(exit_driver_test);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("NoError");
MODULE_DESCRIPTION("driver test");

I built it as module, and insmod it, it's falied, the error is:

# insmod driver_test.ko
[   48.663393] driver_test: loading out-of-tree module taints kernel.
[   48.669891] driver_test: module verification failed: signature and/or required key missing - tainting kernel
[   48.680389] init module!
[   48.683167] Driver 'driver_test' needs updating - please use bus_type methods
[   48.690549] sysfs: cannot create duplicate filename '/devices/virtual/rapidio_port/driver_test/subsystem'
[   48.700176] CPU: 3 PID: 326 Comm: insmod Tainted: G           OE      6.0.11 #3
[   48.707511] Hardware name: OrangePi Zero2 (DT)
[   48.711961] Call trace:
[   48.714412]  dump_backtrace+0xd8/0x120
[   48.718192]  show_stack+0x18/0x50
[   48.721524]  dump_stack_lvl+0x68/0x84
[   48.725201]  dump_stack+0x18/0x34
[   48.728526]  sysfs_warn_dup+0x60/0x80
[   48.732207]  sysfs_do_create_link_sd+0x138/0x140
[   48.736839]  sysfs_create_link+0x30/0x50
[   48.740777]  bus_add_device+0xf0/0x140
[   48.744542]  device_add+0x33c/0x8b0
[   48.748043]  device_register+0x20/0x30
[   48.751804]  init_driver_test+0x98/0x1000 [mdev_hotplug]
[   48.757143]  do_one_initcall+0x50/0x1c0
[   48.760990]  do_init_module+0x44/0x1d0
[   48.764757]  load_module+0x194c/0x1d50
[   48.768521]  __do_sys_finit_module+0xac/0x130
[   48.772893]  __arm64_sys_finit_module+0x20/0x30
[   48.777439]  invoke_syscall+0x48/0x120
[   48.781203]  el0_svc_common.constprop.0+0x44/0x100
[   48.786008]  do_el0_svc+0x30/0xd0
[   48.789336]  el0_svc+0x2c/0x90
[   48.792408]  el0t_64_sync_handler+0xbc/0x140
[   48.796695]  el0t_64_sync+0x18c/0x190
[   48.800461] driver_test hotplug
[   48.803709] device register error!
[   48.838788] init module!
[   48.841389] sysfs: cannot create duplicate filename '/bus/bus-test'
[   48.847754] CPU: 3 PID: 326 Comm: insmod Tainted: G           OE      6.0.11 #3
[   48.855077] Hardware name: OrangePi Zero2 (DT)
[   48.859524] Call trace:
[   48.861974]  dump_backtrace+0xd8/0x120
[   48.865753]  show_stack+0x18/0x50
[   48.869083]  dump_stack_lvl+0x68/0x84
[   48.872760]  dump_stack+0x18/0x34
[   48.876085]  sysfs_warn_dup+0x60/0x80
[   48.879765]  sysfs_create_dir_ns+0xec/0x110
[   48.883963]  kobject_add_internal+0xbc/0x3a0
[   48.888251]  kset_register+0x58/0x90
[   48.891840]  bus_register+0xc4/0x320
[   48.895432]  init_driver_test+0x2c/0x1000 [mdev_hotplug]
[   48.900769]  do_one_initcall+0x50/0x1c0
[   48.904616]  do_init_module+0x44/0x1d0
[   48.908382]  load_module+0x194c/0x1d50
[   48.912147]  __do_sys_init_module+0x20c/0x250
[   48.916519]  __arm64_sys_init_module+0x1c/0x30
[   48.920977]  invoke_syscall+0x48/0x120
[   48.924742]  el0_svc_common.constprop.0+0x44/0x100
[   48.929546]  do_el0_svc+0x30/0xd0
[   48.932874]  el0_svc+0x2c/0x90
[   48.935946]  el0t_64_sync_handler+0xbc/0x140
[   48.940232]  el0t_64_sync+0x18c/0x190
[   48.943965] kobject_add_internal failed for bus-test with -EEXIST, don't try to register things with the same name in the same directory.
[   48.956343] bus register error!
#

I think the code is ok, and it will create symlink in /sys/class for /sys/devices. But it's failed. I looked at some source code in linux kernel, but that is all using class_create and device_create, I had tried it and it's ok, but the device_create is not initializing device bus, so, the device will not match the driver.


Solution

  • This is a good top, the class is top level, and class is like a box which contains all device that are same kind. enter image description here