Skip to content

Commit a6bb419

Browse files
committed
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
2 parents 41572e2 + ea513dd commit a6bb419

5 files changed

Lines changed: 63 additions & 27 deletions

File tree

drivers/gpio/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,6 @@ config GPIO_TB10X
737737
depends on ARC_PLAT_TB10X || COMPILE_TEST
738738
select GPIO_GENERIC
739739
select GENERIC_IRQ_CHIP
740-
select OF_GPIO
741740

742741
config GPIO_TEGRA
743742
tristate "NVIDIA Tegra GPIO support"
@@ -1568,6 +1567,7 @@ config GPIO_QIXIS_FPGA
15681567
tristate "NXP QIXIS FPGA GPIO support"
15691568
depends on MFD_SIMPLE_MFD_I2C || COMPILE_TEST
15701569
select GPIO_REGMAP
1570+
select REGMAP_MMIO
15711571
help
15721572
This enables support for the GPIOs found in the QIXIS FPGA which is
15731573
integrated on some NXP Layerscape boards such as LX2160ARDB and

drivers/gpio/gpio-mmio.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static int gpio_mmio_set(struct gpio_chip *gc, unsigned int gpio, int val)
231231
struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
232232
unsigned long mask = gpio_mmio_line2mask(gc, gpio);
233233

234-
guard(raw_spinlock)(&chip->lock);
234+
guard(raw_spinlock_irqsave)(&chip->lock);
235235

236236
if (val)
237237
chip->sdata |= mask;
@@ -262,7 +262,7 @@ static int gpio_mmio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
262262
struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
263263
unsigned long mask = gpio_mmio_line2mask(gc, gpio);
264264

265-
guard(raw_spinlock)(&chip->lock);
265+
guard(raw_spinlock_irqsave)(&chip->lock);
266266

267267
if (val)
268268
chip->sdata |= mask;
@@ -302,7 +302,7 @@ static void gpio_mmio_set_multiple_single_reg(struct gpio_chip *gc,
302302
struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
303303
unsigned long set_mask, clear_mask;
304304

305-
guard(raw_spinlock)(&chip->lock);
305+
guard(raw_spinlock_irqsave)(&chip->lock);
306306

307307
gpio_mmio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
308308

@@ -391,7 +391,7 @@ static int gpio_mmio_dir_in(struct gpio_chip *gc, unsigned int gpio)
391391
{
392392
struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
393393

394-
scoped_guard(raw_spinlock, &chip->lock) {
394+
scoped_guard(raw_spinlock_irqsave, &chip->lock) {
395395
chip->sdir &= ~gpio_mmio_line2mask(gc, gpio);
396396

397397
if (chip->reg_dir_in)
@@ -431,7 +431,7 @@ static void gpio_mmio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
431431
{
432432
struct gpio_generic_chip *chip = to_gpio_generic_chip(gc);
433433

434-
guard(raw_spinlock)(&chip->lock);
434+
guard(raw_spinlock_irqsave)(&chip->lock);
435435

436436
chip->sdir |= gpio_mmio_line2mask(gc, gpio);
437437

drivers/gpio/gpio-regmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
338338
config->regmap_irq_line, config->regmap_irq_flags,
339339
0, config->regmap_irq_chip, &gpio->irq_chip_data);
340340
if (ret)
341-
goto err_free_bitmap;
341+
goto err_remove_gpiochip;
342342

343343
irq_domain = regmap_irq_get_domain(gpio->irq_chip_data);
344344
} else

drivers/gpio/gpiolib-acpi-quirks.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,28 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
370370
.ignore_wake = "ASCP1A00:00@8",
371371
},
372372
},
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+
},
373395
{} /* Terminating entry */
374396
};
375397

drivers/gpio/gpiolib-shared.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct gpio_shared_ref {
3636
enum gpiod_flags flags;
3737
char *con_id;
3838
int dev_id;
39+
/* Protects the auxiliary device struct and the lookup table. */
40+
struct mutex lock;
3941
struct auxiliary_device adev;
4042
struct gpiod_lookup_table *lookup;
4143
};
@@ -49,14 +51,14 @@ struct gpio_shared_entry {
4951
unsigned int offset;
5052
/* Index in the property value array. */
5153
size_t index;
54+
/* Synchronizes the modification of shared_desc. */
5255
struct mutex lock;
5356
struct gpio_shared_desc *shared_desc;
5457
struct kref ref;
5558
struct list_head refs;
5659
};
5760

5861
static LIST_HEAD(gpio_shared_list);
59-
static DEFINE_MUTEX(gpio_shared_lock);
6062
static DEFINE_IDA(gpio_shared_ida);
6163

6264
#if IS_ENABLED(CONFIG_OF)
@@ -77,6 +79,10 @@ gpio_shared_find_entry(struct fwnode_handle *controller_node,
7779
/* Handle all special nodes that we should ignore. */
7880
static bool gpio_shared_of_node_ignore(struct device_node *node)
7981
{
82+
/* Ignore disabled devices. */
83+
if (!of_device_is_available(node))
84+
return true;
85+
8086
/*
8187
* __symbols__ is a special, internal node and should not be considered
8288
* when scanning for shared GPIOs.
@@ -183,6 +189,7 @@ static int gpio_shared_of_traverse(struct device_node *curr)
183189

184190
ref->fwnode = fwnode_handle_get(of_fwnode_handle(curr));
185191
ref->flags = args.args[1];
192+
mutex_init(&ref->lock);
186193

187194
if (strends(prop->name, "gpios"))
188195
suffix = "-gpios";
@@ -254,7 +261,7 @@ static int gpio_shared_make_adev(struct gpio_device *gdev,
254261
struct auxiliary_device *adev = &ref->adev;
255262
int ret;
256263

257-
lockdep_assert_held(&gpio_shared_lock);
264+
guard(mutex)(&ref->lock);
258265

259266
memset(adev, 0, sizeof(*adev));
260267

@@ -369,14 +376,14 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags)
369376
if (!lookup)
370377
return -ENOMEM;
371378

372-
guard(mutex)(&gpio_shared_lock);
373-
374379
list_for_each_entry(entry, &gpio_shared_list, list) {
375380
list_for_each_entry(ref, &entry->refs, list) {
376381
if (!device_match_fwnode(consumer, ref->fwnode) &&
377382
!gpio_shared_dev_is_reset_gpio(consumer, entry, ref))
378383
continue;
379384

385+
guard(mutex)(&ref->lock);
386+
380387
/* We've already done that on a previous request. */
381388
if (ref->lookup)
382389
return 0;
@@ -395,7 +402,8 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags)
395402
lookup->table[0] = GPIO_LOOKUP(no_free_ptr(key), 0,
396403
ref->con_id, lflags);
397404

398-
gpiod_add_lookup_table(no_free_ptr(lookup));
405+
ref->lookup = no_free_ptr(lookup);
406+
gpiod_add_lookup_table(ref->lookup);
399407

400408
return 0;
401409
}
@@ -408,10 +416,8 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags)
408416

409417
static void gpio_shared_remove_adev(struct auxiliary_device *adev)
410418
{
411-
lockdep_assert_held(&gpio_shared_lock);
412-
413-
auxiliary_device_uninit(adev);
414419
auxiliary_device_delete(adev);
420+
auxiliary_device_uninit(adev);
415421
}
416422

417423
int gpio_device_setup_shared(struct gpio_device *gdev)
@@ -421,8 +427,6 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
421427
unsigned long *flags;
422428
int ret;
423429

424-
guard(mutex)(&gpio_shared_lock);
425-
426430
list_for_each_entry(entry, &gpio_shared_list, list) {
427431
list_for_each_entry(ref, &entry->refs, list) {
428432
if (gdev->dev.parent == &ref->adev.dev) {
@@ -479,19 +483,32 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
479483
struct gpio_shared_entry *entry;
480484
struct gpio_shared_ref *ref;
481485

482-
guard(mutex)(&gpio_shared_lock);
483-
484486
list_for_each_entry(entry, &gpio_shared_list, list) {
485487
if (!device_match_fwnode(&gdev->dev, entry->fwnode))
486488
continue;
487489

490+
/*
491+
* For some reason if we call synchronize_srcu() in GPIO core,
492+
* descent here and take this mutex and then recursively call
493+
* synchronize_srcu() again from gpiochip_remove() (which is
494+
* totally fine) called after gpio_shared_remove_adev(),
495+
* lockdep prints a false positive deadlock splat. Disable
496+
* lockdep here.
497+
*/
498+
lockdep_off();
488499
list_for_each_entry(ref, &entry->refs, list) {
489-
gpiod_remove_lookup_table(ref->lookup);
490-
kfree(ref->lookup->table[0].key);
491-
kfree(ref->lookup);
492-
ref->lookup = NULL;
500+
guard(mutex)(&ref->lock);
501+
502+
if (ref->lookup) {
503+
gpiod_remove_lookup_table(ref->lookup);
504+
kfree(ref->lookup->table[0].key);
505+
kfree(ref->lookup);
506+
ref->lookup = NULL;
507+
}
508+
493509
gpio_shared_remove_adev(&ref->adev);
494510
}
511+
lockdep_on();
495512
}
496513
}
497514

@@ -515,8 +532,6 @@ static void gpiod_shared_put(void *data)
515532
{
516533
struct gpio_shared_entry *entry = data;
517534

518-
lockdep_assert_not_held(&gpio_shared_lock);
519-
520535
kref_put(&entry->ref, gpio_shared_release);
521536
}
522537

@@ -554,8 +569,6 @@ struct gpio_shared_desc *devm_gpiod_shared_get(struct device *dev)
554569
struct gpio_shared_entry *entry;
555570
int ret;
556571

557-
lockdep_assert_not_held(&gpio_shared_lock);
558-
559572
entry = dev_get_platdata(dev);
560573
if (WARN_ON(!entry))
561574
/* Programmer bug */
@@ -590,6 +603,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_shared_get);
590603
static void gpio_shared_drop_ref(struct gpio_shared_ref *ref)
591604
{
592605
list_del(&ref->list);
606+
mutex_destroy(&ref->lock);
593607
kfree(ref->con_id);
594608
ida_free(&gpio_shared_ida, ref->dev_id);
595609
fwnode_handle_put(ref->fwnode);

0 commit comments

Comments
 (0)