| From 93712205ce2f1fb047739494c0399a26ea4f0890 Mon Sep 17 00:00:00 2001 |
| From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> |
| Date: Thu, 12 Jun 2025 11:14:48 +0200 |
| Subject: pinctrl: qcom: msm: mark certain pins as invalid for interrupts |
| |
| From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> |
| |
| commit 93712205ce2f1fb047739494c0399a26ea4f0890 upstream. |
| |
| On some platforms, the UFS-reset pin has no interrupt logic in TLMM but |
| is nevertheless registered as a GPIO in the kernel. This enables the |
| user-space to trigger a BUG() in the pinctrl-msm driver by running, for |
| example: `gpiomon -c 0 113` on RB2. |
| |
| The exact culprit is requesting pins whose intr_detection_width setting |
| is not 1 or 2 for interrupts. This hits a BUG() in |
| msm_gpio_irq_set_type(). Potentially crashing the kernel due to an |
| invalid request from user-space is not optimal, so let's go through the |
| pins and mark those that would fail the check as invalid for the irq chip |
| as we should not even register them as available irqs. |
| |
| This function can be extended if we determine that there are more |
| corner-cases like this. |
| |
| Fixes: f365be092572 ("pinctrl: Add Qualcomm TLMM driver") |
| Cc: stable@vger.kernel.org |
| Reviewed-by: Bjorn Andersson <andersson@kernel.org> |
| Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> |
| Link: https://lore.kernel.org/20250612091448.41546-1-brgl@bgdev.pl |
| Signed-off-by: Linus Walleij <linus.walleij@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/pinctrl/qcom/pinctrl-msm.c | 20 ++++++++++++++++++++ |
| 1 file changed, 20 insertions(+) |
| |
| --- a/drivers/pinctrl/qcom/pinctrl-msm.c |
| +++ b/drivers/pinctrl/qcom/pinctrl-msm.c |
| @@ -1031,6 +1031,25 @@ static bool msm_gpio_needs_dual_edge_par |
| test_bit(d->hwirq, pctrl->skip_wake_irqs); |
| } |
| |
| +static void msm_gpio_irq_init_valid_mask(struct gpio_chip *gc, |
| + unsigned long *valid_mask, |
| + unsigned int ngpios) |
| +{ |
| + struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
| + const struct msm_pingroup *g; |
| + int i; |
| + |
| + bitmap_fill(valid_mask, ngpios); |
| + |
| + for (i = 0; i < ngpios; i++) { |
| + g = &pctrl->soc->groups[i]; |
| + |
| + if (g->intr_detection_width != 1 && |
| + g->intr_detection_width != 2) |
| + clear_bit(i, valid_mask); |
| + } |
| +} |
| + |
| static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
| { |
| struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| @@ -1392,6 +1411,7 @@ static int msm_gpio_init(struct msm_pinc |
| girq->default_type = IRQ_TYPE_NONE; |
| girq->handler = handle_bad_irq; |
| girq->parents[0] = pctrl->irq; |
| + girq->init_valid_mask = msm_gpio_irq_init_valid_mask; |
| |
| ret = gpiochip_add_data(&pctrl->chip, pctrl); |
| if (ret) { |