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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'gpio-v4.18-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fix from Linus Walleij:
"This is a single fix affecting X86 ACPI, and as such pretty important.

It is going to stable as well and have all the high-notch x86 platform
developers agreeing on it"

* tag 'gpio-v4.18-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
gpiolib-acpi: make sure we trigger edge events at least once on boot

+55 -1
+55 -1
drivers/gpio/gpiolib-acpi.c
··· 25 25 26 26 struct acpi_gpio_event { 27 27 struct list_head node; 28 + struct list_head initial_sync_list; 28 29 acpi_handle handle; 29 30 unsigned int pin; 30 31 unsigned int irq; ··· 50 49 struct gpio_chip *chip; 51 50 struct list_head events; 52 51 }; 52 + 53 + static LIST_HEAD(acpi_gpio_initial_sync_list); 54 + static DEFINE_MUTEX(acpi_gpio_initial_sync_list_lock); 53 55 54 56 static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) 55 57 { ··· 87 83 return ERR_PTR(-EPROBE_DEFER); 88 84 89 85 return gpiochip_get_desc(chip, pin); 86 + } 87 + 88 + static void acpi_gpio_add_to_initial_sync_list(struct acpi_gpio_event *event) 89 + { 90 + mutex_lock(&acpi_gpio_initial_sync_list_lock); 91 + list_add(&event->initial_sync_list, &acpi_gpio_initial_sync_list); 92 + mutex_unlock(&acpi_gpio_initial_sync_list_lock); 93 + } 94 + 95 + static void acpi_gpio_del_from_initial_sync_list(struct acpi_gpio_event *event) 96 + { 97 + mutex_lock(&acpi_gpio_initial_sync_list_lock); 98 + if (!list_empty(&event->initial_sync_list)) 99 + list_del_init(&event->initial_sync_list); 100 + mutex_unlock(&acpi_gpio_initial_sync_list_lock); 90 101 } 91 102 92 103 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data) ··· 155 136 irq_handler_t handler = NULL; 156 137 struct gpio_desc *desc; 157 138 unsigned long irqflags; 158 - int ret, pin, irq; 139 + int ret, pin, irq, value; 159 140 160 141 if (!acpi_gpio_get_irq_resource(ares, &agpio)) 161 142 return AE_OK; ··· 185 166 } 186 167 187 168 gpiod_direction_input(desc); 169 + 170 + value = gpiod_get_value(desc); 188 171 189 172 ret = gpiochip_lock_as_irq(chip, pin); 190 173 if (ret) { ··· 229 208 event->irq = irq; 230 209 event->pin = pin; 231 210 event->desc = desc; 211 + INIT_LIST_HEAD(&event->initial_sync_list); 232 212 233 213 ret = request_threaded_irq(event->irq, NULL, handler, irqflags, 234 214 "ACPI:Event", event); ··· 244 222 enable_irq_wake(irq); 245 223 246 224 list_add_tail(&event->node, &acpi_gpio->events); 225 + 226 + /* 227 + * Make sure we trigger the initial state of the IRQ when using RISING 228 + * or FALLING. Note we run the handlers on late_init, the AML code 229 + * may refer to OperationRegions from other (builtin) drivers which 230 + * may be probed after us. 231 + */ 232 + if (handler == acpi_gpio_irq_handler && 233 + (((irqflags & IRQF_TRIGGER_RISING) && value == 1) || 234 + ((irqflags & IRQF_TRIGGER_FALLING) && value == 0))) 235 + acpi_gpio_add_to_initial_sync_list(event); 236 + 247 237 return AE_OK; 248 238 249 239 fail_free_event: ··· 327 293 328 294 list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { 329 295 struct gpio_desc *desc; 296 + 297 + acpi_gpio_del_from_initial_sync_list(event); 330 298 331 299 if (irqd_is_wakeup_set(irq_get_irq_data(event->irq))) 332 300 disable_irq_wake(event->irq); ··· 1194 1158 1195 1159 return con_id == NULL; 1196 1160 } 1161 + 1162 + /* Sync the initial state of handlers after all builtin drivers have probed */ 1163 + static int acpi_gpio_initial_sync(void) 1164 + { 1165 + struct acpi_gpio_event *event, *ep; 1166 + 1167 + mutex_lock(&acpi_gpio_initial_sync_list_lock); 1168 + list_for_each_entry_safe(event, ep, &acpi_gpio_initial_sync_list, 1169 + initial_sync_list) { 1170 + acpi_evaluate_object(event->handle, NULL, NULL, NULL); 1171 + list_del_init(&event->initial_sync_list); 1172 + } 1173 + mutex_unlock(&acpi_gpio_initial_sync_list_lock); 1174 + 1175 + return 0; 1176 + } 1177 + /* We must use _sync so that this runs after the first deferred_probe run */ 1178 + late_initcall_sync(acpi_gpio_initial_sync);