]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Nov 2015 17:41:13 +0000 (09:41 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Nov 2015 17:41:13 +0000 (09:41 -0800)
added patches:
pinctrl-baytrail-serialize-all-register-access.patch
pinctrl-baytrail-use-raw_spinlock-for-locking.patch

queue-4.2/pinctrl-baytrail-serialize-all-register-access.patch [new file with mode: 0644]
queue-4.2/pinctrl-baytrail-use-raw_spinlock-for-locking.patch [new file with mode: 0644]
queue-4.2/series

diff --git a/queue-4.2/pinctrl-baytrail-serialize-all-register-access.patch b/queue-4.2/pinctrl-baytrail-serialize-all-register-access.patch
new file mode 100644 (file)
index 0000000..ee5d431
--- /dev/null
@@ -0,0 +1,87 @@
+From 39ce8150a079e3ae6ed9abf26d7918a558ef7c19 Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Tue, 4 Aug 2015 15:03:14 +0300
+Subject: pinctrl: baytrail: Serialize all register access
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit 39ce8150a079e3ae6ed9abf26d7918a558ef7c19 upstream.
+
+There is a hardware issue in Intel Baytrail where concurrent GPIO register
+access might result reads of 0xffffffff and writes might get dropped
+completely.
+
+Prevent this from happening by taking the serializing lock in all places
+where it is possible that more than one thread might be accessing the
+hardware concurrently.
+
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lucas De Marchi <lucas.de.marchi@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c |   21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -201,6 +201,9 @@ static int byt_gpio_request(struct gpio_
+       struct byt_gpio *vg = to_byt_gpio(chip);
+       void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
+       u32 value, gpio_mux;
++      unsigned long flags;
++
++      spin_lock_irqsave(&vg->lock, flags);
+       /*
+        * In most cases, func pin mux 000 means GPIO function.
+@@ -214,18 +217,16 @@ static int byt_gpio_request(struct gpio_
+       value = readl(reg) & BYT_PIN_MUX;
+       gpio_mux = byt_get_gpio_mux(vg, offset);
+       if (WARN_ON(gpio_mux != value)) {
+-              unsigned long flags;
+-
+-              spin_lock_irqsave(&vg->lock, flags);
+               value = readl(reg) & ~BYT_PIN_MUX;
+               value |= gpio_mux;
+               writel(value, reg);
+-              spin_unlock_irqrestore(&vg->lock, flags);
+               dev_warn(&vg->pdev->dev,
+                        "pin %u forcibly re-configured as GPIO\n", offset);
+       }
++      spin_unlock_irqrestore(&vg->lock, flags);
++
+       pm_runtime_get(&vg->pdev->dev);
+       return 0;
+@@ -277,7 +278,15 @@ static int byt_irq_type(struct irq_data
+ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+       void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
+-      return readl(reg) & BYT_LEVEL;
++      struct byt_gpio *vg = to_byt_gpio(chip);
++      unsigned long flags;
++      u32 val;
++
++      spin_lock_irqsave(&vg->lock, flags);
++      val = readl(reg);
++      spin_unlock_irqrestore(&vg->lock, flags);
++
++      return val & BYT_LEVEL;
+ }
+ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+@@ -450,8 +459,10 @@ static void byt_irq_ack(struct irq_data
+       unsigned offset = irqd_to_hwirq(d);
+       void __iomem *reg;
++      spin_lock(&vg->lock);
+       reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
+       writel(BIT(offset % 32), reg);
++      spin_unlock(&vg->lock);
+ }
+ static void byt_irq_unmask(struct irq_data *d)
diff --git a/queue-4.2/pinctrl-baytrail-use-raw_spinlock-for-locking.patch b/queue-4.2/pinctrl-baytrail-use-raw_spinlock-for-locking.patch
new file mode 100644 (file)
index 0000000..2c989d6
--- /dev/null
@@ -0,0 +1,249 @@
+From 78e1c896932df5b8bcdff7bf5417d8e72a4d0d6b Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Mon, 17 Aug 2015 16:03:17 +0300
+Subject: pinctrl: baytrail: Use raw_spinlock for locking
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit 78e1c896932df5b8bcdff7bf5417d8e72a4d0d6b upstream.
+
+The Intel Baytrail pinctrl driver implements irqchip callbacks which are
+called with desc->lock raw_spinlock held. In mainline this is fine because
+spinlock resolves to raw_spinlock. However, running the same code in -rt we
+get:
+
+ BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917
+ in_atomic(): 1, irqs_disabled(): 1, pid: 0, name: swapper/0
+ Preemption disabled at:[<ffffffff81092e9f>] cpu_startup_entry+0x17f/0x480
+
+ CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.1.5-rt5 #13
+  ...
+ Call Trace:
+  <IRQ>  [<ffffffff816283c6>] dump_stack+0x4a/0x61
+  [<ffffffff81077e17>] ___might_sleep+0xe7/0x170
+  [<ffffffff8162d6cf>] rt_spin_lock+0x1f/0x50
+  [<ffffffff812e3b88>] byt_gpio_clear_triggering+0x38/0x60
+  [<ffffffff812e3bc1>] byt_irq_mask+0x11/0x20
+  [<ffffffff810a7013>] handle_level_irq+0x83/0x150
+  [<ffffffff810a3457>] generic_handle_irq+0x27/0x40
+  [<ffffffff812e3a5f>] byt_gpio_irq_handler+0x7f/0xc0
+  [<ffffffff810050aa>] handle_irq+0xaa/0x190
+  ...
+
+This is because in -rt spinlocks are preemptible so taking the driver
+private spinlock in irqchip callbacks causes might_sleep() to trigger.
+
+In order to keep -rt happy but at the same time make sure that register
+accesses get serialized, convert the driver to use raw_spinlock instead.
+
+Also shorten the critical section a bit in few places.
+
+Suggested-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Cc: Lucas De Marchi <lucas.de.marchi@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c |   50 +++++++++++++++----------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -146,7 +146,7 @@ struct byt_gpio_pin_context {
+ struct byt_gpio {
+       struct gpio_chip                chip;
+       struct platform_device          *pdev;
+-      spinlock_t                      lock;
++      raw_spinlock_t                  lock;
+       void __iomem                    *reg_base;
+       struct pinctrl_gpio_range       *range;
+       struct byt_gpio_pin_context     *saved_context;
+@@ -174,11 +174,11 @@ static void byt_gpio_clear_triggering(st
+       unsigned long flags;
+       u32 value;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg);
+       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+       writel(value, reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+ }
+ static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
+@@ -203,7 +203,7 @@ static int byt_gpio_request(struct gpio_
+       u32 value, gpio_mux;
+       unsigned long flags;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       /*
+        * In most cases, func pin mux 000 means GPIO function.
+@@ -225,7 +225,7 @@ static int byt_gpio_request(struct gpio_
+                        "pin %u forcibly re-configured as GPIO\n", offset);
+       }
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+       pm_runtime_get(&vg->pdev->dev);
+@@ -251,7 +251,7 @@ static int byt_irq_type(struct irq_data
+       if (offset >= vg->chip.ngpio)
+               return -EINVAL;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg);
+       WARN(value & BYT_DIRECT_IRQ_EN,
+@@ -270,7 +270,7 @@ static int byt_irq_type(struct irq_data
+       else if (type & IRQ_TYPE_LEVEL_MASK)
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+       return 0;
+ }
+@@ -282,9 +282,9 @@ static int byt_gpio_get(struct gpio_chip
+       unsigned long flags;
+       u32 val;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       val = readl(reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+       return val & BYT_LEVEL;
+ }
+@@ -296,7 +296,7 @@ static void byt_gpio_set(struct gpio_chi
+       unsigned long flags;
+       u32 old_val;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       old_val = readl(reg);
+@@ -305,7 +305,7 @@ static void byt_gpio_set(struct gpio_chi
+       else
+               writel(old_val & ~BYT_LEVEL, reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+ }
+ static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+@@ -315,13 +315,13 @@ static int byt_gpio_direction_input(stru
+       unsigned long flags;
+       u32 value;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg) | BYT_DIR_MASK;
+       value &= ~BYT_INPUT_EN;         /* active low */
+       writel(value, reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+       return 0;
+ }
+@@ -335,7 +335,7 @@ static int byt_gpio_direction_output(str
+       unsigned long flags;
+       u32 reg_val;
+-      spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       /*
+        * Before making any direction modifications, do a check if gpio
+@@ -354,7 +354,7 @@ static int byt_gpio_direction_output(str
+       else
+               writel(reg_val & ~BYT_LEVEL, reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+       return 0;
+ }
+@@ -363,18 +363,19 @@ static void byt_gpio_dbg_show(struct seq
+ {
+       struct byt_gpio *vg = to_byt_gpio(chip);
+       int i;
+-      unsigned long flags;
+       u32 conf0, val, offs;
+-      spin_lock_irqsave(&vg->lock, flags);
+-
+       for (i = 0; i < vg->chip.ngpio; i++) {
+               const char *pull_str = NULL;
+               const char *pull = NULL;
++              unsigned long flags;
+               const char *label;
+               offs = vg->range->pins[i] * 16;
++
++              raw_spin_lock_irqsave(&vg->lock, flags);
+               conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
+               val = readl(vg->reg_base + offs + BYT_VAL_REG);
++              raw_spin_unlock_irqrestore(&vg->lock, flags);
+               label = gpiochip_is_requested(chip, i);
+               if (!label)
+@@ -427,7 +428,6 @@ static void byt_gpio_dbg_show(struct seq
+               seq_puts(s, "\n");
+       }
+-      spin_unlock_irqrestore(&vg->lock, flags);
+ }
+ static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+@@ -459,10 +459,10 @@ static void byt_irq_ack(struct irq_data
+       unsigned offset = irqd_to_hwirq(d);
+       void __iomem *reg;
+-      spin_lock(&vg->lock);
++      raw_spin_lock(&vg->lock);
+       reg = byt_gpio_reg(&vg->chip, offset, BYT_INT_STAT_REG);
+       writel(BIT(offset % 32), reg);
+-      spin_unlock(&vg->lock);
++      raw_spin_unlock(&vg->lock);
+ }
+ static void byt_irq_unmask(struct irq_data *d)
+@@ -474,9 +474,9 @@ static void byt_irq_unmask(struct irq_da
+       void __iomem *reg;
+       u32 value;
+-      spin_lock_irqsave(&vg->lock, flags);
+-
+       reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
++
++      raw_spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg);
+       switch (irqd_get_trigger_type(d)) {
+@@ -497,7 +497,7 @@ static void byt_irq_unmask(struct irq_da
+       writel(value, reg);
+-      spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&vg->lock, flags);
+ }
+ static void byt_irq_mask(struct irq_data *d)
+@@ -589,7 +589,7 @@ static int byt_gpio_probe(struct platfor
+       if (IS_ERR(vg->reg_base))
+               return PTR_ERR(vg->reg_base);
+-      spin_lock_init(&vg->lock);
++      raw_spin_lock_init(&vg->lock);
+       gc = &vg->chip;
+       gc->label = dev_name(&pdev->dev);
index 0cad332044cba5251a94ba4096fa8397426b6e9c..b5a2fa3b4803eb74f507a48ffbeada8d968214c7 100644 (file)
@@ -105,3 +105,5 @@ arm64-compat-fix-stxr-failure-case-in-swp-emulation.patch
 nvme-fix-memory-leak-on-retried-commands.patch
 drm-vmwgfx-fix-up-user_dmabuf-refcounting.patch
 thp-use-is_zero_pfn-only-after-pte_present-check.patch
+pinctrl-baytrail-serialize-all-register-access.patch
+pinctrl-baytrail-use-raw_spinlock-for-locking.patch