pinctrl: intel: Protect IO in few call backs by lock
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Fri, 12 Jun 2020 14:50:00 +0000 (17:50 +0300)
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Mon, 22 Jun 2020 07:58:52 +0000 (10:58 +0300)
Protect IO in intel_gpio_get_direction(), intel_gpio_community_irq_handler(),
intel_config_get_debounce() and intel_config_get_pull() by lock. Even for
simple readl() we better serialize IO to avoid potential problems.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/pinctrl/intel/pinctrl-intel.c

index d6ef012f2cc42ab9b37dd7f8d5c491a50bca4f6e..35c88fcb75a2469f8c134547531506a3fe903c30 100644 (file)
@@ -526,11 +526,15 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
 {
        const struct intel_community *community;
        void __iomem *padcfg1;
+       unsigned long flags;
        u32 value, term;
 
        community = intel_get_community(pctrl, pin);
        padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1);
+
+       raw_spin_lock_irqsave(&pctrl->lock, flags);
        value = readl(padcfg1);
+       raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
        term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT;
 
@@ -592,6 +596,7 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p
                                     enum pin_config_param param, u32 *arg)
 {
        void __iomem *padcfg2;
+       unsigned long flags;
        unsigned long v;
        u32 value2;
 
@@ -599,7 +604,9 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p
        if (!padcfg2)
                return -ENOTSUPP;
 
+       raw_spin_lock_irqsave(&pctrl->lock, flags);
        value2 = readl(padcfg2);
+       raw_spin_unlock_irqrestore(&pctrl->lock, flags);
        if (!(value2 & PADCFG2_DEBEN))
                return -EINVAL;
 
@@ -934,6 +941,7 @@ static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset,
 static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
        struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
+       unsigned long flags;
        void __iomem *reg;
        u32 padcfg0;
        int pin;
@@ -946,8 +954,9 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
        if (!reg)
                return -EINVAL;
 
+       raw_spin_lock_irqsave(&pctrl->lock, flags);
        padcfg0 = readl(reg);
-
+       raw_spin_unlock_irqrestore(&pctrl->lock, flags);
        if (padcfg0 & PADCFG0_PMODE_MASK)
                return -EINVAL;
 
@@ -1134,12 +1143,17 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
        for (gpp = 0; gpp < community->ngpps; gpp++) {
                const struct intel_padgroup *padgrp = &community->gpps[gpp];
                unsigned long pending, enabled, gpp_offset;
+               unsigned long flags;
+
+               raw_spin_lock_irqsave(&pctrl->lock, flags);
 
                pending = readl(community->regs + community->is_offset +
                                padgrp->reg_num * 4);
                enabled = readl(community->regs + community->ie_offset +
                                padgrp->reg_num * 4);
 
+               raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
                /* Only interrupts that are enabled */
                pending &= enabled;