From: lakabd <lakabd.work@gmail.com>
To: mark.tomlinson@alliedtelesis.co.nz
Cc: andy.shevchenko@gmail.com, brgl@bgdev.pl,
linus.walleij@linaro.org, linux-gpio@vger.kernel.org,
linux-kernel@vger.kernel.org,
Abderrahim LAKBIR <abderrahim.lakbir@actia.fr>
Subject: Re: [PATCH] gpio: pca953x: Improve interrupt support
Date: Mon, 13 Jan 2025 23:02:22 +0100 [thread overview]
Message-ID: <20250113220221.13545-1-koute102030@gmail.com> (raw)
In-Reply-To: <e407b7b58c966ee35e023618ad428a21f979e761.camel@alliedtelesis.co.nz>
Hi All,
I'm encountering exactly the same issue, and there is indeed a problem in the process of pca953x_irq_pending().
Mark has already explained the issue, but as apparently the discussion stopped, I've tried below to add some details to help better understand the issue. I've also a solution to propose.
The issue:
In the current implementation, when an IRQ occurs, the function pca953x_irq_pending() is called to fill the pending list of IRQs. This function will accomplish the following (for PCA_PCAL):
1- read the interrupt status register
2- read the latched inputs to clear the interrupt
3- apply filter for rising/falling edge selection on the input value
4- filter any bits that aren't related to the IRQ by applying a bitmap_and operation between: value calculated in step 3 and the value of ISR in step 1
5- return True with the pending bitmap if not empty
The problem here is that any interrupt that occurs between operation 1 and 2 will be lost even if latching is enabled !
Example:
* Interrupt occurs in pin 0 of port 0
1- Interrupt status register read (port0) = 0x10
** Interrupt occurs in pin 4 of port 0
2- input register read (port0) = 0x11 --> resets Interruptline
4- bitmap_and operation will remove the newly changed bit:0x11 & 0x10 = 0x10 and the returned pending bitmap will have only the pin0 interrupt !
The latching helps with very short interrupts to not be lost, but in the situation above it is not relevant.
Proposed solution:
In the 4th step apply bitmap_and between the filtered latched input and the bitmap of the unmasked interrupts. This will ensure the same outcome by letting only pins for which the IRQ is unmasked to pass but will not remove newly triggered interrupts.
This new unmasked interrupts bitmap can be filled in pca953x_irq_bus_sync_unlock() when an irq mask is getting set.
Also, by applying this, we can discard completely the read of the interrupt status register in step 1. Hence, the only I2C read that will be sent is the read of the Input register which minimizes the time to interrupt forwarding.
Signed-off-by: Abderrahim LAKBIR <abderrahim.lakbir@actia.fr>
--
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 272febc..886a287 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -215,6 +215,7 @@ struct pca953x_chip {
DECLARE_BITMAP(irq_stat, MAX_LINE);
DECLARE_BITMAP(irq_trig_raise, MAX_LINE);
DECLARE_BITMAP(irq_trig_fall, MAX_LINE);
+ DECLARE_BITMAP(unmasked_interrupts, MAX_LINE);
#endif
atomic_t wakeup_path;
@@ -763,6 +764,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
/* Enable latch on interrupt-enabled inputs */
pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask);
+ /* Store irq_mask for later use when checking pending IRQs */
+ bitmap_or(chip->unmasked_interrupts, chip->unmasked_interrupts, chip->irq_mask, gc->ngpio);
+
bitmap_complement(irq_mask, chip->irq_mask, gc->ngpio);
/* Unmask enabled interrupts */
@@ -842,11 +846,6 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin
int ret;
if (chip->driver_data & PCA_PCAL) {
- /* Read the current interrupt status from the device */
- ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger);
- if (ret)
- return false;
-
/* Check latched inputs and clear interrupt status */
ret = pca953x_read_regs(chip, chip->regs->input, cur_stat);
if (ret)
@@ -855,7 +854,7 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin
/* Apply filter for rising/falling edge selection */
bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise, cur_stat, gc->ngpio);
- bitmap_and(pending, new_stat, trigger, gc->ngpio);
+ bitmap_and(pending, new_stat, chip->unmasked_interrupts, gc->ngpio);
return !bitmap_empty(pending, gc->ngpio);
}
next prev parent reply other threads:[~2025-01-13 22:03 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-06 3:31 [PATCH] gpio: pca953x: Improve interrupt support Mark Tomlinson
2024-06-08 9:44 ` Andy Shevchenko
2024-06-09 22:13 ` Mark Tomlinson
2025-01-13 22:02 ` lakabd [this message]
2025-01-14 9:36 ` Andy Shevchenko
2025-01-14 15:44 ` work work
2025-01-21 10:11 ` lakabd
2025-01-27 7:47 ` Andy Shevchenko
2025-01-27 10:11 ` Andy Shevchenko
2025-01-27 16:45 ` lakabd
2025-01-27 18:58 ` Andy Shevchenko
2025-01-28 3:43 ` Mark Tomlinson
2025-01-27 10:12 ` Andy Shevchenko
2025-02-04 20:27 ` Bartosz Golaszewski
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=20250113220221.13545-1-koute102030@gmail.com \
--to=lakabd.work@gmail.com \
--cc=abderrahim.lakbir@actia.fr \
--cc=andy.shevchenko@gmail.com \
--cc=brgl@bgdev.pl \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.tomlinson@alliedtelesis.co.nz \
/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