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

leds: trigger: gpio: Use threaded IRQ

This both simplifies the code because we can drop the workqueue
indirection, and it enables using the trigger for GPIOs that work with
threaded IRQs themselves.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>

authored by

Jan Kiszka and committed by
Jacek Anaszewski
71c17b06 71afe3cb

+6 -23
+6 -23
drivers/leds/trigger/ledtrig-gpio.c
··· 14 14 #include <linux/init.h> 15 15 #include <linux/gpio.h> 16 16 #include <linux/interrupt.h> 17 - #include <linux/workqueue.h> 18 17 #include <linux/leds.h> 19 18 #include <linux/slab.h> 20 19 #include "../leds.h" 21 20 22 21 struct gpio_trig_data { 23 22 struct led_classdev *led; 24 - struct work_struct work; 25 23 26 24 unsigned desired_brightness; /* desired brightness when led is on */ 27 25 unsigned inverted; /* true when gpio is inverted */ ··· 30 32 { 31 33 struct led_classdev *led = _led; 32 34 struct gpio_trig_data *gpio_data = led->trigger_data; 33 - 34 - /* just schedule_work since gpio_get_value can sleep */ 35 - schedule_work(&gpio_data->work); 36 - 37 - return IRQ_HANDLED; 38 - }; 39 - 40 - static void gpio_trig_work(struct work_struct *work) 41 - { 42 - struct gpio_trig_data *gpio_data = container_of(work, 43 - struct gpio_trig_data, work); 44 35 int tmp; 45 - 46 - if (!gpio_data->gpio) 47 - return; 48 36 49 37 tmp = gpio_get_value_cansleep(gpio_data->gpio); 50 38 if (gpio_data->inverted) ··· 45 61 } else { 46 62 led_set_brightness_nosleep(gpio_data->led, LED_OFF); 47 63 } 64 + 65 + return IRQ_HANDLED; 48 66 } 49 67 50 68 static ssize_t gpio_trig_brightness_show(struct device *dev, ··· 106 120 gpio_data->inverted = inverted; 107 121 108 122 /* After inverting, we need to update the LED. */ 109 - schedule_work(&gpio_data->work); 123 + gpio_trig_irq(0, led); 110 124 111 125 return n; 112 126 } ··· 133 147 ret = sscanf(buf, "%u", &gpio); 134 148 if (ret < 1) { 135 149 dev_err(dev, "couldn't read gpio number\n"); 136 - flush_work(&gpio_data->work); 137 150 return -EINVAL; 138 151 } 139 152 ··· 146 161 return n; 147 162 } 148 163 149 - ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq, 150 - IRQF_SHARED | IRQF_TRIGGER_RISING 164 + ret = request_threaded_irq(gpio_to_irq(gpio), NULL, gpio_trig_irq, 165 + IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING 151 166 | IRQF_TRIGGER_FALLING, "ledtrig-gpio", led); 152 167 if (ret) { 153 168 dev_err(dev, "request_irq failed with error %d\n", ret); ··· 156 171 free_irq(gpio_to_irq(gpio_data->gpio), led); 157 172 gpio_data->gpio = gpio; 158 173 /* After changing the GPIO, we need to update the LED. */ 159 - schedule_work(&gpio_data->work); 174 + gpio_trig_irq(0, led); 160 175 } 161 176 162 177 return ret ? ret : n; ··· 186 201 187 202 gpio_data->led = led; 188 203 led->trigger_data = gpio_data; 189 - INIT_WORK(&gpio_data->work, gpio_trig_work); 190 204 led->activated = true; 191 205 192 206 return; ··· 208 224 device_remove_file(led->dev, &dev_attr_gpio); 209 225 device_remove_file(led->dev, &dev_attr_inverted); 210 226 device_remove_file(led->dev, &dev_attr_desired_brightness); 211 - flush_work(&gpio_data->work); 212 227 if (gpio_data->gpio != 0) 213 228 free_irq(gpio_to_irq(gpio_data->gpio), led); 214 229 kfree(gpio_data);