Skip to content

Commit 1f664bb

Browse files
committed
Merge tag 'gpio-fixes-for-v6.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: "Some fixes to resource leaks in the character device handling and another small fix for shared GPIO management: - fix resource leaks in error paths in GPIO character device code - return -ENOMEM and not -ENODEV on memory allocation failure - fix an audio issue on Qualcomm platforms due to configuration not being propagated to pinctrl from shared GPIO proxy" * tag 'gpio-fixes-for-v6.19-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: shared: propagate configuration to pinctrl gpio: cdev: Fix resource leaks on errors in gpiolib_cdev_register() gpio: cdev: Fix resource leaks on errors in lineinfo_changed_notify() gpio: cdev: Correct return code on memory allocation failure
2 parents 6e49f9e + 4918cc0 commit 1f664bb

4 files changed

Lines changed: 24 additions & 10 deletions

File tree

drivers/gpio/gpiolib-cdev.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,6 +2549,7 @@ static int lineinfo_changed_notify(struct notifier_block *nb,
25492549
ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
25502550
if (!ctx) {
25512551
pr_err("Failed to allocate memory for line info notification\n");
2552+
fput(fp);
25522553
return NOTIFY_DONE;
25532554
}
25542555

@@ -2696,7 +2697,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file)
26962697

26972698
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
26982699
if (!cdev)
2699-
return -ENODEV;
2700+
return -ENOMEM;
27002701

27012702
cdev->watched_lines = bitmap_zalloc(gdev->ngpio, GFP_KERNEL);
27022703
if (!cdev->watched_lines)
@@ -2796,13 +2797,18 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
27962797
return -ENOMEM;
27972798

27982799
ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
2799-
if (ret)
2800+
if (ret) {
2801+
destroy_workqueue(gdev->line_state_wq);
28002802
return ret;
2803+
}
28012804

28022805
guard(srcu)(&gdev->srcu);
28032806
gc = srcu_dereference(gdev->chip, &gdev->srcu);
2804-
if (!gc)
2807+
if (!gc) {
2808+
cdev_device_del(&gdev->chrdev, &gdev->dev);
2809+
destroy_workqueue(gdev->line_state_wq);
28052810
return -ENODEV;
2811+
}
28062812

28072813
gpiochip_dbg(gc, "added GPIO chardev (%d:%d)\n", MAJOR(devt), gdev->id);
28082814

drivers/gpio/gpiolib-shared.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
515515
{
516516
struct gpio_shared_entry *entry;
517517
struct gpio_shared_ref *ref;
518-
unsigned long *flags;
518+
struct gpio_desc *desc;
519519
int ret;
520520

521521
list_for_each_entry(entry, &gpio_shared_list, list) {
@@ -543,15 +543,17 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
543543
if (list_count_nodes(&entry->refs) <= 1)
544544
continue;
545545

546-
flags = &gdev->descs[entry->offset].flags;
546+
desc = &gdev->descs[entry->offset];
547547

548-
__set_bit(GPIOD_FLAG_SHARED, flags);
548+
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
549549
/*
550550
* Shared GPIOs are not requested via the normal path. Make
551551
* them inaccessible to anyone even before we register the
552552
* chip.
553553
*/
554-
__set_bit(GPIOD_FLAG_REQUESTED, flags);
554+
ret = gpiod_request_commit(desc, "shared");
555+
if (ret)
556+
return ret;
555557

556558
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
557559
entry->offset, gpio_device_get_label(gdev));
@@ -562,8 +564,10 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
562564
ref->con_id ?: "(none)");
563565

564566
ret = gpio_shared_make_adev(gdev, entry, ref);
565-
if (ret)
567+
if (ret) {
568+
gpiod_free_commit(desc);
566569
return ret;
570+
}
567571
}
568572
}
569573

@@ -579,6 +583,8 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
579583
if (!device_match_fwnode(&gdev->dev, entry->fwnode))
580584
continue;
581585

586+
gpiod_free_commit(&gdev->descs[entry->offset]);
587+
582588
list_for_each_entry(ref, &entry->refs, list) {
583589
guard(mutex)(&ref->lock);
584590

drivers/gpio/gpiolib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,7 +2453,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
24532453
* on each other, and help provide better diagnostics in debugfs.
24542454
* They're called even less than the "set direction" calls.
24552455
*/
2456-
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
2456+
int gpiod_request_commit(struct gpio_desc *desc, const char *label)
24572457
{
24582458
unsigned int offset;
24592459
int ret;
@@ -2515,7 +2515,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label)
25152515
return ret;
25162516
}
25172517

2518-
static void gpiod_free_commit(struct gpio_desc *desc)
2518+
void gpiod_free_commit(struct gpio_desc *desc)
25192519
{
25202520
unsigned long flags;
25212521

drivers/gpio/gpiolib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ DEFINE_CLASS(gpio_chip_guard,
244244
struct gpio_desc *desc)
245245

246246
int gpiod_request(struct gpio_desc *desc, const char *label);
247+
int gpiod_request_commit(struct gpio_desc *desc, const char *label);
247248
void gpiod_free(struct gpio_desc *desc);
249+
void gpiod_free_commit(struct gpio_desc *desc);
248250

249251
static inline int gpiod_request_user(struct gpio_desc *desc, const char *label)
250252
{

0 commit comments

Comments
 (0)