Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: virtuser: new virtual testing driver for the GPIO API

The GPIO subsystem used to have a serious problem with undefined behavior
and use-after-free bugs on hot-unplug of GPIO chips. This can be
considered a corner-case by some as most GPIO controllers are enabled
early in the boot process and live until the system goes down but most
GPIO drivers do allow unbind over sysfs, many are loadable modules that
can be (force) unloaded and there are also GPIO devices that can be
dynamically detached, for instance CP2112 which is a USB GPIO expender.

Bugs can be triggered both from user-space as well as by in-kernel users.
We have the means of testing it from user-space via the character device
but the issues manifest themselves differently in the kernel.

This is a proposition of adding a new virtual driver - a configurable
GPIO consumer that can be configured over configfs (similarly to
gpio-sim) or described on the device-tree.

This driver is aimed as a helper in spotting any regressions in
hot-unplug handling in GPIOLIB.

Link: https://lore.kernel.org/r/20240708142912.120570-1-brgl@bgdev.pl
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

+1998
+177
Documentation/admin-guide/gpio/gpio-virtuser.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-only 2 + 3 + Virtual GPIO Consumer 4 + ===================== 5 + 6 + The virtual GPIO Consumer module allows users to instantiate virtual devices 7 + that request GPIOs and then control their behavior over debugfs. Virtual 8 + consumer devices can be instantiated from device-tree or over configfs. 9 + 10 + A virtual consumer uses the driver-facing GPIO APIs and allows to cover it with 11 + automated tests driven by user-space. The GPIOs are requested using 12 + ``gpiod_get_array()`` and so we support multiple GPIOs per connector ID. 13 + 14 + Creating GPIO consumers 15 + ----------------------- 16 + 17 + The gpio-consumer module registers a configfs subsystem called 18 + ``'gpio-virtuser'``. For details of the configfs filesystem, please refer to 19 + the configfs documentation. 20 + 21 + The user can create a hierarchy of configfs groups and items as well as modify 22 + values of exposed attributes. Once the consumer is instantiated, this hierarchy 23 + will be translated to appropriate device properties. The general structure is: 24 + 25 + **Group:** ``/config/gpio-virtuser`` 26 + 27 + This is the top directory of the gpio-consumer configfs tree. 28 + 29 + **Group:** ``/config/gpio-consumer/example-name`` 30 + 31 + **Attribute:** ``/config/gpio-consumer/example-name/live`` 32 + 33 + **Attribute:** ``/config/gpio-consumer/example-name/dev_name`` 34 + 35 + This is a directory representing a GPIO consumer device. 36 + 37 + The read-only ``dev_name`` attribute exposes the name of the device as it will 38 + appear in the system on the platform bus. This is useful for locating the 39 + associated debugfs directory under 40 + ``/sys/kernel/debug/gpio-virtuser/$dev_name``. 41 + 42 + The ``'live'`` attribute allows to trigger the actual creation of the device 43 + once it's fully configured. The accepted values are: ``'1'`` to enable the 44 + virtual device and ``'0'`` to disable and tear it down. 45 + 46 + Creating GPIO lookup tables 47 + --------------------------- 48 + 49 + Users can create a number of configfs groups under the device group: 50 + 51 + **Group:** ``/config/gpio-consumer/example-name/con_id`` 52 + 53 + The ``'con_id'`` directory represents a single GPIO lookup and its value maps 54 + to the ``'con_id'`` argument of the ``gpiod_get()`` function. For example: 55 + ``con_id`` == ``'reset'`` maps to the ``reset-gpios`` device property. 56 + 57 + Users can assign a number of GPIOs to each lookup. Each GPIO is a sub-directory 58 + with a user-defined name under the ``'con_id'`` group. 59 + 60 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/key`` 61 + 62 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/offset`` 63 + 64 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/drive`` 65 + 66 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/pull`` 67 + 68 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/active_low`` 69 + 70 + **Attribute:** ``/config/gpio-consumer/example-name/con_id/0/transitory`` 71 + 72 + This is a group describing a single GPIO in the ``con_id-gpios`` property. 73 + 74 + For virtual consumers created using configfs we use machine lookup tables so 75 + this group can be considered as a mapping between the filesystem and the fields 76 + of a single entry in ``'struct gpiod_lookup'``. 77 + 78 + The ``'key'`` attribute represents either the name of the chip this GPIO 79 + belongs to or the GPIO line name. This depends on the value of the ``'offset'`` 80 + attribute: if its value is >= 0, then ``'key'`` represents the label of the 81 + chip to lookup while ``'offset'`` represents the offset of the line in that 82 + chip. If ``'offset'`` is < 0, then ``'key'`` represents the name of the line. 83 + 84 + The remaining attributes map to the ``'flags'`` field of the GPIO lookup 85 + struct. The first two take string values as arguments: 86 + 87 + **``'drive'``:** ``'push-pull'``, ``'open-drain'``, ``'open-source'`` 88 + **``'pull'``:** ``'pull-up'``, ``'pull-down'``, ``'pull-disabled'``, ``'as-is'`` 89 + 90 + ``'active_low'`` and ``'transitory'`` are boolean attributes. 91 + 92 + Activating GPIO consumers 93 + ------------------------- 94 + 95 + Once the confiuration is complete, the ``'live'`` attribute must be set to 1 in 96 + order to instantiate the consumer. It can be set back to 0 to destroy the 97 + virtual device. The module will synchronously wait for the new simulated device 98 + to be successfully probed and if this doesn't happen, writing to ``'live'`` will 99 + result in an error. 100 + 101 + Device-tree 102 + ----------- 103 + 104 + Virtual GPIO consumers can also be defined in device-tree. The compatible string 105 + must be: ``"gpio-virtuser"`` with at least one property following the 106 + standardized GPIO pattern. 107 + 108 + An example device-tree code defining a virtual GPIO consumer: 109 + 110 + .. code-block :: none 111 + 112 + gpio-virt-consumer { 113 + compatible = "gpio-virtuser"; 114 + 115 + foo-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>, <&gpio1 2 0>; 116 + bar-gpios = <&gpio0 6 0>; 117 + }; 118 + 119 + Controlling virtual GPIO consumers 120 + ---------------------------------- 121 + 122 + Once active, the device will export debugfs attributes for controlling GPIO 123 + arrays as well as each requested GPIO line separately. Let's consider the 124 + following device property: ``foo-gpios = <&gpio0 0 0>, <&gpio0 4 0>;``. 125 + 126 + The following debugfs attribute groups will be created: 127 + 128 + **Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/`` 129 + 130 + This is the group that will contain the attributes for the entire GPIO array. 131 + 132 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values`` 133 + 134 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo/values_atomic`` 135 + 136 + Both attributes allow to read and set arrays of GPIO values. User must pass 137 + exactly the number of values that the array contains in the form of a string 138 + containing zeroes and ones representing inactive and active GPIO states 139 + respectively. In this example: ``echo 11 > values``. 140 + 141 + The ``values_atomic`` attribute works the same as ``values`` but the kernel 142 + will execute the GPIO driver callbacks in interrupt context. 143 + 144 + **Group:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/`` 145 + 146 + This is a group that represents a single GPIO with ``$index`` being its offset 147 + in the array. 148 + 149 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/consumer`` 150 + 151 + Allows to set and read the consumer label of the GPIO line. 152 + 153 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/debounce`` 154 + 155 + Allows to set and read the debounce period of the GPIO line. 156 + 157 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction`` 158 + 159 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/direction_atomic`` 160 + 161 + These two attributes allow to set the direction of the GPIO line. They accept 162 + "input" and "output" as values. The atomic variant executes the driver callback 163 + in interrupt context. 164 + 165 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/interrupts`` 166 + 167 + If the line is requested in input mode, writing ``1`` to this attribute will 168 + make the module listen for edge interrupts on the GPIO. Writing ``0`` disables 169 + the monitoring. Reading this attribute returns the current number of registered 170 + interrupts (both edges). 171 + 172 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value`` 173 + 174 + **Attribute:** ``/sys/kernel/debug/gpio-virtuser/$dev_name/gpiod:foo:$index/value_atomic`` 175 + 176 + Both attributes allow to read and set values of individual requested GPIO lines. 177 + They accept the following values: ``1`` and ``0``.
+1
Documentation/admin-guide/gpio/index.rst
··· 10 10 Character Device Userspace API <../../userspace-api/gpio/chardev> 11 11 gpio-aggregator 12 12 gpio-sim 13 + gpio-virtuser 13 14 Obsolete APIs <obsolete> 14 15 15 16 .. only:: subproject and html
+12
drivers/gpio/Kconfig
··· 1908 1908 If this driver is built as a module it will be called 1909 1909 'gpio-sloppy-logic-analyzer'. 1910 1910 1911 + config GPIO_VIRTUSER 1912 + tristate "GPIO Virtual User Testing Module" 1913 + select DEBUG_FS 1914 + select CONFIGFS_FS 1915 + select IRQ_WORK 1916 + help 1917 + Say Y here to enable the configurable, configfs-based virtual GPIO 1918 + consumer testing driver. 1919 + 1920 + This driver is aimed as a helper in spotting any regressions in 1921 + hot-unplug handling in GPIOLIB. 1922 + 1911 1923 endmenu 1912 1924 1913 1925 endif
+1
drivers/gpio/Makefile
··· 182 182 obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o 183 183 obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o 184 184 obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o 185 + obj-$(CONFIG_GPIO_VIRTUSER) += gpio-virtuser.o 185 186 obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o 186 187 obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o 187 188 obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
+1807
drivers/gpio/gpio-virtuser.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Configurable virtual GPIO consumer module. 4 + * 5 + * Copyright (C) 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org> 6 + */ 7 + 8 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 + 10 + #include <linux/array_size.h> 11 + #include <linux/atomic.h> 12 + #include <linux/bitmap.h> 13 + #include <linux/cleanup.h> 14 + #include <linux/completion.h> 15 + #include <linux/configfs.h> 16 + #include <linux/debugfs.h> 17 + #include <linux/device.h> 18 + #include <linux/err.h> 19 + #include <linux/gpio/consumer.h> 20 + #include <linux/gpio/machine.h> 21 + #include <linux/idr.h> 22 + #include <linux/interrupt.h> 23 + #include <linux/irq_work.h> 24 + #include <linux/limits.h> 25 + #include <linux/list.h> 26 + #include <linux/lockdep.h> 27 + #include <linux/mod_devicetable.h> 28 + #include <linux/module.h> 29 + #include <linux/mutex.h> 30 + #include <linux/notifier.h> 31 + #include <linux/of.h> 32 + #include <linux/overflow.h> 33 + #include <linux/platform_device.h> 34 + #include <linux/printk.h> 35 + #include <linux/property.h> 36 + #include <linux/slab.h> 37 + #include <linux/string_helpers.h> 38 + #include <linux/types.h> 39 + 40 + #define GPIO_VIRTUSER_NAME_BUF_LEN 32 41 + 42 + static DEFINE_IDA(gpio_virtuser_ida); 43 + static struct dentry *gpio_virtuser_dbg_root; 44 + 45 + struct gpio_virtuser_attr_data { 46 + union { 47 + struct gpio_desc *desc; 48 + struct gpio_descs *descs; 49 + }; 50 + struct dentry *dbgfs_dir; 51 + }; 52 + 53 + struct gpio_virtuser_line_array_data { 54 + struct gpio_virtuser_attr_data ad; 55 + }; 56 + 57 + struct gpio_virtuser_line_data { 58 + struct gpio_virtuser_attr_data ad; 59 + char consumer[GPIO_VIRTUSER_NAME_BUF_LEN]; 60 + struct mutex consumer_lock; 61 + unsigned int debounce; 62 + atomic_t irq; 63 + atomic_t irq_count; 64 + }; 65 + 66 + struct gpio_virtuser_dbgfs_attr_descr { 67 + const char *name; 68 + const struct file_operations *fops; 69 + }; 70 + 71 + struct gpio_virtuser_irq_work_context { 72 + struct irq_work work; 73 + struct completion work_completion; 74 + union { 75 + struct { 76 + struct gpio_desc *desc; 77 + int dir; 78 + int val; 79 + int ret; 80 + }; 81 + struct { 82 + struct gpio_descs *descs; 83 + unsigned long *values; 84 + }; 85 + }; 86 + }; 87 + 88 + static struct gpio_virtuser_irq_work_context * 89 + to_gpio_virtuser_irq_work_context(struct irq_work *work) 90 + { 91 + return container_of(work, struct gpio_virtuser_irq_work_context, work); 92 + } 93 + 94 + static void 95 + gpio_virtuser_init_irq_work_context(struct gpio_virtuser_irq_work_context *ctx) 96 + { 97 + memset(ctx, 0, sizeof(*ctx)); 98 + init_completion(&ctx->work_completion); 99 + } 100 + 101 + static void 102 + gpio_virtuser_irq_work_queue_sync(struct gpio_virtuser_irq_work_context *ctx) 103 + { 104 + irq_work_queue(&ctx->work); 105 + wait_for_completion(&ctx->work_completion); 106 + } 107 + 108 + static void gpio_virtuser_dbgfs_emit_value_array(char *buf, 109 + unsigned long *values, 110 + size_t num_values) 111 + { 112 + size_t i; 113 + 114 + for (i = 0; i < num_values; i++) 115 + buf[i] = test_bit(i, values) ? '1' : '0'; 116 + 117 + buf[i++] = '\n'; 118 + } 119 + 120 + static void gpio_virtuser_get_value_array_atomic(struct irq_work *work) 121 + { 122 + struct gpio_virtuser_irq_work_context *ctx = 123 + to_gpio_virtuser_irq_work_context(work); 124 + struct gpio_descs *descs = ctx->descs; 125 + 126 + ctx->ret = gpiod_get_array_value(descs->ndescs, descs->desc, 127 + descs->info, ctx->values); 128 + complete(&ctx->work_completion); 129 + } 130 + 131 + static int gpio_virtuser_get_array_value(struct gpio_descs *descs, 132 + unsigned long *values, bool atomic) 133 + { 134 + struct gpio_virtuser_irq_work_context ctx; 135 + 136 + if (!atomic) 137 + return gpiod_get_array_value_cansleep(descs->ndescs, 138 + descs->desc, 139 + descs->info, values); 140 + 141 + gpio_virtuser_init_irq_work_context(&ctx); 142 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_get_value_array_atomic); 143 + ctx.descs = descs; 144 + ctx.values = values; 145 + 146 + gpio_virtuser_irq_work_queue_sync(&ctx); 147 + 148 + return ctx.ret; 149 + } 150 + 151 + static ssize_t gpio_virtuser_value_array_do_read(struct file *file, 152 + char __user *user_buf, 153 + size_t size, loff_t *ppos, 154 + bool atomic) 155 + { 156 + struct gpio_virtuser_line_data *data = file->private_data; 157 + struct gpio_descs *descs = data->ad.descs; 158 + size_t bufsize; 159 + int ret; 160 + 161 + unsigned long *values __free(bitmap) = bitmap_zalloc(descs->ndescs, 162 + GFP_KERNEL); 163 + if (!values) 164 + return -ENOMEM; 165 + 166 + ret = gpio_virtuser_get_array_value(descs, values, atomic); 167 + if (ret) 168 + return ret; 169 + 170 + bufsize = descs->ndescs + 2; 171 + 172 + char *buf __free(kfree) = kzalloc(bufsize, GFP_KERNEL); 173 + if (!buf) 174 + return -ENOMEM; 175 + 176 + gpio_virtuser_dbgfs_emit_value_array(buf, values, descs->ndescs); 177 + 178 + return simple_read_from_buffer(user_buf, size, ppos, buf, 179 + descs->ndescs + 1); 180 + } 181 + 182 + static int gpio_virtuser_dbgfs_parse_value_array(const char *buf, 183 + size_t len, 184 + unsigned long *values) 185 + { 186 + size_t i; 187 + 188 + for (i = 0; i < len; i++) { 189 + if (buf[i] == '0') 190 + clear_bit(i, values); 191 + else if (buf[i] == '1') 192 + set_bit(i, values); 193 + else 194 + return -EINVAL; 195 + } 196 + 197 + return 0; 198 + } 199 + 200 + static void gpio_virtuser_set_value_array_atomic(struct irq_work *work) 201 + { 202 + struct gpio_virtuser_irq_work_context *ctx = 203 + to_gpio_virtuser_irq_work_context(work); 204 + struct gpio_descs *descs = ctx->descs; 205 + 206 + ctx->ret = gpiod_set_array_value(descs->ndescs, descs->desc, 207 + descs->info, ctx->values); 208 + complete(&ctx->work_completion); 209 + } 210 + 211 + static int gpio_virtuser_set_array_value(struct gpio_descs *descs, 212 + unsigned long *values, bool atomic) 213 + { 214 + struct gpio_virtuser_irq_work_context ctx; 215 + 216 + if (!atomic) 217 + return gpiod_set_array_value_cansleep(descs->ndescs, 218 + descs->desc, 219 + descs->info, values); 220 + 221 + gpio_virtuser_init_irq_work_context(&ctx); 222 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_set_value_array_atomic); 223 + ctx.descs = descs; 224 + ctx.values = values; 225 + 226 + gpio_virtuser_irq_work_queue_sync(&ctx); 227 + 228 + return ctx.ret; 229 + } 230 + 231 + static ssize_t gpio_virtuser_value_array_do_write(struct file *file, 232 + const char __user *user_buf, 233 + size_t count, loff_t *ppos, 234 + bool atomic) 235 + { 236 + struct gpio_virtuser_line_data *data = file->private_data; 237 + struct gpio_descs *descs = data->ad.descs; 238 + int ret; 239 + 240 + if (count - 1 != descs->ndescs) 241 + return -EINVAL; 242 + 243 + char *buf __free(kfree) = kzalloc(count, GFP_KERNEL); 244 + if (!buf) 245 + return -ENOMEM; 246 + 247 + ret = simple_write_to_buffer(buf, count, ppos, user_buf, count); 248 + if (ret < 0) 249 + return ret; 250 + 251 + unsigned long *values __free(bitmap) = bitmap_zalloc(descs->ndescs, 252 + GFP_KERNEL); 253 + if (!values) 254 + return -ENOMEM; 255 + 256 + ret = gpio_virtuser_dbgfs_parse_value_array(buf, count - 1, values); 257 + if (ret) 258 + return ret; 259 + 260 + ret = gpio_virtuser_set_array_value(descs, values, atomic); 261 + if (ret) 262 + return ret; 263 + 264 + return count; 265 + } 266 + 267 + static ssize_t gpio_virtuser_value_array_read(struct file *file, 268 + char __user *user_buf, 269 + size_t count, loff_t *ppos) 270 + { 271 + return gpio_virtuser_value_array_do_read(file, user_buf, count, ppos, 272 + false); 273 + } 274 + 275 + static ssize_t gpio_virtuser_value_array_write(struct file *file, 276 + const char __user *user_buf, 277 + size_t count, loff_t *ppos) 278 + { 279 + return gpio_virtuser_value_array_do_write(file, user_buf, count, ppos, 280 + false); 281 + } 282 + 283 + static const struct file_operations gpio_virtuser_value_array_fops = { 284 + .read = gpio_virtuser_value_array_read, 285 + .write = gpio_virtuser_value_array_write, 286 + .open = simple_open, 287 + .owner = THIS_MODULE, 288 + .llseek = default_llseek, 289 + }; 290 + 291 + static ssize_t 292 + gpio_virtuser_value_array_atomic_read(struct file *file, char __user *user_buf, 293 + size_t count, loff_t *ppos) 294 + { 295 + return gpio_virtuser_value_array_do_read(file, user_buf, count, ppos, 296 + true); 297 + } 298 + 299 + static ssize_t 300 + gpio_virtuser_value_array_atomic_write(struct file *file, 301 + const char __user *user_buf, 302 + size_t count, loff_t *ppos) 303 + { 304 + return gpio_virtuser_value_array_do_write(file, user_buf, count, ppos, 305 + true); 306 + } 307 + 308 + static const struct file_operations gpio_virtuser_value_array_atomic_fops = { 309 + .read = gpio_virtuser_value_array_atomic_read, 310 + .write = gpio_virtuser_value_array_atomic_write, 311 + .open = simple_open, 312 + .owner = THIS_MODULE, 313 + .llseek = default_llseek, 314 + }; 315 + 316 + static void gpio_virtuser_do_get_direction_atomic(struct irq_work *work) 317 + { 318 + struct gpio_virtuser_irq_work_context *ctx = 319 + to_gpio_virtuser_irq_work_context(work); 320 + 321 + ctx->ret = gpiod_get_direction(ctx->desc); 322 + complete(&ctx->work_completion); 323 + } 324 + 325 + static int gpio_virtuser_get_direction_atomic(struct gpio_desc *desc) 326 + { 327 + struct gpio_virtuser_irq_work_context ctx; 328 + 329 + gpio_virtuser_init_irq_work_context(&ctx); 330 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_do_get_direction_atomic); 331 + ctx.desc = desc; 332 + 333 + gpio_virtuser_irq_work_queue_sync(&ctx); 334 + 335 + return ctx.ret; 336 + } 337 + 338 + static ssize_t gpio_virtuser_direction_do_read(struct file *file, 339 + char __user *user_buf, 340 + size_t size, loff_t *ppos, 341 + bool atomic) 342 + { 343 + struct gpio_virtuser_line_data *data = file->private_data; 344 + struct gpio_desc *desc = data->ad.desc; 345 + char buf[32]; 346 + int dir; 347 + 348 + if (!atomic) 349 + dir = gpiod_get_direction(desc); 350 + else 351 + dir = gpio_virtuser_get_direction_atomic(desc); 352 + if (dir < 0) 353 + return dir; 354 + 355 + snprintf(buf, sizeof(buf), "%s\n", dir ? "input" : "output"); 356 + 357 + return simple_read_from_buffer(user_buf, size, ppos, buf, strlen(buf)); 358 + } 359 + 360 + static int gpio_virtuser_set_direction(struct gpio_desc *desc, int dir, int val) 361 + { 362 + if (dir) 363 + return gpiod_direction_input(desc); 364 + 365 + return gpiod_direction_output(desc, val); 366 + } 367 + 368 + static void gpio_virtuser_do_set_direction_atomic(struct irq_work *work) 369 + { 370 + struct gpio_virtuser_irq_work_context *ctx = 371 + to_gpio_virtuser_irq_work_context(work); 372 + 373 + ctx->ret = gpio_virtuser_set_direction(ctx->desc, ctx->dir, ctx->val); 374 + complete(&ctx->work_completion); 375 + } 376 + 377 + static int gpio_virtuser_set_direction_atomic(struct gpio_desc *desc, 378 + int dir, int val) 379 + { 380 + struct gpio_virtuser_irq_work_context ctx; 381 + 382 + gpio_virtuser_init_irq_work_context(&ctx); 383 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_do_set_direction_atomic); 384 + ctx.desc = desc; 385 + ctx.dir = dir; 386 + ctx.val = val; 387 + 388 + gpio_virtuser_irq_work_queue_sync(&ctx); 389 + 390 + return ctx.ret; 391 + } 392 + 393 + static ssize_t gpio_virtuser_direction_do_write(struct file *file, 394 + const char __user *user_buf, 395 + size_t count, loff_t *ppos, 396 + bool atomic) 397 + { 398 + struct gpio_virtuser_line_data *data = file->private_data; 399 + struct gpio_desc *desc = data->ad.desc; 400 + char buf[32], *trimmed; 401 + int ret, dir, val = 0; 402 + 403 + ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count); 404 + if (ret < 0) 405 + return ret; 406 + 407 + trimmed = strim(buf); 408 + 409 + if (strcmp(buf, "input") == 0) { 410 + dir = 1; 411 + } else if (strcmp(buf, "output-high") == 0) { 412 + dir = 0; 413 + val = 1; 414 + } else if (strcmp(buf, "output-low") == 0) { 415 + dir = val = 0; 416 + } else { 417 + return -EINVAL; 418 + } 419 + 420 + if (!atomic) 421 + ret = gpio_virtuser_set_direction(desc, dir, val); 422 + else 423 + ret = gpio_virtuser_set_direction_atomic(desc, dir, val); 424 + if (ret) 425 + return ret; 426 + 427 + return count; 428 + } 429 + 430 + static ssize_t gpio_virtuser_direction_read(struct file *file, 431 + char __user *user_buf, 432 + size_t size, loff_t *ppos) 433 + { 434 + return gpio_virtuser_direction_do_read(file, user_buf, size, ppos, 435 + false); 436 + } 437 + 438 + static ssize_t gpio_virtuser_direction_write(struct file *file, 439 + const char __user *user_buf, 440 + size_t count, loff_t *ppos) 441 + { 442 + return gpio_virtuser_direction_do_write(file, user_buf, count, ppos, 443 + false); 444 + } 445 + 446 + static const struct file_operations gpio_virtuser_direction_fops = { 447 + .read = gpio_virtuser_direction_read, 448 + .write = gpio_virtuser_direction_write, 449 + .open = simple_open, 450 + .owner = THIS_MODULE, 451 + .llseek = default_llseek, 452 + }; 453 + 454 + static ssize_t gpio_virtuser_direction_atomic_read(struct file *file, 455 + char __user *user_buf, 456 + size_t size, loff_t *ppos) 457 + { 458 + return gpio_virtuser_direction_do_read(file, user_buf, size, ppos, 459 + true); 460 + } 461 + 462 + static ssize_t gpio_virtuser_direction_atomic_write(struct file *file, 463 + const char __user *user_buf, 464 + size_t count, loff_t *ppos) 465 + { 466 + return gpio_virtuser_direction_do_write(file, user_buf, count, ppos, 467 + true); 468 + } 469 + 470 + static const struct file_operations gpio_virtuser_direction_atomic_fops = { 471 + .read = gpio_virtuser_direction_atomic_read, 472 + .write = gpio_virtuser_direction_atomic_write, 473 + .open = simple_open, 474 + .owner = THIS_MODULE, 475 + .llseek = default_llseek, 476 + }; 477 + 478 + static int gpio_virtuser_value_get(void *data, u64 *val) 479 + { 480 + struct gpio_virtuser_line_data *ld = data; 481 + int ret; 482 + 483 + ret = gpiod_get_value_cansleep(ld->ad.desc); 484 + if (ret < 0) 485 + return ret; 486 + 487 + *val = ret; 488 + 489 + return 0; 490 + } 491 + 492 + static int gpio_virtuser_value_set(void *data, u64 val) 493 + { 494 + struct gpio_virtuser_line_data *ld = data; 495 + 496 + if (val > 1) 497 + return -EINVAL; 498 + 499 + gpiod_set_value_cansleep(ld->ad.desc, (int)val); 500 + 501 + return 0; 502 + } 503 + 504 + DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_fops, 505 + gpio_virtuser_value_get, 506 + gpio_virtuser_value_set, 507 + "%llu\n"); 508 + 509 + static void gpio_virtuser_get_value_atomic(struct irq_work *work) 510 + { 511 + struct gpio_virtuser_irq_work_context *ctx = 512 + to_gpio_virtuser_irq_work_context(work); 513 + 514 + ctx->val = gpiod_get_value(ctx->desc); 515 + complete(&ctx->work_completion); 516 + } 517 + 518 + static int gpio_virtuser_value_atomic_get(void *data, u64 *val) 519 + { 520 + struct gpio_virtuser_line_data *ld = data; 521 + struct gpio_virtuser_irq_work_context ctx; 522 + 523 + gpio_virtuser_init_irq_work_context(&ctx); 524 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_get_value_atomic); 525 + ctx.desc = ld->ad.desc; 526 + 527 + gpio_virtuser_irq_work_queue_sync(&ctx); 528 + 529 + if (ctx.val < 0) 530 + return ctx.val; 531 + 532 + *val = ctx.val; 533 + 534 + return 0; 535 + } 536 + 537 + static void gpio_virtuser_set_value_atomic(struct irq_work *work) 538 + { 539 + struct gpio_virtuser_irq_work_context *ctx = 540 + to_gpio_virtuser_irq_work_context(work); 541 + 542 + gpiod_set_value(ctx->desc, ctx->val); 543 + complete(&ctx->work_completion); 544 + } 545 + 546 + static int gpio_virtuser_value_atomic_set(void *data, u64 val) 547 + { 548 + struct gpio_virtuser_line_data *ld = data; 549 + struct gpio_virtuser_irq_work_context ctx; 550 + 551 + if (val > 1) 552 + return -EINVAL; 553 + 554 + gpio_virtuser_init_irq_work_context(&ctx); 555 + ctx.work = IRQ_WORK_INIT_HARD(gpio_virtuser_set_value_atomic); 556 + ctx.desc = ld->ad.desc; 557 + ctx.val = (int)val; 558 + 559 + gpio_virtuser_irq_work_queue_sync(&ctx); 560 + 561 + return 0; 562 + } 563 + 564 + DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_value_atomic_fops, 565 + gpio_virtuser_value_atomic_get, 566 + gpio_virtuser_value_atomic_set, 567 + "%llu\n"); 568 + 569 + static int gpio_virtuser_debounce_get(void *data, u64 *val) 570 + { 571 + struct gpio_virtuser_line_data *ld = data; 572 + 573 + *val = READ_ONCE(ld->debounce); 574 + 575 + return 0; 576 + } 577 + 578 + static int gpio_virtuser_debounce_set(void *data, u64 val) 579 + { 580 + struct gpio_virtuser_line_data *ld = data; 581 + int ret; 582 + 583 + if (val > UINT_MAX) 584 + return -E2BIG; 585 + 586 + ret = gpiod_set_debounce(ld->ad.desc, (unsigned int)val); 587 + if (ret) 588 + /* Don't propagate errno unknown to user-space. */ 589 + return ret == -ENOTSUPP ? -EOPNOTSUPP : ret; 590 + 591 + WRITE_ONCE(ld->debounce, (unsigned int)val); 592 + 593 + return 0; 594 + } 595 + 596 + DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_debounce_fops, 597 + gpio_virtuser_debounce_get, 598 + gpio_virtuser_debounce_set, 599 + "%llu\n"); 600 + 601 + static ssize_t gpio_virtuser_consumer_read(struct file *file, 602 + char __user *user_buf, 603 + size_t size, loff_t *ppos) 604 + { 605 + struct gpio_virtuser_line_data *data = file->private_data; 606 + char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 1]; 607 + ssize_t ret; 608 + 609 + memset(buf, 0x0, sizeof(buf)); 610 + 611 + scoped_guard(mutex, &data->consumer_lock) 612 + ret = snprintf(buf, sizeof(buf), "%s\n", data->consumer); 613 + 614 + return simple_read_from_buffer(user_buf, size, ppos, buf, ret); 615 + } 616 + 617 + static ssize_t gpio_virtuser_consumer_write(struct file *file, 618 + const char __user *user_buf, 619 + size_t count, loff_t *ppos) 620 + { 621 + struct gpio_virtuser_line_data *data = file->private_data; 622 + char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2]; 623 + int ret; 624 + 625 + ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos, 626 + user_buf, count); 627 + if (ret < 0) 628 + return ret; 629 + 630 + buf[strlen(buf) - 1] = '\0'; 631 + 632 + ret = gpiod_set_consumer_name(data->ad.desc, buf); 633 + if (ret) 634 + return ret; 635 + 636 + scoped_guard(mutex, &data->consumer_lock) 637 + strscpy(data->consumer, buf, sizeof(data->consumer)); 638 + 639 + return count; 640 + } 641 + 642 + static const struct file_operations gpio_virtuser_consumer_fops = { 643 + .read = gpio_virtuser_consumer_read, 644 + .write = gpio_virtuser_consumer_write, 645 + .open = simple_open, 646 + .owner = THIS_MODULE, 647 + .llseek = default_llseek, 648 + }; 649 + 650 + static int gpio_virtuser_interrupts_get(void *data, u64 *val) 651 + { 652 + struct gpio_virtuser_line_data *ld = data; 653 + 654 + *val = atomic_read(&ld->irq_count); 655 + 656 + return 0; 657 + } 658 + 659 + static irqreturn_t gpio_virtuser_irq_handler(int irq, void *data) 660 + { 661 + struct gpio_virtuser_line_data *ld = data; 662 + 663 + atomic_inc(&ld->irq_count); 664 + 665 + return IRQ_HANDLED; 666 + } 667 + 668 + static int gpio_virtuser_interrupts_set(void *data, u64 val) 669 + { 670 + struct gpio_virtuser_line_data *ld = data; 671 + int irq, ret; 672 + 673 + if (val > 1) 674 + return -EINVAL; 675 + 676 + if (val) { 677 + irq = gpiod_to_irq(ld->ad.desc); 678 + if (irq < 0) 679 + return irq; 680 + 681 + ret = request_threaded_irq(irq, NULL, 682 + gpio_virtuser_irq_handler, 683 + IRQF_TRIGGER_RISING | 684 + IRQF_TRIGGER_FALLING | 685 + IRQF_ONESHOT, 686 + ld->consumer, data); 687 + if (ret) 688 + return ret; 689 + 690 + atomic_set(&ld->irq, irq); 691 + } else { 692 + irq = atomic_xchg(&ld->irq, 0); 693 + free_irq(irq, ld); 694 + } 695 + 696 + return 0; 697 + } 698 + 699 + DEFINE_DEBUGFS_ATTRIBUTE(gpio_virtuser_interrupts_fops, 700 + gpio_virtuser_interrupts_get, 701 + gpio_virtuser_interrupts_set, 702 + "%llu\n"); 703 + 704 + static const struct gpio_virtuser_dbgfs_attr_descr 705 + gpio_virtuser_line_array_dbgfs_attrs[] = { 706 + { 707 + .name = "values", 708 + .fops = &gpio_virtuser_value_array_fops, 709 + }, 710 + { 711 + .name = "values_atomic", 712 + .fops = &gpio_virtuser_value_array_atomic_fops, 713 + }, 714 + }; 715 + 716 + static const struct gpio_virtuser_dbgfs_attr_descr 717 + gpio_virtuser_line_dbgfs_attrs[] = { 718 + { 719 + .name = "direction", 720 + .fops = &gpio_virtuser_direction_fops, 721 + }, 722 + { 723 + .name = "direction_atomic", 724 + .fops = &gpio_virtuser_direction_atomic_fops, 725 + }, 726 + { 727 + .name = "value", 728 + .fops = &gpio_virtuser_value_fops, 729 + }, 730 + { 731 + .name = "value_atomic", 732 + .fops = &gpio_virtuser_value_atomic_fops, 733 + }, 734 + { 735 + .name = "debounce", 736 + .fops = &gpio_virtuser_debounce_fops, 737 + }, 738 + { 739 + .name = "consumer", 740 + .fops = &gpio_virtuser_consumer_fops, 741 + }, 742 + { 743 + .name = "interrupts", 744 + .fops = &gpio_virtuser_interrupts_fops, 745 + }, 746 + }; 747 + 748 + static int gpio_virtuser_create_debugfs_attrs( 749 + const struct gpio_virtuser_dbgfs_attr_descr *attr, 750 + size_t num_attrs, struct dentry *parent, void *data) 751 + { 752 + struct dentry *ret; 753 + size_t i; 754 + 755 + for (i = 0; i < num_attrs; i++, attr++) { 756 + ret = debugfs_create_file(attr->name, 0644, parent, data, 757 + attr->fops); 758 + if (IS_ERR(ret)) 759 + return PTR_ERR(ret); 760 + } 761 + 762 + return 0; 763 + } 764 + 765 + static int gpio_virtuser_dbgfs_init_line_array_attrs(struct device *dev, 766 + struct gpio_descs *descs, 767 + const char *id, 768 + struct dentry *dbgfs_entry) 769 + { 770 + struct gpio_virtuser_line_array_data *data; 771 + char *name; 772 + 773 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 774 + if (!data) 775 + return -ENOMEM; 776 + 777 + data->ad.descs = descs; 778 + 779 + name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s", id); 780 + if (!name) 781 + return -ENOMEM; 782 + 783 + data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry); 784 + if (IS_ERR(data->ad.dbgfs_dir)) 785 + return PTR_ERR(data->ad.dbgfs_dir); 786 + 787 + return gpio_virtuser_create_debugfs_attrs( 788 + gpio_virtuser_line_array_dbgfs_attrs, 789 + ARRAY_SIZE(gpio_virtuser_line_array_dbgfs_attrs), 790 + data->ad.dbgfs_dir, data); 791 + } 792 + 793 + static int gpio_virtuser_dbgfs_init_line_attrs(struct device *dev, 794 + struct gpio_desc *desc, 795 + const char *id, 796 + unsigned int index, 797 + struct dentry *dbgfs_entry) 798 + { 799 + struct gpio_virtuser_line_data *data; 800 + char *name; 801 + int ret; 802 + 803 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 804 + if (!data) 805 + return -ENOMEM; 806 + 807 + data->ad.desc = desc; 808 + sprintf(data->consumer, id); 809 + atomic_set(&data->irq, 0); 810 + atomic_set(&data->irq_count, 0); 811 + 812 + name = devm_kasprintf(dev, GFP_KERNEL, "gpiod:%s:%u", id, index); 813 + if (!name) 814 + return -ENOMEM; 815 + 816 + ret = devm_mutex_init(dev, &data->consumer_lock); 817 + if (ret) 818 + return ret; 819 + 820 + data->ad.dbgfs_dir = debugfs_create_dir(name, dbgfs_entry); 821 + if (IS_ERR(data->ad.dbgfs_dir)) 822 + return PTR_ERR(data->ad.dbgfs_dir); 823 + 824 + return gpio_virtuser_create_debugfs_attrs( 825 + gpio_virtuser_line_dbgfs_attrs, 826 + ARRAY_SIZE(gpio_virtuser_line_dbgfs_attrs), 827 + data->ad.dbgfs_dir, data); 828 + } 829 + 830 + static void gpio_virtuser_debugfs_remove(void *data) 831 + { 832 + struct dentry *dbgfs_entry = data; 833 + 834 + debugfs_remove_recursive(dbgfs_entry); 835 + } 836 + 837 + static int gpio_virtuser_prop_is_gpio(struct property *prop) 838 + { 839 + char *dash = strrchr(prop->name, '-'); 840 + 841 + return dash && strcmp(dash, "-gpios") == 0; 842 + } 843 + 844 + /* 845 + * If this is an OF-based system, then we iterate over properties and consider 846 + * all whose names end in "-gpios". For configfs we expect an additional string 847 + * array property - "gpio-virtuser,ids" - containing the list of all GPIO IDs 848 + * to request. 849 + */ 850 + static int gpio_virtuser_count_ids(struct device *dev) 851 + { 852 + struct device_node *of_node = dev_of_node(dev); 853 + struct property *prop; 854 + int ret = 0; 855 + 856 + if (!of_node) 857 + return device_property_string_array_count(dev, 858 + "gpio-virtuser,ids"); 859 + 860 + for_each_property_of_node(of_node, prop) { 861 + if (gpio_virtuser_prop_is_gpio(prop)) 862 + ++ret; 863 + } 864 + 865 + return ret; 866 + } 867 + 868 + static int gpio_virtuser_get_ids(struct device *dev, const char **ids, 869 + int num_ids) 870 + { 871 + struct device_node *of_node = dev_of_node(dev); 872 + struct property *prop; 873 + size_t pos = 0, diff; 874 + char *dash, *tmp; 875 + 876 + if (!of_node) 877 + return device_property_read_string_array(dev, 878 + "gpio-virtuser,ids", 879 + ids, num_ids); 880 + 881 + for_each_property_of_node(of_node, prop) { 882 + if (!gpio_virtuser_prop_is_gpio(prop)) 883 + continue; 884 + 885 + dash = strrchr(prop->name, '-'); 886 + diff = dash - prop->name; 887 + 888 + tmp = devm_kmemdup(dev, prop->name, diff + 1, 889 + GFP_KERNEL); 890 + if (!tmp) 891 + return -ENOMEM; 892 + 893 + tmp[diff] = '\0'; 894 + ids[pos++] = tmp; 895 + } 896 + 897 + return 0; 898 + } 899 + 900 + static int gpio_virtuser_probe(struct platform_device *pdev) 901 + { 902 + struct device *dev = &pdev->dev; 903 + struct dentry *dbgfs_entry; 904 + struct gpio_descs *descs; 905 + int ret, num_ids = 0, i; 906 + const char **ids; 907 + unsigned int j; 908 + 909 + num_ids = gpio_virtuser_count_ids(dev); 910 + if (num_ids < 0) 911 + return dev_err_probe(dev, num_ids, 912 + "Failed to get the number of GPIOs to request\n"); 913 + 914 + if (num_ids == 0) 915 + return dev_err_probe(dev, -EINVAL, "No GPIO IDs specified\n"); 916 + 917 + ids = devm_kcalloc(dev, num_ids, sizeof(*ids), GFP_KERNEL); 918 + if (!ids) 919 + return -ENOMEM; 920 + 921 + ret = gpio_virtuser_get_ids(dev, ids, num_ids); 922 + if (ret < 0) 923 + return dev_err_probe(dev, ret, 924 + "Failed to get the IDs of GPIOs to request\n"); 925 + 926 + dbgfs_entry = debugfs_create_dir(dev_name(dev), gpio_virtuser_dbg_root); 927 + ret = devm_add_action_or_reset(dev, gpio_virtuser_debugfs_remove, 928 + dbgfs_entry); 929 + if (ret) 930 + return ret; 931 + 932 + for (i = 0; i < num_ids; i++) { 933 + descs = devm_gpiod_get_array(dev, ids[i], GPIOD_ASIS); 934 + if (IS_ERR(descs)) 935 + return dev_err_probe(dev, PTR_ERR(descs), 936 + "Failed to request the '%s' GPIOs\n", 937 + ids[i]); 938 + 939 + ret = gpio_virtuser_dbgfs_init_line_array_attrs(dev, descs, 940 + ids[i], 941 + dbgfs_entry); 942 + if (ret) 943 + return dev_err_probe(dev, ret, 944 + "Failed to setup the debugfs array interface for the '%s' GPIOs\n", 945 + ids[i]); 946 + 947 + for (j = 0; j < descs->ndescs; j++) { 948 + ret = gpio_virtuser_dbgfs_init_line_attrs(dev, 949 + descs->desc[j], ids[i], 950 + j, dbgfs_entry); 951 + if (ret) 952 + return dev_err_probe(dev, ret, 953 + "Failed to setup the debugfs line interface for the '%s' GPIOs\n", 954 + ids[i]); 955 + } 956 + } 957 + 958 + return 0; 959 + } 960 + 961 + static const struct of_device_id gpio_virtuser_of_match[] = { 962 + { .compatible = "gpio-virtuser" }, 963 + { } 964 + }; 965 + MODULE_DEVICE_TABLE(of, gpio_virtuser_of_match); 966 + 967 + static struct platform_driver gpio_virtuser_driver = { 968 + .driver = { 969 + .name = "gpio-virtuser", 970 + .of_match_table = gpio_virtuser_of_match, 971 + }, 972 + .probe = gpio_virtuser_probe, 973 + }; 974 + 975 + struct gpio_virtuser_device { 976 + struct config_group group; 977 + 978 + struct platform_device *pdev; 979 + int id; 980 + struct mutex lock; 981 + 982 + struct notifier_block bus_notifier; 983 + struct completion probe_completion; 984 + bool driver_bound; 985 + 986 + struct gpiod_lookup_table *lookup_table; 987 + 988 + struct list_head lookup_list; 989 + }; 990 + 991 + static int gpio_virtuser_bus_notifier_call(struct notifier_block *nb, 992 + unsigned long action, void *data) 993 + { 994 + struct gpio_virtuser_device *vdev; 995 + struct device *dev = data; 996 + char devname[32]; 997 + 998 + vdev = container_of(nb, struct gpio_virtuser_device, bus_notifier); 999 + snprintf(devname, sizeof(devname), "gpio-virtuser.%d", vdev->id); 1000 + 1001 + if (!device_match_name(dev, devname)) 1002 + return NOTIFY_DONE; 1003 + 1004 + switch (action) { 1005 + case BUS_NOTIFY_BOUND_DRIVER: 1006 + vdev->driver_bound = true; 1007 + break; 1008 + case BUS_NOTIFY_DRIVER_NOT_BOUND: 1009 + vdev->driver_bound = false; 1010 + break; 1011 + default: 1012 + return NOTIFY_DONE; 1013 + } 1014 + 1015 + complete(&vdev->probe_completion); 1016 + return NOTIFY_OK; 1017 + } 1018 + 1019 + static struct gpio_virtuser_device * 1020 + to_gpio_virtuser_device(struct config_item *item) 1021 + { 1022 + struct config_group *group = to_config_group(item); 1023 + 1024 + return container_of(group, struct gpio_virtuser_device, group); 1025 + } 1026 + 1027 + static bool 1028 + gpio_virtuser_device_is_live(struct gpio_virtuser_device *dev) 1029 + { 1030 + lockdep_assert_held(&dev->lock); 1031 + 1032 + return !!dev->pdev; 1033 + } 1034 + 1035 + struct gpio_virtuser_lookup { 1036 + struct config_group group; 1037 + 1038 + struct gpio_virtuser_device *parent; 1039 + struct list_head siblings; 1040 + 1041 + char *con_id; 1042 + 1043 + struct list_head entry_list; 1044 + }; 1045 + 1046 + static struct gpio_virtuser_lookup * 1047 + to_gpio_virtuser_lookup(struct config_item *item) 1048 + { 1049 + struct config_group *group = to_config_group(item); 1050 + 1051 + return container_of(group, struct gpio_virtuser_lookup, group); 1052 + } 1053 + 1054 + struct gpio_virtuser_lookup_entry { 1055 + struct config_group group; 1056 + 1057 + struct gpio_virtuser_lookup *parent; 1058 + struct list_head siblings; 1059 + 1060 + char *key; 1061 + /* Can be negative to indicate lookup by name. */ 1062 + int offset; 1063 + enum gpio_lookup_flags flags; 1064 + }; 1065 + 1066 + static struct gpio_virtuser_lookup_entry * 1067 + to_gpio_virtuser_lookup_entry(struct config_item *item) 1068 + { 1069 + struct config_group *group = to_config_group(item); 1070 + 1071 + return container_of(group, struct gpio_virtuser_lookup_entry, group); 1072 + } 1073 + 1074 + static ssize_t 1075 + gpio_virtuser_lookup_entry_config_key_show(struct config_item *item, char *page) 1076 + { 1077 + struct gpio_virtuser_lookup_entry *entry = 1078 + to_gpio_virtuser_lookup_entry(item); 1079 + struct gpio_virtuser_device *dev = entry->parent->parent; 1080 + 1081 + guard(mutex)(&dev->lock); 1082 + 1083 + return sprintf(page, "%s\n", entry->key ?: ""); 1084 + } 1085 + 1086 + static ssize_t 1087 + gpio_virtuser_lookup_entry_config_key_store(struct config_item *item, 1088 + const char *page, size_t count) 1089 + { 1090 + struct gpio_virtuser_lookup_entry *entry = 1091 + to_gpio_virtuser_lookup_entry(item); 1092 + struct gpio_virtuser_device *dev = entry->parent->parent; 1093 + 1094 + char *key __free(kfree) = kstrndup(skip_spaces(page), count, 1095 + GFP_KERNEL); 1096 + if (!key) 1097 + return -ENOMEM; 1098 + 1099 + strim(key); 1100 + 1101 + guard(mutex)(&dev->lock); 1102 + 1103 + if (gpio_virtuser_device_is_live(dev)) 1104 + return -EBUSY; 1105 + 1106 + kfree(entry->key); 1107 + entry->key = no_free_ptr(key); 1108 + 1109 + return count; 1110 + } 1111 + 1112 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, key); 1113 + 1114 + static ssize_t 1115 + gpio_virtuser_lookup_entry_config_offset_show(struct config_item *item, 1116 + char *page) 1117 + { 1118 + struct gpio_virtuser_lookup_entry *entry = 1119 + to_gpio_virtuser_lookup_entry(item); 1120 + struct gpio_virtuser_device *dev = entry->parent->parent; 1121 + unsigned int offset; 1122 + 1123 + scoped_guard(mutex, &dev->lock) 1124 + offset = entry->offset; 1125 + 1126 + return sprintf(page, "%d\n", offset); 1127 + } 1128 + 1129 + static ssize_t 1130 + gpio_virtuser_lookup_entry_config_offset_store(struct config_item *item, 1131 + const char *page, size_t count) 1132 + { 1133 + struct gpio_virtuser_lookup_entry *entry = 1134 + to_gpio_virtuser_lookup_entry(item); 1135 + struct gpio_virtuser_device *dev = entry->parent->parent; 1136 + int offset, ret; 1137 + 1138 + ret = kstrtoint(page, 0, &offset); 1139 + if (ret) 1140 + return ret; 1141 + 1142 + /* 1143 + * Negative number here means: 'key' represents a line name to lookup. 1144 + * Non-negative means: 'key' represents the label of the chip with 1145 + * the 'offset' value representing the line within that chip. 1146 + * 1147 + * GPIOLIB uses the U16_MAX value to indicate lookup by line name so 1148 + * the greatest offset we can accept is (U16_MAX - 1). 1149 + */ 1150 + if (offset > (U16_MAX - 1)) 1151 + return -EINVAL; 1152 + 1153 + guard(mutex)(&dev->lock); 1154 + 1155 + if (gpio_virtuser_device_is_live(dev)) 1156 + return -EBUSY; 1157 + 1158 + entry->offset = offset; 1159 + 1160 + return count; 1161 + } 1162 + 1163 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, offset); 1164 + 1165 + static enum gpio_lookup_flags 1166 + gpio_virtuser_lookup_get_flags(struct config_item *item) 1167 + { 1168 + struct gpio_virtuser_lookup_entry *entry = 1169 + to_gpio_virtuser_lookup_entry(item); 1170 + struct gpio_virtuser_device *dev = entry->parent->parent; 1171 + 1172 + guard(mutex)(&dev->lock); 1173 + 1174 + return entry->flags; 1175 + } 1176 + 1177 + static ssize_t 1178 + gpio_virtuser_lookup_entry_config_drive_show(struct config_item *item, char *page) 1179 + { 1180 + enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item); 1181 + const char *repr; 1182 + 1183 + if (flags & GPIO_OPEN_DRAIN) 1184 + repr = "open-drain"; 1185 + else if (flags & GPIO_OPEN_SOURCE) 1186 + repr = "open-source"; 1187 + else 1188 + repr = "push-pull"; 1189 + 1190 + return sprintf(page, "%s\n", repr); 1191 + } 1192 + 1193 + static ssize_t 1194 + gpio_virtuser_lookup_entry_config_drive_store(struct config_item *item, 1195 + const char *page, size_t count) 1196 + { 1197 + struct gpio_virtuser_lookup_entry *entry = 1198 + to_gpio_virtuser_lookup_entry(item); 1199 + struct gpio_virtuser_device *dev = entry->parent->parent; 1200 + 1201 + guard(mutex)(&dev->lock); 1202 + 1203 + if (gpio_virtuser_device_is_live(dev)) 1204 + return -EBUSY; 1205 + 1206 + if (sysfs_streq(page, "push-pull")) { 1207 + entry->flags &= ~(GPIO_OPEN_DRAIN | GPIO_OPEN_SOURCE); 1208 + } else if (sysfs_streq(page, "open-drain")) { 1209 + entry->flags &= ~GPIO_OPEN_SOURCE; 1210 + entry->flags |= GPIO_OPEN_DRAIN; 1211 + } else if (sysfs_streq(page, "open-source")) { 1212 + entry->flags &= ~GPIO_OPEN_DRAIN; 1213 + entry->flags |= GPIO_OPEN_SOURCE; 1214 + } else { 1215 + count = -EINVAL; 1216 + } 1217 + 1218 + return count; 1219 + } 1220 + 1221 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, drive); 1222 + 1223 + static ssize_t 1224 + gpio_virtuser_lookup_entry_config_pull_show(struct config_item *item, char *page) 1225 + { 1226 + enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item); 1227 + const char *repr; 1228 + 1229 + if (flags & GPIO_PULL_UP) 1230 + repr = "pull-up"; 1231 + else if (flags & GPIO_PULL_DOWN) 1232 + repr = "pull-down"; 1233 + else if (flags & GPIO_PULL_DISABLE) 1234 + repr = "pull-disabled"; 1235 + else 1236 + repr = "as-is"; 1237 + 1238 + return sprintf(page, "%s\n", repr); 1239 + } 1240 + 1241 + static ssize_t 1242 + gpio_virtuser_lookup_entry_config_pull_store(struct config_item *item, 1243 + const char *page, size_t count) 1244 + { 1245 + struct gpio_virtuser_lookup_entry *entry = 1246 + to_gpio_virtuser_lookup_entry(item); 1247 + struct gpio_virtuser_device *dev = entry->parent->parent; 1248 + 1249 + guard(mutex)(&dev->lock); 1250 + 1251 + if (gpio_virtuser_device_is_live(dev)) 1252 + return -EBUSY; 1253 + 1254 + if (sysfs_streq(page, "pull-up")) { 1255 + entry->flags &= ~(GPIO_PULL_DOWN | GPIO_PULL_DISABLE); 1256 + entry->flags |= GPIO_PULL_UP; 1257 + } else if (sysfs_streq(page, "pull-down")) { 1258 + entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DISABLE); 1259 + entry->flags |= GPIO_PULL_DOWN; 1260 + } else if (sysfs_streq(page, "pull-disabled")) { 1261 + entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN); 1262 + entry->flags |= GPIO_PULL_DISABLE; 1263 + } else if (sysfs_streq(page, "as-is")) { 1264 + entry->flags &= ~(GPIO_PULL_UP | GPIO_PULL_DOWN | 1265 + GPIO_PULL_DISABLE); 1266 + } else { 1267 + count = -EINVAL; 1268 + } 1269 + 1270 + return count; 1271 + } 1272 + 1273 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, pull); 1274 + 1275 + static ssize_t 1276 + gpio_virtuser_lookup_entry_config_active_low_show(struct config_item *item, 1277 + char *page) 1278 + { 1279 + enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item); 1280 + 1281 + return sprintf(page, "%c\n", flags & GPIO_ACTIVE_LOW ? '1' : '0'); 1282 + } 1283 + 1284 + static ssize_t 1285 + gpio_virtuser_lookup_entry_config_active_low_store(struct config_item *item, 1286 + const char *page, 1287 + size_t count) 1288 + { 1289 + struct gpio_virtuser_lookup_entry *entry = 1290 + to_gpio_virtuser_lookup_entry(item); 1291 + struct gpio_virtuser_device *dev = entry->parent->parent; 1292 + bool active_low; 1293 + int ret; 1294 + 1295 + ret = kstrtobool(page, &active_low); 1296 + if (ret) 1297 + return ret; 1298 + 1299 + guard(mutex)(&dev->lock); 1300 + 1301 + if (gpio_virtuser_device_is_live(dev)) 1302 + return -EBUSY; 1303 + 1304 + if (active_low) 1305 + entry->flags |= GPIO_ACTIVE_LOW; 1306 + else 1307 + entry->flags &= ~GPIO_ACTIVE_LOW; 1308 + 1309 + return count; 1310 + } 1311 + 1312 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, active_low); 1313 + 1314 + static ssize_t 1315 + gpio_virtuser_lookup_entry_config_transitory_show(struct config_item *item, 1316 + char *page) 1317 + { 1318 + enum gpio_lookup_flags flags = gpio_virtuser_lookup_get_flags(item); 1319 + 1320 + return sprintf(page, "%c\n", flags & GPIO_TRANSITORY ? '1' : '0'); 1321 + } 1322 + 1323 + static ssize_t 1324 + gpio_virtuser_lookup_entry_config_transitory_store(struct config_item *item, 1325 + const char *page, 1326 + size_t count) 1327 + { 1328 + struct gpio_virtuser_lookup_entry *entry = 1329 + to_gpio_virtuser_lookup_entry(item); 1330 + struct gpio_virtuser_device *dev = entry->parent->parent; 1331 + bool transitory; 1332 + int ret; 1333 + 1334 + ret = kstrtobool(page, &transitory); 1335 + if (ret) 1336 + return ret; 1337 + 1338 + guard(mutex)(&dev->lock); 1339 + 1340 + if (gpio_virtuser_device_is_live(dev)) 1341 + return -EBUSY; 1342 + 1343 + if (transitory) 1344 + entry->flags |= GPIO_TRANSITORY; 1345 + else 1346 + entry->flags &= ~GPIO_TRANSITORY; 1347 + 1348 + return count; 1349 + } 1350 + 1351 + CONFIGFS_ATTR(gpio_virtuser_lookup_entry_config_, transitory); 1352 + 1353 + static struct configfs_attribute *gpio_virtuser_lookup_entry_config_attrs[] = { 1354 + &gpio_virtuser_lookup_entry_config_attr_key, 1355 + &gpio_virtuser_lookup_entry_config_attr_offset, 1356 + &gpio_virtuser_lookup_entry_config_attr_drive, 1357 + &gpio_virtuser_lookup_entry_config_attr_pull, 1358 + &gpio_virtuser_lookup_entry_config_attr_active_low, 1359 + &gpio_virtuser_lookup_entry_config_attr_transitory, 1360 + NULL 1361 + }; 1362 + 1363 + static ssize_t 1364 + gpio_virtuser_device_config_dev_name_show(struct config_item *item, 1365 + char *page) 1366 + { 1367 + struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item); 1368 + struct platform_device *pdev; 1369 + 1370 + guard(mutex)(&dev->lock); 1371 + 1372 + pdev = dev->pdev; 1373 + if (pdev) 1374 + return sprintf(page, "%s\n", dev_name(&pdev->dev)); 1375 + 1376 + return sprintf(page, "gpio-sim.%d\n", dev->id); 1377 + } 1378 + 1379 + CONFIGFS_ATTR_RO(gpio_virtuser_device_config_, dev_name); 1380 + 1381 + static ssize_t gpio_virtuser_device_config_live_show(struct config_item *item, 1382 + char *page) 1383 + { 1384 + struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item); 1385 + bool live; 1386 + 1387 + scoped_guard(mutex, &dev->lock) 1388 + live = gpio_virtuser_device_is_live(dev); 1389 + 1390 + return sprintf(page, "%c\n", live ? '1' : '0'); 1391 + } 1392 + 1393 + static size_t 1394 + gpio_virtuser_get_lookup_count(struct gpio_virtuser_device *dev) 1395 + { 1396 + struct gpio_virtuser_lookup *lookup; 1397 + size_t count = 0; 1398 + 1399 + lockdep_assert_held(&dev->lock); 1400 + 1401 + list_for_each_entry(lookup, &dev->lookup_list, siblings) 1402 + count += list_count_nodes(&lookup->entry_list); 1403 + 1404 + return count; 1405 + } 1406 + 1407 + static int 1408 + gpio_virtuser_make_lookup_table(struct gpio_virtuser_device *dev) 1409 + { 1410 + size_t num_entries = gpio_virtuser_get_lookup_count(dev); 1411 + struct gpio_virtuser_lookup_entry *entry; 1412 + struct gpio_virtuser_lookup *lookup; 1413 + struct gpiod_lookup *curr; 1414 + unsigned int i = 0; 1415 + 1416 + lockdep_assert_held(&dev->lock); 1417 + 1418 + struct gpiod_lookup_table *table __free(kfree) = 1419 + kzalloc(struct_size(table, table, num_entries + 1), GFP_KERNEL); 1420 + if (!table) 1421 + return -ENOMEM; 1422 + 1423 + table->dev_id = kasprintf(GFP_KERNEL, "gpio-virtuser.%d", dev->id); 1424 + if (!table->dev_id) 1425 + return -ENOMEM; 1426 + 1427 + list_for_each_entry(lookup, &dev->lookup_list, siblings) { 1428 + list_for_each_entry(entry, &lookup->entry_list, siblings) { 1429 + curr = &table->table[i]; 1430 + 1431 + curr->con_id = lookup->con_id; 1432 + curr->idx = i; 1433 + curr->key = entry->key; 1434 + curr->chip_hwnum = entry->offset < 0 ? 1435 + U16_MAX : entry->offset; 1436 + curr->flags = entry->flags; 1437 + i++; 1438 + } 1439 + } 1440 + 1441 + gpiod_add_lookup_table(table); 1442 + dev->lookup_table = no_free_ptr(table); 1443 + 1444 + return 0; 1445 + } 1446 + 1447 + static struct fwnode_handle * 1448 + gpio_virtuser_make_device_swnode(struct gpio_virtuser_device *dev) 1449 + { 1450 + struct property_entry properties[2]; 1451 + struct gpio_virtuser_lookup *lookup; 1452 + unsigned int i = 0; 1453 + size_t num_ids; 1454 + 1455 + memset(properties, 0, sizeof(properties)); 1456 + 1457 + num_ids = list_count_nodes(&dev->lookup_list); 1458 + char **ids __free(kfree) = kcalloc(num_ids + 1, sizeof(*ids), 1459 + GFP_KERNEL); 1460 + if (!ids) 1461 + return ERR_PTR(-ENOMEM); 1462 + 1463 + list_for_each_entry(lookup, &dev->lookup_list, siblings) 1464 + ids[i++] = lookup->con_id; 1465 + 1466 + properties[0] = PROPERTY_ENTRY_STRING_ARRAY_LEN("gpio-virtuser,ids", 1467 + ids, num_ids); 1468 + 1469 + return fwnode_create_software_node(properties, NULL); 1470 + } 1471 + 1472 + static int 1473 + gpio_virtuser_device_activate(struct gpio_virtuser_device *dev) 1474 + { 1475 + struct platform_device_info pdevinfo; 1476 + struct fwnode_handle *swnode; 1477 + struct platform_device *pdev; 1478 + int ret; 1479 + 1480 + lockdep_assert_held(&dev->lock); 1481 + 1482 + if (list_empty(&dev->lookup_list)) 1483 + return -ENODATA; 1484 + 1485 + swnode = gpio_virtuser_make_device_swnode(dev); 1486 + if (IS_ERR(swnode)) 1487 + return PTR_ERR(swnode); 1488 + 1489 + memset(&pdevinfo, 0, sizeof(pdevinfo)); 1490 + pdevinfo.name = "gpio-virtuser"; 1491 + pdevinfo.id = dev->id; 1492 + pdevinfo.fwnode = swnode; 1493 + 1494 + ret = gpio_virtuser_make_lookup_table(dev); 1495 + if (ret) { 1496 + fwnode_remove_software_node(swnode); 1497 + return ret; 1498 + } 1499 + 1500 + reinit_completion(&dev->probe_completion); 1501 + dev->driver_bound = false; 1502 + bus_register_notifier(&platform_bus_type, &dev->bus_notifier); 1503 + 1504 + pdev = platform_device_register_full(&pdevinfo); 1505 + if (IS_ERR(pdev)) { 1506 + bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier); 1507 + fwnode_remove_software_node(swnode); 1508 + return PTR_ERR(pdev); 1509 + } 1510 + 1511 + wait_for_completion(&dev->probe_completion); 1512 + bus_unregister_notifier(&platform_bus_type, &dev->bus_notifier); 1513 + 1514 + if (!dev->driver_bound) { 1515 + platform_device_unregister(pdev); 1516 + fwnode_remove_software_node(swnode); 1517 + return -ENXIO; 1518 + } 1519 + 1520 + dev->pdev = pdev; 1521 + 1522 + return 0; 1523 + } 1524 + 1525 + static void 1526 + gpio_virtuser_device_deactivate(struct gpio_virtuser_device *dev) 1527 + { 1528 + struct fwnode_handle *swnode; 1529 + 1530 + lockdep_assert_held(&dev->lock); 1531 + 1532 + swnode = dev_fwnode(&dev->pdev->dev); 1533 + platform_device_unregister(dev->pdev); 1534 + fwnode_remove_software_node(swnode); 1535 + dev->pdev = NULL; 1536 + gpiod_remove_lookup_table(dev->lookup_table); 1537 + kfree(dev->lookup_table); 1538 + } 1539 + 1540 + static ssize_t 1541 + gpio_virtuser_device_config_live_store(struct config_item *item, 1542 + const char *page, size_t count) 1543 + { 1544 + struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item); 1545 + int ret = 0; 1546 + bool live; 1547 + 1548 + ret = kstrtobool(page, &live); 1549 + if (ret) 1550 + return ret; 1551 + 1552 + guard(mutex)(&dev->lock); 1553 + 1554 + if (live == gpio_virtuser_device_is_live(dev)) 1555 + return -EPERM; 1556 + 1557 + if (live) 1558 + ret = gpio_virtuser_device_activate(dev); 1559 + else 1560 + gpio_virtuser_device_deactivate(dev); 1561 + 1562 + return ret ?: count; 1563 + } 1564 + 1565 + CONFIGFS_ATTR(gpio_virtuser_device_config_, live); 1566 + 1567 + static struct configfs_attribute *gpio_virtuser_device_config_attrs[] = { 1568 + &gpio_virtuser_device_config_attr_dev_name, 1569 + &gpio_virtuser_device_config_attr_live, 1570 + NULL 1571 + }; 1572 + 1573 + static void 1574 + gpio_virtuser_lookup_entry_config_group_release(struct config_item *item) 1575 + { 1576 + struct gpio_virtuser_lookup_entry *entry = 1577 + to_gpio_virtuser_lookup_entry(item); 1578 + struct gpio_virtuser_device *dev = entry->parent->parent; 1579 + 1580 + guard(mutex)(&dev->lock); 1581 + 1582 + list_del(&entry->siblings); 1583 + 1584 + kfree(entry->key); 1585 + kfree(entry); 1586 + } 1587 + 1588 + static struct 1589 + configfs_item_operations gpio_virtuser_lookup_entry_config_item_ops = { 1590 + .release = gpio_virtuser_lookup_entry_config_group_release, 1591 + }; 1592 + 1593 + static const struct 1594 + config_item_type gpio_virtuser_lookup_entry_config_group_type = { 1595 + .ct_item_ops = &gpio_virtuser_lookup_entry_config_item_ops, 1596 + .ct_attrs = gpio_virtuser_lookup_entry_config_attrs, 1597 + .ct_owner = THIS_MODULE, 1598 + }; 1599 + 1600 + static struct config_group * 1601 + gpio_virtuser_make_lookup_entry_group(struct config_group *group, 1602 + const char *name) 1603 + { 1604 + struct gpio_virtuser_lookup *lookup = 1605 + to_gpio_virtuser_lookup(&group->cg_item); 1606 + struct gpio_virtuser_device *dev = lookup->parent; 1607 + 1608 + guard(mutex)(&dev->lock); 1609 + 1610 + if (gpio_virtuser_device_is_live(dev)) 1611 + return ERR_PTR(-EBUSY); 1612 + 1613 + struct gpio_virtuser_lookup_entry *entry __free(kfree) = 1614 + kzalloc(sizeof(*entry), GFP_KERNEL); 1615 + if (!entry) 1616 + return ERR_PTR(-ENOMEM); 1617 + 1618 + config_group_init_type_name(&entry->group, name, 1619 + &gpio_virtuser_lookup_entry_config_group_type); 1620 + entry->flags = GPIO_LOOKUP_FLAGS_DEFAULT; 1621 + entry->parent = lookup; 1622 + list_add_tail(&entry->siblings, &lookup->entry_list); 1623 + 1624 + return &no_free_ptr(entry)->group; 1625 + } 1626 + 1627 + static void gpio_virtuser_lookup_config_group_release(struct config_item *item) 1628 + { 1629 + struct gpio_virtuser_lookup *lookup = to_gpio_virtuser_lookup(item); 1630 + struct gpio_virtuser_device *dev = lookup->parent; 1631 + 1632 + guard(mutex)(&dev->lock); 1633 + 1634 + list_del(&lookup->siblings); 1635 + 1636 + kfree(lookup->con_id); 1637 + kfree(lookup); 1638 + } 1639 + 1640 + static struct configfs_item_operations gpio_virtuser_lookup_config_item_ops = { 1641 + .release = gpio_virtuser_lookup_config_group_release, 1642 + }; 1643 + 1644 + static struct 1645 + configfs_group_operations gpio_virtuser_lookup_config_group_ops = { 1646 + .make_group = gpio_virtuser_make_lookup_entry_group, 1647 + }; 1648 + 1649 + static const struct config_item_type gpio_virtuser_lookup_config_group_type = { 1650 + .ct_group_ops = &gpio_virtuser_lookup_config_group_ops, 1651 + .ct_item_ops = &gpio_virtuser_lookup_config_item_ops, 1652 + .ct_owner = THIS_MODULE, 1653 + }; 1654 + 1655 + static struct config_group * 1656 + gpio_virtuser_make_lookup_group(struct config_group *group, const char *name) 1657 + { 1658 + struct gpio_virtuser_device *dev = 1659 + to_gpio_virtuser_device(&group->cg_item); 1660 + 1661 + if (strlen(name) > (GPIO_VIRTUSER_NAME_BUF_LEN - 1)) 1662 + return ERR_PTR(-E2BIG); 1663 + 1664 + guard(mutex)(&dev->lock); 1665 + 1666 + if (gpio_virtuser_device_is_live(dev)) 1667 + return ERR_PTR(-EBUSY); 1668 + 1669 + struct gpio_virtuser_lookup *lookup __free(kfree) = 1670 + kzalloc(sizeof(*lookup), GFP_KERNEL); 1671 + if (!lookup) 1672 + return ERR_PTR(-ENOMEM); 1673 + 1674 + lookup->con_id = kstrdup(name, GFP_KERNEL); 1675 + if (!lookup->con_id) 1676 + return ERR_PTR(-ENOMEM); 1677 + 1678 + config_group_init_type_name(&lookup->group, name, 1679 + &gpio_virtuser_lookup_config_group_type); 1680 + INIT_LIST_HEAD(&lookup->entry_list); 1681 + lookup->parent = dev; 1682 + list_add_tail(&lookup->siblings, &dev->lookup_list); 1683 + 1684 + return &no_free_ptr(lookup)->group; 1685 + } 1686 + 1687 + static void gpio_virtuser_device_config_group_release(struct config_item *item) 1688 + { 1689 + struct gpio_virtuser_device *dev = to_gpio_virtuser_device(item); 1690 + 1691 + guard(mutex)(&dev->lock); 1692 + 1693 + if (gpio_virtuser_device_is_live(dev)) 1694 + gpio_virtuser_device_deactivate(dev); 1695 + 1696 + mutex_destroy(&dev->lock); 1697 + ida_free(&gpio_virtuser_ida, dev->id); 1698 + kfree(dev); 1699 + } 1700 + 1701 + static struct configfs_item_operations gpio_virtuser_device_config_item_ops = { 1702 + .release = gpio_virtuser_device_config_group_release, 1703 + }; 1704 + 1705 + static struct configfs_group_operations gpio_virtuser_device_config_group_ops = { 1706 + .make_group = gpio_virtuser_make_lookup_group, 1707 + }; 1708 + 1709 + static const struct config_item_type gpio_virtuser_device_config_group_type = { 1710 + .ct_group_ops = &gpio_virtuser_device_config_group_ops, 1711 + .ct_item_ops = &gpio_virtuser_device_config_item_ops, 1712 + .ct_attrs = gpio_virtuser_device_config_attrs, 1713 + .ct_owner = THIS_MODULE, 1714 + }; 1715 + 1716 + static struct config_group * 1717 + gpio_virtuser_config_make_device_group(struct config_group *group, 1718 + const char *name) 1719 + { 1720 + struct gpio_virtuser_device *dev __free(kfree) = kzalloc(sizeof(*dev), 1721 + GFP_KERNEL); 1722 + if (!dev) 1723 + return ERR_PTR(-ENOMEM); 1724 + 1725 + dev->id = ida_alloc(&gpio_virtuser_ida, GFP_KERNEL); 1726 + if (dev->id < 0) 1727 + return ERR_PTR(dev->id); 1728 + 1729 + config_group_init_type_name(&dev->group, name, 1730 + &gpio_virtuser_device_config_group_type); 1731 + mutex_init(&dev->lock); 1732 + INIT_LIST_HEAD(&dev->lookup_list); 1733 + dev->bus_notifier.notifier_call = gpio_virtuser_bus_notifier_call; 1734 + init_completion(&dev->probe_completion); 1735 + 1736 + return &no_free_ptr(dev)->group; 1737 + } 1738 + 1739 + static struct configfs_group_operations gpio_virtuser_config_group_ops = { 1740 + .make_group = gpio_virtuser_config_make_device_group, 1741 + }; 1742 + 1743 + static const struct config_item_type gpio_virtuser_config_type = { 1744 + .ct_group_ops = &gpio_virtuser_config_group_ops, 1745 + .ct_owner = THIS_MODULE, 1746 + }; 1747 + 1748 + static struct configfs_subsystem gpio_virtuser_config_subsys = { 1749 + .su_group = { 1750 + .cg_item = { 1751 + .ci_namebuf = "gpio-virtuser", 1752 + .ci_type = &gpio_virtuser_config_type, 1753 + }, 1754 + }, 1755 + }; 1756 + 1757 + static int __init gpio_virtuser_init(void) 1758 + { 1759 + int ret; 1760 + 1761 + ret = platform_driver_register(&gpio_virtuser_driver); 1762 + if (ret) { 1763 + pr_err("Failed to register the platform driver: %d\n", ret); 1764 + return ret; 1765 + } 1766 + 1767 + config_group_init(&gpio_virtuser_config_subsys.su_group); 1768 + mutex_init(&gpio_virtuser_config_subsys.su_mutex); 1769 + ret = configfs_register_subsystem(&gpio_virtuser_config_subsys); 1770 + if (ret) { 1771 + pr_err("Failed to register the '%s' configfs subsystem: %d\n", 1772 + gpio_virtuser_config_subsys.su_group.cg_item.ci_namebuf, 1773 + ret); 1774 + goto err_plat_drv_unreg; 1775 + } 1776 + 1777 + gpio_virtuser_dbg_root = debugfs_create_dir("gpio-virtuser", NULL); 1778 + if (IS_ERR(gpio_virtuser_dbg_root)) { 1779 + ret = PTR_ERR(gpio_virtuser_dbg_root); 1780 + pr_err("Failed to create the debugfs tree: %d\n", ret); 1781 + goto err_configfs_unreg; 1782 + } 1783 + 1784 + return 0; 1785 + 1786 + err_configfs_unreg: 1787 + configfs_unregister_subsystem(&gpio_virtuser_config_subsys); 1788 + err_plat_drv_unreg: 1789 + mutex_destroy(&gpio_virtuser_config_subsys.su_mutex); 1790 + platform_driver_unregister(&gpio_virtuser_driver); 1791 + 1792 + return ret; 1793 + } 1794 + module_init(gpio_virtuser_init); 1795 + 1796 + static void __exit gpio_virtuser_exit(void) 1797 + { 1798 + configfs_unregister_subsystem(&gpio_virtuser_config_subsys); 1799 + mutex_destroy(&gpio_virtuser_config_subsys.su_mutex); 1800 + platform_driver_unregister(&gpio_virtuser_driver); 1801 + debugfs_remove_recursive(gpio_virtuser_dbg_root); 1802 + } 1803 + module_exit(gpio_virtuser_exit); 1804 + 1805 + MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>"); 1806 + MODULE_DESCRIPTION("Virtual GPIO consumer module"); 1807 + MODULE_LICENSE("GPL");