mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
pinctrl: mcp23s08: Get rid of spurious level interrupts
irq_mask()/irq_unmask() are not called for nested interrupts. So level interrupts are never masked, chip's interrupt output is not cleared on INTCAP or GPIO read, the irq handler is uselessly called again. Nested irq handler is not called again, because interrupt reason is cleared by its first call. /proc/interrupts shows that number of chip's irqs is greater than number of nested irqs. This patch adds masking and unmasking level interrupts inside irq handler. Signed-off-by: Dmitry Mastykin <mastichi@gmail.com> Link: https://lore.kernel.org/20250122120504.1279790-1-mastichi@gmail.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
d6c6fd77e5
commit
7b0671b97f
|
|
@ -382,6 +382,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
|||
{
|
||||
struct mcp23s08 *mcp = data;
|
||||
int intcap, intcon, intf, i, gpio, gpio_orig, intcap_mask, defval, gpinten;
|
||||
bool need_unmask = false;
|
||||
unsigned long int enabled_interrupts;
|
||||
unsigned int child_irq;
|
||||
bool intf_set, intcap_changed, gpio_bit_changed,
|
||||
|
|
@ -396,9 +397,6 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCAP, &intcap))
|
||||
goto unlock;
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCON, &intcon))
|
||||
goto unlock;
|
||||
|
||||
|
|
@ -408,6 +406,16 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
|||
if (mcp_read(mcp, MCP_DEFVAL, &defval))
|
||||
goto unlock;
|
||||
|
||||
/* Mask level interrupts to avoid their immediate reactivation after clearing */
|
||||
if (intcon) {
|
||||
need_unmask = true;
|
||||
if (mcp_write(mcp, MCP_GPINTEN, gpinten & ~intcon))
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCAP, &intcap))
|
||||
goto unlock;
|
||||
|
||||
/* This clears the interrupt(configurable on S18) */
|
||||
if (mcp_read(mcp, MCP_GPIO, &gpio))
|
||||
goto unlock;
|
||||
|
|
@ -470,9 +478,18 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
if (need_unmask) {
|
||||
mutex_lock(&mcp->lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
unlock:
|
||||
if (need_unmask)
|
||||
if (mcp_write(mcp, MCP_GPINTEN, gpinten))
|
||||
dev_err(mcp->chip.parent, "can't unmask GPINTEN\n");
|
||||
|
||||
mutex_unlock(&mcp->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user