summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>2026-08-19 16:32:15 +0530
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>2026-09-09 10:54:48 -0700
commit9a78703ec4a895bd2e99bf43bd18d76683126c19 (patch)
tree59ba36aca5df3a262036720e21eaedd03f90a9a5
parent12ca935af2e68447e9218a615ebbb5ff7faf1554 (diff)
downloadlinux-next-9a78703ec4a895bd2e99bf43bd18d76683126c19.tar.gz
linux-next-9a78703ec4a895bd2e99bf43bd18d76683126c19.zip
wifi: ath12k: Free allocated external IRQs on request_irq() failure
When external IRQ configuration fails, the driver does not release all IRQs that were successfully requested before the failure. This can leak IRQ resources during probe failure. Free previously requested external IRQs when external IRQ configuration fails. Also remove the NAPI instance with netif_napi_del() before freeing the associated netdev to properly clean up the NAPI resources. Store the IRQ number only after request_irq() succeeds to avoid recording an IRQ that was not successfully requested. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Link: https://patch.msgid.link/20260819110215.2485514-3-aaradhana.sahu@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index 1525e6866cf4..af0e882fd0b5 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -326,11 +326,11 @@ static void ath12k_pci_free_ce_irq(struct ath12k_base *ab, int num_ce)
}
}
-static void ath12k_pci_free_ext_irq(struct ath12k_base *ab)
+static void ath12k_pci_free_ext_irq(struct ath12k_base *ab, int num_ext_irq_grp)
{
int i, j;
- for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
+ for (i = 0; i < num_ext_irq_grp; i++) {
struct ath12k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
for (j = 0; j < irq_grp->num_irq; j++)
@@ -344,7 +344,7 @@ static void ath12k_pci_free_ext_irq(struct ath12k_base *ab)
static void ath12k_pci_free_irq(struct ath12k_base *ab)
{
ath12k_pci_free_ce_irq(ab, ab->hw_params->ce_count);
- ath12k_pci_free_ext_irq(ab);
+ ath12k_pci_free_ext_irq(ab, ATH12K_EXT_IRQ_GRP_NUM_MAX);
}
static void ath12k_pci_ce_irq_enable(struct ath12k_base *ab, u16 ce_id)
@@ -600,8 +600,6 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
irq = ath12k_pci_get_msi_irq(ab->dev, vector);
- ab->irq_num[irq_idx] = irq;
-
ath12k_dbg(ab, ATH12K_DBG_PCI,
"irq:%d group:%d\n", irq, i);
@@ -612,22 +610,24 @@ static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)
if (ret) {
ath12k_err(ab, "failed request irq %d: %d\n",
vector, ret);
- goto fail_request;
+
+ for (n = 0; n < j; n++)
+ free_irq(ab->irq_num[irq_grp->irqs[n]], irq_grp);
+
+ netif_napi_del(&ab->ext_irq_grp[i].napi);
+ free_netdev(ab->ext_irq_grp[i].napi_ndev);
+ goto fail_allocate;
}
+
+ ab->irq_num[irq_idx] = irq;
}
ath12k_pci_ext_grp_disable(irq_grp);
}
return 0;
-fail_request:
- /* i ->napi_ndev was properly allocated. Free it also */
- i += 1;
fail_allocate:
- for (n = 0; n < i; n++) {
- irq_grp = &ab->ext_irq_grp[n];
- free_netdev(irq_grp->napi_ndev);
- }
+ ath12k_pci_free_ext_irq(ab, i);
return ret;
}