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-fixes-for-v6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:

- fix spinlock op type after conversion to lock guards

- fix a memory leak in error path in gpio-regmap

- Kconfig fixes in GPIO drivers

- add a GPIO ACPI quirk for Dell Precision 7780

- set of fixes for shared GPIO management

* tag 'gpio-fixes-for-v6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
gpio: shared: make locking more fine-grained
gpio: shared: fix auxiliary device cleanup order
gpio: shared: check if a reference is populated before cleaning its resources
gpio: shared: fix NULL-pointer dereference in teardown path
gpio: shared: ignore disabled nodes when traversing the device-tree
gpiolib: acpi: Add quirk for Dell Precision 7780
gpio: tb10x: fix OF_GPIO dependency
gpio: qixis: select CONFIG_REGMAP_MMIO
gpio: regmap: Fix memleak in error path in gpio_regmap_register()
gpio: mmio: fix bad guard conversion

+63 -27
+1 -1
drivers/gpio/Kconfig
··· 737 737 depends on ARC_PLAT_TB10X || COMPILE_TEST 738 738 select GPIO_GENERIC 739 739 select GENERIC_IRQ_CHIP 740 - select OF_GPIO 741 740 742 741 config GPIO_TEGRA 743 742 tristate "NVIDIA Tegra GPIO support" ··· 1567 1568 tristate "NXP QIXIS FPGA GPIO support" 1568 1569 depends on MFD_SIMPLE_MFD_I2C || COMPILE_TEST 1569 1570 select GPIO_REGMAP 1571 + select REGMAP_MMIO 1570 1572 help 1571 1573 This enables support for the GPIOs found in the QIXIS FPGA which is 1572 1574 integrated on some NXP Layerscape boards such as LX2160ARDB and
+5 -5
drivers/gpio/gpio-mmio.c
··· 231 231 struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); 232 232 unsigned long mask = gpio_mmio_line2mask(gc, gpio); 233 233 234 - guard(raw_spinlock)(&chip->lock); 234 + guard(raw_spinlock_irqsave)(&chip->lock); 235 235 236 236 if (val) 237 237 chip->sdata |= mask; ··· 262 262 struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); 263 263 unsigned long mask = gpio_mmio_line2mask(gc, gpio); 264 264 265 - guard(raw_spinlock)(&chip->lock); 265 + guard(raw_spinlock_irqsave)(&chip->lock); 266 266 267 267 if (val) 268 268 chip->sdata |= mask; ··· 302 302 struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); 303 303 unsigned long set_mask, clear_mask; 304 304 305 - guard(raw_spinlock)(&chip->lock); 305 + guard(raw_spinlock_irqsave)(&chip->lock); 306 306 307 307 gpio_mmio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask); 308 308 ··· 391 391 { 392 392 struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); 393 393 394 - scoped_guard(raw_spinlock, &chip->lock) { 394 + scoped_guard(raw_spinlock_irqsave, &chip->lock) { 395 395 chip->sdir &= ~gpio_mmio_line2mask(gc, gpio); 396 396 397 397 if (chip->reg_dir_in) ··· 431 431 { 432 432 struct gpio_generic_chip *chip = to_gpio_generic_chip(gc); 433 433 434 - guard(raw_spinlock)(&chip->lock); 434 + guard(raw_spinlock_irqsave)(&chip->lock); 435 435 436 436 chip->sdir |= gpio_mmio_line2mask(gc, gpio); 437 437
+1 -1
drivers/gpio/gpio-regmap.c
··· 338 338 config->regmap_irq_line, config->regmap_irq_flags, 339 339 0, config->regmap_irq_chip, &gpio->irq_chip_data); 340 340 if (ret) 341 - goto err_free_bitmap; 341 + goto err_remove_gpiochip; 342 342 343 343 irq_domain = regmap_irq_get_domain(gpio->irq_chip_data); 344 344 } else
+22
drivers/gpio/gpiolib-acpi-quirks.c
··· 370 370 .ignore_wake = "ASCP1A00:00@8", 371 371 }, 372 372 }, 373 + { 374 + /* 375 + * Spurious wakeups, likely from touchpad controller 376 + * Dell Precision 7780 377 + * Found in BIOS 1.24.1 378 + * 379 + * Found in touchpad firmware, installed by Dell Touchpad Firmware Update Utility version 1160.4196.9, A01 380 + * ( Dell-Touchpad-Firmware-Update-Utility_VYGNN_WIN64_1160.4196.9_A00.EXE ), 381 + * released on 11 Jul 2024 382 + * 383 + * https://lore.kernel.org/linux-i2c/197ae95ffd8.dc819e60457077.7692120488609091556@zohomail.com/ 384 + */ 385 + .matches = { 386 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 387 + DMI_MATCH(DMI_PRODUCT_FAMILY, "Precision"), 388 + DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7780"), 389 + DMI_MATCH(DMI_BOARD_NAME, "0C6JVW"), 390 + }, 391 + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { 392 + .ignore_wake = "VEN_0488:00@355", 393 + }, 394 + }, 373 395 {} /* Terminating entry */ 374 396 }; 375 397
+34 -20
drivers/gpio/gpiolib-shared.c
··· 36 36 enum gpiod_flags flags; 37 37 char *con_id; 38 38 int dev_id; 39 + /* Protects the auxiliary device struct and the lookup table. */ 40 + struct mutex lock; 39 41 struct auxiliary_device adev; 40 42 struct gpiod_lookup_table *lookup; 41 43 }; ··· 51 49 unsigned int offset; 52 50 /* Index in the property value array. */ 53 51 size_t index; 52 + /* Synchronizes the modification of shared_desc. */ 54 53 struct mutex lock; 55 54 struct gpio_shared_desc *shared_desc; 56 55 struct kref ref; ··· 59 56 }; 60 57 61 58 static LIST_HEAD(gpio_shared_list); 62 - static DEFINE_MUTEX(gpio_shared_lock); 63 59 static DEFINE_IDA(gpio_shared_ida); 64 60 65 61 #if IS_ENABLED(CONFIG_OF) ··· 79 77 /* Handle all special nodes that we should ignore. */ 80 78 static bool gpio_shared_of_node_ignore(struct device_node *node) 81 79 { 80 + /* Ignore disabled devices. */ 81 + if (!of_device_is_available(node)) 82 + return true; 83 + 82 84 /* 83 85 * __symbols__ is a special, internal node and should not be considered 84 86 * when scanning for shared GPIOs. ··· 189 183 190 184 ref->fwnode = fwnode_handle_get(of_fwnode_handle(curr)); 191 185 ref->flags = args.args[1]; 186 + mutex_init(&ref->lock); 192 187 193 188 if (strends(prop->name, "gpios")) 194 189 suffix = "-gpios"; ··· 261 254 struct auxiliary_device *adev = &ref->adev; 262 255 int ret; 263 256 264 - lockdep_assert_held(&gpio_shared_lock); 257 + guard(mutex)(&ref->lock); 265 258 266 259 memset(adev, 0, sizeof(*adev)); 267 260 ··· 376 369 if (!lookup) 377 370 return -ENOMEM; 378 371 379 - guard(mutex)(&gpio_shared_lock); 380 - 381 372 list_for_each_entry(entry, &gpio_shared_list, list) { 382 373 list_for_each_entry(ref, &entry->refs, list) { 383 374 if (!device_match_fwnode(consumer, ref->fwnode) && 384 375 !gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) 385 376 continue; 377 + 378 + guard(mutex)(&ref->lock); 386 379 387 380 /* We've already done that on a previous request. */ 388 381 if (ref->lookup) ··· 402 395 lookup->table[0] = GPIO_LOOKUP(no_free_ptr(key), 0, 403 396 ref->con_id, lflags); 404 397 405 - gpiod_add_lookup_table(no_free_ptr(lookup)); 398 + ref->lookup = no_free_ptr(lookup); 399 + gpiod_add_lookup_table(ref->lookup); 406 400 407 401 return 0; 408 402 } ··· 416 408 417 409 static void gpio_shared_remove_adev(struct auxiliary_device *adev) 418 410 { 419 - lockdep_assert_held(&gpio_shared_lock); 420 - 421 - auxiliary_device_uninit(adev); 422 411 auxiliary_device_delete(adev); 412 + auxiliary_device_uninit(adev); 423 413 } 424 414 425 415 int gpio_device_setup_shared(struct gpio_device *gdev) ··· 426 420 struct gpio_shared_ref *ref; 427 421 unsigned long *flags; 428 422 int ret; 429 - 430 - guard(mutex)(&gpio_shared_lock); 431 423 432 424 list_for_each_entry(entry, &gpio_shared_list, list) { 433 425 list_for_each_entry(ref, &entry->refs, list) { ··· 483 479 struct gpio_shared_entry *entry; 484 480 struct gpio_shared_ref *ref; 485 481 486 - guard(mutex)(&gpio_shared_lock); 487 - 488 482 list_for_each_entry(entry, &gpio_shared_list, list) { 489 483 if (!device_match_fwnode(&gdev->dev, entry->fwnode)) 490 484 continue; 491 485 486 + /* 487 + * For some reason if we call synchronize_srcu() in GPIO core, 488 + * descent here and take this mutex and then recursively call 489 + * synchronize_srcu() again from gpiochip_remove() (which is 490 + * totally fine) called after gpio_shared_remove_adev(), 491 + * lockdep prints a false positive deadlock splat. Disable 492 + * lockdep here. 493 + */ 494 + lockdep_off(); 492 495 list_for_each_entry(ref, &entry->refs, list) { 493 - gpiod_remove_lookup_table(ref->lookup); 494 - kfree(ref->lookup->table[0].key); 495 - kfree(ref->lookup); 496 - ref->lookup = NULL; 496 + guard(mutex)(&ref->lock); 497 + 498 + if (ref->lookup) { 499 + gpiod_remove_lookup_table(ref->lookup); 500 + kfree(ref->lookup->table[0].key); 501 + kfree(ref->lookup); 502 + ref->lookup = NULL; 503 + } 504 + 497 505 gpio_shared_remove_adev(&ref->adev); 498 506 } 507 + lockdep_on(); 499 508 } 500 509 } 501 510 ··· 531 514 static void gpiod_shared_put(void *data) 532 515 { 533 516 struct gpio_shared_entry *entry = data; 534 - 535 - lockdep_assert_not_held(&gpio_shared_lock); 536 517 537 518 kref_put(&entry->ref, gpio_shared_release); 538 519 } ··· 569 554 struct gpio_shared_entry *entry; 570 555 int ret; 571 556 572 - lockdep_assert_not_held(&gpio_shared_lock); 573 - 574 557 entry = dev_get_platdata(dev); 575 558 if (WARN_ON(!entry)) 576 559 /* Programmer bug */ ··· 603 590 static void gpio_shared_drop_ref(struct gpio_shared_ref *ref) 604 591 { 605 592 list_del(&ref->list); 593 + mutex_destroy(&ref->lock); 606 594 kfree(ref->con_id); 607 595 ida_free(&gpio_shared_ida, ref->dev_id); 608 596 fwnode_handle_put(ref->fwnode);