]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blobdiff - releases/4.14.111/hid-intel-ish-hid-avoid-binding-wrong-ishtp_cl_devic.patch
Linux 4.14.111
[thirdparty/kernel/stable-queue.git] / releases / 4.14.111 / hid-intel-ish-hid-avoid-binding-wrong-ishtp_cl_devic.patch
diff --git a/releases/4.14.111/hid-intel-ish-hid-avoid-binding-wrong-ishtp_cl_devic.patch b/releases/4.14.111/hid-intel-ish-hid-avoid-binding-wrong-ishtp_cl_devic.patch
new file mode 100644 (file)
index 0000000..6d8dadf
--- /dev/null
@@ -0,0 +1,53 @@
+From 016e05071277498ac923d2ae2fed9d1e48ba9ae9 Mon Sep 17 00:00:00 2001
+From: Hong Liu <hong.liu@intel.com>
+Date: Tue, 12 Feb 2019 20:05:20 +0800
+Subject: HID: intel-ish-hid: avoid binding wrong ishtp_cl_device
+
+[ Upstream commit 0d28f49412405d87d3aae83da255070a46e67627 ]
+
+When performing a warm reset in ishtp bus driver, the ishtp_cl_device
+will not be removed, its fw_client still points to the already freed
+ishtp_device.fw_clients array.
+
+Later after driver finishing ishtp client enumeration, this dangling
+pointer may cause driver to bind the wrong ishtp_cl_device to the new
+client, causing wrong callback to be called for messages intended for
+the new client.
+
+This helps in development of firmware where frequent switching of
+firmwares is required without Linux reboot.
+
+Signed-off-by: Hong Liu <hong.liu@intel.com>
+Tested-by: Hongyan Song <hongyan.song@intel.com>
+Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/intel-ish-hid/ishtp/bus.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c
+index 2623a567ffba..f546635e9ac9 100644
+--- a/drivers/hid/intel-ish-hid/ishtp/bus.c
++++ b/drivers/hid/intel-ish-hid/ishtp/bus.c
+@@ -623,7 +623,8 @@ int ishtp_cl_device_bind(struct ishtp_cl *cl)
+       spin_lock_irqsave(&cl->dev->device_list_lock, flags);
+       list_for_each_entry(cl_device, &cl->dev->device_list,
+                       device_link) {
+-              if (cl_device->fw_client->client_id == cl->fw_client_id) {
++              if (cl_device->fw_client &&
++                  cl_device->fw_client->client_id == cl->fw_client_id) {
+                       cl->device = cl_device;
+                       rv = 0;
+                       break;
+@@ -683,6 +684,7 @@ void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev,
+       spin_lock_irqsave(&ishtp_dev->device_list_lock, flags);
+       list_for_each_entry_safe(cl_device, n, &ishtp_dev->device_list,
+                                device_link) {
++              cl_device->fw_client = NULL;
+               if (warm_reset && cl_device->reference_count)
+                       continue;
+-- 
+2.19.1
+