xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_station_info.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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_station_info.c
22  *
23  * WLAN station info functions
24  *
25  */
26 
27 #include "osif_sync.h"
28 #include <wlan_hdd_includes.h>
29 #include <linux/netdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/etherdevice.h>
32 #include <linux/if_ether.h>
33 #include <wlan_cfg80211_mc_cp_stats.h>
34 #include <wlan_cp_stats_mc_ucfg_api.h>
35 #include <wlan_hdd_stats.h>
36 #include <wlan_hdd_hostapd.h>
37 #include <wlan_hdd_station_info.h>
38 #include "wlan_mlme_ucfg_api.h"
39 #include "wlan_hdd_sta_info.h"
40 #include "wlan_hdd_object_manager.h"
41 #include "wlan_ipa_ucfg_api.h"
42 
43 #include <cdp_txrx_handle.h>
44 #include <cdp_txrx_stats_struct.h>
45 #include <cdp_txrx_peer_ops.h>
46 #include <cdp_txrx_host_stats.h>
47 #include <osif_cm_util.h>
48 
49 #include "wlan_hdd_stats.h"
50 
51 /*
52  * define short names for the global vendor params
53  * used by __wlan_hdd_cfg80211_get_station_cmd()
54  */
55 #define STATION_INVALID \
56 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
57 #define STATION_INFO \
58 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
59 #define STATION_ASSOC_FAIL_REASON \
60 	QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
61 #define STATION_REMOTE \
62 	QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
63 #define STATION_MAX \
64 	QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
65 
66 #define STA_INFO_INVALID \
67 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID
68 #define STA_INFO_BIP_MIC_ERROR_COUNT \
69 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT
70 #define STA_INFO_BIP_REPLAY_COUNT \
71 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT
72 #define STA_INFO_BEACON_MIC_ERROR_COUNT \
73 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT
74 #define STA_INFO_BEACON_REPLAY_COUNT \
75 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT
76 #define STA_INFO_CONNECT_FAIL_REASON_CODE \
77 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE
78 #define STA_INFO_MAX \
79 	QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX
80 
81 /* define short names for get station info attributes */
82 #define LINK_INFO_STANDARD_NL80211_ATTR \
83 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
84 #define AP_INFO_STANDARD_NL80211_ATTR \
85 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
86 #define INFO_ROAM_COUNT \
87 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
88 #define INFO_AKM \
89 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
90 #define WLAN802_11_MODE \
91 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
92 #define AP_INFO_HS20_INDICATION \
93 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
94 #define HT_OPERATION \
95 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
96 #define VHT_OPERATION \
97 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
98 #define HE_OPERATION \
99 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION
100 #define INFO_ASSOC_FAIL_REASON \
101 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
102 #define REMOTE_MAX_PHY_RATE \
103 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
104 #define REMOTE_TX_PACKETS \
105 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
106 #define REMOTE_TX_BYTES \
107 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
108 #define REMOTE_RX_PACKETS \
109 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
110 #define REMOTE_RX_BYTES \
111 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
112 #define REMOTE_LAST_TX_RATE \
113 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
114 #define REMOTE_LAST_RX_RATE \
115 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
116 #define REMOTE_WMM \
117 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
118 #define REMOTE_SUPPORTED_MODE \
119 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
120 #define REMOTE_AMPDU \
121 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
122 #define REMOTE_TX_STBC \
123 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
124 #define REMOTE_RX_STBC \
125 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
126 #define REMOTE_CH_WIDTH\
127 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
128 #define REMOTE_SGI_ENABLE\
129 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
130 #define REMOTE_PAD\
131 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
132 #define REMOTE_RX_RETRY_COUNT \
133 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_RETRY_COUNT
134 #define REMOTE_RX_BC_MC_COUNT \
135 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BC_MC_COUNT
136 #define DISCONNECT_REASON \
137 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON
138 #define BEACON_IES \
139 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES
140 #define ASSOC_REQ_IES \
141 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES
142 #define REMOTE_CH_WIDTH_V2\
143 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH_V2
144 #define EHT_OPERATION \
145 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_EHT_OPERATION
146 
147 /*
148  * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
149  * feature or not, if first bit is 1 it indicates that FW supports this
150  * feature, if it is 0 it indicates FW doesn't support this feature
151  */
152 #define HDD_STATION_INFO_RX_MC_BC_COUNT (1 << 31)
153 
154 /*
155  * Use this macro to check channel bandwidth 160MHZ
156  */
157 #define MAX_CHANNEL_BW_160 160
158 
159 const struct nla_policy
160 hdd_get_station_policy[STATION_MAX + 1] = {
161 	[STATION_INFO] = {.type = NLA_FLAG},
162 	[STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
163 	[STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
164 };
165 
166 const struct nla_policy
167 hdd_get_sta_policy[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1] = {
168 	[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC] = {.type = NLA_BINARY,
169 						   .len = QDF_MAC_ADDR_SIZE},
170 };
171 
hdd_get_sta_congestion(struct wlan_hdd_link_info * link_info,uint32_t * congestion)172 static int hdd_get_sta_congestion(struct wlan_hdd_link_info *link_info,
173 				  uint32_t *congestion)
174 {
175 	QDF_STATUS status;
176 	struct cca_stats cca_stats;
177 	struct wlan_objmgr_vdev *vdev;
178 
179 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_STATS_ID);
180 	if (!vdev) {
181 		hdd_err("vdev is NULL");
182 		return -EINVAL;
183 	}
184 
185 	status = ucfg_mc_cp_stats_cca_stats_get(vdev, &cca_stats);
186 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_STATS_ID);
187 	if (QDF_IS_STATUS_ERROR(status))
188 		return -EINVAL;
189 
190 	*congestion = cca_stats.congestion;
191 	return 0;
192 }
193 
194 /**
195  * hdd_get_station_assoc_fail() - Handle get station assoc fail
196  * @link_info: Link info pointer in HDD adaper
197  *
198  * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
199  * Validate cmd attributes and send the station info to upper layers.
200  *
201  * Return: Success(0) or reason code for failure
202  */
hdd_get_station_assoc_fail(struct wlan_hdd_link_info * link_info)203 static int hdd_get_station_assoc_fail(struct wlan_hdd_link_info *link_info)
204 {
205 	struct sk_buff *skb = NULL;
206 	uint32_t nl_buf_len;
207 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
208 	struct hdd_station_ctx *hdd_sta_ctx;
209 	uint32_t congestion;
210 
211 	nl_buf_len = NLMSG_HDRLEN;
212 	nl_buf_len += sizeof(uint32_t);
213 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
214 						       nl_buf_len);
215 	if (!skb) {
216 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
217 		return -ENOMEM;
218 	}
219 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
220 
221 	if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
222 			hdd_sta_ctx->conn_info.assoc_status_code)) {
223 		hdd_err("put fail");
224 		goto fail;
225 	}
226 
227 	if (hdd_get_sta_congestion(link_info, &congestion))
228 		congestion = 0;
229 
230 	hdd_info("congestion:%d", congestion);
231 	if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
232 			congestion)) {
233 		hdd_err("put fail");
234 		goto fail;
235 	}
236 
237 	return wlan_cfg80211_vendor_cmd_reply(skb);
238 fail:
239 	wlan_cfg80211_vendor_free_skb(skb);
240 	return -EINVAL;
241 }
242 
243 /**
244  * hdd_convert_auth_type() - transform auth type specific to
245  * vendor command
246  * @auth_type: csr auth type
247  *
248  * Return: vendor command auth type
249  */
hdd_convert_auth_type(uint32_t auth_type)250 static int hdd_convert_auth_type(uint32_t auth_type)
251 {
252 	uint32_t ret_val;
253 
254 	switch (auth_type) {
255 	case eCSR_AUTH_TYPE_OPEN_SYSTEM:
256 		ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
257 		break;
258 	case eCSR_AUTH_TYPE_SHARED_KEY:
259 		ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
260 		break;
261 	case eCSR_AUTH_TYPE_WPA:
262 		ret_val = QCA_WLAN_AUTH_TYPE_WPA;
263 		break;
264 	case eCSR_AUTH_TYPE_WPA_PSK:
265 		ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
266 		break;
267 	case eCSR_AUTH_TYPE_AUTOSWITCH:
268 		ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
269 		break;
270 	case eCSR_AUTH_TYPE_WPA_NONE:
271 		ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
272 		break;
273 	case eCSR_AUTH_TYPE_RSN:
274 		ret_val = QCA_WLAN_AUTH_TYPE_RSN;
275 		break;
276 	case eCSR_AUTH_TYPE_RSN_PSK:
277 		ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
278 		break;
279 	case eCSR_AUTH_TYPE_FT_RSN:
280 		ret_val = QCA_WLAN_AUTH_TYPE_FT;
281 		break;
282 	case eCSR_AUTH_TYPE_FT_RSN_PSK:
283 		ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
284 		break;
285 	case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
286 		ret_val = QCA_WLAN_AUTH_TYPE_WAI;
287 		break;
288 	case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
289 		ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
290 		break;
291 	case eCSR_AUTH_TYPE_CCKM_WPA:
292 		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
293 		break;
294 	case eCSR_AUTH_TYPE_CCKM_RSN:
295 		ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
296 		break;
297 	case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
298 		ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
299 		break;
300 	case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
301 		ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
302 		break;
303 	case eCSR_AUTH_TYPE_FT_SAE:
304 		ret_val = QCA_WLAN_AUTH_TYPE_FT_SAE;
305 		break;
306 	case eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384:
307 		ret_val = QCA_WLAN_AUTH_TYPE_FT_SUITEB_EAP_SHA384;
308 		break;
309 	case eCSR_AUTH_TYPE_SAE:
310 		ret_val = QCA_WLAN_AUTH_TYPE_SAE;
311 		break;
312 	case eCSR_AUTH_TYPE_FILS_SHA256:
313 		ret_val = QCA_WLAN_AUTH_TYPE_FILS_SHA256;
314 		break;
315 	case eCSR_AUTH_TYPE_FILS_SHA384:
316 		ret_val = QCA_WLAN_AUTH_TYPE_FILS_SHA384;
317 		break;
318 	case eCSR_AUTH_TYPE_FT_FILS_SHA256:
319 		ret_val = QCA_WLAN_AUTH_TYPE_FT_FILS_SHA256;
320 		break;
321 	case eCSR_AUTH_TYPE_FT_FILS_SHA384:
322 		ret_val = QCA_WLAN_AUTH_TYPE_FT_FILS_SHA384;
323 		break;
324 	case eCSR_AUTH_TYPE_DPP_RSN:
325 		ret_val = QCA_WLAN_AUTH_TYPE_DPP_RSN;
326 		break;
327 	case eCSR_AUTH_TYPE_OWE:
328 		ret_val = QCA_WLAN_AUTH_TYPE_OWE;
329 		break;
330 	case eCSR_AUTH_TYPE_SUITEB_EAP_SHA256:
331 		ret_val = QCA_WLAN_AUTH_TYPE_SUITEB_EAP_SHA256;
332 		break;
333 	case eCSR_AUTH_TYPE_SUITEB_EAP_SHA384:
334 		ret_val = QCA_WLAN_AUTH_TYPE_SUITEB_EAP_SHA384;
335 		break;
336 	case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
337 	case eCSR_AUTH_TYPE_FAILED:
338 	case eCSR_AUTH_TYPE_NONE:
339 	default:
340 		ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
341 		break;
342 	}
343 	return ret_val;
344 }
345 
346 /**
347  * hdd_convert_dot11mode() - transform dot11mode type specific to
348  * vendor command
349  * @dot11mode: CSR dot11 mode
350  *
351  * Return: vendor command dot11 mode
352  */
hdd_convert_dot11mode(uint32_t dot11mode)353 static int hdd_convert_dot11mode(uint32_t dot11mode)
354 {
355 	uint32_t ret_val;
356 
357 	switch (dot11mode) {
358 	case eCSR_CFG_DOT11_MODE_11A:
359 		ret_val = QCA_WLAN_802_11_MODE_11A;
360 		break;
361 	case eCSR_CFG_DOT11_MODE_11B:
362 		ret_val = QCA_WLAN_802_11_MODE_11B;
363 		break;
364 	case eCSR_CFG_DOT11_MODE_11G:
365 		ret_val = QCA_WLAN_802_11_MODE_11G;
366 		break;
367 	case eCSR_CFG_DOT11_MODE_11N:
368 		ret_val = QCA_WLAN_802_11_MODE_11N;
369 		break;
370 	case eCSR_CFG_DOT11_MODE_11AC:
371 		ret_val = QCA_WLAN_802_11_MODE_11AC;
372 		break;
373 	case eCSR_CFG_DOT11_MODE_11AX:
374 		ret_val = QCA_WLAN_802_11_MODE_11AX;
375 		break;
376 	case eCSR_CFG_DOT11_MODE_11BE:
377 		ret_val = QCA_WLAN_802_11_MODE_11BE;
378 		break;
379 	case eCSR_CFG_DOT11_MODE_AUTO:
380 	case eCSR_CFG_DOT11_MODE_ABG:
381 	default:
382 		ret_val = QCA_WLAN_802_11_MODE_INVALID;
383 	}
384 	return ret_val;
385 }
386 
387 /**
388  * hdd_calculate_tx_bitrate_ie_size - calculate tx bitrate ie size
389  *
390  * Return: tx bitrate ie size
391  */
hdd_calculate_tx_bitrate_ie_size(void)392 static uint32_t hdd_calculate_tx_bitrate_ie_size(void)
393 {
394 	uint32_t nl_buf_len = nla_total_size(0);
395 
396 		/* NL80211_RATE_INFO_BITRATE32 */
397 	nl_buf_len +=  nla_total_size(sizeof(uint32_t)) +
398 		/* NL80211_RATE_INFO_BITRATE */
399 		nla_total_size(sizeof(uint16_t)) +
400 		/* NL80211_RATE_INFO_VHT_NSS */
401 		nla_total_size(sizeof(uint8_t));
402 
403 	return nl_buf_len;
404 }
405 
406 /**
407  * hdd_add_tx_bitrate() - add tx bitrate attribute
408  * @skb: pointer to sk buff
409  * @link_info: Link info pointer in HDD adapter
410  * @idx: attribute index
411  *
412  * Return: Success(0) or reason code for failure
413  */
hdd_add_tx_bitrate(struct sk_buff * skb,struct wlan_hdd_link_info * link_info,int idx)414 static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
415 				  struct wlan_hdd_link_info *link_info, int idx)
416 {
417 	struct nlattr *nla_attr;
418 	uint32_t bitrate, bitrate_compat;
419 	struct hdd_station_ctx *sta_ctx;
420 
421 	nla_attr = nla_nest_start(skb, idx);
422 	if (!nla_attr) {
423 		hdd_err("nla_nest_start failed");
424 		goto fail;
425 	}
426 
427 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
428 
429 	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
430 	if (hdd_cm_is_vdev_associated(link_info))
431 		bitrate = cfg80211_calculate_bitrate(
432 				&sta_ctx->cache_conn_info.max_tx_bitrate);
433 	else
434 		bitrate = cfg80211_calculate_bitrate(
435 					&sta_ctx->cache_conn_info.txrate);
436 	/* report 16-bit bitrate only if we can */
437 	bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
438 
439 	if (bitrate > 0) {
440 		if (nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
441 			hdd_err("put fail bitrate: %u", bitrate);
442 			goto fail;
443 		}
444 	} else {
445 		hdd_err("Invalid bitrate: %u", bitrate);
446 	}
447 
448 	if (bitrate_compat > 0) {
449 		if (nla_put_u16(skb, NL80211_RATE_INFO_BITRATE,
450 				bitrate_compat)) {
451 			hdd_err("put fail bitrate_compat: %u", bitrate_compat);
452 			goto fail;
453 		}
454 	} else {
455 		hdd_err("Invalid bitrate_compat: %u", bitrate_compat);
456 	}
457 
458 	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
459 		      sta_ctx->cache_conn_info.txrate.nss)) {
460 		hdd_err("put fail");
461 		goto fail;
462 	}
463 	nla_nest_end(skb, nla_attr);
464 
465 	hdd_nofl_debug(
466 		"STA Tx rate info:: bitrate:%d, bitrate_compat:%d, NSS:%d",
467 		bitrate, bitrate_compat,
468 		sta_ctx->cache_conn_info.txrate.nss);
469 
470 	return 0;
471 fail:
472 	return -EINVAL;
473 }
474 
475 /**
476  * hdd_calculate_sta_info_ie_size - calculate sta info size
477  *
478  * Return: sta info ie size
479  */
hdd_calculate_sta_info_ie_size(void)480 static uint32_t hdd_calculate_sta_info_ie_size(void)
481 {
482 	uint32_t nl_buf_len = nla_total_size(0);
483 
484 		/* NL80211_STA_INFO_SIGNAL */
485 	nl_buf_len += nla_total_size(sizeof(int8_t)) +
486 		hdd_calculate_tx_bitrate_ie_size();
487 
488 	return nl_buf_len;
489 }
490 
491 /**
492  * hdd_add_sta_info() - add station info attribute
493  * @skb: pointer to sk buff
494  * @link_info: Link info pointer in HDD adapter
495  * @idx: attribute index
496  *
497  * Return: Success(0) or reason code for failure
498  */
hdd_add_sta_info(struct sk_buff * skb,struct wlan_hdd_link_info * link_info,int idx)499 static int32_t hdd_add_sta_info(struct sk_buff *skb,
500 				struct wlan_hdd_link_info *link_info, int idx)
501 {
502 	struct nlattr *nla_attr;
503 	struct hdd_station_ctx *hdd_sta_ctx;
504 
505 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
506 
507 	nla_attr = nla_nest_start(skb, idx);
508 	if (!nla_attr) {
509 		hdd_err("nla_nest_start failed");
510 		goto fail;
511 	}
512 
513 	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
514 		       (hdd_sta_ctx->cache_conn_info.signal + 100))) {
515 		hdd_err("put fail");
516 		goto fail;
517 	}
518 
519 	if (hdd_cm_is_vdev_associated(link_info))
520 		hdd_get_max_tx_bitrate(link_info);
521 
522 	if (hdd_add_tx_bitrate(skb, link_info, NL80211_STA_INFO_TX_BITRATE)) {
523 		hdd_err("hdd_add_tx_bitrate failed");
524 		goto fail;
525 	}
526 
527 	nla_nest_end(skb, nla_attr);
528 	return 0;
529 fail:
530 	return -EINVAL;
531 }
532 
533 /**
534  * hdd_calculate_survey_info_ie_size - calculate survey info size
535  *
536  * Return: survey info ie size
537  */
hdd_calculate_survey_info_ie_size(void)538 static uint32_t hdd_calculate_survey_info_ie_size(void)
539 {
540 	uint32_t nl_buf_len = nla_total_size(0);
541 
542 		/* NL80211_SURVEY_INFO_FREQUENCY */
543 	nl_buf_len +=  nla_total_size(sizeof(uint32_t)) +
544 		 /* NL80211_SURVEY_INFO_NOISE */
545 		nla_total_size(sizeof(int8_t));
546 
547 	return nl_buf_len;
548 }
549 
550 /**
551  * hdd_add_survey_info() - add survey info attribute
552  * @skb: pointer to sk buff
553  * @hdd_sta_ctx: pointer to hdd station context
554  * @idx: attribute index
555  *
556  * Return: Success(0) or reason code for failure
557  */
hdd_add_survey_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx,int idx)558 static int32_t hdd_add_survey_info(struct sk_buff *skb,
559 				   struct hdd_station_ctx *hdd_sta_ctx,
560 				   int idx)
561 {
562 	struct nlattr *nla_attr;
563 
564 	nla_attr = nla_nest_start(skb, idx);
565 	if (!nla_attr)
566 		goto fail;
567 	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
568 			hdd_sta_ctx->cache_conn_info.chan_freq) ||
569 	    nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
570 		       (hdd_sta_ctx->cache_conn_info.noise + 100))) {
571 		hdd_err("put fail");
572 		goto fail;
573 	}
574 	nla_nest_end(skb, nla_attr);
575 	return 0;
576 fail:
577 	return -EINVAL;
578 }
579 
580 /**
581  * hdd_calculate_link_standard_info_ie_size - calculate link standard info size
582  *
583  * Return: link standard info ie size
584  */
hdd_calculate_link_standard_info_ie_size(void)585 static uint32_t hdd_calculate_link_standard_info_ie_size(void)
586 {
587 	uint32_t nl_buf_len = nla_total_size(0);
588 
589 		/* NL80211_ATTR_SSID */
590 	nl_buf_len += nla_total_size(WLAN_SSID_MAX_LEN + 1) +
591 		/* NL80211_ATTR_MAC */
592 		nla_total_size(QDF_MAC_ADDR_SIZE) +
593 		hdd_calculate_survey_info_ie_size() +
594 		hdd_calculate_sta_info_ie_size();
595 
596 	return nl_buf_len;
597 }
598 
599 /**
600  * hdd_add_link_standard_info() - add link info attribute
601  * @skb: pointer to sk buff
602  * @link_info: Link info pointer in HDD adapter
603  * @idx: attribute index
604  *
605  * Return: Success(0) or reason code for failure
606  */
607 static int32_t
hdd_add_link_standard_info(struct sk_buff * skb,struct wlan_hdd_link_info * link_info,int idx)608 hdd_add_link_standard_info(struct sk_buff *skb,
609 			   struct wlan_hdd_link_info *link_info, int idx)
610 {
611 	struct nlattr *nla_attr;
612 	struct hdd_station_ctx *hdd_sta_ctx;
613 
614 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
615 	if (!hdd_sta_ctx) {
616 		hdd_err("Invalid sta ctx");
617 		goto fail;
618 	}
619 
620 	nla_attr = nla_nest_start(skb, idx);
621 	if (!nla_attr) {
622 		hdd_err("nla_nest_start failed");
623 		goto fail;
624 	}
625 
626 	if (nla_put(skb,
627 		    NL80211_ATTR_SSID,
628 		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
629 		    hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
630 		hdd_err("put fail");
631 		goto fail;
632 	}
633 	if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
634 		    hdd_sta_ctx->cache_conn_info.bssid.bytes)) {
635 		hdd_err("put bssid failed");
636 		goto fail;
637 	}
638 	if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) {
639 		hdd_err("hdd_add_survey_info failed");
640 		goto fail;
641 	}
642 
643 	if (hdd_add_sta_info(skb, link_info, NL80211_ATTR_STA_INFO)) {
644 		hdd_err("hdd_add_sta_info failed");
645 		goto fail;
646 	}
647 	nla_nest_end(skb, nla_attr);
648 	return 0;
649 fail:
650 	return -EINVAL;
651 }
652 
653 /**
654  * hdd_calculate_ap_standard_info_ie_size - calculate ap standard info size
655  * @hdd_sta_ctx: pointer to hdd station context
656  *
657  * Return: ap standard info size
658  */
hdd_calculate_ap_standard_info_ie_size(struct hdd_station_ctx * hdd_sta_ctx)659 static uint32_t hdd_calculate_ap_standard_info_ie_size(
660 			struct hdd_station_ctx *hdd_sta_ctx)
661 {
662 	uint32_t nl_buf_len = nla_total_size(0);
663 
664 	/* NL80211_ATTR_VHT_CAPABILITY */
665 	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
666 		nl_buf_len += nla_total_size(sizeof(
667 				hdd_sta_ctx->cache_conn_info.vht_caps));
668 	/* NL80211_ATTR_HT_CAPABILITY */
669 	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
670 		nl_buf_len += nla_total_size(sizeof(
671 				hdd_sta_ctx->cache_conn_info.ht_caps));
672 
673 	return nl_buf_len;
674 }
675 
676 /**
677  * hdd_add_ap_standard_info() - add ap info attribute
678  * @skb: pointer to sk buff
679  * @hdd_sta_ctx: pointer to hdd station context
680  * @idx: attribute index
681  *
682  * Return: Success(0) or reason code for failure
683  */
684 static int32_t
hdd_add_ap_standard_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx,int idx)685 hdd_add_ap_standard_info(struct sk_buff *skb,
686 			 struct hdd_station_ctx *hdd_sta_ctx, int idx)
687 {
688 	struct nlattr *nla_attr;
689 	struct hdd_connection_info *conn_info;
690 
691 	conn_info = &hdd_sta_ctx->cache_conn_info;
692 	nla_attr = nla_nest_start(skb, idx);
693 	if (!nla_attr)
694 		goto fail;
695 	if (conn_info->conn_flag.vht_present) {
696 		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
697 			    sizeof(conn_info->vht_caps),
698 			    &conn_info->vht_caps)) {
699 			hdd_err("put fail");
700 			goto fail;
701 		}
702 		hdd_nofl_debug("STA VHT capabilities:");
703 		qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
704 				   (uint8_t *)&conn_info->vht_caps,
705 				   sizeof(conn_info->vht_caps));
706 	}
707 	if (conn_info->conn_flag.ht_present) {
708 		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
709 			    sizeof(conn_info->ht_caps),
710 			    &conn_info->ht_caps)) {
711 			hdd_err("put fail");
712 			goto fail;
713 		}
714 		hdd_nofl_debug("STA HT capabilities:");
715 		qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
716 				   (uint8_t *)&conn_info->ht_caps,
717 				   sizeof(conn_info->ht_caps));
718 	}
719 	nla_nest_end(skb, nla_attr);
720 	return 0;
721 fail:
722 	return -EINVAL;
723 }
724 
725 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) && \
726      defined(WLAN_FEATURE_11AX)
hdd_add_he_oper_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx)727 static int32_t hdd_add_he_oper_info(struct sk_buff *skb,
728 				    struct hdd_station_ctx *hdd_sta_ctx)
729 {
730 	int32_t ret = 0;
731 	struct hdd_connection_info *conn_info;
732 
733 	conn_info = &hdd_sta_ctx->cache_conn_info;
734 	if (!conn_info->he_oper_len || !conn_info->he_operation)
735 		return ret;
736 
737 	if (nla_put(skb, HE_OPERATION, conn_info->he_oper_len,
738 		    conn_info->he_operation)) {
739 		ret = -EINVAL;
740 	} else {
741 		hdd_nofl_debug("STA HE operation:");
742 		qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
743 				   (uint8_t *)&conn_info->he_operation,
744 				   conn_info->he_oper_len);
745 	}
746 
747 	qdf_mem_free(hdd_sta_ctx->cache_conn_info.he_operation);
748 	hdd_sta_ctx->cache_conn_info.he_operation = NULL;
749 	hdd_sta_ctx->cache_conn_info.he_oper_len = 0;
750 	return ret;
751 }
752 
hdd_get_he_op_len(struct hdd_station_ctx * hdd_sta_ctx)753 static int32_t hdd_get_he_op_len(struct hdd_station_ctx *hdd_sta_ctx)
754 {
755 	return hdd_sta_ctx->cache_conn_info.he_oper_len;
756 }
757 
758 #else
hdd_add_he_oper_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx)759 static inline uint32_t hdd_add_he_oper_info(
760 					struct sk_buff *skb,
761 					struct hdd_station_ctx *hdd_sta_ctx)
762 {
763 	return 0;
764 }
765 
hdd_get_he_op_len(struct hdd_station_ctx * hdd_sta_ctx)766 static uint32_t hdd_get_he_op_len(struct hdd_station_ctx *hdd_sta_ctx)
767 {
768 	return 0;
769 }
770 #endif
771 
772 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) && \
773 	defined(WLAN_FEATURE_11BE)
hdd_add_eht_oper_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx)774 static int32_t hdd_add_eht_oper_info(struct sk_buff *skb,
775 				     struct hdd_station_ctx *hdd_sta_ctx)
776 {
777 	int32_t ret = 0;
778 	struct hdd_connection_info *conn_info;
779 
780 	conn_info = &hdd_sta_ctx->cache_conn_info;
781 	if (!conn_info->eht_oper_len)
782 		return -EINVAL;
783 
784 	if (nla_put(skb, EHT_OPERATION, conn_info->eht_oper_len,
785 		    &conn_info->eht_operation)) {
786 		ret = -EINVAL;
787 	} else {
788 		hdd_nofl_debug("STA EHT operation:");
789 		qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
790 				   (uint8_t *)&conn_info->eht_operation,
791 				   conn_info->eht_oper_len);
792 	}
793 
794 	return ret;
795 }
796 #else
hdd_add_eht_oper_info(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx)797 static inline int32_t hdd_add_eht_oper_info(
798 					struct sk_buff *skb,
799 					struct hdd_station_ctx *hdd_sta_ctx)
800 {
801 	return 0;
802 }
803 #endif
804 
hdd_get_prev_connected_bss_ies_len(struct hdd_station_ctx * hdd_sta_ctx)805 static uint32_t hdd_get_prev_connected_bss_ies_len(
806 					struct hdd_station_ctx *hdd_sta_ctx)
807 {
808 	return hdd_sta_ctx->conn_info.prev_ap_bcn_ie.len;
809 }
810 
hdd_add_prev_connected_bss_ies(struct sk_buff * skb,struct hdd_station_ctx * hdd_sta_ctx)811 static uint32_t hdd_add_prev_connected_bss_ies(
812 					struct sk_buff *skb,
813 					struct hdd_station_ctx *hdd_sta_ctx)
814 {
815 	struct element_info *bcn_ie = &hdd_sta_ctx->conn_info.prev_ap_bcn_ie;
816 
817 	if (bcn_ie->len) {
818 		if (nla_put(skb, BEACON_IES, bcn_ie->len, bcn_ie->ptr)) {
819 			hdd_err("Failed to put beacon IEs: bytes left: %d, ie_len: %u ",
820 				skb_tailroom(skb), bcn_ie->len);
821 			return -EINVAL;
822 		}
823 
824 		hdd_nofl_debug("Beacon IEs len: %u", bcn_ie->len);
825 
826 		qdf_mem_free(bcn_ie->ptr);
827 		bcn_ie->ptr = NULL;
828 		bcn_ie->len = 0;
829 	}
830 
831 	return 0;
832 }
833 
834 /**
835  * hdd_calculate_station_info_ie_size - calculate bss ie size
836  * @hdd_sta_ctx: pointer to hdd station context
837  *
838  * Return: bss ie size
839  */
hdd_calculate_station_info_ie_size(struct hdd_station_ctx * hdd_sta_ctx)840 static uint32_t hdd_calculate_station_info_ie_size(
841 					struct hdd_station_ctx *hdd_sta_ctx)
842 {
843 	/* NLA_HDRLEN */
844 	uint32_t nl_buf_len = NLA_HDRLEN;
845 
846 	nl_buf_len += hdd_calculate_link_standard_info_ie_size() +
847 		hdd_calculate_ap_standard_info_ie_size(hdd_sta_ctx);
848 
849 		/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT */
850 	nl_buf_len += nla_total_size(sizeof(uint32_t)) +
851 		/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM */
852 		nla_total_size(sizeof(uint32_t)) +
853 		/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE */
854 		nla_total_size(sizeof(uint32_t));
855 
856 	 /* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION */
857 	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
858 		nl_buf_len += nla_total_size(sizeof(
859 				hdd_sta_ctx->cache_conn_info.ht_operation));
860 
861 	/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION */
862 	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
863 		nl_buf_len += nla_total_size(sizeof(
864 				hdd_sta_ctx->cache_conn_info.vht_operation));
865 
866 	/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HE_OPERATION */
867 	nl_buf_len += nla_total_size(hdd_get_he_op_len(hdd_sta_ctx));
868 
869 	/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION */
870 	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
871 		nl_buf_len += nla_total_size(sizeof(
872 			hdd_sta_ctx->cache_conn_info.hs20vendor_ie) - 1);
873 
874 	 /* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_DRIVER_DISCONNECT_REASON */
875 	nl_buf_len += nla_total_size(sizeof(uint32_t));
876 
877 	/* QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_BEACON_IES */
878 	if (hdd_sta_ctx->conn_info.prev_ap_bcn_ie.len)
879 		nl_buf_len += nla_total_size(
880 			hdd_get_prev_connected_bss_ies_len(hdd_sta_ctx));
881 
882 	return nl_buf_len;
883 }
884 
885 /**
886  * hdd_populate_station_info_skb - populate station info in skb
887  * @skb: pointer to socket buffer
888  * @link_info: Link info pointer in HDD adapter
889  *
890  * Return: QDF_STATUS_SUCCESS in case of success else failure
891  */
892 static QDF_STATUS
hdd_populate_station_info_skb(struct sk_buff * skb,struct wlan_hdd_link_info * link_info)893 hdd_populate_station_info_skb(struct sk_buff *skb,
894 			      struct wlan_hdd_link_info *link_info)
895 {
896 	uint8_t *tmp_hs20 = NULL;
897 	struct hdd_station_ctx *hdd_sta_ctx =
898 					WLAN_HDD_GET_STATION_CTX_PTR(link_info);
899 
900 	if (hdd_add_link_standard_info(skb, link_info,
901 				       LINK_INFO_STANDARD_NL80211_ATTR)) {
902 		hdd_err("link_standard_info put fail");
903 		return QDF_STATUS_E_FAILURE;
904 	}
905 
906 	if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
907 				     AP_INFO_STANDARD_NL80211_ATTR)) {
908 		hdd_err("ap standard info fail");
909 		return QDF_STATUS_E_FAILURE;
910 	}
911 
912 	if (nla_put_u32(skb, INFO_ROAM_COUNT,
913 			hdd_sta_ctx->cache_conn_info.roam_count) ||
914 	    nla_put_u32(skb, INFO_AKM,
915 			hdd_convert_auth_type(
916 			hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
917 	    nla_put_u32(skb, WLAN802_11_MODE,
918 			hdd_convert_dot11mode(
919 			hdd_sta_ctx->cache_conn_info.dot11mode))) {
920 		hdd_err("Roam, AKM, dot11mode put fail");
921 		return QDF_STATUS_E_FAILURE;
922 	}
923 
924 	if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present) {
925 		if (nla_put(skb, HT_OPERATION,
926 			    (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
927 			    &hdd_sta_ctx->cache_conn_info.ht_operation)) {
928 			hdd_err("ht operation put fail");
929 			return QDF_STATUS_E_FAILURE;
930 		}
931 		hdd_nofl_debug("STA HT operation:");
932 		qdf_trace_hex_dump(
933 			QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
934 			(uint8_t *)&hdd_sta_ctx->cache_conn_info.ht_operation,
935 			sizeof(hdd_sta_ctx->cache_conn_info.ht_operation));
936 	}
937 
938 	if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present) {
939 		if (nla_put(skb, VHT_OPERATION,
940 			    (sizeof(hdd_sta_ctx->
941 					cache_conn_info.vht_operation)),
942 			    &hdd_sta_ctx->cache_conn_info.vht_operation)) {
943 			hdd_err("vht operation put fail");
944 			return QDF_STATUS_E_FAILURE;
945 		}
946 		hdd_nofl_debug("STA VHT operation:");
947 		qdf_trace_hex_dump(
948 			QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
949 			(uint8_t *)&hdd_sta_ctx->cache_conn_info.vht_operation,
950 			sizeof(hdd_sta_ctx->cache_conn_info.vht_operation));
951 	}
952 
953 	if (hdd_add_he_oper_info(skb, hdd_sta_ctx)) {
954 		hdd_err("he operation info put fail");
955 		return QDF_STATUS_E_FAILURE;
956 	}
957 	if (hdd_sta_ctx->cache_conn_info.conn_flag.eht_op_present) {
958 		if (hdd_add_eht_oper_info(skb, hdd_sta_ctx)) {
959 			hdd_err("eht operation info put fail");
960 			return QDF_STATUS_E_FAILURE;
961 		}
962 	}
963 
964 	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
965 		tmp_hs20 =
966 			(uint8_t *)&hdd_sta_ctx->cache_conn_info.hs20vendor_ie;
967 		if (nla_put(skb, AP_INFO_HS20_INDICATION,
968 			    (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
969 			     - 1),
970 			    tmp_hs20 + 1)) {
971 			hdd_err("hs20 put fail");
972 			return QDF_STATUS_E_FAILURE;
973 		}
974 		hdd_nofl_debug("STA hs20 vendor IE:");
975 		qdf_trace_hex_dump(
976 			QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
977 			(uint8_t *)(tmp_hs20 + 1),
978 			sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie) - 1);
979 	}
980 
981 	if (nla_put_u32(skb, DISCONNECT_REASON,
982 			link_info->adapter->last_disconnect_reason)) {
983 		hdd_err("Failed to put disconnect reason");
984 		return QDF_STATUS_E_FAILURE;
985 	}
986 
987 	if (hdd_add_prev_connected_bss_ies(skb, hdd_sta_ctx)) {
988 		hdd_err("disconnect_reason put fail");
989 		return QDF_STATUS_E_FAILURE;
990 	}
991 	return QDF_STATUS_SUCCESS;
992 }
993 
994 /**
995  * hdd_get_station_info() - send BSS information to supplicant
996  * @link_info: Link info pointer in HDD adapter
997  *
998  * Return: 0 if success else error status
999  */
hdd_get_station_info(struct wlan_hdd_link_info * link_info)1000 static int hdd_get_station_info(struct wlan_hdd_link_info *link_info)
1001 {
1002 	struct sk_buff *skb = NULL;
1003 	uint32_t nl_buf_len;
1004 	struct hdd_adapter *adapter = link_info->adapter;
1005 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1006 	struct hdd_station_ctx *hdd_sta_ctx;
1007 
1008 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
1009 
1010 	if (hdd_cm_is_vdev_connected(link_info)) {
1011 		hdd_err("Station is connected, command is not supported");
1012 		return -EINVAL;
1013 	}
1014 
1015 	nl_buf_len = hdd_calculate_station_info_ie_size(hdd_sta_ctx);
1016 	if (!nl_buf_len) {
1017 		hdd_err("BSS ie size calculation failed");
1018 		return -EINVAL;
1019 	}
1020 
1021 	skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1022 	if (!skb) {
1023 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1024 		return -ENOMEM;
1025 	}
1026 
1027 	if (hdd_populate_station_info_skb(skb, link_info) != QDF_STATUS_SUCCESS)
1028 		goto fail;
1029 
1030 	hdd_nofl_debug(
1031 		"STA Info:: SSID:" QDF_SSID_FMT ", BSSID:" QDF_MAC_ADDR_FMT ", freq:%d, "
1032 		"Noise:%d, signal:%d, roam_count:%d, last_auth_type:%d, "
1033 		"dot11mode:%d, disconnect_reason:%d, ",
1034 		QDF_SSID_REF(WLAN_SSID_MAX_LEN,
1035 			hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId),
1036 		QDF_MAC_ADDR_REF(hdd_sta_ctx->cache_conn_info.bssid.bytes),
1037 		hdd_sta_ctx->cache_conn_info.chan_freq,
1038 		(hdd_sta_ctx->cache_conn_info.noise + 100),
1039 		(hdd_sta_ctx->cache_conn_info.signal + 100),
1040 		hdd_sta_ctx->cache_conn_info.roam_count,
1041 		hdd_convert_auth_type(
1042 			hdd_sta_ctx->cache_conn_info.last_auth_type),
1043 		hdd_convert_dot11mode(hdd_sta_ctx->cache_conn_info.dot11mode),
1044 		adapter->last_disconnect_reason);
1045 
1046 	return wlan_cfg80211_vendor_cmd_reply(skb);
1047 fail:
1048 	wlan_cfg80211_vendor_free_skb(skb);
1049 	return -EINVAL;
1050 }
1051 
1052 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
remote_station_put_u64(struct sk_buff * skb,int32_t attrtype,uint64_t value)1053 static inline int32_t remote_station_put_u64(struct sk_buff *skb,
1054 					     int32_t attrtype,
1055 					     uint64_t value)
1056 {
1057 	return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
1058 }
1059 #else
remote_station_put_u64(struct sk_buff * skb,int32_t attrtype,uint64_t value)1060 static inline int32_t remote_station_put_u64(struct sk_buff *skb,
1061 					     int32_t attrtype,
1062 					     uint64_t value)
1063 {
1064 	return nla_put_u64(skb, attrtype, value);
1065 }
1066 #endif
1067 
1068 /**
1069  * hdd_add_survey_info_sap_get_len - get data length used in
1070  * hdd_add_survey_info_sap()
1071  *
1072  * This function calculates the data length used in hdd_add_survey_info_sap()
1073  *
1074  * Return: total data length used in hdd_add_survey_info_sap()
1075  */
hdd_add_survey_info_sap_get_len(void)1076 static uint32_t hdd_add_survey_info_sap_get_len(void)
1077 {
1078 	return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
1079 }
1080 
1081 /**
1082  * hdd_add_survey_info_sap() - add survey info attribute
1083  * @skb: pointer to response skb buffer
1084  * @stainfo: station information
1085  * @idx: attribute type index for nla_next_start()
1086  *
1087  * This function adds survey info attribute to response skb buffer
1088  *
1089  * Return : 0 on success and errno on failure
1090  */
hdd_add_survey_info_sap(struct sk_buff * skb,struct hdd_station_info * stainfo,int idx)1091 static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
1092 				       struct hdd_station_info *stainfo,
1093 				       int idx)
1094 {
1095 	struct nlattr *nla_attr;
1096 
1097 	nla_attr = nla_nest_start(skb, idx);
1098 	if (!nla_attr)
1099 		goto fail;
1100 	if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
1101 			stainfo->freq)) {
1102 		hdd_err("put fail");
1103 		goto fail;
1104 	}
1105 	nla_nest_end(skb, nla_attr);
1106 	hdd_nofl_debug("Remote STA freq: %d", stainfo->freq);
1107 	return 0;
1108 fail:
1109 	return -EINVAL;
1110 }
1111 
1112 /**
1113  * hdd_add_tx_bitrate_sap_get_len - get data length used in
1114  * hdd_add_tx_bitrate_sap()
1115  *
1116  * This function calculates the data length used in hdd_add_tx_bitrate_sap()
1117  *
1118  * Return: total data length used in hdd_add_tx_bitrate_sap()
1119  */
hdd_add_tx_bitrate_sap_get_len(void)1120 static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
1121 {
1122 	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
1123 }
1124 
hdd_add_sta_capability_get_len(void)1125 static uint32_t hdd_add_sta_capability_get_len(void)
1126 {
1127 	return nla_total_size(sizeof(uint16_t));
1128 }
1129 
1130 /**
1131  * hdd_add_tx_bitrate_sap - add vhs nss info attribute
1132  * @skb: pointer to response skb buffer
1133  * @stainfo: station information
1134  * @idx: attribute type index for nla_next_start()
1135  *
1136  * This function adds vht nss attribute to response skb buffer
1137  *
1138  * Return : 0 on success and errno on failure
1139  */
hdd_add_tx_bitrate_sap(struct sk_buff * skb,struct hdd_station_info * stainfo,int idx)1140 static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
1141 				  struct hdd_station_info *stainfo,
1142 				  int idx)
1143 {
1144 	struct nlattr *nla_attr;
1145 
1146 	nla_attr = nla_nest_start(skb, idx);
1147 	if (!nla_attr)
1148 		goto fail;
1149 
1150 	if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
1151 		       stainfo->nss)) {
1152 		hdd_err("put fail");
1153 		goto fail;
1154 	}
1155 	nla_nest_end(skb, nla_attr);
1156 	hdd_nofl_debug("Remote STA VHT NSS: %d", stainfo->nss);
1157 	return 0;
1158 fail:
1159 	return -EINVAL;
1160 }
1161 
1162 /**
1163  * hdd_add_sta_info_sap_get_len - get data length used in
1164  * hdd_add_sta_info_sap()
1165  *
1166  * This function calculates the data length used in hdd_add_sta_info_sap()
1167  *
1168  * Return: total data length used in hdd_add_sta_info_sap()
1169  */
hdd_add_sta_info_sap_get_len(void)1170 static uint32_t hdd_add_sta_info_sap_get_len(void)
1171 {
1172 	return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
1173 		hdd_add_tx_bitrate_sap_get_len() +
1174 		hdd_add_sta_capability_get_len());
1175 }
1176 
1177 /**
1178  * hdd_add_sta_info_sap - add sta signal info attribute
1179  * @skb: pointer to response skb buffer
1180  * @rssi: station RSSI
1181  * @stainfo: station information
1182  * @idx: attribute type index for nla_next_start()
1183  *
1184  * This function adds sta signal attribute to response skb buffer
1185  *
1186  * Return : 0 on success and errno on failure
1187  */
hdd_add_sta_info_sap(struct sk_buff * skb,int8_t rssi,struct hdd_station_info * stainfo,int idx)1188 static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
1189 				    struct hdd_station_info *stainfo, int idx)
1190 {
1191 	struct nlattr *nla_attr;
1192 
1193 	nla_attr = nla_nest_start(skb, idx);
1194 	if (!nla_attr)
1195 		goto fail;
1196 
1197 	if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
1198 		       rssi)) {
1199 		hdd_err("put fail");
1200 		goto fail;
1201 	}
1202 	if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
1203 		goto fail;
1204 
1205 	nla_nest_end(skb, nla_attr);
1206 	hdd_nofl_debug("Remote STA RSSI: %d", rssi - HDD_NOISE_FLOOR_DBM);
1207 	return 0;
1208 fail:
1209 	return -EINVAL;
1210 }
1211 
1212 /**
1213  * hdd_add_link_standard_info_sap_get_len - get data length used in
1214  * hdd_add_link_standard_info_sap()
1215  *
1216  * This function calculates the data length used in
1217  * hdd_add_link_standard_info_sap()
1218  *
1219  * Return: total data length used in hdd_add_link_standard_info_sap()
1220  */
hdd_add_link_standard_info_sap_get_len(void)1221 static uint32_t hdd_add_link_standard_info_sap_get_len(void)
1222 {
1223 	return ((NLA_HDRLEN) +
1224 		hdd_add_survey_info_sap_get_len() +
1225 		hdd_add_sta_info_sap_get_len() +
1226 		(sizeof(uint32_t) + NLA_HDRLEN));
1227 }
1228 
1229 /**
1230  * hdd_add_link_standard_info_sap - add add link info attribute
1231  * @skb: pointer to response skb buffer
1232  * @rssi: station RSSI
1233  * @stainfo: station information
1234  * @idx: attribute type index for nla_next_start()
1235  *
1236  * This function adds link info attribute to response skb buffer
1237  *
1238  * Return : 0 on success and errno on failure
1239  */
hdd_add_link_standard_info_sap(struct sk_buff * skb,int8_t rssi,struct hdd_station_info * stainfo,int idx)1240 static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
1241 					  struct hdd_station_info *stainfo,
1242 					  int idx)
1243 {
1244 	struct nlattr *nla_attr;
1245 
1246 	nla_attr = nla_nest_start(skb, idx);
1247 	if (!nla_attr)
1248 		goto fail;
1249 	if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
1250 		goto fail;
1251 	if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
1252 		goto fail;
1253 
1254 	if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
1255 		hdd_err("Reason code put fail");
1256 		goto fail;
1257 	}
1258 	if (nla_put_u16(skb, NL80211_ATTR_STA_CAPABILITY,
1259 			stainfo->capability)) {
1260 		hdd_err("put fail");
1261 		goto fail;
1262 	}
1263 	nla_nest_end(skb, nla_attr);
1264 	return 0;
1265 fail:
1266 	return -EINVAL;
1267 }
1268 
1269 /**
1270  * hdd_add_ap_standard_info_sap_get_len - get data length used in
1271  * hdd_add_ap_standard_info_sap()
1272  * @stainfo: station information
1273  *
1274  * This function calculates the data length used in
1275  * hdd_add_ap_standard_info_sap()
1276  *
1277  * Return: total data length used in hdd_add_ap_standard_info_sap()
1278  */
hdd_add_ap_standard_info_sap_get_len(struct hdd_station_info * stainfo)1279 static uint32_t hdd_add_ap_standard_info_sap_get_len(
1280 				struct hdd_station_info *stainfo)
1281 {
1282 	uint32_t len;
1283 
1284 	len = NLA_HDRLEN;
1285 	if (stainfo->vht_present)
1286 		len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
1287 	if (stainfo->ht_present)
1288 		len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
1289 
1290 	return len;
1291 }
1292 
1293 /**
1294  * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
1295  * @skb: pointer to response skb buffer
1296  * @stainfo: station information
1297  * @idx: attribute type index for nla_next_start()
1298  *
1299  * This function adds HT and VHT info attributes to response skb buffer
1300  *
1301  * Return : 0 on success and errno on failure
1302  */
hdd_add_ap_standard_info_sap(struct sk_buff * skb,struct hdd_station_info * stainfo,int idx)1303 static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
1304 					struct hdd_station_info *stainfo,
1305 					int idx)
1306 {
1307 	struct nlattr *nla_attr;
1308 
1309 	nla_attr = nla_nest_start(skb, idx);
1310 	if (!nla_attr)
1311 		goto fail;
1312 
1313 	if (stainfo->vht_present) {
1314 		if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
1315 			    sizeof(stainfo->vht_caps),
1316 			    &stainfo->vht_caps)) {
1317 			hdd_err("put fail");
1318 			goto fail;
1319 		}
1320 
1321 		hdd_nofl_debug("Remote STA VHT capabilities len:%u",
1322 			       (uint32_t)sizeof(stainfo->vht_caps));
1323 	}
1324 	if (stainfo->ht_present) {
1325 		if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
1326 			    sizeof(stainfo->ht_caps),
1327 			    &stainfo->ht_caps)) {
1328 			hdd_err("put fail");
1329 			goto fail;
1330 		}
1331 
1332 		hdd_nofl_debug("Remote STA HT capabilities len:%u",
1333 			       (uint32_t)sizeof(stainfo->ht_caps));
1334 	}
1335 	nla_nest_end(skb, nla_attr);
1336 	return 0;
1337 fail:
1338 	return -EINVAL;
1339 }
1340 
1341 /**
1342  * hdd_decode_ch_width - decode channel band width based
1343  * @ch_width: encoded enum value holding channel band width
1344  *
1345  * This function decodes channel band width from the given encoded enum value.
1346  *
1347  * Returns: decoded channel band width.
1348  */
hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)1349 static uint16_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
1350 {
1351 	switch (ch_width) {
1352 	case 0:
1353 		return 20;
1354 	case 1:
1355 		return 40;
1356 	case 2:
1357 		return 80;
1358 	case 3:
1359 	case 4:
1360 		return 160;
1361 	case 5:
1362 		return 320;
1363 	default:
1364 		hdd_debug("invalid enum: %d", ch_width);
1365 		return 20;
1366 	}
1367 }
1368 
1369 /**
1370  * hdd_get_cached_station_remote() - get cached(deleted) peer's info
1371  * @hdd_ctx: hdd context
1372  * @adapter: hostapd interface
1373  * @mac_addr: mac address of requested peer
1374  *
1375  * This function collect and indicate the cached(deleted) peer's info
1376  *
1377  * Return: 0 on success, otherwise error value
1378  */
1379 
hdd_get_cached_station_remote(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,struct qdf_mac_addr mac_addr)1380 static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
1381 					 struct hdd_adapter *adapter,
1382 					 struct qdf_mac_addr mac_addr)
1383 {
1384 	struct hdd_station_info *stainfo;
1385 	struct sk_buff *skb = NULL;
1386 	uint32_t nl_buf_len = NLMSG_HDRLEN;
1387 	uint8_t channel_width;
1388 	uint16_t channel_width_v2;
1389 
1390 
1391 	stainfo = hdd_get_sta_info_by_mac(&adapter->cache_sta_info_list,
1392 					  mac_addr.bytes,
1393 					  STA_INFO_GET_CACHED_STATION_REMOTE);
1394 
1395 	if (!stainfo) {
1396 		hdd_err("peer " QDF_MAC_ADDR_FMT " not found",
1397 			QDF_MAC_ADDR_REF(mac_addr.bytes));
1398 		return -EINVAL;
1399 	}
1400 
1401 	nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
1402 			hdd_add_ap_standard_info_sap_get_len(stainfo) +
1403 			(sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
1404 			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
1405 			(sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
1406 			(sizeof(stainfo->rx_rate) + NLA_HDRLEN) +
1407 			(sizeof(stainfo->support_mode) + NLA_HDRLEN) +
1408 			(sizeof(stainfo->rx_mc_bc_cnt) + NLA_HDRLEN) +
1409 			(sizeof(stainfo->rx_retry_cnt) + NLA_HDRLEN);
1410 	if (stainfo->assoc_req_ies.len)
1411 		nl_buf_len += stainfo->assoc_req_ies.len + NLA_HDRLEN;
1412 
1413 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
1414 						       nl_buf_len);
1415 	if (!skb) {
1416 		hdd_put_sta_info_ref(&adapter->cache_sta_info_list,
1417 				     &stainfo, true,
1418 				     STA_INFO_GET_CACHED_STATION_REMOTE);
1419 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1420 		return -ENOMEM;
1421 	}
1422 
1423 	if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
1424 					   LINK_INFO_STANDARD_NL80211_ATTR)) {
1425 		hdd_err("link standard put fail");
1426 		goto fail;
1427 	}
1428 
1429 	if (hdd_add_ap_standard_info_sap(skb, stainfo,
1430 					 AP_INFO_STANDARD_NL80211_ATTR)) {
1431 		hdd_err("ap standard put fail");
1432 		goto fail;
1433 	}
1434 
1435 	/* upper layer expects decoded channel BW */
1436 	channel_width_v2 = hdd_decode_ch_width(stainfo->ch_width);
1437 	if (channel_width_v2 > MAX_CHANNEL_BW_160)
1438 		channel_width = MAX_CHANNEL_BW_160;
1439 	else
1440 		channel_width = channel_width_v2;
1441 
1442 	if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
1443 			stainfo->support_mode) ||
1444 	    nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width) ||
1445 	    nla_put_u16(skb, REMOTE_CH_WIDTH_V2, channel_width_v2)) {
1446 		hdd_err("remote ch put fail");
1447 		goto fail;
1448 	}
1449 	/* Convert the data from kbps to mbps as expected by the user space */
1450 	if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate / 1000)) {
1451 		hdd_err("tx rate put fail");
1452 		goto fail;
1453 	}
1454 	/* Convert the data from kbps to mbps as expected by the user space */
1455 	if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate / 1000)) {
1456 		hdd_err("rx rate put fail");
1457 		goto fail;
1458 	}
1459 	if (nla_put_u32(skb, WLAN802_11_MODE, stainfo->dot11_mode)) {
1460 		hdd_err("dot11 mode put fail");
1461 		goto fail;
1462 	}
1463 	if (!(stainfo->rx_mc_bc_cnt & HDD_STATION_INFO_RX_MC_BC_COUNT)) {
1464 		hdd_debug("rx mc bc count is not supported by FW");
1465 	} else if (nla_put_u32(skb, REMOTE_RX_BC_MC_COUNT,
1466 			       (stainfo->rx_mc_bc_cnt &
1467 			       (~HDD_STATION_INFO_RX_MC_BC_COUNT)))) {
1468 		hdd_err("rx mc bc put fail");
1469 		goto fail;
1470 	} else {
1471 		hdd_nofl_debug("Remote STA RX mc_bc_count: %d",
1472 			       (stainfo->rx_mc_bc_cnt &
1473 			       (~HDD_STATION_INFO_RX_MC_BC_COUNT)));
1474 	}
1475 
1476 	/* Currently rx_retry count is not supported */
1477 	if (stainfo->rx_retry_cnt) {
1478 		if (nla_put_u32(skb, REMOTE_RX_RETRY_COUNT,
1479 				stainfo->rx_retry_cnt)) {
1480 			hdd_err("rx retry count put fail");
1481 			goto fail;
1482 		}
1483 		hdd_nofl_debug("Remote STA retry count: %d",
1484 			       stainfo->rx_retry_cnt);
1485 	}
1486 
1487 	if (stainfo->assoc_req_ies.len) {
1488 		if (nla_put(skb, ASSOC_REQ_IES, stainfo->assoc_req_ies.len,
1489 			    stainfo->assoc_req_ies.ptr)) {
1490 			hdd_err("Failed to put assoc req IEs");
1491 			goto fail;
1492 		}
1493 		hdd_nofl_debug("Remote STA assoc req IE len: %d",
1494 			       stainfo->assoc_req_ies.len);
1495 	}
1496 
1497 	hdd_nofl_debug(
1498 		"Remote STA Info:: freq:%d, RSSI:%d, Tx NSS:%d, Reason code:%d,"
1499 		"capability:0x%x, Supported mode:%d, chan_width:%d, Tx rate:%d,"
1500 		"Rx rate:%d, dot11mode:%d",
1501 		stainfo->freq, stainfo->rssi,
1502 		stainfo->nss, stainfo->reason_code, stainfo->capability,
1503 		stainfo->support_mode, channel_width, stainfo->tx_rate,
1504 		stainfo->rx_rate, stainfo->dot11_mode);
1505 
1506 	hdd_sta_info_detach(&adapter->cache_sta_info_list, &stainfo);
1507 	hdd_put_sta_info_ref(&adapter->cache_sta_info_list, &stainfo, true,
1508 			     STA_INFO_GET_CACHED_STATION_REMOTE);
1509 	qdf_atomic_dec(&adapter->cache_sta_count);
1510 
1511 	return wlan_cfg80211_vendor_cmd_reply(skb);
1512 fail:
1513 	hdd_put_sta_info_ref(&adapter->cache_sta_info_list, &stainfo, true,
1514 			     STA_INFO_GET_CACHED_STATION_REMOTE);
1515 	wlan_cfg80211_vendor_free_skb(skb);
1516 	return -EINVAL;
1517 }
1518 
1519 /**
1520  * hdd_get_connected_station_info() - get connected peer's info
1521  * @link_info: Link info pointer in HDD adapter
1522  * @mac_addr: mac address of requested peer
1523  * @stainfo: location to store peer info
1524  *
1525  * This function collect and indicate the connected peer's info
1526  *
1527  * Return: 0 on success, otherwise error value
1528  */
hdd_get_connected_station_info(struct wlan_hdd_link_info * link_info,struct qdf_mac_addr mac_addr,struct hdd_station_info * stainfo)1529 static int hdd_get_connected_station_info(struct wlan_hdd_link_info *link_info,
1530 					  struct qdf_mac_addr mac_addr,
1531 					  struct hdd_station_info *stainfo)
1532 {
1533 	struct sk_buff *skb = NULL;
1534 	uint32_t nl_buf_len;
1535 	struct stats_event *stats;
1536 	bool txrx_rate = false, value;
1537 	QDF_STATUS status;
1538 	int ret;
1539 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1540 
1541 	nl_buf_len = NLMSG_HDRLEN;
1542 	nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
1543 		(sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
1544 		(sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
1545 		(sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
1546 		(sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
1547 		(sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
1548 		(sizeof(stainfo->mode) + NLA_HDRLEN);
1549 
1550 	status = ucfg_mlme_get_sap_get_peer_info(hdd_ctx->psoc, &value);
1551 	if (status != QDF_STATUS_SUCCESS)
1552 		hdd_err("Unable to fetch sap ger peer info");
1553 	if (value) {
1554 		stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(
1555 					link_info->vdev, mac_addr.bytes,
1556 					&ret);
1557 		if (ret || !stats) {
1558 			hdd_err("fail to get tx/rx rate");
1559 			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
1560 		} else {
1561 			txrx_rate = true;
1562 		}
1563 	}
1564 
1565 	if (txrx_rate) {
1566 		stainfo->tx_rate = stats->peer_stats_info_ext->tx_rate;
1567 		stainfo->rx_rate = stats->peer_stats_info_ext->rx_rate;
1568 		stainfo->tx_packets = stats->peer_stats_info_ext->tx_packets;
1569 		stainfo->tx_bytes = stats->peer_stats_info_ext->tx_bytes;
1570 		stainfo->rx_packets = stats->peer_stats_info_ext->rx_packets;
1571 		stainfo->rx_bytes = stats->peer_stats_info_ext->rx_bytes;
1572 		nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
1573 			(sizeof(stainfo->rx_rate) + NLA_HDRLEN);
1574 		wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
1575 	}
1576 
1577 	/* below info is only valid for HT/VHT mode */
1578 	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
1579 		nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
1580 			(sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
1581 			(sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
1582 			(sizeof(stainfo->ch_width) + NLA_HDRLEN) +
1583 			(sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
1584 
1585 	hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
1586 
1587 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
1588 						       nl_buf_len);
1589 	if (!skb) {
1590 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1591 		return -ENOMEM;
1592 	}
1593 
1594 	hdd_info("stainfo");
1595 	hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
1596 		 stainfo->max_phy_rate, stainfo->tx_packets, stainfo->tx_bytes);
1597 	hdd_info("rx_pkts %x rx_bytes %llx mode %x",
1598 		 stainfo->rx_packets, stainfo->rx_bytes, stainfo->mode);
1599 	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
1600 		hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
1601 			 stainfo->ampdu, stainfo->tx_stbc, stainfo->rx_stbc);
1602 		hdd_info("wmm %d chwidth %d sgi %d",
1603 			 stainfo->is_qos_enabled,
1604 			 stainfo->ch_width, stainfo->sgi_enable);
1605 	}
1606 
1607 	if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
1608 	    nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
1609 	    remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
1610 	    nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
1611 	    remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
1612 	    nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
1613 	    nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
1614 		hdd_err("put fail");
1615 		goto fail;
1616 	}
1617 
1618 	if (txrx_rate) {
1619 		if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
1620 		    nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
1621 			hdd_err("put fail");
1622 			goto fail;
1623 		} else {
1624 			hdd_info("tx_rate %x rx_rate %x",
1625 				 stainfo->tx_rate, stainfo->rx_rate);
1626 		}
1627 	}
1628 
1629 	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
1630 		if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
1631 		    nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
1632 		    nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
1633 		    nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
1634 		    nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
1635 			hdd_err("put fail");
1636 			goto fail;
1637 		}
1638 	}
1639 
1640 	return wlan_cfg80211_vendor_cmd_reply(skb);
1641 
1642 fail:
1643 	wlan_cfg80211_vendor_free_skb(skb);
1644 	return -EINVAL;
1645 }
1646 
1647 /**
1648  * hdd_get_station_remote() - get remote peer's info
1649  * @link_info: Link info pointer in HDD adapter
1650  * @mac_addr: mac address of requested peer
1651  *
1652  * This function collect and indicate the remote peer's info
1653  *
1654  * Return: 0 on success, otherwise error value
1655  */
hdd_get_station_remote(struct wlan_hdd_link_info * link_info,struct qdf_mac_addr mac_addr)1656 static int hdd_get_station_remote(struct wlan_hdd_link_info *link_info,
1657 				  struct qdf_mac_addr mac_addr)
1658 {
1659 	int status = 0;
1660 	struct hdd_adapter *adapter = link_info->adapter;
1661 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1662 	struct hdd_station_info *stainfo =
1663 			hdd_get_sta_info_by_mac(
1664 					&adapter->sta_info_list,
1665 					mac_addr.bytes,
1666 					STA_INFO_HDD_GET_STATION_REMOTE);
1667 
1668 	if (!stainfo) {
1669 		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
1670 						       mac_addr);
1671 		return status;
1672 	}
1673 
1674 	status = hdd_get_connected_station_info(link_info, mac_addr, stainfo);
1675 	hdd_put_sta_info_ref(&adapter->sta_info_list, &stainfo, true,
1676 			     STA_INFO_HDD_GET_STATION_REMOTE);
1677 	return status;
1678 }
1679 
1680 /**
1681  * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
1682  * @wiphy: corestack handler
1683  * @wdev: wireless device
1684  * @data: data
1685  * @data_len: data length
1686  *
1687  * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
1688  * Validate cmd attributes and send the station info to upper layers.
1689  *
1690  * Return: Success(0) or reason code for failure
1691  */
1692 static int
__hdd_cfg80211_get_station_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1693 __hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
1694 			       struct wireless_dev *wdev,
1695 			       const void *data,
1696 			       int data_len)
1697 {
1698 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1699 	struct net_device *dev = wdev->netdev;
1700 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1701 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
1702 	int32_t status;
1703 
1704 	hdd_enter_dev(dev);
1705 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
1706 		hdd_err("Command not allowed in FTM mode");
1707 		status = -EPERM;
1708 		goto out;
1709 	}
1710 
1711 	status = wlan_hdd_validate_context(hdd_ctx);
1712 	if (status != 0)
1713 		goto out;
1714 
1715 	status = wlan_cfg80211_nla_parse(tb,
1716 					 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
1717 					 data, data_len,
1718 					 hdd_get_station_policy);
1719 	if (status) {
1720 		hdd_err("Invalid ATTR");
1721 		goto out;
1722 	}
1723 
1724 	/* Parse and fetch Command Type*/
1725 	if (tb[STATION_INFO]) {
1726 		status = hdd_get_station_info(adapter->deflink);
1727 	} else if (tb[STATION_ASSOC_FAIL_REASON]) {
1728 		status = hdd_get_station_assoc_fail(adapter->deflink);
1729 	} else if (tb[STATION_REMOTE]) {
1730 		struct qdf_mac_addr mac_addr;
1731 
1732 		if (adapter->device_mode != QDF_SAP_MODE &&
1733 		    adapter->device_mode != QDF_P2P_GO_MODE) {
1734 			hdd_err("invalid device_mode:%d", adapter->device_mode);
1735 			status = -EINVAL;
1736 			goto out;
1737 		}
1738 
1739 		nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
1740 			   QDF_MAC_ADDR_SIZE);
1741 
1742 		hdd_debug("STATION_REMOTE " QDF_MAC_ADDR_FMT,
1743 			  QDF_MAC_ADDR_REF(mac_addr.bytes));
1744 
1745 		status = hdd_get_station_remote(adapter->deflink, mac_addr);
1746 	} else {
1747 		hdd_err("get station info cmd type failed");
1748 		status = -EINVAL;
1749 		goto out;
1750 	}
1751 	hdd_exit();
1752 out:
1753 	return status;
1754 }
1755 
hdd_cfg80211_get_station_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1756 int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
1757 				     struct wireless_dev *wdev,
1758 				     const void *data,
1759 				     int data_len)
1760 {
1761 	struct osif_vdev_sync *vdev_sync;
1762 	int errno;
1763 
1764 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1765 	if (errno)
1766 		return errno;
1767 
1768 	errno = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
1769 
1770 	osif_vdev_sync_op_stop(vdev_sync);
1771 
1772 	return errno;
1773 }
1774 
1775 /**
1776  * hdd_get_peer_stats - get peer statistics information
1777  * @adapter: pointer to adapter
1778  * @stainfo: station information
1779  *
1780  * This function gets peer statistics information. If IPA is
1781  * enabled the Rx bcast/mcast count is updated in the
1782  * exception callback invoked by the IPA driver. In case of
1783  * back pressure the packets may get routed to the sw path and
1784  * where eventually the peer mcast/bcast pkt counts are updated in
1785  * dp rx process handling.
1786  *
1787  * Return : 0 on success and errno on failure
1788  */
hdd_get_peer_stats(struct hdd_adapter * adapter,struct hdd_station_info * stainfo)1789 static int hdd_get_peer_stats(struct hdd_adapter *adapter,
1790 			      struct hdd_station_info *stainfo)
1791 {
1792 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1793 	struct cdp_peer_stats *peer_stats;
1794 	struct cds_vdev_dp_stats dp_stats;
1795 	struct stats_event *stats;
1796 	QDF_STATUS status;
1797 	int i, ret = 0;
1798 
1799 	peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
1800 	if (!peer_stats)
1801 		return -ENOMEM;
1802 
1803 	status = cdp_host_get_peer_stats(soc, adapter->deflink->vdev_id,
1804 					 stainfo->sta_mac.bytes, peer_stats);
1805 	if (status != QDF_STATUS_SUCCESS) {
1806 		hdd_err("cdp_host_get_peer_stats failed");
1807 		qdf_mem_free(peer_stats);
1808 		return -EINVAL;
1809 	}
1810 
1811 	stainfo->rx_retry_cnt = peer_stats->rx.rx_retries;
1812 	if (!ucfg_ipa_is_enabled())
1813 		stainfo->rx_mc_bc_cnt = peer_stats->rx.multicast.num +
1814 					peer_stats->rx.bcast.num;
1815 	else
1816 		stainfo->rx_mc_bc_cnt += peer_stats->rx.multicast.num +
1817 					 peer_stats->rx.bcast.num;
1818 
1819 	qdf_mem_free(peer_stats);
1820 	peer_stats = NULL;
1821 
1822 	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(adapter->deflink->vdev,
1823 							 stainfo->sta_mac.bytes,
1824 							 &ret);
1825 	if (ret || !stats) {
1826 		wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
1827 		hdd_err("Failed to get peer stats info");
1828 		return -EINVAL;
1829 	}
1830 
1831 	if (cds_dp_get_vdev_stats(adapter->deflink->vdev_id, &dp_stats))
1832 		stainfo->tx_retry_succeed =
1833 					dp_stats.tx_mpdu_success_with_retries;
1834 	else
1835 		hdd_err("failed to get dp vdev stats");
1836 
1837 	/* This host counter is not supported
1838 	 * since currently tx retry is not done in host side
1839 	 */
1840 	stainfo->tx_retry_exhaust = 0;
1841 	stainfo->tx_total_fw = stats->peer_stats_info_ext->tx_packets;
1842 	stainfo->tx_retry_fw = stats->peer_stats_info_ext->tx_retries;
1843 	stainfo->tx_retry_exhaust_fw = stats->peer_stats_info_ext->tx_failed;
1844 
1845 	if (stats->peer_stats_info_ext->num_tx_rate_counts) {
1846 		stainfo->tx_pkt_per_mcs = qdf_mem_malloc(
1847 				stats->peer_stats_info_ext->num_tx_rate_counts *
1848 				sizeof(uint32_t));
1849 		if (stainfo->tx_pkt_per_mcs) {
1850 			stainfo->num_tx_rate_count =
1851 				stats->peer_stats_info_ext->num_tx_rate_counts;
1852 			qdf_mem_copy(
1853 				stainfo->tx_pkt_per_mcs,
1854 				stats->peer_stats_info_ext->tx_pkt_per_mcs,
1855 				stainfo->num_tx_rate_count * sizeof(uint32_t));
1856 		}
1857 	}
1858 	if (stats->peer_stats_info_ext->num_rx_rate_counts) {
1859 		stainfo->rx_pkt_per_mcs = qdf_mem_malloc(
1860 				stats->peer_stats_info_ext->num_rx_rate_counts *
1861 				sizeof(uint32_t));
1862 		if (stainfo->rx_pkt_per_mcs) {
1863 			stainfo->num_rx_rate_count =
1864 				stats->peer_stats_info_ext->num_rx_rate_counts;
1865 			qdf_mem_copy(
1866 				stainfo->rx_pkt_per_mcs,
1867 				stats->peer_stats_info_ext->rx_pkt_per_mcs,
1868 				stainfo->num_rx_rate_count * sizeof(uint32_t));
1869 		}
1870 	}
1871 
1872 	/* Optional, just print logs here */
1873 	if (!stats->num_peer_adv_stats) {
1874 		hdd_debug("Failed to get peer adv stats info");
1875 		stainfo->rx_fcs_count = 0;
1876 	}
1877 
1878 	for (i = 0; i < stats->num_peer_adv_stats; i++) {
1879 		if (!qdf_mem_cmp(stainfo->sta_mac.bytes,
1880 				 stats->peer_adv_stats[i].peer_macaddr,
1881 				 QDF_MAC_ADDR_SIZE)) {
1882 			stainfo->rx_fcs_count = stats->peer_adv_stats[i].
1883 								      fcs_count;
1884 			break;
1885 		}
1886 	}
1887 
1888 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
1889 
1890 	return ret;
1891 }
1892 
1893 /**
1894  * hdd_free_tx_rx_pkts_per_mcs - Free memory for tx packets per MCS and
1895  * rx packets per MCS
1896  * @stainfo: station information
1897  *
1898  * Return: None
1899  */
hdd_free_tx_rx_pkts_per_mcs(struct hdd_station_info * stainfo)1900 static void hdd_free_tx_rx_pkts_per_mcs(struct hdd_station_info *stainfo)
1901 {
1902 	if (stainfo->tx_pkt_per_mcs) {
1903 		qdf_mem_free(stainfo->tx_pkt_per_mcs);
1904 		stainfo->tx_pkt_per_mcs = NULL;
1905 	}
1906 	if (stainfo->rx_pkt_per_mcs) {
1907 		qdf_mem_free(stainfo->rx_pkt_per_mcs);
1908 		stainfo->rx_pkt_per_mcs = NULL;
1909 	}
1910 }
1911 
1912 /**
1913  * hdd_add_peer_stats_get_len - get data length used in
1914  * hdd_add_peer_stats()
1915  * @stainfo: station information
1916  *
1917  * This function calculates the data length used in
1918  * hdd_add_peer_stats()
1919  *
1920  * Return: total data length used in hdd_add_peer_stats()
1921  */
1922 static uint32_t
hdd_add_peer_stats_get_len(struct hdd_station_info * stainfo)1923 hdd_add_peer_stats_get_len(struct hdd_station_info *stainfo)
1924 {
1925 	uint32_t tx_count_size = 0;
1926 	uint32_t rx_count_size = 0;
1927 	uint16_t i;
1928 
1929 	for (i = 0; i < stainfo->num_tx_rate_count; i++)
1930 		tx_count_size += nla_attr_size(sizeof(uint32_t));
1931 	for (i = 0; i < stainfo->num_rx_rate_count; i++)
1932 		rx_count_size += nla_attr_size(sizeof(uint32_t));
1933 
1934 	return (nla_attr_size(sizeof(stainfo->rx_retry_cnt)) +
1935 		nla_attr_size(sizeof(stainfo->rx_mc_bc_cnt)) +
1936 		nla_attr_size(sizeof(stainfo->tx_retry_succeed)) +
1937 		nla_attr_size(sizeof(stainfo->tx_retry_exhaust)) +
1938 		nla_attr_size(sizeof(stainfo->tx_total_fw)) +
1939 		nla_attr_size(sizeof(stainfo->tx_retry_fw)) +
1940 		nla_attr_size(sizeof(stainfo->tx_retry_exhaust_fw)) +
1941 		nla_attr_size(sizeof(stainfo->rx_fcs_count)) +
1942 		tx_count_size + rx_count_size);
1943 }
1944 
1945 /**
1946  * hdd_get_pmf_bcn_protect_stats_len() - get pmf bcn protect counters len
1947  * @link_info: pointer to link_info struct in adapter
1948  *
1949  * This function calculates the data length for valid pmf bcn counters.
1950  *
1951  * Return: total data length used in hdd_add_peer_stats()
1952  */
1953 static uint32_t
hdd_get_pmf_bcn_protect_stats_len(struct wlan_hdd_link_info * link_info)1954 hdd_get_pmf_bcn_protect_stats_len(struct wlan_hdd_link_info *link_info)
1955 {
1956 	if (!link_info->hdd_stats.bcn_protect_stats.pmf_bcn_stats_valid)
1957 		return 0;
1958 
1959 	/* 4 pmf becon protect counters each of 32 bit */
1960 	return nla_total_size(sizeof(uint32_t)) * 4;
1961 }
1962 
1963 static uint32_t
hdd_get_connect_fail_reason_code_len(struct hdd_adapter * adapter)1964 hdd_get_connect_fail_reason_code_len(struct hdd_adapter *adapter)
1965 {
1966 	if (adapter->connect_req_status == STATUS_SUCCESS)
1967 		return 0;
1968 
1969 	return nla_total_size(sizeof(uint32_t));
1970 }
1971 
1972 /**
1973  * hdd_add_pmf_bcn_protect_stats() - add pmf bcn protect counters in resp
1974  * @skb: pointer to response skb buffer
1975  * @link_info: Pointer to link_info holding valid bcn protect counters
1976  *
1977  * This function adds the pmf bcn stats in response.
1978  *
1979  * Return: 0 on success
1980  */
1981 static int
hdd_add_pmf_bcn_protect_stats(struct sk_buff * skb,struct wlan_hdd_link_info * link_info)1982 hdd_add_pmf_bcn_protect_stats(struct sk_buff *skb,
1983 			      struct wlan_hdd_link_info *link_info)
1984 {
1985 	struct hdd_stats *hdd_stats = &link_info->hdd_stats;
1986 
1987 	if (!hdd_stats->bcn_protect_stats.pmf_bcn_stats_valid)
1988 		return 0;
1989 
1990 	hdd_stats->bcn_protect_stats.pmf_bcn_stats_valid = 0;
1991 	if (nla_put_u32(skb, STA_INFO_BIP_MIC_ERROR_COUNT,
1992 			hdd_stats->bcn_protect_stats.igtk_mic_fail_cnt) ||
1993 	    nla_put_u32(skb, STA_INFO_BIP_REPLAY_COUNT,
1994 			hdd_stats->bcn_protect_stats.igtk_replay_cnt) ||
1995 	    nla_put_u32(skb, STA_INFO_BEACON_MIC_ERROR_COUNT,
1996 			hdd_stats->bcn_protect_stats.bcn_mic_fail_cnt) ||
1997 	    nla_put_u32(skb, STA_INFO_BEACON_REPLAY_COUNT,
1998 			hdd_stats->bcn_protect_stats.bcn_replay_cnt)) {
1999 		hdd_err("put fail");
2000 		return -EINVAL;
2001 	}
2002 
2003 	return 0;
2004 }
2005 
2006 #ifdef WLAN_FEATURE_BIG_DATA_STATS
2007 /**
2008  * hdd_get_big_data_stats_len - get data length used in
2009  * hdd_big_data_pack_resp_nlmsg()
2010  * @link_info: Link info pointer in HDD adapter.
2011  *
2012  * This function calculates the data length used in
2013  * hdd_big_data_pack_resp_nlmsg()
2014  *
2015  * Return: total data length used in hdd_big_data_pack_resp_nlmsg()
2016  */
2017 static uint32_t
hdd_get_big_data_stats_len(struct wlan_hdd_link_info * link_info)2018 hdd_get_big_data_stats_len(struct wlan_hdd_link_info *link_info)
2019 {
2020 	uint32_t len;
2021 	struct big_data_stats_event *big_data_stats =
2022 					&link_info->big_data_stats;
2023 
2024 	len = nla_total_size(sizeof(big_data_stats->last_tx_data_rate_kbps)) +
2025 	      nla_total_size(sizeof(big_data_stats->target_power_ofdm)) +
2026 	      nla_total_size(sizeof(big_data_stats->target_power_dsss)) +
2027 	      nla_total_size(sizeof(big_data_stats->last_tx_data_rix)) +
2028 	      nla_total_size(sizeof(big_data_stats->tsf_out_of_sync)) +
2029 	      nla_total_size(sizeof(big_data_stats->ani_level)) +
2030 	      nla_total_size(sizeof(big_data_stats->last_data_tx_pwr));
2031 
2032 	/** Add len of roam params **/
2033 	len += nla_total_size(sizeof(uint32_t)) * 3;
2034 
2035 	return len;
2036 }
2037 
2038 /**
2039  * hdd_big_data_pack_resp_nlmsg() - pack big data nl resp msg
2040  * @skb: pointer to response skb buffer
2041  * @link_info: Link info pointer in HDD adapter
2042  *
2043  * This function adds big data stats in response.
2044  *
2045  * Return: 0 on success
2046  */
hdd_big_data_pack_resp_nlmsg(struct sk_buff * skb,struct wlan_hdd_link_info * link_info)2047 static int hdd_big_data_pack_resp_nlmsg(struct sk_buff *skb,
2048 					struct wlan_hdd_link_info *link_info)
2049 {
2050 	struct hdd_station_ctx *hdd_sta_ctx;
2051 	struct hdd_context *hdd_ctx = link_info->adapter->hdd_ctx;
2052 	struct big_data_stats_event *big_data_stats =
2053 					&link_info->big_data_stats;
2054 
2055 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
2056 	if (!hdd_sta_ctx) {
2057 		hdd_err("Invalid station context");
2058 		return -EINVAL;
2059 	}
2060 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE,
2061 			big_data_stats->last_tx_data_rate_kbps)){
2062 		hdd_err("latest tx rate put fail");
2063 		return -EINVAL;
2064 	}
2065 
2066 	if (WLAN_REG_IS_5GHZ_CH_FREQ(hdd_sta_ctx->cache_conn_info.chan_freq)) {
2067 		if (nla_put_u32(
2068 			skb,
2069 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS,
2070 			big_data_stats->target_power_ofdm)){
2071 			hdd_err("5G ofdm power put fail");
2072 			return -EINVAL;
2073 		}
2074 	} else if (WLAN_REG_IS_24GHZ_CH_FREQ(
2075 				hdd_sta_ctx->cache_conn_info.chan_freq)){
2076 		if (nla_put_u32(
2077 		       skb,
2078 		       QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS,
2079 		       big_data_stats->target_power_ofdm)){
2080 			hdd_err("2.4G ofdm power put fail");
2081 			return -EINVAL;
2082 		}
2083 		if (nla_put_u32(
2084 		       skb,
2085 		       QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS,
2086 		       big_data_stats->target_power_dsss)){
2087 			hdd_err("target power dsss put fail");
2088 			return -EINVAL;
2089 		}
2090 	}
2091 
2092 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX,
2093 			big_data_stats->last_tx_data_rix)){
2094 		hdd_err("last rix rate put fail");
2095 		return -EINVAL;
2096 	}
2097 	if (nla_put_u32(skb,
2098 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT,
2099 			big_data_stats->tsf_out_of_sync)){
2100 		hdd_err("tsf out of sync put fail");
2101 		return -EINVAL;
2102 	}
2103 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL,
2104 			big_data_stats->ani_level)){
2105 		hdd_err("ani level put fail");
2106 		return -EINVAL;
2107 	}
2108 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER,
2109 			big_data_stats->last_data_tx_pwr)){
2110 		hdd_err("last data tx power put fail");
2111 		return -EINVAL;
2112 	}
2113 	if (nla_put_u32(skb,
2114 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON,
2115 			wlan_cm_get_roam_states(hdd_ctx->psoc,
2116 						link_info->vdev_id,
2117 						ROAM_TRIGGER_REASON))){
2118 		hdd_err("roam trigger reason put fail");
2119 		return -EINVAL;
2120 	}
2121 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON,
2122 			wlan_cm_get_roam_states(hdd_ctx->psoc,
2123 						link_info->vdev_id,
2124 						ROAM_FAIL_REASON))){
2125 		hdd_err("roam fail reason put fail");
2126 		return -EINVAL;
2127 	}
2128 	if (nla_put_u32(
2129 		      skb,
2130 		      QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON,
2131 		      wlan_cm_get_roam_states(hdd_ctx->psoc,
2132 					      link_info->vdev_id,
2133 					      ROAM_INVOKE_FAIL_REASON))){
2134 		hdd_err("roam invoke fail reason put fail");
2135 		return -EINVAL;
2136 	}
2137 
2138 	return 0;
2139 }
2140 
2141 /**
2142  * hdd_reset_roam_params() - reset roam params
2143  * @psoc: psoc
2144  * @vdev_id: vdev id
2145  *
2146  * This function resets big data roam params
2147  *
2148  * Return: None
2149  */
2150 static void
hdd_reset_roam_params(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)2151 hdd_reset_roam_params(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
2152 {
2153 	wlan_cm_update_roam_states(psoc, vdev_id,
2154 				   0, ROAM_TRIGGER_REASON);
2155 	wlan_cm_update_roam_states(psoc, vdev_id,
2156 				   0, ROAM_FAIL_REASON);
2157 	wlan_cm_update_roam_states(psoc, vdev_id,
2158 				   0, ROAM_INVOKE_FAIL_REASON);
2159 }
2160 #else
2161 static inline int
hdd_big_data_pack_resp_nlmsg(struct sk_buff * skb,struct wlan_hdd_link_info * link_info)2162 hdd_big_data_pack_resp_nlmsg(struct sk_buff *skb,
2163 			     struct wlan_hdd_link_info *link_info)
2164 {
2165 	return 0;
2166 }
2167 
2168 static uint32_t
hdd_get_big_data_stats_len(struct wlan_hdd_link_info * link_info)2169 hdd_get_big_data_stats_len(struct wlan_hdd_link_info *link_info)
2170 {
2171 	return 0;
2172 }
2173 
2174 static void
hdd_reset_roam_params(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)2175 hdd_reset_roam_params(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
2176 {}
2177 #endif
2178 
2179 /**
2180  * hdd_add_connect_fail_reason_code() - Fills connect fail reason code
2181  * @skb: pointer to skb
2182  * @adapter: pointer to hdd adapter
2183  *
2184  * Return: on success 0 else error code
2185  */
hdd_add_connect_fail_reason_code(struct sk_buff * skb,struct hdd_adapter * adapter)2186 static int hdd_add_connect_fail_reason_code(struct sk_buff *skb,
2187 					    struct hdd_adapter *adapter)
2188 {
2189 	uint32_t reason;
2190 
2191 	reason = osif_cm_mac_to_qca_connect_fail_reason(
2192 					adapter->connect_req_status);
2193 	if (!reason)
2194 		return 0;
2195 
2196 	if (nla_put_u32(skb, STA_INFO_CONNECT_FAIL_REASON_CODE, reason)) {
2197 		hdd_err("put fail");
2198 		return -EINVAL;
2199 	}
2200 
2201 	return 0;
2202 }
2203 
2204 /**
2205  * hdd_add_peer_stats - add peer statistics information
2206  * @skb: pointer to response skb buffer
2207  * @stainfo: station information
2208  *
2209  * This function adds peer statistics information to response skb buffer
2210  *
2211  * Return : 0 on success and errno on failure
2212  */
hdd_add_peer_stats(struct sk_buff * skb,struct hdd_station_info * stainfo)2213 static int hdd_add_peer_stats(struct sk_buff *skb,
2214 			      struct hdd_station_info *stainfo)
2215 {
2216 	struct nlattr *nla_attr;
2217 	uint8_t i;
2218 
2219 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT,
2220 			stainfo->rx_retry_cnt)) {
2221 		hdd_err("Failed to put rx_retry_cnt");
2222 		goto fail;
2223 	}
2224 
2225 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT,
2226 			stainfo->rx_mc_bc_cnt)) {
2227 		hdd_err("Failed to put rx_mc_bc_cnt");
2228 		goto fail;
2229 	}
2230 
2231 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED,
2232 			stainfo->tx_retry_succeed)) {
2233 		hdd_err("Failed to put tx_retry_succeed");
2234 		goto fail;
2235 	}
2236 
2237 	if (nla_put_u32(skb,
2238 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED,
2239 			stainfo->tx_retry_exhaust)) {
2240 		hdd_err("Failed to put tx_retry_exhaust");
2241 		goto fail;
2242 	}
2243 
2244 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL,
2245 			stainfo->tx_total_fw)) {
2246 		hdd_err("Failed to put tx_total_fw");
2247 		goto fail;
2248 	}
2249 
2250 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY,
2251 			stainfo->tx_retry_fw)) {
2252 		hdd_err("Failed to put tx_retry_fw");
2253 		goto fail;
2254 	}
2255 
2256 	if (nla_put_u32(skb,
2257 		    QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED,
2258 		    stainfo->tx_retry_exhaust_fw)) {
2259 		hdd_err("Failed to put tx_retry_exhaust_fw");
2260 		goto fail;
2261 	}
2262 
2263 	if (nla_put_u32(skb,
2264 		     QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_CRC_FAIL_COUNT,
2265 		     stainfo->rx_fcs_count)) {
2266 		hdd_err("Failed to put rx_fcs_count");
2267 		goto fail;
2268 	}
2269 
2270 	nla_attr = nla_nest_start(skb,
2271 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_TX_PACKETS);
2272 	if (!nla_attr) {
2273 		hdd_err("nla nest start for tx packets fail");
2274 		goto fail;
2275 	}
2276 
2277 	for (i = 0; i < stainfo->num_tx_rate_count; i++)
2278 		if (nla_put_u32(skb,
2279 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_TX_PACKETS,
2280 			stainfo->tx_pkt_per_mcs[i])) {
2281 			hdd_err("Failed to put tx_rate_count for MCS[%d]", i);
2282 			goto fail;
2283 		}
2284 	nla_nest_end(skb, nla_attr);
2285 
2286 	nla_attr = nla_nest_start(skb,
2287 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_RX_PACKETS);
2288 	if (!nla_attr) {
2289 		hdd_err("nla nest start for rx packets fail");
2290 		goto fail;
2291 	}
2292 
2293 	for (i = 0; i < stainfo->num_rx_rate_count; i++)
2294 		if (nla_put_u32(skb,
2295 			QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PER_MCS_TX_PACKETS,
2296 			stainfo->rx_pkt_per_mcs[i])) {
2297 			hdd_err("Failed to put rx_rate_count for MCS[%d]", i);
2298 			goto fail;
2299 		}
2300 	nla_nest_end(skb, nla_attr);
2301 
2302 	hdd_free_tx_rx_pkts_per_mcs(stainfo);
2303 	return 0;
2304 fail:
2305 	hdd_free_tx_rx_pkts_per_mcs(stainfo);
2306 	return -EINVAL;
2307 }
2308 
2309 /**
2310  * hdd_get_connected_station_info_ex() - get connected peer's info
2311  * @hdd_ctx: hdd context
2312  * @adapter: hostapd interface
2313  * @stainfo: pointer to hdd_station_info
2314  *
2315  * This function collect and indicate the connected peer's info
2316  *
2317  * Return: 0 on success, otherwise error value
2318  */
hdd_get_connected_station_info_ex(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,struct hdd_station_info * stainfo)2319 static int hdd_get_connected_station_info_ex(struct hdd_context *hdd_ctx,
2320 					     struct hdd_adapter *adapter,
2321 					     struct hdd_station_info *stainfo)
2322 {
2323 	struct sk_buff *skb = NULL;
2324 	uint32_t nl_buf_len, guard_interval;
2325 	bool sap_get_peer_info;
2326 	struct nl80211_sta_flag_update sta_flags = {0};
2327 	const uint8_t *mac_addr;
2328 	QDF_STATUS status;
2329 
2330 	if (hdd_get_peer_stats(adapter, stainfo)) {
2331 		hdd_err_rl("hdd_get_peer_stats fail");
2332 		return -EINVAL;
2333 	}
2334 
2335 	nl_buf_len = NLMSG_HDRLEN;
2336 	nl_buf_len += nla_attr_size(QDF_MAC_ADDR_SIZE);
2337 	status = ucfg_mlme_get_sap_get_peer_info(hdd_ctx->psoc,
2338 						 &sap_get_peer_info);
2339 	if (status != QDF_STATUS_SUCCESS)
2340 		hdd_err_rl("Unable to fetch sap ger peer info");
2341 
2342 	if (sap_get_peer_info)
2343 		nl_buf_len += hdd_add_peer_stats_get_len(stainfo);
2344 
2345 	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
2346 		nl_buf_len += nla_attr_size(sizeof(sta_flags)) +
2347 			      nla_attr_size(sizeof(guard_interval));
2348 
2349 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
2350 						       nl_buf_len);
2351 	if (!skb) {
2352 		hdd_err_rl("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
2353 		return -ENOMEM;
2354 	}
2355 
2356 	if (qdf_is_macaddr_zero(&stainfo->mld_addr))
2357 		mac_addr = &stainfo->sta_mac.bytes[0];
2358 	else
2359 		mac_addr = &stainfo->mld_addr.bytes[0];
2360 
2361 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC,
2362 		    QDF_MAC_ADDR_SIZE, mac_addr)) {
2363 		hdd_err_rl("Failed to put MAC address");
2364 		goto fail;
2365 	}
2366 
2367 	if (sap_get_peer_info && hdd_add_peer_stats(skb, stainfo)) {
2368 		hdd_err_rl("hdd_add_peer_stats fail");
2369 		goto fail;
2370 	}
2371 
2372 	if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
2373 		sta_flags.mask = QCA_VENDOR_WLAN_STA_FLAG_AMPDU |
2374 				 QCA_VENDOR_WLAN_STA_FLAG_TX_STBC |
2375 				 QCA_VENDOR_WLAN_STA_FLAG_RX_STBC;
2376 
2377 		if (stainfo->ampdu)
2378 			sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_AMPDU;
2379 		if (stainfo->tx_stbc)
2380 			sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_TX_STBC;
2381 		if (stainfo->rx_stbc)
2382 			sta_flags.set |= QCA_VENDOR_WLAN_STA_FLAG_RX_STBC;
2383 
2384 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS,
2385 			    sizeof(sta_flags), &sta_flags)) {
2386 			hdd_err_rl("Failed to put STA flags");
2387 			goto fail;
2388 		}
2389 
2390 		switch (stainfo->guard_interval) {
2391 		case TXRATE_GI_0_8_US:
2392 			guard_interval = QCA_VENDOR_WLAN_STA_GI_800_NS;
2393 			break;
2394 		case TXRATE_GI_0_4_US:
2395 			guard_interval = QCA_VENDOR_WLAN_STA_GI_400_NS;
2396 			break;
2397 		case TXRATE_GI_1_6_US:
2398 			guard_interval = QCA_VENDOR_WLAN_STA_GI_1600_NS;
2399 			break;
2400 		case TXRATE_GI_3_2_US:
2401 			guard_interval = QCA_VENDOR_WLAN_STA_GI_3200_NS;
2402 			break;
2403 		default:
2404 			hdd_err_rl("Invalid guard_interval %d",
2405 				   stainfo->guard_interval);
2406 			goto fail;
2407 		}
2408 
2409 		if (nla_put_u32(skb,
2410 			       QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL,
2411 			       guard_interval)) {
2412 			hdd_err_rl("Failed to put guard_interval");
2413 			goto fail;
2414 		}
2415 	}
2416 
2417 	return wlan_cfg80211_vendor_cmd_reply(skb);
2418 
2419 fail:
2420 	wlan_cfg80211_vendor_free_skb(skb);
2421 	return -EINVAL;
2422 }
2423 
2424 /**
2425  * hdd_get_station_remote_ex() - get remote peer's info, for SAP/GO mode only
2426  * @hdd_ctx: hdd context
2427  * @adapter: hostapd interface
2428  * @mac_addr: mac address of requested peer
2429  *
2430  * This function collect and indicate the remote peer's info
2431  *
2432  * Return: 0 on success, otherwise error value
2433  */
hdd_get_station_remote_ex(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,struct qdf_mac_addr mac_addr)2434 static int hdd_get_station_remote_ex(struct hdd_context *hdd_ctx,
2435 				     struct hdd_adapter *adapter,
2436 				     struct qdf_mac_addr mac_addr)
2437 {
2438 	struct hdd_station_info *stainfo =
2439 				hdd_get_sta_info_by_mac(&adapter->sta_info_list,
2440 					       mac_addr.bytes,
2441 					       STA_INFO_HDD_GET_STATION_REMOTE);
2442 	int status;
2443 
2444 	/* For now, only connected STAs are supported */
2445 	if (!stainfo) {
2446 		hdd_err_rl("Failed to get peer STA " QDF_MAC_ADDR_FMT,
2447 			   QDF_MAC_ADDR_REF(mac_addr.bytes));
2448 		return -ENXIO;
2449 	}
2450 
2451 	status = hdd_get_connected_station_info_ex(hdd_ctx, adapter, stainfo);
2452 	hdd_put_sta_info_ref(&adapter->sta_info_list, &stainfo, true,
2453 			     STA_INFO_HDD_GET_STATION_REMOTE);
2454 
2455 	return status;
2456 }
2457 
2458 /**
2459  * hdd_get_station_info_ex() - send STA info to userspace, for STA mode only
2460  * @link_info: Pointer of link info in HDD adapter.
2461  *
2462  * Return: 0 if success else error status
2463  */
hdd_get_station_info_ex(struct wlan_hdd_link_info * link_info)2464 static int hdd_get_station_info_ex(struct wlan_hdd_link_info *link_info)
2465 {
2466 	struct hdd_adapter *adapter = link_info->adapter;
2467 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
2468 	struct sk_buff *skb;
2469 	uint32_t nl_buf_len = 0, connect_fail_rsn_len;
2470 	struct hdd_station_ctx *hdd_sta_ctx;
2471 	bool big_data_stats_req = false;
2472 	bool big_data_fw_support = false;
2473 	int ret;
2474 
2475 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
2476 	ucfg_mc_cp_get_big_data_fw_support(hdd_ctx->psoc, &big_data_fw_support);
2477 
2478 	if (hdd_cm_is_disconnected(link_info) && big_data_fw_support)
2479 		big_data_stats_req = true;
2480 
2481 	if (wlan_hdd_get_station_stats(link_info))
2482 		hdd_err_rl("wlan_hdd_get_station_stats fail");
2483 
2484 	wlan_hdd_get_peer_rx_rate_stats(link_info);
2485 
2486 	if (big_data_stats_req) {
2487 		if (wlan_hdd_get_big_data_station_stats(link_info)) {
2488 			hdd_err_rl("wlan_hdd_get_big_data_station_stats fail");
2489 			return -EINVAL;
2490 		}
2491 		nl_buf_len = hdd_get_big_data_stats_len(link_info);
2492 	}
2493 
2494 	nl_buf_len += hdd_get_pmf_bcn_protect_stats_len(link_info);
2495 	connect_fail_rsn_len = hdd_get_connect_fail_reason_code_len(adapter);
2496 	nl_buf_len += connect_fail_rsn_len;
2497 	nl_buf_len += hdd_get_uplink_delay_len(adapter);
2498 	if (!nl_buf_len) {
2499 		hdd_err_rl("Failed to get bcn pmf stats");
2500 		return -EINVAL;
2501 	}
2502 
2503 	nl_buf_len += NLMSG_HDRLEN;
2504 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
2505 						       nl_buf_len);
2506 	if (!skb) {
2507 		hdd_err_rl("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
2508 		return -ENOMEM;
2509 	}
2510 
2511 	if (hdd_add_pmf_bcn_protect_stats(skb, link_info)) {
2512 		hdd_err_rl("hdd_add_pmf_bcn_protect_stats fail");
2513 		wlan_cfg80211_vendor_free_skb(skb);
2514 		return -EINVAL;
2515 	}
2516 
2517 	if (connect_fail_rsn_len) {
2518 		if (hdd_add_connect_fail_reason_code(skb, adapter)) {
2519 			hdd_err_rl("hdd_add_connect_fail_reason_code fail");
2520 			wlan_cfg80211_vendor_free_skb(skb);
2521 			return -ENOMEM;
2522 		}
2523 	}
2524 
2525 	if (big_data_stats_req) {
2526 		if (hdd_big_data_pack_resp_nlmsg(skb, link_info)) {
2527 			wlan_cfg80211_vendor_free_skb(skb);
2528 			return -EINVAL;
2529 		}
2530 	}
2531 
2532 	if (QDF_IS_STATUS_ERROR(hdd_add_uplink_delay(adapter, skb))) {
2533 		hdd_err_rl("hdd_add_uplink_delay fail");
2534 		wlan_cfg80211_vendor_free_skb(skb);
2535 		return -EINVAL;
2536 	}
2537 
2538 	ret = wlan_cfg80211_vendor_cmd_reply(skb);
2539 	hdd_reset_roam_params(hdd_ctx->psoc, link_info->vdev_id);
2540 	return ret;
2541 }
2542 
2543 /**
2544  * __hdd_cfg80211_get_sta_info_cmd() - Handle get sta info vendor cmd
2545  * @wiphy: pointer to wireless phy
2546  * @wdev: wireless device
2547  * @data: data
2548  * @data_len: data length
2549  *
2550  * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO.
2551  * Validate cmd attributes and send the station info to upper layers.
2552  *
2553  * Return: Success(0) or reason code for failure
2554  */
2555 static int
__hdd_cfg80211_get_sta_info_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)2556 __hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
2557 				struct wireless_dev *wdev,
2558 				const void *data,
2559 				int data_len)
2560 {
2561 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2562 	struct net_device *dev = wdev->netdev;
2563 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2564 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
2565 	struct qdf_mac_addr mac_addr;
2566 	int32_t status;
2567 
2568 	hdd_enter_dev(dev);
2569 
2570 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE ||
2571 	    hdd_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
2572 		hdd_err_rl("Command not allowed in FTM / Monitor mode");
2573 		status = -EPERM;
2574 		goto out;
2575 	}
2576 
2577 	status = wlan_hdd_validate_context(hdd_ctx);
2578 	if (status != 0)
2579 		goto out;
2580 
2581 	status = wlan_cfg80211_nla_parse(tb,
2582 					 QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX,
2583 					 data, data_len,
2584 					 hdd_get_sta_policy);
2585 	if (status) {
2586 		hdd_err_rl("Invalid ATTR");
2587 		goto out;
2588 	}
2589 
2590 	switch (adapter->device_mode) {
2591 	case QDF_STA_MODE:
2592 	case QDF_P2P_CLIENT_MODE:
2593 		status = hdd_get_station_info_ex(adapter->deflink);
2594 		break;
2595 	case QDF_SAP_MODE:
2596 	case QDF_P2P_GO_MODE:
2597 		if (!tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC]) {
2598 			hdd_err_rl("MAC address is not present");
2599 			status = -EINVAL;
2600 			goto out;
2601 		}
2602 
2603 		nla_memcpy(mac_addr.bytes,
2604 			   tb[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC],
2605 			   QDF_MAC_ADDR_SIZE);
2606 		hdd_debug("STA " QDF_MAC_ADDR_FMT,
2607 			  QDF_MAC_ADDR_REF(mac_addr.bytes));
2608 		status = hdd_get_station_remote_ex(hdd_ctx, adapter, mac_addr);
2609 		break;
2610 	default:
2611 		hdd_err_rl("Invalid device_mode: %d", adapter->device_mode);
2612 		status = -EINVAL;
2613 		goto out;
2614 	}
2615 
2616 	hdd_exit();
2617 out:
2618 	return status;
2619 }
2620 
hdd_cfg80211_get_sta_info_cmd(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)2621 int32_t hdd_cfg80211_get_sta_info_cmd(struct wiphy *wiphy,
2622 				      struct wireless_dev *wdev,
2623 				      const void *data,
2624 				      int data_len)
2625 {
2626 	struct osif_vdev_sync *vdev_sync;
2627 	int errno;
2628 
2629 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
2630 	if (errno)
2631 		return errno;
2632 
2633 	errno = wlan_hdd_qmi_get_sync_resume();
2634 	if (errno) {
2635 		hdd_err("qmi sync resume failed: %d", errno);
2636 		goto end;
2637 	}
2638 
2639 	errno = __hdd_cfg80211_get_sta_info_cmd(wiphy, wdev, data, data_len);
2640 
2641 	wlan_hdd_qmi_put_suspend();
2642 
2643 end:
2644 	osif_vdev_sync_op_stop(vdev_sync);
2645 
2646 	return errno;
2647 }
2648 
2649