From 1979af10ca9286b04f601bc7f00a37cdc8f7c4f1 Mon Sep 17 00:00:00 2001
From: DENG Qingfang <dengqf6@mail2.sysu.edu.cn>
Date: Thu, 19 Sep 2019 11:44:48 +0200
Subject: [PATCH] kernel: 4.19: fix crash when setting up spi-gpio
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If an spi-gpio was specified with num-chipselects = <0> in dts, kernel
will crash:

 Unable to handle kernel paging request at virtual address 32697073
 pgd = (ptrval)
 [32697073] *pgd=00000000
 Internal error: Oops: 5 [# 1] SMP ARM
 Modules linked in:
 CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.72 #0
 Hardware name: Generic DT based system
 PC is at validate_desc+0x28/0x80
 LR is at gpiod_direction_output+0x14/0x128
 ...
 [<c0544db4>] (validate_desc) from [<c0545228>] (gpiod_direction_output+0x14/0x128)
 [<c0545228>] (gpiod_direction_output) from [<c05fa714>] (spi_gpio_setup+0x58/0x64)
 [<c05fa714>] (spi_gpio_setup) from [<c05f7258>] (spi_setup+0x12c/0x148)
 [<c05f7258>] (spi_setup) from [<c05f7330>] (spi_add_device+0xbc/0x12c)
 [<c05f7330>] (spi_add_device) from [<c05f7f74>] (spi_register_controller+0x838/0x924)
 [<c05f7f74>] (spi_register_controller) from [<c05fa494>] (spi_bitbang_start+0x108/0x120)
 [<c05fa494>] (spi_bitbang_start) from [<c05faa34>] (spi_gpio_probe+0x314/0x338)
 [<c05faa34>] (spi_gpio_probe) from [<c05a844c>] (platform_drv_probe+0x34/0x70)

The cause is spi_gpio_setup() did not check if the spi-gpio has
chipselect pins before setting their direction and results in derefing
an invalid pointer.

The bug is spotted in kernel 4.19.72 and does not occur in 4.14.

There is a similar fix upstream in kernel 5.2 in commit 249e2632dcd0
("spi: gpio: Don't request CS GPIO in DT use-case").

Ref: https://patchwork.kernel.org/patch/11150619/
Signed-off-by: DENG Qingfang <dengqf6@mail2.sysu.edu.cn>
[use upstream patch, moved from hack to pending dir, commit facelift]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
---
 ...-fix-crash-when-num-chipselects-is-0.patch | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch

diff --git a/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch b/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch
new file mode 100644
index 00000000000..7c171745c23
--- /dev/null
+++ b/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch
@@ -0,0 +1,66 @@
+From 0f76408d8c1cb0979f4286dd23912e6e59784b35 Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <dqfext@gmail.com>
+Date: Thu, 19 Sep 2019 11:42:55 +0200
+Subject: [PATCH] spi: spi-gpio: fix crash when num-chipselects is 0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If an spi-gpio was specified with num-chipselects = <0> in dts, kernel will crash:
+
+Unable to handle kernel paging request at virtual address 32697073
+pgd = (ptrval)
+[32697073] *pgd=00000000
+Internal error: Oops: 5 [# 1] SMP ARM
+Modules linked in:
+CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.72 #0
+Hardware name: Generic DT based system
+PC is at validate_desc+0x28/0x80
+LR is at gpiod_direction_output+0x14/0x128
+...
+[<c0544db4>] (validate_desc) from [<c0545228>] (gpiod_direction_output+0x14/0x128)
+[<c0545228>] (gpiod_direction_output) from [<c05fa714>] (spi_gpio_setup+0x58/0x64)
+[<c05fa714>] (spi_gpio_setup) from [<c05f7258>] (spi_setup+0x12c/0x148)
+[<c05f7258>] (spi_setup) from [<c05f7330>] (spi_add_device+0xbc/0x12c)
+[<c05f7330>] (spi_add_device) from [<c05f7f74>] (spi_register_controller+0x838/0x924)
+[<c05f7f74>] (spi_register_controller) from [<c05fa494>] (spi_bitbang_start+0x108/0x120)
+[<c05fa494>] (spi_bitbang_start) from [<c05faa34>] (spi_gpio_probe+0x314/0x338)
+[<c05faa34>] (spi_gpio_probe) from [<c05a844c>] (platform_drv_probe+0x34/0x70)
+
+The cause is spi_gpio_setup() did not check if the spi-gpio has chipselect pins
+before setting their direction and results in derefing an invalid pointer.
+
+The bug is spotted in kernel 4.19.72 on OpenWrt, and does not occur in 4.14.
+
+There is a similar fix upstream 249e2632dcd0509b8f8f296f5aabf4d48dfd6da8.
+
+Ref: https://patchwork.kernel.org/patch/11150619/
+Cc: Linus Walleij <linus.walleij@linaro.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: DENG Qingfang <dqfext@gmail.com>
+Signed-off-by: Petr Štetiar <ynezz@true.cz>
+---
+ drivers/spi/spi-gpio.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
+index 088772ebef9b..57d5b6dc0dd0 100644
+--- a/drivers/spi/spi-gpio.c
++++ b/drivers/spi/spi-gpio.c
+@@ -242,10 +242,12 @@ static int spi_gpio_setup(struct spi_device *spi)
+ 	 * The CS GPIOs have already been
+ 	 * initialized from the descriptor lookup.
+ 	 */
+-	cs = spi_gpio->cs_gpios[spi->chip_select];
+-	if (!spi->controller_state && cs)
+-		status = gpiod_direction_output(cs,
+-						!(spi->mode & SPI_CS_HIGH));
++	if (spi_gpio->has_cs) {
++		cs = spi_gpio->cs_gpios[spi->chip_select];
++		if (!spi->controller_state && cs)
++			status = gpiod_direction_output(cs,
++						  !(spi->mode & SPI_CS_HIGH));
++	}
+ 
+ 	if (!status)
+ 		status = spi_bitbang_setup(spi);
-- 
GitLab