Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2015, 2016 Intel Corporation.
0004  */
0005 
0006 #include <linux/cdev.h>
0007 #include <linux/device.h>
0008 #include <linux/fs.h>
0009 
0010 #include "hfi.h"
0011 #include "device.h"
0012 
0013 static struct class *class;
0014 static struct class *user_class;
0015 static dev_t hfi1_dev;
0016 
0017 int hfi1_cdev_init(int minor, const char *name,
0018            const struct file_operations *fops,
0019            struct cdev *cdev, struct device **devp,
0020            bool user_accessible,
0021            struct kobject *parent)
0022 {
0023     const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor);
0024     struct device *device = NULL;
0025     int ret;
0026 
0027     cdev_init(cdev, fops);
0028     cdev->owner = THIS_MODULE;
0029     cdev_set_parent(cdev, parent);
0030     kobject_set_name(&cdev->kobj, name);
0031 
0032     ret = cdev_add(cdev, dev, 1);
0033     if (ret < 0) {
0034         pr_err("Could not add cdev for minor %d, %s (err %d)\n",
0035                minor, name, -ret);
0036         goto done;
0037     }
0038 
0039     if (user_accessible)
0040         device = device_create(user_class, NULL, dev, NULL, "%s", name);
0041     else
0042         device = device_create(class, NULL, dev, NULL, "%s", name);
0043 
0044     if (IS_ERR(device)) {
0045         ret = PTR_ERR(device);
0046         device = NULL;
0047         pr_err("Could not create device for minor %d, %s (err %d)\n",
0048             minor, name, -ret);
0049         cdev_del(cdev);
0050     }
0051 done:
0052     *devp = device;
0053     return ret;
0054 }
0055 
0056 void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp)
0057 {
0058     struct device *device = *devp;
0059 
0060     if (device) {
0061         device_unregister(device);
0062         *devp = NULL;
0063 
0064         cdev_del(cdev);
0065     }
0066 }
0067 
0068 static const char *hfi1_class_name = "hfi1";
0069 
0070 const char *class_name(void)
0071 {
0072     return hfi1_class_name;
0073 }
0074 
0075 static char *hfi1_devnode(struct device *dev, umode_t *mode)
0076 {
0077     if (mode)
0078         *mode = 0600;
0079     return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
0080 }
0081 
0082 static const char *hfi1_class_name_user = "hfi1_user";
0083 static const char *class_name_user(void)
0084 {
0085     return hfi1_class_name_user;
0086 }
0087 
0088 static char *hfi1_user_devnode(struct device *dev, umode_t *mode)
0089 {
0090     if (mode)
0091         *mode = 0666;
0092     return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
0093 }
0094 
0095 int __init dev_init(void)
0096 {
0097     int ret;
0098 
0099     ret = alloc_chrdev_region(&hfi1_dev, 0, HFI1_NMINORS, DRIVER_NAME);
0100     if (ret < 0) {
0101         pr_err("Could not allocate chrdev region (err %d)\n", -ret);
0102         goto done;
0103     }
0104 
0105     class = class_create(THIS_MODULE, class_name());
0106     if (IS_ERR(class)) {
0107         ret = PTR_ERR(class);
0108         pr_err("Could not create device class (err %d)\n", -ret);
0109         unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
0110         goto done;
0111     }
0112     class->devnode = hfi1_devnode;
0113 
0114     user_class = class_create(THIS_MODULE, class_name_user());
0115     if (IS_ERR(user_class)) {
0116         ret = PTR_ERR(user_class);
0117         pr_err("Could not create device class for user accessible files (err %d)\n",
0118                -ret);
0119         class_destroy(class);
0120         class = NULL;
0121         user_class = NULL;
0122         unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
0123         goto done;
0124     }
0125     user_class->devnode = hfi1_user_devnode;
0126 
0127 done:
0128     return ret;
0129 }
0130 
0131 void dev_cleanup(void)
0132 {
0133     class_destroy(class);
0134     class = NULL;
0135 
0136     class_destroy(user_class);
0137     user_class = NULL;
0138 
0139     unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
0140 }