blob: 35af7f3e2d00a7754339b2980cdaadcfa36c347e [file] [log] [blame]
Qiwei Caie689a262018-07-26 15:50:22 +08001/*
2 * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_hdd_station_info.c
21 *
22 * WLAN station info functions
23 *
24 */
25
26#include <wlan_hdd_includes.h>
27#include <linux/netdevice.h>
28#include <linux/skbuff.h>
29#include <linux/etherdevice.h>
30#include <linux/if_ether.h>
31#include <wlan_cp_stats_mc_ucfg_api.h>
32#include <wlan_hdd_stats.h>
33#include <wlan_hdd_hostapd.h>
34#include <wlan_hdd_station_info.h>
35
36/*
37 * define short names for the global vendor params
38 * used by __wlan_hdd_cfg80211_get_station_cmd()
39 */
40#define STATION_INVALID \
41 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
42#define STATION_INFO \
43 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
44#define STATION_ASSOC_FAIL_REASON \
45 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
46#define STATION_REMOTE \
47 QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
48#define STATION_MAX \
49 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
50
51/* define short names for get station info attributes */
52#define LINK_INFO_STANDARD_NL80211_ATTR \
53 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
54#define AP_INFO_STANDARD_NL80211_ATTR \
55 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
56#define INFO_ROAM_COUNT \
57 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
58#define INFO_AKM \
59 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
60#define WLAN802_11_MODE \
61 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
62#define AP_INFO_HS20_INDICATION \
63 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
64#define HT_OPERATION \
65 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
66#define VHT_OPERATION \
67 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
68#define INFO_ASSOC_FAIL_REASON \
69 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
70#define REMOTE_MAX_PHY_RATE \
71 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
72#define REMOTE_TX_PACKETS \
73 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
74#define REMOTE_TX_BYTES \
75 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
76#define REMOTE_RX_PACKETS \
77 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
78#define REMOTE_RX_BYTES \
79 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
80#define REMOTE_LAST_TX_RATE \
81 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
82#define REMOTE_LAST_RX_RATE \
83 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
84#define REMOTE_WMM \
85 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
86#define REMOTE_SUPPORTED_MODE \
87 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
88#define REMOTE_AMPDU \
89 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
90#define REMOTE_TX_STBC \
91 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
92#define REMOTE_RX_STBC \
93 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
94#define REMOTE_CH_WIDTH\
95 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
96#define REMOTE_SGI_ENABLE\
97 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
98#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
99 #define REMOTE_PAD\
100 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
101#endif
102
103static const struct nla_policy
104hdd_get_station_policy[STATION_MAX + 1] = {
105 [STATION_INFO] = {.type = NLA_FLAG},
106 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
107 [STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
108};
109
110#ifdef QCA_SUPPORT_CP_STATS
111static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
112 uint32_t *congestion)
113{
114 QDF_STATUS status;
115 struct cca_stats cca_stats;
116
117 status = ucfg_mc_cp_stats_cca_stats_get(adapter->hdd_vdev, &cca_stats);
118 if (QDF_IS_STATUS_ERROR(status))
119 return -EINVAL;
120
121 *congestion = cca_stats.congestion;
122 return 0;
123}
124#else
125static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
126 uint32_t *congestion)
127{
128 struct hdd_station_ctx *hdd_sta_ctx;
129
130 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
131 *congestion = hdd_sta_ctx->conn_info.cca;
132 return 0;
133}
134#endif
135
136/**
137 * hdd_get_station_assoc_fail() - Handle get station assoc fail
138 * @hdd_ctx: HDD context within host driver
139 * @wdev: wireless device
140 *
141 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
142 * Validate cmd attributes and send the station info to upper layers.
143 *
144 * Return: Success(0) or reason code for failure
145 */
146static int hdd_get_station_assoc_fail(struct hdd_context *hdd_ctx,
147 struct hdd_adapter *adapter)
148{
149 struct sk_buff *skb = NULL;
150 uint32_t nl_buf_len;
151 struct hdd_station_ctx *hdd_sta_ctx;
152 uint32_t congestion;
153
154 nl_buf_len = NLMSG_HDRLEN;
155 nl_buf_len += sizeof(uint32_t);
156 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
157
158 if (!skb) {
159 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
160 return -ENOMEM;
161 }
162
163 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
164
165 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
166 hdd_sta_ctx->conn_info.assoc_status_code)) {
167 hdd_err("put fail");
168 goto fail;
169 }
170
171 if (hdd_get_sta_congestion(adapter, &congestion))
172 congestion = 0;
173
174 hdd_info("congestion:%d", congestion);
175 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
176 congestion)) {
177 hdd_err("put fail");
178 goto fail;
179 }
180
181 return cfg80211_vendor_cmd_reply(skb);
182fail:
183 if (skb)
184 kfree_skb(skb);
185 return -EINVAL;
186}
187
188/**
189 * hdd_map_auth_type() - transform auth type specific to
190 * vendor command
191 * @auth_type: csr auth type
192 *
193 * Return: Success(0) or reason code for failure
194 */
195static int hdd_convert_auth_type(uint32_t auth_type)
196{
197 uint32_t ret_val;
198
199 switch (auth_type) {
200 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
201 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
202 break;
203 case eCSR_AUTH_TYPE_SHARED_KEY:
204 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
205 break;
206 case eCSR_AUTH_TYPE_WPA:
207 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
208 break;
209 case eCSR_AUTH_TYPE_WPA_PSK:
210 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
211 break;
212 case eCSR_AUTH_TYPE_AUTOSWITCH:
213 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
214 break;
215 case eCSR_AUTH_TYPE_WPA_NONE:
216 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
217 break;
218 case eCSR_AUTH_TYPE_RSN:
219 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
220 break;
221 case eCSR_AUTH_TYPE_RSN_PSK:
222 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
223 break;
224 case eCSR_AUTH_TYPE_FT_RSN:
225 ret_val = QCA_WLAN_AUTH_TYPE_FT;
226 break;
227 case eCSR_AUTH_TYPE_FT_RSN_PSK:
228 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
229 break;
230 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
231 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
232 break;
233 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
234 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
235 break;
236 case eCSR_AUTH_TYPE_CCKM_WPA:
237 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
238 break;
239 case eCSR_AUTH_TYPE_CCKM_RSN:
240 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
241 break;
242 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
243 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
244 break;
245 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
246 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
247 break;
248 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
249 case eCSR_AUTH_TYPE_FAILED:
250 case eCSR_AUTH_TYPE_NONE:
251 default:
252 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
253 break;
254 }
255 return ret_val;
256}
257
258/**
259 * hdd_map_dot_11_mode() - transform dot11mode type specific to
260 * vendor command
261 * @dot11mode: dot11mode
262 *
263 * Return: Success(0) or reason code for failure
264 */
265static int hdd_convert_dot11mode(uint32_t dot11mode)
266{
267 uint32_t ret_val;
268
269 switch (dot11mode) {
270 case eCSR_CFG_DOT11_MODE_11A:
271 ret_val = QCA_WLAN_802_11_MODE_11A;
272 break;
273 case eCSR_CFG_DOT11_MODE_11B:
274 ret_val = QCA_WLAN_802_11_MODE_11B;
275 break;
276 case eCSR_CFG_DOT11_MODE_11G:
277 ret_val = QCA_WLAN_802_11_MODE_11G;
278 break;
279 case eCSR_CFG_DOT11_MODE_11N:
280 ret_val = QCA_WLAN_802_11_MODE_11N;
281 break;
282 case eCSR_CFG_DOT11_MODE_11AC:
283 ret_val = QCA_WLAN_802_11_MODE_11AC;
284 break;
285 case eCSR_CFG_DOT11_MODE_AUTO:
286 case eCSR_CFG_DOT11_MODE_ABG:
287 default:
288 ret_val = QCA_WLAN_802_11_MODE_INVALID;
289 }
290 return ret_val;
291}
292
293/**
294 * hdd_add_tx_bitrate() - add tx bitrate attribute
295 * @skb: pointer to sk buff
296 * @hdd_sta_ctx: pointer to hdd station context
297 * @idx: attribute index
298 *
299 * Return: Success(0) or reason code for failure
300 */
301static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
302 struct hdd_station_ctx *hdd_sta_ctx,
303 int idx)
304{
305 struct nlattr *nla_attr;
306 uint32_t bitrate, bitrate_compat;
307
308 nla_attr = nla_nest_start(skb, idx);
309 if (!nla_attr) {
310 hdd_err("nla_nest_start failed");
311 goto fail;
312 }
313
314 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
315 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->
316 cache_conn_info.txrate);
317
318 /* report 16-bit bitrate only if we can */
319 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
320
321 if (bitrate > 0) {
322 if (nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
323 hdd_err("put fail bitrate: %u", bitrate);
324 goto fail;
325 }
326 } else {
327 hdd_err("Invalid bitrate: %u", bitrate);
328 }
329
330 if (bitrate_compat > 0) {
331 if (nla_put_u16(skb, NL80211_RATE_INFO_BITRATE,
332 bitrate_compat)) {
333 hdd_err("put fail bitrate_compat: %u", bitrate_compat);
334 goto fail;
335 }
336 } else {
337 hdd_err("Invalid bitrate_compat: %u", bitrate_compat);
338 }
339
340 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
341 hdd_sta_ctx->cache_conn_info.txrate.nss)) {
342 hdd_err("put fail");
343 goto fail;
344 }
345 nla_nest_end(skb, nla_attr);
346 return 0;
347fail:
348 return -EINVAL;
349}
350
351/**
352 * hdd_add_sta_info() - add station info attribute
353 * @skb: pointer to sk buff
354 * @hdd_sta_ctx: pointer to hdd station context
355 * @idx: attribute index
356 *
357 * Return: Success(0) or reason code for failure
358 */
359static int32_t hdd_add_sta_info(struct sk_buff *skb,
360 struct hdd_station_ctx *hdd_sta_ctx,
361 int idx)
362{
363 struct nlattr *nla_attr;
364
365 nla_attr = nla_nest_start(skb, idx);
366 if (!nla_attr) {
367 hdd_err("nla_nest_start failed");
368 goto fail;
369 }
370
371 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
372 (hdd_sta_ctx->cache_conn_info.signal + 100))) {
373 hdd_err("put fail");
374 goto fail;
375 }
376 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) {
377 hdd_err("hdd_add_tx_bitrate failed");
378 goto fail;
379 }
380
381 nla_nest_end(skb, nla_attr);
382 return 0;
383fail:
384 return -EINVAL;
385}
386
387/**
388 * hdd_add_survey_info() - add survey info attribute
389 * @skb: pointer to sk buff
390 * @hdd_sta_ctx: pointer to hdd station context
391 * @idx: attribute index
392 *
393 * Return: Success(0) or reason code for failure
394 */
395static int32_t hdd_add_survey_info(struct sk_buff *skb,
396 struct hdd_station_ctx *hdd_sta_ctx,
397 int idx)
398{
399 struct nlattr *nla_attr;
400
401 nla_attr = nla_nest_start(skb, idx);
402 if (!nla_attr)
403 goto fail;
404 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
405 hdd_sta_ctx->cache_conn_info.freq) ||
406 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
407 (hdd_sta_ctx->cache_conn_info.noise + 100))) {
408 hdd_err("put fail");
409 goto fail;
410 }
411 nla_nest_end(skb, nla_attr);
412 return 0;
413fail:
414 return -EINVAL;
415}
416
417/**
418 * hdd_add_link_standard_info() - add link info attribute
419 * @skb: pointer to sk buff
420 * @hdd_sta_ctx: pointer to hdd station context
421 * @idx: attribute index
422 *
423 * Return: Success(0) or reason code for failure
424 */
425static int32_t
426hdd_add_link_standard_info(struct sk_buff *skb,
427 struct hdd_station_ctx *hdd_sta_ctx, int idx)
428{
429 struct nlattr *nla_attr;
430
431 nla_attr = nla_nest_start(skb, idx);
432 if (!nla_attr) {
433 hdd_err("nla_nest_start failed");
434 goto fail;
435 }
436
437 if (nla_put(skb,
438 NL80211_ATTR_SSID,
439 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
440 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
441 hdd_err("put fail");
442 goto fail;
443 }
444 if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
445 hdd_sta_ctx->cache_conn_info.bssId.bytes)) {
446 hdd_err("put bssid failed");
447 goto fail;
448 }
449 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) {
450 hdd_err("hdd_add_survey_info failed");
451 goto fail;
452 }
453
454 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) {
455 hdd_err("hdd_add_sta_info failed");
456 goto fail;
457 }
458 nla_nest_end(skb, nla_attr);
459 return 0;
460fail:
461 return -EINVAL;
462}
463
464/**
465 * hdd_add_ap_standard_info() - add ap info attribute
466 * @skb: pointer to sk buff
467 * @hdd_sta_ctx: pointer to hdd station context
468 * @idx: attribute index
469 *
470 * Return: Success(0) or reason code for failure
471 */
472static int32_t
473hdd_add_ap_standard_info(struct sk_buff *skb,
474 struct hdd_station_ctx *hdd_sta_ctx, int idx)
475{
476 struct nlattr *nla_attr;
477
478 nla_attr = nla_nest_start(skb, idx);
479 if (!nla_attr)
480 goto fail;
481 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
482 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
483 sizeof(hdd_sta_ctx->cache_conn_info.vht_caps),
484 &hdd_sta_ctx->cache_conn_info.vht_caps)) {
485 hdd_err("put fail");
486 goto fail;
487 }
488 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
489 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
490 sizeof(hdd_sta_ctx->cache_conn_info.ht_caps),
491 &hdd_sta_ctx->cache_conn_info.ht_caps)) {
492 hdd_err("put fail");
493 goto fail;
494 }
495 nla_nest_end(skb, nla_attr);
496 return 0;
497fail:
498 return -EINVAL;
499}
500
501/**
502 * hdd_get_station_info() - send BSS information to supplicant
503 * @hdd_ctx: pointer to hdd context
504 * @adapter: pointer to adapter
505 *
506 * Return: 0 if success else error status
507 */
508static int hdd_get_station_info(struct hdd_context *hdd_ctx,
509 struct hdd_adapter *adapter)
510{
511 struct sk_buff *skb = NULL;
512 uint8_t *tmp_hs20 = NULL;
513 uint32_t nl_buf_len;
514 struct hdd_station_ctx *hdd_sta_ctx;
515
516 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
517
518 nl_buf_len = NLMSG_HDRLEN;
519 nl_buf_len += sizeof(hdd_sta_ctx->
520 cache_conn_info.last_ssid.SSID.length) +
521 QDF_MAC_ADDR_SIZE +
522 sizeof(hdd_sta_ctx->cache_conn_info.freq) +
523 sizeof(hdd_sta_ctx->cache_conn_info.noise) +
524 sizeof(hdd_sta_ctx->cache_conn_info.signal) +
525 (sizeof(uint32_t) * 2) +
526 sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) +
527 sizeof(hdd_sta_ctx->cache_conn_info.roam_count) +
528 sizeof(hdd_sta_ctx->cache_conn_info.last_auth_type) +
529 sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode);
530 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
531 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps);
532 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
533 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps);
534 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
535 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->
536 cache_conn_info.hs20vendor_ie);
537 nl_buf_len += (sizeof(hdd_sta_ctx->
538 cache_conn_info.hs20vendor_ie) - 1);
539 }
540 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
541 nl_buf_len += sizeof(hdd_sta_ctx->
542 cache_conn_info.ht_operation);
543 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
544 nl_buf_len += sizeof(hdd_sta_ctx->
545 cache_conn_info.vht_operation);
546
547 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
548 if (!skb) {
549 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
550 return -ENOMEM;
551 }
552
553 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
554 LINK_INFO_STANDARD_NL80211_ATTR)) {
555 hdd_err("put fail");
556 goto fail;
557 }
558 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
559 AP_INFO_STANDARD_NL80211_ATTR)) {
560 hdd_err("put fail");
561 goto fail;
562 }
563 if (nla_put_u32(skb, INFO_ROAM_COUNT,
564 hdd_sta_ctx->cache_conn_info.roam_count) ||
565 nla_put_u32(skb, INFO_AKM,
566 hdd_convert_auth_type(
567 hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
568 nla_put_u32(skb, WLAN802_11_MODE,
569 hdd_convert_dot11mode(
570 hdd_sta_ctx->cache_conn_info.dot11Mode))) {
571 hdd_err("put fail");
572 goto fail;
573 }
574 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
575 if (nla_put(skb, HT_OPERATION,
576 (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
577 &hdd_sta_ctx->cache_conn_info.ht_operation)) {
578 hdd_err("put fail");
579 goto fail;
580 }
581 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
582 if (nla_put(skb, VHT_OPERATION,
583 (sizeof(hdd_sta_ctx->
584 cache_conn_info.vht_operation)),
585 &hdd_sta_ctx->cache_conn_info.vht_operation)) {
586 hdd_err("put fail");
587 goto fail;
588 }
589 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
590 if (nla_put(skb, AP_INFO_HS20_INDICATION,
591 (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
592 - 1),
593 tmp_hs20 + 1)) {
594 hdd_err("put fail");
595 goto fail;
596 }
597
598 return cfg80211_vendor_cmd_reply(skb);
599fail:
600 if (skb)
601 kfree_skb(skb);
602 return -EINVAL;
603}
604
605#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
606static inline int32_t remote_station_put_u64(struct sk_buff *skb,
607 int32_t attrtype,
608 uint64_t value)
609{
610 return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
611}
612#else
613static inline int32_t remote_station_put_u64(struct sk_buff *skb,
614 int32_t attrtype,
615 uint64_t value)
616{
617 return nla_put_u64(skb, attrtype, value);
618}
619#endif
620
621/**
622 * hdd_add_survey_info_sap_get_len - get data length used in
623 * hdd_add_survey_info_sap()
624 *
625 * This function calculates the data length used in hdd_add_survey_info_sap()
626 *
627 * Return: total data length used in hdd_add_survey_info_sap()
628 */
629static uint32_t hdd_add_survey_info_sap_get_len(void)
630{
631 return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
632}
633
634/**
635 * hdd_add_survey_info - add survey info attribute
636 * @skb: pointer to response skb buffer
637 * @stainfo: station information
638 * @idx: attribute type index for nla_next_start()
639 *
640 * This function adds survey info attribute to response skb buffer
641 *
642 * Return : 0 on success and errno on failure
643 */
644static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
645 struct hdd_station_info *stainfo,
646 int idx)
647{
648 struct nlattr *nla_attr;
649
650 nla_attr = nla_nest_start(skb, idx);
651 if (!nla_attr)
652 goto fail;
653 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
654 stainfo->freq)) {
655 hdd_err("put fail");
656 goto fail;
657 }
658 nla_nest_end(skb, nla_attr);
659 return 0;
660fail:
661 return -EINVAL;
662}
663
664/**
665 * hdd_add_tx_bitrate_sap_get_len - get data length used in
666 * hdd_add_tx_bitrate_sap()
667 *
668 * This function calculates the data length used in hdd_add_tx_bitrate_sap()
669 *
670 * Return: total data length used in hdd_add_tx_bitrate_sap()
671 */
672static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
673{
674 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
675}
676
677/**
678 * hdd_add_tx_bitrate_sap - add vhs nss info attribute
679 * @skb: pointer to response skb buffer
680 * @stainfo: station information
681 * @idx: attribute type index for nla_next_start()
682 *
683 * This function adds vht nss attribute to response skb buffer
684 *
685 * Return : 0 on success and errno on failure
686 */
687static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
688 struct hdd_station_info *stainfo,
689 int idx)
690{
691 struct nlattr *nla_attr;
692
693 nla_attr = nla_nest_start(skb, idx);
694 if (!nla_attr)
695 goto fail;
696
697 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
698 stainfo->nss)) {
699 hdd_err("put fail");
700 goto fail;
701 }
702 nla_nest_end(skb, nla_attr);
703 return 0;
704fail:
705 return -EINVAL;
706}
707
708/**
709 * hdd_add_sta_info_sap_get_len - get data length used in
710 * hdd_add_sta_info_sap()
711 *
712 * This function calculates the data length used in hdd_add_sta_info_sap()
713 *
714 * Return: total data length used in hdd_add_sta_info_sap()
715 */
716static uint32_t hdd_add_sta_info_sap_get_len(void)
717{
718 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
719 hdd_add_tx_bitrate_sap_get_len());
720}
721
722/**
723 * hdd_add_sta_info_sap - add sta signal info attribute
724 * @skb: pointer to response skb buffer
725 * @stainfo: station information
726 * @idx: attribute type index for nla_next_start()
727 *
728 * This function adds sta signal attribute to response skb buffer
729 *
730 * Return : 0 on success and errno on failure
731 */
732static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
733 struct hdd_station_info *stainfo, int idx)
734{
735 struct nlattr *nla_attr;
736
737 nla_attr = nla_nest_start(skb, idx);
738 if (!nla_attr)
739 goto fail;
740
741 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
742 hdd_err("put fail");
743 goto fail;
744 }
745 if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
746 goto fail;
747
748 nla_nest_end(skb, nla_attr);
749 return 0;
750fail:
751 return -EINVAL;
752}
753
754/**
755 * hdd_add_link_standard_info_sap_get_len - get data length used in
756 * hdd_add_link_standard_info_sap()
757 *
758 * This function calculates the data length used in
759 * hdd_add_link_standard_info_sap()
760 *
761 * Return: total data length used in hdd_add_link_standard_info_sap()
762 */
763static uint32_t hdd_add_link_standard_info_sap_get_len(void)
764{
765 return ((NLA_HDRLEN) +
766 hdd_add_survey_info_sap_get_len() +
767 hdd_add_sta_info_sap_get_len() +
768 (sizeof(uint32_t) + NLA_HDRLEN));
769}
770
771/**
772 * hdd_add_link_standard_info_sap - add add link info attribut
773 * @skb: pointer to response skb buffer
774 * @stainfo: station information
775 * @idx: attribute type index for nla_next_start()
776 *
777 * This function adds link info attribut to response skb buffer
778 *
779 * Return : 0 on success and errno on failure
780 */
781static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
782 struct hdd_station_info *stainfo,
783 int idx)
784{
785 struct nlattr *nla_attr;
786
787 nla_attr = nla_nest_start(skb, idx);
788 if (!nla_attr)
789 goto fail;
790 if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
791 goto fail;
792 if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
793 goto fail;
794
795 if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
796 hdd_err("Reason code put fail");
797 goto fail;
798 }
799
800 nla_nest_end(skb, nla_attr);
801 return 0;
802fail:
803 return -EINVAL;
804}
805
806/**
807 * hdd_add_ap_standard_info_sap_get_len - get data length used in
808 * hdd_add_ap_standard_info_sap()
809 * @stainfo: station information
810 *
811 * This function calculates the data length used in
812 * hdd_add_ap_standard_info_sap()
813 *
814 * Return: total data length used in hdd_add_ap_standard_info_sap()
815 */
816static uint32_t hdd_add_ap_standard_info_sap_get_len(
817 struct hdd_station_info *stainfo)
818{
819 uint32_t len;
820
821 len = NLA_HDRLEN;
822 if (stainfo->vht_present)
823 len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
824 if (stainfo->ht_present)
825 len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
826
827 return len;
828}
829
830/**
831 * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
832 * @skb: pointer to response skb buffer
833 * @stainfo: station information
834 * @idx: attribute type index for nla_next_start()
835 *
836 * This function adds HT and VHT info attributes to response skb buffer
837 *
838 * Return : 0 on success and errno on failure
839 */
840static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
841 struct hdd_station_info *stainfo,
842 int idx)
843{
844 struct nlattr *nla_attr;
845
846 nla_attr = nla_nest_start(skb, idx);
847 if (!nla_attr)
848 goto fail;
849
850 if (stainfo->vht_present) {
851 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
852 sizeof(stainfo->vht_caps),
853 &stainfo->vht_caps)) {
854 hdd_err("put fail");
855 goto fail;
856 }
857 }
858 if (stainfo->ht_present) {
859 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
860 sizeof(stainfo->ht_caps),
861 &stainfo->ht_caps)) {
862 hdd_err("put fail");
863 goto fail;
864 }
865 }
866 nla_nest_end(skb, nla_attr);
867 return 0;
868fail:
869 return -EINVAL;
870}
871
872/**
873 * hdd_decode_ch_width - decode channel band width based
874 * @ch_width: encoded enum value holding channel band width
875 *
876 * This function decodes channel band width from the given encoded enum value.
877 *
878 * Returns: decoded channel band width.
879 */
880static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
881{
882 switch (ch_width) {
883 case 0:
884 return 20;
885 case 1:
886 return 40;
887 case 2:
888 return 80;
889 case 3:
890 case 4:
891 return 160;
892 default:
893 hdd_debug("invalid enum: %d", ch_width);
894 return 20;
895 }
896}
897
898/**
899 * hdd_get_cached_station_remote() - get cached(deleted) peer's info
900 * @hdd_ctx: hdd context
901 * @adapter: hostapd interface
902 * @mac_addr: mac address of requested peer
903 *
904 * This function collect and indicate the cached(deleted) peer's info
905 *
906 * Return: 0 on success, otherwise error value
907 */
908
909static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
910 struct hdd_adapter *adapter,
911 struct qdf_mac_addr mac_addr)
912{
913 struct hdd_station_info *stainfo = hdd_get_stainfo(
914 adapter->cache_sta_info,
915 mac_addr);
916 struct sk_buff *skb = NULL;
917 uint32_t nl_buf_len = NLMSG_HDRLEN;
918 uint8_t channel_width;
919
920 if (!stainfo) {
921 hdd_err("peer " MAC_ADDRESS_STR " not found",
922 MAC_ADDR_ARRAY(mac_addr.bytes));
923 return -EINVAL;
924 }
925
926 nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
927 hdd_add_ap_standard_info_sap_get_len(stainfo) +
928 (sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
929 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
930 (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
931 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
932
933 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
934 if (!skb) {
935 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
936 return -ENOMEM;
937 }
938
939 if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
940 LINK_INFO_STANDARD_NL80211_ATTR)) {
941 hdd_err("link standard put fail");
942 goto fail;
943 }
944
945 if (hdd_add_ap_standard_info_sap(skb, stainfo,
946 AP_INFO_STANDARD_NL80211_ATTR)) {
947 hdd_err("ap standard put fail");
948 goto fail;
949 }
950
951 /* upper layer expects decoded channel BW */
952 channel_width = hdd_decode_ch_width(stainfo->ch_width);
953
954 if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
955 hdd_convert_dot11mode(
956 stainfo->mode)) ||
957 nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
958 hdd_err("remote ch put fail");
959 goto fail;
960 }
961 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
962 hdd_err("tx rate put fail");
963 goto fail;
964 }
965 if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
966 hdd_err("rx rate put fail");
967 goto fail;
968 }
969
970 qdf_mem_zero(stainfo, sizeof(*stainfo));
971
972 return cfg80211_vendor_cmd_reply(skb);
973fail:
974 if (skb)
975 kfree_skb(skb);
976
977 return -EINVAL;
978}
979
980/**
981 * hdd_get_cached_station_remote() - get connected peer's info
982 * @hdd_ctx: hdd context
983 * @adapter: hostapd interface
984 * @mac_addr: mac address of requested peer
985 *
986 * This function collect and indicate the connected peer's info
987 *
988 * Return: 0 on success, otherwise error value
989 */
990static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
991 struct hdd_adapter *adapter,
992 struct qdf_mac_addr mac_addr,
993 struct hdd_station_info *stainfo)
994{
995 struct sk_buff *skb = NULL;
996 uint32_t nl_buf_len;
997 struct sir_peer_info_ext peer_info;
998 bool txrx_rate = true;
999
1000 nl_buf_len = NLMSG_HDRLEN;
1001 nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
1002 (sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
1003 (sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
1004 (sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
1005 (sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
1006 (sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
1007 (sizeof(stainfo->mode) + NLA_HDRLEN);
1008
1009 if (!hdd_ctx->config->sap_get_peer_info ||
1010 wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
1011 hdd_err("fail to get tx/rx rate");
1012 txrx_rate = false;
1013 } else {
1014 stainfo->tx_rate = peer_info.tx_rate;
1015 stainfo->rx_rate = peer_info.rx_rate;
1016 nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
1017 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
1018 }
1019
1020 /* below info is only valid for HT/VHT mode */
1021 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
1022 nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
1023 (sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
1024 (sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
1025 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
1026 (sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
1027
1028 hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
1029
1030 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
1031 nl_buf_len);
1032 if (!skb) {
1033 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
1034 goto fail;
1035 }
1036
1037 hdd_info("stainfo");
1038 hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
1039 stainfo->max_phy_rate, stainfo->tx_packets,
1040 stainfo->tx_bytes);
1041 hdd_info("rx_pkts %x rx_bytes %llx mode %x",
1042 stainfo->rx_packets, stainfo->rx_bytes,
1043 stainfo->mode);
1044 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
1045 hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
1046 stainfo->ampdu, stainfo->tx_stbc,
1047 stainfo->rx_stbc);
1048 hdd_info("wmm %d chwidth %d sgi %d",
1049 stainfo->is_qos_enabled,
1050 stainfo->ch_width,
1051 stainfo->sgi_enable);
1052 }
1053
1054 if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
1055 nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
1056 remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
1057 nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
1058 remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
1059 nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
1060 nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
1061 hdd_err("put fail");
1062 goto fail;
1063 }
1064
1065 if (txrx_rate) {
1066 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
1067 nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
1068 hdd_err("put fail");
1069 goto fail;
1070 } else {
1071 hdd_info("tx_rate %x rx_rate %x",
1072 stainfo->tx_rate, stainfo->rx_rate);
1073 }
1074 }
1075
1076 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
1077 if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
1078 nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
1079 nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
1080 nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
1081 nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
1082 hdd_err("put fail");
1083 goto fail;
1084 }
1085 }
1086
1087 return cfg80211_vendor_cmd_reply(skb);
1088
1089fail:
1090 if (skb)
1091 kfree_skb(skb);
1092
1093 return -EINVAL;
1094}
1095
1096/**
1097 * hdd_get_station_remote() - get remote peer's info
1098 * @hdd_ctx: hdd context
1099 * @adapter: hostapd interface
1100 * @mac_addr: mac address of requested peer
1101 *
1102 * This function collect and indicate the remote peer's info
1103 *
1104 * Return: 0 on success, otherwise error value
1105 */
1106static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
1107 struct hdd_adapter *adapter,
1108 struct qdf_mac_addr mac_addr)
1109{
1110 struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
1111 mac_addr);
1112 int status = 0;
1113 bool is_associated = false;
1114
1115 if (!stainfo) {
1116 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
1117 mac_addr);
1118 return status;
1119 }
1120
1121 is_associated = hdd_is_peer_associated(adapter, &mac_addr);
1122 if (!is_associated) {
1123 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
1124 mac_addr);
1125 return status;
1126 }
1127
1128 status = hdd_get_connected_station_info(hdd_ctx, adapter,
1129 mac_addr, stainfo);
1130 return status;
1131}
1132
1133/**
1134 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
1135 * @wiphy: corestack handler
1136 * @wdev: wireless device
1137 * @data: data
1138 * @data_len: data length
1139 *
1140 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
1141 * Validate cmd attributes and send the station info to upper layers.
1142 *
1143 * Return: Success(0) or reason code for failure
1144 */
1145static int
1146__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
1147 struct wireless_dev *wdev,
1148 const void *data,
1149 int data_len)
1150{
1151 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1152 struct net_device *dev = wdev->netdev;
1153 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1154 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
1155 int32_t status;
1156
1157 hdd_enter_dev(dev);
1158 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
1159 hdd_err("Command not allowed in FTM mode");
1160 status = -EPERM;
1161 goto out;
1162 }
1163
1164 status = wlan_hdd_validate_context(hdd_ctx);
1165 if (status != 0)
1166 goto out;
1167
1168 status = wlan_cfg80211_nla_parse(tb,
1169 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
1170 data, data_len,
1171 hdd_get_station_policy);
1172 if (status) {
1173 hdd_err("Invalid ATTR");
1174 goto out;
1175 }
1176
1177 /* Parse and fetch Command Type*/
1178 if (tb[STATION_INFO]) {
1179 status = hdd_get_station_info(hdd_ctx, adapter);
1180 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
1181 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
1182 } else if (tb[STATION_REMOTE]) {
1183 struct qdf_mac_addr mac_addr;
1184
1185 if (adapter->device_mode != QDF_SAP_MODE &&
1186 adapter->device_mode != QDF_P2P_GO_MODE) {
1187 hdd_err("invalid device_mode:%d", adapter->device_mode);
1188 status = -EINVAL;
1189 goto out;
1190 }
1191
1192 nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
1193 QDF_MAC_ADDR_SIZE);
1194
1195 hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
1196 MAC_ADDR_ARRAY(mac_addr.bytes));
1197
1198 status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
1199 } else {
1200 hdd_err("get station info cmd type failed");
1201 status = -EINVAL;
1202 goto out;
1203 }
1204 hdd_exit();
1205out:
1206 return status;
1207}
1208
1209int32_t hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
1210 struct wireless_dev *wdev,
1211 const void *data,
1212 int data_len)
1213{
1214 int ret;
1215
1216 cds_ssr_protect(__func__);
1217 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
1218 cds_ssr_unprotect(__func__);
1219
1220 return ret;
1221}
1222