From nobody Sun Dec 14 05:56:39 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 CAE0C335086 for ; Wed, 5 Nov 2025 17:22:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363354; cv=none; b=qPtASyIH8VfmCYFuGDqnLWK83bD0nLYvEjMpo77IkB9tMCO+z1uo+9pnAlIN6CKR/j0jIYipNdHADzNAaq7803SNtymCxfGu8EbJ7s5pqDo5bFMoCq4WyZitLvf3iATj8iq/RBCglcDmKGHsDKqvLXN3YaCRT99S1i5sq5OIUiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363354; c=relaxed/simple; bh=5KQqtMoLixSs1ft+qPtIztREZGWdfQkFybMN6GvgnbQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KXXsv2ErNQpPxQA4GYywojKP89SUE1eaPC82h6q9k5Iu8GwYdJcIRYqGDRFjjhj0NiDrGShWcFi574Wgf6c7I6F0qpQSGwyyJ2y0C5MUxHU/BJMJSqYBuzDTHiss8/FqXOk85kKzcw39AuvfaV6kiyrKZGCJrc7wUJzXFtu85Is= 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=kOfttD1z; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=YidjOKqW; arc=none smtp.client-ip=205.220.180.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="kOfttD1z"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="YidjOKqW" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A5D5pOG4056238 for ; Wed, 5 Nov 2025 17:22:31 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=KeVshtHCZ35 30glQM5ntY9XB0frGjHklSQGuyQPrwt4=; b=kOfttD1zkm8Ev963yoRjYpGiYt3 R6rM5KnMY9Cajzp1MllrziV9MwpsaP2jOjsGVxFBfQkoHV5Q8piejBG31Qyxncbf Y2kn5UUlUXbOb9g1k5rv3m+V+YTcBFwJxf2ILkzpuT4Rg4nGEWBIB09UPIn9kNLK RJxEUWUpesYrXFXSNOcr4wBWhfW/iKH4D3TrRziFdMSCOTF5iTQbJpdMQVY95SZH c/jBgP5lCB3iz1mlgi/VWW3OPnsd672VmOTMbqQTqOsuAa18/fHlrL/vmEtYjsv3 MkO9EYutYeeMFwhJwEwvWyq69gzI6bLl1dWIFis47BRx/uxfkQSXdKz2Krw== Received: from mail-pf1-f200.google.com (mail-pf1-f200.google.com [209.85.210.200]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a7yp622qq-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:31 +0000 (GMT) Received: by mail-pf1-f200.google.com with SMTP id d2e1a72fcca58-77f610f7325so93904b3a.1 for ; Wed, 05 Nov 2025 09:22:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363351; x=1762968151; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KeVshtHCZ3530glQM5ntY9XB0frGjHklSQGuyQPrwt4=; b=YidjOKqWc0FgKwGed4cFZm3WCU129nYh4oQdeUFWDALNpnz/1IrOC/w+rXKvKHPMx6 SLYr5jxWKSzFJjdF7Ztg7XAnErCYTKCl7+d1Ucy//iM9pRGdgrF2k8QZTabD73EZ/bVk RUl0VCcllgD5msIKBhTRyV2OBOBNUsLBpODx59rmbBG7LF3jwZUAgPfsQnwqMG9XPhkd SiqLLYLvFXdSC4aZ6uR3fy3ieRN1Sei/pZUcjpD0QlImdbWpmOtjvzozUHLsNNh1k2Xb tcrF6PevuPjDd6MIg1A3MBU22f0yf1wdrLZVIQ5/4rKkrie/yCc/HjiINLOfDNfIkgJR aPbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363351; x=1762968151; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KeVshtHCZ3530glQM5ntY9XB0frGjHklSQGuyQPrwt4=; b=av/+qt/YoQzG6errTGFzCLbHqZr/tbBfhMkUvBGnBcxD/x6ONh96l/I1K/2055c8MG O1eLHEYxaETjQNyXOnkugUYN8QsHMKsOhEkTXIcj8pYZfZGhdis0hWrUW/P42iAYDpEn m+X+BL8FaLXP7z2Z9O4llzaXq8ScUo9KhOxXVFkkUxlNZ4pLLe8v0uVlpIf1ncoSGqK5 ctUOmO8S8MtIAQSYxTycZUU38mSFrOucJiEHQhinpz6kSMPlrYqbGzaMsFR7iPnSMjsX dE/+jUNoiMBiHY4I5OmxvljhSmpKQy2ZrCNrLIzVOPnDpZjtDmsocB32Kf6pBW/N3WKO HrWA== X-Forwarded-Encrypted: i=1; AJvYcCU9+aNGl9U/TcZIeNmxa8+7iqmWby6AVTgJxVkOFxiSpfKPmUz/IONLwHBZZvmqlCYrJ9InEHx0myg+VBY=@vger.kernel.org X-Gm-Message-State: AOJu0Yyrjc4IIy4UgA0F/yDjoed8NJ0q25nyhUN0904Eyiy7Q5Hynubp n0pHItftR1a/oyqPykba1Tq0H+sRms9td9O8NXtv9yakx5WD0YqKU5ELKddoy9n2qDvO1UH9FIS 4s2Ux3s8pBuLxox9Ce6CdW3UDOl63exZETwMPxLnsx4AS9MJfWox/nOoQOAqjKT1XCqk= X-Gm-Gg: ASbGncsrNgvgZEiZPds7Y4/BEKen6sSRQoLkicoiA2Ke9yuz3Gjk9DrCwl3UcZGb0rJ yG+O6AW+E4d9r/3vf/YOVQZlDPJ6Id+FZ7HocBiFJBK8eWk+Dku0jpMzySgxeFNHV/MDu4tI+1D vbCjlH+/N2xcsTKxeQJFoBbVZWZH6sKlDSBYw7C5pCXILTdK5RqnE21RkJt6xjHXPLt+s+Udu13 zY6IJQLOienqwkY2Xo4fw5YRirzqb9FREu4M5itzUXc36nAtm9FWob9bSOF/wn0NuvQ1j8dOt/b TKhweS8xtSjg/f9Bk4GByiu5tm7K5JujfNGS0glQ9hOcKNsdc0BHDJ/ljJ3NGp/RvuhgTwtNz4v TRwPkAPIQb78fAh4xGwpqvEBV4vd0E2YDTfqywL0b2Th5 X-Received: by 2002:a05:6a00:c93:b0:780:fff4:f7db with SMTP id d2e1a72fcca58-7ae1ef998cfmr4995604b3a.15.1762363350269; Wed, 05 Nov 2025 09:22:30 -0800 (PST) X-Google-Smtp-Source: AGHT+IEFRrgFLPe3pW+2d0sEVrNGAKtbS4pj4oNIhdOGG8J99aitMheEbN0HxSSBTQEUVmRT8qNGAQ== X-Received: by 2002:a05:6a00:c93:b0:780:fff4:f7db with SMTP id d2e1a72fcca58-7ae1ef998cfmr4995550b3a.15.1762363349636; Wed, 05 Nov 2025 09:22:29 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:28 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 1/6] wifi: ath11k: Add initialization and deinitialization sequence for CFR module Date: Wed, 5 Nov 2025 09:22:21 -0800 Message-Id: <20251105172226.3182968-2-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: VGqFMPLyxSAlY8EpTseGlzpgv2YJ2v14 X-Proofpoint-ORIG-GUID: VGqFMPLyxSAlY8EpTseGlzpgv2YJ2v14 X-Authority-Analysis: v=2.4 cv=TsrrRTXh c=1 sm=1 tr=0 ts=690b87d7 cx=c_pps a=mDZGXZTwRPZaeRUbqKGCBw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=sTJiG90S0w3vqaoQ0_0A:9 a=zc0IvFSfCIW2DFIPzwfm:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfX7zPbF0ctLfhI v0M+N2u0sDkOSIAP0degn7tLv6VSwOleEfR65DU0OfUGaUzGcoL8JXeb9VrMofLJFVtODHGa3EO g6yvyTuhLKsFaLrSyPNlDGGfm3kZW1JJZYYjcqhVa6DdHzPysknqoFe75pCaCluKN+rTWdUTYvj j0zJ6i/M4fe1JZqhSMmOX1ZI7X71OkKX42kdhuxaSly1PyW9JxTllyMHDhzSUCQ/maoLBMKVnuz pB5utGs1sBlrP5cehCyaA7PkNtGQ7/AF2iKJBUIiPJB8OI8pdIpZMnchDtC16ZFPZxOf4FPGWBy 1nVBO7H9FD6hQtsKUh0L4La0KKIp2CYZU0oDa7k2nGAi2wk9tjgMVJprTnCwAQwgN5cegghisi0 xhHGunU+1b+SDzbsRkkVP6tRTAs3gg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 spamscore=0 phishscore=0 priorityscore=1501 lowpriorityscore=0 bulkscore=0 impostorscore=0 adultscore=0 clxscore=1015 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 Content-Type: text/plain; charset="utf-8" From: Venkateswara Naralasetty Channel Frequency Response (CFR) module will be initialized only when the following criteria passes: * Enabled CFR support for the hardware through the hardware param 'cfr_support' * WMI service enabled for the CFR support 'WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT' Also, provide a configuration option CONFIG_ATH11K_CFR to enable CFR feature support during the compilation time. CFR module initialization includes Direct Buffer(DB) ring initialization where hardware uses the DB ring buffers to copy CFR data to host. Number of buffers and buffer size of the ring is based on the DB ring capabilities advertised by the firmware through WMI service ready. Also ring configurations are sent to firmware through ath11k_dbring_wmi_cfg_setup(). Predefine ath11k_cfr_dma_hdr, ath11k_look_up_table, and ath11k_cfr structs and fields for subsequent patches. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/Kconfig | 11 ++ drivers/net/wireless/ath/ath11k/Makefile | 1 + drivers/net/wireless/ath/ath11k/cfr.c | 170 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/cfr.h | 85 ++++++++++++ drivers/net/wireless/ath/ath11k/core.c | 41 +++++- drivers/net/wireless/ath/ath11k/core.h | 8 +- drivers/net/wireless/ath/ath11k/dbring.c | 40 ++++-- drivers/net/wireless/ath/ath11k/dbring.h | 6 +- drivers/net/wireless/ath/ath11k/hal.c | 3 +- drivers/net/wireless/ath/ath11k/hw.h | 5 +- drivers/net/wireless/ath/ath11k/wmi.h | 1 + 11 files changed, 354 insertions(+), 17 deletions(-) create mode 100644 drivers/net/wireless/ath/ath11k/cfr.c create mode 100644 drivers/net/wireless/ath/ath11k/cfr.h diff --git a/drivers/net/wireless/ath/ath11k/Kconfig b/drivers/net/wireless= /ath/ath11k/Kconfig index 659ef134ef16..47dfd39caa89 100644 --- a/drivers/net/wireless/ath/ath11k/Kconfig +++ b/drivers/net/wireless/ath/ath11k/Kconfig @@ -58,3 +58,14 @@ config ATH11K_SPECTRAL Enable ath11k spectral scan support =20 Say Y to enable access to the FFT/spectral data via debugfs. + +config ATH11K_CFR + bool "ath11k channel frequency response support" + depends on ATH11K_DEBUGFS + depends on RELAY + help + Enable ath11k channel frequency response dump support. + This option exposes debugfs nodes that will allow the user + to enable, disable, and dump data. + + Say Y to enable CFR data dump collection via debugfs. diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireles= s/ath/ath11k/Makefile index d9092414b362..b1435fcf3e1b 100644 --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile @@ -28,6 +28,7 @@ ath11k-$(CONFIG_THERMAL) +=3D thermal.o ath11k-$(CONFIG_ATH11K_SPECTRAL) +=3D spectral.o ath11k-$(CONFIG_PM) +=3D wow.o ath11k-$(CONFIG_DEV_COREDUMP) +=3D coredump.o +ath11k-$(CONFIG_ATH11K_CFR) +=3D cfr.o =20 obj-$(CONFIG_ATH11K_AHB) +=3D ath11k_ahb.o ath11k_ahb-y +=3D ahb.o diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c new file mode 100644 index 000000000000..78e356672eba --- /dev/null +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear +/* + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include +#include "core.h" +#include "debug.h" + +static int ath11k_cfr_process_data(struct ath11k *ar, + struct ath11k_dbring_data *param) +{ + return 0; +} + +void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, + u32 buf_id) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + + if (cfr->lut) + cfr->lut[buf_id].dbr_address =3D paddr; +} + +static void ath11k_cfr_ring_free(struct ath11k *ar) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + + ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring); + ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring); +} + +static int ath11k_cfr_ring_alloc(struct ath11k *ar, + struct ath11k_dbring_cap *db_cap) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + int ret; + + ret =3D ath11k_dbring_srng_setup(ar, &cfr->rx_ring, + ATH11K_CFR_NUM_RING_ENTRIES, + db_cap->min_elem); + if (ret) { + ath11k_warn(ar->ab, "failed to setup db ring: %d\n", ret); + return ret; + } + + ath11k_dbring_set_cfg(ar, &cfr->rx_ring, + ATH11K_CFR_NUM_RESP_PER_EVENT, + ATH11K_CFR_EVENT_TIMEOUT_MS, + ath11k_cfr_process_data); + + ret =3D ath11k_dbring_buf_setup(ar, &cfr->rx_ring, db_cap); + if (ret) { + ath11k_warn(ar->ab, "failed to setup db ring buffer: %d\n", ret); + goto srng_cleanup; + } + + ret =3D ath11k_dbring_wmi_cfg_setup(ar, &cfr->rx_ring, WMI_DIRECT_BUF_CFR= ); + if (ret) { + ath11k_warn(ar->ab, "failed to setup db ring cfg: %d\n", ret); + goto buffer_cleanup; + } + + return 0; + +buffer_cleanup: + ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring); +srng_cleanup: + ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring); + return ret; +} + +void ath11k_cfr_deinit(struct ath11k_base *ab) +{ + struct ath11k_cfr *cfr; + struct ath11k *ar; + int i; + + if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) || + !ab->hw_params.cfr_support) + return; + + for (i =3D 0; i < ab->num_radios; i++) { + ar =3D ab->pdevs[i].ar; + cfr =3D &ar->cfr; + + if (!cfr->enabled) + continue; + + ath11k_cfr_ring_free(ar); + + spin_lock_bh(&cfr->lut_lock); + kfree(cfr->lut); + cfr->lut =3D NULL; + cfr->enabled =3D false; + spin_unlock_bh(&cfr->lut_lock); + } +} + +int ath11k_cfr_init(struct ath11k_base *ab) +{ + struct ath11k_dbring_cap db_cap; + struct ath11k_cfr *cfr; + u32 num_lut_entries; + struct ath11k *ar; + int i, ret; + + if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) || + !ab->hw_params.cfr_support) + return 0; + + for (i =3D 0; i < ab->num_radios; i++) { + ar =3D ab->pdevs[i].ar; + cfr =3D &ar->cfr; + + ret =3D ath11k_dbring_get_cap(ar->ab, ar->pdev_idx, + WMI_DIRECT_BUF_CFR, &db_cap); + if (ret) + continue; + + idr_init(&cfr->rx_ring.bufs_idr); + spin_lock_init(&cfr->rx_ring.idr_lock); + spin_lock_init(&cfr->lock); + spin_lock_init(&cfr->lut_lock); + + num_lut_entries =3D min_t(u32, CFR_MAX_LUT_ENTRIES, db_cap.min_elem); + cfr->lut =3D kcalloc(num_lut_entries, sizeof(*cfr->lut), + GFP_KERNEL); + if (!cfr->lut) { + ret =3D -ENOMEM; + goto err; + } + + ret =3D ath11k_cfr_ring_alloc(ar, &db_cap); + if (ret) { + ath11k_warn(ab, "failed to init cfr ring for pdev %d: %d\n", + i, ret); + spin_lock_bh(&cfr->lut_lock); + kfree(cfr->lut); + cfr->lut =3D NULL; + cfr->enabled =3D false; + spin_unlock_bh(&cfr->lut_lock); + goto err; + } + + cfr->lut_num =3D num_lut_entries; + cfr->enabled =3D true; + } + + return 0; + +err: + for (i =3D i - 1; i >=3D 0; i--) { + ar =3D ab->pdevs[i].ar; + cfr =3D &ar->cfr; + + if (!cfr->enabled) + continue; + + ath11k_cfr_ring_free(ar); + + spin_lock_bh(&cfr->lut_lock); + kfree(cfr->lut); + cfr->lut =3D NULL; + cfr->enabled =3D false; + spin_unlock_bh(&cfr->lut_lock); + } + return ret; +} diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h new file mode 100644 index 000000000000..3534176c3e01 --- /dev/null +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* + * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef ATH11K_CFR_H +#define ATH11K_CFR_H + +#include "dbring.h" +#include "wmi.h" + +#define ATH11K_CFR_NUM_RESP_PER_EVENT 1 +#define ATH11K_CFR_EVENT_TIMEOUT_MS 1 +#define ATH11K_CFR_NUM_RING_ENTRIES 1 + +#define CFR_MAX_LUT_ENTRIES 136 + +#define HOST_MAX_CHAINS 8 + +struct ath11k_cfr_dma_hdr { + u16 info0; + u16 info1; + u16 sw_peer_id; + u16 phy_ppdu_id; +}; + +struct ath11k_look_up_table { + bool dbr_recv; + bool tx_recv; + u8 *data; + u32 data_len; + u16 dbr_ppdu_id; + u16 tx_ppdu_id; + dma_addr_t dbr_address; + struct ath11k_cfr_dma_hdr hdr; + u64 txrx_tstamp; + u64 dbr_tstamp; + u32 header_length; + u32 payload_length; + struct ath11k_dbring_element *buff; +}; + +struct ath11k_cfr { + struct ath11k_dbring rx_ring; + /* Protects cfr data */ + spinlock_t lock; + /* Protect for lut entries */ + spinlock_t lut_lock; + struct ath11k_look_up_table *lut; + u32 lut_num; + u64 tx_evt_cnt; + u64 dbr_evt_cnt; + u64 release_cnt; + u64 tx_peer_status_cfr_fail; + u64 tx_evt_status_cfr_fail; + u64 tx_dbr_lookup_fail; + u64 last_success_tstamp; + u64 flush_dbr_cnt; + u64 clear_txrx_event; + u64 cfr_dma_aborts; + bool enabled; +}; + +#ifdef CONFIG_ATH11K_CFR +int ath11k_cfr_init(struct ath11k_base *ab); +void ath11k_cfr_deinit(struct ath11k_base *ab); +void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, + u32 buf_id); +#else +static inline int ath11k_cfr_init(struct ath11k_base *ab) +{ + return 0; +} + +static inline void ath11k_cfr_deinit(struct ath11k_base *ab) +{ +} + +static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar, + dma_addr_t paddr, u32 buf_id) +{ +} +#endif /* CONFIG_ATH11K_CFR */ +#endif /* ATH11K_CFR_H */ diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/= ath/ath11k/core.c index 2810752260f2..71926a774f57 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights res= erved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 @@ -126,6 +125,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .smp2p_wow_exit =3D false, .support_dual_stations =3D false, .pdev_suspend =3D false, + .cfr_support =3D true, + .cfr_num_stream_bufs =3D 255, + .cfr_stream_buf_size =3D 8200, }, { .hw_rev =3D ATH11K_HW_IPQ6018_HW10, @@ -211,6 +213,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D false, .support_dual_stations =3D false, .pdev_suspend =3D false, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "qca6390 hw2.0", @@ -301,6 +306,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D true, .support_dual_stations =3D true, .pdev_suspend =3D false, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "qcn9074 hw1.0", @@ -385,6 +393,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D false, .support_dual_stations =3D false, .pdev_suspend =3D false, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "wcn6855 hw2.0", @@ -475,6 +486,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D true, .support_dual_stations =3D true, .pdev_suspend =3D false, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "wcn6855 hw2.1", @@ -563,6 +577,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D true, .support_dual_stations =3D true, .pdev_suspend =3D false, + .cfr_support =3D true, + .cfr_num_stream_bufs =3D 255, + .cfr_stream_buf_size =3D 8200, }, { .name =3D "wcn6750 hw1.0", @@ -646,6 +663,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D true, .support_dual_stations =3D false, .pdev_suspend =3D true, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .hw_rev =3D ATH11K_HW_IPQ5018_HW10, @@ -729,6 +749,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D false, .support_dual_stations =3D false, .pdev_suspend =3D false, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "qca2066 hw2.1", @@ -818,6 +841,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .smp2p_wow_exit =3D false, .support_fw_mac_sequence =3D true, .support_dual_stations =3D true, + .cfr_support =3D false, + .cfr_num_stream_bufs =3D 0, + .cfr_stream_buf_size =3D 0, }, { .name =3D "qca6698aq hw2.1", @@ -906,6 +932,9 @@ static const struct ath11k_hw_params ath11k_hw_params[]= =3D { .support_fw_mac_sequence =3D true, .support_dual_stations =3D true, .pdev_suspend =3D false, + .cfr_support =3D true, + .cfr_num_stream_bufs =3D 255, + .cfr_stream_buf_size =3D 8200, }, }; =20 @@ -1945,8 +1974,16 @@ static int ath11k_core_pdev_create(struct ath11k_bas= e *ab) goto err_thermal_unregister; } =20 + ret =3D ath11k_cfr_init(ab); + if (ret) { + ath11k_err(ab, "failed to init cfr %d\n", ret); + goto err_spectral_unregister; + } + return 0; =20 +err_spectral_unregister: + ath11k_spectral_deinit(ab); err_thermal_unregister: ath11k_thermal_unregister(ab); err_mac_unregister: @@ -1996,6 +2033,7 @@ static void ath11k_core_pdev_suspend_target(struct at= h11k_base *ab) =20 static void ath11k_core_pdev_destroy(struct ath11k_base *ab) { + ath11k_cfr_deinit(ab); ath11k_spectral_deinit(ab); ath11k_thermal_unregister(ab); ath11k_mac_unregister(ab); @@ -2208,6 +2246,7 @@ static int ath11k_core_reconfigure_on_crash(struct at= h11k_base *ab) mutex_lock(&ab->core_lock); ath11k_thermal_unregister(ab); ath11k_dp_pdev_free(ab); + ath11k_cfr_deinit(ab); ath11k_spectral_deinit(ab); ath11k_ce_cleanup_pipes(ab); ath11k_wmi_detach(ab); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/= ath/ath11k/core.h index e8780b05ce11..40fb7cee3e43 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights res= erved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 #ifndef ATH11K_CORE_H @@ -35,6 +35,7 @@ #include "wow.h" #include "fw.h" #include "coredump.h" +#include "cfr.h" =20 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) =20 @@ -795,6 +796,11 @@ struct ath11k { bool ps_state_enable; bool ps_timekeeper_enable; s8 max_allowed_tx_power; + +#ifdef CONFIG_ATH11K_CFR + struct ath11k_cfr cfr; +#endif + bool cfr_enabled; }; =20 struct ath11k_band_cap { diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireles= s/ath/ath11k/dbring.c index 520d8b8662a2..ed2b781a6bab 100644 --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights res= erved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 @@ -37,10 +36,10 @@ static void ath11k_dbring_fill_magic_value(struct ath11= k *ar, memset32(buffer, ATH11K_DB_MAGIC_VALUE, size); } =20 -static int ath11k_dbring_bufs_replenish(struct ath11k *ar, - struct ath11k_dbring *ring, - struct ath11k_dbring_element *buff, - enum wmi_direct_buffer_module id) +int ath11k_dbring_bufs_replenish(struct ath11k *ar, + struct ath11k_dbring *ring, + struct ath11k_dbring_element *buff, + enum wmi_direct_buffer_module id) { struct ath11k_base *ab =3D ar->ab; struct hal_srng *srng; @@ -80,6 +79,9 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar, goto err_idr_remove; } =20 + if (id =3D=3D WMI_DIRECT_BUF_CFR) + ath11k_cfr_lut_update_paddr(ar, paddr, buf_id); + buff->paddr =3D paddr; =20 cookie =3D FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) | @@ -155,12 +157,11 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar, enum wmi_direct_buffer_module id) { struct ath11k_wmi_pdev_dma_ring_cfg_req_cmd param =3D {}; - int ret; + int ret, i; =20 if (id >=3D WMI_DIRECT_BUF_MAX) return -EINVAL; =20 - param.pdev_id =3D DP_SW2HW_MACID(ring->pdev_id); param.module_id =3D id; param.base_paddr_lo =3D lower_32_bits(ring->refill_srng.paddr); param.base_paddr_hi =3D upper_32_bits(ring->refill_srng.paddr); @@ -173,10 +174,23 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar, param.num_resp_per_event =3D ring->num_resp_per_event; param.event_timeout_ms =3D ring->event_timeout_ms; =20 - ret =3D ath11k_wmi_pdev_dma_ring_cfg(ar, ¶m); - if (ret) { - ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); - return ret; + /* For single pdev, 2GHz and 5GHz use one DBR. */ + if (ar->ab->hw_params.single_pdev_only) { + for (i =3D 0; i < ar->ab->target_pdev_count; i++) { + param.pdev_id =3D ar->ab->target_pdev_ids[i].pdev_id; + ret =3D ath11k_wmi_pdev_dma_ring_cfg(ar, ¶m); + if (ret) { + ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); + return ret; + } + } + } else { + param.pdev_id =3D DP_SW2HW_MACID(ring->pdev_id); + ret =3D ath11k_wmi_pdev_dma_ring_cfg(ar, ¶m); + if (ret) { + ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); + return ret; + } } =20 return 0; @@ -285,6 +299,10 @@ int ath11k_dbring_buffer_release_event(struct ath11k_b= ase *ab, pdev_idx =3D ev->fixed.pdev_id; module_id =3D ev->fixed.module_id; =20 + if (ab->hw_params.single_pdev_only && + pdev_idx < ab->target_pdev_count) + pdev_idx =3D 0; + if (pdev_idx >=3D ab->num_radios) { ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx); return -EINVAL; diff --git a/drivers/net/wireless/ath/ath11k/dbring.h b/drivers/net/wireles= s/ath/ath11k/dbring.h index 2f93b78a50df..0a380120f7a0 100644 --- a/drivers/net/wireless/ath/ath11k/dbring.h +++ b/drivers/net/wireless/ath/ath11k/dbring.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 #ifndef ATH11K_DBRING_H @@ -61,6 +61,10 @@ int ath11k_dbring_set_cfg(struct ath11k *ar, u32 event_timeout_ms, int (*handler)(struct ath11k *, struct ath11k_dbring_data *)); +int ath11k_dbring_bufs_replenish(struct ath11k *ar, + struct ath11k_dbring *ring, + struct ath11k_dbring_element *buff, + enum wmi_direct_buffer_module id); int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar, struct ath11k_dbring *ring, enum wmi_direct_buffer_module id); diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/a= th/ath11k/hal.c index 0c797b8d0a27..e821e5a62c1c 100644 --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights res= erved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include @@ -184,7 +183,7 @@ static const struct hal_srng_config hw_srng_config_temp= late[] =3D { }, { /* RXDMA DIR BUF */ .start_ring_id =3D HAL_SRNG_RING_ID_RXDMA_DIR_BUF, - .max_rings =3D 1, + .max_rings =3D 2, .entry_size =3D 8 >> 2, /* TODO: Define the struct */ .lmac_ring =3D true, .ring_dir =3D HAL_SRNG_DIR_SRC, diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/at= h/ath11k/hw.h index 52d9f4c13b13..e13ca02a9d05 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights res= erved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 #ifndef ATH11K_HW_H @@ -228,6 +228,9 @@ struct ath11k_hw_params { bool support_fw_mac_sequence; bool support_dual_stations; bool pdev_suspend; + bool cfr_support; + u32 cfr_num_stream_bufs; + u32 cfr_stream_buf_size; }; =20 struct ath11k_hw_ops { diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/a= th/ath11k/wmi.h index 0f0de24a3840..7a55fe0879c0 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -981,6 +981,7 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, + WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE =3D 0xa8, WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD =3D 0xbc, WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC =3D 0xbe, WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT =3D 0xc6, --=20 2.34.1 From nobody Sun Dec 14 05:56:39 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 9D93A338917 for ; Wed, 5 Nov 2025 17:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363357; cv=none; b=DDGktnUZFGZZ8p3LnpVU2JjvMCOPK0AaZJRVQn0PBTcDYSr+PRvklGQjos5uphEFcvEFEk7a9BDzFonCY2yHN8paxU+DRSMTXgWp7NX6R46kfiq4bSDi2AXGT6olq3momcafQd7TDgFArqxc9s7bm2RGwgC8+8TwWxRm7QBin3E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363357; c=relaxed/simple; bh=6ofBZkgnuKeikocs39ch7Y+goxcJRQOOAc7ECI7ZU6U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dRY0k3yzXusTzgTHWmKzkrlu6smCVLvfiCLiOz+j1k87gdv79zQNBAapIchCzuhxzsj0yiYDvcetiboDpDaZic7JyHkshfmML7bDVvYwEkt8yJ0gQ/OCxIcesXcuhX8krM2WDqI+4+ev5nuvqF9O5c+MW1P/5eumXBQHYiNXYu0= 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=j5iwViok; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=KNdHxWJ6; arc=none smtp.client-ip=205.220.180.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="j5iwViok"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="KNdHxWJ6" Received: from pps.filterd (m0279869.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A5H6Gpn1542497 for ; Wed, 5 Nov 2025 17:22:33 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=fPbfG9sCcTZ PXhCpjHpnFRU9uZKUodfoJEY25YPmkf0=; b=j5iwViok0jjC0bNOtpOgmVIxhiX pibe6WlbTN5udLGTkGYRUCIR1YB/+VxWLFwjE7zha3b3uPZOQ5zZm6n7AHvs1SJv vHJskk4QbIoHB+fttuH8LdE6Kt/omUgjUXRv69bVhvzcHKskCAGGuU7vpHrML37E 1mcTycHPaWffPWeNj/JCdXDSt+zP35x60hIMWIJht+Nw2wqyNrruGWlehE2fYu7y O3wmpF5rOrrQr8teaCsmgO83R3WnHfcUTVWvynUZ+Ua9y5W88fso6z7TQPVvR8vJ P7xC2gih7oapd2gQSAy8T0XYFEPcdfL7+buQHU58+OM9Ptqf65n0KweDXIA== Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a8apgr1uu-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:32 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-34176460924so94961a91.3 for ; Wed, 05 Nov 2025 09:22:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363352; x=1762968152; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fPbfG9sCcTZPXhCpjHpnFRU9uZKUodfoJEY25YPmkf0=; b=KNdHxWJ6zrvkOZM2TbSJ3FZ25HMR4+4gITp0R2uWcmwIrZbQRz9FyX/LeUhRA4z4Fi Co5EIFprnAx88PrH8dAFvl87wzYhy6Q6LuseekbBjZcpb+pXWZ9FJGhhPomYi4wqLuGH pU4KRMM6o0+ncUt1UJqVgrEyoje77bWw3UEBAW9V/Qy1TqvsWheRZeL+P7qVyxCUd69Z DlhSN1nWzDQcE1sLD7ERAnyRP9miibTMKZK76LItexQ3uwa/PsBN8rYnh/Sb9OYXcyzi owYrFR36L/tlKdFR+qifRtRKs1ecssgLp+p8GqGYyxbg+2jBvKjN8YJvyvlDgDGpbiZv lqKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363352; x=1762968152; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fPbfG9sCcTZPXhCpjHpnFRU9uZKUodfoJEY25YPmkf0=; b=dcohSnrv1Jpll5yEcrO586inEP/o07IgoqPspJYSTa68BI5QfjC/RkTitKXzFrwk2q fgy7eqElBj3iocw2mWeJF7FqxliYKx5txZ/931W6ZKlCAJoJTGXEvJBiQf9QUPPdIFOO huI0XcScn29i9E2qumbdULnh5I24T12uoP6Y1vjlkXHxVgLPTd2NyjOy6i3zuNKRzaZ1 2QzroMvsCEaoYzZpB8wnExZY96rcLq307jfv03rD6/2u/bNd03IGpJPqdHJEocVW1cU/ pBf5I9bkDXkSLISlYTd9ocm0TVedXy/xR2ItQ/IkWaiV4ROd4QlgVJ4voZ8+EmwofnG7 Jx5w== X-Forwarded-Encrypted: i=1; AJvYcCU9GLUz6ao9HJuTkK1SmA0K0ueveEryUe9CwIXcXgnOLDGhRp3I3YPEnaJAK4uIQmoQUoaRnfIZ/V6G4dY=@vger.kernel.org X-Gm-Message-State: AOJu0Yw6gEnQuVi5Sbu2WLwvr2gEl40WDn5RESwzVPvMMBPCnw0QJJOn w5cckJARG2F0jbjbVqPmk7+JjgiKNQqrkrv+6nFEviiM5tblR9xb2/hvUNSH+clP3a9v/iw7MM5 DJGVc/4K/zMKdf1UVnh3osGqrqub95zw64ApwpC6qPS6Kfpe99plDsuEeaIu1K3ZVuH4= X-Gm-Gg: ASbGnctlA0vDIUufEPwptJ9JM2eXg9MmyL8DqB3STNNqw9IrYjS9Q0V8W98KQjfpfHp BO3GIRuAWsXWZN3u4zQ5Qyfvn6r2xcY5IoN2h7xNfesmZabfi8VpwtD1tdEnco/f9rnCgStbs7X OI28MOW/eqcqGUOIdZ9yXWrT4sIH0Am+lnIjGtR4btAh+JVJ8vSwRQa6BGI4Hzt73ZU+jGBnJvc f2SMBRSok7A6NnYmbDuTFSzsAXS8q6nzGjZd4/PCvAHvj9EwS2FVDJqYxJuYeF6wFQ+0pCKwsJb lExhK3wGF9dPBAP512xFTdKchjNOQzYMP7x8nXo24J82VfcwcCkSgtKnJ6JPUIQh0rJR0OGQcfY vhYkib7LBfDXbOyDBjMyjdF23aOqXB/6TPkxCSfYVsx8t X-Received: by 2002:a17:90a:e705:b0:32a:34d8:33d3 with SMTP id 98e67ed59e1d1-341a6b0d548mr4741807a91.0.1762363351576; Wed, 05 Nov 2025 09:22:31 -0800 (PST) X-Google-Smtp-Source: AGHT+IHUOQRLzu+WY5Ade/pSsfUUKW5MyofKkt0ydn6yc9pbg3ZegpKK28GN8hMKfizGjjLHEkJ7Wg== X-Received: by 2002:a17:90a:e705:b0:32a:34d8:33d3 with SMTP id 98e67ed59e1d1-341a6b0d548mr4741766a91.0.1762363350944; Wed, 05 Nov 2025 09:22:30 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:30 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 2/6] wifi: ath11k: Register debugfs for CFR configuration Date: Wed, 5 Nov 2025 09:22:22 -0800 Message-Id: <20251105172226.3182968-3-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfX+QsuQB3Hx0yh kBXJ2QCwYh4VRtj+kC+0cZAo6sXKS6xsKLknK6mVXk4pYncM9r10dC5oar9CusGnGrDoOy/ksVv kM9dIwEvfr6jUpcevoiq61F4vr25fQiiTq1LEZFezt72RHh1XF86w0CAOHNctPpTq9Xi0XVf7+R EeDtLQupl6TEKpj0RlYihsVOAClotUDr28gut/4IO9mrHt5oSDieRbM4cXGOQMOdG94NPEb20lZ HJ+vJOu/HeT0zD7bO5Q9ENloYZ43HwFCI96t7Twn15FAHbm/41uU9WLBiAxkwU5OAWoRT8RrOHu H33On/XAk9IQlaHPqAXF2zz/n0QByTJ0uA819tFbeXWMCJpzn/1kTk3m7wdBqTQNWIIiKbF8Py3 akAJpAoUeHpeCfLPR5XdQohrKtSP4A== X-Authority-Analysis: v=2.4 cv=LoCfC3dc c=1 sm=1 tr=0 ts=690b87d9 cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=dJ9JZWBW9j4LC2dvM44A:9 a=uKXjsCUrEbL0IQVhDsJ9:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-GUID: B5uzbw8idvmRbqJKDcTIYdeOw8mfAMtc X-Proofpoint-ORIG-GUID: B5uzbw8idvmRbqJKDcTIYdeOw8mfAMtc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 malwarescore=0 suspectscore=0 spamscore=0 phishscore=0 impostorscore=0 bulkscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 Content-Type: text/plain; charset="utf-8" From: Venkateswara Naralasetty Provide debugfs interfaces support to config CFR from the user space. To enable/disable cfr feature use command, echo > /sys/kernel/debug/ieee80211/phyX/ath11k/enable_cfr where, val: 0 to disable CFR and 1 to enable CFR. To enable CFR capture for associated peers, echo " " > /sys/kernel/debug/ieee80211/phyX/netdev\:wlanx/stations//cfr_capture val: 0 - stop CFR capture 1 - start CFR capture bw: CFR capture bandwidth 0 - 20MHZ 1 - 40MHZ 2 - 80MHZ Periodicity: Periodicity at which hardware is expected to collect CFR dump. 0 - single shot capture. non zero - for Periodic captures (value must be multiple of 10 ms) method: Method used by hardware to collect the CFR dump. 0 - from the ACKs of QOS NULL packets. Also, send the required WMI commands to the firmware based on the CFR configurations. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/cfr.c | 191 ++++++++++++++++++ drivers/net/wireless/ath/ath11k/cfr.h | 41 ++++ drivers/net/wireless/ath/ath11k/core.h | 11 + drivers/net/wireless/ath/ath11k/debugfs_sta.c | 143 ++++++++++++- drivers/net/wireless/ath/ath11k/mac.c | 2 + drivers/net/wireless/ath/ath11k/wmi.c | 41 ++++ drivers/net/wireless/ath/ath11k/wmi.h | 50 ++++- 7 files changed, 476 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c index 78e356672eba..bf0b880e8746 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.c +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -14,6 +14,193 @@ static int ath11k_cfr_process_data(struct ath11k *ar, return 0; } =20 +void ath11k_cfr_decrement_peer_count(struct ath11k *ar, + struct ath11k_sta *arsta) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + + spin_lock_bh(&cfr->lock); + + if (arsta->cfr_capture.cfr_enable) + cfr->cfr_enabled_peer_cnt--; + + spin_unlock_bh(&cfr->lock); +} + +static enum ath11k_wmi_cfr_capture_bw +ath11k_cfr_bw_to_fw_cfr_bw(enum ath11k_cfr_capture_bw bw) +{ + switch (bw) { + case ATH11K_CFR_CAPTURE_BW_20: + return WMI_PEER_CFR_CAPTURE_BW_20; + case ATH11K_CFR_CAPTURE_BW_40: + return WMI_PEER_CFR_CAPTURE_BW_40; + case ATH11K_CFR_CAPTURE_BW_80: + return WMI_PEER_CFR_CAPTURE_BW_80; + default: + return WMI_PEER_CFR_CAPTURE_BW_MAX; + } +} + +static enum ath11k_wmi_cfr_capture_method +ath11k_cfr_method_to_fw_cfr_method(enum ath11k_cfr_capture_method method) +{ + switch (method) { + case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME: + return WMI_CFR_CAPTURE_METHOD_NULL_FRAME; + case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE: + return WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE; + case ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP: + return WMI_CFR_CAPTURE_METHOD_PROBE_RESP; + default: + return WMI_CFR_CAPTURE_METHOD_MAX; + } +} + +int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, + struct ath11k_sta *arsta, + struct ath11k_per_peer_cfr_capture *params, + const u8 *peer_mac) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + struct wmi_peer_cfr_capture_conf_arg arg; + enum ath11k_wmi_cfr_capture_bw bw; + enum ath11k_wmi_cfr_capture_method method; + int ret =3D 0; + + if (cfr->cfr_enabled_peer_cnt >=3D ATH11K_MAX_CFR_ENABLED_CLIENTS && + !arsta->cfr_capture.cfr_enable) { + ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n", + cfr->cfr_enabled_peer_cnt); + return -ENOSPC; + } + + if (params->cfr_enable =3D=3D arsta->cfr_capture.cfr_enable && + params->cfr_period =3D=3D arsta->cfr_capture.cfr_period && + params->cfr_method =3D=3D arsta->cfr_capture.cfr_method && + params->cfr_bw =3D=3D arsta->cfr_capture.cfr_bw) + return ret; + + if (!params->cfr_enable && !arsta->cfr_capture.cfr_enable) + return ret; + + bw =3D ath11k_cfr_bw_to_fw_cfr_bw(params->cfr_bw); + if (bw >=3D WMI_PEER_CFR_CAPTURE_BW_MAX) { + ath11k_warn(ar->ab, "FW doesn't support configured bw %d\n", + params->cfr_bw); + return -EINVAL; + } + + method =3D ath11k_cfr_method_to_fw_cfr_method(params->cfr_method); + if (method >=3D WMI_CFR_CAPTURE_METHOD_MAX) { + ath11k_warn(ar->ab, "FW doesn't support configured method %d\n", + params->cfr_method); + return -EINVAL; + } + + arg.request =3D params->cfr_enable; + arg.periodicity =3D params->cfr_period; + arg.bw =3D bw; + arg.method =3D method; + + ret =3D ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id, + peer_mac, &arg); + if (ret) { + ath11k_warn(ar->ab, + "failed to send cfr capture info: vdev_id %u peer %pM: %d\n", + arsta->arvif->vdev_id, peer_mac, ret); + return ret; + } + + spin_lock_bh(&cfr->lock); + + if (params->cfr_enable && + params->cfr_enable !=3D arsta->cfr_capture.cfr_enable) + cfr->cfr_enabled_peer_cnt++; + else if (!params->cfr_enable) + cfr->cfr_enabled_peer_cnt--; + + spin_unlock_bh(&cfr->lock); + + arsta->cfr_capture.cfr_enable =3D params->cfr_enable; + arsta->cfr_capture.cfr_period =3D params->cfr_period; + arsta->cfr_capture.cfr_method =3D params->cfr_method; + arsta->cfr_capture.cfr_bw =3D params->cfr_bw; + + return ret; +} + +static ssize_t ath11k_read_file_enable_cfr(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath11k *ar =3D file->private_data; + char buf[32] =3D {}; + size_t len; + + mutex_lock(&ar->conf_mutex); + len =3D scnprintf(buf, sizeof(buf), "%d\n", ar->cfr_enabled); + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t ath11k_write_file_enable_cfr(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k *ar =3D file->private_data; + u32 enable_cfr; + int ret; + + if (kstrtouint_from_user(ubuf, count, 0, &enable_cfr)) + return -EINVAL; + + guard(mutex)(&ar->conf_mutex); + + if (ar->state !=3D ATH11K_STATE_ON) + return -ENETDOWN; + + if (enable_cfr > 1) + return -EINVAL; + + if (ar->cfr_enabled =3D=3D enable_cfr) + return count; + + ret =3D ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE, + enable_cfr, ar->pdev->pdev_id); + if (ret) { + ath11k_warn(ar->ab, + "Failed to enable/disable per peer cfr %d\n", ret); + return ret; + } + + ar->cfr_enabled =3D enable_cfr; + + return count; +} + +static const struct file_operations fops_enable_cfr =3D { + .read =3D ath11k_read_file_enable_cfr, + .write =3D ath11k_write_file_enable_cfr, + .open =3D simple_open, + .owner =3D THIS_MODULE, + .llseek =3D default_llseek, +}; + +static void ath11k_cfr_debug_unregister(struct ath11k *ar) +{ + debugfs_remove(ar->cfr.enable_cfr); + ar->cfr.enable_cfr =3D NULL; +} + +static void ath11k_cfr_debug_register(struct ath11k *ar) +{ + ar->cfr.enable_cfr =3D debugfs_create_file("enable_cfr", 0600, + ar->debug.debugfs_pdev, ar, + &fops_enable_cfr); +} + void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, u32 buf_id) { @@ -88,6 +275,7 @@ void ath11k_cfr_deinit(struct ath11k_base *ab) if (!cfr->enabled) continue; =20 + ath11k_cfr_debug_unregister(ar); ath11k_cfr_ring_free(ar); =20 spin_lock_bh(&cfr->lut_lock); @@ -146,6 +334,8 @@ int ath11k_cfr_init(struct ath11k_base *ab) =20 cfr->lut_num =3D num_lut_entries; cfr->enabled =3D true; + + ath11k_cfr_debug_register(ar); } =20 return 0; @@ -158,6 +348,7 @@ int ath11k_cfr_init(struct ath11k_base *ab) if (!cfr->enabled) continue; =20 + ath11k_cfr_debug_unregister(ar); ath11k_cfr_ring_free(ar); =20 spin_lock_bh(&cfr->lut_lock); diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h index 3534176c3e01..7d161f7f7be8 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.h +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -14,10 +14,14 @@ #define ATH11K_CFR_EVENT_TIMEOUT_MS 1 #define ATH11K_CFR_NUM_RING_ENTRIES 1 =20 +#define ATH11K_MAX_CFR_ENABLED_CLIENTS 10 #define CFR_MAX_LUT_ENTRIES 136 =20 #define HOST_MAX_CHAINS 8 =20 +struct ath11k_sta; +struct ath11k_per_peer_cfr_capture; + struct ath11k_cfr_dma_hdr { u16 info0; u16 info1; @@ -48,6 +52,8 @@ struct ath11k_cfr { /* Protect for lut entries */ spinlock_t lut_lock; struct ath11k_look_up_table *lut; + struct dentry *enable_cfr; + u8 cfr_enabled_peer_cnt; u32 lut_num; u64 tx_evt_cnt; u64 dbr_evt_cnt; @@ -62,11 +68,32 @@ struct ath11k_cfr { bool enabled; }; =20 +enum ath11k_cfr_capture_method { + ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME, + ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE, + ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP, + ATH11K_CFR_CAPTURE_METHOD_MAX, +}; + +enum ath11k_cfr_capture_bw { + ATH11K_CFR_CAPTURE_BW_20, + ATH11K_CFR_CAPTURE_BW_40, + ATH11K_CFR_CAPTURE_BW_80, + ATH11K_CFR_CAPTURE_BW_MAX, +}; + #ifdef CONFIG_ATH11K_CFR int ath11k_cfr_init(struct ath11k_base *ab); void ath11k_cfr_deinit(struct ath11k_base *ab); void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, u32 buf_id); +void ath11k_cfr_decrement_peer_count(struct ath11k *ar, + struct ath11k_sta *arsta); +int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, + struct ath11k_sta *arsta, + struct ath11k_per_peer_cfr_capture *params, + const u8 *peer_mac); + #else static inline int ath11k_cfr_init(struct ath11k_base *ab) { @@ -81,5 +108,19 @@ static inline void ath11k_cfr_lut_update_paddr(struct a= th11k *ar, dma_addr_t paddr, u32 buf_id) { } + +static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar, + struct ath11k_sta *arsta) +{ +} + +static inline int +ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, + struct ath11k_sta *arsta, + struct ath11k_per_peer_cfr_capture *params, + const u8 *peer_mac) +{ + return 0; +} #endif /* CONFIG_ATH11K_CFR */ #endif /* ATH11K_CFR_H */ diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/= ath/ath11k/core.h index 40fb7cee3e43..3f41e6569a78 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -532,6 +532,13 @@ struct ath11k_per_ppdu_tx_stats { =20 DECLARE_EWMA(avg_rssi, 10, 8) =20 +struct ath11k_per_peer_cfr_capture { + enum ath11k_cfr_capture_method cfr_method; + enum ath11k_cfr_capture_bw cfr_bw; + u32 cfr_enable; + u32 cfr_period; +}; + struct ath11k_sta { struct ath11k_vif *arvif; =20 @@ -572,6 +579,10 @@ struct ath11k_sta { bool peer_current_ps_valid; =20 u32 bw_prev; + +#ifdef CONFIG_ATH11K_CFR + struct ath11k_per_peer_cfr_capture cfr_capture; +#endif }; =20 #define ATH11K_MIN_5G_FREQ 4150 diff --git a/drivers/net/wireless/ath/ath11k/debugfs_sta.c b/drivers/net/wi= reless/ath/ath11k/debugfs_sta.c index d89d0f28d890..dfb9d877d28a 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights res= erved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 @@ -240,6 +239,141 @@ static const struct file_operations fops_tx_stats =3D= { .llseek =3D default_llseek, }; =20 +#ifdef CONFIG_ATH11K_CFR +static ssize_t ath11k_dbg_sta_write_cfr_capture(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta =3D file->private_data; + struct ath11k_sta *arsta =3D ath11k_sta_to_arsta(sta); + struct ath11k *ar =3D arsta->arvif->ar; + struct ath11k_cfr *cfr =3D &ar->cfr; + struct wmi_peer_cfr_capture_conf_arg arg; + u32 cfr_capture_enable =3D 0, cfr_capture_bw =3D 0; + u32 cfr_capture_method =3D 0, cfr_capture_period =3D 0; + char buf[64] =3D {}; + int ret; + + simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); + + guard(mutex)(&ar->conf_mutex); + + if (ar->state !=3D ATH11K_STATE_ON) + return -ENETDOWN; + + if (!ar->cfr_enabled) + return -EINVAL; + + ret =3D sscanf(buf, "%u %u %u %u", &cfr_capture_enable, &cfr_capture_bw, + &cfr_capture_period, &cfr_capture_method); + + if (ret < 1 || (cfr_capture_enable && ret !=3D 4)) + return -EINVAL; + + if (cfr_capture_enable =3D=3D arsta->cfr_capture.cfr_enable && + (cfr_capture_period && + cfr_capture_period =3D=3D arsta->cfr_capture.cfr_period) && + cfr_capture_bw =3D=3D arsta->cfr_capture.cfr_bw && + cfr_capture_method =3D=3D arsta->cfr_capture.cfr_method) + return count; + + if (!cfr_capture_enable && + cfr_capture_enable =3D=3D arsta->cfr_capture.cfr_enable) + return count; + + if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE || + cfr_capture_bw > arsta->bw || + cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80 || + cfr_capture_method > ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE = || + cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX) + return -EINVAL; + + /* Target expects cfr period in multiple of 10 */ + if (cfr_capture_period % 10) { + ath11k_err(ar->ab, "periodicity should be 10x\n"); + return -EINVAL; + } + + if (ar->cfr.cfr_enabled_peer_cnt >=3D ATH11K_MAX_CFR_ENABLED_CLIENTS && + !arsta->cfr_capture.cfr_enable) { + ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n", + ar->cfr.cfr_enabled_peer_cnt); + return -EINVAL; + } + + if (!cfr_capture_enable) { + cfr_capture_bw =3D arsta->cfr_capture.cfr_bw; + cfr_capture_period =3D arsta->cfr_capture.cfr_period; + cfr_capture_method =3D arsta->cfr_capture.cfr_method; + } + + arg.request =3D cfr_capture_enable; + arg.periodicity =3D cfr_capture_period; + arg.bw =3D cfr_capture_bw; + arg.method =3D cfr_capture_method; + + ret =3D ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id, + sta->addr, &arg); + if (ret) { + ath11k_warn(ar->ab, + "failed to send cfr capture info: vdev_id %u peer %pM: %d\n", + arsta->arvif->vdev_id, sta->addr, ret); + return ret; + } + + spin_lock_bh(&ar->cfr.lock); + + if (cfr_capture_enable && + cfr_capture_enable !=3D arsta->cfr_capture.cfr_enable) + cfr->cfr_enabled_peer_cnt++; + else if (!cfr_capture_enable) + cfr->cfr_enabled_peer_cnt--; + + spin_unlock_bh(&ar->cfr.lock); + + arsta->cfr_capture.cfr_enable =3D cfr_capture_enable; + arsta->cfr_capture.cfr_period =3D cfr_capture_period; + arsta->cfr_capture.cfr_bw =3D cfr_capture_bw; + arsta->cfr_capture.cfr_method =3D cfr_capture_method; + + return count; +} + +static ssize_t ath11k_dbg_sta_read_cfr_capture(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta =3D file->private_data; + struct ath11k_sta *arsta =3D ath11k_sta_to_arsta(sta); + struct ath11k *ar =3D arsta->arvif->ar; + char buf[512] =3D {}; + int len =3D 0; + + mutex_lock(&ar->conf_mutex); + + len +=3D scnprintf(buf + len, sizeof(buf) - len, "cfr_enabled =3D %d\n", + arsta->cfr_capture.cfr_enable); + len +=3D scnprintf(buf + len, sizeof(buf) - len, "bandwidth =3D %d\n", + arsta->cfr_capture.cfr_bw); + len +=3D scnprintf(buf + len, sizeof(buf) - len, "period =3D %d\n", + arsta->cfr_capture.cfr_period); + len +=3D scnprintf(buf + len, sizeof(buf) - len, "cfr_method =3D %d\n", + arsta->cfr_capture.cfr_method); + + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_peer_cfr_capture =3D { + .write =3D ath11k_dbg_sta_write_cfr_capture, + .read =3D ath11k_dbg_sta_read_cfr_capture, + .open =3D simple_open, + .owner =3D THIS_MODULE, + .llseek =3D default_llseek, +}; +#endif /* CONFIG_ATH11K_CFR */ + static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -877,6 +1011,13 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *h= w, struct ieee80211_vif *vi debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta, &fops_htt_peer_stats_reset); =20 +#ifdef CONFIG_ATH11K_CFR + if (test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, + ar->ab->wmi_ab.svc_map)) + debugfs_create_file("cfr_capture", 0600, dir, sta, + &fops_peer_cfr_capture); +#endif/* CONFIG_ATH11K_CFR */ + debugfs_create_file("peer_ps_state", 0400, dir, sta, &fops_peer_ps_state); =20 diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/a= th/ath11k/mac.c index c6360d6a72bd..965c377cd8dc 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9979,6 +9979,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_h= w *hw, } spin_unlock_bh(&ar->ab->base_lock); mutex_unlock(&ar->ab->tbl_mtx_lock); + + ath11k_cfr_decrement_peer_count(ar, arsta); } else if (old_state =3D=3D IEEE80211_STA_AUTH && new_state =3D=3D IEEE80211_STA_ASSOC && (vif->type =3D=3D NL80211_IFTYPE_AP || diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/a= th/ath11k/wmi.c index edff6fb61344..846c9946a084 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -3941,6 +3941,47 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar= , u32 vdev_id, return 0; } =20 +int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar, + u32 vdev_id, const u8 *mac_addr, + struct wmi_peer_cfr_capture_conf_arg *arg) +{ + struct ath11k_pdev_wmi *wmi =3D ar->wmi; + struct wmi_peer_cfr_capture_cmd_fixed_param *cmd; + struct sk_buff *skb; + int ret; + + skb =3D ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd =3D (struct wmi_peer_cfr_capture_cmd_fixed_param *)skb->data; + cmd->tlv_header =3D FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_PEER_CFR_CAPTURE_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + memcpy(&cmd->mac_addr, mac_addr, ETH_ALEN); + cmd->request =3D arg->request; + cmd->vdev_id =3D vdev_id; + cmd->periodicity =3D arg->periodicity; + cmd->bandwidth =3D arg->bw; + cmd->capture_method =3D arg->method; + + ret =3D ath11k_wmi_cmd_send(ar->wmi, skb, WMI_PEER_CFR_CAPTURE_CMDID); + if (ret) { + ath11k_warn(ar->ab, + "WMI vdev %d failed to send peer cfr capture cmd: %d\n", + vdev_id, ret); + dev_kfree_skb(skb); + } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "WMI peer CFR capture cmd req %u id %u period %u bw %u mode %u\n", + arg->request, vdev_id, arg->periodicity, + arg->bw, arg->method); + + return ret; +} + int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id, struct sk_buff *tmpl) { diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/a= th/ath11k/wmi.h index 7a55fe0879c0..1562d169ba9a 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -362,6 +362,10 @@ enum wmi_tlv_cmd_id { WMI_PEER_REORDER_QUEUE_REMOVE_CMDID, WMI_PEER_SET_RX_BLOCKSIZE_CMDID, WMI_PEER_ANTDIV_INFO_REQ_CMDID, + WMI_PEER_RESERVED0_CMDID, + WMI_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMDID, + WMI_PEER_TID_CONFIGURATIONS_CMDID, + WMI_PEER_CFR_CAPTURE_CMDID, WMI_BCN_TX_CMDID =3D WMI_TLV_CMD(WMI_GRP_MGMT), WMI_PDEV_SEND_BCN_CMDID, WMI_BCN_TMPL_CMDID, @@ -3833,7 +3837,8 @@ struct wmi_scan_prob_req_oui_cmd { #define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8) #define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15) #define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20) -#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21) +#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21) +#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22) =20 struct wmi_mgmt_send_params { u32 tlv_header; @@ -4218,6 +4223,45 @@ enum cc_setting_code { */ }; =20 +enum ath11k_wmi_cfr_capture_bw { + WMI_PEER_CFR_CAPTURE_BW_20, + WMI_PEER_CFR_CAPTURE_BW_40, + WMI_PEER_CFR_CAPTURE_BW_80, + WMI_PEER_CFR_CAPTURE_BW_MAX, +}; + +enum ath11k_wmi_cfr_capture_method { + WMI_CFR_CAPTURE_METHOD_NULL_FRAME, + WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE, + WMI_CFR_CAPTURE_METHOD_PROBE_RESP, + WMI_CFR_CAPTURE_METHOD_MAX, +}; + +struct wmi_peer_cfr_capture_conf_arg { + enum ath11k_wmi_cfr_capture_bw bw; + enum ath11k_wmi_cfr_capture_method method; + u32 request; + u32 periodicity; +}; + +struct wmi_peer_cfr_capture_cmd_fixed_param { + u32 tlv_header; + u32 request; + struct wmi_mac_addr mac_addr; + u32 vdev_id; + u32 periodicity; + /* BW of measurement - of type enum ath11k_wmi_cfr_capture_bw */ + u32 bandwidth; + /* Method used to capture CFR - of type enum ath11k_wmi_cfr_capture_metho= d */ + u32 capture_method; +} __packed; + +#define WMI_PEER_CFR_CAPTURE_ENABLE 1 +#define WMI_PEER_CFR_CAPTURE_DISABLE 0 + +/*periodicity in ms */ +#define WMI_PEER_CFR_PERIODICITY_MAX 600000 + static inline enum cc_setting_code ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code) { @@ -6532,5 +6576,7 @@ bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *a= r); int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar, u32 vdev_id, struct ath11k_reg_tpc_power_info *param); - +int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar, + u32 vdev_id, const u8 *mac, + struct wmi_peer_cfr_capture_conf_arg *arg); #endif --=20 2.34.1 From nobody Sun Dec 14 05:56:39 2025 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 D154C338F26 for ; Wed, 5 Nov 2025 17:22:34 +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=1762363357; cv=none; b=RbFKpGXkJHpDXXEttsdm1tdfyCaTOxNeVK1fsGYBIgPw72Xl+nsXtvmmHp8MY7XKiP2hroLk/gEyBbIuHx+WEfGRDKkMMJB08Fuh3FndV43uNo7nPLNHYBCJbr8s6csX+qcD8BdibuME7bIANPZiNK4ef6xGi1jafGVWpOu4CVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363357; c=relaxed/simple; bh=4RVJZpkDmGjO+msxIE19nXLYcV6yuaVmFY24Hl9aYxo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=cYT2yOfY0k0uQCWDAz4QIXu9xiaCSQQ0eOW1IezxNZg6oYtxEITihcRqbPj1B1KZU3qee1+R8Fh7KYIB7jwEAdLzm5v8pTTvrmPOBEKvJgK5sGXivH/BkqNrTPV/0MUEbXV4Nw07xpAUM3A7OwiOrchpt7DTrUvjIDCmyyemP6U= 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=TFRkpsTH; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=WNuC2B7y; 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="TFRkpsTH"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="WNuC2B7y" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A5E8CQr876658 for ; Wed, 5 Nov 2025 17:22:34 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= M+34BFVYwe9cWjXpD4W2ZZm1y1yXgMO3SO03SfHDt+M=; b=TFRkpsTHodp6hGM6 WsPaPmLOGVIftKTTERtg5MXAPlHCI7Nt67VgRHsLNnWfy7iaegeEIEa6SqfSv9Z8 I6ga3r6bazQpuJwlWlYdiAy4VoeaRSH4cuXSe1ACXWq2Mk/IVsbGHuEEYkkj9RSQ DnNtkReOxDKwR3TVZbrd7C0EV5ua5vBfrNmNM1iX2U21BFwhV9VheJORjUTpU6aK 4DzDWBfsNnK7E3MD8drjhypKWlBejd45HFhdXSafPD11caznbOPsRzrTjOF0QOxM JV0zQ1s83YGgqBjZY2PHHcSWbx3qC59PXu9NaB7YJUlA1bUkBN6iFuz2hLGNc/d9 awGf8Q== Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a88318mps-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:34 +0000 (GMT) Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-7a43210187cso89912b3a.3 for ; Wed, 05 Nov 2025 09:22:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363353; x=1762968153; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=M+34BFVYwe9cWjXpD4W2ZZm1y1yXgMO3SO03SfHDt+M=; b=WNuC2B7y4ZD1/vzgkskKDGc4qvVl72aB00/981S5E7YSftQUd2JEj/k5GwdC7z7ueG 2Iw5BUTc4x+rXMH2EuXhZR2GY3xMfz1CGZ6XLcXmYADTrGu6UX6hkIO2tMDSEc5jVvpT WsmlDRv1LsL/nzg+YLnyzFLq9fQpYxbKJEbITGiFU6IRPIG49uatlh2+AkNBtvuQ2+Xu k/yi835mxsWyHk9rRTLBN/SoYOxOrTT0r3Te4g7lnHE6GJ4tiw27y/qN380sf+TGjiLn FGLxge+/xzKfm57MkUqAhd67MZRFWGsmkXbQbvYnhDmtOT3OrVbEdDRMQUEgL63Kcdme w88Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363353; x=1762968153; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=M+34BFVYwe9cWjXpD4W2ZZm1y1yXgMO3SO03SfHDt+M=; b=wHeDUIfvFdxw8Ux5dwZR+6mjX61it+pWkTss3XhEXkyXrAicQk85B1B20Emsfu6J5c +5UC+/xoVsLlKdI039GH/21v8DOjwCn8mg8bOmC4yOFTqWGnVWqpxZ26RR6dVZ7eRiAO o+U9vkHQo5L2LxtM/9vrWvJNIAgBPaLD0WowmfN2s13rWLFaDJanbu2SfIcvm7tI5VOs tHJAKnY09+tv7LSn2dOzUWB1hCCjvRSL5uJYEbqV/3TYAL9V3D3rOE4FgXLQocjj3kXu zVU+hJu01mQWRrUuHdsoA6THvEL8/MuVtRjK0WOUoHblnr6cCCtE5N6NPjXQD+l7iNhc 6WvQ== X-Forwarded-Encrypted: i=1; AJvYcCXU/odtquLM6DREkNZPls/wjjGpPPgc+u0amBpVgelcoIAZMzxZHOUJqjnf8oF0Co3oMy9OIB2wE29A1Go=@vger.kernel.org X-Gm-Message-State: AOJu0YxdD2gMXSViNWl4kwRJqk/D0Cgop6/MOopXZFPFMdTaBdYJysu5 VQRwQxMej14qdd2OSdYMdhH+Rw8kJ15/4fjW1+I7eAx5jvbCwujx/76pBfRmJvfLZX9d3VtHor3 AuPt2FGd2RWH2T1MeMa0tAU+tipYMy36du03zewrVdqwUHcytFBvYrSuREaiLw6KWFhs= X-Gm-Gg: ASbGncvDlwO+zjc3MICx4n4QBu9+gkToY8sEdjaUjsdH4QqtVYftzGLeZiuexg2CZE7 K87AvdUdMyDTB7ZKmZHoQzS95Q9QNoZEmXzJ2Y+Bix2Ebq4LZzpGiyqCN1LJ2PIlss7b3BOU/5U gK9a8pG3R6DtqkQo6a3CQun3kX+rX+Z6ck9GGItXE2ixFBQgvgdBoyI+zjSfRm+s7ZJgJOoHxXR taJ3VQHgahmoJPjTYOsopQq/Iggr6MfrOb9gec4qAE8zJHjvWiAxwEvUp7rYGMPuSj3ofBDcuQG baxrgsmdAskoz6u1A4I+Z5Zbodkl3F1SJ+yG6AHvnR/gj7HPc4nSi8tNjgEiSAeHVXkRtO2UmVb PQmiUivO8OyGj7q0ILBz22hvXaxD3oaD+vJvW7G56PkKY X-Received: by 2002:a05:6a00:b43:b0:7a9:c21a:5599 with SMTP id d2e1a72fcca58-7ae1cc60453mr4473807b3a.4.1762363353144; Wed, 05 Nov 2025 09:22:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IGXsnqq8V0HlcCFpvBUNFm3lbgoprJDL3freZkPBlpJH94la+YsFi/UYiNee4CxhF+1f+ypHA== X-Received: by 2002:a05:6a00:b43:b0:7a9:c21a:5599 with SMTP id d2e1a72fcca58-7ae1cc60453mr4473764b3a.4.1762363352544; Wed, 05 Nov 2025 09:22:32 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:31 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 3/6] wifi: ath11k: Add support unassociated client CFR Date: Wed, 5 Nov 2025 09:22:23 -0800 Message-Id: <20251105172226.3182968-4-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: KDP_edu4sKYat_3E5PnFa5YOozo6fM70 X-Proofpoint-GUID: KDP_edu4sKYat_3E5PnFa5YOozo6fM70 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfX2XYMP2cgG1tc yYmCyt5oZZM78VLaUM13Ly2Dtce+T2ZqhXDtnSqnQ+RbXLWBPtM/4vHI+oaeqHdqOQ4PgY8a5KR dW6YPmJ0ZDxpYyTzWU9+OatBcUOJfA8t7ymTTpLS70EiT6VwC3zBIxzTG1l1oWfjjgRQmEL9q8p dsOw6nAQjJ4irg2JFUrlRKnxvvwWDJF3VXPMdTnxgW64ZMgGaUUytys3t4EfM+fxQ1Q82AwOf8X TrU1Ox/JVtcJDHTT7n+Jt8amA45mpAv/ZQNbMWml4/ccTP85hSTsg9Rj4UkLT9SkgUPd7mFeGSe SfRtC/AhgfveDvmARgnwUNujCDxHUDlT4M0vWcY7xyvL/jxDqifQHFYnwGYxJK9Yvp3I6uoIMqU LBqBKXVIN5J102uoLzqj3RXAOjhZUw== X-Authority-Analysis: v=2.4 cv=Mdhhep/f c=1 sm=1 tr=0 ts=690b87da cx=c_pps a=rEQLjTOiSrHUhVqRoksmgQ==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=J6nKnfFvHuu1lZMax6MA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=2VI0MkxyNR6bbpdq8BZq:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 bulkscore=0 suspectscore=0 spamscore=0 clxscore=1015 malwarescore=0 adultscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 From: Venkateswara Naralasetty Provide debugfs interfaces support to config unassociated client CFR from the user space. To enable CFR capture for unassociated clients, echo =E2=80=9C =E2=80=9D > /sys/kernel/debug/ieee80211/phyX/ath11k/cfr_unassoc Mac address: mac address of the client. Val: 0 - start CFR capture 1 =E2=80=93 stop CFR capture Periodicity: Periodicity at which hardware is expected to collect CFR dump. 0 - single shot capture. non zero - for Periodic captures (value must be multiple of 10 ms) Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/cfr.c | 228 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/cfr.h | 33 ++++ drivers/net/wireless/ath/ath11k/mac.c | 15 +- drivers/net/wireless/ath/ath11k/wmi.c | 16 +- drivers/net/wireless/ath/ath11k/wmi.h | 2 +- 5 files changed, 290 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c index bf0b880e8746..e22b0151833c 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.c +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -14,6 +14,60 @@ static int ath11k_cfr_process_data(struct ath11k *ar, return 0; } =20 +/* Helper function to check whether the given peer mac address + * is in unassociated peer pool or not. + */ +bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *p= eer_mac) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + struct cfr_unassoc_pool_entry *entry; + int i; + + if (!ar->cfr_enabled) + return false; + + spin_lock_bh(&cfr->lock); + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + if (!entry->is_valid) + continue; + + if (ether_addr_equal(peer_mac, entry->peer_mac)) { + spin_unlock_bh(&cfr->lock); + return true; + } + } + + spin_unlock_bh(&cfr->lock); + + return false; +} + +void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar, + const u8 *peer_mac) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + struct cfr_unassoc_pool_entry *entry; + int i; + + spin_lock_bh(&cfr->lock); + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + if (!entry->is_valid) + continue; + + if (ether_addr_equal(peer_mac, entry->peer_mac) && + entry->period =3D=3D 0) { + memset(entry->peer_mac, 0, ETH_ALEN); + entry->is_valid =3D false; + cfr->cfr_enabled_peer_cnt--; + break; + } + } + + spin_unlock_bh(&cfr->lock); +} + void ath11k_cfr_decrement_peer_count(struct ath11k *ar, struct ath11k_sta *arsta) { @@ -130,6 +184,59 @@ int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k= *ar, return ret; } =20 +void ath11k_cfr_update_unassoc_pool(struct ath11k *ar, + struct ath11k_per_peer_cfr_capture *params, + u8 *peer_mac) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + struct cfr_unassoc_pool_entry *entry; + int available_idx =3D -1; + int i; + + guard(spinlock_bh)(&cfr->lock); + + if (!params->cfr_enable) { + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + if (ether_addr_equal(peer_mac, entry->peer_mac)) { + memset(entry->peer_mac, 0, ETH_ALEN); + entry->is_valid =3D false; + cfr->cfr_enabled_peer_cnt--; + break; + } + } + return; + } + + if (cfr->cfr_enabled_peer_cnt >=3D ATH11K_MAX_CFR_ENABLED_CLIENTS) { + ath11k_info(ar->ab, "Max cfr peer threshold reached\n"); + return; + } + + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + + if (ether_addr_equal(peer_mac, entry->peer_mac)) { + ath11k_info(ar->ab, + "peer entry already present updating params\n"); + entry->period =3D params->cfr_period; + available_idx =3D -1; + break; + } + + if (available_idx < 0 && !entry->is_valid) + available_idx =3D i; + } + + if (available_idx >=3D 0) { + entry =3D &cfr->unassoc_pool[available_idx]; + ether_addr_copy(entry->peer_mac, peer_mac); + entry->period =3D params->cfr_period; + entry->is_valid =3D true; + cfr->cfr_enabled_peer_cnt++; + } +} + static ssize_t ath11k_read_file_enable_cfr(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -188,10 +295,127 @@ static const struct file_operations fops_enable_cfr = =3D { .llseek =3D default_llseek, }; =20 +static ssize_t ath11k_write_file_cfr_unassoc(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k *ar =3D file->private_data; + struct ath11k_cfr *cfr =3D &ar->cfr; + struct cfr_unassoc_pool_entry *entry; + char buf[64] =3D {}; + u8 peer_mac[6]; + u32 cfr_capture_enable; + u32 cfr_capture_period; + int available_idx =3D -1; + int ret, i; + + simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); + + guard(mutex)(&ar->conf_mutex); + guard(spinlock_bh)(&cfr->lock); + + if (ar->state !=3D ATH11K_STATE_ON) + return -ENETDOWN; + + if (!ar->cfr_enabled) { + ath11k_err(ar->ab, "CFR is not enabled on this pdev %d\n", + ar->pdev_idx); + return -EINVAL; + } + + ret =3D sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %u %u", + &peer_mac[0], &peer_mac[1], &peer_mac[2], &peer_mac[3], + &peer_mac[4], &peer_mac[5], &cfr_capture_enable, + &cfr_capture_period); + + if (ret < 1) + return -EINVAL; + + if (cfr_capture_enable && ret !=3D 8) + return -EINVAL; + + if (!cfr_capture_enable) { + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + if (ether_addr_equal(peer_mac, entry->peer_mac)) { + memset(entry->peer_mac, 0, ETH_ALEN); + entry->is_valid =3D false; + cfr->cfr_enabled_peer_cnt--; + } + } + + return count; + } + + if (cfr->cfr_enabled_peer_cnt >=3D ATH11K_MAX_CFR_ENABLED_CLIENTS) { + ath11k_info(ar->ab, "Max cfr peer threshold reached\n"); + return count; + } + + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + + if (available_idx < 0 && !entry->is_valid) + available_idx =3D i; + + if (ether_addr_equal(peer_mac, entry->peer_mac)) { + ath11k_info(ar->ab, + "peer entry already present updating params\n"); + entry->period =3D cfr_capture_period; + return count; + } + } + + if (available_idx >=3D 0) { + entry =3D &cfr->unassoc_pool[available_idx]; + ether_addr_copy(entry->peer_mac, peer_mac); + entry->period =3D cfr_capture_period; + entry->is_valid =3D true; + cfr->cfr_enabled_peer_cnt++; + } + + return count; +} + +static ssize_t ath11k_read_file_cfr_unassoc(struct file *file, + char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k *ar =3D file->private_data; + struct ath11k_cfr *cfr =3D &ar->cfr; + struct cfr_unassoc_pool_entry *entry; + char buf[512] =3D {}; + int len =3D 0, i; + + spin_lock_bh(&cfr->lock); + + for (i =3D 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { + entry =3D &cfr->unassoc_pool[i]; + if (entry->is_valid) + len +=3D scnprintf(buf + len, sizeof(buf) - len, + "peer: %pM period: %u\n", + entry->peer_mac, entry->period); + } + + spin_unlock_bh(&cfr->lock); + + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static const struct file_operations fops_configure_cfr_unassoc =3D { + .write =3D ath11k_write_file_cfr_unassoc, + .read =3D ath11k_read_file_cfr_unassoc, + .open =3D simple_open, + .owner =3D THIS_MODULE, + .llseek =3D default_llseek, +}; + static void ath11k_cfr_debug_unregister(struct ath11k *ar) { debugfs_remove(ar->cfr.enable_cfr); ar->cfr.enable_cfr =3D NULL; + debugfs_remove(ar->cfr.cfr_unassoc); + ar->cfr.cfr_unassoc =3D NULL; } =20 static void ath11k_cfr_debug_register(struct ath11k *ar) @@ -199,6 +423,10 @@ static void ath11k_cfr_debug_register(struct ath11k *a= r) ar->cfr.enable_cfr =3D debugfs_create_file("enable_cfr", 0600, ar->debug.debugfs_pdev, ar, &fops_enable_cfr); + + ar->cfr.cfr_unassoc =3D debugfs_create_file("cfr_unassoc", 0600, + ar->debug.debugfs_pdev, ar, + &fops_configure_cfr_unassoc); } =20 void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h index 7d161f7f7be8..e7b69e98cbf5 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.h +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -45,6 +45,12 @@ struct ath11k_look_up_table { struct ath11k_dbring_element *buff; }; =20 +struct cfr_unassoc_pool_entry { + u8 peer_mac[ETH_ALEN]; + u32 period; + bool is_valid; +}; + struct ath11k_cfr { struct ath11k_dbring rx_ring; /* Protects cfr data */ @@ -53,6 +59,7 @@ struct ath11k_cfr { spinlock_t lut_lock; struct ath11k_look_up_table *lut; struct dentry *enable_cfr; + struct dentry *cfr_unassoc; u8 cfr_enabled_peer_cnt; u32 lut_num; u64 tx_evt_cnt; @@ -66,6 +73,7 @@ struct ath11k_cfr { u64 clear_txrx_event; u64 cfr_dma_aborts; bool enabled; + struct cfr_unassoc_pool_entry unassoc_pool[ATH11K_MAX_CFR_ENABLED_CLIENTS= ]; }; =20 enum ath11k_cfr_capture_method { @@ -89,6 +97,13 @@ void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_= addr_t paddr, u32 buf_id); void ath11k_cfr_decrement_peer_count(struct ath11k *ar, struct ath11k_sta *arsta); +void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar, + const u8 *peer_mac); +bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, + const u8 *peer_mac); +void ath11k_cfr_update_unassoc_pool(struct ath11k *ar, + struct ath11k_per_peer_cfr_capture *params, + u8 *peer_mac); int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, struct ath11k_sta *arsta, struct ath11k_per_peer_cfr_capture *params, @@ -114,6 +129,24 @@ static inline void ath11k_cfr_decrement_peer_count(str= uct ath11k *ar, { } =20 +static inline void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar, + const u8 *peer_mac) +{ +} + +static inline bool +ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_m= ac) +{ + return false; +} + +static inline void +ath11k_cfr_update_unassoc_pool(struct ath11k *ar, + struct ath11k_per_peer_cfr_capture *params, + u8 *peer_mac) +{ +} + static inline int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, struct ath11k_sta *arsta, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/a= th/ath11k/mac.c index 965c377cd8dc..2fbd64d78338 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6186,6 +6186,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, = struct ath11k_vif *arvif, dma_addr_t paddr; int buf_id; int ret; + bool tx_params_valid =3D false; + bool peer_in_unassoc_pool; =20 ATH11K_SKB_CB(skb)->ar =3D ar; =20 @@ -6224,7 +6226,18 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar,= struct ath11k_vif *arvif, =20 ATH11K_SKB_CB(skb)->paddr =3D paddr; =20 - ret =3D ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); + peer_in_unassoc_pool =3D ath11k_cfr_peer_is_in_cfr_unassoc_pool(ar, hdr->= addr1); + + if (ar->cfr_enabled && + ieee80211_is_probe_resp(hdr->frame_control) && + peer_in_unassoc_pool) + tx_params_valid =3D true; + + if (peer_in_unassoc_pool) + ath11k_cfr_update_unassoc_pool_entry(ar, hdr->addr1); + + ret =3D ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb, + tx_params_valid); if (ret) { ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); goto err_unmap_buf; diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/a= th/ath11k/wmi.c index 846c9946a084..0b4cc943c290 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -651,11 +651,12 @@ static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar, } =20 int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, - struct sk_buff *frame) + struct sk_buff *frame, bool tx_params_valid) { struct ath11k_pdev_wmi *wmi =3D ar->wmi; struct ieee80211_tx_info *info =3D IEEE80211_SKB_CB(frame); struct wmi_mgmt_send_cmd *cmd; + struct wmi_mgmt_send_params *params; struct wmi_tlv *frame_tlv; struct sk_buff *skb; u32 buf_len; @@ -665,6 +666,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id= , u32 buf_id, frame->len : WMI_MGMT_SEND_DOWNLD_LEN; =20 len =3D sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4); + if (tx_params_valid) + len +=3D sizeof(*params); =20 skb =3D ath11k_wmi_alloc_skb(wmi->wmi_ab, len); if (!skb) @@ -680,7 +683,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id= , u32 buf_id, cmd->paddr_hi =3D upper_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->frame_len =3D frame->len; cmd->buf_len =3D buf_len; - cmd->tx_params_valid =3D 0; + cmd->tx_params_valid =3D !!tx_params_valid; =20 frame_tlv =3D (struct wmi_tlv *)(skb->data + sizeof(*cmd)); frame_tlv->header =3D FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | @@ -690,6 +693,15 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_i= d, u32 buf_id, =20 ath11k_ce_byte_swap(frame_tlv->value, buf_len); =20 + if (tx_params_valid) { + params =3D + (struct wmi_mgmt_send_params *)(skb->data + (len - sizeof(*params))); + params->tlv_header =3D FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TX_SEND_PARAMS) | + FIELD_PREP(WMI_TLV_LEN, + sizeof(*params) - TLV_HDR_SIZE); + params->tx_params_dword1 |=3D WMI_TX_PARAMS_DWORD1_CFR_CAPTURE; + } + ret =3D ath11k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID); if (ret) { ath11k_warn(ar->ab, diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/a= th/ath11k/wmi.h index 1562d169ba9a..afc78fa4389b 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -6391,7 +6391,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, = struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 l= en); int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, - struct sk_buff *frame); + struct sk_buff *frame, bool tx_params_valid); int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id, const u8 *p2p_ie); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, --=20 2.34.1 From nobody Sun Dec 14 05:56:39 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.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 4AD42331A4B for ; Wed, 5 Nov 2025 17:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363359; cv=none; b=PZQDpIi1uTQLuilZjNFQHI0MaQuWjXYlJ/GptKFscoe3Fk1AD8ecYOkWPUBPYGTCmHn+rBZ4qjx8SnBTKC9prtKiRPouEMSqiC/vJk8kMpc3tob1eBf+E077lVs8UDV9E5rq9TUSPGJi1Dooe0/n/2k7Pu7MS4h4jq3KPHx+e5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363359; c=relaxed/simple; bh=t5/ge6GzdGgh1+ffRzwal3+n/u8ueUwYnBULeeTMjhs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=d5U9tMNO6+6waz5F/6aZuknp4kIJvQjhOdobcwnk4Z6eXYGH0305ly1zJ8N+mT43co5ktAiMvNqL/l/BTtc3ecebjGxuVkgKt39zTMsWlqnWNFsgvEqPyPYtBxDlEB4yyA/SZoicnkvaerKBltUF5FS9xsj66X5EfiaRzlBk3Jc= 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=fjsJtXBz; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=Rnj1zQqY; arc=none smtp.client-ip=205.220.180.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="fjsJtXBz"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Rnj1zQqY" Received: from pps.filterd (m0279871.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A5B31Hk655038 for ; Wed, 5 Nov 2025 17:22:36 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=E/JGA8NlNfL RHt5JiK60dzndBvs8Ulpj2FKRq2wFm+Y=; b=fjsJtXBzDSPJJ349QyWR+5zW7t2 BHj9sS6k6/MPWe5I9YF4lCXV0+M5tLznEKi5kAG/egd3EnpEXcwPO1JYOzidhLtr qn5ScDgkUT1WPeijvvVH7diNH0AI5Cv9CF1IJokHnFNF0CE0+Q8SplvoKdmZ5FeW CxLxX/uUm7xMLcnSkCmNsqyLK8p1bDgBKg7GnD23uvP7V44FfuhsN86xDcE2xG1Q nyOzuX2Ug8pAf8Xi+uxGFD4v/W0x0nCwufmShzKOUdbL9z91dcsWA88YnHdFYqyZ YF5f+EPPLYUWvKngW30dCpqTCOaRerwFRPxftDj0SNgBShlyNN79b7LRO6Q== Received: from mail-pg1-f200.google.com (mail-pg1-f200.google.com [209.85.215.200]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a85c8h2np-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:35 +0000 (GMT) Received: by mail-pg1-f200.google.com with SMTP id 41be03b00d2f7-b993eb2701bso25809a12.0 for ; Wed, 05 Nov 2025 09:22:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363355; x=1762968155; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=E/JGA8NlNfLRHt5JiK60dzndBvs8Ulpj2FKRq2wFm+Y=; b=Rnj1zQqYMzUY4txLQMyS46y706g8n8ljYnVMJwIHO+Ypp9unkwfCy2EmfJfyqvzCgX y+4egnuun6uSJokoyW44uk3MSv2FejSMte2kz3sUuzfve8ayN15GYo3ld/I9hZARJrXo tn8/8emf8yk2+32G9OxKNqGhSmsORDW2dFBDVd4OWnhQsauViSDeEhEfgbmqNr2PyjU/ 4wvzeAw3UgNyPXbn9AzIxz6LwFpZQStYfbpWv47OjGIOCM1pfjV0JRkQfpwE9U35yeiJ jnNy3QYPhqqK7VMfWb/EdEF3/yTFIw3nc8a9bx3XBYOojkyPVhcn4GThqQwfFt5J4EnW +VSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363355; x=1762968155; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=E/JGA8NlNfLRHt5JiK60dzndBvs8Ulpj2FKRq2wFm+Y=; b=rP6eQuQk8JI5SImZZPOGTPTcYG9/nVIlGJtWJhsLUW03Qm4bTQKeqVXLbyPyfSBsUu OMrVsmCbpS0QgLIvUcvV+JmmQczNX6mBQLIFWOTgj3l+gDRaehrtDQHlVaVRWTCmuPMA +Gq+TP8GTjGJPtyE2i7eWueYxqPZNpap03PYdySwr32evuDaW0cwUOYBpMuGNJ5BXW/+ FmthIEqDVW+WuOBrxVNlagnA4BZryry/J9++dDltMyBmyc603C3yOoWQkMsCVtgeMF0R 1+bPjbJC/hcrYIgoLlHv805tQUic+3xO/kksHwwjf+QDAUKz+sCQnP9LfcpytWAKuk2j HJJg== X-Forwarded-Encrypted: i=1; AJvYcCXsh3QiQSCKbXYUSGlFBFMbm1hdXcYh+ms5E36LEpYlbJXN4pavwFFIQTvUHcfMwz7VpetBm35ewVH0yy0=@vger.kernel.org X-Gm-Message-State: AOJu0YwPVH1JYSZtOwUrg1Be78/UTEdkLAWag3PN20js4Sl2vq48YCoD NfbpLHVOPE3Y53KXA2RTXBaAt0RFXfOUKSlRMVvXzRIx7dLdhF+i35ijROIHDVmsefXiDQM6yh+ yj087oS9tahxVLscWghGzSsC7tuqy+UYriH4h6LoHIShb9Pc6qNDSTXyX9nuxebZRACA= X-Gm-Gg: ASbGncsxem46vlbvQHvkH8PrbXKV5/pYVpTCkr2sAkRbEDUtvGog21B4UexgxS+46f8 O4WQEnxYdP8XLbDLpyAKX8SH4ZPxTQDY3YML+m8hIG3uEtZfkU9TDj6IwUHozAhN3Oix53m2fqw Sg/StD4CgZTJv0wO5WLAIsSMLPPwG4ShaaYhlgzRBLewI4WYKfiCOJ8LiXNpH+7WtatAifVU563 HSMKylP8vACzYJ2kyEx+lq5Uh6sSIB62xJ40FLXB9FF79vOYIh0dvbvx5XNEVEwLHORgKoNrzkg /fveivfyA4Ob2bxK/OY1iTtffQPkqZ8nX5aYGCsaWpE0L2vKSOzpCF9SGVd6YEv2i9XojPdMJd0 zfD7w+cjcauZm5HUllu8WSUipzPMyeOEsGnc41Mmh22xh X-Received: by 2002:a05:6a21:999a:b0:34e:8864:7952 with SMTP id adf61e73a8af0-34f837ed9b3mr5866649637.2.1762363354809; Wed, 05 Nov 2025 09:22:34 -0800 (PST) X-Google-Smtp-Source: AGHT+IFhtxpt0U6Mdf8qB4LCjblFkBg1cLt9Axqbp/AgV/z0MjgUl5CIsJwY6PTbirUDR60J6qg/9g== X-Received: by 2002:a05:6a21:999a:b0:34e:8864:7952 with SMTP id adf61e73a8af0-34f837ed9b3mr5866532637.2.1762363353727; Wed, 05 Nov 2025 09:22:33 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:33 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 4/6] wifi: ath11k: Register relayfs entries for CFR dump Date: Wed, 5 Nov 2025 09:22:24 -0800 Message-Id: <20251105172226.3182968-5-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: VZr-6aQnvKpaZoLFFvNCnxLgS3fB-IhR X-Proofpoint-GUID: VZr-6aQnvKpaZoLFFvNCnxLgS3fB-IhR X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfX75iPdHkvjyK/ R7hA0r/aTQNDMYigGgnMH74hxVso2dCrwFIBxpWd+ceVd/zRtPU+nW74cmglGQNYjxJYJfX6LBq VgBMP6BAFXA7Eviy4ZvX/OTS7iswNlxFuRSqGh+2/JCZzuL7X9ZYtlzGZJ3D+PzxEteF0Ipo9UN m/B32bS/zbrv/mxBr2vdFWeJgn5Iwd58BuTq8VhdX0cJUV5nzDkMCpC6lnlrUevAj6bUzUNaYfZ ZzVWe/fTGO5fcpE8o6ow9p1AN99zDKJC+roP24MCY3QSVz9xBTy2czq1wwcMJP0byz3U8h838Mi 2HI/VaxYz3O5JzOHWP9TBrDc3hckpZVeFUjNK0JJc2X5UsM+ojqx5A8VlWESK+SqEfpcUt/lTmO CdzHTUajIfR6RvsSkBXsU4AAmWytOQ== X-Authority-Analysis: v=2.4 cv=apS/yCZV c=1 sm=1 tr=0 ts=690b87db cx=c_pps a=oF/VQ+ItUULfLr/lQ2/icg==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=6mQ44K8ZfP1dJrZg0vYA:9 a=3WC7DwWrALyhR5TkjVHa:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 spamscore=0 malwarescore=0 lowpriorityscore=0 adultscore=0 bulkscore=0 phishscore=0 clxscore=1015 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 Content-Type: text/plain; charset="utf-8" From: Venkateswara Naralasetty Provide a relayfs interface to collect the CFR dump from the user space. '/sys/kernel/debug/ieee80211/phyX/ath11k/cfr_capture' is exposed to user space to get CFR data. CFR format to user space: ___________________________________________ | CFR header | CFR payload | CFR tail data | |____________|_____________|_______________| CFR header contains the following fields, * Start magic number 0xDEADBEAF - 4 bytes * vendor id - 4 bytes * cfr metadata version - 1 byte * cfr data version - 1 byte * device type - 1 byte * platform type - 1 byte * CFR metadata length - 4 bytes * metadata - 92 bytes peer mac - 6 bytes capture status - 1 byte (1 for success 0 for failure) capture_bw - 1 byte channel_bw - 1 byte phy_mode - 1 byte prim20_chan - 2 bytes center_freq1 - 2 bytes center_freq2 - 2 bytes capture_mode - 1 byte capture_type - 1 byte sts_count - 1 byte num_rx_chain - 1 byte timestamp - 4 bytes length - 4 bytes chain_rssi - 32 bytes (4 bytes for each chain) chain_phase - 16 bytes (2 bytes for each chain) cfo_measurement - 4 bytes agc_gain - 8 bytes (1 bytes for each chain) rx_start_ts - 4 bytes CFR payload: CFR payload contains 8bytes of ucode header followed by the tone information. Tone order is positive tones, followed by PHY memory garbage, followed by negative tones. Dummy tones are uploaded to make number of tones always integer number of 64. Number of tones is not preamble type dependent. Each CFR tone has 14-bit I component and 14-bit Q component and is sign extended to 16-bit I/Q. Two tones are packed into one 64-bit unit as: [63:0] =3D [Tone1_Q(63:48) Tone1_I(47:32) Tone0_Q(31:16) Tone0_I(15:0)] CFR tail: end magic number 0xBEAFDEAD Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/cfr.c | 35 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/cfr.h | 1 + 2 files changed, 36 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c index e22b0151833c..495b2c6742aa 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.c +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -416,10 +416,45 @@ static void ath11k_cfr_debug_unregister(struct ath11k= *ar) ar->cfr.enable_cfr =3D NULL; debugfs_remove(ar->cfr.cfr_unassoc); ar->cfr.cfr_unassoc =3D NULL; + + relay_close(ar->cfr.rfs_cfr_capture); + ar->cfr.rfs_cfr_capture =3D NULL; } =20 +static struct dentry *ath11k_cfr_create_buf_file_handler(const char *filen= ame, + struct dentry *parent, + umode_t mode, + struct rchan_buf *buf, + int *is_global) +{ + struct dentry *buf_file; + + buf_file =3D debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); + *is_global =3D 1; + return buf_file; +} + +static int ath11k_cfr_remove_buf_file_handler(struct dentry *dentry) +{ + debugfs_remove(dentry); + + return 0; +} + +static const struct rchan_callbacks rfs_cfr_capture_cb =3D { + .create_buf_file =3D ath11k_cfr_create_buf_file_handler, + .remove_buf_file =3D ath11k_cfr_remove_buf_file_handler, +}; + static void ath11k_cfr_debug_register(struct ath11k *ar) { + ar->cfr.rfs_cfr_capture =3D relay_open("cfr_capture", + ar->debug.debugfs_pdev, + ar->ab->hw_params.cfr_stream_buf_size, + ar->ab->hw_params.cfr_num_stream_bufs, + &rfs_cfr_capture_cb, NULL); + ar->cfr.enable_cfr =3D debugfs_create_file("enable_cfr", 0600, ar->debug.debugfs_pdev, ar, &fops_enable_cfr); diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h index e7b69e98cbf5..19f136d34c65 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.h +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -60,6 +60,7 @@ struct ath11k_cfr { struct ath11k_look_up_table *lut; struct dentry *enable_cfr; struct dentry *cfr_unassoc; + struct rchan *rfs_cfr_capture; u8 cfr_enabled_peer_cnt; u32 lut_num; u64 tx_evt_cnt; --=20 2.34.1 From nobody Sun Dec 14 05:56:39 2025 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 B1A6633BBCE for ; Wed, 5 Nov 2025 17:22:37 +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=1762363359; cv=none; b=AOvjp/eEfTMs7TtJksnsMMYrS78k9wPYkKpwoICMg15rSqEK0H0twoXvdt6ID37cp9bj0/j1AFIhATuiWVMPRqV6V9KG7FcO5tdOZk0JZlSZSUffzwIy6JfhhBBv1wT5wj8euSztm4ndcZzO/UExvZyqGJi6lzaEEHDqm6TIe/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363359; c=relaxed/simple; bh=RNp6w+k7RL3TVxMV0cZ9A1hYDd6+hGugRf845/M5PEg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=m1oGkWnXgPeHtt1X47TAbeY5mtD7H9YGMdJ07BC0JcFosR40/DQlqRP6gRoDOtl2ODSPtxhS3N0Rkm6R4uM9zDT0RaBeR6XdYt58onSd/Ecz/wVP70zQIauDvJfsSJTxiWWDEzUbK3K9sCjlL+M8Rj0vfukHnRfLyr6DJI13rB0= 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=EGkKtQWq; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=Ddirl1GS; 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="EGkKtQWq"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="Ddirl1GS" Received: from pps.filterd (m0279862.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A599iGA356694 for ; Wed, 5 Nov 2025 17:22:37 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=NRavOzXI5iU /UskpcOXH8hDApcUTgjxol6w5awACPP8=; b=EGkKtQWq9dfVO1qjFivl1o30ucs NlS4kP5ChFYom0NrMopV0ZEBQ77JHnymD0+6PjytItM7QkJ8tTavZ6vmXv1izeey hDZXm5mbYBP5kKzy4vTf8LeScrQV5AhABkHfVm4Y44r1cAxvtn9Rd5gvnsEoDfCl hb0N1Te5GiLQ3eLT4MWiBZp81TfqD0+nz9CFVndqaW2vux0HXa96zkxneQVnIJ3x 0HwZ1aItLQhDA3Ape/IFzoHzMR1poiQNR9gwVJ6tHQqechtgpSKFxc+vKpC+dH2e wjCVR7FtOqGS/vaqKNvugo8mfXg8VXSZAtbYpzl39nNYSX4PiWS7DSwlpZA== Received: from mail-pf1-f200.google.com (mail-pf1-f200.google.com [209.85.210.200]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a83q5hd8d-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:36 +0000 (GMT) Received: by mail-pf1-f200.google.com with SMTP id d2e1a72fcca58-7a675fbd6c7so110919b3a.2 for ; Wed, 05 Nov 2025 09:22:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363356; x=1762968156; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NRavOzXI5iU/UskpcOXH8hDApcUTgjxol6w5awACPP8=; b=Ddirl1GSonHMJjZIKeWaHWtjmgzv+TJidIkQWbQEo7qQgGOBOqjj96yG7ljUcKosKR 79VFXtJauRP7KG4gqFin8qSiWyUONvbD7y2g9mnYoTA5RjRL+G9qX39NxWP3ah47/WFs 3Rr7xjQ7209V5FdcD6/lBzJw5w8rFJe2CnCRzqYffbNo6lGeIV2NSaHIVeLppPftfJJL 5UMjhYAjEKWC6cb5q9DweIm8DzEwrC9TCBKdPtlxuCjaC+aBm1WhkGx3i0K/aZqdeZjw 6FDBByziWZk0z9UY6xRfmH3ealFAOvFbxuRYh2SLVSBK8HmKrbYilzt0Tf+SQ4gdrvK/ Yakw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363356; x=1762968156; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NRavOzXI5iU/UskpcOXH8hDApcUTgjxol6w5awACPP8=; b=LrXXG3wGVF+kHsePBvhWsZvnYdl4ss0BKZY8c/5KC8R7nAZtigbFq9IRNWEnZJTAGA 9z8ihvURStcxTklof+buSc9UJApSi1zNea/JG3sl/B2n8599lTw4Cn0vHpoDKXIvhN85 v44NTO4CEJ3azLFJFJTpIu6IM4Vf7zWJ13qjX2QpauYoR5eTlVFFKO2lvEzXH+icqnSj 97KVaY+aQtJ6d2HxSH93R0O5bIfmi/erI4KleNDC7wiHmcBPo7yo62lGUnFmojAk60vL NgQpMCL1QuOspmDORv6vncJEW48tqEYc/nPTP2dqdBd1RjVEc5/mDO+dC8RILsERKBNS E3rw== X-Forwarded-Encrypted: i=1; AJvYcCUGhWU3rRaJHNHUmFpOxZBp/PIP2jaPFBEQsCMo8A4uCIGivk4+hommVof+sUkDtO4s/DgJrfRhPViEY5w=@vger.kernel.org X-Gm-Message-State: AOJu0Yxh+5YJTCWnkrlc1GETplv6qOPPRyMJNlpa7l1RGZIuNFnSI0pE WRcIdMCqa0Jq+FkC5fE+/bj+ljEJhgXWsjhubiD30ABIKbhQp8hVSbutobpnIg36SydbOLgSbhA qBxwUJXxFL7wYGjZPFLAqhlVrzs2Cu1uSXmLHnXRKNPyjSABq/YG4YqMeZxPg5zJiIKH7kW1yqr HwygC5 X-Gm-Gg: ASbGncumJxCVA0hPULxwonzcljyAIpFkRPOBzl3nQZSFqPG4OmR8J+uGgH8Nr90oB5O yrZx6Io0g7devqajQJE4AcyItKrRf7tqk6Sp6kp+6+H3G22SuQHCl5C+SlK0FFtT4YxxQYalEVb xdaItqss3rAa8Y4SNSfnxi+kHTIM4fpOWIYX5Ym1vjSuqwzlUMv7UhgjFc3T+TCLDinQvwKr+lo 1KJzTy76c7+rwNG6ew68eIrmYimCjsquMBfLAdm0SoFskqW+YFL2d7gp1U0w5MH5MC5enOs3kck 6rj6ET+C8q5qR5lcVmA9l+MjIj6N+bEMVvyrsdF7hNPbzetnFnzVTfFy4tTDD8UM0FSsxhOjZ4b 4vSeFZFKbXpFSBWWYdclXRVuEQC+4oeZZOp4lsaxx4cpf X-Received: by 2002:a05:6a00:2d10:b0:781:16de:cc1a with SMTP id d2e1a72fcca58-7ae1fc7d8b0mr5465547b3a.32.1762363355831; Wed, 05 Nov 2025 09:22:35 -0800 (PST) X-Google-Smtp-Source: AGHT+IEkW2uiqjIaRIMXu/EAGpvLes8wJXNeJ8AzJU9vR6LWLaKChq/rAqHi16zdwVz1pw+DPTpq6A== X-Received: by 2002:a05:6a00:2d10:b0:781:16de:cc1a with SMTP id d2e1a72fcca58-7ae1fc7d8b0mr5465497b3a.32.1762363355225; Wed, 05 Nov 2025 09:22:35 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:34 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 5/6] wifi: ath11k: Register DBR event handler for CFR data Date: Wed, 5 Nov 2025 09:22:25 -0800 Message-Id: <20251105172226.3182968-6-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: jW_ntyUqCxtEf7w5MwIXiR3aPyfNxxs2 X-Proofpoint-GUID: jW_ntyUqCxtEf7w5MwIXiR3aPyfNxxs2 X-Authority-Analysis: v=2.4 cv=YZKwJgRf c=1 sm=1 tr=0 ts=690b87dc cx=c_pps a=mDZGXZTwRPZaeRUbqKGCBw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=X6MYPc9AQ2pAf6QSHKQA:9 a=zc0IvFSfCIW2DFIPzwfm:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfX6B1DeHT20vOj BjE3TJV/ZU4ddiMguz1Zr92Dd5QoVJ2PDYJLm+kL96vJhKe4bRpkSvQgDiInSH4oZYATD9gfie+ 3vjPg7ecYvjWvZUVvmiQfcqkWXC+I4rh61Y/D8Mn74Rhh5lNIHzT4zWUzNxUM20iZZS0W8vZiw1 LHLShYBwdJE469DGwri87ebwRzVtGaevNtjoFon4O3U8fAPxNti5gefxr6V8ewD9xEeotwxAsGn At5JRWh7c2m1UFeriXK9lW+aF0MKpPx6H1daMkGrZllwPC3HSWnECFfEUJN3UxdQ4wKd1jIhEq8 G8u5Qxvb/U7Fvvx40YpLDW1Ku1LiwkocYQfXqF6xp5Vj1g2EvrDyxvx930KE+It3wlL7PWm/3mP Rwz48txDiUwWll/bTCX43dR+Rx8U4A== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 lowpriorityscore=0 impostorscore=0 adultscore=0 priorityscore=1501 clxscore=1015 malwarescore=0 bulkscore=0 suspectscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 Content-Type: text/plain; charset="utf-8" From: Venkateswara Naralasetty Add handler for WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT which indicates CFR data availability in the DB ring. Add CFR data processing from DB ring buffers. Use correlate_and_relay API to match CFR data with metadata from WMI_PEER_CFR_CAPTURE_EVENT. Release buffer to userspace through relayfs on successful correlation, otherwise hold buffer waiting for matching WMI event from firmware. Add new debug masks: - ATH11K_DBG_CFR: Enables CFR-related debug logs. - ATH11K_DBG_CFR_DUMP: Enables detailed CFR data dump for analysis. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/cfr.c | 240 ++++++++++++++++++++++- drivers/net/wireless/ath/ath11k/cfr.h | 82 ++++++++ drivers/net/wireless/ath/ath11k/dbring.c | 10 +- drivers/net/wireless/ath/ath11k/dbring.h | 2 + drivers/net/wireless/ath/ath11k/debug.h | 8 +- 5 files changed, 339 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c index 495b2c6742aa..ee7626bd4b1a 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.c +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -8,10 +8,248 @@ #include "core.h" #include "debug.h" =20 +struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar) +{ + if (ar->cfr_enabled) + return &ar->cfr.rx_ring; + + return NULL; +} + +static int ath11k_cfr_calculate_tones_from_dma_hdr(struct ath11k_cfr_dma_h= dr *hdr) +{ + u8 bw =3D FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW, hdr->info1); + u8 preamble =3D FIELD_GET(CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE, hdr->info1); + + switch (preamble) { + case ATH11K_CFR_PREAMBLE_TYPE_LEGACY: + fallthrough; + case ATH11K_CFR_PREAMBLE_TYPE_VHT: + switch (bw) { + case 0: + return TONES_IN_20MHZ; + case 1: /* DUP40/VHT40 */ + return TONES_IN_40MHZ; + case 2: /* DUP80/VHT80 */ + return TONES_IN_80MHZ; + case 3: /* DUP160/VHT160 */ + return TONES_IN_160MHZ; + default: + return TONES_INVALID; + } + case ATH11K_CFR_PREAMBLE_TYPE_HT: + switch (bw) { + case 0: + return TONES_IN_20MHZ; + case 1: + return TONES_IN_40MHZ; + default: + return TONES_INVALID; + } + default: + return TONES_INVALID; + } +} + +void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut) +{ + memset(lut, 0, sizeof(*lut)); +} + +static void ath11k_cfr_rfs_write(struct ath11k *ar, const void *head, + u32 head_len, const void *data, u32 data_len, + const void *tail, int tail_data) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + + if (!cfr->rfs_cfr_capture) + return; + + relay_write(cfr->rfs_cfr_capture, head, head_len); + relay_write(cfr->rfs_cfr_capture, data, data_len); + relay_write(cfr->rfs_cfr_capture, tail, tail_data); + relay_flush(cfr->rfs_cfr_capture); +} + +static void ath11k_cfr_free_pending_dbr_events(struct ath11k *ar) +{ + struct ath11k_cfr *cfr =3D &ar->cfr; + struct ath11k_look_up_table *lut; + int i; + + if (!cfr->lut) + return; + + for (i =3D 0; i < cfr->lut_num; i++) { + lut =3D &cfr->lut[i]; + if (lut->dbr_recv && !lut->tx_recv && + lut->dbr_tstamp < cfr->last_success_tstamp) { + ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, lut->buff, + WMI_DIRECT_BUF_CFR); + ath11k_cfr_release_lut_entry(lut); + cfr->flush_dbr_cnt++; + } + } +} + +/** + * ath11k_cfr_correlate_and_relay() - Correlate and relay CFR events + * @ar: Pointer to ath11k structure + * @lut: Lookup table for correlation + * @event_type: Type of event received (TX or DBR) + * + * Correlates WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT (DBR) and + * WMI_PEER_CFR_CAPTURE_EVENT (TX capture) by PPDU ID. If both events + * are present and the PPDU IDs match, returns CORRELATE_STATUS_RELEASE + * to relay thecorrelated data to userspace. Otherwise returns + * CORRELATE_STATUS_HOLD to wait for the other event. + * + * Also checks pending DBR events and clears them when no corresponding TX + * capture event is received for the PPDU. + * + * Return: CORRELATE_STATUS_RELEASE or CORRELATE_STATUS_HOLD + */ + +static enum ath11k_cfr_correlate_status +ath11k_cfr_correlate_and_relay(struct ath11k *ar, + struct ath11k_look_up_table *lut, + u8 event_type) +{ + enum ath11k_cfr_correlate_status status; + struct ath11k_cfr *cfr =3D &ar->cfr; + u64 diff; + + if (event_type =3D=3D ATH11K_CORRELATE_TX_EVENT) { + if (lut->tx_recv) + cfr->cfr_dma_aborts++; + cfr->tx_evt_cnt++; + lut->tx_recv =3D true; + } else if (event_type =3D=3D ATH11K_CORRELATE_DBR_EVENT) { + cfr->dbr_evt_cnt++; + lut->dbr_recv =3D true; + } + + if (lut->dbr_recv && lut->tx_recv) { + if (lut->dbr_ppdu_id =3D=3D lut->tx_ppdu_id) { + /* + * 64-bit counters make wraparound highly improbable, + * wraparound handling is omitted. + */ + cfr->last_success_tstamp =3D lut->dbr_tstamp; + if (lut->dbr_tstamp > lut->txrx_tstamp) { + diff =3D lut->dbr_tstamp - lut->txrx_tstamp; + ath11k_dbg(ar->ab, ATH11K_DBG_CFR, + "txrx event -> dbr event delay =3D %u ms", + jiffies_to_msecs(diff)); + } else if (lut->txrx_tstamp > lut->dbr_tstamp) { + diff =3D lut->txrx_tstamp - lut->dbr_tstamp; + ath11k_dbg(ar->ab, ATH11K_DBG_CFR, + "dbr event -> txrx event delay =3D %u ms", + jiffies_to_msecs(diff)); + } + + ath11k_cfr_free_pending_dbr_events(ar); + + cfr->release_cnt++; + status =3D ATH11K_CORRELATE_STATUS_RELEASE; + } else { + /* + * Discard TXRX event on PPDU ID mismatch because multiple PPDUs + * may share the same DMA address due to ucode aborts. + */ + + ath11k_dbg(ar->ab, ATH11K_DBG_CFR, + "Received dbr event twice for the same lut entry"); + lut->tx_recv =3D false; + lut->tx_ppdu_id =3D 0; + cfr->clear_txrx_event++; + cfr->cfr_dma_aborts++; + status =3D ATH11K_CORRELATE_STATUS_HOLD; + } + } else { + status =3D ATH11K_CORRELATE_STATUS_HOLD; + } + + return status; +} + static int ath11k_cfr_process_data(struct ath11k *ar, struct ath11k_dbring_data *param) { - return 0; + u32 end_magic =3D ATH11K_CFR_END_MAGIC; + struct ath11k_csi_cfr_header *header; + struct ath11k_cfr_dma_hdr *dma_hdr; + struct ath11k_cfr *cfr =3D &ar->cfr; + struct ath11k_look_up_table *lut; + struct ath11k_base *ab =3D ar->ab; + u32 buf_id, tones, length; + u8 num_chains; + int status; + u8 *data; + + data =3D param->data; + buf_id =3D param->buf_id; + + if (param->data_sz < sizeof(*dma_hdr)) + return -EINVAL; + + dma_hdr =3D (struct ath11k_cfr_dma_hdr *)data; + + tones =3D ath11k_cfr_calculate_tones_from_dma_hdr(dma_hdr); + if (tones =3D=3D TONES_INVALID) { + ath11k_warn(ar->ab, "Number of tones received is invalid\n"); + return -EINVAL; + } + + num_chains =3D FIELD_GET(CFIR_DMA_HDR_INFO1_NUM_CHAINS, + dma_hdr->info1); + + length =3D sizeof(*dma_hdr); + length +=3D tones * (num_chains + 1); + + spin_lock_bh(&cfr->lut_lock); + + if (!cfr->lut) { + spin_unlock_bh(&cfr->lut_lock); + return -EINVAL; + } + + lut =3D &cfr->lut[buf_id]; + + ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "data_from_buf_rel:", "", + data, length); + + lut->buff =3D param->buff; + lut->data =3D data; + lut->data_len =3D length; + lut->dbr_ppdu_id =3D dma_hdr->phy_ppdu_id; + lut->dbr_tstamp =3D jiffies; + + memcpy(&lut->hdr, dma_hdr, sizeof(*dma_hdr)); + + header =3D &lut->header; + header->meta_data.channel_bw =3D FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_= BW, + dma_hdr->info1); + header->meta_data.length =3D length; + + status =3D ath11k_cfr_correlate_and_relay(ar, lut, + ATH11K_CORRELATE_DBR_EVENT); + if (status =3D=3D ATH11K_CORRELATE_STATUS_RELEASE) { + ath11k_dbg(ab, ATH11K_DBG_CFR, + "releasing CFR data to user space"); + ath11k_cfr_rfs_write(ar, &lut->header, + sizeof(struct ath11k_csi_cfr_header), + lut->data, lut->data_len, + &end_magic, sizeof(u32)); + ath11k_cfr_release_lut_entry(lut); + } else if (status =3D=3D ATH11K_CORRELATE_STATUS_HOLD) { + ath11k_dbg(ab, ATH11K_DBG_CFR, + "tx event is not yet received holding the buf"); + } + + spin_unlock_bh(&cfr->lut_lock); + + return status; } =20 /* Helper function to check whether the given peer mac address diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h index 19f136d34c65..c8e5086674d2 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.h +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -19,9 +19,78 @@ =20 #define HOST_MAX_CHAINS 8 =20 +enum ath11k_cfr_correlate_event_type { + ATH11K_CORRELATE_DBR_EVENT, + ATH11K_CORRELATE_TX_EVENT, +}; + struct ath11k_sta; struct ath11k_per_peer_cfr_capture; =20 +#define ATH11K_CFR_END_MAGIC 0xBEAFDEAD + +enum ath11k_cfr_correlate_status { + ATH11K_CORRELATE_STATUS_RELEASE, + ATH11K_CORRELATE_STATUS_HOLD, + ATH11K_CORRELATE_STATUS_ERR, +}; + +enum ath11k_cfr_preamble_type { + ATH11K_CFR_PREAMBLE_TYPE_LEGACY, + ATH11K_CFR_PREAMBLE_TYPE_HT, + ATH11K_CFR_PREAMBLE_TYPE_VHT, +}; + +struct cfr_metadata { + u8 peer_addr[ETH_ALEN]; + u8 status; + u8 capture_bw; + u8 channel_bw; + u8 phy_mode; + u16 prim20_chan; + u16 center_freq1; + u16 center_freq2; + u8 capture_mode; + u8 capture_type; + u8 sts_count; + u8 num_rx_chain; + u32 timestamp; + u32 length; + u32 chain_rssi[HOST_MAX_CHAINS]; + u16 chain_phase[HOST_MAX_CHAINS]; + u32 cfo_measurement; + u8 agc_gain[HOST_MAX_CHAINS]; + u32 rx_start_ts; +} __packed; + +struct ath11k_csi_cfr_header { + u32 start_magic_num; + u32 vendorid; + u8 cfr_metadata_version; + u8 cfr_data_version; + u8 chip_type; + u8 platform_type; + u32 reserved; + struct cfr_metadata meta_data; +} __packed; + +#define TONES_IN_20MHZ 256 +#define TONES_IN_40MHZ 512 +#define TONES_IN_80MHZ 1024 +#define TONES_IN_160MHZ 2048 /* 160 MHz isn't supported yet */ +#define TONES_INVALID 0 + +#define CFIR_DMA_HDR_INFO0_TAG GENMASK(7, 0) +#define CFIR_DMA_HDR_INFO0_LEN GENMASK(13, 8) + +#define CFIR_DMA_HDR_INFO1_UPLOAD_DONE GENMASK(0, 0) +#define CFIR_DMA_HDR_INFO1_CAPTURE_TYPE GENMASK(3, 1) +#define CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE GENMASK(5, 4) +#define CFIR_DMA_HDR_INFO1_NSS GENMASK(8, 6) +#define CFIR_DMA_HDR_INFO1_NUM_CHAINS GENMASK(11, 9) +#define CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW GENMASK(14, 12) +#define CFIR_DMA_HDR_INFO1_SW_PEER_ID_VALID GENMASK(15, 15) + struct ath11k_cfr_dma_hdr { u16 info0; u16 info1; @@ -37,6 +106,7 @@ struct ath11k_look_up_table { u16 dbr_ppdu_id; u16 tx_ppdu_id; dma_addr_t dbr_address; + struct ath11k_csi_cfr_header header; struct ath11k_cfr_dma_hdr hdr; u64 txrx_tstamp; u64 dbr_tstamp; @@ -109,6 +179,8 @@ int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k = *ar, struct ath11k_sta *arsta, struct ath11k_per_peer_cfr_capture *params, const u8 *peer_mac); +struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar); +void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut); =20 #else static inline int ath11k_cfr_init(struct ath11k_base *ab) @@ -156,5 +228,15 @@ ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, { return 0; } + +static inline void ath11k_cfr_release_lut_entry(struct ath11k_look_up_tabl= e *lut) +{ +} + +static inline +struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar) +{ + return NULL; +} #endif /* CONFIG_ATH11K_CFR */ #endif /* ATH11K_CFR_H */ diff --git a/drivers/net/wireless/ath/ath11k/dbring.c b/drivers/net/wireles= s/ath/ath11k/dbring.c index ed2b781a6bab..d6994ce6ebff 100644 --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c @@ -295,6 +295,7 @@ int ath11k_dbring_buffer_release_event(struct ath11k_ba= se *ab, int size; dma_addr_t paddr; int ret =3D 0; + int status; =20 pdev_idx =3D ev->fixed.pdev_id; module_id =3D ev->fixed.module_id; @@ -328,6 +329,9 @@ int ath11k_dbring_buffer_release_event(struct ath11k_ba= se *ab, case WMI_DIRECT_BUF_SPECTRAL: ring =3D ath11k_spectral_get_dbring(ar); break; + case WMI_DIRECT_BUF_CFR: + ring =3D ath11k_cfr_get_dbring(ar); + break; default: ring =3D NULL; ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n", @@ -378,8 +382,12 @@ int ath11k_dbring_buffer_release_event(struct ath11k_b= ase *ab, handler_data.data =3D PTR_ALIGN(vaddr_unalign, ring->buf_align); handler_data.data_sz =3D ring->buf_sz; + handler_data.buff =3D buff; + handler_data.buf_id =3D buf_id; =20 - ring->handler(ar, &handler_data); + status =3D ring->handler(ar, &handler_data); + if (status =3D=3D ATH11K_CORRELATE_STATUS_HOLD) + continue; } =20 buff->paddr =3D 0; diff --git a/drivers/net/wireless/ath/ath11k/dbring.h b/drivers/net/wireles= s/ath/ath11k/dbring.h index 0a380120f7a0..e5f244dfa963 100644 --- a/drivers/net/wireless/ath/ath11k/dbring.h +++ b/drivers/net/wireless/ath/ath11k/dbring.h @@ -21,6 +21,8 @@ struct ath11k_dbring_data { void *data; u32 data_sz; struct wmi_dma_buf_release_meta_data meta; + struct ath11k_dbring_element *buff; + u32 buf_id; }; =20 struct ath11k_dbring_buf_release_event { diff --git a/drivers/net/wireless/ath/ath11k/debug.h b/drivers/net/wireless= /ath/ath11k/debug.h index cc8934d15697..aaa0034527a5 100644 --- a/drivers/net/wireless/ath/ath11k/debug.h +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights res= erved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ =20 #ifndef _ATH11K_DEBUG_H_ @@ -27,6 +27,8 @@ enum ath11k_debug_mask { ATH11K_DBG_DP_TX =3D 0x00002000, ATH11K_DBG_DP_RX =3D 0x00004000, ATH11K_DBG_CE =3D 0x00008000, + ATH11K_DBG_CFR =3D 0x00010000, + ATH11K_DBG_CFR_DUMP =3D 0x00020000, }; =20 static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask) @@ -64,6 +66,10 @@ static inline const char *ath11k_dbg_str(enum ath11k_deb= ug_mask mask) return "dp_rx"; case ATH11K_DBG_CE: return "ce"; + case ATH11K_DBG_CFR: + return "cfr"; + case ATH11K_DBG_CFR_DUMP: + return "cfr_dump"; =20 /* no default handler to allow compiler to check that the * enum is fully handled --=20 2.34.1 From nobody Sun Dec 14 05:56:39 2025 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 939E533C51A for ; Wed, 5 Nov 2025 17:22:38 +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=1762363361; cv=none; b=W+rzjK+Re8YNhU98aLXEngZTpiRChwJVwytSKJGuqAtyoUBJTXPvwNqtQbq9TYoCUk51zxyHvcKYuxrZ6XZZRdp6IqDP2x//5cvRDpkoiwH/Z7ZdZCCKHH7DCY8YIX2zeNB94wKMCITGWL+h7v7m0fUz1K6rD0zOaxiJ9P/kVDI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762363361; c=relaxed/simple; bh=HOqt9BuedG5uKv1yKxuShwimEq1mdstx+e5yGAecMMU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GT3OVc5HdAopxg8yL+Nr3pS4ywXK0X9JajL+8AKgcSG+3OvyVf2ZQucXOrOVDcqf9WUkw7otQ6AJfYaonAxJz6gnJhyxADtqlBKVU523LCwSh4yPrGbh3OwfThEY21NUA6gLI7bEalNVYINhPXMIAI5bZ43MFgeGoAfbxLkezk4= 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=cU+phUa1; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=GfMaUepO; 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="cU+phUa1"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="GfMaUepO" Received: from pps.filterd (m0279865.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 5A5H2uor1379703 for ; Wed, 5 Nov 2025 17:22:38 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=zDYaxendOKg BXNHSEYqdstxwAT0j4LcK+vc404gFmq4=; b=cU+phUa1nSd2vrpn7DV7LYO5cGF OHSrBv99yDi6KVRGpGLjHS5s7ykNhBKe8uwXDIWzTpkxOaiz347rkkd83S1zzf4L vGs9bQ9kTvmhpuFbrNhEOxZWNsKYDDNuDvah8RdKLuq8/smjWaoY+LqX4edjvh/x V1nphjiQ7k8uBAn259cRdHpkBtQsxzOdo3522+kum/cOsUYzs6pGg/HkIP9ExICc zvVTZltiUBhANxiDcG1pHBb0EmJhwLlHq4bPcPqRcz4MrLuEI9U2jhQF9/sglVbp zabXolZl5BN0Q8lD/kcZZ3vgpIPmsmuvSA0HGjfkGnX6Uc8tO91ni+wl5CQ== Received: from mail-pf1-f197.google.com (mail-pf1-f197.google.com [209.85.210.197]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4a8amx82j0-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 05 Nov 2025 17:22:37 +0000 (GMT) Received: by mail-pf1-f197.google.com with SMTP id d2e1a72fcca58-7ae220b9d18so82692b3a.2 for ; Wed, 05 Nov 2025 09:22:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1762363357; x=1762968157; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zDYaxendOKgBXNHSEYqdstxwAT0j4LcK+vc404gFmq4=; b=GfMaUepOcs4s4o5vh8oDWBLwnRSsfvg1nfjJMBlUHU19kw6/MJoj/lonnGnFY7PS/V 7hXIb8mx5CN9/73uTr/k8WPDIpMFzee7oF4Hc6zZXga0FxjTQvRr3mIyEvxzn5uTXTRJ gxz1i/SkXjyUog8DjSFGCv+f+J4ioD0BiI8hLxmyocxdnBuzJGhBPhDrxhEq9SMfnYOd oo9OY2eIDCKwAtB/iVxdiCL/npN/CHU8cSbxo3CdHx1BEl4AYbpxpeXB4SLfvOv+ybAQ jc8U/zpU4AfqfMeOmJAHMMz9omU9yUAxyFoybkz4Mnpab66T5EH45h8lDDWJnPDYyTbs +p0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762363357; x=1762968157; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zDYaxendOKgBXNHSEYqdstxwAT0j4LcK+vc404gFmq4=; b=DbdLhTTd1Gbc8w4vQfBCzquU4qP8Nvcvj0dYV0orBdY74Z+cx8c1bGfPGfgiOobJOQ HPeXtyVT127QIzp3KFd7bhvoRMr4rc9lxPsJqMY8w1wMFp+pSzrmMWeSMKtUnyDTi4ro XzSrdzDQSpoorP49gl3FG3SWxe5BhMfsh+hYpQOfHKUAUoE+FhhTuz30t4XoWFXSB1Ua Z/UMe1jslt5EbdEBBvgbqrfMPV+E44OHzF2/GfE81EggRHUSlbo2qb486mI2WGqHVSYu 6M5460PBBpEH+X6d14cKYkbA7lfud7stzPrg0bd93yE0Zkl5sl7Pp5psctQjKzlYT0wn Evmg== X-Forwarded-Encrypted: i=1; AJvYcCW6xTW0Iqq/KQhl7i7iQd+sdj1wkctcPIFz04mEXJJNzRlcUoRz9M5ntTFVqN0Sf3ziwO++I9oU6iWqo8s=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+9aXd4wAib+UuidkuftLtlrMNXtTbu439ecoOHOsB9wFC3nVf TsUVQ8meTxuY77Hm9/mcho2nTyUmRShlLroeB6opffbzUJ9EbvvgpYK8XHwp3rMGj+bPKrf16dK 42nRfyOkRdUynGIhD/Skoure0l9jNNhr2/5OPSgXVDEJJw6EGPwh5FjNhNXdwCGMVkIA= X-Gm-Gg: ASbGncvCfkrmIEkk9r6LPcqtEfdnzmKOk4pnGmPOoHMNusd46dqW4YsrjgoDa05vplC racjl1znhDkH3sdnBxVcYyVbVMggWa6z+biFqnV44abJ0Ofi0Feghnp1K+HTtmK/qbZQstze8MF 8RmQhoWPWB3kAPneV/Gb2I3VORsdOyVotfgvyjhUiWWXKiiQvMt7xncQQXmL/5L5yAUc1XFLx/y 9yAM0bdRoCNIj7UsxEpD8QUoW/VkR53yzyJd1E9iWuHRlGeTIE69bo4N+8nGpCrUGOAL3DRIvQt JqUdPSmz+w0HF55LSyRjsstZZaZnAJQUDV5Szl1s4bi263CJXvkwbqfwTdMDbrhE/4DU5QYrdY8 rPftKrLoaohs6C4hch1Sghqv4lzHBvs6kpZs2eolv3bWF X-Received: by 2002:a05:6a00:1ac6:b0:7ad:df61:e67a with SMTP id d2e1a72fcca58-7ae1f48d17cmr4215975b3a.22.1762363356874; Wed, 05 Nov 2025 09:22:36 -0800 (PST) X-Google-Smtp-Source: AGHT+IGuHkiMFhW7PI2amrhRkIUX0V7Y9Yv0M9IU6zLbW3SZkFglf8nG7gtIKmKWmIk9hfTfSV6R1A== X-Received: by 2002:a05:6a00:1ac6:b0:7ad:df61:e67a with SMTP id d2e1a72fcca58-7ae1f48d17cmr4215933b3a.22.1762363356264; Wed, 05 Nov 2025 09:22:36 -0800 (PST) Received: from hu-yuzha-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7af48d83c20sm518014b3a.62.2025.11.05.09.22.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 09:22:35 -0800 (PST) From: "Yu Zhang(Yuriy)" To: jjohnson@kernel.org Cc: baochen.qiang@oss.qualcomm.com, linux-kernel@vger.kernel.org, linux-wireless@vger.kernel.org, ath11k@lists.infradead.org, Yu Zhang , Vasanthakumar Thiagarajan Subject: [PATCH ath-next v3 6/6] wifi: ath11k: Register handler for CFR capture event Date: Wed, 5 Nov 2025 09:22:26 -0800 Message-Id: <20251105172226.3182968-7-yu.zhang@oss.qualcomm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> References: <20251105172226.3182968-1-yu.zhang@oss.qualcomm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: kgz-YxvgcG_daGJ7nrT31Rv30HaVk7jP X-Authority-Analysis: v=2.4 cv=P443RyAu c=1 sm=1 tr=0 ts=690b87dd cx=c_pps a=rEQLjTOiSrHUhVqRoksmgQ==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=6UeiqGixMTsA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=RXpQw9b9vDifZkLeuRoA:9 a=2VI0MkxyNR6bbpdq8BZq:22 a=TjNXssC_j7lpFel5tvFf:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA1MDEzNSBTYWx0ZWRfXxVF+zey5657U U8k94YbB29pycTqh8Fyf6TLCM3udwsD6Edvo27cWN5P44wnfVlQfsiqnLjWwTbVIaexDwbZAGuv 2vaogEt4rA1FSlwxRvkkSClKWH+evzdXFuOeoRf1pY5g94SCbwf9rN2TVlmR/q72xNzuky5ZNi4 B9zPmE6LMeiNkh0FsAZRrVj1nvEHQ6k31tY+kJtH6y4GNmijNmN3lMY1iC4qzob/mL04LlGrNO/ OaJlBJ7eJyaTeGVMS4ADjk+HavmfDGPmov9EHB+7aj3ccHSoc8fhg6D3ORUtHA6uwRtocSohlaw XZgAFLN+SvtcVwrY2EvWLd9i6nwPAlyxn/R91xlv+O0d6IepVbLs/9fsFQ7oG651JFd4ohKyBBx SfjLzgIYRSZ6P8nvkIlzqQTeBaInaw== X-Proofpoint-ORIG-GUID: kgz-YxvgcG_daGJ7nrT31Rv30HaVk7jP X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-05_06,2025-11-03_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 priorityscore=1501 suspectscore=0 impostorscore=0 phishscore=0 malwarescore=0 bulkscore=0 lowpriorityscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2510240001 definitions=main-2511050135 Content-Type: text/plain; charset="utf-8" From: Venkateswara Naralasetty Firmware sends CFR meta data through the WMI event WMI_PEER_CFR_CAPTURE_EVENT. Parse the meta data coming from the firmware and invoke correlate_and_relay function to correlate the CFR meta data with the CFR payload coming from the other WMI event WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT. Release the buffer to user space once correlate and relay return success. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICO= NZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_I= OE-1 Signed-off-by: Venkateswara Naralasetty Co-developed-by: Yu Zhang (Yuriy) Signed-off-by: Yu Zhang (Yuriy) Reviewed-by: Vasanthakumar Thiagarajan Reviewed-by: Baochen Qiang --- drivers/net/wireless/ath/ath11k/cfr.c | 145 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/cfr.h | 62 ++++++++++- drivers/net/wireless/ath/ath11k/wmi.c | 90 ++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 44 ++++++++ 4 files changed, 340 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/a= th/ath11k/cfr.c index ee7626bd4b1a..3a42e54ddf80 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.c +++ b/drivers/net/wireless/ath/ath11k/cfr.c @@ -252,6 +252,151 @@ static int ath11k_cfr_process_data(struct ath11k *ar, return status; } =20 +static void ath11k_cfr_fill_hdr_info(struct ath11k *ar, + struct ath11k_csi_cfr_header *header, + struct ath11k_cfr_peer_tx_param *params) +{ + header->cfr_metadata_version =3D ATH11K_CFR_META_VERSION_4; + header->cfr_data_version =3D ATH11K_CFR_DATA_VERSION_1; + header->cfr_metadata_len =3D sizeof(struct cfr_metadata); + header->chip_type =3D ar->ab->hw_rev; + header->meta_data.status =3D FIELD_GET(WMI_CFR_PEER_CAPTURE_STATUS, + params->status); + header->meta_data.capture_bw =3D params->bandwidth; + header->meta_data.phy_mode =3D params->phy_mode; + header->meta_data.prim20_chan =3D params->primary_20mhz_chan; + header->meta_data.center_freq1 =3D params->band_center_freq1; + header->meta_data.center_freq2 =3D params->band_center_freq2; + + /* + * CFR capture is triggered by the ACK of a QoS Null frame: + * - 20 MHz: Legacy ACK + * - 40/80/160 MHz: DUP Legacy ACK + */ + header->meta_data.capture_mode =3D params->bandwidth ? + ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK : ATH11K_CFR_CAPTURE_LEGACY_ACK; + header->meta_data.capture_type =3D params->capture_method; + header->meta_data.num_rx_chain =3D ar->num_rx_chains; + header->meta_data.sts_count =3D params->spatial_streams; + header->meta_data.timestamp =3D params->timestamp_us; + ether_addr_copy(header->meta_data.peer_addr, params->peer_mac_addr); + memcpy(header->meta_data.chain_rssi, params->chain_rssi, + sizeof(params->chain_rssi)); + memcpy(header->meta_data.chain_phase, params->chain_phase, + sizeof(params->chain_phase)); + memcpy(header->meta_data.agc_gain, params->agc_gain, + sizeof(params->agc_gain)); +} + +int ath11k_process_cfr_capture_event(struct ath11k_base *ab, + struct ath11k_cfr_peer_tx_param *params) +{ + struct ath11k_look_up_table *lut =3D NULL; + u32 end_magic =3D ATH11K_CFR_END_MAGIC; + struct ath11k_csi_cfr_header *header; + struct ath11k_dbring_element *buff; + struct ath11k_cfr *cfr; + dma_addr_t buf_addr; + struct ath11k *ar; + u8 tx_status; + int status; + int i; + + rcu_read_lock(); + ar =3D ath11k_mac_get_ar_by_vdev_id(ab, params->vdev_id); + if (!ar) { + rcu_read_unlock(); + ath11k_warn(ab, "Failed to get ar for vdev id %d\n", + params->vdev_id); + return -ENOENT; + } + + cfr =3D &ar->cfr; + rcu_read_unlock(); + + if (WMI_CFR_CAPTURE_STATUS_PEER_PS & params->status) { + ath11k_warn(ab, "CFR capture failed as peer %pM is in powersave", + params->peer_mac_addr); + return -EINVAL; + } + + if (!(WMI_CFR_PEER_CAPTURE_STATUS & params->status)) { + ath11k_warn(ab, "CFR capture failed for the peer : %pM", + params->peer_mac_addr); + cfr->tx_peer_status_cfr_fail++; + return -EINVAL; + } + + tx_status =3D FIELD_GET(WMI_CFR_FRAME_TX_STATUS, params->status); + if (tx_status !=3D WMI_FRAME_TX_STATUS_OK) { + ath11k_warn(ab, "WMI tx status %d for the peer %pM", + tx_status, params->peer_mac_addr); + cfr->tx_evt_status_cfr_fail++; + return -EINVAL; + } + + buf_addr =3D (((u64)FIELD_GET(WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH, + params->correlation_info_2)) << 32) | + params->correlation_info_1; + + spin_lock_bh(&cfr->lut_lock); + + if (!cfr->lut) { + spin_unlock_bh(&cfr->lut_lock); + return -EINVAL; + } + + for (i =3D 0; i < cfr->lut_num; i++) { + struct ath11k_look_up_table *temp =3D &cfr->lut[i]; + + if (temp->dbr_address =3D=3D buf_addr) { + lut =3D &cfr->lut[i]; + break; + } + } + + if (!lut) { + spin_unlock_bh(&cfr->lut_lock); + ath11k_warn(ab, "lut failure to process tx event\n"); + cfr->tx_dbr_lookup_fail++; + return -EINVAL; + } + + lut->tx_ppdu_id =3D FIELD_GET(WMI_CFR_CORRELATION_INFO2_PPDU_ID, + params->correlation_info_2); + lut->txrx_tstamp =3D jiffies; + + header =3D &lut->header; + header->start_magic_num =3D ATH11K_CFR_START_MAGIC; + header->vendorid =3D VENDOR_QCA; + header->platform_type =3D PLATFORM_TYPE_ARM; + + ath11k_cfr_fill_hdr_info(ar, header, params); + + status =3D ath11k_cfr_correlate_and_relay(ar, lut, + ATH11K_CORRELATE_TX_EVENT); + if (status =3D=3D ATH11K_CORRELATE_STATUS_RELEASE) { + ath11k_dbg(ab, ATH11K_DBG_CFR, + "Releasing CFR data to user space"); + ath11k_cfr_rfs_write(ar, &lut->header, + sizeof(struct ath11k_csi_cfr_header), + lut->data, lut->data_len, + &end_magic, sizeof(u32)); + buff =3D lut->buff; + ath11k_cfr_release_lut_entry(lut); + + ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, buff, + WMI_DIRECT_BUF_CFR); + } else if (status =3D=3D ATH11K_CORRELATE_STATUS_HOLD) { + ath11k_dbg(ab, ATH11K_DBG_CFR, + "dbr event is not yet received holding buf\n"); + } + + spin_unlock_bh(&cfr->lut_lock); + + return 0; +} + /* Helper function to check whether the given peer mac address * is in unassociated peer pool or not. */ diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/a= th/ath11k/cfr.h index c8e5086674d2..b17a8ca16b69 100644 --- a/drivers/net/wireless/ath/ath11k/cfr.h +++ b/drivers/net/wireless/ath/ath11k/cfr.h @@ -27,8 +27,37 @@ enum ath11k_cfr_correlate_event_type { struct ath11k_sta; struct ath11k_per_peer_cfr_capture; =20 +#define ATH11K_CFR_START_MAGIC 0xDEADBEAF #define ATH11K_CFR_END_MAGIC 0xBEAFDEAD =20 +#define VENDOR_QCA 0x8cfdf0 +#define PLATFORM_TYPE_ARM 2 + +enum ath11k_cfr_meta_version { + ATH11K_CFR_META_VERSION_NONE, + ATH11K_CFR_META_VERSION_1, + ATH11K_CFR_META_VERSION_2, + ATH11K_CFR_META_VERSION_3, + ATH11K_CFR_META_VERSION_4, + ATH11K_CFR_META_VERSION_MAX =3D 0xFF, +}; + +enum ath11k_cfr_data_version { + ATH11K_CFR_DATA_VERSION_NONE, + ATH11K_CFR_DATA_VERSION_1, + ATH11K_CFR_DATA_VERSION_MAX =3D 0xFF, +}; + +enum ath11k_cfr_capture_ack_mode { + ATH11K_CFR_CAPTURE_LEGACY_ACK, + ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK, + ATH11K_CFR_CAPTURE_HT_ACK, + ATH11K_CFR_CAPTURE_VHT_ACK, + + /*Always keep this at last*/ + ATH11K_CFR_CAPTURE_INVALID_ACK +}; + enum ath11k_cfr_correlate_status { ATH11K_CORRELATE_STATUS_RELEASE, ATH11K_CORRELATE_STATUS_HOLD, @@ -41,6 +70,28 @@ enum ath11k_cfr_preamble_type { ATH11K_CFR_PREAMBLE_TYPE_VHT, }; =20 +struct ath11k_cfr_peer_tx_param { + u32 capture_method; + u32 vdev_id; + u8 peer_mac_addr[ETH_ALEN]; + u32 primary_20mhz_chan; + u32 bandwidth; + u32 phy_mode; + u32 band_center_freq1; + u32 band_center_freq2; + u32 spatial_streams; + u32 correlation_info_1; + u32 correlation_info_2; + u32 status; + u32 timestamp_us; + u32 counter; + u32 chain_rssi[WMI_MAX_CHAINS]; + u16 chain_phase[WMI_MAX_CHAINS]; + u32 cfo_measurement; + u8 agc_gain[HOST_MAX_CHAINS]; + u32 rx_start_ts; +}; + struct cfr_metadata { u8 peer_addr[ETH_ALEN]; u8 status; @@ -70,7 +121,7 @@ struct ath11k_csi_cfr_header { u8 cfr_data_version; u8 chip_type; u8 platform_type; - u32 reserved; + u32 cfr_metadata_len; struct cfr_metadata meta_data; } __packed; =20 @@ -181,6 +232,8 @@ int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k = *ar, const u8 *peer_mac); struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar); void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut); +int ath11k_process_cfr_capture_event(struct ath11k_base *ab, + struct ath11k_cfr_peer_tx_param *params); =20 #else static inline int ath11k_cfr_init(struct ath11k_base *ab) @@ -238,5 +291,12 @@ struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath= 11k *ar) { return NULL; } + +static inline +int ath11k_process_cfr_capture_event(struct ath11k_base *ab, + struct ath11k_cfr_peer_tx_param *params) +{ + return 0; +} #endif /* CONFIG_ATH11K_CFR */ #endif /* ATH11K_CFR_H */ diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/a= th/ath11k/wmi.c index 0b4cc943c290..65f084524855 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8802,6 +8802,93 @@ static void ath11k_wmi_p2p_noa_event(struct ath11k_b= ase *ab, kfree(tb); } =20 +static void ath11k_wmi_tlv_cfr_capture_event_fixed_param(const void *ptr, + void *data) +{ + struct ath11k_cfr_peer_tx_param *tx_params =3D data; + const struct ath11k_wmi_cfr_peer_tx_event_param *params =3D ptr; + + tx_params->capture_method =3D params->capture_method; + tx_params->vdev_id =3D params->vdev_id; + ether_addr_copy(tx_params->peer_mac_addr, params->mac_addr.addr); + tx_params->primary_20mhz_chan =3D params->chan_mhz; + tx_params->bandwidth =3D params->bandwidth; + tx_params->phy_mode =3D params->phy_mode; + tx_params->band_center_freq1 =3D params->band_center_freq1; + tx_params->band_center_freq2 =3D params->band_center_freq2; + tx_params->spatial_streams =3D params->sts_count; + tx_params->correlation_info_1 =3D params->correlation_info_1; + tx_params->correlation_info_2 =3D params->correlation_info_2; + tx_params->status =3D params->status; + tx_params->timestamp_us =3D params->timestamp_us; + tx_params->counter =3D params->counter; + tx_params->rx_start_ts =3D params->rx_start_ts; + + memcpy(tx_params->chain_rssi, params->chain_rssi, + sizeof(tx_params->chain_rssi)); + + if (WMI_CFR_CFO_MEASUREMENT_VALID & params->cfo_measurement) + tx_params->cfo_measurement =3D FIELD_GET(WMI_CFR_CFO_MEASUREMENT_RAW_DAT= A, + params->cfo_measurement); +} + +static void ath11k_wmi_tlv_cfr_capture_phase_fixed_param(const void *ptr, + void *data) +{ + struct ath11k_cfr_peer_tx_param *tx_params =3D data; + const struct ath11k_wmi_cfr_peer_tx_event_phase_param *params =3D ptr; + int i; + + for (i =3D 0; i < WMI_MAX_CHAINS; i++) { + tx_params->chain_phase[i] =3D params->chain_phase[i]; + tx_params->agc_gain[i] =3D params->agc_gain[i]; + } +} + +static int ath11k_wmi_tlv_cfr_capture_evt_parse(struct ath11k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) +{ + switch (tag) { + case WMI_TAG_PEER_CFR_CAPTURE_EVENT: + ath11k_wmi_tlv_cfr_capture_event_fixed_param(ptr, data); + break; + case WMI_TAG_CFR_CAPTURE_PHASE_PARAM: + ath11k_wmi_tlv_cfr_capture_phase_fixed_param(ptr, data); + break; + default: + ath11k_warn(ab, "Invalid tag received tag %d len %d\n", + tag, len); + return -EINVAL; + } + + return 0; +} + +static void ath11k_wmi_parse_cfr_capture_event(struct ath11k_base *ab, + struct sk_buff *skb) +{ + struct ath11k_cfr_peer_tx_param params =3D {}; + int ret; + + ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "cfr_dump:", "", + skb->data, skb->len); + + ret =3D ath11k_wmi_tlv_iter(ab, skb->data, skb->len, + ath11k_wmi_tlv_cfr_capture_evt_parse, + ¶ms); + if (ret) { + ath11k_warn(ab, "failed to parse cfr capture event tlv %d\n", + ret); + return; + } + + ret =3D ath11k_process_cfr_capture_event(ab, ¶ms); + if (ret) + ath11k_dbg(ab, ATH11K_DBG_CFR, + "failed to process cfr capture ret =3D %d\n", ret); +} + static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *s= kb) { struct wmi_cmd_hdr *cmd_hdr; @@ -8932,6 +9019,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *= ab, struct sk_buff *skb) case WMI_P2P_NOA_EVENTID: ath11k_wmi_p2p_noa_event(ab, skb); break; + case WMI_PEER_CFR_CAPTURE_EVENTID: + ath11k_wmi_parse_cfr_capture_event(ab, skb); + break; default: ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id); break; diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/a= th/ath11k/wmi.h index afc78fa4389b..baed501b640b 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -1889,6 +1889,8 @@ enum wmi_tlv_tag { WMI_TAG_NDP_EVENT, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD =3D 0x301, WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO, + WMI_TAG_PEER_CFR_CAPTURE_EVENT =3D 0x317, + WMI_TAG_CFR_CAPTURE_PHASE_PARAM =3D 0x33b, WMI_TAG_FILS_DISCOVERY_TMPL_CMD =3D 0x344, WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD =3D 0x37b, WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, @@ -4237,6 +4239,48 @@ enum ath11k_wmi_cfr_capture_method { WMI_CFR_CAPTURE_METHOD_MAX, }; =20 +#define WMI_CFR_FRAME_TX_STATUS GENMASK(1, 0) +#define WMI_CFR_CAPTURE_STATUS_PEER_PS BIT(30) +#define WMI_CFR_PEER_CAPTURE_STATUS BIT(31) + +#define WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH GENMASK(3, 0) +#define WMI_CFR_CORRELATION_INFO2_PPDU_ID GENMASK(31, 16) + +#define WMI_CFR_CFO_MEASUREMENT_VALID BIT(0) +#define WMI_CFR_CFO_MEASUREMENT_RAW_DATA GENMASK(14, 1) + +struct ath11k_wmi_cfr_peer_tx_event_param { + u32 capture_method; + u32 vdev_id; + struct wmi_mac_addr mac_addr; + u32 chan_mhz; + u32 bandwidth; + u32 phy_mode; + u32 band_center_freq1; + u32 band_center_freq2; + u32 sts_count; + u32 correlation_info_1; + u32 correlation_info_2; + u32 status; + u32 timestamp_us; + u32 counter; + u32 chain_rssi[WMI_MAX_CHAINS]; + u32 cfo_measurement; + u32 rx_start_ts; +} __packed; + +struct ath11k_wmi_cfr_peer_tx_event_phase_param { + u32 chain_phase[WMI_MAX_CHAINS]; + u8 agc_gain[WMI_MAX_CHAINS]; +} __packed; + +enum ath11k_wmi_frame_tx_status { + WMI_FRAME_TX_STATUS_OK, + WMI_FRAME_TX_STATUS_XRETRY, + WMI_FRAME_TX_STATUS_DROP, + WMI_FRAME_TX_STATUS_FILTERED, +}; + struct wmi_peer_cfr_capture_conf_arg { enum ath11k_wmi_cfr_capture_bw bw; enum ath11k_wmi_cfr_capture_method method; --=20 2.34.1