1 /*
2  * Copyright (c) 2021, 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: wlan_hdd_sysfs_bmiss.c
19  *
20  * Implementation for creating sysfs file bmiss
21  */
22 
23 #include <wlan_hdd_includes.h>
24 #include <wlan_hdd_sysfs.h>
25 #include "osif_vdev_sync.h"
26 #include <wlan_hdd_sysfs_bmiss.h>
27 #include <wlan_hdd_stats.h>
28 #include <wlan_cp_stats_mc_ucfg_api.h>
29 
30 static struct infra_cp_stats_event*
wlan_hdd_get_bmiss(struct hdd_adapter * adapter)31 wlan_hdd_get_bmiss(struct hdd_adapter *adapter)
32 {
33 	struct hdd_station_ctx *hdd_sta_ctx;
34 	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
35 	int errno;
36 
37 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
38 	if (!hdd_sta_ctx) {
39 		hdd_debug("hdd_sta_ctx received NULL");
40 		return NULL;
41 	}
42 	qdf_mem_copy(peer_mac, hdd_sta_ctx->conn_info.bssid.bytes,
43 		     QDF_MAC_ADDR_SIZE);
44 	return wlan_cfg80211_mc_bmiss_get_infra_cp_stats(adapter->deflink->vdev,
45 							 peer_mac, &errno);
46 }
47 
48 static ssize_t
__hdd_sysfs_bmiss_show(struct net_device * net_dev,char * buf)49 __hdd_sysfs_bmiss_show(struct net_device *net_dev, char *buf)
50 {
51 	struct hdd_adapter *adapter;
52 	struct hdd_context *hdd_ctx;
53 	struct infra_cp_stats_event *ev_ptr;
54 	ssize_t ret = 0;
55 	int idx = 0;
56 
57 	adapter = netdev_priv(net_dev);
58 	if (hdd_validate_adapter(adapter))
59 		return -EINVAL;
60 
61 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
62 	ret = wlan_hdd_validate_context(hdd_ctx);
63 	if (ret)
64 		return ret;
65 
66 	if (!wlan_hdd_validate_modules_state(hdd_ctx))
67 		return -EINVAL;
68 
69 	ev_ptr = wlan_hdd_get_bmiss(adapter);
70 	if (!ev_ptr) {
71 		hdd_err_rl("GET_BMISS failed");
72 		return ret;
73 	}
74 
75 	ret = scnprintf(buf, PAGE_SIZE, "num_pre_bmiss:%u\n",
76 			ev_ptr->bmiss_infra_cp_stats->num_pre_bmiss);
77 	if (ret <= 0)
78 		return ret;
79 
80 	for (idx = 0; idx < BMISS_STATS_RSSI_SAMPLES_MAX; idx++) {
81 		if ((PAGE_SIZE - ret) <= 0)
82 			return ret;
83 
84 		ret += scnprintf(
85 			buf + ret, PAGE_SIZE - ret,
86 			"rssi_sample%d-rssi:%d\n", idx,
87 			ev_ptr->bmiss_infra_cp_stats->rssi_samples[idx].rssi);
88 		if ((PAGE_SIZE - ret) <= 0)
89 			return ret;
90 
91 		ret += scnprintf(
92 			buf + ret, PAGE_SIZE - ret,
93 			"rssi_sample%d-sample_time:%u\n", idx,
94 			ev_ptr->bmiss_infra_cp_stats->rssi_samples[idx].sample_time);
95 	}
96 	if ((PAGE_SIZE - ret) <= 0)
97 		return ret;
98 
99 	ret += scnprintf(buf + ret, PAGE_SIZE - ret,
100 			 "rssi_sample_curr_index:%u\n"
101 			 "num_first_bmiss:%u\n"
102 			 "num_final_bmiss:%u\n"
103 			 "num_null_sent_in_first_bmiss:%u\n"
104 			 "num_null_failed_in_first_bmiss:%u\n"
105 			 "num_null_sent_in_final_bmiss:%u\n"
106 			 "num_null_failed_in_final_bmiss:%u\n"
107 			 "cons_bmiss_stats.num_of_bmiss_sequences:%u\n"
108 			 "cons_bmiss_stats.num_bitmask_wraparound:%u\n"
109 			 "cons_bmiss_stats.num_bcn_hist_lost:%u\n",
110 			 ev_ptr->bmiss_infra_cp_stats->rssi_sample_curr_index,
111 			 ev_ptr->bmiss_infra_cp_stats->num_first_bmiss,
112 			 ev_ptr->bmiss_infra_cp_stats->num_final_bmiss,
113 			 ev_ptr->bmiss_infra_cp_stats->num_null_sent_in_first_bmiss,
114 			 ev_ptr->bmiss_infra_cp_stats->num_null_failed_in_first_bmiss,
115 			 ev_ptr->bmiss_infra_cp_stats->num_null_sent_in_final_bmiss,
116 			 ev_ptr->bmiss_infra_cp_stats->num_null_failed_in_final_bmiss,
117 			 ev_ptr->bmiss_infra_cp_stats->cons_bmiss_stats.num_of_bmiss_sequences,
118 			 ev_ptr->bmiss_infra_cp_stats->cons_bmiss_stats.num_bitmask_wraparound,
119 			 ev_ptr->bmiss_infra_cp_stats->cons_bmiss_stats.num_bcn_hist_lost);
120 
121 	qdf_mem_free(ev_ptr->bmiss_infra_cp_stats);
122 	qdf_mem_free(ev_ptr);
123 	return ret;
124 }
125 
126 static ssize_t
hdd_sysfs_bmiss_show(struct device * dev,struct device_attribute * attr,char * buf)127 hdd_sysfs_bmiss_show(struct device *dev, struct device_attribute *attr,
128 		     char *buf)
129 {
130 	struct net_device *net_dev;
131 	struct osif_vdev_sync *vdev_sync;
132 	ssize_t err_size;
133 
134 	net_dev = container_of(dev, struct net_device, dev);
135 	err_size = osif_vdev_sync_op_start(net_dev, &vdev_sync);
136 	if (err_size)
137 		return err_size;
138 
139 	err_size = __hdd_sysfs_bmiss_show(net_dev, buf);
140 	osif_vdev_sync_op_stop(vdev_sync);
141 	return err_size;
142 }
143 
144 static DEVICE_ATTR(bmiss, 0440, hdd_sysfs_bmiss_show, NULL);
145 
hdd_sysfs_bmiss_create(struct hdd_adapter * adapter)146 int hdd_sysfs_bmiss_create(struct hdd_adapter *adapter)
147 {
148 	int error;
149 
150 	error = device_create_file(&adapter->dev->dev,
151 				   &dev_attr_bmiss);
152 	if (!error)
153 		hdd_err("could not create bmiss sysfs file");
154 	return error;
155 }
156 
hdd_sysfs_bmiss_destroy(struct hdd_adapter * adapter)157 void hdd_sysfs_bmiss_destroy(struct hdd_adapter *adapter)
158 {
159 	device_remove_file(&adapter->dev->dev, &dev_attr_bmiss);
160 }
161 
162