1 /*
2 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: wlan_hdd_sysfs_connect_info.c
20 *
21 * WLAN Host Device Driver implementation to update sysfs with connect
22 * information
23 */
24
25 #include <wlan_hdd_includes.h>
26 #include "osif_vdev_sync.h"
27 #include "wlan_hdd_sysfs_connect_info.h"
28 #include "qwlan_version.h"
29
30 /**
31 * wlan_hdd_version_info() - Populate driver, FW and HW version
32 * @hdd_ctx: pointer to hdd context
33 * @buf: output buffer to hold version info
34 * @buf_avail_len: available buffer length
35 *
36 * Return: No.of bytes populated by this function in buffer
37 */
38 static ssize_t
wlan_hdd_version_info(struct hdd_context * hdd_ctx,uint8_t * buf,ssize_t buf_avail_len)39 wlan_hdd_version_info(struct hdd_context *hdd_ctx, uint8_t *buf,
40 ssize_t buf_avail_len)
41 {
42 ssize_t length = 0;
43 int ret_val;
44
45 ret_val = scnprintf(buf, buf_avail_len,
46 "\nVERSION DETAILS\n");
47 if (ret_val <= 0)
48 return length;
49 length += ret_val;
50
51 if (length >= buf_avail_len) {
52 hdd_err("No sufficient buf_avail_len");
53 return buf_avail_len;
54 }
55
56 ret_val = scnprintf(buf + length, buf_avail_len - length,
57 "Host Driver Version: %s\n"
58 "Firmware Version: %d.%d.%d.%d.%d.%d\n"
59 "Hardware Version: %s\n",
60 QWLAN_VERSIONSTR,
61 hdd_ctx->fw_version_info.major_spid,
62 hdd_ctx->fw_version_info.minor_spid,
63 hdd_ctx->fw_version_info.siid,
64 hdd_ctx->fw_version_info.rel_id,
65 hdd_ctx->fw_version_info.crmid,
66 hdd_ctx->fw_version_info.sub_id,
67 hdd_ctx->target_hw_name);
68 if (ret_val <= 0)
69 return length;
70
71 length += ret_val;
72
73 return length;
74 }
75
76 /**
77 * wlan_hdd_add_nss_info() - Populate NSS info
78 * @conn_info: station connection information
79 * @buf: output buffer to hold version info
80 * @buf_avail_len: available buffer length
81 *
82 * Return: No.of bytes populated by this function in buffer
83 */
84 static ssize_t
wlan_hdd_add_nss_info(struct hdd_connection_info * conn_info,uint8_t * buf,ssize_t buf_avail_len)85 wlan_hdd_add_nss_info(struct hdd_connection_info *conn_info,
86 uint8_t *buf, ssize_t buf_avail_len)
87 {
88 ssize_t length = 0;
89 int ret_val;
90
91 if (!conn_info->conn_flag.ht_present &&
92 !conn_info->conn_flag.vht_present)
93 return length;
94
95 ret_val = scnprintf(buf, buf_avail_len,
96 "nss = %u\n",
97 conn_info->txrate.nss);
98 if (ret_val <= 0)
99 return length;
100
101 length = ret_val;
102 return length;
103 }
104
105 /**
106 * wlan_hdd_add_ht_cap_info() - Populate HT info
107 * @conn_info: station connection information
108 * @buf: output buffer to hold version info
109 * @buf_avail_len: available buffer length
110 *
111 * Return: No.of bytes populated by this function in buffer
112 */
113 static ssize_t
wlan_hdd_add_ht_cap_info(struct hdd_connection_info * conn_info,uint8_t * buf,ssize_t buf_avail_len)114 wlan_hdd_add_ht_cap_info(struct hdd_connection_info *conn_info,
115 uint8_t *buf, ssize_t buf_avail_len)
116 {
117 struct ieee80211_ht_cap *ht_caps;
118 ssize_t length = 0;
119 int ret;
120
121 if (!conn_info->conn_flag.ht_present)
122 return length;
123
124 ht_caps = &conn_info->ht_caps;
125 ret = scnprintf(buf, buf_avail_len,
126 "ht_cap_info = %x\n"
127 "ampdu_params_info = %x\n"
128 "extended_ht_cap_info = %x\n"
129 "tx_BF_cap_info = %x\n"
130 "antenna_selection_info = %x\n"
131 "ht_rx_higest = %x\n"
132 "ht_tx_params = %x\n",
133 ht_caps->cap_info,
134 ht_caps->ampdu_params_info,
135 ht_caps->extended_ht_cap_info,
136 ht_caps->tx_BF_cap_info,
137 ht_caps->antenna_selection_info,
138 ht_caps->mcs.rx_highest,
139 ht_caps->mcs.tx_params);
140 if (ret <= 0)
141 return length;
142
143 length = ret;
144 return length;
145 }
146
147 /**
148 * wlan_hdd_add_vht_cap_info() - Populate VHT info
149 * @conn_info: station connection information
150 * @buf: output buffer to hold version info
151 * @buf_avail_len: available buffer length
152 *
153 * Return: No.of bytes populated by this function in buffer
154 */
155 static ssize_t
wlan_hdd_add_vht_cap_info(struct hdd_connection_info * conn_info,uint8_t * buf,ssize_t buf_avail_len)156 wlan_hdd_add_vht_cap_info(struct hdd_connection_info *conn_info,
157 uint8_t *buf, ssize_t buf_avail_len)
158 {
159 struct ieee80211_vht_cap *vht_caps;
160 ssize_t length = 0;
161 int ret;
162
163 if (!conn_info->conn_flag.vht_present)
164 return length;
165
166 vht_caps = &conn_info->vht_caps;
167 ret = scnprintf(buf, buf_avail_len,
168 "vht_cap_info = %x\n"
169 "rx_mcs_map = %x\n"
170 "rx_highest = %x\n"
171 "tx_mcs_map = %x\n"
172 "tx_highest = %x\n",
173 vht_caps->vht_cap_info,
174 vht_caps->supp_mcs.rx_mcs_map,
175 vht_caps->supp_mcs.rx_highest,
176 vht_caps->supp_mcs.tx_mcs_map,
177 vht_caps->supp_mcs.tx_highest);
178 if (ret <= 0)
179 return length;
180
181 length = ret;
182 return length;
183 }
184
185 /**
186 * hdd_auth_type_str() - Get string for enum csr auth type
187 * @auth_type: authentication id
188 *
189 * Return: Meaningful string for enum csr auth type
190 */
191 static
hdd_auth_type_str(uint32_t auth_type)192 uint8_t *hdd_auth_type_str(uint32_t auth_type)
193 {
194 switch (auth_type) {
195 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
196 return "OPEN SYSTEM";
197 case eCSR_AUTH_TYPE_SHARED_KEY:
198 return "SHARED KEY";
199 case eCSR_AUTH_TYPE_SAE:
200 return "SAE";
201 case eCSR_AUTH_TYPE_AUTOSWITCH:
202 return "AUTO SWITCH";
203 case eCSR_AUTH_TYPE_WPA:
204 return "WPA";
205 case eCSR_AUTH_TYPE_WPA_PSK:
206 return "WPA PSK";
207 case eCSR_AUTH_TYPE_WPA_NONE:
208 return "WPA NONE";
209
210 case eCSR_AUTH_TYPE_RSN:
211 return "RSN";
212 case eCSR_AUTH_TYPE_RSN_PSK:
213 return "RSN PSK";
214 case eCSR_AUTH_TYPE_FT_RSN:
215 return "FT RSN";
216 case eCSR_AUTH_TYPE_FT_RSN_PSK:
217 return "FT RSN PSK";
218 #ifdef FEATURE_WLAN_WAPI
219 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
220 return "WAPI WAI CERTIFICATE";
221 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
222 return "WAPI WAI PSK";
223 #endif /* FEATURE_WLAN_WAPI */
224 case eCSR_AUTH_TYPE_CCKM_WPA:
225 return "CCKM WPA";
226 case eCSR_AUTH_TYPE_CCKM_RSN:
227 return "CCKM RSN";
228 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
229 return "RSN PSK SHA256";
230 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
231 return "RSN 8021X SHA256";
232 case eCSR_AUTH_TYPE_FILS_SHA256:
233 return "FILS SHA256";
234 case eCSR_AUTH_TYPE_FILS_SHA384:
235 return "FILS SHA384";
236 case eCSR_AUTH_TYPE_FT_FILS_SHA256:
237 return "FT FILS SHA256";
238 case eCSR_AUTH_TYPE_FT_FILS_SHA384:
239 return "FT FILS SHA384";
240 case eCSR_AUTH_TYPE_DPP_RSN:
241 return "DPP RSN";
242 case eCSR_AUTH_TYPE_OWE:
243 return "OWE";
244 case eCSR_AUTH_TYPE_SUITEB_EAP_SHA256:
245 return "SUITEB EAP SHA256";
246 case eCSR_AUTH_TYPE_SUITEB_EAP_SHA384:
247 return "SUITEB EAP SHA384";
248 case eCSR_AUTH_TYPE_OSEN:
249 return "OSEN";
250 case eCSR_AUTH_TYPE_FT_SAE:
251 return "FT SAE";
252 case eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384:
253 return "FT Suite B SHA384";
254 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
255 return "NUM OF SUPPORT AUTH TYPE";
256 case eCSR_AUTH_TYPE_FAILED:
257 return "FAILED";
258 case eCSR_AUTH_TYPE_NONE:
259 return "NONE";
260 }
261
262 return "UNKNOWN";
263 }
264
265 /**
266 * hdd_dot11_mode_str() - Get string for enum csr dot11 mode
267 * @dot11mode: dot11 mode ID
268 *
269 * Return: Meaningful string for enum csr dot11 mode
270 */
271 static
hdd_dot11_mode_str(uint32_t dot11mode)272 uint8_t *hdd_dot11_mode_str(uint32_t dot11mode)
273 {
274 switch (dot11mode) {
275 case eCSR_CFG_DOT11_MODE_11A:
276 return "DOT11 MODE 11A";
277 case eCSR_CFG_DOT11_MODE_11B:
278 return "DOT11 MODE 11B";
279 case eCSR_CFG_DOT11_MODE_11G:
280 return "DOT11 MODE 11G";
281 case eCSR_CFG_DOT11_MODE_11N:
282 return "DOT11 MODE 11N";
283 case eCSR_CFG_DOT11_MODE_11AC:
284 return "DOT11 MODE 11AC";
285 case eCSR_CFG_DOT11_MODE_AUTO:
286 return "DOT11 MODE AUTO";
287 case eCSR_CFG_DOT11_MODE_ABG:
288 return "DOT11 MODE 11ABG";
289 case eCSR_CFG_DOT11_MODE_11AX:
290 case eCSR_CFG_DOT11_MODE_11AX_ONLY:
291 return "DOT11_MODE_11AX";
292 case eCSR_CFG_DOT11_MODE_11BE:
293 case eCSR_CFG_DOT11_MODE_11BE_ONLY:
294 return "DOT11_MODE_11BE";
295 }
296
297 return "UNKNOWN";
298 }
299
300 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
301 /**
302 * wlan_hdd_connect_info() - Populate connect info
303 * @adapter: pointer to sta adapter for which connect info is required
304 * @buf: output buffer to hold version info
305 * @buf_avail_len: available buffer length
306 *
307 * Return: No.of bytes populated by this function in buffer
308 */
wlan_hdd_connect_info(struct hdd_adapter * adapter,uint8_t * buf,ssize_t buf_avail_len)309 static ssize_t wlan_hdd_connect_info(struct hdd_adapter *adapter, uint8_t *buf,
310 ssize_t buf_avail_len)
311 {
312 struct wlan_hdd_link_info *link_info;
313 struct hdd_station_ctx *hdd_sta_ctx;
314 uint32_t len = 0;
315 ssize_t length = 0;
316 struct hdd_connection_info *conn_info;
317 uint32_t tx_bit_rate, rx_bit_rate;
318 bool is_legacy = false;
319 bool is_standby = false;
320
321 if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
322 len = scnprintf(buf, buf_avail_len,
323 "STA is not connected\n");
324 if (len >= 0)
325 return length;
326 }
327
328 len = scnprintf(buf, buf_avail_len,
329 "CONNECTION DETAILS\n");
330 if (len <= 0)
331 return length;
332
333 length += len;
334 if (length >= buf_avail_len) {
335 hdd_err("No sufficient buf_avail_len");
336 return buf_avail_len;
337 }
338
339 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
340 if (adapter->deflink == &adapter->link_info[0] &&
341 hdd_sta_ctx->conn_info.ieee_link_id == WLAN_INVALID_LINK_ID) {
342 len = scnprintf(buf + length, buf_avail_len - length,
343 "CONNECTION DETAILS: Non-ML connection\n");
344 is_legacy = true;
345 } else {
346 len = scnprintf(buf + length, buf_avail_len - length,
347 "CONNECTION DETAILS: ML connection\n");
348 }
349
350 if (len <= 0)
351 return length;
352
353 length += len;
354 if (length >= buf_avail_len) {
355 hdd_err("No sufficient buf_avail_len");
356 return buf_avail_len;
357 }
358
359 len = scnprintf(buf + length, buf_avail_len - length,
360 "ssid: %s\n"
361 "bssid: " QDF_MAC_ADDR_FMT "\n"
362 "connect_time: %s\n"
363 "auth_time: %s\n"
364 "last_auth_type: %s\n"
365 "dot11mode: %s\n",
366 hdd_sta_ctx->conn_info.last_ssid.SSID.ssId,
367 QDF_MAC_ADDR_REF(hdd_sta_ctx->conn_info.bssid.bytes),
368 hdd_sta_ctx->conn_info.connect_time,
369 hdd_sta_ctx->conn_info.auth_time,
370 hdd_auth_type_str(hdd_sta_ctx->conn_info.last_auth_type),
371 hdd_dot11_mode_str(hdd_sta_ctx->conn_info.dot11mode));
372 if (len <= 0)
373 return length;
374 length += len;
375 if (length >= buf_avail_len) {
376 hdd_err("No sufficient buf_avail_len");
377 return buf_avail_len;
378 }
379
380 hdd_adapter_for_each_link_info(adapter, link_info) {
381 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
382 conn_info = &hdd_sta_ctx->conn_info;
383
384 if(!is_legacy && conn_info->ieee_link_id == WLAN_INVALID_LINK_ID)
385 continue;
386
387 if (hdd_cm_is_vdev_roaming(link_info)) {
388 len = scnprintf(buf + length, buf_avail_len - length,
389 "Roaming is in progress");
390 if (len <= 0)
391 return length;
392
393 length += len;
394 }
395
396 tx_bit_rate = cfg80211_calculate_bitrate(&conn_info->txrate);
397 rx_bit_rate = cfg80211_calculate_bitrate(&conn_info->rxrate);
398
399 if (!is_legacy) {
400 len = scnprintf(buf + length, buf_avail_len - length,
401 "\nlink_id: %d\n",
402 conn_info->ieee_link_id);
403 if (len <= 0)
404 return length;
405
406 length += len;
407 if (length >= buf_avail_len) {
408 hdd_debug("No sufficient buf_avail_len");
409 return buf_avail_len;
410 }
411
412 if (link_info->vdev_id == WLAN_INVALID_VDEV_ID &&
413 conn_info->ieee_link_id != WLAN_INVALID_LINK_ID)
414 is_standby = true;
415
416 len = scnprintf(buf + length, buf_avail_len - length,
417 "stand-by link: %d\n",
418 is_standby);
419 if (len <= 0)
420 return length;
421
422 length += len;
423 if (length >= buf_avail_len) {
424 hdd_debug("No sufficient buf_avail_len");
425 return buf_avail_len;
426 }
427 }
428
429 len = scnprintf(buf + length, buf_avail_len - length,
430 "freq: %u\n"
431 "ch_width: %s\n"
432 "signal: %ddBm\n"
433 "tx_bit_rate: %u\n"
434 "rx_bit_rate: %u\n"
435 "last_auth_type: %s\n"
436 "dot11mode: %s\n",
437 conn_info->chan_freq,
438 hdd_ch_width_str(conn_info->ch_width),
439 conn_info->signal,
440 tx_bit_rate,
441 rx_bit_rate,
442 hdd_auth_type_str(conn_info->last_auth_type),
443 hdd_dot11_mode_str(conn_info->dot11mode));
444
445 if (len <= 0)
446 return length;
447
448 length += len;
449 if (length >= buf_avail_len) {
450 hdd_debug("No sufficient buf_avail_len");
451 return buf_avail_len;
452 }
453
454 length += wlan_hdd_add_nss_info(conn_info, buf + length,
455 buf_avail_len - length);
456 if (length >= buf_avail_len) {
457 hdd_debug("No sufficient buf_avail_len");
458 return buf_avail_len;
459 }
460
461 length += wlan_hdd_add_ht_cap_info(conn_info, buf + length,
462 buf_avail_len - length);
463 if (length >= buf_avail_len) {
464 hdd_debug("No sufficient buf_avail_len");
465 return buf_avail_len;
466 }
467
468 length += wlan_hdd_add_vht_cap_info(conn_info, buf + length,
469 buf_avail_len - length);
470 if (is_legacy)
471 return length;
472 }
473
474 return length;
475 }
476 #else
wlan_hdd_connect_info(struct hdd_adapter * adapter,uint8_t * buf,ssize_t buf_avail_len)477 static ssize_t wlan_hdd_connect_info(struct hdd_adapter *adapter, uint8_t *buf,
478 ssize_t buf_avail_len)
479 {
480 ssize_t length = 0;
481 struct hdd_station_ctx *hdd_sta_ctx;
482 struct hdd_connection_info *conn_info;
483 uint32_t tx_bit_rate, rx_bit_rate;
484 int ret_val;
485
486 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
487 if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
488 ret_val = scnprintf(buf, buf_avail_len,
489 "\nSTA is not connected\n");
490 if (ret_val >= 0)
491 length = ret_val;
492 return length;
493 }
494
495 ret_val = scnprintf(buf, buf_avail_len,
496 "\nCONNECTION DETAILS\n");
497 if (ret_val <= 0)
498 return length;
499 length += ret_val;
500
501 if (length >= buf_avail_len) {
502 hdd_err("No sufficient buf_avail_len");
503 return buf_avail_len;
504 }
505
506 if (hdd_cm_is_vdev_roaming(adapter->deflink)) {
507 ret_val = scnprintf(buf + length, buf_avail_len - length,
508 "Roaming is in progress");
509 if (ret_val <= 0)
510 return length;
511 length += ret_val;
512 }
513
514 conn_info = &hdd_sta_ctx->conn_info;
515 tx_bit_rate = cfg80211_calculate_bitrate(&conn_info->txrate);
516 rx_bit_rate = cfg80211_calculate_bitrate(&conn_info->rxrate);
517
518 if (length >= buf_avail_len) {
519 hdd_err("No sufficient buf_avail_len");
520 return buf_avail_len;
521 }
522 ret_val = scnprintf(buf + length, buf_avail_len - length,
523 "ssid = %s\n"
524 "bssid = " QDF_MAC_ADDR_FMT "\n"
525 "connect_time = %s\n"
526 "auth_time = %s\n"
527 "freq = %u\n"
528 "ch_width = %s\n"
529 "signal = %ddBm\n"
530 "tx_bit_rate = %u\n"
531 "rx_bit_rate = %u\n"
532 "last_auth_type = %s\n"
533 "dot11mode = %s\n",
534 conn_info->last_ssid.SSID.ssId,
535 QDF_MAC_ADDR_REF(conn_info->bssid.bytes),
536 conn_info->connect_time,
537 conn_info->auth_time,
538 conn_info->chan_freq,
539 hdd_ch_width_str(conn_info->ch_width),
540 conn_info->signal,
541 tx_bit_rate,
542 rx_bit_rate,
543 hdd_auth_type_str(conn_info->last_auth_type),
544 hdd_dot11_mode_str(conn_info->dot11mode));
545
546 if (ret_val <= 0)
547 return length;
548 length += ret_val;
549
550 if (length >= buf_avail_len) {
551 hdd_err("No sufficient buf_avail_len");
552 return buf_avail_len;
553 }
554 length += wlan_hdd_add_nss_info(conn_info, buf + length,
555 buf_avail_len - length);
556
557 if (length >= buf_avail_len) {
558 hdd_err("No sufficient buf_avail_len");
559 return buf_avail_len;
560 }
561
562 length += wlan_hdd_add_ht_cap_info(conn_info, buf + length,
563 buf_avail_len - length);
564
565 if (length >= buf_avail_len) {
566 hdd_err("No sufficient buf_avail_len");
567 return buf_avail_len;
568 }
569 length += wlan_hdd_add_vht_cap_info(conn_info, buf + length,
570 buf_avail_len - length);
571 return length;
572 }
573 #endif
574
575 static ssize_t
wlan_hdd_current_time_info(uint8_t * buf,ssize_t buf_avail_len)576 wlan_hdd_current_time_info(uint8_t *buf, ssize_t buf_avail_len)
577 {
578 ssize_t length;
579 char time_buffer[HDD_TIME_STRING_LEN];
580 int ret_val;
581
582 qdf_get_time_of_the_day_in_hr_min_sec_usec(time_buffer,
583 sizeof(time_buffer));
584 ret_val = scnprintf(buf, buf_avail_len,
585 "\nTime at which this file generated = %s\n",
586 time_buffer);
587 if (ret_val < 0)
588 return 0;
589 length = ret_val;
590
591 return length;
592 }
593
__show_connect_info(struct net_device * net_dev,char * buf,ssize_t buf_avail_len)594 static ssize_t __show_connect_info(struct net_device *net_dev, char *buf,
595 ssize_t buf_avail_len)
596 {
597 struct hdd_adapter *adapter = netdev_priv(net_dev);
598 struct hdd_context *hdd_ctx;
599 ssize_t len;
600 int ret_val;
601
602 hdd_enter_dev(net_dev);
603
604 len = wlan_hdd_current_time_info(buf, buf_avail_len);
605 if (len >= buf_avail_len) {
606 hdd_err("No sufficient buf_avail_len");
607 len = buf_avail_len;
608 goto exit;
609 }
610
611 ret_val = hdd_validate_adapter(adapter);
612 if (0 != ret_val)
613 return len;
614
615 if (adapter->device_mode != QDF_STA_MODE) {
616 ret_val = scnprintf(buf + len, buf_avail_len - len,
617 "Interface is not operating STA Mode\n");
618 if (ret_val <= 0)
619 goto exit;
620
621 len += ret_val;
622 goto exit;
623 }
624
625 if (len >= buf_avail_len) {
626 hdd_err("No sufficient buf_avail_len");
627 len = buf_avail_len;
628 goto exit;
629 }
630
631 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
632 ret_val = wlan_hdd_validate_context(hdd_ctx);
633 if (0 != ret_val)
634 goto exit;
635
636 len += wlan_hdd_version_info(hdd_ctx, buf + len, buf_avail_len - len);
637
638 if (len >= buf_avail_len) {
639 hdd_err("No sufficient buf_avail_len");
640 len = buf_avail_len;
641 goto exit;
642 }
643 len += wlan_hdd_connect_info(adapter, buf + len, buf_avail_len - len);
644
645 exit:
646 hdd_exit();
647 return len;
648 }
649
show_connect_info(struct device * dev,struct device_attribute * attr,char * buf)650 static ssize_t show_connect_info(struct device *dev,
651 struct device_attribute *attr,
652 char *buf)
653 {
654 struct net_device *net_dev = container_of(dev, struct net_device, dev);
655 struct osif_vdev_sync *vdev_sync;
656 ssize_t err_size;
657 ssize_t buf_avail_len = SYSFS_CONNECT_INFO_BUF_SIZE;
658
659 err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
660 if (err_size)
661 return err_size;
662
663 err_size = __show_connect_info(net_dev, buf, buf_avail_len);
664
665 osif_vdev_sync_op_stop(vdev_sync);
666
667 return err_size;
668 }
669
670 static DEVICE_ATTR(connect_info, 0444, show_connect_info, NULL);
671
hdd_sysfs_connect_info_interface_create(struct hdd_adapter * adapter)672 void hdd_sysfs_connect_info_interface_create(struct hdd_adapter *adapter)
673 {
674 int error;
675
676 error = device_create_file(&adapter->dev->dev, &dev_attr_connect_info);
677 if (error)
678 hdd_err("could not create connect_info sysfs file");
679 }
680
hdd_sysfs_connect_info_interface_destroy(struct hdd_adapter * adapter)681 void hdd_sysfs_connect_info_interface_destroy(struct hdd_adapter *adapter)
682 {
683 device_remove_file(&adapter->dev->dev, &dev_attr_connect_info);
684 }
685
686