mbox series

[RFC,0/3] gpio: ep93xx: convert to multi irqchips

Message ID 20201224112203.7174-1-nikita.shubin@maquefel.me
Headers show
Series gpio: ep93xx: convert to multi irqchips | expand

Message

Nikita Shubin Dec. 24, 2020, 11:22 a.m. UTC
I was lucky enough to became an owner of some splendid piece's of
antiques called ts7250 based on the top of Cirrus Logic EP9302.

I don't know what fate expects this hardware (it's not EOL it's just Not
recommended for new designs) but i wanted to share fixes in ep93xx gpio area.

It seems ep93xx is deadly broken at current state usage of AB gpiochips
interrupts leads to deadlocks coused by irq_unmask/irq_mask recursions.

Port F is not working at all:

-bash-5.0# gpio-event-mon -n gpiochip5 -o 0 -r -f
------------[ cut here ]------------
kernel BUG at drivers/gpio/gpio-ep93xx.c:64!
Internal error: Oops - BUG: 0 [#1] ARM
Modules linked in:
CPU: 0 PID: 403 Comm: gpio-event-mon Not tainted 5.9.10-00011-ge93e9618628b-dirty #19
Hardware name: Technologic Systems TS-72xx SBC
PC is at ep93xx_gpio_update_int_params+0x1c/0x80
LR is at ep93xx_gpio_update_int_params+0x14/0x80
pc : [<c03abc44>]    lr : [<c03abc3c>]    psr: 20000093
sp : c158de00  ip : 00000000  fp : 00000001
r10: c44154d4  r9 : 00000000  r8 : c4415020
r7 : c04ef884  r6 : c051c842  r5 : c4415020  r4 : 00000005
r3 : 00000000  r2 : 00000000  r1 : c04eb768  r0 : 00000008
Flags: nzCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 0000717f  Table: 01684000  DAC: 00000051
Process gpio-event-mon (pid: 403, stack limit = 0x(ptrval))
Stack: (0xc158de00 to 0xc158e000)
de00: 00000005 00000002 c051c842 c0238dc0 c0238c98 c0238c98 c04ef874 00000000
de20: 00000003 c04fcfcc 60000013 c04ef910 c04ef8d4 c00456f0 c04ef874 c15f1e00
de40: 00000000 00000000 00000001 c0045d40 c15f1e00 c4400160 c0044ca8 c04ef8a8
de60: 60000013 00000000 c15f1e00 c04ef874 c04ef884 00000001 c0235d70 c158b800
de80: be825f0f c0045ec8 00000003 c158b800 c440aa00 be825bc8 00000003 00000001
dea0: 00000000 c0236f00 c44ed3a0 c158b800 c45c2015 00000000 00000001 00000003
dec0: 6f697067 6576652d 6d2d746e 00006e6f 00000000 00000000 00000000 00000000
dee0: be825df4 c00abb0c c440c500 c00aabd4 c440c500 c528b840 c45c2010 c04e1228
df00: 00000ff0 c4478d28 c030b404 be825bc8 c1550e20 00000003 c1550e20 c00c3388
df20: c4478d28 c00c3d48 be825f0f c00abd00 c45c2000 c45c2000 c1550e20 c00bfea8
df40: 00000003 c00b0714 00000000 c4450000 00000004 00000100 00000001 c04e1228
df60: c158dfb0 ffffff9c 000231f8 00000003 00000142 c00b085c 00000000 c04e1228
df80: 00000000 be825f0f 00000003 00000003 00000036 c00083c4 c158c000 00000000
dfa0: be825f0f c00081e0 be825f0f 00000003 00000003 c030b404 be825bc8 00000000
dfc0: be825f0f 00000003 00000003 00000036 00000001 00000000 00022070 be825f0f
dfe0: b6f2e4e0 be825bac 00010acc b6f2e4ec 60000010 00000003 00000000 00000000
[<c03abc44>] (ep93xx_gpio_update_int_params) from [<c0238dc0>] (ep93xx_gpio_irq_type+0x128/0x1c0)
[<c0238dc0>] (ep93xx_gpio_irq_type) from [<c00456f0>] (__irq_set_trigger+0x6c/0x128)
[<c00456f0>] (__irq_set_trigger) from [<c0045d40>] (__setup_irq+0x594/0x678)
[<c0045d40>] (__setup_irq) from [<c0045ec8>] (request_threaded_irq+0xa4/0x128)
[<c0045ec8>] (request_threaded_irq) from [<c0236f00>] (gpio_ioctl+0x300/0x4d8)
[<c0236f00>] (gpio_ioctl) from [<c00c3388>] (vfs_ioctl+0x24/0x3c)
[<c00c3388>] (vfs_ioctl) from [<c00c3d48>] (sys_ioctl+0xbc/0x768)
[<c00c3d48>] (sys_ioctl) from [<c00081e0>] (ret_fast_syscall+0x0/0x50)
Exception stack(0xc158dfa8 to 0xc158dff0)
dfa0:                   be825f0f 00000003 00000003 c030b404 be825bc8 00000000
dfc0: be825f0f 00000003 00000003 00000036 00000001 00000000 00022070 be825f0f
dfe0: b6f2e4e0 be825bac 00010acc b6f2e4ec
Code: e59f0060 ebfff3e1 e3540002 9a000000 (e7f001f2)
---[ end trace 3f6544e133e9f5ae ]---

These change requires your judgment.

Comments

Andy Shevchenko Dec. 26, 2020, 5:34 p.m. UTC | #1
On Thu, Dec 24, 2020 at 1:24 PM Nikita Shubin <nikita.shubin@maquefel.me> wrote:
>

> I was lucky enough to became an owner of some splendid piece's of

> antiques called ts7250 based on the top of Cirrus Logic EP9302.

>

> I don't know what fate expects this hardware (it's not EOL it's just Not

> recommended for new designs) but i wanted to share fixes in ep93xx gpio area.

>

> It seems ep93xx is deadly broken at current state usage of AB gpiochips

> interrupts leads to deadlocks coused by irq_unmask/irq_mask recursions.


I personally consider it quite nice to have support even for outdated
hardware (reminds me about a recent LWN article about 32-bit
architectures and a comment there how it could affect the environment
if we drop them from being supported).

So I fully support this series.

-- 
With Best Regards,
Andy Shevchenko
Andy Shevchenko Dec. 26, 2020, 5:52 p.m. UTC | #2
On Thu, Dec 24, 2020 at 1:23 PM Nikita Shubin <nikita.shubin@maquefel.me> wrote:
>

> Since gpiolib requires having separate irqchips for each gpiochip, we

> need to add some we definetly need a separate one for F port, and we


definitely

> could combine gpiochip A and B into one - but this will break namespace

> and logick.

>

> So despite 3 irqchips is a bit beefy we need a separate irqchip for each


is a -> being a

> interrupt capable port.

>

> - added separate irqchip for each iterrupt capable gpiochip


interrupt

> - dropped ep93xx_gpio_port (it wasn't working correct for port F anyway)

> - moved irq registers into separate struct ep93xx_irq_chip, togather


irq -> IRQ (everywhere)

together

>   with regs current state

> - reworked irq handle for ab gpiochips (through bit not tottaly sure this

>   is a correct thing to do)


ab -> AB ?

In the parentheses something like "I'm not totally sure that this is a
correct thing to do, though".

> - dropped has_irq and has_hierarchical_irq and added a simple index

>   which we rely on when adding irq's to gpiochip's


IRQs to GPIO chips

(It would be nice if you can spell check and proofread  commit
messages and comments in the code.

...

> +struct ep93xx_irq_chip {

> +       void __iomem    *int_type1;

> +       void __iomem    *int_type2;

> +       void __iomem    *eoi;

> +       void __iomem    *en;

> +       void __iomem    *debounce;

> +       void __iomem    *status;


This is a bit... overcomplicated.
Can we rather use regmap API?

> +       u8              gpio_int_unmasked;

> +       u8              gpio_int_enabled;

> +       u8              gpio_int_type1;

> +       u8              gpio_int_type2;

> +       u8              gpio_int_debounce;

> +       struct  irq_chip chip;

> +};


...

>  /* Port ordering is: A B F */

> +static const char *irq_chip_names[3]           = {"gpio-irq-a",

> +                                               "gpio-irq-b",

> +                                               "gpio-irq-f"};


Can you use better pattern, ie.
static const char * const foo[] = {
  ...
};

(there are two things: splitting per lines and additional const)?

...

> +       ab_parent_irq = platform_get_irq(pdev, 0);


Error check, please?
Also, if it's an optional resource, use platform_get_irq_optional().

> +       err = devm_request_irq(dev, ab_parent_irq,

> +                       ep93xx_ab_irq_handler,

> +                       IRQF_SHARED, eic->chip.name, gc);


> +


Redundant blank line.

> +       if (err) {

> +               dev_err(dev, "error requesting IRQ : %d\n", ab_parent_irq);

> +               return err;

> +       }


...

> +       girq->num_parents = 1;

> +       girq->parents = devm_kcalloc(dev, 1,

> +                               sizeof(*girq->parents),

> +                               GFP_KERNEL);


Can be squeezed to less amount of LOCs. Also consider to use
girq->num_parents as a parameter to devm_kcalloc().

> +       if (!girq->parents)

> +               return -ENOMEM;


...

> +       girq->handler = handle_level_irq;


Don't we want to mark them as bad by using handle_bad_irq() as default handler?

...

> +       /*

> +        * FIXME: convert this to use hierarchical IRQ support!

> +        * this requires fixing the root irqchip to be hierarchial.


hierarchical

> +        */


...

> +       girq->num_parents = 8;

> +       girq->parents = devm_kcalloc(dev, 8,

> +                                    sizeof(*girq->parents),

> +                                    GFP_KERNEL);


As per above.

> +


Redundant blank line.

> +       if (!girq->parents)

> +               return -ENOMEM;


...

> +       /* Pick resources 1..8 for these IRQs */

> +       for (i = 1; i <= 8; i++)

> +               girq->parents[i - 1] = platform_get_irq(pdev, i);


I would rather like to see i + 1 as a parameter which is much easier
to read and understand.

> +       for (i = 0; i < 8; i++) {


Also in both cases replace 8 by ARRAY_SIZE() or predefined constant.

> +               gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;

> +               irq_set_chip_data(gpio_irq, gc);

> +               irq_set_chip_and_handler(gpio_irq,

> +                                       girq->chip,

> +                                       handle_level_irq);

> +               irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);

> +       }


Okay, I see that this is in the original code. Consider them as
suggestions for additional changes.

And briefly looking into the rest of the code the recommendation is to
split this and perhaps other patches to smaller logical pieces.

Also, try to organize your series in groups each of them respectively
represents the following
1) fixes (can be backported, usually contain Fixes tag to the culprit commit);
2) preparatory refactoring patches / cleanups;
3) new features.


-- 
With Best Regards,
Andy Shevchenko
Linus Walleij Dec. 27, 2020, 1:55 p.m. UTC | #3
Paging Hartley who I think uses this chip.

On Thu, Dec 24, 2020 at 12:22 PM Nikita Shubin
<nikita.shubin@maquefel.me> wrote:

> I was lucky enough to became an owner of some splendid piece's of

> antiques called ts7250 based on the top of Cirrus Logic EP9302.

>

> I don't know what fate expects this hardware (it's not EOL it's just Not

> recommended for new designs) but i wanted to share fixes in ep93xx gpio area.

>

> It seems ep93xx is deadly broken at current state usage of AB gpiochips

> interrupts leads to deadlocks coused by irq_unmask/irq_mask recursions.

>

> Port F is not working at all:


Yeah when I converted this gpio driver I did not have access to a hardware
which made use of port F :(

I used the SIM.One board but they all died on me, then I acquired another
EP93xx board that I just didn't have time to test.

The long term plan is to convert these boards to use device tree and
multiplatform. Interested in the job? ;)

Thanks for fixing up the GPIO chip, let's get the patches in shape and
merge as fixes. Bartosz is handling the fixes right now, I'll try to review too!

Yours,
Linus Walleij
Linus Walleij Dec. 27, 2020, 2 p.m. UTC | #4
On Sat, Dec 26, 2020 at 6:34 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:

> I personally consider it quite nice to have support even for outdated

> hardware (reminds me about a recent LWN article about 32-bit

> architectures and a comment there how it could affect the environment

> if we drop them from being supported).

>

> So I fully support this series.


I had a lecture on the subject actually where EP93xx came up:
https://docs.google.com/presentation/d/1pv9MTCDpb0EgzrzicA9JF3pdUL6EcUmKhTavk5_hOHs

As seen it is considered a "fully developed product" and it would not
surprise me if Cirrus is taping out new EP93xx chips even.

This SoC is definitely on my shortlist of stuff we need to support.
(I wish Cirrus would provide some manpower but ...)

Yours,
Linus Walleij
Linus Walleij Dec. 27, 2020, 9:22 p.m. UTC | #5
On Thu, Dec 24, 2020 at 12:22 PM Nikita Shubin
<nikita.shubin@maquefel.me> wrote:

> Port F irq's should be statically mapped to EP93XX_GPIO_F_IRQ_BASE.

>

> So we need to specify girq->first otherwise:

>

> "If device tree is used, then first_irq will be 0 and

> irqs get mapped dynamically on the fly"

>

> And that's not the thing we want.

>

> Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>


Reviewed-by: Linus Walleij <linus.walleij@linaro.org>


We can only fix this properly once we convert the platform
to device tree. (Along with making the irqchip hierarchical.)

Yours,
Linus Walleij
Nikita Shubin Dec. 28, 2020, 3:05 p.m. UTC | #6
26.12.2020, 20:52, "Andy Shevchenko" <andy.shevchenko@gmail.com>:
> On Thu, Dec 24, 2020 at 1:23 PM Nikita Shubin <nikita.shubin@maquefel.me> wrote:

>>  Since gpiolib requires having separate irqchips for each gpiochip, we

>>  need to add some we definetly need a separate one for F port, and we

>

> definitely

>

>>  could combine gpiochip A and B into one - but this will break namespace

>>  and logick.

>>

>>  So despite 3 irqchips is a bit beefy we need a separate irqchip for each

>

> is a -> being a

>

>>  interrupt capable port.

>>

>>  - added separate irqchip for each iterrupt capable gpiochip

>

> interrupt

>

>>  - dropped ep93xx_gpio_port (it wasn't working correct for port F anyway)

>>  - moved irq registers into separate struct ep93xx_irq_chip, togather

>

> irq -> IRQ (everywhere)

>

> together

>

>>    with regs current state

>>  - reworked irq handle for ab gpiochips (through bit not tottaly sure this

>>    is a correct thing to do)

>

> ab -> AB ?

>

> In the parentheses something like "I'm not totally sure that this is a

> correct thing to do, though".

>

>>  - dropped has_irq and has_hierarchical_irq and added a simple index

>>    which we rely on when adding irq's to gpiochip's

>

> IRQs to GPIO chips

>

> (It would be nice if you can spell check and proofread commit

> messages and comments in the code.

>

> ...

>

>>  +struct ep93xx_irq_chip {

>>  + void __iomem *int_type1;

>>  + void __iomem *int_type2;

>>  + void __iomem *eoi;

>>  + void __iomem *en;

>>  + void __iomem *debounce;

>>  + void __iomem *status;

>

> This is a bit... overcomplicated.

> Can we rather use regmap API?

>

>>  + u8 gpio_int_unmasked;

>>  + u8 gpio_int_enabled;

>>  + u8 gpio_int_type1;

>>  + u8 gpio_int_type2;

>>  + u8 gpio_int_debounce;

>>  + struct irq_chip chip;

>>  +};

>

> ...

>

>>   /* Port ordering is: A B F */

>>  +static const char *irq_chip_names[3] = {"gpio-irq-a",

>>  + "gpio-irq-b",

>>  + "gpio-irq-f"};

>

> Can you use better pattern, ie.

> static const char * const foo[] = {

>   ...

> };

>

> (there are two things: splitting per lines and additional const)?

>

> ...

>

>>  + ab_parent_irq = platform_get_irq(pdev, 0);

>

> Error check, please?

> Also, if it's an optional resource, use platform_get_irq_optional().

>

>>  + err = devm_request_irq(dev, ab_parent_irq,

>>  + ep93xx_ab_irq_handler,

>>  + IRQF_SHARED, eic->chip.name, gc);

>

>>  +

>

> Redundant blank line.

>

>>  + if (err) {

>>  + dev_err(dev, "error requesting IRQ : %d\n", ab_parent_irq);

>>  + return err;

>>  + }

>

> ...

>

>>  + girq->num_parents = 1;

>>  + girq->parents = devm_kcalloc(dev, 1,

>>  + sizeof(*girq->parents),

>>  + GFP_KERNEL);

>

> Can be squeezed to less amount of LOCs. Also consider to use

> girq->num_parents as a parameter to devm_kcalloc().

>

>>  + if (!girq->parents)

>>  + return -ENOMEM;

>

> ...

>

>>  + girq->handler = handle_level_irq;

>

> Don't we want to mark them as bad by using handle_bad_irq() as default handler?

>

> ...

>

>>  + /*

>>  + * FIXME: convert this to use hierarchical IRQ support!

>>  + * this requires fixing the root irqchip to be hierarchial.

>

> hierarchical

>

>>  + */

>

> ...

>

>>  + girq->num_parents = 8;

>>  + girq->parents = devm_kcalloc(dev, 8,

>>  + sizeof(*girq->parents),

>>  + GFP_KERNEL);

>

> As per above.

>

>>  +

>

> Redundant blank line.

>

>>  + if (!girq->parents)

>>  + return -ENOMEM;

>

> ...

>

>>  + /* Pick resources 1..8 for these IRQs */

>>  + for (i = 1; i <= 8; i++)

>>  + girq->parents[i - 1] = platform_get_irq(pdev, i);

>

> I would rather like to see i + 1 as a parameter which is much easier

> to read and understand.

>

>>  + for (i = 0; i < 8; i++) {

>

> Also in both cases replace 8 by ARRAY_SIZE() or predefined constant.

>

>>  + gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;

>>  + irq_set_chip_data(gpio_irq, gc);

>>  + irq_set_chip_and_handler(gpio_irq,

>>  + girq->chip,

>>  + handle_level_irq);

>>  + irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);

>>  + }

>

> Okay, I see that this is in the original code. Consider them as

> suggestions for additional changes.

>

> And briefly looking into the rest of the code the recommendation is to

> split this and perhaps other patches to smaller logical pieces.

>

> Also, try to organize your series in groups each of them respectively

> represents the following

> 1) fixes (can be backported, usually contain Fixes tag to the culprit commit);

> 2) preparatory refactoring patches / cleanups;

> 3) new features.

>

> --

> With Best Regards,

> Andy Shevchenko


Thank you, Andy, i ll rework my RFC patch according to your advices and resubmit.
Nikita Shubin Dec. 28, 2020, 3:14 p.m. UTC | #7
27.12.2020, 16:55, "Linus Walleij" <linus.walleij@linaro.org>:
> Paging Hartley who I think uses this chip.

>

> On Thu, Dec 24, 2020 at 12:22 PM Nikita Shubin

> <nikita.shubin@maquefel.me> wrote:

>

>>  I was lucky enough to became an owner of some splendid piece's of

>>  antiques called ts7250 based on the top of Cirrus Logic EP9302.

>>

>>  I don't know what fate expects this hardware (it's not EOL it's just Not

>>  recommended for new designs) but i wanted to share fixes in ep93xx gpio area.

>>

>>  It seems ep93xx is deadly broken at current state usage of AB gpiochips

>>  interrupts leads to deadlocks coused by irq_unmask/irq_mask recursions.

>>

>>  Port F is not working at all:

>

> Yeah when I converted this gpio driver I did not have access to a hardware

> which made use of port F :(

>

> I used the SIM.One board but they all died on me, then I acquired another

> EP93xx board that I just didn't have time to test.

>

> The long term plan is to convert these boards to use device tree and

> multiplatform. Interested in the job? ;)

>


I had such a thought, but I was stopped by the delusion that no one is using this 
hardware anymore.

Not promising anything right now - but such a job sounds like a real fun.

> Thanks for fixing up the GPIO chip, let's get the patches in shape and

> merge as fixes. Bartosz is handling the fixes right now, I'll try to review too!


I am glad that this work is interesting not only for me. For this, I'm willing to put in 
a little effort to make the proposed changes look decent.

>

> Yours,

> Linus Walleij
Linus Walleij Dec. 28, 2020, 8:41 p.m. UTC | #8
On Mon, Dec 28, 2020 at 4:14 PM <nikita.shubin@maquefel.me> wrote:

> I had such a thought, but I was stopped by the delusion that no one is using this

> hardware anymore.


It is definately *used* a lot. It is dubious if it is used with the
latest kernel.
Hartley was/is using it on engraving machinery and using the latest
kernel, I think his setup is pretty large.

The number of deployed machines using EP93xx is likely large, but
more importantly, as with MOXA Art it is likely to be internet connected
and managing vital control systems.

In short: nobody may be upgrading these kernels, but the definately
*should* be upgrading them. For security reasons.

So as a community hat I have concluded it would be socially unacceptable
to delete it and not offer an upgrade path for these systems the
day they realize "oh s.... that is an internet connected pressure boiler".

So if possible it should be modernized.

> Not promising anything right now - but such a job sounds like a real fun.


I would be grateful.

Yours,
Linus Walleij