OSDN Git Service

staging: axis-fifo: convert to use miscdevice
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Sep 2021 11:40:44 +0000 (13:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Sep 2021 06:49:53 +0000 (08:49 +0200)
Using a struct class, a cdev, and another device just for a single minor
device is total overkill.  Just use a dynamic misc device instead,
saving lots of logic and memory.

Cc: Jacob Feder <jacobsfeder@gmail.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Muhammad Usama Anjum <musamaanjum@gmail.com>
Link: https://lore.kernel.org/r/YTdPvBgKW6cKYrvb@kroah.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/axis-fifo/axis-fifo.c

index b23eabb..632f140 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/jiffies.h>
+#include <linux/miscdevice.h>
 
 #include <linux/of_address.h>
 #include <linux/of_device.h>
  *           globals
  * ----------------------------
  */
-
-static struct class *axis_fifo_driver_class; /* char device class */
-
 static int read_timeout = 1000; /* ms to wait before read() times out */
 static int write_timeout = 1000; /* ms to wait before write() times out */
 
@@ -140,9 +138,7 @@ struct axis_fifo {
        unsigned int read_flags; /* read file flags */
 
        struct device *dt_device; /* device created from the device tree */
-       struct device *device; /* device associated with char_device */
-       dev_t devt; /* our char device number */
-       struct cdev char_device; /* our char device */
+       struct miscdevice miscdev;
 };
 
 /* ----------------------------
@@ -319,6 +315,11 @@ static const struct attribute_group axis_fifo_attrs_group = {
        .attrs = axis_fifo_attrs,
 };
 
+static const struct attribute_group *axis_fifo_attrs_groups[] = {
+       &axis_fifo_attrs_group,
+       NULL,
+};
+
 /* ----------------------------
  *        implementation
  * ----------------------------
@@ -684,8 +685,8 @@ static irqreturn_t axis_fifo_irq(int irq, void *dw)
 
 static int axis_fifo_open(struct inode *inod, struct file *f)
 {
-       struct axis_fifo *fifo = (struct axis_fifo *)container_of(inod->i_cdev,
-                                       struct axis_fifo, char_device);
+       struct axis_fifo *fifo = container_of(f->private_data,
+                                             struct axis_fifo, miscdev);
        f->private_data = fifo;
 
        if (((f->f_flags & O_ACCMODE) == O_WRONLY) ||
@@ -812,9 +813,7 @@ static int axis_fifo_probe(struct platform_device *pdev)
        struct resource *r_mem; /* IO mem resources */
        struct device *dev = &pdev->dev; /* OS device (from device tree) */
        struct axis_fifo *fifo = NULL;
-
-       char device_name[32];
-
+       char *device_name;
        int rc = 0; /* error return value */
 
        /* ----------------------------
@@ -822,8 +821,12 @@ static int axis_fifo_probe(struct platform_device *pdev)
         * ----------------------------
         */
 
+       device_name = devm_kzalloc(dev, 32, GFP_KERNEL);
+       if (!device_name)
+               return -ENOMEM;
+
        /* allocate device wrapper memory */
-       fifo = devm_kmalloc(dev, sizeof(*fifo), GFP_KERNEL);
+       fifo = devm_kzalloc(dev, sizeof(*fifo), GFP_KERNEL);
        if (!fifo)
                return -ENOMEM;
 
@@ -859,9 +862,7 @@ static int axis_fifo_probe(struct platform_device *pdev)
        dev_dbg(fifo->dt_device, "remapped memory to 0x%p\n", fifo->base_addr);
 
        /* create unique device name */
-       snprintf(device_name, sizeof(device_name), "%s_%pa",
-                DRIVER_NAME, &r_mem->start);
-
+       snprintf(device_name, 32, "%s_%pa", DRIVER_NAME, &r_mem->start);
        dev_dbg(fifo->dt_device, "device name [%s]\n", device_name);
 
        /* ----------------------------
@@ -904,51 +905,21 @@ static int axis_fifo_probe(struct platform_device *pdev)
         * ----------------------------
         */
 
-       /* allocate device number */
-       rc = alloc_chrdev_region(&fifo->devt, 0, 1, DRIVER_NAME);
+       /* create character device */
+       fifo->miscdev.fops = &fops;
+       fifo->miscdev.minor = MISC_DYNAMIC_MINOR;
+       fifo->miscdev.name = device_name;
+       fifo->miscdev.groups = axis_fifo_attrs_groups;
+       fifo->miscdev.parent = dev;
+       rc = misc_register(&fifo->miscdev);
        if (rc < 0)
                goto err_initial;
-       dev_dbg(fifo->dt_device, "allocated device number major %i minor %i\n",
-               MAJOR(fifo->devt), MINOR(fifo->devt));
-
-       /* create driver file */
-       fifo->device = device_create(axis_fifo_driver_class, NULL, fifo->devt,
-                                    NULL, device_name);
-       if (IS_ERR(fifo->device)) {
-               dev_err(fifo->dt_device,
-                       "couldn't create driver file\n");
-               rc = PTR_ERR(fifo->device);
-               goto err_chrdev_region;
-       }
-       dev_set_drvdata(fifo->device, fifo);
-
-       /* create character device */
-       cdev_init(&fifo->char_device, &fops);
-       rc = cdev_add(&fifo->char_device, fifo->devt, 1);
-       if (rc < 0) {
-               dev_err(fifo->dt_device, "couldn't create character device\n");
-               goto err_dev;
-       }
-
-       /* create sysfs entries */
-       rc = devm_device_add_group(fifo->device, &axis_fifo_attrs_group);
-       if (rc < 0) {
-               dev_err(fifo->dt_device, "couldn't register sysfs group\n");
-               goto err_cdev;
-       }
 
-       dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i, major=%i, minor=%i\n",
-                &r_mem->start, &fifo->base_addr, fifo->irq,
-                MAJOR(fifo->devt), MINOR(fifo->devt));
+       dev_info(fifo->dt_device, "axis-fifo created at %pa mapped to 0x%pa, irq=%i\n",
+                &r_mem->start, &fifo->base_addr, fifo->irq);
 
        return 0;
 
-err_cdev:
-       cdev_del(&fifo->char_device);
-err_dev:
-       device_destroy(axis_fifo_driver_class, fifo->devt);
-err_chrdev_region:
-       unregister_chrdev_region(fifo->devt, 1);
 err_initial:
        dev_set_drvdata(dev, NULL);
        return rc;
@@ -959,10 +930,7 @@ static int axis_fifo_remove(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct axis_fifo *fifo = dev_get_drvdata(dev);
 
-       cdev_del(&fifo->char_device);
-       dev_set_drvdata(fifo->device, NULL);
-       device_destroy(axis_fifo_driver_class, fifo->devt);
-       unregister_chrdev_region(fifo->devt, 1);
+       misc_deregister(&fifo->miscdev);
        dev_set_drvdata(dev, NULL);
 
        return 0;
@@ -987,9 +955,6 @@ static int __init axis_fifo_init(void)
 {
        pr_info("axis-fifo driver loaded with parameters read_timeout = %i, write_timeout = %i\n",
                read_timeout, write_timeout);
-       axis_fifo_driver_class = class_create(THIS_MODULE, DRIVER_NAME);
-       if (IS_ERR(axis_fifo_driver_class))
-               return PTR_ERR(axis_fifo_driver_class);
        return platform_driver_register(&axis_fifo_driver);
 }
 
@@ -998,7 +963,6 @@ module_init(axis_fifo_init);
 static void __exit axis_fifo_exit(void)
 {
        platform_driver_unregister(&axis_fifo_driver);
-       class_destroy(axis_fifo_driver_class);
 }
 
 module_exit(axis_fifo_exit);