]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Drop gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch
authorSasha Levin <sashal@kernel.org>
Mon, 22 Jan 2024 10:34:59 +0000 (05:34 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 22 Jan 2024 10:34:59 +0000 (05:34 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.6/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch [deleted file]
queue-6.6/series
queue-6.7/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch [deleted file]
queue-6.7/series

diff --git a/queue-6.6/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch b/queue-6.6/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch
deleted file mode 100644 (file)
index db6342a..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-From 962616d67e96d400fca23f3ab8be6865608f39b1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 15 Dec 2023 16:53:00 +0100
-Subject: gpiolib: use a mutex to protect the list of GPIO devices
-
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-[ Upstream commit 65a828bab15887b33336d251fd659b2ae86de6d6 ]
-
-The global list of GPIO devices is never modified or accessed from
-atomic context so it's fine to protect it using a mutex. Add a new
-global lock dedicated to the gpio_devices list and use it whenever
-accessing or modifying it.
-
-Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Stable-dep-of: 48e1b4d369cf ("gpiolib: remove the GPIO device from the list when it's unregistered")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/gpio/gpiolib-sysfs.c |  45 ++++++------
- drivers/gpio/gpiolib-sysfs.h |   6 ++
- drivers/gpio/gpiolib.c       | 137 ++++++++++++++++-------------------
- drivers/gpio/gpiolib.h       |   2 +
- 4 files changed, 90 insertions(+), 100 deletions(-)
-
-diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
-index 12d853845bb8..1e91e7395d01 100644
---- a/drivers/gpio/gpiolib-sysfs.c
-+++ b/drivers/gpio/gpiolib-sysfs.c
-@@ -769,6 +769,25 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
-       return 0;
- }
-+int gpiochip_sysfs_register_all(void)
-+{
-+      struct gpio_device *gdev;
-+      int ret;
-+
-+      guard(mutex)(&gpio_devices_lock);
-+
-+      list_for_each_entry(gdev, &gpio_devices, list) {
-+              if (gdev->mockdev)
-+                      continue;
-+
-+              ret = gpiochip_sysfs_register(gdev);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      return 0;
-+}
-+
- void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- {
-       struct gpio_desc *desc;
-@@ -793,9 +812,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- static int __init gpiolib_sysfs_init(void)
- {
--      int             status;
--      unsigned long   flags;
--      struct gpio_device *gdev;
-+      int status;
-       status = class_register(&gpio_class);
-       if (status < 0)
-@@ -807,26 +824,6 @@ static int __init gpiolib_sysfs_init(void)
-        * We run before arch_initcall() so chip->dev nodes can have
-        * registered, and so arch_initcall() can always gpiod_export().
-        */
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list) {
--              if (gdev->mockdev)
--                      continue;
--
--              /*
--               * TODO we yield gpio_lock here because
--               * gpiochip_sysfs_register() acquires a mutex. This is unsafe
--               * and needs to be fixed.
--               *
--               * Also it would be nice to use gpio_device_find() here so we
--               * can keep gpio_chips local to gpiolib.c, but the yield of
--               * gpio_lock prevents us from doing this.
--               */
--              spin_unlock_irqrestore(&gpio_lock, flags);
--              status = gpiochip_sysfs_register(gdev);
--              spin_lock_irqsave(&gpio_lock, flags);
--      }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
--      return status;
-+      return gpiochip_sysfs_register_all();
- }
- postcore_initcall(gpiolib_sysfs_init);
-diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h
-index b794b396d6a5..ab157cec0b4b 100644
---- a/drivers/gpio/gpiolib-sysfs.h
-+++ b/drivers/gpio/gpiolib-sysfs.h
-@@ -8,6 +8,7 @@ struct gpio_device;
- #ifdef CONFIG_GPIO_SYSFS
- int gpiochip_sysfs_register(struct gpio_device *gdev);
-+int gpiochip_sysfs_register_all(void);
- void gpiochip_sysfs_unregister(struct gpio_device *gdev);
- #else
-@@ -17,6 +18,11 @@ static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
-       return 0;
- }
-+static inline int gpiochip_sysfs_register_all(void)
-+{
-+      return 0;
-+}
-+
- static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- {
- }
-diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index d722b6301906..1a53e1e5379b 100644
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -2,6 +2,7 @@
- #include <linux/acpi.h>
- #include <linux/bitmap.h>
-+#include <linux/cleanup.h>
- #include <linux/compat.h>
- #include <linux/debugfs.h>
- #include <linux/device.h>
-@@ -15,6 +16,7 @@
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/seq_file.h>
-@@ -93,7 +95,9 @@ DEFINE_SPINLOCK(gpio_lock);
- static DEFINE_MUTEX(gpio_lookup_lock);
- static LIST_HEAD(gpio_lookup_list);
-+
- LIST_HEAD(gpio_devices);
-+DEFINE_MUTEX(gpio_devices_lock);
- static DEFINE_MUTEX(gpio_machine_hogs_mutex);
- static LIST_HEAD(gpio_machine_hogs);
-@@ -125,20 +129,15 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
- struct gpio_desc *gpio_to_desc(unsigned gpio)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
--
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list) {
--              if (gdev->base <= gpio &&
--                  gdev->base + gdev->ngpio > gpio) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
--                      return &gdev->descs[gpio - gdev->base];
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              list_for_each_entry(gdev, &gpio_devices, list) {
-+                      if (gdev->base <= gpio &&
-+                          gdev->base + gdev->ngpio > gpio)
-+                              return &gdev->descs[gpio - gdev->base];
-               }
-       }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       if (!gpio_is_valid(gpio))
-               pr_warn("invalid GPIO %d\n", gpio);
-@@ -320,26 +319,21 @@ static int gpiodev_add_to_list_unlocked(struct gpio_device *gdev)
- static struct gpio_desc *gpio_name_to_desc(const char * const name)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
-       if (!name)
-               return NULL;
--      spin_lock_irqsave(&gpio_lock, flags);
-+      guard(mutex)(&gpio_devices_lock);
-       list_for_each_entry(gdev, &gpio_devices, list) {
-               struct gpio_desc *desc;
-               for_each_gpio_desc(gdev->chip, desc) {
--                      if (desc->name && !strcmp(desc->name, name)) {
--                              spin_unlock_irqrestore(&gpio_lock, flags);
-+                      if (desc->name && !strcmp(desc->name, name))
-                               return desc;
--                      }
-               }
-       }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       return NULL;
- }
-@@ -577,11 +571,9 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
- static void gpiodev_release(struct device *dev)
- {
-       struct gpio_device *gdev = to_gpio_device(dev);
--      unsigned long flags;
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_del(&gdev->list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock)
-+              list_del(&gdev->list);
-       ida_free(&gpio_ida, gdev->id);
-       kfree_const(gdev->label);
-@@ -739,7 +731,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-                              struct lock_class_key *request_key)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
-       unsigned int i;
-       int base = 0;
-       int ret = 0;
-@@ -804,49 +795,46 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-       gdev->ngpio = gc->ngpio;
--      spin_lock_irqsave(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              /*
-+               * TODO: this allocates a Linux GPIO number base in the global
-+               * GPIO numberspace for this chip. In the long run we want to
-+               * get *rid* of this numberspace and use only descriptors, but
-+               * it may be a pipe dream. It will not happen before we get rid
-+               * of the sysfs interface anyways.
-+               */
-+              base = gc->base;
--      /*
--       * TODO: this allocates a Linux GPIO number base in the global
--       * GPIO numberspace for this chip. In the long run we want to
--       * get *rid* of this numberspace and use only descriptors, but
--       * it may be a pipe dream. It will not happen before we get rid
--       * of the sysfs interface anyways.
--       */
--      base = gc->base;
--      if (base < 0) {
--              base = gpiochip_find_base_unlocked(gc->ngpio);
-               if (base < 0) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
--                      ret = base;
--                      base = 0;
-+                      base = gpiochip_find_base_unlocked(gc->ngpio);
-+                      if (base < 0) {
-+                              ret = base;
-+                              base = 0;
-+                              goto err_free_label;
-+                      }
-+                      /*
-+                       * TODO: it should not be necessary to reflect the assigned
-+                       * base outside of the GPIO subsystem. Go over drivers and
-+                       * see if anyone makes use of this, else drop this and assign
-+                       * a poison instead.
-+                       */
-+                      gc->base = base;
-+              } else {
-+                      dev_warn(&gdev->dev,
-+                               "Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
-+              }
-+              gdev->base = base;
-+
-+              ret = gpiodev_add_to_list_unlocked(gdev);
-+              if (ret) {
-+                      chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
-                       goto err_free_label;
-               }
--              /*
--               * TODO: it should not be necessary to reflect the assigned
--               * base outside of the GPIO subsystem. Go over drivers and
--               * see if anyone makes use of this, else drop this and assign
--               * a poison instead.
--               */
--              gc->base = base;
--      } else {
--              dev_warn(&gdev->dev,
--                       "Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
--      }
--      gdev->base = base;
--      ret = gpiodev_add_to_list_unlocked(gdev);
--      if (ret) {
--              spin_unlock_irqrestore(&gpio_lock, flags);
--              chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
--              goto err_free_label;
-+              for (i = 0; i < gc->ngpio; i++)
-+                      gdev->descs[i].gdev = gdev;
-       }
--      for (i = 0; i < gc->ngpio; i++)
--              gdev->descs[i].gdev = gdev;
--
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
-       BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
-       init_rwsem(&gdev->sem);
-@@ -937,9 +925,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-               goto err_print_message;
-       }
- err_remove_from_list:
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_del(&gdev->list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock)
-+              list_del(&gdev->list);
- err_free_label:
-       kfree_const(gdev->label);
- err_free_descs:
-@@ -1070,7 +1057,7 @@ struct gpio_device *gpio_device_find(void *data,
-        */
-       might_sleep();
--      guard(spinlock_irqsave)(&gpio_lock);
-+      guard(mutex)(&gpio_devices_lock);
-       list_for_each_entry(gdev, &gpio_devices, list) {
-               if (gdev->chip && match(gdev->chip, data))
-@@ -4626,35 +4613,33 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
- static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
- {
--      unsigned long flags;
-       struct gpio_device *gdev = NULL;
-       loff_t index = *pos;
-       s->private = "";
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list)
--              if (index-- == 0) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
-+      guard(mutex)(&gpio_devices_lock);
-+
-+      list_for_each_entry(gdev, &gpio_devices, list) {
-+              if (index-- == 0)
-                       return gdev;
--              }
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      }
-       return NULL;
- }
- static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
- {
--      unsigned long flags;
-       struct gpio_device *gdev = v;
-       void *ret = NULL;
--      spin_lock_irqsave(&gpio_lock, flags);
--      if (list_is_last(&gdev->list, &gpio_devices))
--              ret = NULL;
--      else
--              ret = list_first_entry(&gdev->list, struct gpio_device, list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              if (list_is_last(&gdev->list, &gpio_devices))
-+                      ret = NULL;
-+              else
-+                      ret = list_first_entry(&gdev->list, struct gpio_device,
-+                                             list);
-+      }
-       s->private = "\n";
-       ++*pos;
-diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
-index aa1926083689..3e0f01d5d4cb 100644
---- a/drivers/gpio/gpiolib.h
-+++ b/drivers/gpio/gpiolib.h
-@@ -15,6 +15,7 @@
- #include <linux/gpio/consumer.h> /* for enum gpiod_flags */
- #include <linux/gpio/driver.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
- #include <linux/notifier.h>
- #include <linux/rwsem.h>
-@@ -136,6 +137,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
- extern spinlock_t gpio_lock;
- extern struct list_head gpio_devices;
-+extern struct mutex gpio_devices_lock;
- void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
--- 
-2.43.0
-
index 486ea16b5f6004fac40b4c11be3ec0d1d40fec19..9c6bb518d4b5176499113705a6b4a96cdb1cf3fc 100644 (file)
@@ -329,7 +329,6 @@ gpiolib-make-gpio_device_get-and-gpio_device_put-pub.patch
 gpiolib-provide-gpio_device_find.patch
 gpio-sysfs-drop-the-mention-of-gpiochip_find-from-sy.patch
 gpiolib-rename-static-functions-that-are-called-with.patch
-gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch
 gpiolib-remove-the-gpio-device-from-the-list-when-it.patch
 ib-iser-prevent-invalidating-wrong-mr.patch
 drm-amdkfd-confirm-list-is-non-empty-before-utilizin.patch
diff --git a/queue-6.7/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch b/queue-6.7/gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch
deleted file mode 100644 (file)
index 85870d2..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-From da7a9adaae4424fca4134f6089a4490e431a4b35 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 15 Dec 2023 16:53:00 +0100
-Subject: gpiolib: use a mutex to protect the list of GPIO devices
-
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-[ Upstream commit 65a828bab15887b33336d251fd659b2ae86de6d6 ]
-
-The global list of GPIO devices is never modified or accessed from
-atomic context so it's fine to protect it using a mutex. Add a new
-global lock dedicated to the gpio_devices list and use it whenever
-accessing or modifying it.
-
-Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Stable-dep-of: 48e1b4d369cf ("gpiolib: remove the GPIO device from the list when it's unregistered")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/gpio/gpiolib-sysfs.c |  45 ++++++------
- drivers/gpio/gpiolib-sysfs.h |   6 ++
- drivers/gpio/gpiolib.c       | 137 ++++++++++++++++-------------------
- drivers/gpio/gpiolib.h       |   2 +
- 4 files changed, 90 insertions(+), 100 deletions(-)
-
-diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
-index 12d853845bb8..1e91e7395d01 100644
---- a/drivers/gpio/gpiolib-sysfs.c
-+++ b/drivers/gpio/gpiolib-sysfs.c
-@@ -769,6 +769,25 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
-       return 0;
- }
-+int gpiochip_sysfs_register_all(void)
-+{
-+      struct gpio_device *gdev;
-+      int ret;
-+
-+      guard(mutex)(&gpio_devices_lock);
-+
-+      list_for_each_entry(gdev, &gpio_devices, list) {
-+              if (gdev->mockdev)
-+                      continue;
-+
-+              ret = gpiochip_sysfs_register(gdev);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      return 0;
-+}
-+
- void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- {
-       struct gpio_desc *desc;
-@@ -793,9 +812,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- static int __init gpiolib_sysfs_init(void)
- {
--      int             status;
--      unsigned long   flags;
--      struct gpio_device *gdev;
-+      int status;
-       status = class_register(&gpio_class);
-       if (status < 0)
-@@ -807,26 +824,6 @@ static int __init gpiolib_sysfs_init(void)
-        * We run before arch_initcall() so chip->dev nodes can have
-        * registered, and so arch_initcall() can always gpiod_export().
-        */
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list) {
--              if (gdev->mockdev)
--                      continue;
--
--              /*
--               * TODO we yield gpio_lock here because
--               * gpiochip_sysfs_register() acquires a mutex. This is unsafe
--               * and needs to be fixed.
--               *
--               * Also it would be nice to use gpio_device_find() here so we
--               * can keep gpio_chips local to gpiolib.c, but the yield of
--               * gpio_lock prevents us from doing this.
--               */
--              spin_unlock_irqrestore(&gpio_lock, flags);
--              status = gpiochip_sysfs_register(gdev);
--              spin_lock_irqsave(&gpio_lock, flags);
--      }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
--      return status;
-+      return gpiochip_sysfs_register_all();
- }
- postcore_initcall(gpiolib_sysfs_init);
-diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h
-index b794b396d6a5..ab157cec0b4b 100644
---- a/drivers/gpio/gpiolib-sysfs.h
-+++ b/drivers/gpio/gpiolib-sysfs.h
-@@ -8,6 +8,7 @@ struct gpio_device;
- #ifdef CONFIG_GPIO_SYSFS
- int gpiochip_sysfs_register(struct gpio_device *gdev);
-+int gpiochip_sysfs_register_all(void);
- void gpiochip_sysfs_unregister(struct gpio_device *gdev);
- #else
-@@ -17,6 +18,11 @@ static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
-       return 0;
- }
-+static inline int gpiochip_sysfs_register_all(void)
-+{
-+      return 0;
-+}
-+
- static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
- {
- }
-diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index 9e69d42ff5af..3518481c433f 100644
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -2,6 +2,7 @@
- #include <linux/acpi.h>
- #include <linux/bitmap.h>
-+#include <linux/cleanup.h>
- #include <linux/compat.h>
- #include <linux/debugfs.h>
- #include <linux/device.h>
-@@ -15,6 +16,7 @@
- #include <linux/kernel.h>
- #include <linux/list.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/seq_file.h>
-@@ -94,7 +96,9 @@ DEFINE_SPINLOCK(gpio_lock);
- static DEFINE_MUTEX(gpio_lookup_lock);
- static LIST_HEAD(gpio_lookup_list);
-+
- LIST_HEAD(gpio_devices);
-+DEFINE_MUTEX(gpio_devices_lock);
- static DEFINE_MUTEX(gpio_machine_hogs_mutex);
- static LIST_HEAD(gpio_machine_hogs);
-@@ -126,20 +130,15 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
- struct gpio_desc *gpio_to_desc(unsigned gpio)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
--
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list) {
--              if (gdev->base <= gpio &&
--                  gdev->base + gdev->ngpio > gpio) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
--                      return &gdev->descs[gpio - gdev->base];
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              list_for_each_entry(gdev, &gpio_devices, list) {
-+                      if (gdev->base <= gpio &&
-+                          gdev->base + gdev->ngpio > gpio)
-+                              return &gdev->descs[gpio - gdev->base];
-               }
-       }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       if (!gpio_is_valid(gpio))
-               pr_warn("invalid GPIO %d\n", gpio);
-@@ -398,26 +397,21 @@ static int gpiodev_add_to_list_unlocked(struct gpio_device *gdev)
- static struct gpio_desc *gpio_name_to_desc(const char * const name)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
-       if (!name)
-               return NULL;
--      spin_lock_irqsave(&gpio_lock, flags);
-+      guard(mutex)(&gpio_devices_lock);
-       list_for_each_entry(gdev, &gpio_devices, list) {
-               struct gpio_desc *desc;
-               for_each_gpio_desc(gdev->chip, desc) {
--                      if (desc->name && !strcmp(desc->name, name)) {
--                              spin_unlock_irqrestore(&gpio_lock, flags);
-+                      if (desc->name && !strcmp(desc->name, name))
-                               return desc;
--                      }
-               }
-       }
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       return NULL;
- }
-@@ -655,11 +649,9 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
- static void gpiodev_release(struct device *dev)
- {
-       struct gpio_device *gdev = to_gpio_device(dev);
--      unsigned long flags;
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_del(&gdev->list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock)
-+              list_del(&gdev->list);
-       ida_free(&gpio_ida, gdev->id);
-       kfree_const(gdev->label);
-@@ -817,7 +809,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-                              struct lock_class_key *request_key)
- {
-       struct gpio_device *gdev;
--      unsigned long flags;
-       unsigned int i;
-       int base = 0;
-       int ret = 0;
-@@ -882,49 +873,46 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-       gdev->ngpio = gc->ngpio;
--      spin_lock_irqsave(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              /*
-+               * TODO: this allocates a Linux GPIO number base in the global
-+               * GPIO numberspace for this chip. In the long run we want to
-+               * get *rid* of this numberspace and use only descriptors, but
-+               * it may be a pipe dream. It will not happen before we get rid
-+               * of the sysfs interface anyways.
-+               */
-+              base = gc->base;
--      /*
--       * TODO: this allocates a Linux GPIO number base in the global
--       * GPIO numberspace for this chip. In the long run we want to
--       * get *rid* of this numberspace and use only descriptors, but
--       * it may be a pipe dream. It will not happen before we get rid
--       * of the sysfs interface anyways.
--       */
--      base = gc->base;
--      if (base < 0) {
--              base = gpiochip_find_base_unlocked(gc->ngpio);
-               if (base < 0) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
--                      ret = base;
--                      base = 0;
-+                      base = gpiochip_find_base_unlocked(gc->ngpio);
-+                      if (base < 0) {
-+                              ret = base;
-+                              base = 0;
-+                              goto err_free_label;
-+                      }
-+                      /*
-+                       * TODO: it should not be necessary to reflect the assigned
-+                       * base outside of the GPIO subsystem. Go over drivers and
-+                       * see if anyone makes use of this, else drop this and assign
-+                       * a poison instead.
-+                       */
-+                      gc->base = base;
-+              } else {
-+                      dev_warn(&gdev->dev,
-+                               "Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
-+              }
-+              gdev->base = base;
-+
-+              ret = gpiodev_add_to_list_unlocked(gdev);
-+              if (ret) {
-+                      chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
-                       goto err_free_label;
-               }
--              /*
--               * TODO: it should not be necessary to reflect the assigned
--               * base outside of the GPIO subsystem. Go over drivers and
--               * see if anyone makes use of this, else drop this and assign
--               * a poison instead.
--               */
--              gc->base = base;
--      } else {
--              dev_warn(&gdev->dev,
--                       "Static allocation of GPIO base is deprecated, use dynamic allocation.\n");
--      }
--      gdev->base = base;
--      ret = gpiodev_add_to_list_unlocked(gdev);
--      if (ret) {
--              spin_unlock_irqrestore(&gpio_lock, flags);
--              chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
--              goto err_free_label;
-+              for (i = 0; i < gc->ngpio; i++)
-+                      gdev->descs[i].gdev = gdev;
-       }
--      for (i = 0; i < gc->ngpio; i++)
--              gdev->descs[i].gdev = gdev;
--
--      spin_unlock_irqrestore(&gpio_lock, flags);
--
-       BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
-       BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
-       init_rwsem(&gdev->sem);
-@@ -1015,9 +1003,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
-               goto err_print_message;
-       }
- err_remove_from_list:
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_del(&gdev->list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock)
-+              list_del(&gdev->list);
- err_free_label:
-       kfree_const(gdev->label);
- err_free_descs:
-@@ -1126,7 +1113,7 @@ struct gpio_device *gpio_device_find(void *data,
-        */
-       might_sleep();
--      guard(spinlock_irqsave)(&gpio_lock);
-+      guard(mutex)(&gpio_devices_lock);
-       list_for_each_entry(gdev, &gpio_devices, list) {
-               if (gdev->chip && match(gdev->chip, data))
-@@ -4727,35 +4714,33 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
- static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
- {
--      unsigned long flags;
-       struct gpio_device *gdev = NULL;
-       loff_t index = *pos;
-       s->private = "";
--      spin_lock_irqsave(&gpio_lock, flags);
--      list_for_each_entry(gdev, &gpio_devices, list)
--              if (index-- == 0) {
--                      spin_unlock_irqrestore(&gpio_lock, flags);
-+      guard(mutex)(&gpio_devices_lock);
-+
-+      list_for_each_entry(gdev, &gpio_devices, list) {
-+              if (index-- == 0)
-                       return gdev;
--              }
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      }
-       return NULL;
- }
- static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
- {
--      unsigned long flags;
-       struct gpio_device *gdev = v;
-       void *ret = NULL;
--      spin_lock_irqsave(&gpio_lock, flags);
--      if (list_is_last(&gdev->list, &gpio_devices))
--              ret = NULL;
--      else
--              ret = list_first_entry(&gdev->list, struct gpio_device, list);
--      spin_unlock_irqrestore(&gpio_lock, flags);
-+      scoped_guard(mutex, &gpio_devices_lock) {
-+              if (list_is_last(&gdev->list, &gpio_devices))
-+                      ret = NULL;
-+              else
-+                      ret = list_first_entry(&gdev->list, struct gpio_device,
-+                                             list);
-+      }
-       s->private = "\n";
-       ++*pos;
-diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
-index 3ccacf3c1288..8142b5cbc395 100644
---- a/drivers/gpio/gpiolib.h
-+++ b/drivers/gpio/gpiolib.h
-@@ -15,6 +15,7 @@
- #include <linux/gpio/consumer.h> /* for enum gpiod_flags */
- #include <linux/gpio/driver.h>
- #include <linux/module.h>
-+#include <linux/mutex.h>
- #include <linux/notifier.h>
- #include <linux/rwsem.h>
-@@ -136,6 +137,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
- extern spinlock_t gpio_lock;
- extern struct list_head gpio_devices;
-+extern struct mutex gpio_devices_lock;
- void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
--- 
-2.43.0
-
index 479e91f2173bc3f4d423e85bfc4f7b11b0eb2212..a34a87036f4a9ac78ffd596147b5a78057ab87e8 100644 (file)
@@ -365,7 +365,6 @@ mmc-sdhci_am654-fix-ti-soc-dependencies.patch
 mmc-sdhci_omap-fix-ti-soc-dependencies.patch
 drm-amdkfd-fix-type-of-dbg_flags-in-struct-kfd_proce.patch
 gpiolib-rename-static-functions-that-are-called-with.patch
-gpiolib-use-a-mutex-to-protect-the-list-of-gpio-devi.patch
 gpiolib-remove-the-gpio-device-from-the-list-when-it.patch
 ib-iser-prevent-invalidating-wrong-mr.patch
 drm-amdkfd-confirm-list-is-non-empty-before-utilizin.patch