]> git.dujemihanovic.xyz Git - linux.git/commitdiff
gpiolib: cdev: fix uninitialised kfifo
authorKent Gibson <warthog618@gmail.com>
Fri, 10 May 2024 06:53:42 +0000 (14:53 +0800)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Fri, 10 May 2024 14:38:27 +0000 (16:38 +0200)
If a line is requested with debounce, and that results in debouncing
in software, and the line is subsequently reconfigured to enable edge
detection then the allocation of the kfifo to contain edge events is
overlooked.  This results in events being written to and read from an
uninitialised kfifo.  Read events are returned to userspace.

Initialise the kfifo in the case where the software debounce is
already active.

Fixes: 65cff7046406 ("gpiolib: cdev: support setting debounce")
Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://lore.kernel.org/r/20240510065342.36191-1-warthog618@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpiolib-cdev.c

index 46a45093d4d0da7738ae286281e67adaf92452f9..9dad67ea25974ea4c2dd68d267d728af7603f2bc 100644 (file)
@@ -1193,6 +1193,8 @@ static int edge_detector_update(struct line *line,
                                struct gpio_v2_line_config *lc,
                                unsigned int line_idx, u64 edflags)
 {
+       u64 eflags;
+       int ret;
        u64 active_edflags = READ_ONCE(line->edflags);
        unsigned int debounce_period_us =
                        gpio_v2_line_config_debounce_period(lc, line_idx);
@@ -1204,6 +1206,18 @@ static int edge_detector_update(struct line *line,
        /* sw debounced and still will be...*/
        if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
                line_set_debounce_period(line, debounce_period_us);
+               /*
+                * ensure event fifo is initialised if edge detection
+                * is now enabled.
+                */
+               eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
+               if (eflags && !kfifo_initialized(&line->req->events)) {
+                       ret = kfifo_alloc(&line->req->events,
+                                         line->req->event_buffer_size,
+                                         GFP_KERNEL);
+                       if (ret)
+                               return ret;
+               }
                return 0;
        }