Skip to contentSkip to conversation

Input: psmouse - fix cleaning up SMBus companions

PATCH In review Dmitry Torokhov 2 participants 2 messages Apr 1, 2017 – Apr 3, 2017

Subsystems (2)
lore
Share & tools
lore

Dmitry Torokhov

author maintainer
#0 lore raw

PATCH 1/1 Input: psmouse - fix cleaning up SMBus companions

When trying to destroy platform data after destruction of SMbus companion, we need to make sure that we are actually dealing with an SMB companion device, and not some random I2C client device.

Fixes 8eb92e5c9133 ("Input: psmouse - add support for SMBus companions")
---
 drivers/input/mouse/psmouse-smbus.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/input/mouse/psmouse-smbus.c +19 -11
index d0cf2fde173e..c7ac24d119c1 100644
@@ -61,24 +61,29 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
 
 static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
 {
-	struct psmouse_smbus_dev *smbdev;
+	struct psmouse_smbus_dev *smbdev, *tmp;
 
 	mutex_lock(&psmouse_smbus_mutex);
 
-	list_for_each_entry(smbdev, &psmouse_smbus_list, node) {
-		if (smbdev->client == client) {
+	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
+		if (smbdev->client != client)
+			continue;
+
+		kfree(client->dev.platform_data);
+		client->dev.platform_data = NULL;
+
+		if (!smbdev->dead) {
 			psmouse_dbg(smbdev->psmouse,
 				    "Marking SMBus companion %s as gone\n",
 				    dev_name(&smbdev->client->dev));
-			smbdev->client = NULL;
 			smbdev->dead = true;
 			serio_rescan(smbdev->psmouse->ps2dev.serio);
+		} else {
+			list_del(&smbdev->node);
+			kfree(smbdev);
 		}
 	}
 
-	kfree(client->dev.platform_data);
-	client->dev.platform_data = NULL;
-
 	mutex_unlock(&psmouse_smbus_mutex);
 }
 
@@ -162,17 +167,20 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse)
 	struct psmouse_smbus_dev *smbdev = psmouse->private;
 
 	mutex_lock(&psmouse_smbus_mutex);
-	list_del(&smbdev->node);
-	mutex_unlock(&psmouse_smbus_mutex);
 
-	if (smbdev->client) {
+	if (smbdev->dead) {
+		list_del(&smbdev->node);
+		kfree(smbdev);
+	} else {
+		smbdev->dead = true;
 		psmouse_dbg(smbdev->psmouse,
 			    "posting removal request for SMBus companion %s\n",
 			    dev_name(&smbdev->client->dev));
 		psmouse_smbus_schedule_remove(smbdev->client);
 	}
 
-	kfree(smbdev);
+	mutex_unlock(&psmouse_smbus_mutex);
+
 	psmouse->private = NULL;
 }
 
Signature · 5 lines
2.12.2.564.g063fe858b8-goog


-- 
Dmitry
Tested-by on v1 1/1
#1 lore raw
Quoted 8 lines · Dmitry Torokhov

When trying to destroy platform data after destruction of SMbus companion, we need to make sure that we are actually dealing with an SMB companion device, and not some random I2C client device.

Fixes 8eb92e5c9133 ("Input: psmouse - add support for SMBus companions")

---

Thanks for the fix!

Cheers,
Benjamin

Quoted 75 lines
 drivers/input/mouse/psmouse-smbus.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/input/mouse/psmouse-smbus.c +19 -11
index d0cf2fde173e..c7ac24d119c1 100644
@@ -61,24 +61,29 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter)
 
 static void psmouse_smbus_detach_i2c_client(struct i2c_client *client)
 {
-	struct psmouse_smbus_dev *smbdev;
+	struct psmouse_smbus_dev *smbdev, *tmp;
 
 	mutex_lock(&psmouse_smbus_mutex);
 
-	list_for_each_entry(smbdev, &psmouse_smbus_list, node) {
-		if (smbdev->client == client) {
+	list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) {
+		if (smbdev->client != client)
+			continue;
+
+		kfree(client->dev.platform_data);
+		client->dev.platform_data = NULL;
+
+		if (!smbdev->dead) {
 			psmouse_dbg(smbdev->psmouse,
 				    "Marking SMBus companion %s as gone\n",
 				    dev_name(&smbdev->client->dev));
-			smbdev->client = NULL;
 			smbdev->dead = true;
 			serio_rescan(smbdev->psmouse->ps2dev.serio);
+		} else {
+			list_del(&smbdev->node);
+			kfree(smbdev);
 		}
 	}
 
-	kfree(client->dev.platform_data);
-	client->dev.platform_data = NULL;
-
 	mutex_unlock(&psmouse_smbus_mutex);
 }
 
@@ -162,17 +167,20 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse)
 	struct psmouse_smbus_dev *smbdev = psmouse->private;
 
 	mutex_lock(&psmouse_smbus_mutex);
-	list_del(&smbdev->node);
-	mutex_unlock(&psmouse_smbus_mutex);
 
-	if (smbdev->client) {
+	if (smbdev->dead) {
+		list_del(&smbdev->node);
+		kfree(smbdev);
+	} else {
+		smbdev->dead = true;
 		psmouse_dbg(smbdev->psmouse,
 			    "posting removal request for SMBus companion %s\n",
 			    dev_name(&smbdev->client->dev));
 		psmouse_smbus_schedule_remove(smbdev->client);
 	}
 
-	kfree(smbdev);
+	mutex_unlock(&psmouse_smbus_mutex);
+
 	psmouse->private = NULL;
 }
 
Signature · 5 lines
2.12.2.564.g063fe858b8-goog


-- 
Dmitry