| From bbc126ae381cf0a27822c1f822d0aeed74cc40d9 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> |
| Date: Mon, 2 May 2022 10:04:56 +0200 |
| Subject: usb: typec: tcpci: Don't skip cleanup in .remove() on error |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| |
| commit bbc126ae381cf0a27822c1f822d0aeed74cc40d9 upstream. |
| |
| Returning an error value in an i2c remove callback results in an error |
| message being emitted by the i2c core, but otherwise it doesn't make a |
| difference. The device goes away anyhow and the devm cleanups are |
| called. |
| |
| In this case the remove callback even returns early without stopping the |
| tcpm worker thread and various timers. A work scheduled on the work |
| queue, or a firing timer after tcpci_remove() returned probably results |
| in a use-after-free situation because the regmap and driver data were |
| freed. So better make sure that tcpci_unregister_port() is called even |
| if disabling the irq failed. |
| |
| Also emit a more specific error message instead of the i2c core's |
| "remove failed (EIO), will be ignored" and return 0 to suppress the |
| core's warning. |
| |
| This patch is (also) a preparation for making i2c remove callbacks |
| return void. |
| |
| Fixes: 3ba76256fc4e ("usb: typec: tcpci: mask event interrupts when remove driver") |
| Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> |
| Cc: stable <stable@vger.kernel.org> |
| Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> |
| Reviewed-by: Guenter Roeck <linux@roeck-us.net> |
| Link: https://lore.kernel.org/r/20220502080456.21568-1-u.kleine-koenig@pengutronix.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/usb/typec/tcpm/tcpci.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/usb/typec/tcpm/tcpci.c |
| +++ b/drivers/usb/typec/tcpm/tcpci.c |
| @@ -877,7 +877,7 @@ static int tcpci_remove(struct i2c_clien |
| /* Disable chip interrupts before unregistering port */ |
| err = tcpci_write16(chip->tcpci, TCPC_ALERT_MASK, 0); |
| if (err < 0) |
| - return err; |
| + dev_warn(&client->dev, "Failed to disable irqs (%pe)\n", ERR_PTR(err)); |
| |
| tcpci_unregister_port(chip->tcpci); |
| |