2022-09-08 06:11:38

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 3/4] gpiolib: rework quirk handling in of_find_gpio()

Instead of having a string of "if" statements let's put all quirks into
an array and iterate over them.

Signed-off-by: Dmitry Torokhov <[email protected]>
---
drivers/gpio/gpiolib-of.c | 62 ++++++++++++++++-----------------------
1 file changed, 26 insertions(+), 36 deletions(-)

diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 30b89b694530..097e948c1d49 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -372,14 +372,12 @@ EXPORT_SYMBOL_GPL(gpiod_get_from_of_node);
* properties should be named "foo-gpios" so we have this special kludge for
* them.
*/
-static struct gpio_desc *of_find_spi_gpio(struct device *dev,
+static struct gpio_desc *of_find_spi_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
enum of_gpio_flags *of_flags)
{
char prop_name[32]; /* 32 is max size of property name */
- const struct device_node *np = dev->of_node;
- struct gpio_desc *desc;

/*
* Hopefully the compiler stubs the rest of the function if this
@@ -395,8 +393,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev,
/* Will be "gpio-sck", "gpio-mosi" or "gpio-miso" */
snprintf(prop_name, sizeof(prop_name), "%s-%s", "gpio", con_id);

- desc = of_get_named_gpiod_flags(np, prop_name, idx, of_flags);
- return desc;
+ return of_get_named_gpiod_flags(np, prop_name, idx, of_flags);
}

/*
@@ -404,13 +401,11 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev,
* lines rather than "cs-gpios" like all other SPI hardware. Account for this
* with a special quirk.
*/
-static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
+static struct gpio_desc *of_find_spi_cs_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
enum of_gpio_flags *of_flags)
{
- const struct device_node *np = dev->of_node;
-
if (!IS_ENABLED(CONFIG_SPI_MASTER))
return ERR_PTR(-ENOENT);

@@ -428,7 +423,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
* uses just "gpios" so translate to that when "cs-gpios" is
* requested.
*/
- return of_get_named_gpiod_flags(dev->of_node, "gpios", idx, of_flags);
+ return of_get_named_gpiod_flags(np, "gpios", idx, of_flags);
}

/*
@@ -436,7 +431,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
* properties should be named "foo-gpios" so we have this special kludge for
* them.
*/
-static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
+static struct gpio_desc *of_find_regulator_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
enum of_gpio_flags *of_flags)
@@ -447,8 +442,6 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
"wlf,ldo1ena", /* WM8994 */
"wlf,ldo2ena", /* WM8994 */
};
- const struct device_node *np = dev->of_node;
- struct gpio_desc *desc;
int i;

if (!IS_ENABLED(CONFIG_REGULATOR))
@@ -461,11 +454,10 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
if (i < 0)
return ERR_PTR(-ENOENT);

- desc = of_get_named_gpiod_flags(np, con_id, idx, of_flags);
- return desc;
+ return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
}

-static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
+static struct gpio_desc *of_find_arizona_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
enum of_gpio_flags *of_flags)
@@ -476,10 +468,10 @@ static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
if (!con_id || strcmp(con_id, "wlf,reset"))
return ERR_PTR(-ENOENT);

- return of_get_named_gpiod_flags(dev->of_node, con_id, idx, of_flags);
+ return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
}

-static struct gpio_desc *of_find_usb_gpio(struct device *dev,
+static struct gpio_desc *of_find_usb_gpio(struct device_node *np,
const char *con_id,
unsigned int idx,
enum of_gpio_flags *of_flags)
@@ -495,14 +487,27 @@ static struct gpio_desc *of_find_usb_gpio(struct device *dev,
if (!con_id || strcmp(con_id, "fcs,int_n"))
return ERR_PTR(-ENOENT);

- return of_get_named_gpiod_flags(dev->of_node, con_id, idx, of_flags);
+ return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
}

+typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np,
+ const char *con_id,
+ unsigned int idx,
+ enum of_gpio_flags *of_flags);
+static const of_find_gpio_quirk of_find_gpio_quirks[] = {
+ of_find_spi_gpio,
+ of_find_spi_cs_gpio,
+ of_find_regulator_gpio,
+ of_find_arizona_gpio,
+ of_find_usb_gpio,
+};
+
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, unsigned long *flags)
{
char prop_name[32]; /* 32 is max size of property name */
enum of_gpio_flags of_flags;
+ const of_find_gpio_quirk *q;
struct gpio_desc *desc;
unsigned int i;

@@ -522,24 +527,9 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
break;
}

- if (gpiod_not_found(desc)) {
- /* Special handling for SPI GPIOs if used */
- desc = of_find_spi_gpio(dev, con_id, idx, &of_flags);
- }
-
- if (gpiod_not_found(desc))
- desc = of_find_spi_cs_gpio(dev, con_id, idx, &of_flags);
-
- if (gpiod_not_found(desc)) {
- /* Special handling for regulator GPIOs if used */
- desc = of_find_regulator_gpio(dev, con_id, idx, &of_flags);
- }
-
- if (gpiod_not_found(desc))
- desc = of_find_arizona_gpio(dev, con_id, idx, &of_flags);
-
- if (gpiod_not_found(desc))
- desc = of_find_usb_gpio(dev, con_id, idx, &of_flags);
+ /* Properly named GPIO was not found, try workarounds */
+ for (q = of_find_gpio_quirks; gpiod_not_found(desc) && *q; q++)
+ desc = (*q)(dev->of_node, con_id, idx, &of_flags);

if (IS_ERR(desc))
return desc;
--
2.37.2.789.g6183377224-goog


2022-09-08 13:27:19

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 3/4] gpiolib: rework quirk handling in of_find_gpio()

On Thu, Sep 8, 2022 at 7:39 AM Dmitry Torokhov
<[email protected]> wrote:

> Instead of having a string of "if" statements let's put all quirks into
> an array and iterate over them.
>
> Signed-off-by: Dmitry Torokhov <[email protected]>

That's a change I wanted to do but didn't get around to, thanks a lot!
Reviewed-by: Linus Walleij <[email protected]>

Yours,
Linus Walleij

2022-09-16 11:26:44

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH 3/4] gpiolib: rework quirk handling in of_find_gpio()

On 08/09/2022 06:39, Dmitry Torokhov wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> Instead of having a string of "if" statements let's put all quirks into
> an array and iterate over them.
>
> Signed-off-by: Dmitry Torokhov <[email protected]>

Hey,
This seems to have landed in -next today as a2b5e207cade which has
unfortunately broken boot for me:

[ 0.765969] Unable to handle kernel paging request at virtual address ffffffad6f697066
[ 0.774948] Oops [#1]
[ 0.777491] Modules linked in:
[ 0.780896] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc1-00037-ga2b5e207cade #1
[ 0.789668] Hardware name: Microchip PolarFire-SoC Icicle Kit (DT)
[ 0.796512] epc : 0xffffffad6f697066
[ 0.800491] ra : of_find_gpio+0x12c/0x1fa
[ 0.805066] epc : ffffffad6f697066 ra : ffffffff8042032c sp : ffffffc80400b4e0
[ 0.813062] gp : ffffffff810ef490 tp : ffffffe77fe68000 t0 : 0000000400000000
[ 0.821063] t1 : 0000001000000000 t2 : 0000000000000010 s0 : ffffffc80400b560
[ 0.829058] s1 : ffffffff80c52a88 a0 : ffffffe7bfdf37b0 a1 : ffffffff80d5320e
[ 0.837053] a2 : 0000000000000000 a3 : ffffffc80400b4e4 a4 : 6e61722d6f697067
[ 0.845057] a5 : 0000000000000000 a6 : ffffffff80c4e760 a7 : ffffffe77ffb5b73
[ 0.853048] s2 : ffffffc80400b588 s3 : 0000000000000000 s4 : ffffffe77ffad810
[ 0.861052] s5 : ffffffff810f3098 s6 : ffffffff80d5320e s7 : fffffffffffffffe
[ 0.869048] s8 : fffffffffffff000 s9 : 0000000000000003 s10: 0000000000000000
[ 0.877050] s11: ffffffff80d5320e t3 : 0000000200000000 t4 : ffffffff80c4ebe8
[ 0.885045] t5 : ffffffff80d4ce2e t6 : ffffffe77ffb5b72
[ 0.890929] status: 0000000200000120 badaddr: ffffffad6f697066 cause: 000000000000000c
[ 0.900316] ---[ end trace 0000000000000000 ]---
[ 0.905544] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 0.914024] SMP: stopping secondary CPUs
[ 0.918394] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]---

In case it is useful to you, I have gpio nodes in my devicetree
but I am not building a driver that binds to those nodes. Since I
don't have a driver, that's pretty much all of the relevant info
from the boot log. Anything else you need, lmk and I will try to
provide :)

Thanks,
Conor.


> ---
> drivers/gpio/gpiolib-of.c | 62 ++++++++++++++++-----------------------
> 1 file changed, 26 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
> index 30b89b694530..097e948c1d49 100644
> --- a/drivers/gpio/gpiolib-of.c
> +++ b/drivers/gpio/gpiolib-of.c
> @@ -372,14 +372,12 @@ EXPORT_SYMBOL_GPL(gpiod_get_from_of_node);
> * properties should be named "foo-gpios" so we have this special kludge for
> * them.
> */
> -static struct gpio_desc *of_find_spi_gpio(struct device *dev,
> +static struct gpio_desc *of_find_spi_gpio(struct device_node *np,
> const char *con_id,
> unsigned int idx,
> enum of_gpio_flags *of_flags)
> {
> char prop_name[32]; /* 32 is max size of property name */
> - const struct device_node *np = dev->of_node;
> - struct gpio_desc *desc;
>
> /*
> * Hopefully the compiler stubs the rest of the function if this
> @@ -395,8 +393,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev,
> /* Will be "gpio-sck", "gpio-mosi" or "gpio-miso" */
> snprintf(prop_name, sizeof(prop_name), "%s-%s", "gpio", con_id);
>
> - desc = of_get_named_gpiod_flags(np, prop_name, idx, of_flags);
> - return desc;
> + return of_get_named_gpiod_flags(np, prop_name, idx, of_flags);
> }
>
> /*
> @@ -404,13 +401,11 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev,
> * lines rather than "cs-gpios" like all other SPI hardware. Account for this
> * with a special quirk.
> */
> -static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
> +static struct gpio_desc *of_find_spi_cs_gpio(struct device_node *np,
> const char *con_id,
> unsigned int idx,
> enum of_gpio_flags *of_flags)
> {
> - const struct device_node *np = dev->of_node;
> -
> if (!IS_ENABLED(CONFIG_SPI_MASTER))
> return ERR_PTR(-ENOENT);
>
> @@ -428,7 +423,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
> * uses just "gpios" so translate to that when "cs-gpios" is
> * requested.
> */
> - return of_get_named_gpiod_flags(dev->of_node, "gpios", idx, of_flags);
> + return of_get_named_gpiod_flags(np, "gpios", idx, of_flags);
> }
>
> /*
> @@ -436,7 +431,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev,
> * properties should be named "foo-gpios" so we have this special kludge for
> * them.
> */
> -static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
> +static struct gpio_desc *of_find_regulator_gpio(struct device_node *np,
> const char *con_id,
> unsigned int idx,
> enum of_gpio_flags *of_flags)
> @@ -447,8 +442,6 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
> "wlf,ldo1ena", /* WM8994 */
> "wlf,ldo2ena", /* WM8994 */
> };
> - const struct device_node *np = dev->of_node;
> - struct gpio_desc *desc;
> int i;
>
> if (!IS_ENABLED(CONFIG_REGULATOR))
> @@ -461,11 +454,10 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev,
> if (i < 0)
> return ERR_PTR(-ENOENT);
>
> - desc = of_get_named_gpiod_flags(np, con_id, idx, of_flags);
> - return desc;
> + return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
> }
>
> -static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
> +static struct gpio_desc *of_find_arizona_gpio(struct device_node *np,
> const char *con_id,
> unsigned int idx,
> enum of_gpio_flags *of_flags)
> @@ -476,10 +468,10 @@ static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
> if (!con_id || strcmp(con_id, "wlf,reset"))
> return ERR_PTR(-ENOENT);
>
> - return of_get_named_gpiod_flags(dev->of_node, con_id, idx, of_flags);
> + return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
> }
>
> -static struct gpio_desc *of_find_usb_gpio(struct device *dev,
> +static struct gpio_desc *of_find_usb_gpio(struct device_node *np,
> const char *con_id,
> unsigned int idx,
> enum of_gpio_flags *of_flags)
> @@ -495,14 +487,27 @@ static struct gpio_desc *of_find_usb_gpio(struct device *dev,
> if (!con_id || strcmp(con_id, "fcs,int_n"))
> return ERR_PTR(-ENOENT);
>
> - return of_get_named_gpiod_flags(dev->of_node, con_id, idx, of_flags);
> + return of_get_named_gpiod_flags(np, con_id, idx, of_flags);
> }
>
> +typedef struct gpio_desc *(*of_find_gpio_quirk)(struct device_node *np,
> + const char *con_id,
> + unsigned int idx,
> + enum of_gpio_flags *of_flags);
> +static const of_find_gpio_quirk of_find_gpio_quirks[] = {
> + of_find_spi_gpio,
> + of_find_spi_cs_gpio,
> + of_find_regulator_gpio,
> + of_find_arizona_gpio,
> + of_find_usb_gpio,
> +};
> +
> struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> unsigned int idx, unsigned long *flags)
> {
> char prop_name[32]; /* 32 is max size of property name */
> enum of_gpio_flags of_flags;
> + const of_find_gpio_quirk *q;
> struct gpio_desc *desc;
> unsigned int i;
>
> @@ -522,24 +527,9 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> break;
> }
>
> - if (gpiod_not_found(desc)) {
> - /* Special handling for SPI GPIOs if used */
> - desc = of_find_spi_gpio(dev, con_id, idx, &of_flags);
> - }
> -
> - if (gpiod_not_found(desc))
> - desc = of_find_spi_cs_gpio(dev, con_id, idx, &of_flags);
> -
> - if (gpiod_not_found(desc)) {
> - /* Special handling for regulator GPIOs if used */
> - desc = of_find_regulator_gpio(dev, con_id, idx, &of_flags);
> - }
> -
> - if (gpiod_not_found(desc))
> - desc = of_find_arizona_gpio(dev, con_id, idx, &of_flags);
> -
> - if (gpiod_not_found(desc))
> - desc = of_find_usb_gpio(dev, con_id, idx, &of_flags);
> + /* Properly named GPIO was not found, try workarounds */
> + for (q = of_find_gpio_quirks; gpiod_not_found(desc) && *q; q++)
> + desc = (*q)(dev->of_node, con_id, idx, &of_flags);
>
> if (IS_ERR(desc))
> return desc;
> --
> 2.37.2.789.g6183377224-goog
>

2022-09-16 11:29:22

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH 3/4] gpiolib: rework quirk handling in of_find_gpio()

On 16/09/2022 12:20, Linus Walleij wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
> On Fri, Sep 16, 2022 at 1:04 PM <[email protected]> wrote:
>>
>> On 08/09/2022 06:39, Dmitry Torokhov wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Instead of having a string of "if" statements let's put all quirks into
>>> an array and iterate over them.
>>>
>>> Signed-off-by: Dmitry Torokhov <[email protected]>
>>
>> Hey,
>> This seems to have landed in -next today as a2b5e207cade which has
>> unfortunately broken boot for me:
>
> Michael Walle has sent a patch fixing it:
> https://lore.kernel.org/linux-gpio/[email protected]/

Ohh great, I checked before I started writing my mail but didn't
see anything, which makes sense given the times..

2022-09-16 11:53:58

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 3/4] gpiolib: rework quirk handling in of_find_gpio()

On Fri, Sep 16, 2022 at 1:04 PM <[email protected]> wrote:
>
> On 08/09/2022 06:39, Dmitry Torokhov wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >
> > Instead of having a string of "if" statements let's put all quirks into
> > an array and iterate over them.
> >
> > Signed-off-by: Dmitry Torokhov <[email protected]>
>
> Hey,
> This seems to have landed in -next today as a2b5e207cade which has
> unfortunately broken boot for me:

Michael Walle has sent a patch fixing it:
https://lore.kernel.org/linux-gpio/[email protected]/

Yours,
Linus Walleij