]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Dec 2020 15:47:09 +0000 (16:47 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Dec 2020 15:47:09 +0000 (16:47 +0100)
added patches:
spi-prevent-adding-devices-below-an-unregistering-controller.patch

queue-4.4/series
queue-4.4/spi-prevent-adding-devices-below-an-unregistering-controller.patch [new file with mode: 0644]

index e05dbedd5ca00146568a03dcc9ac42abece82acb..47a00eefe5a6824fceb6db431aaa840414e8e68f 100644 (file)
@@ -5,3 +5,4 @@ platform-x86-acer-wmi-add-automatic-keyboard-backgro.patch
 input-cm109-do-not-stomp-on-control-urb.patch
 input-i8042-add-acer-laptops-to-the-i8042-reset-list.patch
 pinctrl-amd-remove-debounce-filter-setting-in-irq-type-setting.patch
+spi-prevent-adding-devices-below-an-unregistering-controller.patch
diff --git a/queue-4.4/spi-prevent-adding-devices-below-an-unregistering-controller.patch b/queue-4.4/spi-prevent-adding-devices-below-an-unregistering-controller.patch
new file mode 100644 (file)
index 0000000..cfe652b
--- /dev/null
@@ -0,0 +1,110 @@
+From foo@baz Mon Dec 14 04:45:32 PM CET 2020
+From: Lukas Wunner <lukas@wunner.de>
+Date: Mon, 3 Aug 2020 13:09:01 +0200
+Subject: spi: Prevent adding devices below an unregistering controller
+
+From: Lukas Wunner <lukas@wunner.de>
+
+commit ddf75be47ca748f8b12d28ac64d624354fddf189 upstream
+
+CONFIG_OF_DYNAMIC and CONFIG_ACPI allow adding SPI devices at runtime
+using a DeviceTree overlay or DSDT patch.  CONFIG_SPI_SLAVE allows the
+same via sysfs.
+
+But there are no precautions to prevent adding a device below a
+controller that's being removed.  Such a device is unusable and may not
+even be able to unbind cleanly as it becomes inaccessible once the
+controller has been torn down.  E.g. it is then impossible to quiesce
+the device's interrupt.
+
+of_spi_notify() and acpi_spi_notify() do hold a ref on the controller,
+but otherwise run lockless against spi_unregister_controller().
+
+Fix by holding the spi_add_lock in spi_unregister_controller() and
+bailing out of spi_add_device() if the controller has been unregistered
+concurrently.
+
+Fixes: ce79d54ae447 ("spi/of: Add OF notifier handler")
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org # v3.19+
+Cc: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Octavian Purdila <octavian.purdila@intel.com>
+Cc: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+Link: https://lore.kernel.org/r/a8c3205088a969dc8410eec1eba9aface60f36af.1596451035.git.lukas@wunner.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[sudip: adjust context]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/Kconfig |    3 +++
+ drivers/spi/spi.c   |   21 ++++++++++++++++++++-
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -706,4 +706,7 @@ endif # SPI_MASTER
+ # (slave support would go here)
++config SPI_DYNAMIC
++      def_bool ACPI || OF_DYNAMIC || SPI_SLAVE
++
+ endif # SPI
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -418,6 +418,12 @@ static LIST_HEAD(spi_master_list);
+  */
+ static DEFINE_MUTEX(board_lock);
++/*
++ * Prevents addition of devices with same chip select and
++ * addition of devices below an unregistering controller.
++ */
++static DEFINE_MUTEX(spi_add_lock);
++
+ /**
+  * spi_alloc_device - Allocate a new SPI device
+  * @master: Controller to which device is connected
+@@ -496,7 +502,6 @@ static int spi_dev_check(struct device *
+  */
+ int spi_add_device(struct spi_device *spi)
+ {
+-      static DEFINE_MUTEX(spi_add_lock);
+       struct spi_master *master = spi->master;
+       struct device *dev = master->dev.parent;
+       int status;
+@@ -525,6 +530,13 @@ int spi_add_device(struct spi_device *sp
+               goto done;
+       }
++      /* Controller may unregister concurrently */
++      if (IS_ENABLED(CONFIG_SPI_DYNAMIC) &&
++          !device_is_registered(&master->dev)) {
++              status = -ENODEV;
++              goto done;
++      }
++
+       if (master->cs_gpios)
+               spi->cs_gpio = master->cs_gpios[spi->chip_select];
+@@ -1962,6 +1974,10 @@ static int __unregister(struct device *d
+  */
+ void spi_unregister_master(struct spi_master *master)
+ {
++      /* Prevent addition of new devices, unregister existing ones */
++      if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
++              mutex_lock(&spi_add_lock);
++
+       device_for_each_child(&master->dev, NULL, __unregister);
+       if (master->queued) {
+@@ -1981,6 +1997,9 @@ void spi_unregister_master(struct spi_ma
+       if (!devres_find(master->dev.parent, devm_spi_release_master,
+                        devm_spi_match_master, master))
+               put_device(&master->dev);
++
++      if (IS_ENABLED(CONFIG_SPI_DYNAMIC))
++              mutex_unlock(&spi_add_lock);
+ }
+ EXPORT_SYMBOL_GPL(spi_unregister_master);