Some of the device files are required to be user accessible for PSM while most should remain accessible only by root. Add a parameter to hfi1_cdev_init which controls if the user should have access to this device which places it in a different class with the appropriate devnode callback. In addition set the devnode call back for the existing class to be a bit more explicit for those permissions. Finally remove the unnecessary null check before class_destroy
Unified · Split
| @@ -57,11 +57,13 @@ · 56 unmodified lines | ||
| 57 | 57 | #include "device.h" |
| 58 | 58 | |
| 59 | 59 | static struct class *class; |
| 60 | +static struct class *user_class; | |
| 60 | 61 | static dev_t hfi1_dev; |
| 61 | 62 | |
| 62 | 63 | int hfi1_cdev_init(int minor, const char *name, |
| 63 | 64 | const struct file_operations *fops, |
| 64 | − struct cdev *cdev, struct device **devp) | |
| 65 | + struct cdev *cdev, struct device **devp, | |
| 66 | + bool user_accessible) | |
| 65 | 67 | { |
| 66 | 68 | const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor); |
| 67 | 69 | struct device *device = NULL; |
| @@ -78,7 +80,11 @@ int hfi1_cdev_init(int minor, const char *name, · 10 unmodified lines | ||
| 78 | 80 | goto done; |
| 79 | 81 | } |
| 80 | 82 | |
| 81 | − device = device_create(class, NULL, dev, NULL, "%s", name); | |
| 83 | + if (user_accessible) | |
| 84 | + device = device_create(user_class, NULL, dev, NULL, "%s", name); | |
| 85 | + else | |
| 86 | + device = device_create(class, NULL, dev, NULL, "%s", name); | |
| 87 | + | |
| 82 | 88 | if (!IS_ERR(device)) |
| 83 | 89 | goto done; |
| 84 | 90 | ret = PTR_ERR(device); |
| @@ -110,6 +116,26 @@ const char *class_name(void) · 25 unmodified lines | ||
| 110 | 116 | return hfi1_class_name; |
| 111 | 117 | } |
| 112 | 118 | |
| 119 | +static char *hfi1_devnode(struct device *dev, umode_t *mode) | |
| 120 | +{ | |
| 121 | + if (mode) | |
| 122 | + *mode = 0600; | |
| 123 | + return kasprintf(GFP_KERNEL, "%s", dev_name(dev)); | |
| 124 | +} | |
| 125 | + | |
| 126 | +static const char *hfi1_class_name_user = "hfi1_user"; | |
| 127 | +const char *class_name_user(void) | |
| 128 | +{ | |
| 129 | + return hfi1_class_name_user; | |
| 130 | +} | |
| 131 | + | |
| 132 | +static char *hfi1_user_devnode(struct device *dev, umode_t *mode) | |
| 133 | +{ | |
| 134 | + if (mode) | |
| 135 | + *mode = 0666; | |
| 136 | + return kasprintf(GFP_KERNEL, "%s", dev_name(dev)); | |
| 137 | +} | |
| 138 | + | |
| 113 | 139 | int __init dev_init(void) |
| 114 | 140 | { |
| 115 | 141 | int ret; |
| @@ -125,7 +151,22 @@ int __init dev_init(void) · 9 unmodified lines | ||
| 125 | 151 | ret = PTR_ERR(class); |
| 126 | 152 | pr_err("Could not create device class (err %d)\n", -ret); |
| 127 | 153 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); |
| 154 | + goto done; | |
| 128 | 155 | } |
| 156 | + class->devnode = hfi1_devnode; | |
| 157 | + | |
| 158 | + user_class = class_create(THIS_MODULE, class_name_user()); | |
| 159 | + if (IS_ERR(user_class)) { | |
| 160 | + ret = PTR_ERR(user_class); | |
| 161 | + pr_err("Could not create device class for user accessible files (err %d)\n", | |
| 162 | + -ret); | |
| 163 | + class_destroy(class); | |
| 164 | + class = NULL; | |
| 165 | + user_class = NULL; | |
| 166 | + unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); | |
| 167 | + goto done; | |
| 168 | + } | |
| 169 | + user_class->devnode = hfi1_user_devnode; | |
| 129 | 170 | |
| 130 | 171 | done: |
| 131 | 172 | return ret; |
| @@ -133,10 +174,11 @@ done: · 1 unmodified line | ||
| 133 | 174 | |
| 134 | 175 | void dev_cleanup(void) |
| 135 | 176 | { |
| 136 | − if (class) { | |
| 137 | − class_destroy(class); | |
| 138 | − class = NULL; | |
| 139 | − } | |
| 177 | + class_destroy(class); | |
| 178 | + class = NULL; | |
| 179 | + | |
| 180 | + class_destroy(user_class); | |
| 181 | + user_class = NULL; | |
| 140 | 182 | |
| 141 | 183 | unregister_chrdev_region(hfi1_dev, HFI1_NMINORS); |
| 142 | 184 | } |
| @@ -52,7 +52,8 @@ · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | int hfi1_cdev_init(int minor, const char *name, |
| 54 | 54 | const struct file_operations *fops, |
| 55 | − struct cdev *cdev, struct device **devp); | |
| 55 | + struct cdev *cdev, struct device **devp, | |
| 56 | + bool user_accessible); | |
| 56 | 57 | void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp); |
| 57 | 58 | const char *class_name(void); |
| 58 | 59 | int __init dev_init(void); |
| @@ -292,7 +292,7 @@ int hfi1_diag_add(struct hfi1_devdata *dd) · 291 unmodified lines | ||
| 292 | 292 | if (atomic_inc_return(&diagpkt_count) == 1) { |
| 293 | 293 | ret = hfi1_cdev_init(HFI1_DIAGPKT_MINOR, name, |
| 294 | 294 | &diagpkt_file_ops, &diagpkt_cdev, |
| 295 | − &diagpkt_device); | |
| 295 | + &diagpkt_device, false); | |
| 296 | 296 | } |
| 297 | 297 | |
| 298 | 298 | return ret; |
| @@ -592,7 +592,8 @@ static int hfi1_snoop_add(struct hfi1_devdata *dd, const char *name) · 293 unmodified lines | ||
| 592 | 592 | |
| 593 | 593 | ret = hfi1_cdev_init(HFI1_SNOOP_CAPTURE_BASE + dd->unit, name, |
| 594 | 594 | &snoop_file_ops, |
| 595 | − &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev); | |
| 595 | + &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev, | |
| 596 | + false); | |
| 596 | 597 | |
| 597 | 598 | if (ret) { |
| 598 | 599 | dd_dev_err(dd, "Couldn't create %s device: %d", name, ret); |
| @@ -2090,14 +2090,16 @@ static int user_add(struct hfi1_devdata *dd) · 2089 unmodified lines | ||
| 2090 | 2090 | |
| 2091 | 2091 | if (atomic_inc_return(&user_count) == 1) { |
| 2092 | 2092 | ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops, |
| 2093 | − &wildcard_cdev, &wildcard_device); | |
| 2093 | + &wildcard_cdev, &wildcard_device, | |
| 2094 | + true); | |
| 2094 | 2095 | if (ret) |
| 2095 | 2096 | goto done; |
| 2096 | 2097 | } |
| 2097 | 2098 | |
| 2098 | 2099 | snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit); |
| 2099 | 2100 | ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops, |
| 2100 | − &dd->user_cdev, &dd->user_device); | |
| 2101 | + &dd->user_cdev, &dd->user_device, | |
| 2102 | + true); | |
| 2101 | 2103 | if (ret) |
| 2102 | 2104 | goto done; |
| 2103 | 2105 | |
| @@ -2105,7 +2107,8 @@ static int user_add(struct hfi1_devdata *dd) · 1 unmodified line | ||
| 2105 | 2107 | snprintf(name, sizeof(name), |
| 2106 | 2108 | "%s_ui%d", class_name(), dd->unit); |
| 2107 | 2109 | ret = hfi1_cdev_init(dd->unit + UI_OFFSET, name, &ui_file_ops, |
| 2108 | − &dd->ui_cdev, &dd->ui_device); | |
| 2110 | + &dd->ui_cdev, &dd->ui_device, | |
| 2111 | + false); | |
| 2109 | 2112 | if (ret) |
| 2110 | 2113 | goto done; |
| 2111 | 2114 | } |