* [PATCH 0/2] gpio: use raw spinlocks in irq startup paths @ 2026-06-17 15:40 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:40 ` [PATCH 2/2] gpio: eic-sprd: " Runyu Xiao 0 siblings, 2 replies; 6+ messages in thread From: Runyu Xiao @ 2026-06-17 15:40 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: Orson Zhai, Baolin Wang, Chunyan Zhang, Andy Shevchenko, Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt, Jan Kiszka, linux-gpio, linux-rt-devel, linux-kernel, jianhao.xu, runyu.xiao This 2-patch series fixes two GPIO irqchip paths where IRQ startup or unmask can update controller state under a regular spinlock. On PREEMPT_RT, that lock can sleep while irq_startup() is running in a non-sleepable context. Both issues were found by our static analysis tool and then manually reviewed against the current tree. The grounded PoCs kept the request_threaded_irq() -> __setup_irq() -> irq_startup() carriers and Lockdep reported "BUG: sleeping function called from invalid context" on the corresponding driver update helpers. Convert the affected register locks to raw_spinlock_t. The locked sections only serialize MMIO register access and irqchip state updates, so they should remain non-sleeping. The conversion does not move any sleepable operation under a raw lock; it preserves the existing short register-critical sections while making their non-sleeping requirement explicit for PREEMPT_RT. Runyu Xiao (2): gpio: sch: use raw_spinlock_t in the irq startup path gpio: eic-sprd: use raw_spinlock_t in the irq startup path drivers/gpio/gpio-eic-sprd.c | 8 ++++---- drivers/gpio/gpio-sch.c | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) -- 2.34.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] gpio: sch: use raw_spinlock_t in the irq startup path 2026-06-17 15:40 [PATCH 0/2] gpio: use raw spinlocks in irq startup paths Runyu Xiao @ 2026-06-17 15:40 ` 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 1 sibling, 2 replies; 6+ messages in thread From: Runyu Xiao @ 2026-06-17 15:40 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: Orson Zhai, Baolin Wang, Chunyan Zhang, Andy Shevchenko, Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt, Jan Kiszka, linux-gpio, linux-rt-devel, linux-kernel, jianhao.xu, runyu.xiao, stable sch_irq_unmask() enables the GPIO IRQ and then updates the controller state through sch_irq_mask_unmask(), which takes sch->lock with spin_lock_irqsave(). The callback can be reached from irq_startup() while setting up a requested IRQ. That path is not sleepable, but on PREEMPT_RT a regular spinlock_t becomes a sleeping lock. This issue was found by our static analysis tool and then manually reviewed against the current tree. The grounded PoC kept the request_threaded_irq() -> __setup_irq() -> irq_startup() -> sch_irq_unmask() -> sch_irq_mask_unmask() carrier and used the original spin_lock_irqsave(&sch->lock) edge. Lockdep reported: BUG: sleeping function called from invalid context hardirqs last disabled at ... __setup_irq.constprop.0 ... [vuln_msv] sch_rt_spin_lock_irqsave+0x1c/0x30 [vuln_msv] sch_irq_mask_unmask.constprop.0+0x31/0x70 [vuln_msv] __setup_irq.constprop.0+0xd/0x30 [vuln_msv] Convert the SCH controller lock to raw_spinlock_t. The same lock is also used by the GPIO direction and value callbacks, but those critical sections only update MMIO-backed GPIO registers and do not contain sleepable operations. Keeping this register lock non-sleeping is therefore appropriate for the irqchip callbacks and does not change the GPIO-side locking contract. Fixes: 7a81638485c1 ("gpio: sch: Add edge event support") Cc: stable@vger.kernel.org Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn> --- drivers/gpio/gpio-sch.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 966d16a6d515..5e361742a11a 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -39,7 +39,7 @@ struct sch_gpio { struct gpio_chip chip; void __iomem *regs; - spinlock_t lock; + raw_spinlock_t lock; unsigned short resume_base; /* GPE handling */ @@ -104,9 +104,9 @@ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num) struct sch_gpio *sch = gpiochip_get_data(gc); unsigned long flags; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GIO, 1); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); return 0; } @@ -122,9 +122,9 @@ static int sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val) struct sch_gpio *sch = gpiochip_get_data(gc); unsigned long flags; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GLV, val); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); return 0; } @@ -135,9 +135,9 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num, struct sch_gpio *sch = gpiochip_get_data(gc); unsigned long flags; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GIO, 0); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); /* * according to the datasheet, writing to the level register has no @@ -196,14 +196,14 @@ static int sch_irq_type(struct irq_data *d, unsigned int type) return -EINVAL; } - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GTPE, rising); sch_gpio_reg_set(sch, gpio_num, GTNE, falling); irq_set_handler_locked(d, handle_edge_irq); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); return 0; } @@ -215,9 +215,9 @@ static void sch_irq_ack(struct irq_data *d) irq_hw_number_t gpio_num = irqd_to_hwirq(d); unsigned long flags; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GTS, 1); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); } static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, int val) @@ -225,9 +225,9 @@ static void sch_irq_mask_unmask(struct gpio_chip *gc, irq_hw_number_t gpio_num, struct sch_gpio *sch = gpiochip_get_data(gc); unsigned long flags; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); sch_gpio_reg_set(sch, gpio_num, GGPE, val); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); } static void sch_irq_mask(struct irq_data *d) @@ -268,12 +268,12 @@ static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context) int offset; u32 ret; - spin_lock_irqsave(&sch->lock, flags); + raw_spin_lock_irqsave(&sch->lock, flags); core_status = ioread32(sch->regs + CORE_BANK_OFFSET + GTS); resume_status = ioread32(sch->regs + RESUME_BANK_OFFSET + GTS); - spin_unlock_irqrestore(&sch->lock, flags); + raw_spin_unlock_irqrestore(&sch->lock, flags); pending = (resume_status << sch->resume_base) | core_status; for_each_set_bit(offset, &pending, sch->chip.ngpio) @@ -343,7 +343,7 @@ static int sch_gpio_probe(struct platform_device *pdev) sch->regs = regs; - spin_lock_init(&sch->lock); + raw_spin_lock_init(&sch->lock); sch->chip = sch_gpio_chip; sch->chip.label = dev_name(dev); sch->chip.parent = dev; -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] gpio: sch: use raw_spinlock_t in the irq startup path 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 1 sibling, 0 replies; 6+ messages in thread From: Andy Shevchenko @ 2026-06-17 15:57 UTC (permalink / raw) To: Runyu Xiao Cc: Linus Walleij, Bartosz Golaszewski, Orson Zhai, Baolin Wang, Chunyan Zhang, Andy Shevchenko, Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt, Jan Kiszka, linux-gpio, linux-rt-devel, linux-kernel, jianhao.xu, stable On Wed, Jun 17, 2026 at 11:40:34PM +0800, Runyu Xiao wrote: > sch_irq_unmask() enables the GPIO IRQ and then updates the controller > state through sch_irq_mask_unmask(), which takes sch->lock with > spin_lock_irqsave(). The callback can be reached from irq_startup() > while setting up a requested IRQ. That path is not sleepable, but on > PREEMPT_RT a regular spinlock_t becomes a sleeping lock. > > This issue was found by our static analysis tool and then manually > reviewed against the current tree. > > The grounded PoC kept the request_threaded_irq() -> __setup_irq() -> > irq_startup() -> sch_irq_unmask() -> sch_irq_mask_unmask() carrier and > used the original spin_lock_irqsave(&sch->lock) edge. Lockdep reported: > > BUG: sleeping function called from invalid context > hardirqs last disabled at ... __setup_irq.constprop.0 ... [vuln_msv] > sch_rt_spin_lock_irqsave+0x1c/0x30 [vuln_msv] > sch_irq_mask_unmask.constprop.0+0x31/0x70 [vuln_msv] > __setup_irq.constprop.0+0xd/0x30 [vuln_msv] > > Convert the SCH controller lock to raw_spinlock_t. The same lock is > also used by the GPIO direction and value callbacks, but those critical > sections only update MMIO-backed GPIO registers and do not contain > sleepable operations. Keeping this register lock non-sleeping is > therefore appropriate for the irqchip callbacks and does not change the > GPIO-side locking contract. Okay, no objection. Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com> Bart, you can take it to your branch directly in case it's not too late for getting into v7.2-rc1, otherwise I can take via my branch and then PR somewhere near -rc2. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] gpio: sch: use raw_spinlock_t in the irq startup path 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 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-06-17 20:21 UTC (permalink / raw) To: Runyu Xiao; +Cc: linux-kernel, linux-rt-devel Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Read-Modify-Write cycle on the Write-1-to-Clear (W1C) status register causes lost interrupts. -- commit 088444fdf19ac3925d66a59ae9e74b003c72c066 Author: Runyu Xiao <runyu.xiao@seu.edu.cn> gpio: sch: use raw_spinlock_t in the irq startup path This patch converts the SCH controller lock from spinlock_t to raw_spinlock_t to prevent a sleep-in-invalid-context bug on PREEMPT_RT. The lock is acquired in the non-sleepable IRQ startup path. > diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c > index 966d16a6d5157..5e361742a11ad 100644 > --- a/drivers/gpio/gpio-sch.c > +++ b/drivers/gpio/gpio-sch.c [ ... ] > @@ -215,9 +215,9 @@ static void sch_irq_ack(struct irq_data *d) > irq_hw_number_t gpio_num = irqd_to_hwirq(d); > unsigned long flags; > > - spin_lock_irqsave(&sch->lock, flags); > + raw_spin_lock_irqsave(&sch->lock, flags); > sch_gpio_reg_set(sch, gpio_num, GTS, 1); [Severity: High] This isn't a bug introduced by this patch, but does this cause lost interrupts due to a read-modify-write on a write-1-to-clear register? sch_irq_ack() acknowledges a GPIO interrupt by calling sch_gpio_reg_set() for the GTS register. Looking at sch_gpio_reg_set(): drivers/gpio/gpio-sch.c:sch_gpio_reg_set() { ... reg_val = ioread8(sch->regs + offset); if (val) reg_val |= BIT(bit); else reg_val &= ~BIT(bit); iowrite8(reg_val, sch->regs + offset); } And sch_gpio_gpe_handler() demonstrates that GTS returns the status of pending interrupts when read: drivers/gpio/gpio-sch.c:sch_gpio_gpe_handler() { ... core_status = ioread32(sch->regs + CORE_BANK_OFFSET + GTS); ... } Because GTS is a write-1-to-clear status register, the ioread8() in sch_gpio_reg_set() returns 1s for all currently pending interrupts. When those 1s are written back via iowrite8(), won't it inadvertently clear all pending interrupts in that bank, instead of just the specific gpio_num being acknowledged? > - spin_unlock_irqrestore(&sch->lock, flags); > + raw_spin_unlock_irqrestore(&sch->lock, flags); > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260617154035.1199948-1-runyu.xiao@seu.edu.cn?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] gpio: eic-sprd: use raw_spinlock_t in the irq startup path 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:40 ` Runyu Xiao 2026-06-17 20:32 ` sashiko-bot 1 sibling, 1 reply; 6+ messages in thread From: Runyu Xiao @ 2026-06-17 15:40 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: Orson Zhai, Baolin Wang, Chunyan Zhang, Andy Shevchenko, Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt, Jan Kiszka, linux-gpio, linux-rt-devel, linux-kernel, jianhao.xu, runyu.xiao, stable 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. That path is not sleepable, but on PREEMPT_RT a regular spinlock_t becomes a sleeping lock. This issue was found by our static analysis tool and then manually reviewed against the current tree. The grounded PoC kept the request_threaded_irq() -> __setup_irq() -> irq_startup() -> sprd_eic_irq_unmask() -> sprd_eic_update() carrier and used the original spin_lock_irqsave(&sprd_eic->lock) edge. Lockdep reported: BUG: sleeping function called from invalid context hardirqs last disabled at ... __setup_irq.constprop.0 ... [vuln_msv] sprd_rt_spin_lock_irqsave+0x1c/0x30 [vuln_msv] sprd_eic_update.constprop.0+0x48/0x90 [vuln_msv] sprd_eic_irq_unmask.constprop.0+0x35/0x50 [vuln_msv] __setup_irq.constprop.0+0xd/0x30 [vuln_msv] Convert the Spreadtrum EIC controller lock to raw_spinlock_t. The locked section only serializes MMIO register updates and does not contain sleepable operations, so keeping it non-sleeping is appropriate for the irqchip callbacks. Fixes: 25518e024e3a ("gpio: Add Spreadtrum EIC driver support") Cc: stable@vger.kernel.org Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn> --- drivers/gpio/gpio-eic-sprd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 50fafeda8d7e..3b7ebcf12fe7 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -95,7 +95,7 @@ struct sprd_eic { struct notifier_block irq_nb; void __iomem *base[SPRD_EIC_MAX_BANK]; enum sprd_eic_type type; - spinlock_t lock; + raw_spinlock_t lock; int irq; }; @@ -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); } static int sprd_eic_read(struct gpio_chip *chip, unsigned int offset, u16 reg) @@ -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); -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] gpio: eic-sprd: use raw_spinlock_t in the irq startup path 2026-06-17 15:40 ` [PATCH 2/2] gpio: eic-sprd: " Runyu Xiao @ 2026-06-17 20:32 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-06-17 20:32 UTC (permalink / raw) To: Runyu Xiao; +Cc: linux-rt-devel, linux-kernel 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 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-17 20:32 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 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.