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