gpio: remove gpiochip_is_requested()

- provide a safer alternative to gpiochip_is_requested()
 - convert all existing users
 - remove gpiochip_is_requested()
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmVy01QACgkQEacuoBRx
 13LcZhAAyJlx3u3snkGjMc8O//2Se5YYhWMuUV37oNjTK5P+ahvq5T+DWSTVtNJz
 uJS4rdx4n4TXsbPJKPu8TAyIYhBZGmFAYmfJ4O3IgSrqEieRCp1TfUDI3q+iEHJ2
 APdLFF1OqYXpz1lqz/nMyyJaEyRmRrS09gMo9CSPgjh66oHAd+epN5pJTYffJ9yZ
 aAxKMIL8CBpLzfNlz4gqwsvObQZOTTM4L7BkH9JaXXnDTAtyQ+HpdlwwwJxTkkzy
 YEKrs06/quAoM8Re724l1EmCcgbZzbCkFnTLB/xSFgnV35L2MAvyFEOtd9Jnd8XP
 jeWV7hzPYrWKeSKCEOH042ILlyBkNfN/A6MDmF3B/3/D+eM1k/rXfSKA064plMl8
 BzSSzb1ylPOPLQp4idlV4qA3WY1AemAQZTOmQmV9C3/OaqdgcXLgyBXaARz2gOM4
 u0L+WybwjgmHd/4WuDLtuJ95gaU/YEpURtCGFWaKWQraaSQFDT2EV3nQf/hZ9WgM
 2SGqT0sVnmu2K0n0+EW5M4PZyForOwSM9tzqtYmTmal9s1adnL6yx9YH62ON3TV4
 Yazi+QpAo+lZ4zfzWV0JODE5ENOn0g9WTmGPLOBfYG7HiqK58WOCz2gwZpqX+xv6
 y6JppF7KD5k5xacpMFYHlE92HUyO8VqmTid92Q+97e7JG9xGDG4=
 =PlCm
 -----END PGP SIGNATURE-----

Merge tag 'gpio-remove-gpiochip_is_requested-for-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel

gpio: remove gpiochip_is_requested()

- provide a safer alternative to gpiochip_is_requested()
- convert all existing users
- remove gpiochip_is_requested()
This commit is contained in:
Linus Walleij 2023-12-12 00:46:23 +01:00
commit 78b778e363
9 changed files with 96 additions and 47 deletions

View File

@ -5,6 +5,7 @@
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@ -255,7 +256,6 @@ static void stmpe_dbg_show_one(struct seq_file *s,
{
struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
struct stmpe *stmpe = stmpe_gpio->stmpe;
const char *label = gpiochip_is_requested(gc, offset);
bool val = !!stmpe_gpio_get(gc, offset);
u8 bank = offset / 8;
u8 dir_reg = stmpe->regs[STMPE_IDX_GPDR_LSB + bank];
@ -263,6 +263,10 @@ static void stmpe_dbg_show_one(struct seq_file *s,
int ret;
u8 dir;
char *label __free(kfree) = gpiochip_dup_line_label(gc, offset);
if (IS_ERR(label))
return;
ret = stmpe_reg_read(stmpe, dir_reg);
if (ret < 0)
return;

View File

@ -8,6 +8,7 @@
*
*/
#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
@ -160,18 +161,21 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
int reg;
const char *label, *pull, *powerdomain;
const char *pull, *powerdomain;
/* We report the GPIO even if it's not requested since
* we're also reporting things like alternate
* functions which apply even when the GPIO is not in
* use as a GPIO.
*/
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label)) {
dev_err(wm831x->dev, "Failed to duplicate label\n");
continue;
}
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
seq_printf(s, " gpio-%-3d (%-20.20s) ",
gpio, label ?: "Unrequested");
reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
if (reg < 0) {

View File

@ -8,6 +8,7 @@
*
*/
#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
@ -193,18 +194,20 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
int reg;
const char *label;
/* We report the GPIO even if it's not requested since
* we're also reporting things like alternate
* functions which apply even when the GPIO is not in
* use as a GPIO.
*/
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label)) {
dev_err(wm8994->dev, "Failed to duplicate label\n");
continue;
}
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio,
label ?: "Unrequested");
reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
if (reg < 0) {

View File

@ -1085,7 +1085,7 @@ void gpiochip_remove(struct gpio_chip *gc)
spin_lock_irqsave(&gpio_lock, flags);
for (i = 0; i < gdev->ngpio; i++) {
if (gpiochip_is_requested(gc, i))
if (test_bit(FLAG_REQUESTED, &gdev->descs[i].flags))
break;
}
spin_unlock_irqrestore(&gpio_lock, flags);
@ -2374,31 +2374,38 @@ void gpiod_free(struct gpio_desc *desc)
}
/**
* gpiochip_is_requested - return string iff signal was requested
* @gc: controller managing the signal
* @offset: of signal within controller's 0..(ngpio - 1) range
* gpiochip_dup_line_label - Get a copy of the consumer label.
* @gc: GPIO chip controlling this line.
* @offset: Hardware offset of the line.
*
* Returns NULL if the GPIO is not currently requested, else a string.
* The string returned is the label passed to gpio_request(); if none has been
* passed it is a meaningless, non-NULL constant.
* Returns:
* Pointer to a copy of the consumer label if the line is requested or NULL
* if it's not. If a valid pointer was returned, it must be freed using
* kfree(). In case of a memory allocation error, the function returns %ENOMEM.
*
* This function is for use by GPIO controller drivers. The label can
* help with diagnostics, and knowing that the signal is used as a GPIO
* can help avoid accidentally multiplexing it to another controller.
* Must not be called from atomic context.
*/
const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset)
char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_desc *desc;
char *label;
desc = gpiochip_get_desc(gc, offset);
if (IS_ERR(desc))
return NULL;
if (test_bit(FLAG_REQUESTED, &desc->flags) == 0)
guard(spinlock_irqsave)(&gpio_lock);
if (!test_bit(FLAG_REQUESTED, &desc->flags))
return NULL;
return desc->label;
label = kstrdup(desc->label, GFP_KERNEL);
if (!label)
return ERR_PTR(-ENOMEM);
return label;
}
EXPORT_SYMBOL_GPL(gpiochip_is_requested);
EXPORT_SYMBOL_GPL(gpiochip_dup_line_label);
/**
* gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor

View File

@ -9,6 +9,7 @@
#include <linux/acpi.h>
#include <linux/array_size.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@ -1173,7 +1174,6 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
const char *pull_str = NULL;
const char *pull = NULL;
unsigned long flags;
const char *label;
unsigned int pin;
pin = vg->soc->pins[i].number;
@ -1200,9 +1200,10 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, "Pin %i: can't retrieve community\n", pin);
continue;
}
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label))
continue;
switch (conf0 & BYT_PULL_ASSIGN_MASK) {
case BYT_PULL_ASSIGN_UP:
@ -1231,7 +1232,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s,
" gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
pin,
label,
label ?: "Unrequested",
val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out",
str_hi_lo(val & BYT_LEVEL),

View File

@ -6,7 +6,9 @@
*
* Driver allows to use AxB5xx unused pins to be used as GPIO
*/
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
@ -453,12 +455,11 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
unsigned offset, unsigned gpio)
{
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
const char *label = gpiochip_is_requested(chip, offset - 1);
u8 gpio_offset = offset - 1;
int mode = -1;
bool is_out;
bool pd;
int ret;
int ret = -ENOMEM;
const char *modes[] = {
[ABX500_DEFAULT] = "default",
@ -474,6 +475,10 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
[ABX500_GPIO_PULL_UP] = "pull up",
};
char *label __free(kfree) = gpiochip_dup_line_label(chip, offset - 1);
if (IS_ERR(label))
goto out;
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
gpio_offset, &is_out);
if (ret < 0)

View File

@ -8,6 +8,7 @@
* Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
*/
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
@ -917,7 +918,6 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
struct pinctrl_dev *pctldev, struct gpio_chip *chip,
unsigned offset, unsigned gpio)
{
const char *label = gpiochip_is_requested(chip, offset);
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
int mode;
bool is_out;
@ -934,6 +934,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
[NMK_GPIO_ALT_C+4] = "altC4",
};
char *label = gpiochip_dup_line_label(chip, offset);
if (IS_ERR(label))
return;
clk_enable(nmk_chip->clk);
is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset));

View File

@ -4,6 +4,7 @@
* Copyright (C) Sunplus Tech / Tibbo Tech.
*/
#include <linux/cleanup.h>
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/err.h>
@ -500,16 +501,15 @@ static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
const char *label;
int i;
for (i = 0; i < chip->ngpio; i++) {
label = gpiochip_is_requested(chip, i);
if (!label)
label = "";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label))
continue;
seq_printf(s, " gpio-%03d (%-16.16s | %-16.16s)", i + chip->base,
chip->names[i], label);
chip->names[i], label ?: "");
seq_printf(s, " %c", sppctl_gpio_get_direction(chip, i) ? 'I' : 'O');
seq_printf(s, ":%d", sppctl_gpio_get(chip, i));
seq_printf(s, " %s", sppctl_first_get(chip, i) ? "gpi" : "mux");

View File

@ -531,19 +531,40 @@ struct gpio_chip {
#endif /* CONFIG_OF_GPIO */
};
const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset);
char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset);
struct _gpiochip_for_each_data {
const char **label;
unsigned int *i;
};
DEFINE_CLASS(_gpiochip_for_each_data,
struct _gpiochip_for_each_data,
if (*_T.label) kfree(*_T.label),
({
struct _gpiochip_for_each_data _data = { label, i };
*_data.i = 0;
_data;
}),
const char **label, int *i)
/**
* for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range
* @chip: the chip to query
* @i: loop variable
* @base: first GPIO in the range
* @size: amount of GPIOs to check starting from @base
* @label: label of current GPIO
* @_chip: the chip to query
* @_i: loop variable
* @_base: first GPIO in the range
* @_size: amount of GPIOs to check starting from @base
* @_label: label of current GPIO
*/
#define for_each_requested_gpio_in_range(chip, i, base, size, label) \
for (i = 0; i < size; i++) \
if ((label = gpiochip_is_requested(chip, base + i)) == NULL) {} else
#define for_each_requested_gpio_in_range(_chip, _i, _base, _size, _label) \
for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \
*_data.i < _size; \
(*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \
if ((*_data.label = \
gpiochip_dup_line_label(_chip, _base + *_data.i)) == NULL) {} \
else if (IS_ERR(*_data.label)) {} \
else
/* Iterates over all requested GPIO of the given @chip */
#define for_each_requested_gpio(chip, i, label) \