1 /*
2  * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_he.c
22  *
23  * WLAN Host Device Driver file for 802.11ax (High Efficiency) support.
24  *
25  */
26 
27 #include "wlan_hdd_main.h"
28 #include "wlan_hdd_he.h"
29 #include "osif_sync.h"
30 #include "wma_he.h"
31 #include "wlan_utility.h"
32 #include "wlan_mlme_ucfg_api.h"
33 #include "spatial_reuse_ucfg_api.h"
34 #include "cdp_txrx_host_stats.h"
35 #include "wlan_policy_mgr_i.h"
36 #include "wlan_objmgr_vdev_obj.h"
37 #include "wlan_hdd_object_manager.h"
38 
39 const struct nla_policy
40 wlan_hdd_sr_policy[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1] = {
41 	[QCA_WLAN_VENDOR_ATTR_SR_OPERATION] = {.type = NLA_U8},
42 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS] = {.type = NLA_NESTED},
43 	[QCA_WLAN_VENDOR_ATTR_SR_STATS] = {.type = NLA_NESTED},
44 };
45 
46 static const struct nla_policy
47 qca_wlan_vendor_srp_param_policy[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1] = {
48 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE] = {
49 							.type = NLA_FLAG},
50 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW] = {
51 							.type = NLA_FLAG},
52 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET] = {
53 							.type = NLA_U8},
54 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET] = {
55 							.type = NLA_U8},
56 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET] = {
57 							.type = NLA_U8},
58 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD] = {
59 							.type = NLA_S32},
60 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD] = {
61 							.type = NLA_S32},
62 	[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE] = {.type = NLA_U32},
63 
64 };
65 
hdd_update_tgt_he_cap(struct hdd_context * hdd_ctx,struct wma_tgt_cfg * cfg)66 void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx,
67 			   struct wma_tgt_cfg *cfg)
68 {
69 	QDF_STATUS status;
70 	tDot11fIEhe_cap he_cap_ini = {0};
71 	uint8_t value = 0;
72 
73 	status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
74 							&value);
75 	if (!QDF_IS_STATUS_SUCCESS(status))
76 		hdd_err("unable to get tx_bfee_ant_supp");
77 
78 	he_cap_ini.bfee_sts_lt_80 = value;
79 	sme_update_tgt_he_cap(hdd_ctx->mac_handle, cfg, &he_cap_ini);
80 
81 	ucfg_mlme_update_tgt_he_cap(hdd_ctx->psoc, cfg);
82 }
83 
wlan_hdd_check_11ax_support(struct hdd_beacon_data * beacon,struct sap_config * config)84 void wlan_hdd_check_11ax_support(struct hdd_beacon_data *beacon,
85 				 struct sap_config *config)
86 {
87 	const uint8_t *ie;
88 
89 	ie = wlan_get_ext_ie_ptr_from_ext_id(HE_CAP_OUI_TYPE, HE_CAP_OUI_SIZE,
90 					    beacon->tail, beacon->tail_len);
91 	if (ie)
92 		config->SapHw_mode = eCSR_DOT11_MODE_11ax;
93 }
94 
hdd_update_he_cap_in_cfg(struct hdd_context * hdd_ctx)95 int hdd_update_he_cap_in_cfg(struct hdd_context *hdd_ctx)
96 {
97 	uint32_t val;
98 	uint32_t val1 = 0;
99 	QDF_STATUS status;
100 	int ret;
101 	uint8_t enable_ul_ofdma, enable_ul_mimo;
102 
103 	status = ucfg_mlme_cfg_get_he_ul_mumimo(hdd_ctx->psoc, &val);
104 	if (QDF_IS_STATUS_ERROR(status)) {
105 		hdd_err("could not get CFG_HE_UL_MUMIMO");
106 		return qdf_status_to_os_return(status);
107 	}
108 
109 	/* In val,
110 	 * Bit 1 - corresponds to UL MIMO
111 	 * Bit 2 - corresponds to UL OFDMA
112 	 */
113 	ret = ucfg_mlme_cfg_get_enable_ul_mimo(hdd_ctx->psoc,
114 					       &enable_ul_mimo);
115 	if (ret)
116 		return ret;
117 	ret = ucfg_mlme_cfg_get_enable_ul_ofdm(hdd_ctx->psoc,
118 					       &enable_ul_ofdma);
119 	if (ret)
120 		return ret;
121 	if (val & 0x1 || (val >> 1) & 0x1)
122 		val1 = enable_ul_mimo & 0x1;
123 
124 	if ((val >> 1) & 0x1)
125 		val1 |= ((enable_ul_ofdma & 0x1) << 1);
126 
127 	ret = ucfg_mlme_cfg_set_he_ul_mumimo(hdd_ctx->psoc, val1);
128 
129 	return ret;
130 }
131 
132 /*
133  * __wlan_hdd_cfg80211_get_he_cap() - get HE Capabilities
134  * @wiphy: Pointer to wiphy
135  * @wdev: Pointer to wdev
136  * @data: Pointer to data
137  * @data_len: Data length
138  *
139  * Return: 0 if success, non-zero for failure
140  */
141 static int
__wlan_hdd_cfg80211_get_he_cap(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)142 __wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
143 			       struct wireless_dev *wdev,
144 			       const void *data,
145 			       int data_len)
146 {
147 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
148 	int ret;
149 	QDF_STATUS status;
150 	struct sk_buff *reply_skb;
151 	uint32_t nl_buf_len;
152 	struct he_capability he_cap;
153 	uint8_t he_supported = 0;
154 
155 	hdd_enter();
156 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
157 		hdd_err("Command not allowed in FTM mode");
158 		return -EPERM;
159 	}
160 
161 	ret = wlan_hdd_validate_context(hdd_ctx);
162 	if (0 != ret)
163 		return ret;
164 
165 	nl_buf_len = NLMSG_HDRLEN;
166 	if (sme_is_feature_supported_by_fw(DOT11AX)) {
167 		he_supported = 1;
168 
169 		status = wma_get_he_capabilities(&he_cap);
170 		if (QDF_STATUS_SUCCESS != status)
171 			return -EINVAL;
172 	} else {
173 		hdd_info("11AX: HE not supported, send only QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED");
174 	}
175 
176 	if (he_supported) {
177 		nl_buf_len += NLA_HDRLEN + sizeof(he_supported) +
178 			      NLA_HDRLEN + sizeof(he_cap.phy_cap) +
179 			      NLA_HDRLEN + sizeof(he_cap.mac_cap) +
180 			      NLA_HDRLEN + sizeof(he_cap.mcs) +
181 			      NLA_HDRLEN + sizeof(he_cap.ppet.numss_m1) +
182 			      NLA_HDRLEN + sizeof(he_cap.ppet.ru_bit_mask) +
183 			      NLA_HDRLEN +
184 				sizeof(he_cap.ppet.ppet16_ppet8_ru3_ru0);
185 	} else {
186 		nl_buf_len += NLA_HDRLEN + sizeof(he_supported);
187 	}
188 
189 	hdd_info("11AX: he_supported: %d", he_supported);
190 
191 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
192 	if (!reply_skb) {
193 		hdd_err("Allocate reply_skb failed");
194 		return -EINVAL;
195 	}
196 
197 	if (nla_put_u8(reply_skb,
198 		       QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED, he_supported))
199 		goto nla_put_failure;
200 
201 	/* No need to populate other attributes if HE is not supported */
202 	if (0 == he_supported)
203 		goto end;
204 
205 	if (nla_put_u32(reply_skb,
206 			QCA_WLAN_VENDOR_ATTR_MAC_CAPAB, he_cap.mac_cap) ||
207 	    nla_put_u32(reply_skb,
208 			QCA_WLAN_VENDOR_ATTR_HE_MCS, he_cap.mcs) ||
209 	    nla_put_u32(reply_skb,
210 			QCA_WLAN_VENDOR_ATTR_NUM_SS, he_cap.ppet.numss_m1) ||
211 	    nla_put_u32(reply_skb,
212 			QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK,
213 			he_cap.ppet.ru_bit_mask) ||
214 	    nla_put(reply_skb,
215 		    QCA_WLAN_VENDOR_ATTR_PHY_CAPAB,
216 		    sizeof(u32) * HE_MAX_PHY_CAP_SIZE, he_cap.phy_cap) ||
217 	    nla_put(reply_skb, QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD,
218 		    sizeof(u32) * PSOC_HOST_MAX_NUM_SS,
219 		    he_cap.ppet.ppet16_ppet8_ru3_ru0))
220 		goto nla_put_failure;
221 end:
222 	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
223 	hdd_exit();
224 	return ret;
225 
226 nla_put_failure:
227 	hdd_err("nla put fail");
228 	wlan_cfg80211_vendor_free_skb(reply_skb);
229 	return -EINVAL;
230 }
231 
wlan_hdd_cfg80211_get_he_cap(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)232 int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
233 				 struct wireless_dev *wdev,
234 				 const void *data,
235 				 int data_len)
236 {
237 	struct osif_psoc_sync *psoc_sync;
238 	int errno;
239 
240 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
241 	if (errno)
242 		return errno;
243 
244 	errno = __wlan_hdd_cfg80211_get_he_cap(wiphy, wdev, data, data_len);
245 
246 	osif_psoc_sync_op_stop(psoc_sync);
247 
248 	return errno;
249 }
250 
251 #ifdef WLAN_FEATURE_SR
252 static QDF_STATUS
hdd_sr_event_convert_reason_code(enum sr_osif_reason_code sr_osif_rc,enum qca_wlan_sr_reason_code * sr_nl_rc)253 hdd_sr_event_convert_reason_code(enum sr_osif_reason_code sr_osif_rc,
254 				 enum qca_wlan_sr_reason_code *sr_nl_rc)
255 {
256 	QDF_STATUS status = QDF_STATUS_SUCCESS;
257 
258 	switch (sr_osif_rc) {
259 	case SR_REASON_CODE_ROAMING:
260 		*sr_nl_rc = QCA_WLAN_SR_REASON_CODE_ROAMING;
261 		break;
262 	case SR_REASON_CODE_CONCURRENCY:
263 		*sr_nl_rc = QCA_WLAN_SR_REASON_CODE_CONCURRENCY;
264 		break;
265 	default:
266 		status = QDF_STATUS_E_INVAL;
267 	}
268 
269 	return status;
270 }
271 
272 static QDF_STATUS
hdd_sr_event_convert_operation(enum sr_osif_operation sr_osif_oper,enum qca_wlan_sr_operation * sr_nl_oper)273 hdd_sr_event_convert_operation(enum sr_osif_operation sr_osif_oper,
274 			       enum qca_wlan_sr_operation *sr_nl_oper)
275 {
276 	QDF_STATUS status = QDF_STATUS_SUCCESS;
277 
278 	switch (sr_osif_oper) {
279 	case SR_OPERATION_SUSPEND:
280 		*sr_nl_oper = QCA_WLAN_SR_OPERATION_SR_SUSPEND;
281 		break;
282 	case SR_OPERATION_RESUME:
283 		*sr_nl_oper = QCA_WLAN_SR_OPERATION_SR_RESUME;
284 		break;
285 	case SR_OPERATION_UPDATE_PARAMS:
286 		*sr_nl_oper = QCA_WLAN_SR_OPERATION_UPDATE_PARAMS;
287 		break;
288 	default:
289 		status = QDF_STATUS_E_INVAL;
290 	}
291 
292 	return status;
293 }
294 
hdd_sr_pack_suspend_resume_event(struct sk_buff * skb,enum qca_wlan_sr_operation sr_nl_oper,enum qca_wlan_sr_reason_code sr_nl_rc,uint8_t srg_max_pd_offset,uint8_t srg_min_pd_offset,uint8_t non_srg_max_pd_offset)295 static QDF_STATUS hdd_sr_pack_suspend_resume_event(
296 					 struct sk_buff *skb,
297 					 enum qca_wlan_sr_operation sr_nl_oper,
298 					 enum qca_wlan_sr_reason_code sr_nl_rc,
299 					 uint8_t srg_max_pd_offset,
300 					 uint8_t srg_min_pd_offset,
301 					 uint8_t non_srg_max_pd_offset)
302 {
303 	struct nlattr *attr;
304 	QDF_STATUS status = QDF_STATUS_E_FAULT;
305 
306 	if (((sr_nl_rc != QCA_WLAN_SR_REASON_CODE_CONCURRENCY) &&
307 	     (sr_nl_rc != QCA_WLAN_SR_REASON_CODE_ROAMING)) ||
308 	    ((sr_nl_oper != QCA_WLAN_SR_OPERATION_SR_SUSPEND) &&
309 	     (sr_nl_oper != QCA_WLAN_SR_OPERATION_SR_RESUME))) {
310 		hdd_err("SR operation is invalid");
311 		status = QDF_STATUS_E_INVAL;
312 		goto sr_events_end;
313 	}
314 
315 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SR_OPERATION, sr_nl_oper)) {
316 		hdd_err("failed to put attr SR Operation");
317 		goto sr_events_end;
318 	}
319 
320 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SR_PARAMS);
321 	if (!attr) {
322 		hdd_err("nesting failed");
323 		goto sr_events_end;
324 	}
325 
326 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE,
327 			sr_nl_rc)) {
328 		hdd_err("failed to put attr SR Reascon Code");
329 		goto sr_events_end;
330 	}
331 	if (sr_nl_rc == QCA_WLAN_SR_REASON_CODE_ROAMING &&
332 	    sr_nl_oper == QCA_WLAN_SR_OPERATION_SR_RESUME) {
333 		if (nla_put_u32(
334 			skb,
335 			QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET,
336 			srg_min_pd_offset)) {
337 			hdd_err("srg_pd_min_offset put fail");
338 			goto sr_events_end;
339 		}
340 		if (nla_put_u32(
341 			skb,
342 			QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET,
343 			srg_max_pd_offset)) {
344 			hdd_err("srg_pd_min_offset put fail");
345 			goto sr_events_end;
346 		}
347 		if (nla_put_u32(
348 		      skb,
349 		      QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET,
350 		      non_srg_max_pd_offset)) {
351 			hdd_err("non_srg_pd_offset put fail");
352 			goto sr_events_end;
353 		}
354 	}
355 	status = QDF_STATUS_SUCCESS;
356 	nla_nest_end(skb, attr);
357 
358 sr_events_end:
359 	return status;
360 }
361 
hdd_sr_osif_events(struct wlan_objmgr_vdev * vdev,enum sr_osif_operation sr_osif_oper,enum sr_osif_reason_code sr_osif_rc)362 static void hdd_sr_osif_events(struct wlan_objmgr_vdev *vdev,
363 			       enum sr_osif_operation sr_osif_oper,
364 			       enum sr_osif_reason_code sr_osif_rc)
365 {
366 	struct hdd_adapter *adapter;
367 	struct wireless_dev *wdev;
368 	struct wiphy *wiphy;
369 	struct sk_buff *skb;
370 	uint32_t idx = QCA_NL80211_VENDOR_SUBCMD_SR_INDEX;
371 	uint32_t len = NLMSG_HDRLEN;
372 	uint8_t non_srg_max_pd_offset = 0;
373 	uint8_t srg_max_pd_offset = 0;
374 	uint8_t srg_min_pd_offset = 0;
375 	QDF_STATUS status;
376 	enum qca_wlan_sr_operation sr_nl_oper;
377 	enum qca_wlan_sr_reason_code sr_nl_rc;
378 	struct wlan_hdd_link_info *link_info;
379 
380 	if (!vdev) {
381 		hdd_err("Null VDEV");
382 		return;
383 	}
384 
385 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
386 	if (!link_info) {
387 		hdd_err("Null adapter");
388 		return;
389 	}
390 
391 	adapter = link_info->adapter;
392 	wlan_vdev_mlme_get_srg_pd_offset(vdev, &srg_max_pd_offset,
393 					 &srg_min_pd_offset);
394 	non_srg_max_pd_offset = wlan_vdev_mlme_get_non_srg_pd_offset(vdev);
395 	status = hdd_sr_event_convert_operation(sr_osif_oper, &sr_nl_oper);
396 	if (QDF_IS_STATUS_ERROR(status)) {
397 		hdd_err("Invalid SR Operation: %d", sr_osif_oper);
398 		return;
399 	}
400 	status = hdd_sr_event_convert_reason_code(sr_osif_rc, &sr_nl_rc);
401 	if (QDF_IS_STATUS_ERROR(status)) {
402 		hdd_err("Invalid SR Reason Code: %d", sr_osif_rc);
403 		return;
404 	}
405 
406 	hdd_debug("SR Operation: %u SR Reason Code: %u",
407 		  sr_nl_oper, sr_nl_rc);
408 	switch (sr_nl_oper) {
409 	case QCA_WLAN_SR_OPERATION_SR_SUSPEND:
410 	case QCA_WLAN_SR_OPERATION_SR_RESUME:
411 		if (sr_nl_rc == QCA_WLAN_SR_REASON_CODE_CONCURRENCY ||
412 		    sr_nl_rc == QCA_WLAN_SR_REASON_CODE_ROAMING) {
413 			wiphy = adapter->hdd_ctx->wiphy;
414 			wdev = &adapter->wdev;
415 			/* QCA_WLAN_VENDOR_ATTR_SR_OPERATION */
416 			len += nla_total_size(sizeof(uint8_t));
417 			/* QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE */
418 			len += nla_total_size(sizeof(uint32_t));
419 			/* QCA_WLAN_VENDOR_ATTR_SR_PARAMS */
420 			len += nla_total_size(0);
421 			/*
422 			 * In case of resume due to roaming additional config
423 			 * params are required to be sent.
424 			 */
425 			if (sr_nl_rc == QCA_WLAN_SR_REASON_CODE_ROAMING &&
426 			    sr_nl_oper == QCA_WLAN_SR_OPERATION_SR_RESUME) {
427 				/* SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET */
428 				len += nla_total_size(sizeof(int32_t));
429 				/* SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET */
430 				len += nla_total_size(sizeof(int32_t));
431 				/* SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET */
432 				len += nla_total_size(sizeof(int32_t));
433 			}
434 			skb = wlan_cfg80211_vendor_event_alloc(wiphy, wdev,
435 							       len, idx,
436 							       GFP_KERNEL);
437 			if (!skb) {
438 				hdd_err("wlan_cfg80211_vendor_event_alloc failed");
439 				return;
440 			}
441 			status = hdd_sr_pack_suspend_resume_event(
442 					skb, sr_nl_oper, sr_nl_rc,
443 					srg_max_pd_offset, srg_min_pd_offset,
444 					non_srg_max_pd_offset);
445 			if (QDF_IS_STATUS_ERROR(status)) {
446 				wlan_cfg80211_vendor_free_skb(skb);
447 				return;
448 			}
449 
450 			wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
451 			hdd_debug("SR cfg80211 event is sent");
452 		} else {
453 			hdd_debug("SR Reason code not supported");
454 		}
455 		break;
456 	default:
457 		hdd_debug("SR Operation not supported");
458 		break;
459 	}
460 }
461 
hdd_sr_register_callbacks(struct hdd_context * hdd_ctx)462 void hdd_sr_register_callbacks(struct hdd_context *hdd_ctx)
463 {
464 	ucfg_spatial_reuse_register_cb(hdd_ctx->psoc, hdd_sr_osif_events);
465 }
466 
hdd_get_srp_stats_len(void)467 static int hdd_get_srp_stats_len(void)
468 {
469 	struct cdp_pdev_obss_pd_stats_tlv stats;
470 	uint32_t len = NLMSG_HDRLEN;
471 
472 	len += nla_total_size(sizeof(stats.num_srg_ppdu_success)) +
473 		nla_total_size(sizeof(stats.num_srg_ppdu_tried)) +
474 		nla_total_size(sizeof(stats.num_srg_opportunities)) +
475 		nla_total_size(sizeof(stats.num_non_srg_ppdu_success)) +
476 		nla_total_size(sizeof(stats.num_non_srg_ppdu_tried)) +
477 		nla_total_size(sizeof(stats.num_non_srg_opportunities));
478 
479 	return len;
480 }
481 
hdd_get_srp_param_len(void)482 static int hdd_get_srp_param_len(void)
483 {
484 	uint32_t len = NLMSG_HDRLEN;
485 
486 	len += nla_total_size(sizeof(bool)) +
487 	       nla_total_size(sizeof(bool))+
488 	       nla_total_size(sizeof(uint8_t))+
489 	       nla_total_size(sizeof(uint8_t))+
490 	       nla_total_size(sizeof(uint8_t));
491 
492 	return len;
493 }
494 
495 static int
hdd_add_param_info(struct sk_buff * skb,uint8_t srg_max_pd_offset,uint8_t srg_min_pd_offset,uint8_t non_srg_pd_offset,uint8_t sr_ctrl,int idx)496 hdd_add_param_info(struct sk_buff *skb, uint8_t srg_max_pd_offset,
497 		   uint8_t srg_min_pd_offset, uint8_t non_srg_pd_offset,
498 		   uint8_t sr_ctrl, int idx)
499 {
500 	struct nlattr *nla_attr;
501 	bool non_srg_obss_pd_disallow = sr_ctrl & NON_SRG_PD_SR_DISALLOWED;
502 	bool hesega_val_15_enable = sr_ctrl & HE_SIG_VAL_15_ALLOWED;
503 
504 	nla_attr = nla_nest_start(skb, idx);
505 	if (!nla_attr)
506 		goto fail;
507 	hdd_debug("SR params of connected AP srg_max_pd_offset %d srg_min_pd_offset %d non_srg_pd_offset %d non_srg_obss_pd_disallow %d hesega_val_15_enable %d",
508 		  srg_max_pd_offset, srg_min_pd_offset, non_srg_pd_offset,
509 		  non_srg_obss_pd_disallow, hesega_val_15_enable);
510 
511 	if (nla_put_u32(skb,
512 			QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET,
513 			srg_min_pd_offset)) {
514 		hdd_err("srg_pd_min_offset put fail");
515 		goto fail;
516 	}
517 	if (nla_put_u32(skb,
518 			QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET,
519 			srg_max_pd_offset)) {
520 		hdd_err("srg_pd_min_offset put fail");
521 		goto fail;
522 	}
523 	if (nla_put_u32(
524 		skb,
525 		QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET,
526 		non_srg_pd_offset)) {
527 		hdd_err("non_srg_pd_offset put fail");
528 		goto fail;
529 	}
530 	if (non_srg_obss_pd_disallow && nla_put_flag(
531 		skb,
532 		QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW)) {
533 		hdd_err("non_srg_obss_pd_disallow put fail or enabled");
534 		goto fail;
535 	}
536 	if (hesega_val_15_enable && nla_put_flag(
537 			 skb,
538 			 QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE)) {
539 		hdd_err("hesega_val_15_enable put fail or disabled");
540 		goto fail;
541 	}
542 
543 	nla_nest_end(skb, nla_attr);
544 	return 0;
545 fail:
546 	return -EINVAL;
547 }
548 static int
hdd_add_stats_info(struct sk_buff * skb,struct cdp_pdev_obss_pd_stats_tlv * stats)549 hdd_add_stats_info(struct sk_buff *skb,
550 		   struct cdp_pdev_obss_pd_stats_tlv *stats)
551 {
552 	struct nlattr *nla_attr;
553 
554 	nla_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SR_STATS);
555 	if (!nla_attr)
556 		goto fail;
557 
558 	hdd_debug("SR stats - srg: ppdu_success %d tried %d opportunities %d non-srg: ppdu_success %d tried %d opportunities %d",
559 		  stats->num_srg_ppdu_success, stats->num_srg_ppdu_tried,
560 		  stats->num_srg_opportunities, stats->num_non_srg_ppdu_success,
561 		  stats->num_non_srg_ppdu_tried,
562 		  stats->num_non_srg_opportunities);
563 	if (nla_put_u32(skb,
564 			QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_SUCCESS_COUNT,
565 			stats->num_srg_ppdu_success)) {
566 		hdd_err("num_srg_ppdu_success put fail");
567 		goto fail;
568 	}
569 	if (nla_put_u32(skb,
570 			QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_PPDU_TRIED_COUNT,
571 			stats->num_srg_ppdu_tried)) {
572 		hdd_err("num_srg_ppdu_tried put fail");
573 		goto fail;
574 	}
575 	if (nla_put_u32(
576 		skb,
577 		QCA_WLAN_VENDOR_ATTR_SR_STATS_SRG_TX_OPPORTUNITIES_COUNT,
578 		stats->num_srg_opportunities)) {
579 		hdd_err("num_srg_opportunities put fail");
580 		goto fail;
581 	}
582 	if (nla_put_u32(
583 		skb,
584 		QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_SUCCESS_COUNT,
585 		stats->num_non_srg_ppdu_success)) {
586 		hdd_err("num_non_srg_ppdu_success put fail");
587 		goto fail;
588 	}
589 	if (nla_put_u32(
590 		skb,
591 		QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_PPDU_TRIED_COUNT,
592 		stats->num_non_srg_ppdu_tried)) {
593 		hdd_err("num_non_srg_ppdu_tried put fail");
594 		goto fail;
595 	}
596 	if (nla_put_u32(
597 		skb,
598 		QCA_WLAN_VENDOR_ATTR_SR_STATS_NON_SRG_TX_OPPORTUNITIES_COUNT,
599 		stats->num_non_srg_opportunities)) {
600 		hdd_err("num_non_srg_opportunities put fail");
601 		goto fail;
602 	}
603 	nla_nest_end(skb, nla_attr);
604 	return 0;
605 fail:
606 	return -EINVAL;
607 }
608 
hdd_get_sr_stats(struct hdd_context * hdd_ctx,uint8_t mac_id,struct cdp_pdev_obss_pd_stats_tlv * stats)609 static int hdd_get_sr_stats(struct hdd_context *hdd_ctx, uint8_t mac_id,
610 			    struct cdp_pdev_obss_pd_stats_tlv *stats)
611 {
612 	ol_txrx_soc_handle soc;
613 	uint8_t pdev_id;
614 	struct cdp_txrx_stats_req req = {0};
615 
616 	soc = cds_get_context(QDF_MODULE_ID_SOC);
617 	if (!soc) {
618 		hdd_err("invalid soc");
619 		return -EINVAL;
620 	}
621 
622 	req.mac_id = mac_id;
623 	pdev_id = wlan_objmgr_pdev_get_pdev_id(hdd_ctx->pdev);
624 	cdp_get_pdev_obss_pd_stats(soc, pdev_id, stats, &req);
625 	if (!stats) {
626 		hdd_err("invalid stats");
627 		return -EINVAL;
628 	}
629 	return 0;
630 }
631 
hdd_clear_sr_stats(struct hdd_context * hdd_ctx,uint8_t mac_id)632 static int hdd_clear_sr_stats(struct hdd_context *hdd_ctx, uint8_t mac_id)
633 {
634 	QDF_STATUS status;
635 	ol_txrx_soc_handle soc;
636 	uint8_t pdev_id;
637 	struct cdp_txrx_stats_req req = {0};
638 
639 	soc = cds_get_context(QDF_MODULE_ID_SOC);
640 	if (!soc) {
641 		hdd_err("invalid soc");
642 		return -EINVAL;
643 	}
644 
645 	req.mac_id = mac_id;
646 	pdev_id = wlan_objmgr_pdev_get_pdev_id(hdd_ctx->pdev);
647 	status = cdp_clear_pdev_obss_pd_stats(soc, pdev_id, &req);
648 	if (QDF_IS_STATUS_ERROR(status)) {
649 		hdd_err("Unable to clear stats");
650 		return -EAGAIN;
651 	}
652 	return 0;
653 }
654 
655 /**
656  * hdd_check_mode_support_for_sr: Check if SR allowed or not
657  * @adapter: hdd adapter
658  * @sr_ctrl: sr ctrl ie
659  *
660  * Return: true if provided mode supports SR else flase
661  */
hdd_check_mode_support_for_sr(struct hdd_adapter * adapter,uint8_t sr_ctrl)662 static bool hdd_check_mode_support_for_sr(struct hdd_adapter *adapter,
663 					  uint8_t sr_ctrl)
664 {
665 	if ((adapter->device_mode == QDF_STA_MODE) &&
666 	    (!hdd_cm_is_vdev_connected(adapter->deflink) ||
667 	    ((sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
668 	    !(sr_ctrl & SRG_INFO_PRESENT)))) {
669 		hdd_err("mode %d doesn't supports SR", adapter->device_mode);
670 		return false;
671 	}
672 	return true;
673 }
674 
675 /**
676  * __wlan_hdd_cfg80211_sr_operations: To handle SR operation
677  *
678  * @wiphy: wiphy structure
679  * @wdev: wireless dev
680  * @data: vendor command data
681  * @data_len: data len
682  *
683  * return: success/failure code
684  */
__wlan_hdd_cfg80211_sr_operations(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)685 static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
686 					     struct wireless_dev *wdev,
687 					     const void *data, int data_len)
688 {
689 	QDF_STATUS status;
690 	uint32_t id;
691 	bool is_sr_enable = false;
692 	int32_t srg_pd_threshold = 0;
693 	int32_t non_srg_pd_threshold = 0;
694 	uint8_t sr_he_siga_val15_allowed = true;
695 	uint8_t mac_id, sr_ctrl, non_srg_max_pd_offset;
696 	uint8_t srg_min_pd_offset = 0, srg_max_pd_offset = 0;
697 	uint32_t nl_buf_len;
698 	int ret;
699 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
700 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
701 	struct wlan_objmgr_vdev *vdev;
702 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1];
703 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1] = {0};
704 	enum qca_wlan_sr_operation sr_oper;
705 	struct nlattr *sr_oper_attr;
706 	struct nlattr *sr_param_attr;
707 	struct sk_buff *skb;
708 	struct cdp_pdev_obss_pd_stats_tlv stats;
709 	uint8_t sr_device_modes;
710 
711 	hdd_enter_dev(wdev->netdev);
712 
713 	ret = wlan_hdd_validate_context(hdd_ctx);
714 	if (ret)
715 		return ret;
716 
717 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
718 	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
719 		hdd_err("Command not allowed in FTM or Monitor mode");
720 		return -EPERM;
721 	}
722 
723 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
724 					   WLAN_HDD_ID_OBJ_MGR);
725 	if (!vdev) {
726 		hdd_err("Null VDEV");
727 		return -EINVAL;
728 	}
729 	/**
730 	 * Reject command if SR concurrency is not allowed and
731 	 * only STA mode is set in ini to enable SR.
732 	 **/
733 	ucfg_mlme_get_sr_enable_modes(hdd_ctx->psoc, &sr_device_modes);
734 	if (!(sr_device_modes & (1 << adapter->device_mode))) {
735 		hdd_debug("SR operation not allowed for mode %d",
736 			  adapter->device_mode);
737 		ret = -EINVAL;
738 		goto exit;
739 	}
740 
741 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
742 		hdd_err("Driver Modules are closed");
743 		ret = -EINVAL;
744 		goto exit;
745 	}
746 	if (!sme_is_feature_supported_by_fw(DOT11AX)) {
747 		hdd_err("11AX is not supported");
748 		ret = -EINVAL;
749 		goto exit;
750 	}
751 	status = ucfg_spatial_reuse_operation_allowed(hdd_ctx->psoc, vdev);
752 	if (QDF_IS_STATUS_ERROR(status)) {
753 		hdd_err("SR operations not allowed status: %u", status);
754 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
755 		return qdf_status_to_os_return(status);
756 	}
757 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SR_MAX, data,
758 				    data_len, wlan_hdd_sr_policy)) {
759 		hdd_err("invalid attr");
760 		ret = -EINVAL;
761 		goto exit;
762 	}
763 
764 	id = QCA_WLAN_VENDOR_ATTR_SR_OPERATION;
765 	sr_oper_attr = tb[id];
766 	if (!sr_oper_attr) {
767 		hdd_err("SR operation not specified");
768 		ret = -EINVAL;
769 		goto exit;
770 	}
771 
772 	sr_oper = nla_get_u8(sr_oper_attr);
773 	hdd_debug("SR Operation 0x%x", sr_oper);
774 
775 	ucfg_spatial_reuse_get_sr_config(vdev, &sr_ctrl, &non_srg_max_pd_offset,
776 					 &is_sr_enable);
777 
778 	if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl) &&
779 	    (sr_oper != QCA_WLAN_SR_OPERATION_GET_PARAMS)) {
780 		hdd_err("SR operation not allowed, sr_ctrl = %x, mode = %d",
781 			sr_ctrl, adapter->device_mode);
782 		ret = -EINVAL;
783 		goto exit;
784 	}
785 
786 	if (sr_oper != QCA_WLAN_SR_OPERATION_SR_ENABLE && !is_sr_enable) {
787 		hdd_err("SR operation not allowed");
788 		ret = -EINVAL;
789 		goto exit;
790 	}
791 
792 	id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS;
793 	sr_param_attr = tb[id];
794 	if (sr_param_attr) {
795 		ret = wlan_cfg80211_nla_parse_nested(
796 				tb2, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX,
797 				sr_param_attr,
798 				qca_wlan_vendor_srp_param_policy);
799 		if (ret) {
800 			hdd_err("sr_param_attr parse failed");
801 			goto exit;
802 		}
803 	}
804 	switch (sr_oper) {
805 	case QCA_WLAN_SR_OPERATION_SR_ENABLE:
806 	case QCA_WLAN_SR_OPERATION_SR_DISABLE:
807 		if (sr_oper == QCA_WLAN_SR_OPERATION_SR_ENABLE) {
808 			is_sr_enable = true;
809 		} else {
810 			is_sr_enable = false;
811 			if (!wlan_vdev_mlme_get_he_spr_enabled(vdev)) {
812 				hdd_debug("SR not enabled, reject disable command");
813 				ret = -EINVAL;
814 				goto exit;
815 			}
816 		}
817 		/**
818 		 * As per currenct implementation from userspace same
819 		 * PD threshold value is configured for both SRG and
820 		 * NON-SRG and fw will decide further based on BSS color
821 		 * So only SRG param is parsed and set as pd threshold
822 		 */
823 		if (is_sr_enable &&
824 		    tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]) {
825 			srg_pd_threshold =
826 			nla_get_s32(
827 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]);
828 			wlan_vdev_mlme_set_pd_threshold_present(vdev, true);
829 		}
830 
831 		if (is_sr_enable &&
832 		    tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD]) {
833 			non_srg_pd_threshold =
834 			nla_get_s32(
835 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD]
836 			);
837 			wlan_vdev_mlme_set_pd_threshold_present(vdev, true);
838 		}
839 
840 		hdd_debug("setting sr enable %d with pd threshold srg: %d non srg: %d",
841 			  is_sr_enable, srg_pd_threshold, non_srg_pd_threshold);
842 		/* Set the variables */
843 		ucfg_spatial_reuse_set_sr_enable(vdev, is_sr_enable);
844 		status = ucfg_spatial_reuse_setup_req(vdev, hdd_ctx->pdev,
845 						      is_sr_enable,
846 						      srg_pd_threshold,
847 						      non_srg_pd_threshold);
848 		if (status != QDF_STATUS_SUCCESS) {
849 			hdd_err("failed to enable Spatial Reuse feature");
850 			ret = -EINVAL;
851 			goto exit;
852 		}
853 
854 		break;
855 	case QCA_WLAN_SR_OPERATION_GET_STATS:
856 		status = policy_mgr_get_mac_id_by_session_id(
857 						hdd_ctx->psoc,
858 						adapter->deflink->vdev_id,
859 						&mac_id);
860 		if (QDF_IS_STATUS_ERROR(status)) {
861 			hdd_err("Failed to get mac_id for vdev_id: %u",
862 				adapter->deflink->vdev_id); {
863 				ret = -EAGAIN;
864 				goto exit;
865 			}
866 		}
867 		if (hdd_get_sr_stats(hdd_ctx, mac_id, &stats)) {
868 			ret = -EINVAL;
869 			goto exit;
870 		}
871 		nl_buf_len = hdd_get_srp_stats_len();
872 		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
873 							       nl_buf_len);
874 		if (!skb) {
875 			hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
876 			ret = -ENOMEM;
877 			goto exit;
878 		}
879 		if (hdd_add_stats_info(skb, &stats)) {
880 			wlan_cfg80211_vendor_free_skb(skb);
881 			ret = -EINVAL;
882 			goto exit;
883 		}
884 
885 		ret = wlan_cfg80211_vendor_cmd_reply(skb);
886 		break;
887 	case QCA_WLAN_SR_OPERATION_CLEAR_STATS:
888 		status = policy_mgr_get_mac_id_by_session_id(
889 						hdd_ctx->psoc,
890 						adapter->deflink->vdev_id,
891 						&mac_id);
892 		if (QDF_IS_STATUS_ERROR(status)) {
893 			hdd_err("Failed to get mac_id for vdev_id: %u",
894 				adapter->deflink->vdev_id);
895 			ret = -EAGAIN;
896 			goto exit;
897 		}
898 		if (hdd_clear_sr_stats(hdd_ctx, mac_id)) {
899 			ret = -EAGAIN;
900 			goto exit;
901 		}
902 		break;
903 	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT:
904 		if (tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE])
905 			sr_he_siga_val15_allowed = nla_get_u8(
906 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE]
907 			);
908 		if (!sr_he_siga_val15_allowed) {
909 			hdd_err("invalid sr_he_siga_val15_enable param");
910 			ret = -EINVAL;
911 			goto exit;
912 		}
913 		if (!QDF_IS_STATUS_SUCCESS(ucfg_spatial_reuse_send_sr_prohibit(
914 					   vdev, sr_he_siga_val15_allowed))) {
915 			hdd_debug("Prohibit command can not be sent");
916 			ret = -EINVAL;
917 			goto exit;
918 		}
919 		break;
920 	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW:
921 		if (!QDF_IS_STATUS_SUCCESS(ucfg_spatial_reuse_send_sr_prohibit(
922 					   vdev, false))) {
923 			hdd_debug("Prohibit command can not be sent");
924 			ret = -EINVAL;
925 			goto exit;
926 		}
927 		break;
928 	case QCA_WLAN_SR_OPERATION_GET_PARAMS:
929 		wlan_vdev_mlme_get_srg_pd_offset(vdev, &srg_max_pd_offset,
930 						 &srg_min_pd_offset);
931 		non_srg_max_pd_offset =
932 			wlan_vdev_mlme_get_non_srg_pd_offset(vdev);
933 		sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev);
934 		nl_buf_len = hdd_get_srp_param_len();
935 		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
936 							       nl_buf_len);
937 		if (!skb) {
938 			hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
939 			ret = -ENOMEM;
940 			goto exit;
941 		}
942 		if (hdd_add_param_info(skb, srg_max_pd_offset,
943 				       srg_min_pd_offset, non_srg_max_pd_offset,
944 				       sr_ctrl,
945 				       QCA_WLAN_VENDOR_ATTR_SR_PARAMS)) {
946 			wlan_cfg80211_vendor_free_skb(skb);
947 			ret = -EINVAL;
948 			goto exit;
949 		}
950 
951 		ret = wlan_cfg80211_vendor_cmd_reply(skb);
952 		break;
953 	default:
954 		hdd_err("Invalid SR Operation");
955 		ret = -EINVAL;
956 		break;
957 	}
958 
959 	hdd_exit();
960 exit:
961 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
962 	return ret;
963 }
964 
wlan_hdd_cfg80211_sr_operations(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)965 int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
966 				    struct wireless_dev *wdev,
967 				    const void *data, int data_len)
968 {
969 	struct osif_psoc_sync *psoc_sync;
970 	int errno;
971 
972 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
973 	if (errno)
974 		return errno;
975 
976 	errno = __wlan_hdd_cfg80211_sr_operations(wiphy, wdev, data, data_len);
977 
978 	osif_psoc_sync_op_stop(psoc_sync);
979 
980 	return errno;
981 }
982 #endif
983