Skip to content

Commit efb8235

Browse files
author
Bartosz Golaszewski
committed
gpiolib: revert the attempt to protect the GPIO device list with an rwsem
This reverts commits 1979a28 ("gpiolib: replace the GPIO device mutex with a read-write semaphore") and 65a828b ("gpiolib: use a mutex to protect the list of GPIO devices"). Unfortunately the legacy GPIO API that's still used in older code has to translate numbers from the global GPIO numberspace to descriptors. This results in a GPIO device lookup in every call to legacy functions. Some of those functions - like gpio_set/get_value() - can be called from atomic context so taking a sleeping lock that is an RW semaphore results in an error. We'll probably have to protect this list with SRCU. Reported-by: Dan Carpenter <[email protected]> Closes: https://lore.kernel.org/linux-wireless/[email protected]/ Fixes: 1979a28 ("gpiolib: replace the GPIO device mutex with a read-write semaphore") Fixes: 65a828b ("gpiolib: use a mutex to protect the list of GPIO devices") Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 62b38f3 commit efb8235

File tree

4 files changed

+97
-89
lines changed

4 files changed

+97
-89
lines changed

drivers/gpio/gpiolib-sysfs.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -768,25 +768,6 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
768768
return 0;
769769
}
770770

771-
int gpiochip_sysfs_register_all(void)
772-
{
773-
struct gpio_device *gdev;
774-
int ret;
775-
776-
guard(rwsem_read)(&gpio_devices_sem);
777-
778-
list_for_each_entry(gdev, &gpio_devices, list) {
779-
if (gdev->mockdev)
780-
continue;
781-
782-
ret = gpiochip_sysfs_register(gdev);
783-
if (ret)
784-
return ret;
785-
}
786-
787-
return 0;
788-
}
789-
790771
void gpiochip_sysfs_unregister(struct gpio_device *gdev)
791772
{
792773
struct gpio_desc *desc;
@@ -811,7 +792,9 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
811792

812793
static int __init gpiolib_sysfs_init(void)
813794
{
814-
int status;
795+
int status;
796+
unsigned long flags;
797+
struct gpio_device *gdev;
815798

816799
status = class_register(&gpio_class);
817800
if (status < 0)
@@ -823,6 +806,26 @@ static int __init gpiolib_sysfs_init(void)
823806
* We run before arch_initcall() so chip->dev nodes can have
824807
* registered, and so arch_initcall() can always gpiod_export().
825808
*/
826-
return gpiochip_sysfs_register_all();
809+
spin_lock_irqsave(&gpio_lock, flags);
810+
list_for_each_entry(gdev, &gpio_devices, list) {
811+
if (gdev->mockdev)
812+
continue;
813+
814+
/*
815+
* TODO we yield gpio_lock here because
816+
* gpiochip_sysfs_register() acquires a mutex. This is unsafe
817+
* and needs to be fixed.
818+
*
819+
* Also it would be nice to use gpio_device_find() here so we
820+
* can keep gpio_chips local to gpiolib.c, but the yield of
821+
* gpio_lock prevents us from doing this.
822+
*/
823+
spin_unlock_irqrestore(&gpio_lock, flags);
824+
status = gpiochip_sysfs_register(gdev);
825+
spin_lock_irqsave(&gpio_lock, flags);
826+
}
827+
spin_unlock_irqrestore(&gpio_lock, flags);
828+
829+
return status;
827830
}
828831
postcore_initcall(gpiolib_sysfs_init);

drivers/gpio/gpiolib-sysfs.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ struct gpio_device;
88
#ifdef CONFIG_GPIO_SYSFS
99

1010
int gpiochip_sysfs_register(struct gpio_device *gdev);
11-
int gpiochip_sysfs_register_all(void);
1211
void gpiochip_sysfs_unregister(struct gpio_device *gdev);
1312

1413
#else
@@ -18,11 +17,6 @@ static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
1817
return 0;
1918
}
2019

21-
static inline int gpiochip_sysfs_register_all(void)
22-
{
23-
return 0;
24-
}
25-
2620
static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
2721
{
2822
}

drivers/gpio/gpiolib.c

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
#include <linux/acpi.h>
44
#include <linux/bitmap.h>
5-
#include <linux/cleanup.h>
65
#include <linux/compat.h>
76
#include <linux/debugfs.h>
87
#include <linux/device.h>
@@ -16,7 +15,6 @@
1615
#include <linux/kernel.h>
1716
#include <linux/list.h>
1817
#include <linux/module.h>
19-
#include <linux/mutex.h>
2018
#include <linux/of.h>
2119
#include <linux/pinctrl/consumer.h>
2220
#include <linux/seq_file.h>
@@ -83,9 +81,7 @@ DEFINE_SPINLOCK(gpio_lock);
8381

8482
static DEFINE_MUTEX(gpio_lookup_lock);
8583
static LIST_HEAD(gpio_lookup_list);
86-
8784
LIST_HEAD(gpio_devices);
88-
DECLARE_RWSEM(gpio_devices_sem);
8985

9086
static DEFINE_MUTEX(gpio_machine_hogs_mutex);
9187
static LIST_HEAD(gpio_machine_hogs);
@@ -117,15 +113,20 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
117113
struct gpio_desc *gpio_to_desc(unsigned gpio)
118114
{
119115
struct gpio_device *gdev;
116+
unsigned long flags;
117+
118+
spin_lock_irqsave(&gpio_lock, flags);
120119

121-
scoped_guard(rwsem_read, &gpio_devices_sem) {
122-
list_for_each_entry(gdev, &gpio_devices, list) {
123-
if (gdev->base <= gpio &&
124-
gdev->base + gdev->ngpio > gpio)
125-
return &gdev->descs[gpio - gdev->base];
120+
list_for_each_entry(gdev, &gpio_devices, list) {
121+
if (gdev->base <= gpio &&
122+
gdev->base + gdev->ngpio > gpio) {
123+
spin_unlock_irqrestore(&gpio_lock, flags);
124+
return &gdev->descs[gpio - gdev->base];
126125
}
127126
}
128127

128+
spin_unlock_irqrestore(&gpio_lock, flags);
129+
129130
if (!gpio_is_valid(gpio))
130131
pr_warn("invalid GPIO %d\n", gpio);
131132

@@ -398,21 +399,26 @@ static int gpiodev_add_to_list_unlocked(struct gpio_device *gdev)
398399
static struct gpio_desc *gpio_name_to_desc(const char * const name)
399400
{
400401
struct gpio_device *gdev;
402+
unsigned long flags;
401403

402404
if (!name)
403405
return NULL;
404406

405-
guard(rwsem_read)(&gpio_devices_sem);
407+
spin_lock_irqsave(&gpio_lock, flags);
406408

407409
list_for_each_entry(gdev, &gpio_devices, list) {
408410
struct gpio_desc *desc;
409411

410412
for_each_gpio_desc(gdev->chip, desc) {
411-
if (desc->name && !strcmp(desc->name, name))
413+
if (desc->name && !strcmp(desc->name, name)) {
414+
spin_unlock_irqrestore(&gpio_lock, flags);
412415
return desc;
416+
}
413417
}
414418
}
415419

420+
spin_unlock_irqrestore(&gpio_lock, flags);
421+
416422
return NULL;
417423
}
418424

@@ -807,6 +813,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
807813
struct lock_class_key *request_key)
808814
{
809815
struct gpio_device *gdev;
816+
unsigned long flags;
810817
unsigned int i;
811818
int base = 0;
812819
int ret = 0;
@@ -871,46 +878,49 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
871878

872879
gdev->ngpio = gc->ngpio;
873880

874-
scoped_guard(rwsem_write, &gpio_devices_sem) {
875-
/*
876-
* TODO: this allocates a Linux GPIO number base in the global
877-
* GPIO numberspace for this chip. In the long run we want to
878-
* get *rid* of this numberspace and use only descriptors, but
879-
* it may be a pipe dream. It will not happen before we get rid
880-
* of the sysfs interface anyways.
881-
*/
882-
base = gc->base;
881+
spin_lock_irqsave(&gpio_lock, flags);
883882

883+
/*
884+
* TODO: this allocates a Linux GPIO number base in the global
885+
* GPIO numberspace for this chip. In the long run we want to
886+
* get *rid* of this numberspace and use only descriptors, but
887+
* it may be a pipe dream. It will not happen before we get rid
888+
* of the sysfs interface anyways.
889+
*/
890+
base = gc->base;
891+
if (base < 0) {
892+
base = gpiochip_find_base_unlocked(gc->ngpio);
884893
if (base < 0) {
885-
base = gpiochip_find_base_unlocked(gc->ngpio);
886-
if (base < 0) {
887-
ret = base;
888-
base = 0;
889-
goto err_free_label;
890-
}
891-
/*
892-
* TODO: it should not be necessary to reflect the assigned
893-
* base outside of the GPIO subsystem. Go over drivers and
894-
* see if anyone makes use of this, else drop this and assign
895-
* a poison instead.
896-
*/
897-
gc->base = base;
898-
} else {
899-
dev_warn(&gdev->dev,
900-
"Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
901-
}
902-
gdev->base = base;
903-
904-
ret = gpiodev_add_to_list_unlocked(gdev);
905-
if (ret) {
906-
chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
894+
spin_unlock_irqrestore(&gpio_lock, flags);
895+
ret = base;
896+
base = 0;
907897
goto err_free_label;
908898
}
899+
/*
900+
* TODO: it should not be necessary to reflect the assigned
901+
* base outside of the GPIO subsystem. Go over drivers and
902+
* see if anyone makes use of this, else drop this and assign
903+
* a poison instead.
904+
*/
905+
gc->base = base;
906+
} else {
907+
dev_warn(&gdev->dev,
908+
"Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
909+
}
910+
gdev->base = base;
909911

910-
for (i = 0; i < gc->ngpio; i++)
911-
gdev->descs[i].gdev = gdev;
912+
ret = gpiodev_add_to_list_unlocked(gdev);
913+
if (ret) {
914+
spin_unlock_irqrestore(&gpio_lock, flags);
915+
chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
916+
goto err_free_label;
912917
}
913918

919+
for (i = 0; i < gc->ngpio; i++)
920+
gdev->descs[i].gdev = gdev;
921+
922+
spin_unlock_irqrestore(&gpio_lock, flags);
923+
914924
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
915925
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
916926
init_rwsem(&gdev->sem);
@@ -1001,8 +1011,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
10011011
goto err_print_message;
10021012
}
10031013
err_remove_from_list:
1004-
scoped_guard(rwsem_write, &gpio_devices_sem)
1005-
list_del(&gdev->list);
1014+
spin_lock_irqsave(&gpio_lock, flags);
1015+
list_del(&gdev->list);
1016+
spin_unlock_irqrestore(&gpio_lock, flags);
10061017
err_free_label:
10071018
kfree_const(gdev->label);
10081019
err_free_descs:
@@ -1065,7 +1076,7 @@ void gpiochip_remove(struct gpio_chip *gc)
10651076
dev_crit(&gdev->dev,
10661077
"REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n");
10671078

1068-
scoped_guard(rwsem_write, &gpio_devices_sem)
1079+
scoped_guard(spinlock_irqsave, &gpio_lock)
10691080
list_del(&gdev->list);
10701081

10711082
/*
@@ -1114,7 +1125,7 @@ struct gpio_device *gpio_device_find(void *data,
11141125
*/
11151126
might_sleep();
11161127

1117-
guard(rwsem_read)(&gpio_devices_sem);
1128+
guard(spinlock_irqsave)(&gpio_lock);
11181129

11191130
list_for_each_entry(gdev, &gpio_devices, list) {
11201131
if (gdev->chip && match(gdev->chip, data))
@@ -4725,33 +4736,35 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
47254736

47264737
static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
47274738
{
4739+
unsigned long flags;
47284740
struct gpio_device *gdev = NULL;
47294741
loff_t index = *pos;
47304742

47314743
s->private = "";
47324744

4733-
guard(rwsem_read)(&gpio_devices_sem);
4734-
4735-
list_for_each_entry(gdev, &gpio_devices, list) {
4736-
if (index-- == 0)
4745+
spin_lock_irqsave(&gpio_lock, flags);
4746+
list_for_each_entry(gdev, &gpio_devices, list)
4747+
if (index-- == 0) {
4748+
spin_unlock_irqrestore(&gpio_lock, flags);
47374749
return gdev;
4738-
}
4750+
}
4751+
spin_unlock_irqrestore(&gpio_lock, flags);
47394752

47404753
return NULL;
47414754
}
47424755

47434756
static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
47444757
{
4758+
unsigned long flags;
47454759
struct gpio_device *gdev = v;
47464760
void *ret = NULL;
47474761

4748-
scoped_guard(rwsem_read, &gpio_devices_sem) {
4749-
if (list_is_last(&gdev->list, &gpio_devices))
4750-
ret = NULL;
4751-
else
4752-
ret = list_first_entry(&gdev->list, struct gpio_device,
4753-
list);
4754-
}
4762+
spin_lock_irqsave(&gpio_lock, flags);
4763+
if (list_is_last(&gdev->list, &gpio_devices))
4764+
ret = NULL;
4765+
else
4766+
ret = list_first_entry(&gdev->list, struct gpio_device, list);
4767+
spin_unlock_irqrestore(&gpio_lock, flags);
47554768

47564769
s->private = "\n";
47574770
++*pos;

drivers/gpio/gpiolib.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <linux/gpio/consumer.h> /* for enum gpiod_flags */
1616
#include <linux/gpio/driver.h>
1717
#include <linux/module.h>
18-
#include <linux/mutex.h>
1918
#include <linux/notifier.h>
2019
#include <linux/rwsem.h>
2120

@@ -137,7 +136,6 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
137136

138137
extern spinlock_t gpio_lock;
139138
extern struct list_head gpio_devices;
140-
extern struct rw_semaphore gpio_devices_sem;
141139

142140
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
143141

0 commit comments

Comments
 (0)