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