xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_cfr.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
6*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
7*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*5113495bSYour Name  */
17*5113495bSYour Name 
18*5113495bSYour Name /**
19*5113495bSYour Name  * DOC: wlan_hdd_cfr.c
20*5113495bSYour Name  *
21*5113495bSYour Name  * WLAN Host Device Driver CFR capture Implementation
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <linux/version.h>
25*5113495bSYour Name #include <linux/module.h>
26*5113495bSYour Name #include <linux/kernel.h>
27*5113495bSYour Name #include <net/cfg80211.h>
28*5113495bSYour Name #include "wlan_hdd_includes.h"
29*5113495bSYour Name #include "osif_sync.h"
30*5113495bSYour Name #include "wlan_hdd_cfr.h"
31*5113495bSYour Name #include "wlan_cfr_ucfg_api.h"
32*5113495bSYour Name #include "wlan_hdd_object_manager.h"
33*5113495bSYour Name #include "wlan_cmn.h"
34*5113495bSYour Name #include "wlan_policy_mgr_ll_sap.h"
35*5113495bSYour Name 
36*5113495bSYour Name const struct nla_policy cfr_config_policy[
37*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1] = {
38*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR] =
39*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
40*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE] = {.type = NLA_FLAG},
41*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH] = {.type = NLA_U8},
42*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY] = {.type = NLA_U32},
43*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD] = {.type = NLA_U8},
44*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION] = {.type = NLA_U8},
45*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE] = {
46*5113495bSYour Name 						.type = NLA_FLAG},
47*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP] = {
48*5113495bSYour Name 						.type = NLA_U32},
49*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION] = {.type = NLA_U32},
50*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL] = {.type = NLA_U32},
51*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE] = {.type = NLA_U32},
52*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK] = {.type = NLA_U64},
53*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT] = {
54*5113495bSYour Name 						.type = NLA_U32},
55*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE] = {
56*5113495bSYour Name 						.type = NLA_NESTED},
57*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY] = {
58*5113495bSYour Name 						.type = NLA_NESTED},
59*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER] = {.type = NLA_U32},
60*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA] =
61*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
62*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA] =
63*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
64*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK] =
65*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
66*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK] =
67*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
68*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS] = {.type = NLA_U32},
69*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW] = {.type = NLA_U32},
70*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER] = {
71*5113495bSYour Name 						.type = NLA_U32},
72*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER] = {
73*5113495bSYour Name 						.type = NLA_U32},
74*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER] = {
75*5113495bSYour Name 						.type = NLA_U32},
76*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE] = {
77*5113495bSYour Name 						.type = NLA_U8},
78*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID] = {
79*5113495bSYour Name 						.type = NLA_U32},
80*5113495bSYour Name };
81*5113495bSYour Name 
82*5113495bSYour Name #ifdef WLAN_ENH_CFR_ENABLE
83*5113495bSYour Name static void
wlan_hdd_transport_mode_cfg(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,uint32_t pid,enum qca_wlan_vendor_cfr_data_transport_modes tx_mode)84*5113495bSYour Name wlan_hdd_transport_mode_cfg(struct wlan_objmgr_pdev *pdev,
85*5113495bSYour Name 			    uint8_t vdev_id, uint32_t pid,
86*5113495bSYour Name 			    enum qca_wlan_vendor_cfr_data_transport_modes tx_mode)
87*5113495bSYour Name {
88*5113495bSYour Name 	struct pdev_cfr *pa;
89*5113495bSYour Name 
90*5113495bSYour Name 	if (!pdev) {
91*5113495bSYour Name 		hdd_err("failed to %s transport mode cb for cfr, pdev is NULL for vdev id %d",
92*5113495bSYour Name 			tx_mode ? "register" : "deregister", vdev_id);
93*5113495bSYour Name 		return;
94*5113495bSYour Name 	}
95*5113495bSYour Name 
96*5113495bSYour Name 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
97*5113495bSYour Name 	if (!pa) {
98*5113495bSYour Name 		hdd_err("cfr private obj is NULL for vdev id %d", vdev_id);
99*5113495bSYour Name 		return;
100*5113495bSYour Name 	}
101*5113495bSYour Name 	pa->nl_cb.vdev_id = vdev_id;
102*5113495bSYour Name 	pa->nl_cb.pid = pid;
103*5113495bSYour Name 	if (tx_mode == QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS)
104*5113495bSYour Name 		pa->nl_cb.cfr_nl_cb = hdd_cfr_data_send_nl_event;
105*5113495bSYour Name 	else
106*5113495bSYour Name 		pa->nl_cb.cfr_nl_cb = NULL;
107*5113495bSYour Name }
108*5113495bSYour Name 
109*5113495bSYour Name #define DEFAULT_CFR_NSS 0xff
110*5113495bSYour Name #define DEFAULT_CFR_BW  0xf
111*5113495bSYour Name static QDF_STATUS
wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev * vdev,struct nlattr * tb[])112*5113495bSYour Name wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev *vdev,
113*5113495bSYour Name 				   struct nlattr *tb[])
114*5113495bSYour Name {
115*5113495bSYour Name 	struct cfr_wlanconfig_param params = { 0 };
116*5113495bSYour Name 
117*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER]) {
118*5113495bSYour Name 		params.grp_id = nla_get_u32(tb[
119*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER]);
120*5113495bSYour Name 		hdd_debug("group_id %d", params.grp_id);
121*5113495bSYour Name 	}
122*5113495bSYour Name 
123*5113495bSYour Name 	if (params.grp_id >= HDD_INVALID_GROUP_ID) {
124*5113495bSYour Name 		hdd_err("invalid group id");
125*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
126*5113495bSYour Name 	}
127*5113495bSYour Name 
128*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA]) {
129*5113495bSYour Name 		nla_memcpy(&params.ta[0],
130*5113495bSYour Name 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA],
131*5113495bSYour Name 			   QDF_MAC_ADDR_SIZE);
132*5113495bSYour Name 		hdd_debug("ta " QDF_MAC_ADDR_FMT,
133*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&params.ta[0]));
134*5113495bSYour Name 	}
135*5113495bSYour Name 
136*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK]) {
137*5113495bSYour Name 		nla_memcpy(&params.ta_mask[0],
138*5113495bSYour Name 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK],
139*5113495bSYour Name 			   QDF_MAC_ADDR_SIZE);
140*5113495bSYour Name 		hdd_debug("ta_mask " QDF_MAC_ADDR_FMT,
141*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&params.ta_mask[0]));
142*5113495bSYour Name 	}
143*5113495bSYour Name 
144*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA]) {
145*5113495bSYour Name 		nla_memcpy(&params.ra[0],
146*5113495bSYour Name 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA],
147*5113495bSYour Name 			   QDF_MAC_ADDR_SIZE);
148*5113495bSYour Name 		hdd_debug("ra " QDF_MAC_ADDR_FMT,
149*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&params.ra[0]));
150*5113495bSYour Name 	}
151*5113495bSYour Name 
152*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK]) {
153*5113495bSYour Name 		nla_memcpy(&params.ra_mask[0],
154*5113495bSYour Name 			   tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK],
155*5113495bSYour Name 			   QDF_MAC_ADDR_SIZE);
156*5113495bSYour Name 		hdd_debug("ra_mask " QDF_MAC_ADDR_FMT,
157*5113495bSYour Name 			  QDF_MAC_ADDR_REF(&params.ra_mask[0]));
158*5113495bSYour Name 	}
159*5113495bSYour Name 
160*5113495bSYour Name 	if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)&params.ta) ||
161*5113495bSYour Name 	    !qdf_is_macaddr_zero((struct qdf_mac_addr *)&params.ra) ||
162*5113495bSYour Name 	    !qdf_is_macaddr_zero((struct qdf_mac_addr *)&params.ta_mask) ||
163*5113495bSYour Name 	    !qdf_is_macaddr_zero((struct qdf_mac_addr *)&params.ra_mask)) {
164*5113495bSYour Name 		hdd_debug("set tara config");
165*5113495bSYour Name 		ucfg_cfr_set_tara_config(vdev, &params);
166*5113495bSYour Name 	}
167*5113495bSYour Name 
168*5113495bSYour Name 	params.nss = DEFAULT_CFR_NSS;
169*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS]) {
170*5113495bSYour Name 		params.nss = nla_get_u32(tb[
171*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS]);
172*5113495bSYour Name 		hdd_debug("nss %d", params.nss);
173*5113495bSYour Name 	}
174*5113495bSYour Name 
175*5113495bSYour Name 	params.bw = DEFAULT_CFR_BW;
176*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW]) {
177*5113495bSYour Name 		params.bw = nla_get_u32(tb[
178*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW]);
179*5113495bSYour Name 		hdd_debug("bw %d", params.bw);
180*5113495bSYour Name 	}
181*5113495bSYour Name 
182*5113495bSYour Name 	if (params.nss || params.bw) {
183*5113495bSYour Name 		hdd_debug("set bw nss");
184*5113495bSYour Name 		ucfg_cfr_set_bw_nss(vdev, &params);
185*5113495bSYour Name 	}
186*5113495bSYour Name 
187*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER]) {
188*5113495bSYour Name 		params.expected_mgmt_subtype = nla_get_u32(tb[
189*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER]);
190*5113495bSYour Name 		hdd_debug("expected_mgmt_subtype %d(%x)",
191*5113495bSYour Name 			  params.expected_mgmt_subtype,
192*5113495bSYour Name 			  params.expected_mgmt_subtype);
193*5113495bSYour Name 	}
194*5113495bSYour Name 
195*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER]) {
196*5113495bSYour Name 		params.expected_ctrl_subtype = nla_get_u32(tb[
197*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER]);
198*5113495bSYour Name 		hdd_debug("expected_mgmt_subtype %d(%x)",
199*5113495bSYour Name 			  params.expected_ctrl_subtype,
200*5113495bSYour Name 			  params.expected_ctrl_subtype);
201*5113495bSYour Name 	}
202*5113495bSYour Name 
203*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER]) {
204*5113495bSYour Name 		params.expected_data_subtype = nla_get_u32(tb[
205*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER]);
206*5113495bSYour Name 		hdd_debug("expected_mgmt_subtype %d(%x)",
207*5113495bSYour Name 			  params.expected_data_subtype,
208*5113495bSYour Name 			  params.expected_data_subtype);
209*5113495bSYour Name 	}
210*5113495bSYour Name 
211*5113495bSYour Name 	if (!params.expected_mgmt_subtype ||
212*5113495bSYour Name 	    !params.expected_ctrl_subtype ||
213*5113495bSYour Name 		!params.expected_data_subtype) {
214*5113495bSYour Name 		hdd_debug("set frame type");
215*5113495bSYour Name 		ucfg_cfr_set_frame_type_subtype(vdev, &params);
216*5113495bSYour Name 	}
217*5113495bSYour Name 
218*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
219*5113495bSYour Name }
220*5113495bSYour Name 
convert_vendor_cfr_capture_type(enum qca_wlan_vendor_cfr_capture_type type)221*5113495bSYour Name static enum capture_type convert_vendor_cfr_capture_type(
222*5113495bSYour Name 			enum qca_wlan_vendor_cfr_capture_type type)
223*5113495bSYour Name {
224*5113495bSYour Name 	switch (type) {
225*5113495bSYour Name 	case QCA_WLAN_VENDOR_CFR_DIRECT_FTM:
226*5113495bSYour Name 		return RCC_DIRECTED_FTM_FILTER;
227*5113495bSYour Name 	case QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK:
228*5113495bSYour Name 		return RCC_ALL_FTM_ACK_FILTER;
229*5113495bSYour Name 	case QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP:
230*5113495bSYour Name 		return RCC_DIRECTED_NDPA_NDP_FILTER;
231*5113495bSYour Name 	case QCA_WLAN_VENDOR_CFR_TA_RA:
232*5113495bSYour Name 		return RCC_TA_RA_FILTER;
233*5113495bSYour Name 	case QCA_WLAN_VENDOR_CFR_ALL_PACKET:
234*5113495bSYour Name 		return RCC_NDPA_NDP_ALL_FILTER;
235*5113495bSYour Name 	default:
236*5113495bSYour Name 		hdd_err("invalid capture type");
237*5113495bSYour Name 		return RCC_DIS_ALL_MODE;
238*5113495bSYour Name 	}
239*5113495bSYour Name }
240*5113495bSYour Name 
241*5113495bSYour Name static int
wlan_cfg80211_cfr_set_config(struct wlan_objmgr_vdev * vdev,struct nlattr * tb[])242*5113495bSYour Name wlan_cfg80211_cfr_set_config(struct wlan_objmgr_vdev *vdev,
243*5113495bSYour Name 			     struct nlattr *tb[])
244*5113495bSYour Name {
245*5113495bSYour Name 	struct nlattr *group[QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1];
246*5113495bSYour Name 	struct nlattr *group_list;
247*5113495bSYour Name 	struct cfr_wlanconfig_param params = { 0 };
248*5113495bSYour Name 	enum capture_type type;
249*5113495bSYour Name 	enum qca_wlan_vendor_cfr_capture_type vendor_capture_type;
250*5113495bSYour Name 	int rem = 0;
251*5113495bSYour Name 	int maxtype;
252*5113495bSYour Name 	int attr;
253*5113495bSYour Name 	uint64_t ul_mu_user_mask = 0;
254*5113495bSYour Name 
255*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION]) {
256*5113495bSYour Name 		params.cap_dur = nla_get_u32(tb[
257*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION]);
258*5113495bSYour Name 		ucfg_cfr_set_capture_duration(vdev, &params);
259*5113495bSYour Name 		hdd_debug("params.cap_dur %d", params.cap_dur);
260*5113495bSYour Name 	}
261*5113495bSYour Name 
262*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL]) {
263*5113495bSYour Name 		params.cap_intvl = nla_get_u32(tb[
264*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL]);
265*5113495bSYour Name 		ucfg_cfr_set_capture_interval(vdev, &params);
266*5113495bSYour Name 		hdd_debug("params.cap_intvl %d", params.cap_intvl);
267*5113495bSYour Name 	}
268*5113495bSYour Name 
269*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE]) {
270*5113495bSYour Name 		vendor_capture_type = nla_get_u32(tb[
271*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE]);
272*5113495bSYour Name 		if ((vendor_capture_type < QCA_WLAN_VENDOR_CFR_DIRECT_FTM) ||
273*5113495bSYour Name 		    (vendor_capture_type > QCA_WLAN_VENDOR_CFR_ALL_PACKET)) {
274*5113495bSYour Name 			hdd_err_rl("invalid capture type %d",
275*5113495bSYour Name 				   vendor_capture_type);
276*5113495bSYour Name 			return -EINVAL;
277*5113495bSYour Name 		}
278*5113495bSYour Name 		type = convert_vendor_cfr_capture_type(vendor_capture_type);
279*5113495bSYour Name 		ucfg_cfr_set_rcc_mode(vdev, type, 1);
280*5113495bSYour Name 		hdd_debug("type %d", type);
281*5113495bSYour Name 	}
282*5113495bSYour Name 
283*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK]) {
284*5113495bSYour Name 		ul_mu_user_mask = nla_get_u64(tb[
285*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK]);
286*5113495bSYour Name 		hdd_debug("ul_mu_user_mask_lower %d",
287*5113495bSYour Name 			  params.ul_mu_user_mask_lower);
288*5113495bSYour Name 	}
289*5113495bSYour Name 
290*5113495bSYour Name 	if (ul_mu_user_mask) {
291*5113495bSYour Name 		params.ul_mu_user_mask_lower =
292*5113495bSYour Name 				(uint32_t)(ul_mu_user_mask & 0xffffffff);
293*5113495bSYour Name 		params.ul_mu_user_mask_lower =
294*5113495bSYour Name 				(uint32_t)(ul_mu_user_mask >> 32);
295*5113495bSYour Name 		hdd_debug("set ul mu user mask");
296*5113495bSYour Name 		ucfg_cfr_set_ul_mu_user_mask(vdev, &params);
297*5113495bSYour Name 	}
298*5113495bSYour Name 
299*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT]) {
300*5113495bSYour Name 		params.freeze_tlv_delay_cnt_thr = nla_get_u32(tb[
301*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT]);
302*5113495bSYour Name 		if (params.freeze_tlv_delay_cnt_thr) {
303*5113495bSYour Name 			params.freeze_tlv_delay_cnt_en = 1;
304*5113495bSYour Name 			ucfg_cfr_set_freeze_tlv_delay_cnt(vdev, &params);
305*5113495bSYour Name 			hdd_debug("freeze_tlv_delay_cnt_thr %d",
306*5113495bSYour Name 				  params.freeze_tlv_delay_cnt_thr);
307*5113495bSYour Name 		}
308*5113495bSYour Name 	}
309*5113495bSYour Name 
310*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE]) {
311*5113495bSYour Name 		maxtype = QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX;
312*5113495bSYour Name 		attr = QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE;
313*5113495bSYour Name 		nla_for_each_nested(group_list, tb[attr], rem) {
314*5113495bSYour Name 			if (wlan_cfg80211_nla_parse(group, maxtype,
315*5113495bSYour Name 						    nla_data(group_list),
316*5113495bSYour Name 						    nla_len(group_list),
317*5113495bSYour Name 						    cfr_config_policy)) {
318*5113495bSYour Name 				hdd_err("nla_parse failed for cfr config group");
319*5113495bSYour Name 				return -EINVAL;
320*5113495bSYour Name 			}
321*5113495bSYour Name 			wlan_cfg80211_cfr_set_group_config(vdev, group);
322*5113495bSYour Name 		}
323*5113495bSYour Name 	}
324*5113495bSYour Name 
325*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE]) {
326*5113495bSYour Name 		uint8_t transport_mode = 0xff;
327*5113495bSYour Name 		uint32_t pid = 0;
328*5113495bSYour Name 
329*5113495bSYour Name 		if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID])
330*5113495bSYour Name 			pid = nla_get_u32(tb[
331*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID]);
332*5113495bSYour Name 		else
333*5113495bSYour Name 			hdd_debug("No PID received");
334*5113495bSYour Name 
335*5113495bSYour Name 		transport_mode = nla_get_u8(tb[
336*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE]);
337*5113495bSYour Name 
338*5113495bSYour Name 		hdd_debug("tx mode attr %d, pid %d", transport_mode, pid);
339*5113495bSYour Name 		if (transport_mode == QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS ||
340*5113495bSYour Name 		    transport_mode == QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS) {
341*5113495bSYour Name 			wlan_hdd_transport_mode_cfg(vdev->vdev_objmgr.wlan_pdev,
342*5113495bSYour Name 						    vdev->vdev_objmgr.vdev_id,
343*5113495bSYour Name 						    pid, transport_mode);
344*5113495bSYour Name 		} else {
345*5113495bSYour Name 			hdd_debug("invalid transport mode %d for vdev id %d",
346*5113495bSYour Name 				  transport_mode, vdev->vdev_objmgr.vdev_id);
347*5113495bSYour Name 		}
348*5113495bSYour Name 	}
349*5113495bSYour Name 
350*5113495bSYour Name 	return 0;
351*5113495bSYour Name }
352*5113495bSYour Name 
hdd_stop_enh_cfr(struct wlan_objmgr_vdev * vdev)353*5113495bSYour Name static QDF_STATUS hdd_stop_enh_cfr(struct wlan_objmgr_vdev *vdev)
354*5113495bSYour Name {
355*5113495bSYour Name 	if (!ucfg_cfr_get_rcc_enabled(vdev))
356*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
357*5113495bSYour Name 
358*5113495bSYour Name 	hdd_debug("cleanup rcc mode");
359*5113495bSYour Name 	wlan_objmgr_vdev_try_get_ref(vdev, WLAN_CFR_ID);
360*5113495bSYour Name 	ucfg_cfr_set_rcc_mode(vdev, RCC_DIS_ALL_MODE, 0);
361*5113495bSYour Name 	ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev),
362*5113495bSYour Name 				     false);
363*5113495bSYour Name 	ucfg_cfr_committed_rcc_config(vdev);
364*5113495bSYour Name 	ucfg_cfr_stop_indication(vdev);
365*5113495bSYour Name 	ucfg_cfr_suspend(wlan_vdev_get_pdev(vdev));
366*5113495bSYour Name 	hdd_debug("stop indication done");
367*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
368*5113495bSYour Name 
369*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
370*5113495bSYour Name }
371*5113495bSYour Name 
hdd_cfr_disconnect(struct wlan_objmgr_vdev * vdev)372*5113495bSYour Name QDF_STATUS hdd_cfr_disconnect(struct wlan_objmgr_vdev *vdev)
373*5113495bSYour Name {
374*5113495bSYour Name 	return hdd_stop_enh_cfr(vdev);
375*5113495bSYour Name }
376*5113495bSYour Name 
377*5113495bSYour Name static int
wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter * adapter,struct nlattr ** tb)378*5113495bSYour Name wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter *adapter,
379*5113495bSYour Name 				   struct nlattr **tb)
380*5113495bSYour Name {
381*5113495bSYour Name 	struct cfr_wlanconfig_param params = { 0 };
382*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
383*5113495bSYour Name 	bool is_start_capture = false;
384*5113495bSYour Name 	int ret = 0;
385*5113495bSYour Name 
386*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]) {
387*5113495bSYour Name 		is_start_capture = nla_get_flag(tb[
388*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]);
389*5113495bSYour Name 	}
390*5113495bSYour Name 
391*5113495bSYour Name 	if (is_start_capture &&
392*5113495bSYour Name 	    !tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP]) {
393*5113495bSYour Name 		hdd_err("Invalid group bitmap");
394*5113495bSYour Name 		return -EINVAL;
395*5113495bSYour Name 	}
396*5113495bSYour Name 
397*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_CFR_ID);
398*5113495bSYour Name 	if (!vdev) {
399*5113495bSYour Name 		hdd_err("can't get vdev");
400*5113495bSYour Name 		return -EINVAL;
401*5113495bSYour Name 	}
402*5113495bSYour Name 
403*5113495bSYour Name 	if (is_start_capture) {
404*5113495bSYour Name 		ret = wlan_cfg80211_cfr_set_config(vdev, tb);
405*5113495bSYour Name 		if (ret) {
406*5113495bSYour Name 			hdd_err("set config failed");
407*5113495bSYour Name 			goto out;
408*5113495bSYour Name 		}
409*5113495bSYour Name 		params.en_cfg = nla_get_u32(tb[
410*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP]);
411*5113495bSYour Name 		hdd_debug("params.en_cfg %d", params.en_cfg);
412*5113495bSYour Name 		ucfg_cfr_set_en_bitmap(vdev, &params);
413*5113495bSYour Name 		ucfg_cfr_resume(wlan_vdev_get_pdev(vdev));
414*5113495bSYour Name 		ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev),
415*5113495bSYour Name 					     true);
416*5113495bSYour Name 		ucfg_cfr_committed_rcc_config(vdev);
417*5113495bSYour Name 	} else {
418*5113495bSYour Name 		hdd_stop_enh_cfr(vdev);
419*5113495bSYour Name 	}
420*5113495bSYour Name out:
421*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
422*5113495bSYour Name 	return ret;
423*5113495bSYour Name }
424*5113495bSYour Name #else
425*5113495bSYour Name static int
wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter * adapter,struct nlattr ** tb)426*5113495bSYour Name wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter *adapter,
427*5113495bSYour Name 				   struct nlattr **tb)
428*5113495bSYour Name {
429*5113495bSYour Name 	return 0;
430*5113495bSYour Name }
431*5113495bSYour Name #endif
432*5113495bSYour Name 
433*5113495bSYour Name #ifdef WLAN_CFR_ADRASTEA
434*5113495bSYour Name static QDF_STATUS
wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter * adapter,struct nlattr ** tb)435*5113495bSYour Name wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
436*5113495bSYour Name 					    struct nlattr **tb)
437*5113495bSYour Name {
438*5113495bSYour Name 	struct cfr_capture_params params = { 0 };
439*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
440*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
441*5113495bSYour Name 	struct wlan_objmgr_peer *peer;
442*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
443*5113495bSYour Name 	struct qdf_mac_addr peer_addr;
444*5113495bSYour Name 	bool is_start_capture = false;
445*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
446*5113495bSYour Name 
447*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR]) {
448*5113495bSYour Name 		hdd_err("peer mac addr not given");
449*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
450*5113495bSYour Name 	}
451*5113495bSYour Name 
452*5113495bSYour Name 	nla_memcpy(peer_addr.bytes, tb[QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR],
453*5113495bSYour Name 		   QDF_MAC_ADDR_SIZE);
454*5113495bSYour Name 
455*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]) {
456*5113495bSYour Name 		is_start_capture = nla_get_flag(tb[
457*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]);
458*5113495bSYour Name 	}
459*5113495bSYour Name 
460*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_CFR_ID);
461*5113495bSYour Name 	if (!vdev) {
462*5113495bSYour Name 		hdd_err("can't get vdev");
463*5113495bSYour Name 		return -EINVAL;
464*5113495bSYour Name 	}
465*5113495bSYour Name 
466*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
467*5113495bSYour Name 	if (!pdev) {
468*5113495bSYour Name 		hdd_err("failed to get pdev");
469*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
470*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
471*5113495bSYour Name 	}
472*5113495bSYour Name 
473*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
474*5113495bSYour Name 	if (!psoc) {
475*5113495bSYour Name 		hdd_err("Failed to get psoc");
476*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
477*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
478*5113495bSYour Name 	}
479*5113495bSYour Name 
480*5113495bSYour Name 	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_addr.bytes, WLAN_CFR_ID);
481*5113495bSYour Name 	if (!peer) {
482*5113495bSYour Name 		hdd_err("No peer object found");
483*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
484*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
485*5113495bSYour Name 	}
486*5113495bSYour Name 
487*5113495bSYour Name 	if (is_start_capture) {
488*5113495bSYour Name 		if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY]) {
489*5113495bSYour Name 			params.period = nla_get_u32(tb[
490*5113495bSYour Name 				QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY]);
491*5113495bSYour Name 			hdd_debug("params.periodicity %d", params.period);
492*5113495bSYour Name 			/* Set the periodic CFR */
493*5113495bSYour Name 			if (params.period)
494*5113495bSYour Name 				ucfg_cfr_set_timer(pdev, params.period);
495*5113495bSYour Name 		}
496*5113495bSYour Name 
497*5113495bSYour Name 		if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD]) {
498*5113495bSYour Name 			params.method = nla_get_u8(tb[
499*5113495bSYour Name 				QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD]);
500*5113495bSYour Name 			/* Adrastea supports only QOS NULL METHOD */
501*5113495bSYour Name 			if (params.method !=
502*5113495bSYour Name 					QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL) {
503*5113495bSYour Name 				hdd_err_rl("invalid capture method %d",
504*5113495bSYour Name 					   params.method);
505*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
506*5113495bSYour Name 				goto exit;
507*5113495bSYour Name 			}
508*5113495bSYour Name 		}
509*5113495bSYour Name 
510*5113495bSYour Name 		if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH]) {
511*5113495bSYour Name 			params.bandwidth = nla_get_u8(tb[
512*5113495bSYour Name 				QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH]);
513*5113495bSYour Name 			/* Adrastea supports only 20Mhz bandwidth CFR capture */
514*5113495bSYour Name 			if (params.bandwidth != NL80211_CHAN_WIDTH_20_NOHT) {
515*5113495bSYour Name 				hdd_err_rl("invalid capture bandwidth %d",
516*5113495bSYour Name 					   params.bandwidth);
517*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
518*5113495bSYour Name 				goto exit;
519*5113495bSYour Name 			}
520*5113495bSYour Name 		}
521*5113495bSYour Name 		ucfg_cfr_start_capture(pdev, peer, &params);
522*5113495bSYour Name 	} else {
523*5113495bSYour Name 		/* Disable the periodic CFR if enabled */
524*5113495bSYour Name 		if (ucfg_cfr_get_timer(pdev))
525*5113495bSYour Name 			ucfg_cfr_set_timer(pdev, 0);
526*5113495bSYour Name 
527*5113495bSYour Name 		/* Disable the peer CFR capture */
528*5113495bSYour Name 		ucfg_cfr_stop_capture(pdev, peer);
529*5113495bSYour Name 	}
530*5113495bSYour Name exit:
531*5113495bSYour Name 	wlan_objmgr_peer_release_ref(peer, WLAN_CFR_ID);
532*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
533*5113495bSYour Name 
534*5113495bSYour Name 	return status;
535*5113495bSYour Name }
536*5113495bSYour Name #elif defined(WLAN_CFR_DBR)
537*5113495bSYour Name static enum
convert_capture_bw(enum nl80211_chan_width capture_bw)538*5113495bSYour Name phy_ch_width convert_capture_bw(enum nl80211_chan_width capture_bw)
539*5113495bSYour Name {
540*5113495bSYour Name 	switch (capture_bw) {
541*5113495bSYour Name 	case NL80211_CHAN_WIDTH_20_NOHT:
542*5113495bSYour Name 	case NL80211_CHAN_WIDTH_20:
543*5113495bSYour Name 		return CH_WIDTH_20MHZ;
544*5113495bSYour Name 	case NL80211_CHAN_WIDTH_40:
545*5113495bSYour Name 		return CH_WIDTH_40MHZ;
546*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80:
547*5113495bSYour Name 		return CH_WIDTH_80MHZ;
548*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80P80:
549*5113495bSYour Name 		return CH_WIDTH_80P80MHZ;
550*5113495bSYour Name 	case NL80211_CHAN_WIDTH_160:
551*5113495bSYour Name 		return CH_WIDTH_160MHZ;
552*5113495bSYour Name 	case NL80211_CHAN_WIDTH_5:
553*5113495bSYour Name 		return CH_WIDTH_5MHZ;
554*5113495bSYour Name 	case NL80211_CHAN_WIDTH_10:
555*5113495bSYour Name 		return CH_WIDTH_10MHZ;
556*5113495bSYour Name 	default:
557*5113495bSYour Name 		hdd_err("invalid capture bw");
558*5113495bSYour Name 		return CH_WIDTH_INVALID;
559*5113495bSYour Name 	}
560*5113495bSYour Name }
561*5113495bSYour Name 
562*5113495bSYour Name static QDF_STATUS
wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter * adapter,struct nlattr ** tb)563*5113495bSYour Name wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
564*5113495bSYour Name 					    struct nlattr **tb)
565*5113495bSYour Name {
566*5113495bSYour Name 	struct cfr_capture_params params = { 0 };
567*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
568*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
569*5113495bSYour Name 	struct wlan_objmgr_peer *peer;
570*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
571*5113495bSYour Name 	struct qdf_mac_addr peer_addr;
572*5113495bSYour Name 	bool is_start_capture = false;
573*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
574*5113495bSYour Name 	int id;
575*5113495bSYour Name 
576*5113495bSYour Name 	id = QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR;
577*5113495bSYour Name 	if (!tb[id]) {
578*5113495bSYour Name 		hdd_err("peer mac addr not given");
579*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
580*5113495bSYour Name 	}
581*5113495bSYour Name 
582*5113495bSYour Name 	nla_memcpy(peer_addr.bytes, tb[id],
583*5113495bSYour Name 		   QDF_MAC_ADDR_SIZE);
584*5113495bSYour Name 
585*5113495bSYour Name 	id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE;
586*5113495bSYour Name 	if (tb[id])
587*5113495bSYour Name 		is_start_capture = nla_get_flag(tb[id]);
588*5113495bSYour Name 
589*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_CFR_ID);
590*5113495bSYour Name 	if (!vdev) {
591*5113495bSYour Name 		hdd_err("can't get vdev");
592*5113495bSYour Name 		return -EINVAL;
593*5113495bSYour Name 	}
594*5113495bSYour Name 
595*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
596*5113495bSYour Name 	if (!pdev) {
597*5113495bSYour Name 		hdd_err("failed to get pdev");
598*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
599*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
600*5113495bSYour Name 	}
601*5113495bSYour Name 
602*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
603*5113495bSYour Name 	if (!psoc) {
604*5113495bSYour Name 		hdd_err("Failed to get psoc");
605*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
606*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
607*5113495bSYour Name 	}
608*5113495bSYour Name 
609*5113495bSYour Name 	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_addr.bytes, WLAN_CFR_ID);
610*5113495bSYour Name 	if (!peer) {
611*5113495bSYour Name 		hdd_err("No peer object found");
612*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
613*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
614*5113495bSYour Name 	}
615*5113495bSYour Name 
616*5113495bSYour Name 	if (is_start_capture) {
617*5113495bSYour Name 		id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY;
618*5113495bSYour Name 		if (tb[id]) {
619*5113495bSYour Name 			params.period = nla_get_u32(tb[id]);
620*5113495bSYour Name 			hdd_debug("params.periodicity %d", params.period);
621*5113495bSYour Name 			/* Set the periodic CFR */
622*5113495bSYour Name 			if (params.period)
623*5113495bSYour Name 				ucfg_cfr_set_timer(pdev, params.period);
624*5113495bSYour Name 		}
625*5113495bSYour Name 		id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD;
626*5113495bSYour Name 		if (tb[id]) {
627*5113495bSYour Name 			params.method = nla_get_u8(tb[id]);
628*5113495bSYour Name 			/* Adrastea supports only QOS NULL METHOD */
629*5113495bSYour Name 			if (params.method !=
630*5113495bSYour Name 					QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL) {
631*5113495bSYour Name 				hdd_err_rl("invalid capture method %d",
632*5113495bSYour Name 					   params.method);
633*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
634*5113495bSYour Name 				goto exit;
635*5113495bSYour Name 			}
636*5113495bSYour Name 		}
637*5113495bSYour Name 		id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH;
638*5113495bSYour Name 		if (tb[id]) {
639*5113495bSYour Name 			params.bandwidth = nla_get_u8(tb[id]);
640*5113495bSYour Name 			params.bandwidth = convert_capture_bw(params.bandwidth);
641*5113495bSYour Name 			if (params.bandwidth > NL80211_CHAN_WIDTH_80) {
642*5113495bSYour Name 				hdd_err_rl("invalid capture bandwidth %d",
643*5113495bSYour Name 					   params.bandwidth);
644*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
645*5113495bSYour Name 				goto exit;
646*5113495bSYour Name 			}
647*5113495bSYour Name 		}
648*5113495bSYour Name 		ucfg_cfr_start_capture(pdev, peer, &params);
649*5113495bSYour Name 	} else {
650*5113495bSYour Name 		/* Disable the periodic CFR if enabled */
651*5113495bSYour Name 		if (ucfg_cfr_get_timer(pdev))
652*5113495bSYour Name 			ucfg_cfr_set_timer(pdev, 0);
653*5113495bSYour Name 
654*5113495bSYour Name 		/* Disable the peer CFR capture */
655*5113495bSYour Name 		ucfg_cfr_stop_capture(pdev, peer);
656*5113495bSYour Name 		ucfg_cfr_stop_indication(vdev);
657*5113495bSYour Name 	}
658*5113495bSYour Name exit:
659*5113495bSYour Name 	wlan_objmgr_peer_release_ref(peer, WLAN_CFR_ID);
660*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
661*5113495bSYour Name 
662*5113495bSYour Name 	return status;
663*5113495bSYour Name }
664*5113495bSYour Name 
665*5113495bSYour Name #else
666*5113495bSYour Name static QDF_STATUS
wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter * adapter,struct nlattr ** tb)667*5113495bSYour Name wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
668*5113495bSYour Name 					    struct nlattr **tb)
669*5113495bSYour Name {
670*5113495bSYour Name 	return QDF_STATUS_E_NOSUPPORT;
671*5113495bSYour Name }
672*5113495bSYour Name #endif
673*5113495bSYour Name 
674*5113495bSYour Name static int
wlan_cfg80211_peer_cfr_capture_cfg(struct wiphy * wiphy,struct hdd_adapter * adapter,const void * data,int data_len)675*5113495bSYour Name wlan_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
676*5113495bSYour Name 				   struct hdd_adapter *adapter,
677*5113495bSYour Name 				   const void *data,
678*5113495bSYour Name 				   int data_len)
679*5113495bSYour Name {
680*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1];
681*5113495bSYour Name 	uint8_t version = 0;
682*5113495bSYour Name 	QDF_STATUS status;
683*5113495bSYour Name 
684*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(
685*5113495bSYour Name 			tb,
686*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX,
687*5113495bSYour Name 			data,
688*5113495bSYour Name 			data_len,
689*5113495bSYour Name 			cfr_config_policy)) {
690*5113495bSYour Name 		hdd_err("Invalid ATTR");
691*5113495bSYour Name 		return -EINVAL;
692*5113495bSYour Name 	}
693*5113495bSYour Name 
694*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION]) {
695*5113495bSYour Name 		version = nla_get_u8(tb[
696*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION]);
697*5113495bSYour Name 		hdd_debug("version %d", version);
698*5113495bSYour Name 		if (version == LEGACY_CFR_VERSION) {
699*5113495bSYour Name 			status = wlan_cfg80211_peer_cfr_capture_cfg_adrastea(
700*5113495bSYour Name 								adapter, tb);
701*5113495bSYour Name 			return qdf_status_to_os_return(status);
702*5113495bSYour Name 		} else if (version != ENHANCED_CFR_VERSION) {
703*5113495bSYour Name 			hdd_err("unsupported version");
704*5113495bSYour Name 			return -EFAULT;
705*5113495bSYour Name 		}
706*5113495bSYour Name 	}
707*5113495bSYour Name 
708*5113495bSYour Name 	return wlan_cfg80211_peer_enh_cfr_capture(adapter, tb);
709*5113495bSYour Name }
710*5113495bSYour Name 
__wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)711*5113495bSYour Name static int __wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
712*5113495bSYour Name 						    struct wireless_dev *wdev,
713*5113495bSYour Name 						    const void *data,
714*5113495bSYour Name 						    int data_len)
715*5113495bSYour Name {
716*5113495bSYour Name 	int ret;
717*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
718*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
719*5113495bSYour Name 	struct hdd_adapter *adapter;
720*5113495bSYour Name 	uint8_t ll_lt_sap_vdev_id;
721*5113495bSYour Name 
722*5113495bSYour Name 	hdd_enter();
723*5113495bSYour Name 
724*5113495bSYour Name 	ret = wlan_hdd_validate_context(hdd_ctx);
725*5113495bSYour Name 	if (ret)
726*5113495bSYour Name 		return ret;
727*5113495bSYour Name 
728*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
729*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
730*5113495bSYour Name 		return -EPERM;
731*5113495bSYour Name 	}
732*5113495bSYour Name 
733*5113495bSYour Name 	adapter = WLAN_HDD_GET_PRIV_PTR(dev);
734*5113495bSYour Name 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
735*5113495bSYour Name 		return -EINVAL;
736*5113495bSYour Name 
737*5113495bSYour Name 	ll_lt_sap_vdev_id =
738*5113495bSYour Name 			wlan_policy_mgr_get_ll_lt_sap_vdev_id(hdd_ctx->psoc);
739*5113495bSYour Name 	if (ll_lt_sap_vdev_id != WLAN_INVALID_VDEV_ID) {
740*5113495bSYour Name 		hdd_info_rl("LL_LT_SAP vdev %d present, cfr cmd not allowed",
741*5113495bSYour Name 			     ll_lt_sap_vdev_id);
742*5113495bSYour Name 		return -EINVAL;
743*5113495bSYour Name 	}
744*5113495bSYour Name 
745*5113495bSYour Name 	wlan_cfg80211_peer_cfr_capture_cfg(wiphy, adapter,
746*5113495bSYour Name 					   data, data_len);
747*5113495bSYour Name 
748*5113495bSYour Name 	hdd_exit();
749*5113495bSYour Name 
750*5113495bSYour Name 	return ret;
751*5113495bSYour Name }
752*5113495bSYour Name 
wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)753*5113495bSYour Name int wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
754*5113495bSYour Name 					   struct wireless_dev *wdev,
755*5113495bSYour Name 					   const void *data,
756*5113495bSYour Name 					   int data_len)
757*5113495bSYour Name {
758*5113495bSYour Name 	struct osif_psoc_sync *psoc_sync;
759*5113495bSYour Name 	int errno;
760*5113495bSYour Name 
761*5113495bSYour Name 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
762*5113495bSYour Name 	if (errno)
763*5113495bSYour Name 		return errno;
764*5113495bSYour Name 
765*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_peer_cfr_capture_cfg(wiphy, wdev,
766*5113495bSYour Name 							 data, data_len);
767*5113495bSYour Name 
768*5113495bSYour Name 	osif_psoc_sync_op_stop(psoc_sync);
769*5113495bSYour Name 
770*5113495bSYour Name 	return errno;
771*5113495bSYour Name }
772