From 1c5fe02ca8d339389c8a23abb71a9097216edd4a Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Wed, 12 Jun 2024 18:13:25 +0800 Subject: [PATCH] usb: typec: tcpci_husb311: Disable IRQ before unregistering TCPCI port For reboot stress tests, have the below crash. [ 15.003004] Unable to handle kernel paging request at virtual address ffffffc009c975a0 [ 14.897469] pc : queued_spin_lock_slowpath+0x274/0x420 [ 14.898086] lr : kthread_queue_work+0xb8/0x114 [ 14.899280] sp : ffffffc00cb93c90 [ 14.899280] x29: ffffffc00cb93c90 x28: 0000000000000000 x27: 0000000000000000 [ 14.899284] x26: ffffffc0080bc414 x25: ffffffc0080bc4f0 ... [ 15.010633] CPU: 5 PID: 240 Comm: irq/82-husb311 Tainted: G O 6.1.75 #120 ... [ 15.029917] Call trace: [ 15.030137] queued_spin_lock_slowpath+0x274/0x420 [ 15.030564] kthread_queue_work+0xb8/0x114 [ 15.030926] tcpm_cc_change+0x60/0xa4 [ 15.031256] tcpci_irq+0x150/0x240 [ 15.031554] husb311_irq+0x50/0x290 [ 15.031863] irq_thread_fn+0x30/0xb0 [ 15.032182] irq_thread+0x16c/0x2c4 [ 15.032490] kthread+0xdc/0xe0 [ 15.032765] ret_from_fork+0x10/0x20 ... This commit addresses the issue by disabling the IRQ before unregistering the TCPCI port in both the remove and shutdown handlers. This ensures that no new interrupts are handled after the port is unregistered, preventing potential race conditions or use-after-free issues. Fixes: 5e320d031053 ("usb: typec: husb311: set vbus off when shutdown") Change-Id: Ie2cb85a15f6c63b019e4a000ba65205bc508e483 Signed-off-by: Caesar Wang --- drivers/usb/typec/tcpm/tcpci_husb311.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci_husb311.c b/drivers/usb/typec/tcpm/tcpci_husb311.c index 74f45f581ca6..175d5f3e2a1d 100644 --- a/drivers/usb/typec/tcpm/tcpci_husb311.c +++ b/drivers/usb/typec/tcpm/tcpci_husb311.c @@ -307,6 +307,7 @@ static void husb311_remove(struct i2c_client *client) struct husb311_chip *chip = i2c_get_clientdata(client); device_init_wakeup(chip->dev, false); + disable_irq(client->irq); cancel_delayed_work_sync(&chip->pm_work); tcpci_unregister_port(chip->tcpci); } @@ -317,6 +318,7 @@ static void husb311_shutdown(struct i2c_client *client) husb311_set_vbus(chip->tcpci, &chip->data, false, false); + disable_irq(client->irq); cancel_delayed_work_sync(&chip->pm_work); tcpci_unregister_port(chip->tcpci); }