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

gpio: sysfs: move irq trigger flags to class-device data

Move irq trigger flags, which as sysfs-interface specific, to the class
device data.

This avoids accessing the gpio-descriptor flags field using non-atomic
operations without any locking, and allows for a more clear separation
of the sysfs interface from gpiolib core.

Signed-off-by: Johan Hovold <johan@kernel.org>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Johan Hovold and committed by
Linus Walleij
cef1717b 427fdeef

+24 -27
+24 -23
drivers/gpio/gpiolib-sysfs.c
··· 10 10 11 11 #include "gpiolib.h" 12 12 13 + #define GPIO_IRQF_TRIGGER_FALLING BIT(0) 14 + #define GPIO_IRQF_TRIGGER_RISING BIT(1) 15 + #define GPIO_IRQF_TRIGGER_BOTH (GPIO_IRQF_TRIGGER_FALLING | \ 16 + GPIO_IRQF_TRIGGER_RISING) 17 + 13 18 struct gpiod_data { 14 19 struct gpio_desc *desc; 15 20 16 21 struct mutex mutex; 17 22 struct kernfs_node *value_kn; 18 23 int irq; 24 + unsigned char irq_flags; 19 25 20 26 bool direction_can_change; 21 27 }; ··· 149 143 } 150 144 151 145 /* Caller holds gpiod-data mutex. */ 152 - static int gpio_sysfs_request_irq(struct device *dev, unsigned long gpio_flags) 146 + static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags) 153 147 { 154 148 struct gpiod_data *data = dev_get_drvdata(dev); 155 149 struct gpio_desc *desc = data->desc; ··· 165 159 return -ENODEV; 166 160 167 161 irq_flags = IRQF_SHARED; 168 - if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) 162 + if (flags & GPIO_IRQF_TRIGGER_FALLING) 169 163 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? 170 164 IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; 171 - if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) 165 + if (flags & GPIO_IRQF_TRIGGER_RISING) 172 166 irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? 173 167 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; 174 168 ··· 189 183 if (ret < 0) 190 184 goto err_unlock; 191 185 192 - desc->flags |= gpio_flags; 186 + data->irq_flags = flags; 193 187 194 188 return 0; 195 189 ··· 210 204 struct gpiod_data *data = dev_get_drvdata(dev); 211 205 struct gpio_desc *desc = data->desc; 212 206 213 - desc->flags &= ~GPIO_TRIGGER_MASK; 207 + data->irq_flags = 0; 214 208 free_irq(data->irq, data); 215 209 gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc)); 216 210 sysfs_put(data->value_kn); ··· 218 212 219 213 static const struct { 220 214 const char *name; 221 - unsigned long flags; 215 + unsigned char flags; 222 216 } trigger_types[] = { 223 217 { "none", 0 }, 224 - { "falling", BIT(FLAG_TRIG_FALL) }, 225 - { "rising", BIT(FLAG_TRIG_RISE) }, 226 - { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) }, 218 + { "falling", GPIO_IRQF_TRIGGER_FALLING }, 219 + { "rising", GPIO_IRQF_TRIGGER_RISING }, 220 + { "both", GPIO_IRQF_TRIGGER_BOTH }, 227 221 }; 228 222 229 223 static ssize_t edge_show(struct device *dev, 230 224 struct device_attribute *attr, char *buf) 231 225 { 232 226 struct gpiod_data *data = dev_get_drvdata(dev); 233 - struct gpio_desc *desc = data->desc; 234 - unsigned long mask; 235 227 ssize_t status = 0; 236 228 int i; 237 229 238 230 mutex_lock(&data->mutex); 239 231 240 232 for (i = 0; i < ARRAY_SIZE(trigger_types); i++) { 241 - mask = desc->flags & GPIO_TRIGGER_MASK; 242 - if (mask == trigger_types[i].flags) { 233 + if (data->irq_flags == trigger_types[i].flags) { 243 234 status = sprintf(buf, "%s\n", trigger_types[i].name); 244 235 break; 245 236 } ··· 251 248 struct device_attribute *attr, const char *buf, size_t size) 252 249 { 253 250 struct gpiod_data *data = dev_get_drvdata(dev); 254 - struct gpio_desc *desc = data->desc; 255 - unsigned long flags; 251 + unsigned char flags; 256 252 ssize_t status = size; 257 253 int i; 258 254 ··· 267 265 268 266 mutex_lock(&data->mutex); 269 267 270 - if ((desc->flags & GPIO_TRIGGER_MASK) == flags) { 268 + if (flags == data->irq_flags) { 271 269 status = size; 272 270 goto out_unlock; 273 271 } 274 272 275 - if (desc->flags & GPIO_TRIGGER_MASK) 273 + if (data->irq_flags) 276 274 gpio_sysfs_free_irq(dev); 277 275 278 276 if (flags) { ··· 294 292 struct gpiod_data *data = dev_get_drvdata(dev); 295 293 struct gpio_desc *desc = data->desc; 296 294 int status = 0; 295 + unsigned int flags = data->irq_flags; 297 296 298 297 if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value) 299 298 return 0; ··· 305 302 clear_bit(FLAG_ACTIVE_LOW, &desc->flags); 306 303 307 304 /* reconfigure poll(2) support if enabled on one edge only */ 308 - if (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^ 309 - !!test_bit(FLAG_TRIG_FALL, &desc->flags)) { 310 - unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK; 311 - 305 + if (flags == GPIO_IRQF_TRIGGER_FALLING || 306 + flags == GPIO_IRQF_TRIGGER_RISING) { 312 307 gpio_sysfs_free_irq(dev); 313 - status = gpio_sysfs_request_irq(dev, trigger_flags); 308 + status = gpio_sysfs_request_irq(dev, flags); 314 309 } 315 310 316 311 return status; ··· 701 700 /* 702 701 * Release irq after deregistration to prevent race with edge_store. 703 702 */ 704 - if (desc->flags & GPIO_TRIGGER_MASK) 703 + if (data->irq_flags) 705 704 gpio_sysfs_free_irq(dev); 706 705 707 706 mutex_unlock(&sysfs_lock);
-4
drivers/gpio/gpiolib.h
··· 83 83 #define FLAG_IS_OUT 1 84 84 #define FLAG_EXPORT 2 /* protected by sysfs_lock */ 85 85 #define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */ 86 - #define FLAG_TRIG_FALL 4 /* trigger on falling edge */ 87 - #define FLAG_TRIG_RISE 5 /* trigger on rising edge */ 88 86 #define FLAG_ACTIVE_LOW 6 /* value has active low */ 89 87 #define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */ 90 88 #define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */ 91 89 #define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */ 92 90 #define FLAG_IS_HOGGED 11 /* GPIO is hogged */ 93 - 94 - #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) 95 91 96 92 const char *label; 97 93 };