Skip to content

Commit a973531

Browse files
stephan-ghjfvogel
authored andcommitted
pinctrl: qcom: Clear latched interrupt status when changing IRQ type
commit e225128c3f8be879e7d4eb71a25949e188b420ae upstream. When submitting the TLMM test driver, Bjorn reported that some of the test cases are failing for GPIOs that not are backed by PDC (i.e. "non-wakeup" GPIOs that are handled directly in pinctrl-msm). Basically, lingering latched interrupt state is still being delivered at IRQ request time, e.g.: ok 1 tlmm_test_silent_rising tlmm_test_silent_falling: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:178 Expected atomic_read(&priv->intr_count) == 0, but atomic_read(&priv->intr_count) == 1 (0x1) not ok 2 tlmm_test_silent_falling tlmm_test_silent_low: ASSERTION FAILED at drivers/pinctrl/qcom/tlmm-test.c:178 Expected atomic_read(&priv->intr_count) == 0, but atomic_read(&priv->intr_count) == 1 (0x1) not ok 3 tlmm_test_silent_low ok 4 tlmm_test_silent_high Whether to report interrupts that came in while the IRQ was unclaimed doesn't seem to be well-defined in the Linux IRQ API. However, looking closer at these specific cases, we're actually reporting events that do not match the interrupt type requested by the driver: 1. After "ok 1 tlmm_test_silent_rising", the GPIO is in low state and configured for IRQF_TRIGGER_RISING. 2. (a) In preparation for "tlmm_test_silent_falling", the GPIO is switched to high state. The rising interrupt gets latched. (b) The GPIO is re-configured for IRQF_TRIGGER_FALLING, but the latched interrupt isn't cleared. (c) The IRQ handler is called for the latched interrupt, but there wasn't any falling edge. 3. (a) For "tlmm_test_silent_low", the GPIO remains in high state. (b) The GPIO is re-configured for IRQF_TRIGGER_LOW. This seems to result in a phantom interrupt that gets latched. (c) The IRQ handler is called for the latched interrupt, but the GPIO isn't in low state. 4. (a) For "tlmm_test_silent_high", the GPIO is switched to low state. (b) This doesn't result in a latched interrupt, because RAW_STATUS_EN was cleared when masking the level-triggered interrupt. Fix this by clearing the interrupt state whenever making any changes to the interrupt configuration. This includes previously disabled interrupts, but also any changes to interrupt polarity or detection type. With this change, all 16 test cases are now passing for the non-wakeup GPIOs in the TLMM. Cc: [email protected] Fixes: cf9d052 ("pinctrl: qcom: Don't clear pending interrupts when enabling") Reported-by: Bjorn Andersson <[email protected]> Closes: https://lore.kernel.org/r/[email protected]/ Signed-off-by: Stephan Gerhold <[email protected]> Tested-by: Bjorn Andersson <[email protected]> Reviewed-by: Bjorn Andersson <[email protected]> Link: https://lore.kernel.org/[email protected] Signed-off-by: Linus Walleij <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit c1368383cd37aa1dddc209c2c8734019d486e50c) Signed-off-by: Jack Vogel <[email protected]>
1 parent 11ee51a commit a973531

File tree

1 file changed

+6
-6
lines changed

1 file changed

+6
-6
lines changed

drivers/pinctrl/qcom/pinctrl-msm.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
10441044
const struct msm_pingroup *g;
10451045
u32 intr_target_mask = GENMASK(2, 0);
10461046
unsigned long flags;
1047-
bool was_enabled;
1048-
u32 val;
1047+
u32 val, oldval;
10491048

10501049
if (msm_gpio_needs_dual_edge_parent_workaround(d, type)) {
10511050
set_bit(d->hwirq, pctrl->dual_edge_irqs);
@@ -1107,8 +1106,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
11071106
* internal circuitry of TLMM, toggling the RAW_STATUS
11081107
* could cause the INTR_STATUS to be set for EDGE interrupts.
11091108
*/
1110-
val = msm_readl_intr_cfg(pctrl, g);
1111-
was_enabled = val & BIT(g->intr_raw_status_bit);
1109+
val = oldval = msm_readl_intr_cfg(pctrl, g);
11121110
val |= BIT(g->intr_raw_status_bit);
11131111
if (g->intr_detection_width == 2) {
11141112
val &= ~(3 << g->intr_detection_bit);
@@ -1161,9 +1159,11 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
11611159
/*
11621160
* The first time we set RAW_STATUS_EN it could trigger an interrupt.
11631161
* Clear the interrupt. This is safe because we have
1164-
* IRQCHIP_SET_TYPE_MASKED.
1162+
* IRQCHIP_SET_TYPE_MASKED. When changing the interrupt type, we could
1163+
* also still have a non-matching interrupt latched, so clear whenever
1164+
* making changes to the interrupt configuration.
11651165
*/
1166-
if (!was_enabled)
1166+
if (val != oldval)
11671167
msm_ack_intr_status(pctrl, g);
11681168

11691169
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))

0 commit comments

Comments
 (0)