From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8CFC53A6F0A for ; Tue, 28 Jul 2026 05:57:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785218223; cv=none; b=rfekHNTa/V6zCrwc51/XmvY/Zl1IhfGx2wYvVljW7VE3Re6w6uUi90rPXOe9DXfzOg+C0j2Bmd7IEjfn6dIrxnpRj4p45DA27WsLOOQ+lwoE5iqThHbwMR1mNmu4qL1LKhs5PMA/WM5abUpbQ6opPEYcIgk9c4T4Ln/debokxhQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785218223; c=relaxed/simple; bh=2blZB1jV12eZ/5s7gEzk8tvSAxwkiIstgao6aHPqp2Y=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=coZe/3eub+uhFeXq4vC6IXh6IZDucLcswrWZOE0OvjTK2+GMCZPdKphHKTTbMojr7a/AIqK3rKXYIPc6CXVLs45Tq/PQeV14sQtWJ6nNYurAk5DLy5lC6E9Ke0k2ymHEg0brc+5VrSrbWALjDdIzuyUV2wQisAtBgCAStCCLQ4k= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=M2J7ZNOj; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=GyVVt95y; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="M2J7ZNOj"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="GyVVt95y" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66S3abtC1303539 for ; Tue, 28 Jul 2026 05:57:00 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= F+odnqadZBL3FcgD3fTy4z7A88GEP8qiW9be37JO80U=; b=M2J7ZNOjbhORguU/ /IABY3powGCGKcXMlgHwuH63ep/j4C8mL2b+lpeUUI1LO8I+SZdfZsOu3P0njWrG QbJvEeCcTi1IWGD1J3GFFwwLl9HEOIq7oEL9vaxDXW5Pex0+NCnRDZW0zoOlQp35 fMwrPLQ9QDBsWk8haEGr6eXHN26qqXJwfz4cxNWTt+EUmMv1pcwuKMzns2K5033P EmGkKkBt+E+oFb98OLgHqIdOuwyZSVi4DkmBqmeF8/pG+vzyxntgW9J51xP9HG8N w5hfT2C6Kx0ewwDNBzSMPAHV5DRyqUTT7an1zX8k8tZeTwtqrxbi6HPROoHL09WF 9An0Aw== Received: from mail-pl1-f198.google.com (mail-pl1-f198.google.com [209.85.214.198]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4fpbp8aqtd-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Tue, 28 Jul 2026 05:57:00 +0000 (GMT) Received: by mail-pl1-f198.google.com with SMTP id d9443c01a7336-2cc88e22f92so80017815ad.1 for ; Mon, 27 Jul 2026 22:57:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1785218220; x=1785823020; darn=vger.kernel.org; h=content-transfer-encoding:content-type:in-reply-to:content-language :from:references:cc:to:subject:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to:content-type; bh=F+odnqadZBL3FcgD3fTy4z7A88GEP8qiW9be37JO80U=; b=GyVVt95yfbpf9sovznAeNqEj/fArAVhIII1Xc1+Pp9AOCBIO7DVRZX7yvz2yiBfpbG NIRO+AFouZz2SDVuXdvLbNE0mLeJkUfv8PqIlqfm8uWrGLB8VeeC7JJ3NecI2d5LbtVJ zGskDohCIEL2t6FxP3UvGrTRe684perRcrJ/fzSu2rjqSDqHUqfZIkYLRk9a0njpDpwP pit+HBegtbRim8Z/p2TNo8FgqL8SzeoS8x7MyW1CVXiaMeX6HHqZH8SiRi8VLEJm4Tdf NvAJ7+eou0HuLtcY3qeJrVHraPot65BgZfNhtowyCI/btdOeXZD8XVWWMsOHaLLeHbbQ qsuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785218220; x=1785823020; h=content-transfer-encoding:content-type:in-reply-to:content-language :from:references:cc:to:subject:user-agent:mime-version:date :message-id:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=F+odnqadZBL3FcgD3fTy4z7A88GEP8qiW9be37JO80U=; b=fNln6Dhgmz7cR8QfqZFHpwgrw5sIxmhD1lKngVSjUwok1kGuncjiAK534/cMNblKTd W0WlDycLEDFWpC3dFljW5cAhq7KZi2SzUlsQ6fKRDIiHaMnethCMrZ5WnlPH7a2KRiZE lxDrXJfJC/5q82epttoP907dsk9CKYRjmf4LVXfeqJlSg6WxbGacvAR1LHNSZZS0TuYz dcvAi4zOwtoo3cIfsllb65rVtP8upwueP9FOaWlrp5AUHDpESeHE9sKj4A+5jrqV9nkO I1ujLn8Y1b/6lkRgSYgP24SlN6GxXTy2XP738zkwy8BYAteOgCAd0gcwj6Us4wrjqrrS EmRg== X-Forwarded-Encrypted: i=1; AHgh+RoSCPWBSFDK8alH1du7Q5GbyxF03TkGQbo2nkdOC2uPDpFAEioP4UKdhXpkDD8p02n6/dkUkHxq4umsA9I=@vger.kernel.org X-Gm-Message-State: AOJu0YxV9cu/cRO44+ao169zi3s+Lt7//dVtL0dBW1ZIi9dEUGxl+JCI xQJIc1vOHKYXd6UslbHHXOndDnF3efyi9ufhDwoyxKIjgk66xhDGq7+xotfoZKbEDZz0XNB5/ac y8GB4OoFU9fSwh3wBppZohc6qLFdNF9KBtrSEJ9jzXlnEvzVRtadrJH4RhJJWclOwinI= X-Gm-Gg: AR+sD12fK+OZrjRWUcpKKJl2AKgtFuh7M19dODUiW8ni9+NLQxsxeuwXxu9KFcb46UR efA1Ew85WTWx7v3HKsg/yhMQPzfggbiKxQtgA0IPJ6PTHrzGmHIcfy7x9VjYkZy+39/kYLQJ9yX h0DvLbxFOE9LBGa1OkmqttKZv3moKKW+2piXZsLLqPouI/Pbw5XI4mFjXw2FIfZpQc1tashqYZ1 cgTmBTdmWxE6b/+jDeNfakggxkEuIpLEtFCjttrXtpfUBvglSXvQg4KkIROWaegdU1Z+7YQcVsZ z5g4g7TUSxS+ekgcUyy2SUfhMKoF7ElN6G/mL6/yBsWey6mkHFhe2b1UVAi6sf1qaeXdLW2xkNg /SpuYRfZXYn4FGvbKBgRGuhL8f03UM47Vr7kwezu8MNoP24rU9tQlKJzKRTEnoLJyLER7GLwKfg == X-Received: by 2002:a17:903:2a88:b0:2c9:ae0b:61e3 with SMTP id d9443c01a7336-2d015b145bcmr11801145ad.2.1785218219829; Mon, 27 Jul 2026 22:56:59 -0700 (PDT) X-Received: by 2002:a17:903:2a88:b0:2c9:ae0b:61e3 with SMTP id d9443c01a7336-2d015b145bcmr11800865ad.2.1785218219347; Mon, 27 Jul 2026 22:56:59 -0700 (PDT) Received: from [10.133.33.251] (tpe-colo-wan-fw-bordernet.qualcomm.com. [103.229.16.4]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2cfde7bc347sm45843315ad.40.2026.07.27.22.56.57 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 27 Jul 2026 22:56:59 -0700 (PDT) Message-ID: <1e19adf8-d3cd-47c8-a986-05faae7af3c5@oss.qualcomm.com> Date: Tue, 28 Jul 2026 13:56:55 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v7] wifi: ath11k: fix resource leak on error in ext IRQ setup To: ZhaoJinming , Jeff Johnson Cc: linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, linux-kernel@vger.kernel.org References: <20260728031335.3818736-1-zhaojinming@uniontech.com> From: Baochen Qiang Content-Language: en-US In-Reply-To: <20260728031335.3818736-1-zhaojinming@uniontech.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Proofpoint-Spam-Info: AW1haW4tMjYwNzI4MDA1MiBTYWx0ZWRfXxRqexYurxjUF nKVUqyWxRZn7eHVShblmfpPiUYS9U07bcBj5coKP3UzzazT9MzB8IzRkp+82skdC4jTn8zs1n9Z 2iDKwLwZQJ8RQxRpUPpJMjks9TEUkSw= X-Proofpoint-GUID: AqkOhp0juVoU9hjM_f2b-CSaoHYhspVq X-Proofpoint-ORIG-GUID: AqkOhp0juVoU9hjM_f2b-CSaoHYhspVq X-Authority-Analysis: v=2.4 cv=KLJqylFo c=1 sm=1 tr=0 ts=6a6844ac cx=c_pps a=MTSHoo12Qbhz2p7MsH1ifg==:117 a=nuhDOHQX5FNHPW3J6Bj6AA==:17 a=IkcTkHD0fZMA:10 a=RAioF0-LDSMA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=YMgV9FUhrdKAYTUUvYB2:22 a=VwQbUJbxAAAA:8 a=EUspDBNiAAAA:8 a=iHwBjlyiAAAA:8 a=X7nvTDC9Kz5FJV0lFOkA:9 a=QEXdDO2ut3YA:10 a=GvdueXVYPmCkWapjIL-Q:22 a=uNSKXYNwxGiU6LD0JREI:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzI4MDA1MiBTYWx0ZWRfX6MXUOtN6i4C8 DDqCfsJWncixn8fvSMAT8EyZhT8xm8/j6QBtBf/EdBQwxlPAFY9xIOo70j4/5TCa42gIHnrcZ4Q hsHOh1Bn9dpGpXoOwR7ayDyxhXIb6yWdYes7luf5VG4bC8EVb80odU4HrFzcYJ+V97LZamz7FU/ a8LGpnnzFI9zXCsMIya+B7qasZJ1IBQs5ahyMCh5kUDekBgzK5TEyRp6f+A1Kk2CkOeq9qrQvzB wZTNkdwX4AJOc/GApbl+DIV7QqybSkuyzQXlgCIwfKb+b8JOn7ekXFc8KFwmeOY7TFPmjc/zcQA gfO9sQWoT/p7W3kZBOcA5J/v8Cz6kslXEPGtIjVaZyH1XH4Q8MOhEalgBQKfAhwrgoyPoguJKX7 RRYiQsPv6dPcnFyk2u0FJ+Ezm6WqFbpFSj/vufLnRWBtxoPY2RWdQtPKgk06m5zPeBHsYZNXS+B QUV+19f/uxrKUGel3CA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-28_01,2026-07-27_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 spamscore=0 impostorscore=0 lowpriorityscore=0 malwarescore=0 adultscore=0 bulkscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607280052 On 7/28/2026 11:13 AM, ZhaoJinming wrote: > In ath11k_ahb_config_irq(), when a CE request_irq() fails, the function > returns the error immediately without freeing the CE IRQs that were > successfully registered in previous loop iterations. The probe error > path does not call ath11k_ahb_free_irq() either, so the previously > registered CE IRQ handlers remain attached to the interrupt lines and > are never released. > > In ath11k_ahb_config_ext_irq(), when an external request_irq() fails, > the error is only logged and the loop continues. The function then > returns 0 indicating success, leaving the device in a partially > configured state where some external IRQs are not registered. This > causes enable_irq()/disable_irq()/free_irq() to be called on > unregistered IRQs during runtime and remove/shutdown, triggering > WARN_ON(!desc->action), and missing interrupt handlers lead to data > loss. > > Additionally, if alloc_netdev_dummy() fails for a later IRQ group, the > function returns -ENOMEM without freeing the ext IRQs and napi_ndev > that were successfully set up for earlier groups. > > Fix all three issues: propagate the error up to the caller and unwind > all successfully registered IRQs and allocated resources on failure. > Also move ab->irq_num[irq_idx] assignment after request_irq() succeeds > in the ext IRQ path to match the CE IRQ path and avoid storing a stale > IRQ number on failure. > > Link: https://lore.kernel.org/all/b6903572-52cc-4c41-b9cf-5845e387c176@oss.qualcomm.com/ this is not the right way to track old versions. If want to do that the right place is in the changelog. Note if you use b4 tool this tracking burden can be done automatically. > Signed-off-by: ZhaoJinming > --- > > Changes in v7: > - Resend in a new thread. No content changes from v6. I mean here. > > Changes in v6: > - Move ab->irq_num[irq_idx] = irq after request_irq() succeeds in the > ext IRQ path to match the CE IRQ logic and avoid storing a stale IRQ > number on failure. > > Changes in v5: > - Resend as a fresh thread. No content changes from v4. > > Changes in v4: > - Drop the napi_ndev NULL guard in ath11k_ahb_free_ext_irq_grp() as it > is unreachable in all existing call paths. A silent guard against an > impossible condition hides bugs instead of exposing them. > > Changes in v3: > - Extract ath11k_ahb_free_ext_irq_grp() to handle per-group ext IRQ > cleanup and refactor ath11k_ahb_free_ext_irq() to use it. > - On request_irq() failure in ath11k_ahb_config_ext_irq(), immediately > clean up the current group via ath11k_ahb_free_ext_irq_grp() before > jumping to the error label to unwind earlier groups. > - Move u32 num_irq declaration before the irq_grp assignment to follow > declaration-before-statement ordering. > - Extract ath11k_ahb_free_ce_irqs() to handle partial/full CE IRQ cleanup > and refactor ath11k_ahb_free_irq() to use it, replacing the duplicated > err_ce_irq cleanup loop in ath11k_ahb_config_irq(). > > Changes in v2: > - Move `irq_grp` declaration from for-loop body to function scope to fix > compile error in err_request_irq error path. > - Set ret = -ENOMEM before goto err_request_irq on alloc_netdev_dummy() > failure to avoid returning uninitialized value. > - When ath11k_ahb_config_ext_irq() fails, unwind the already-registered > CE IRQs via a shared err_ce_irq cleanup path to avoid leaking them. > > diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c > index 1e1dea485760..ec5bf5c9fd79 100644 > --- a/drivers/net/wireless/ath/ath11k/ahb.c > +++ b/drivers/net/wireless/ath/ath11k/ahb.c > @@ -431,36 +431,44 @@ static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) > ab->qmi.service_ins_id = ab->hw_params.qmi_service_ins_id; > } > > -static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) > +static void ath11k_ahb_free_ext_irq_grp(struct ath11k_base *ab, > + struct ath11k_ext_irq_grp *irq_grp) > { > - int i, j; > - > - for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { > - struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; > + int j; > > - for (j = 0; j < irq_grp->num_irq; j++) > - free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); > + for (j = 0; j < irq_grp->num_irq; j++) > + free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); > > - netif_napi_del(&irq_grp->napi); > - free_netdev(irq_grp->napi_ndev); > - } > + netif_napi_del(&irq_grp->napi); > + free_netdev(irq_grp->napi_ndev); > } > > -static void ath11k_ahb_free_irq(struct ath11k_base *ab) > +static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) > { > - int irq_idx; > int i; > > - if (ab->hw_params.hybrid_bus_type) > - return ath11k_pcic_free_irq(ab); > + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) > + ath11k_ahb_free_ext_irq_grp(ab, &ab->ext_irq_grp[i]); > +} > > - for (i = 0; i < ab->hw_params.ce_count; i++) { > +static void ath11k_ahb_free_ce_irqs(struct ath11k_base *ab, int max_idx) > +{ > + int irq_idx, i; > + > + for (i = 0; i < max_idx; i++) { > if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR) > continue; > irq_idx = ATH11K_IRQ_CE0_OFFSET + i; > free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); > } > +} > + > +static void ath11k_ahb_free_irq(struct ath11k_base *ab) > +{ > + if (ab->hw_params.hybrid_bus_type) > + return ath11k_pcic_free_irq(ab); > > + ath11k_ahb_free_ce_irqs(ab, ab->hw_params.ce_count); > ath11k_ahb_free_ext_irq(ab); > } > > @@ -524,20 +532,25 @@ static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg) > static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab) > { > struct ath11k_hw_params *hw = &ab->hw_params; > + struct ath11k_ext_irq_grp *irq_grp; > int i, j; > int irq; > int ret; > > for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { > - struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; > u32 num_irq = 0; > > + irq_grp = &ab->ext_irq_grp[i]; > + > irq_grp->ab = ab; > irq_grp->grp_id = i; > > irq_grp->napi_ndev = alloc_netdev_dummy(0); > - if (!irq_grp->napi_ndev) > - return -ENOMEM; > + if (!irq_grp->napi_ndev) { > + ret = -ENOMEM; > + irq_grp->num_irq = 0; > + goto err_request_irq; > + } > > netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi, > ath11k_ahb_ext_grp_napi_poll); > @@ -585,14 +598,11 @@ static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab) > } > } > } > - irq_grp->num_irq = num_irq; > - > - for (j = 0; j < irq_grp->num_irq; j++) { > + for (j = 0; j < num_irq; j++) { > int irq_idx = irq_grp->irqs[j]; > > irq = platform_get_irq_byname(ab->pdev, > irq_name[irq_idx]); > - ab->irq_num[irq_idx] = irq; > irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY); > ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler, > IRQF_TRIGGER_RISING, > @@ -600,11 +610,24 @@ static int ath11k_ahb_config_ext_irq(struct ath11k_base *ab) > if (ret) { > ath11k_err(ab, "failed request_irq for %d\n", > irq); > + irq_grp->num_irq = j; > + ath11k_ahb_free_ext_irq_grp(ab, irq_grp); > + goto err_request_irq; > } > + ab->irq_num[irq_idx] = irq; > } > + > + irq_grp->num_irq = num_irq; > } > > return 0; > + > +err_request_irq: > + for (i--; i >= 0; i--) { > + irq_grp = &ab->ext_irq_grp[i]; > + ath11k_ahb_free_ext_irq_grp(ab, irq_grp); > + } > + return ret; > } > > static int ath11k_ahb_config_irq(struct ath11k_base *ab) > @@ -629,16 +652,24 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab) > ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler, > IRQF_TRIGGER_RISING, irq_name[irq_idx], > ce_pipe); > - if (ret) > + if (ret) { > + ath11k_err(ab, "failed request_irq for %d\n", irq); > + ath11k_ahb_free_ce_irqs(ab, i); > return ret; > + } > > ab->irq_num[irq_idx] = irq; > } > > /* Configure external interrupts */ > ret = ath11k_ahb_config_ext_irq(ab); > + if (ret) { > + ath11k_err(ab, "failed to configure ext irq: %d\n", ret); > + ath11k_ahb_free_ce_irqs(ab, ab->hw_params.ce_count); > + return ret; > + } > > - return ret; > + return 0; > } > > static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,