From: Bartosz Golaszewski <brgl@bgdev.pl>
To: Linus Walleij <linus.walleij@linaro.org>,
Kent Gibson <warthog618@gmail.com>, Alex Elder <elder@linaro.org>,
Geert Uytterhoeven <geert+renesas@glider.be>,
"Paul E . McKenney" <paulmck@kernel.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Wolfram Sang <wsa@the-dreams.de>
Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org,
Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Subject: [PATCH 07/22] gpio: protect the descriptor label with SRCU
Date: Tue, 30 Jan 2024 13:48:13 +0100 [thread overview]
Message-ID: <20240130124828.14678-8-brgl@bgdev.pl> (raw)
In-Reply-To: <20240130124828.14678-1-brgl@bgdev.pl>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
In order to ensure that the label is not freed while it's being
accessed, let's protect it with SRCU and synchronize it everytime it's
changed.
Let's modify desc_set_label() to manage the memory used for the label as
it can only be freed once synchronize_srcu() returns.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/gpiolib-cdev.c | 10 +++++---
drivers/gpio/gpiolib.c | 47 +++++++++++++++++++++++--------------
drivers/gpio/gpiolib.h | 34 +++++++++++++++++++--------
3 files changed, 61 insertions(+), 30 deletions(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 2c0a0700762d..75f4912339a6 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -2297,6 +2297,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
{
struct gpio_chip *gc = desc->gdev->chip;
unsigned long dflags;
+ const char *label;
memset(info, 0, sizeof(*info));
info->offset = gpio_chip_hwgpio(desc);
@@ -2305,9 +2306,12 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
if (desc->name)
strscpy(info->name, desc->name, sizeof(info->name));
- if (gpiod_get_label(desc))
- strscpy(info->consumer, gpiod_get_label(desc),
- sizeof(info->consumer));
+ scoped_guard(srcu, &desc->srcu) {
+ label = gpiod_get_label(desc);
+ if (label)
+ strscpy(info->consumer, label,
+ sizeof(info->consumer));
+ }
dflags = READ_ONCE(desc->flags);
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 94e1a603cf8b..93b80f3e9fe2 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -114,12 +114,26 @@ const char *gpiod_get_label(struct gpio_desc *desc)
!test_bit(FLAG_REQUESTED, &flags))
return "interrupt";
- return test_bit(FLAG_REQUESTED, &flags) ? desc->label : NULL;
+ return test_bit(FLAG_REQUESTED, &flags) ?
+ rcu_dereference(desc->label) : NULL;
}
-static inline void desc_set_label(struct gpio_desc *d, const char *label)
+static int desc_set_label(struct gpio_desc *desc, const char *label)
{
- d->label = label;
+ const char *new = NULL, *old;
+
+ if (label) {
+ /* FIXME: make this GFP_KERNEL once the spinlock is out. */
+ new = kstrdup_const(label, GFP_ATOMIC);
+ if (!new)
+ return -ENOMEM;
+ }
+
+ old = rcu_replace_pointer(desc->label, new, 1);
+ synchronize_srcu(&desc->srcu);
+ kfree_const(old);
+
+ return 0;
}
/**
@@ -2220,9 +2234,7 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
*/
- if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
- desc_set_label(desc, label ? : "?");
- } else {
+ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags)) {
ret = -EBUSY;
goto out_free_unlock;
}
@@ -2250,6 +2262,13 @@ static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
}
spin_unlock_irqrestore(&gpio_lock, flags);
+
+ ret = desc_set_label(desc, label ? : "?");
+ if (ret) {
+ clear_bit(FLAG_REQUESTED, &desc->flags);
+ return ret;
+ }
+
return 0;
out_free_unlock:
@@ -2334,8 +2353,6 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
gc->free(gc, gpio_chip_hwgpio(desc));
spin_lock_irqsave(&gpio_lock, flags);
}
- kfree_const(desc->label);
- desc_set_label(desc, NULL);
clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
clear_bit(FLAG_REQUESTED, &desc->flags);
clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
@@ -2353,6 +2370,7 @@ static bool gpiod_free_commit(struct gpio_desc *desc)
}
spin_unlock_irqrestore(&gpio_lock, flags);
+ desc_set_label(desc, NULL);
gpiod_line_state_notify(desc, GPIOLINE_CHANGED_RELEASED);
return ret;
@@ -2400,6 +2418,8 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
if (!test_bit(FLAG_REQUESTED, &desc->flags))
return NULL;
+ guard(srcu)(&desc->srcu);
+
/*
* FIXME: Once we mark gpiod_direction_input/output() and
* gpiod_get_direction() with might_sleep(), we'll be able to protect
@@ -3511,16 +3531,8 @@ EXPORT_SYMBOL_GPL(gpiod_cansleep);
int gpiod_set_consumer_name(struct gpio_desc *desc, const char *name)
{
VALIDATE_DESC(desc);
- if (name) {
- name = kstrdup_const(name, GFP_KERNEL);
- if (!name)
- return -ENOMEM;
- }
- kfree_const(desc->label);
- desc_set_label(desc, name);
-
- return 0;
+ return desc_set_label(desc, name);
}
EXPORT_SYMBOL_GPL(gpiod_set_consumer_name);
@@ -4726,6 +4738,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev)
int value;
for_each_gpio_desc(gc, desc) {
+ guard(srcu)(&desc->srcu);
if (test_bit(FLAG_REQUESTED, &desc->flags)) {
gpiod_get_direction(desc);
is_out = test_bit(FLAG_IS_OUT, &desc->flags);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 6e14b629c48b..d2e73eea9e92 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -180,7 +180,7 @@ struct gpio_desc {
#define FLAG_EVENT_CLOCK_HTE 19 /* GPIO CDEV reports hardware timestamps in events */
/* Connection label */
- const char *label;
+ const char __rcu *label;
/* Name of the GPIO */
const char *name;
#ifdef CONFIG_OF_DYNAMIC
@@ -223,15 +223,29 @@ static inline int gpio_chip_hwgpio(const struct gpio_desc *desc)
/* With descriptor prefix */
-#define gpiod_err(desc, fmt, ...) \
- pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_warn(desc, fmt, ...) \
- pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?", \
- ##__VA_ARGS__)
-#define gpiod_dbg(desc, fmt, ...) \
- pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label ? : "?",\
- ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...) \
+do { \
+ scoped_guard(srcu, &desc->srcu) { \
+ pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
+ gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
+ } \
+} while (0)
+
+#define gpiod_warn(desc, fmt, ...) \
+do { \
+ scoped_guard(srcu, &desc->srcu) { \
+ pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
+ gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
+ } \
+} while (0)
+
+#define gpiod_dbg(desc, fmt, ...) \
+do { \
+ scoped_guard(srcu, &desc->srcu) { \
+ pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), \
+ gpiod_get_label(desc) ? : "?", ##__VA_ARGS__); \
+ } \
+} while (0)
/* With chip prefix */
--
2.40.1
next prev parent reply other threads:[~2024-01-30 12:48 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-30 12:48 [PATCH 00/22] gpio: rework locking and object life-time control Bartosz Golaszewski
2024-01-30 12:48 ` [PATCH 01/22] gpio: protect the list of GPIO devices with SRCU Bartosz Golaszewski
2024-01-31 9:34 ` kernel test robot
2024-01-31 12:45 ` Bartosz Golaszewski
2024-01-31 15:01 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 02/22] gpio: of: assign and read the hog pointer atomically Bartosz Golaszewski
2024-01-31 17:38 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 03/22] gpio: remove unused logging helpers Bartosz Golaszewski
2024-01-31 17:39 ` Linus Walleij
2024-01-31 18:08 ` Bartosz Golaszewski
2024-01-31 20:33 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 04/22] gpio: provide and use gpiod_get_label() Bartosz Golaszewski
2024-01-31 19:36 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 05/22] gpio: don't set label from irq helpers Bartosz Golaszewski
2024-01-31 19:38 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 06/22] gpio: add SRCU infrastructure to struct gpio_desc Bartosz Golaszewski
2024-01-31 19:35 ` Linus Walleij
2024-01-30 12:48 ` Bartosz Golaszewski [this message]
2024-01-31 19:41 ` [PATCH 07/22] gpio: protect the descriptor label with SRCU Linus Walleij
2024-01-30 12:48 ` [PATCH 08/22] gpio: sysfs: use gpio_device_find() to iterate over existing devices Bartosz Golaszewski
2024-01-31 19:42 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 09/22] gpio: remove gpio_lock Bartosz Golaszewski
2024-01-31 19:51 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 10/22] gpio: reinforce desc->flags handling Bartosz Golaszewski
2024-01-31 20:01 ` Linus Walleij
2024-01-31 20:35 ` Linus Walleij
2024-02-01 18:30 ` Bartosz Golaszewski
2024-01-30 12:48 ` [PATCH 11/22] gpio: remove unneeded code from gpio_device_get_desc() Bartosz Golaszewski
2024-01-31 20:02 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 12/22] gpio: sysfs: extend the critical section for unregistering sysfs devices Bartosz Golaszewski
2024-01-31 20:06 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 13/22] gpio: sysfs: pass the GPIO device - not chip - to sysfs callbacks Bartosz Golaszewski
2024-01-31 20:09 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 14/22] gpio: cdev: replace gpiochip_get_desc() with gpio_device_get_desc() Bartosz Golaszewski
2024-01-31 20:10 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 15/22] gpio: cdev: don't access gdev->chip if it's not needed Bartosz Golaszewski
2024-01-31 20:11 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 16/22] gpio: reduce the functionality of validate_desc() Bartosz Golaszewski
2024-01-31 20:16 ` Linus Walleij
2024-01-31 20:19 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 17/22] gpio: remove unnecessary checks from gpiod_to_chip() Bartosz Golaszewski
2024-01-30 12:48 ` [PATCH 18/22] gpio: add the can_sleep flag to struct gpio_device Bartosz Golaszewski
2024-01-31 20:17 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 19/22] gpio: add SRCU infrastructure " Bartosz Golaszewski
2024-01-30 12:48 ` [PATCH 20/22] gpio: protect the pointer to gpio_chip in gpio_device with SRCU Bartosz Golaszewski
2024-01-31 0:41 ` kernel test robot
2024-01-31 8:15 ` Bartosz Golaszewski
2024-01-31 2:20 ` kernel test robot
2024-01-31 9:02 ` Bartosz Golaszewski
2024-01-31 9:24 ` Paul E. McKenney
2024-01-31 9:28 ` Bartosz Golaszewski
2024-01-31 9:41 ` Bartosz Golaszewski
2024-01-31 9:42 ` Paul E. McKenney
2024-01-31 10:17 ` brgl
2024-01-31 11:00 ` Paul E. McKenney
2024-01-31 12:23 ` Bartosz Golaszewski
2024-01-31 20:23 ` Linus Walleij
2024-02-01 5:03 ` Dan Carpenter
2024-02-01 7:57 ` Bartosz Golaszewski
2024-01-30 12:48 ` [PATCH 21/22] gpio: remove the RW semaphore from the GPIO device Bartosz Golaszewski
2024-01-31 20:24 ` Linus Walleij
2024-01-30 12:48 ` [PATCH 22/22] gpio: mark unsafe gpio_chip manipulators as deprecated Bartosz Golaszewski
2024-01-31 20:29 ` Linus Walleij
2024-02-01 9:14 ` Bartosz Golaszewski
2024-01-31 20:32 ` [PATCH 00/22] gpio: rework locking and object life-time control Linus Walleij
2024-02-01 8:43 ` Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240130124828.14678-8-brgl@bgdev.pl \
--to=brgl@bgdev.pl \
--cc=andriy.shevchenko@linux.intel.com \
--cc=bartosz.golaszewski@linaro.org \
--cc=elder@linaro.org \
--cc=geert+renesas@glider.be \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@kernel.org \
--cc=warthog618@gmail.com \
--cc=wsa@the-dreams.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.