The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Runyu Xiao" <runyu.xiao@seu.edu.cn>
Cc: linux-rt-devel@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] gpio: eic-sprd: use raw_spinlock_t in the irq startup path
Date: Wed, 17 Jun 2026 20:32:48 +0000	[thread overview]
Message-ID: <20260617203248.6EB581F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260617154035.1199948-3-runyu.xiao@seu.edu.cn>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Potential NULL pointer dereference in `sprd_eic_toggle_trigger` for unmapped or spurious hardware interrupts.
- [High] `sprd_eic_toggle_trigger` fails to properly toggle polarity for `SPRD_EIC_LATCH` because `sprd_eic_get` returns `-ENOTSUPP`.
- [High] Potential hardirq livelock and console spam due to `dev_warn` inside a retry loop in `sprd_eic_toggle_trigger`.
- [High] Unbinding one EIC instance breaks all other EIC instances because they share the same parent IRQ chained handler.
- [High] sprd_eic_toggle_trigger modifies interrupt masks unconditionally without holding desc->lock, creating a race condition with disable_irq().
--

commit 69e3dda6e9ba1a662342eec6f6b0ec04beeadc64
Author: Runyu Xiao <runyu.xiao@seu.edu.cn>

gpio: eic-sprd: use raw_spinlock_t in the irq startup path

sprd_eic_irq_unmask() enables the GPIO IRQ and then updates controller
state through sprd_eic_update(), which takes sprd_eic->lock with
spin_lock_irqsave(). The callback can be reached from irq_startup()
while setting up a requested IRQ, which is not sleepable on PREEMPT_RT.
This patch converts the lock to raw_spinlock_t to avoid sleeping.

> diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
> index 50fafeda8d7e2..3b7ebcf12fe7f 100644
> --- a/drivers/gpio/gpio-eic-sprd.c
> +++ b/drivers/gpio/gpio-eic-sprd.c
[ ... ]
> @@ -149,7 +149,7 @@ static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset,
>  	unsigned long flags;
>  	u32 tmp;
>  
> -	spin_lock_irqsave(&sprd_eic->lock, flags);
> +	raw_spin_lock_irqsave(&sprd_eic->lock, flags);
>  	tmp = readl_relaxed(base + reg);
>  
>  	if (val)
> @@ -158,7 +158,7 @@ static void sprd_eic_update(struct gpio_chip *chip, unsigned int offset,
>  		tmp &= ~BIT(SPRD_EIC_BIT(offset));
>  
>  	writel_relaxed(tmp, base + reg);
> -	spin_unlock_irqrestore(&sprd_eic->lock, flags);
> +	raw_spin_unlock_irqrestore(&sprd_eic->lock, flags);
>  }

[Severity: Critical]
This is a pre-existing issue, but can sprd_eic_handle_one_type() cause a
NULL pointer dereference for unmapped or spurious hardware interrupts?

If an interrupt is unmapped, irq_find_mapping() returns 0:

drivers/gpio/gpio-eic-sprd.c:sprd_eic_handle_one_type() {
    ...
    girq = irq_find_mapping(chip->irq.domain, offset);
    generic_handle_irq(girq);
    sprd_eic_toggle_trigger(chip, girq, offset);
}

The girq value 0 is then passed into sprd_eic_toggle_trigger():

drivers/gpio/gpio-eic-sprd.c:sprd_eic_toggle_trigger() {
    ...
    struct irq_data *data = irq_get_irq_data(irq);
    u32 trigger = irqd_get_trigger_type(data);
    ...
}

Calling irq_get_irq_data(0) returns NULL, which causes irqd_get_trigger_type()
to dereference NULL. Can this path be triggered by the bootloader leaving an
interrupt unmasked?

[Severity: High]
This is a pre-existing issue, but does sprd_eic_toggle_trigger() race with
disable_irq() since it alters the hardware mask without holding the
descriptor lock?

Looking at sprd_eic_toggle_trigger(), it unconditionally calls
sprd_eic_irq_unmask() after returning from an interrupt handler:

drivers/gpio/gpio-eic-sprd.c:sprd_eic_toggle_trigger() {
    ...
    sprd_eic_irq_mask(data);
    ...
    sprd_eic_irq_unmask(data);
}

If a concurrent thread calls disable_irq(), which holds desc->lock and masks
the hardware, sprd_eic_toggle_trigger() could execute immediately afterward and
unmask it again without checking irqd_irq_disabled(data). Can this leave the
system vulnerable to unhandled interrupt storms?

[Severity: High]
This is a pre-existing issue, but does sprd_eic_toggle_trigger() have a
potential hardirq livelock and console spam issue?

If the line state changes, the code logs a warning and retries endlessly:

drivers/gpio/gpio-eic-sprd.c:sprd_eic_toggle_trigger() {
    ...
retry:
    ...
    post_state = sprd_eic_get(chip, offset);
    if (state != post_state) {
        dev_warn(chip->parent, "EIC level was changed.\n");
        state = post_state;
        goto retry;
    }
}

Since this runs in the context of a cascaded interrupt handler, if the input
line oscillates rapidly, will the dev_warn() overhead inside a tight loop
cause lockups and watchdog panics without any retry bounds?

[Severity: High]
This is a pre-existing issue, but does SPRD_EIC_LATCH fail to toggle polarity?

In sprd_eic_toggle_trigger(), the state is used to set the latch polarity:

drivers/gpio/gpio-eic-sprd.c:sprd_eic_toggle_trigger() {
    ...
    state = sprd_eic_get(chip, offset);
    ...
    case SPRD_EIC_LATCH:
        if (state)
            sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
        else
            sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
        break;
}

However, sprd_eic_get() doesn't implement reading for SPRD_EIC_LATCH
and returns -ENOTSUPP. This negative value evaluates as true, meaning the
code will always execute the true branch and never toggle to 1. Will this
cause LATCH EICs to become permanently stuck?

[ ... ]
> @@ -628,7 +628,7 @@ static int sprd_eic_probe(struct platform_device *pdev)
>  	if (!sprd_eic)
>  		return -ENOMEM;
>  
> -	spin_lock_init(&sprd_eic->lock);
> +	raw_spin_lock_init(&sprd_eic->lock);
>  	sprd_eic->type = pdata->type;
>  
>  	sprd_eic->irq = platform_get_irq(pdev, 0);

[Severity: High]
This is a pre-existing issue, but will unbinding one EIC instance break all
other EIC instances?

During probe, each instance sets its parent handler to sprd_eic_irq_handler
on the shared parent IRQ:

drivers/gpio/gpio-eic-sprd.c:sprd_eic_probe() {
    ...
    irq->parent_handler = sprd_eic_irq_handler;
    irq->parent_handler_data = sprd_eic;
    irq->num_parents = 1;
    irq->parents = &sprd_eic->irq;
    ...
}

If any single EIC instance is unbound, gpiolib's cleanup routine calls
irq_set_chained_handler_and_data(parent, NULL, NULL), clearing the shared
parent handler entirely. Will this leave the remaining EIC instances
completely non-functional?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260617154035.1199948-1-runyu.xiao@seu.edu.cn?part=2

      reply	other threads:[~2026-06-17 20:32 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-17 15:40 [PATCH 0/2] gpio: use raw spinlocks in irq startup paths Runyu Xiao
2026-06-17 15:40 ` [PATCH 1/2] gpio: sch: use raw_spinlock_t in the irq startup path Runyu Xiao
2026-06-17 15:57   ` Andy Shevchenko
2026-06-17 20:21   ` sashiko-bot
2026-06-17 15:40 ` [PATCH 2/2] gpio: eic-sprd: " Runyu Xiao
2026-06-17 20:32   ` sashiko-bot [this message]

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=20260617203248.6EB581F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=runyu.xiao@seu.edu.cn \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox