[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230320074028.186282-1-haotienh@nvidia.com>
Date: Mon, 20 Mar 2023 15:40:28 +0800
From: Haotien Hsu <haotienh@...dia.com>
To: Mathias Nyman <mathias.nyman@...el.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Thierry Reding <thierry.reding@...il.com>,
Jonathan Hunter <jonathanh@...dia.com>,
Philipp Zabel <p.zabel@...gutronix.de>,
<linux-usb@...r.kernel.org>, <linux-tegra@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
CC: JC Kuo <jckuo@...dia.com>, Wayne Chang <waynec@...dia.com>,
Haotien Hsu <haotienh@...dia.com>
Subject: [PATCH] usb: xhci: tegra: fix sleep in atomic call
From: Wayne Chang <waynec@...dia.com>
When we set the OTG port to Host mode, we observed the following splat:
[ 167.057718] BUG: sleeping function called from invalid context at
include/linux/sched/mm.h:229
[ 167.057872] Workqueue: events tegra_xusb_usb_phy_work
[ 167.057954] Call trace:
[ 167.057962] dump_backtrace+0x0/0x210
[ 167.057996] show_stack+0x30/0x50
[ 167.058020] dump_stack_lvl+0x64/0x84
[ 167.058065] dump_stack+0x14/0x34
[ 167.058100] __might_resched+0x144/0x180
[ 167.058140] __might_sleep+0x64/0xd0
[ 167.058171] slab_pre_alloc_hook.constprop.0+0xa8/0x110
[ 167.058202] __kmalloc_track_caller+0x74/0x2b0
[ 167.058233] kvasprintf+0xa4/0x190
[ 167.058261] kasprintf+0x58/0x90
[ 167.058285] tegra_xusb_find_port_node.isra.0+0x58/0xd0
[ 167.058334] tegra_xusb_find_port+0x38/0xa0
[ 167.058380] tegra_xusb_padctl_get_usb3_companion+0x38/0xd0
[ 167.058430] tegra_xhci_id_notify+0x8c/0x1e0
[ 167.058473] notifier_call_chain+0x88/0x100
[ 167.058506] atomic_notifier_call_chain+0x44/0x70
[ 167.058537] tegra_xusb_usb_phy_work+0x60/0xd0
[ 167.058581] process_one_work+0x1dc/0x4c0
[ 167.058618] worker_thread+0x54/0x410
[ 167.058650] kthread+0x188/0x1b0
[ 167.058672] ret_from_fork+0x10/0x20
The function tegra_xusb_padctl_get_usb3_companion eventually calls
tegra_xusb_find_port and this in turn calls kasprintf which might sleep
and so cannot be called from an atomic context.
Fix this by moving the call to tegra_xusb_padctl_get_usb3_companion to
the tegra_xhci_id_work function where it is really needed.
Signed-off-by: Wayne Chang <waynec@...dia.com>
Signed-off-by: Haotien Hsu <haotienh@...dia.com>
---
drivers/usb/host/xhci-tegra.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 1ff22f675930..af0185bacc70 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -2,7 +2,7 @@
/*
* NVIDIA Tegra xHCI host controller driver
*
- * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2014 Google, Inc.
*/
@@ -1360,6 +1360,10 @@ static void tegra_xhci_id_work(struct work_struct *work)
mutex_unlock(&tegra->lock);
+ tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
+ tegra->padctl,
+ tegra->otg_usb2_port);
+
if (tegra->host_mode) {
/* switch to host mode */
if (tegra->otg_usb3_port >= 0) {
@@ -1474,9 +1478,6 @@ static int tegra_xhci_id_notify(struct notifier_block *nb,
}
tegra->otg_usb2_port = tegra_xusb_get_usb2_port(tegra, usbphy);
- tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
- tegra->padctl,
- tegra->otg_usb2_port);
tegra->host_mode = (usbphy->last_event == USB_EVENT_ID) ? true : false;
--
2.25.1
Powered by blists - more mailing lists