]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Thu, 2 Jan 2020 02:23:51 +0000 (21:23 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 2 Jan 2020 02:23:51 +0000 (21:23 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/pinctrl-baytrail-really-serialize-all-register-acces.patch [new file with mode: 0644]
queue-4.19/serial-sprd-use-readable-macros-instead-of-magic-num.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/spi-fsl-don-t-map-irq-during-probe.patch [new file with mode: 0644]
queue-4.19/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch [new file with mode: 0644]

diff --git a/queue-4.19/pinctrl-baytrail-really-serialize-all-register-acces.patch b/queue-4.19/pinctrl-baytrail-really-serialize-all-register-acces.patch
new file mode 100644 (file)
index 0000000..a802e9d
--- /dev/null
@@ -0,0 +1,392 @@
+From f4c1e7929241424c54d103804ffa1483d687e1bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Nov 2019 16:46:41 +0100
+Subject: pinctrl: baytrail: Really serialize all register accesses
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 40ecab551232972a39cdd8b6f17ede54a3fdb296 ]
+
+Commit 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
+added a spinlock around all register accesses because:
+
+"There is a hardware issue in Intel Baytrail where concurrent GPIO register
+ access might result reads of 0xffffffff and writes might get dropped
+ completely."
+
+Testing has shown that this does not catch all cases, there are still
+2 problems remaining
+
+1) The original fix uses a spinlock per byt_gpio device / struct,
+additional testing has shown that this is not sufficient concurent
+accesses to 2 different GPIO banks also suffer from the same problem.
+
+This commit fixes this by moving to a single global lock.
+
+2) The original fix did not add a lock around the register accesses in
+the suspend/resume handling.
+
+Since pinctrl-baytrail.c is using normal suspend/resume handlers,
+interrupts are still enabled during suspend/resume handling. Nothing
+should be using the GPIOs when they are being taken down, _but_ the
+GPIOs themselves may still cause interrupts, which are likely to
+use (read) the triggering GPIO. So we need to protect against
+concurrent GPIO register accesses in the suspend/resume handlers too.
+
+This commit fixes this by adding the missing spin_lock / unlock calls.
+
+The 2 fixes together fix the Acer Switch 10 SW5-012 getting completely
+confused after a suspend resume. The DSDT for this device has a bug
+in its _LID method which reprograms the home and power button trigger-
+flags requesting both high and low _level_ interrupts so the IRQs for
+these 2 GPIOs continuously fire. This combined with the saving of
+registers during suspend, triggers concurrent GPIO register accesses
+resulting in saving 0xffffffff as pconf0 value during suspend and then
+when restoring this on resume the pinmux settings get all messed up,
+resulting in various I2C busses being stuck, the wifi no longer working
+and often the tablet simply not coming out of suspend at all.
+
+Cc: stable@vger.kernel.org
+Fixes: 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 81 +++++++++++++-----------
+ 1 file changed, 44 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index f38d596efa05..021e28ff1194 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -196,7 +196,6 @@ struct byt_gpio {
+       struct platform_device *pdev;
+       struct pinctrl_dev *pctl_dev;
+       struct pinctrl_desc pctl_desc;
+-      raw_spinlock_t lock;
+       const struct byt_pinctrl_soc_data *soc_data;
+       struct byt_community *communities_copy;
+       struct byt_gpio_pin_context *saved_context;
+@@ -707,6 +706,8 @@ static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
+       NULL,
+ };
++static DEFINE_RAW_SPINLOCK(byt_lock);
++
+ static struct byt_community *byt_get_community(struct byt_gpio *vg,
+                                              unsigned int pin)
+ {
+@@ -848,7 +849,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
+       unsigned long flags;
+       int i;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       for (i = 0; i < group.npins; i++) {
+               void __iomem *padcfg0;
+@@ -868,7 +869,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
+               writel(value, padcfg0);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+@@ -878,7 +879,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+       unsigned long flags;
+       int i;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       for (i = 0; i < group.npins; i++) {
+               void __iomem *padcfg0;
+@@ -898,7 +899,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+               writel(value, padcfg0);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+@@ -947,11 +948,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
+       unsigned long flags;
+       u32 value;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+       writel(value, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+@@ -963,7 +964,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+       u32 value, gpio_mux;
+       unsigned long flags;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       /*
+        * In most cases, func pin mux 000 means GPIO function.
+@@ -985,7 +986,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+                        "pin %u forcibly re-configured as GPIO\n", offset);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       pm_runtime_get(&vg->pdev->dev);
+@@ -1013,7 +1014,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+       unsigned long flags;
+       u32 value;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(val_reg);
+       value &= ~BYT_DIR_MASK;
+@@ -1030,7 +1031,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+                    "Potential Error: Setting GPIO with direct_irq_en to output");
+       writel(value, val_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1099,11 +1100,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
+       u32 conf, pull, val, debounce;
+       u16 arg = 0;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       conf = readl(conf_reg);
+       pull = conf & BYT_PULL_ASSIGN_MASK;
+       val = readl(val_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+@@ -1130,9 +1131,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
+               if (!(conf & BYT_DEBOUNCE_EN))
+                       return -EINVAL;
+-              raw_spin_lock_irqsave(&vg->lock, flags);
++              raw_spin_lock_irqsave(&byt_lock, flags);
+               debounce = readl(db_reg);
+-              raw_spin_unlock_irqrestore(&vg->lock, flags);
++              raw_spin_unlock_irqrestore(&byt_lock, flags);
+               switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
+               case BYT_DEBOUNCE_PULSE_375US:
+@@ -1184,7 +1185,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
+       u32 conf, val, debounce;
+       int i, ret = 0;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       conf = readl(conf_reg);
+       val = readl(val_reg);
+@@ -1292,7 +1293,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
+       if (!ret)
+               writel(conf, conf_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return ret;
+ }
+@@ -1317,9 +1318,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
+       unsigned long flags;
+       u32 val;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       val = readl(reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return !!(val & BYT_LEVEL);
+ }
+@@ -1334,13 +1335,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+       if (!reg)
+               return;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       old_val = readl(reg);
+       if (value)
+               writel(old_val | BYT_LEVEL, reg);
+       else
+               writel(old_val & ~BYT_LEVEL, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+@@ -1353,9 +1354,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+       if (!reg)
+               return -EINVAL;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       if (!(value & BYT_OUTPUT_EN))
+               return GPIOF_DIR_OUT;
+@@ -1398,14 +1399,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+               const char *label;
+               unsigned int pin;
+-              raw_spin_lock_irqsave(&vg->lock, flags);
++              raw_spin_lock_irqsave(&byt_lock, flags);
+               pin = vg->soc_data->pins[i].number;
+               reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i conf0 reg\n",
+                                  pin);
+-                      raw_spin_unlock_irqrestore(&vg->lock, flags);
++                      raw_spin_unlock_irqrestore(&byt_lock, flags);
+                       continue;
+               }
+               conf0 = readl(reg);
+@@ -1414,11 +1415,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i val reg\n", pin);
+-                      raw_spin_unlock_irqrestore(&vg->lock, flags);
++                      raw_spin_unlock_irqrestore(&byt_lock, flags);
+                       continue;
+               }
+               val = readl(reg);
+-              raw_spin_unlock_irqrestore(&vg->lock, flags);
++              raw_spin_unlock_irqrestore(&byt_lock, flags);
+               comm = byt_get_community(vg, pin);
+               if (!comm) {
+@@ -1502,9 +1503,9 @@ static void byt_irq_ack(struct irq_data *d)
+       if (!reg)
+               return;
+-      raw_spin_lock(&vg->lock);
++      raw_spin_lock(&byt_lock);
+       writel(BIT(offset % 32), reg);
+-      raw_spin_unlock(&vg->lock);
++      raw_spin_unlock(&byt_lock);
+ }
+ static void byt_irq_mask(struct irq_data *d)
+@@ -1528,7 +1529,7 @@ static void byt_irq_unmask(struct irq_data *d)
+       if (!reg)
+               return;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       switch (irqd_get_trigger_type(d)) {
+@@ -1551,7 +1552,7 @@ static void byt_irq_unmask(struct irq_data *d)
+       writel(value, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_irq_type(struct irq_data *d, unsigned int type)
+@@ -1565,7 +1566,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
+       if (!reg || offset >= vg->chip.ngpio)
+               return -EINVAL;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       WARN(value & BYT_DIRECT_IRQ_EN,
+@@ -1587,7 +1588,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
+       else if (type & IRQ_TYPE_LEVEL_MASK)
+               irq_set_handler_locked(d, handle_level_irq);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1623,9 +1624,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
+                       continue;
+               }
+-              raw_spin_lock(&vg->lock);
++              raw_spin_lock(&byt_lock);
+               pending = readl(reg);
+-              raw_spin_unlock(&vg->lock);
++              raw_spin_unlock(&byt_lock);
+               for_each_set_bit(pin, &pending, 32) {
+                       virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
+                       generic_handle_irq(virq);
+@@ -1828,8 +1829,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
+               return PTR_ERR(vg->pctl_dev);
+       }
+-      raw_spin_lock_init(&vg->lock);
+-
+       ret = byt_gpio_probe(vg);
+       if (ret)
+               return ret;
+@@ -1845,8 +1844,11 @@ static int byt_gpio_suspend(struct device *dev)
+ {
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
++      unsigned long flags;
+       int i;
++      raw_spin_lock_irqsave(&byt_lock, flags);
++
+       for (i = 0; i < vg->soc_data->npins; i++) {
+               void __iomem *reg;
+               u32 value;
+@@ -1867,6 +1869,7 @@ static int byt_gpio_suspend(struct device *dev)
+               vg->saved_context[i].val = value;
+       }
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1874,8 +1877,11 @@ static int byt_gpio_resume(struct device *dev)
+ {
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
++      unsigned long flags;
+       int i;
++      raw_spin_lock_irqsave(&byt_lock, flags);
++
+       for (i = 0; i < vg->soc_data->npins; i++) {
+               void __iomem *reg;
+               u32 value;
+@@ -1913,6 +1919,7 @@ static int byt_gpio_resume(struct device *dev)
+               }
+       }
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+ #endif
+-- 
+2.20.1
+
diff --git a/queue-4.19/serial-sprd-use-readable-macros-instead-of-magic-num.patch b/queue-4.19/serial-sprd-use-readable-macros-instead-of-magic-num.patch
new file mode 100644 (file)
index 0000000..376736b
--- /dev/null
@@ -0,0 +1,36 @@
+From b8917f323e25835c0ac8d02cba9253bcd79040cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Dec 2019 20:00:07 +0800
+Subject: serial: sprd: Use readable macros instead of magic number
+
+From: Yonghan Ye <yonghan.ye@unisoc.com>
+
+[ Upstream commit 2b5a997386b0594e671a32c7e429cf59ac8fc54c ]
+
+Define readable macros instead of magic number to make code more readable.
+
+Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
+Acked-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sprd_serial.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
+index 2774af86763e..c6cad45cd34b 100644
+--- a/drivers/tty/serial/sprd_serial.c
++++ b/drivers/tty/serial/sprd_serial.c
+@@ -294,6 +294,9 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
+       if (ims & SPRD_IMSR_TIMEOUT)
+               serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
++      if (ims & SPRD_IMSR_BREAK_DETECT)
++              serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
++
+       if (ims & (SPRD_IMSR_RX_FIFO_FULL |
+               SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT))
+               sprd_rx(port);
+-- 
+2.20.1
+
index 69db9a541712dc1a26711d878f7445c7551d2d9b..30e11ecdab3163943ed1ac23c1b34f0bf175aa03 100644 (file)
@@ -109,3 +109,7 @@ tcp-do-not-send-empty-skb-from-tcp_write_xmit.patch
 gtp-fix-wrong-condition-in-gtp_genl_dump_pdp.patch
 gtp-fix-an-use-after-free-in-ipv4_pdp_find.patch
 gtp-avoid-zero-size-hashtable.patch
+spi-fsl-don-t-map-irq-during-probe.patch
+tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch
+serial-sprd-use-readable-macros-instead-of-magic-num.patch
+pinctrl-baytrail-really-serialize-all-register-acces.patch
diff --git a/queue-4.19/spi-fsl-don-t-map-irq-during-probe.patch b/queue-4.19/spi-fsl-don-t-map-irq-during-probe.patch
new file mode 100644 (file)
index 0000000..1430dc6
--- /dev/null
@@ -0,0 +1,96 @@
+From 1e05fb115ac93ca065dd8f12ff0c8d99ec2e147d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Dec 2019 15:27:27 +0000
+Subject: spi: fsl: don't map irq during probe
+
+From: Christophe Leroy <christophe.leroy@c-s.fr>
+
+[ Upstream commit 3194d2533efffae8b815d84729ecc58b6a9000ab ]
+
+With lastest kernel, the following warning is observed at startup:
+
+[    1.500609] ------------[ cut here ]------------
+[    1.505225] remove_proc_entry: removing non-empty directory 'irq/22', leaking at least 'fsl_spi'
+[    1.514234] WARNING: CPU: 0 PID: 1 at fs/proc/generic.c:682 remove_proc_entry+0x198/0x1c0
+[    1.522403] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-s3k-dev-02248-g93532430a4ff #2564
+[    1.530724] NIP:  c0197694 LR: c0197694 CTR: c0050d80
+[    1.535762] REGS: df4a5af0 TRAP: 0700   Not tainted  (5.4.0-02248-g93532430a4ff)
+[    1.543818] MSR:  00029032 <EE,ME,IR,DR,RI>  CR: 22028222  XER: 00000000
+[    1.550524]
+[    1.550524] GPR00: c0197694 df4a5ba8 df4a0000 00000054 00000000 00000000 00004a38 00000010
+[    1.550524] GPR08: c07c5a30 00000800 00000000 00001032 22000208 00000000 c0004b14 00000000
+[    1.550524] GPR16: 00000000 00000000 00000000 00000000 00000000 00000000 c0830000 c07fc078
+[    1.550524] GPR24: c08e8ca0 df665d10 df60ea98 c07c9db8 00000001 df5d5ae3 df5d5a80 df43f8e3
+[    1.585327] NIP [c0197694] remove_proc_entry+0x198/0x1c0
+[    1.590628] LR [c0197694] remove_proc_entry+0x198/0x1c0
+[    1.595829] Call Trace:
+[    1.598280] [df4a5ba8] [c0197694] remove_proc_entry+0x198/0x1c0 (unreliable)
+[    1.605321] [df4a5bd8] [c0067acc] unregister_irq_proc+0x5c/0x70
+[    1.611238] [df4a5bf8] [c005fbc4] free_desc+0x3c/0x80
+[    1.616286] [df4a5c18] [c005fe2c] irq_free_descs+0x70/0xa8
+[    1.621778] [df4a5c38] [c033d3fc] of_fsl_spi_probe+0xdc/0x3cc
+[    1.627525] [df4a5c88] [c02f0f64] platform_drv_probe+0x44/0xa4
+[    1.633350] [df4a5c98] [c02eee44] really_probe+0x1ac/0x418
+[    1.638829] [df4a5cc8] [c02ed3e8] bus_for_each_drv+0x64/0xb0
+[    1.644481] [df4a5cf8] [c02ef950] __device_attach+0xd4/0x128
+[    1.650132] [df4a5d28] [c02ed61c] bus_probe_device+0xa0/0xbc
+[    1.655783] [df4a5d48] [c02ebbe8] device_add+0x544/0x74c
+[    1.661096] [df4a5d88] [c0382b78] of_platform_device_create_pdata+0xa4/0x100
+[    1.668131] [df4a5da8] [c0382cf4] of_platform_bus_create+0x120/0x20c
+[    1.674474] [df4a5df8] [c0382d50] of_platform_bus_create+0x17c/0x20c
+[    1.680818] [df4a5e48] [c0382e88] of_platform_bus_probe+0x9c/0xf0
+[    1.686907] [df4a5e68] [c0751404] __machine_initcall_cmpcpro_cmpcpro_declare_of_platform_devices+0x74/0x1a4
+[    1.696629] [df4a5e98] [c072a4cc] do_one_initcall+0x8c/0x1d4
+[    1.702282] [df4a5ef8] [c072a768] kernel_init_freeable+0x154/0x204
+[    1.708455] [df4a5f28] [c0004b2c] kernel_init+0x18/0x110
+[    1.713769] [df4a5f38] [c00122ac] ret_from_kernel_thread+0x14/0x1c
+[    1.719926] Instruction dump:
+[    1.722889] 2c030000 4182004c 3863ffb0 3c80c05f 80e3005c 388436a0 3c60c06d 7fa6eb78
+[    1.730630] 7fe5fb78 38840280 38634178 4be8c611 <0fe00000> 4bffff6c 3c60c071 7fe4fb78
+[    1.738556] ---[ end trace 05d0720bf2e352e2 ]---
+
+The problem comes from the error path which calls
+irq_dispose_mapping() while the IRQ has been requested with
+devm_request_irq().
+
+IRQ doesn't need to be mapped with irq_of_parse_and_map(). The only
+need is to get the IRQ virtual number. For that, use
+of_irq_to_resource() instead of the
+irq_of_parse_and_map()/irq_dispose_mapping() pair.
+
+Fixes: 500a32abaf81 ("spi: fsl: Call irq_dispose_mapping in err path")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
+Link: https://lore.kernel.org/r/518cfb83347d5372748e7fe72f94e2e9443d0d4a.1575905123.git.christophe.leroy@c-s.fr
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-fsl-spi.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
+index 8f2e97857e8b..fb34ba3f2b23 100644
+--- a/drivers/spi/spi-fsl-spi.c
++++ b/drivers/spi/spi-fsl-spi.c
+@@ -832,8 +832,8 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
+       if (ret)
+               goto err;
+-      irq = irq_of_parse_and_map(np, 0);
+-      if (!irq) {
++      irq = of_irq_to_resource(np, 0, NULL);
++      if (irq <= 0) {
+               ret = -EINVAL;
+               goto err;
+       }
+@@ -847,7 +847,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
+       return 0;
+ err:
+-      irq_dispose_mapping(irq);
+       if (type == TYPE_FSL)
+               of_fsl_spi_free_chipselects(dev);
+       return ret;
+-- 
+2.20.1
+
diff --git a/queue-4.19/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch b/queue-4.19/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch
new file mode 100644 (file)
index 0000000..5c53f10
--- /dev/null
@@ -0,0 +1,90 @@
+From 4d747889ac553e0bc90d165b32ac8fa625f3d8d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2019 09:54:03 +0100
+Subject: tty/serial: atmel: fix out of range clock divider handling
+
+From: David Engraf <david.engraf@sysgo.com>
+
+[ Upstream commit cb47b9f8630ae3fa3f5fbd0c7003faba7abdf711 ]
+
+Use MCK_DIV8 when the clock divider is > 65535. Unfortunately the mode
+register was already written thus the clock selection is ignored.
+
+Fix by doing the baud rate calulation before setting the mode.
+
+Fixes: 5bf5635ac170 ("tty/serial: atmel: add fractional baud rate support")
+Signed-off-by: David Engraf <david.engraf@sysgo.com>
+Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
+Acked-by: Richard Genoud <richard.genoud@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20191216085403.17050-1-david.engraf@sysgo.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/atmel_serial.c | 43 ++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index dd8949e8fcd7..f34520e9ad6e 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -2154,27 +2154,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+               mode |= ATMEL_US_USMODE_NORMAL;
+       }
+-      /* set the mode, clock divisor, parity, stop bits and data size */
+-      atmel_uart_writel(port, ATMEL_US_MR, mode);
+-
+-      /*
+-       * when switching the mode, set the RTS line state according to the
+-       * new mode, otherwise keep the former state
+-       */
+-      if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
+-              unsigned int rts_state;
+-
+-              if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+-                      /* let the hardware control the RTS line */
+-                      rts_state = ATMEL_US_RTSDIS;
+-              } else {
+-                      /* force RTS line to low level */
+-                      rts_state = ATMEL_US_RTSEN;
+-              }
+-
+-              atmel_uart_writel(port, ATMEL_US_CR, rts_state);
+-      }
+-
+       /*
+        * Set the baud rate:
+        * Fractional baudrate allows to setup output frequency more
+@@ -2200,6 +2179,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+       quot = cd | fp << ATMEL_US_FP_OFFSET;
+       atmel_uart_writel(port, ATMEL_US_BRGR, quot);
++
++      /* set the mode, clock divisor, parity, stop bits and data size */
++      atmel_uart_writel(port, ATMEL_US_MR, mode);
++
++      /*
++       * when switching the mode, set the RTS line state according to the
++       * new mode, otherwise keep the former state
++       */
++      if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
++              unsigned int rts_state;
++
++              if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
++                      /* let the hardware control the RTS line */
++                      rts_state = ATMEL_US_RTSDIS;
++              } else {
++                      /* force RTS line to low level */
++                      rts_state = ATMEL_US_RTSEN;
++              }
++
++              atmel_uart_writel(port, ATMEL_US_CR, rts_state);
++      }
++
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
+       atmel_port->tx_stopped = false;
+-- 
+2.20.1
+