From ef4c7b06207d2387d8aafcb7ade47d819d6429e7 Mon Sep 17 00:00:00 2001 From: haotienh Date: Thu, 19 Jun 2025 07:35:44 +0000 Subject: [PATCH] NVIDIA: SAUCE: xhci: tegra: Fix irq_dispose_mapping() warning Fix calling irq_dispose_mapping() on non-existent IRQ in USB wake function error handling. [ 3.652047] Call trace: [ 3.652051] irq_domain_free_irqs+0x174/0x1b4 [ 3.652054] irq_dispose_mapping+0x9c/0x16c [ 3.652056] tegra_xusb_probe+0x4c8/0x1040 This patch also improves the USB wake function to support individual wake events. Bug 5310553 Bug 5360357 Change-Id: Ibd1cb44a012e99dd7a0b80b581bd249d6249784d Signed-off-by: haotienh Reviewed-on: https://git-master.nvidia.com/r/c/3rdparty/canonical/linux-noble/+/3396822 GVS: buildbot_gerritrpt Reviewed-by: Henry Lin Reviewed-by: Wayne Chang Reviewed-by: WK Tsai Reviewed-by: svcacv (cherry picked from commit c5d11a1e13c5946cd5efc5e0becea1ab6c124d95) Reviewed-on: https://git-master.nvidia.com/r/c/3rdparty/canonical/linux-noble/+/3397611 Tested-by: Kartik Rajput Reviewed-by: Kartik Rajput --- drivers/usb/host/xhci-tegra.c | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 0c9b155fa045..1698d18750b4 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -2166,18 +2166,18 @@ static int tegra_xhci_padctl_notify(struct notifier_block *nb, return NOTIFY_OK; } -static void tegra_xusb_setup_wakeup(struct platform_device *pdev, struct tegra_xusb *tegra) +static int tegra_xusb_setup_wakeup(struct platform_device *pdev, struct tegra_xusb *tegra) { int i; if (device_property_read_bool(tegra->dev, "disable-wake")) - return; + return 0; tegra->wake_irqs = devm_kcalloc(tegra->dev, tegra->soc->num_wakes, sizeof(*tegra->wake_irqs), GFP_KERNEL); if (!tegra->wake_irqs) - return; + return -ENOMEM; for (i = 0; i < tegra->soc->num_wakes; i++) { char irq_name[] = "wakeX"; @@ -2186,19 +2186,16 @@ static void tegra_xusb_setup_wakeup(struct platform_device *pdev, struct tegra_x snprintf(irq_name, sizeof(irq_name), "wake%d", i); tegra->wake_irqs[i] = platform_get_irq_byname(pdev, irq_name); if (tegra->wake_irqs[i] < 0) - goto error; + continue; data = irq_get_irq_data(tegra->wake_irqs[i]); - if (!data) - goto error; + if (!data) { + irq_dispose_mapping(tegra->wake_irqs[i]); + tegra->wake_irqs[i] = -ENXIO; + continue; + } irq_set_irq_type(tegra->wake_irqs[i], irqd_get_trigger_type(data)); } - return; - -error: - for (i = 0; i < tegra->soc->num_wakes && tegra->wake_irqs[i] >= 0; i++) - irq_dispose_mapping(tegra->wake_irqs[i]); - devm_kfree(tegra->dev, tegra->wake_irqs); - tegra->wake_irqs = NULL; + return 0; } static int tegra_xusb_probe(struct platform_device *pdev) @@ -2260,8 +2257,11 @@ static int tegra_xusb_probe(struct platform_device *pdev) if (IS_ERR(tegra->padctl)) return PTR_ERR(tegra->padctl); - if (tegra->soc->num_wakes && !tegra->soc->is_xhci_vf) - tegra_xusb_setup_wakeup(pdev, tegra); + if (tegra->soc->num_wakes && !tegra->soc->is_xhci_vf) { + err = tegra_xusb_setup_wakeup(pdev, tegra); + if (err) + goto put_padctl; + } np = of_parse_phandle(pdev->dev.of_node, "nvidia,xusb-padctl", 0); if (!np) { @@ -2652,7 +2652,8 @@ static void tegra_xusb_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); for (i = 0; i < tegra->soc->num_wakes && tegra->wake_irqs; i++) - irq_dispose_mapping(tegra->wake_irqs[i]); + if (tegra->wake_irqs[i] >= 0) + irq_dispose_mapping(tegra->wake_irqs[i]); pm_runtime_put(&pdev->dev); @@ -3130,7 +3131,8 @@ out: if (enable_irq_wake(tegra->padctl_irq)) dev_err(dev, "failed to enable padctl wakes\n"); for (i = 0; i < tegra->soc->num_wakes && tegra->wake_irqs; i++) - enable_irq_wake(tegra->wake_irqs[i]); + if (tegra->wake_irqs[i] >= 0) + enable_irq_wake(tegra->wake_irqs[i]); } } @@ -3163,7 +3165,8 @@ static __maybe_unused int tegra_xusb_resume(struct device *dev) if (disable_irq_wake(tegra->padctl_irq)) dev_err(dev, "failed to disable padctl wakes\n"); for (i = 0; i < tegra->soc->num_wakes && tegra->wake_irqs; i++) - disable_irq_wake(tegra->wake_irqs[i]); + if (tegra->wake_irqs[i] >= 0) + disable_irq_wake(tegra->wake_irqs[i]); } tegra->suspended = false; mutex_unlock(&tegra->lock);