Re: sysfs in cdev

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Greg KH wrote:

Are you suggesting that I should embedd both struct cdev and struct device in my struct my_device?


Um, no.  The bus your device is on should take care of the struct device
stuff.  What kind of driver are you writing?  Have a pointer to the
code?

It is SPI datakey flash device driver. I originaly put it the mtd subsystem but didn't 'like' it since the device can be removed and mtd partition would not be deleted sometimes (when device is removed) and I don't use anykind of FS on top of raw flash anyway. So I'm writing char device with read/write/erase functions accessible from userspace via read/write/ioctl syscalls. I've chosen platform device (since this driver is meant for embedded device).

My struct my_device:
struct datakey_info {
        int valid;
        struct flash_info *fl_info;
        struct erase_info er_info;
        struct semaphore sem;           /* mutual exclusion semaphore     */
};

What I do now is (no cdev here):

- define file operations and put them in struct file_operations 'datakey_fops'
struct file_operations datakey_fops = {
        .owner          = THIS_MODULE,
        .open           = datakey_open,
//      .release        = datakey_release,
        .read           = datakey_read,
        .write          = datakey_write,
        .ioctl          = datakey_ioctl,
        .llseek         = datakey_llseek,
};

- define struct device_driver
static struct device_driver datakey_platform_driver = {
        .owner          = THIS_MODULE,
        .name           = "datakey",
        .bus            = &platform_bus_type,
        .probe          = datakey_probe,
        .remove         = datakey_remove,
};

- define struct platform_device
static struct platform_device datakey_platform_device = {
        .name   = "datakey",
        .id     = -1,
        .dev    = {
                        .release = datakey_release,
                  },
};

- in datakey_init (called by module_init) this gets done among other stuff
...
        /* register platform driver and device */
        ret = driver_register(&datakey_platform_driver);
        if (ret == 0) {
                ret = platform_device_register(&datakey_platform_device);
                if (ret) {
                        driver_unregister(&datakey_platform_driver);
                        printk(KERN_ERR "%s: coundn't register the device.\n",
                                        __FUNCTION__);
                        return ret;
                }
        }
        else {
                printk(KERN_ERR "%s: coudn't register the driver.\n",
                                __FUNCTION__);
                return ret;
        }

        /* register char device for userspace access */
        if (register_chrdev(datakey_major, "datakey", &datakey_fops)) {
                printk("%s: can't register datakey as char device\n",
                                __FUNCTION__);
                return -EAGAIN;
        }
...
(some timers, workqueues and other allocations)

- in datakey_probe:
static int
__init datakey_probe (struct device *device)
{
        struct platform_device *dev = to_platform_device(device);
        struct datakey_info *datakey = &datakey_data;

        /* zero-out the datakey_data */
        memset(datakey, 0, sizeof(struct datakey_info));
        init_MUTEX(&datakey->sem);

        if ( datakey_detect(datakey) )
                datakey_add();

        dev_set_drvdata(&dev->dev, datakey);

        device_create_file(&dev->dev, &dev_attr_reg_data);
        device_create_file(&dev->dev, &dev_attr_reg_status);
        device_create_file(&dev->dev, &dev_attr_reg_control);

        return 0;
}
(dev_attr_reg_xxx are created earlier...)



Otherwise I can't use cdev_init, cdev_add and similar for cdev registration if I'm understanding this right and need to use old-style (as seen in LDD3 chapter3.4.2. The Older Way) char device registration which it is supposed to be removed in the future.


No, you should use cdev, I never said you should not.  Only that a
struct cdev does not give you a place in sysfs to place your files,
that's all.

Oh, right.
Here is sample code that uses cdev, but no sysfs here:

Different my_device struct:
struct datakey_info {
        int valid;
        struct flash_info *fl_info;
        struct erase_info er_info;
        struct semaphore sem;           /* mutual exclusion semaphore     */
        struct cdev cdev;
};

- datakey_setup_cdev is called from init

static int
datakey_setup_cdev (struct datakey_info *datakey)
{
        int ret = 0;
        dev_t dev = 0;

        memset(datakey, 0, sizeof(struct datakey_info));
        init_MUTEX(&datakey->sem);

        cdev_init(&datakey->cdev, &datakey_fops);
        datakey->cdev.owner = THIS_MODULE;
        datakey->cdev.ops = &datakey_fops;

        if (datakey_major) {
                dev = MKDEV(datakey_major, datakey_minor);
                ret = register_chrdev_region(dev, 1, "datakey");
        }

        if (ret < 0) {
                printk(KERN_WARNING "%s: can't get major %d\n",
                                __FUNCTION__,  datakey_major);
                return ret;
        }

        ret = cdev_add(&datakey->cdev, dev, 1);
        if (ret) {
                printk("%s: error %d adding datakey cdev!\n",
                                        __FUNCTION__, ret);
                return ret;
        }

        return 0;
}

After reading http://lwn.net/Articles/50988/ I think kobject from cdev could be the way to go but I haven't ever digged that deep in the kernel subsystems.

Thanks for your time,
hinko


--
hinko <dot> kocevar <at> iskramedical <dot> si
Hinko Kocevar, embedded systems developer
Iskra Medical d.o.o., Stegne 23, 1k LJ, SLO-EU

	"Aì rén"	|	[Analects XII:22]

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux