1 /*
2 * Copyright (c) 2014-2021 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 FILE: host_diag_log.c
21
22 OVERVIEW: This source file contains definitions for WLAN UTIL diag APIs
23
24 DEPENDENCIES:
25 ============================================================================*/
26
27 #include "qdf_types.h"
28 #include "i_host_diag_core_log.h"
29 #include "host_diag_core_event.h"
30 #include "wlan_nlink_common.h"
31 #include "cds_sched.h"
32 #include "wlan_ptt_sock_svc.h"
33 #include "wlan_nlink_srv.h"
34 #include "cds_api.h"
35 #include "wlan_ps_wow_diag.h"
36 #include "qdf_str.h"
37
38 #define PTT_MSG_DIAG_CMDS_TYPE (0x5050)
39
40 #define DIAG_TYPE_LOGS (1)
41 #define DIAG_TYPE_EVENTS (2)
42
43 #define DIAG_SWAP16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8))
44
45 typedef struct event_report_s {
46 uint32_t diag_type;
47 uint16_t event_id;
48 uint16_t length;
49 } event_report_t;
50
51 /**---------------------------------------------------------------------------
52
53 \brief host_diag_log_set_code() -
54
55 This function sets the logging code in the given log record.
56
57 \param - ptr - Pointer to the log header type.
58 - code - log code.
59 \return - None
60
61 --------------------------------------------------------------------------*/
62
host_diag_log_set_code(void * ptr,uint16_t code)63 void host_diag_log_set_code(void *ptr, uint16_t code)
64 {
65 if (ptr) {
66 /* All log packets are required to start with 'log_header_type' */
67 ((log_hdr_type *) ptr)->code = code;
68 }
69 }
70
71 /**---------------------------------------------------------------------------
72
73 \brief host_diag_log_set_length() -
74
75 This function sets the length field in the given log record.
76
77 \param - ptr - Pointer to the log header type.
78 - length - log length.
79
80 \return - None
81
82 --------------------------------------------------------------------------*/
83
host_diag_log_set_length(void * ptr,uint16_t length)84 void host_diag_log_set_length(void *ptr, uint16_t length)
85 {
86 if (ptr) {
87 /* All log packets are required to start with 'log_header_type' */
88 ((log_hdr_type *) ptr)->len = (uint16_t) length;
89 }
90 }
91
92 /**---------------------------------------------------------------------------
93
94 \brief host_diag_log_submit() -
95
96 This function sends the log data to the ptt socket app only if it is registered with the driver.
97
98 \param - ptr - Pointer to the log header type.
99
100 \return - None
101
102 --------------------------------------------------------------------------*/
103
host_diag_log_submit(void * plog_hdr_ptr)104 void host_diag_log_submit(void *plog_hdr_ptr)
105 {
106 log_hdr_type *pHdr = (log_hdr_type *) plog_hdr_ptr;
107 tAniHdr *wmsg = NULL;
108 uint8_t *pBuf;
109 uint16_t data_len;
110 uint16_t total_len;
111
112 if (cds_is_load_or_unload_in_progress())
113 return;
114
115 if (nl_srv_is_initialized() != 0)
116 return;
117
118 if (cds_is_multicast_logging()) {
119 data_len = pHdr->len;
120
121 total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len;
122
123 pBuf = (uint8_t *) qdf_mem_malloc(total_len);
124
125 if (!pBuf)
126 return;
127
128 wmsg = (tAniHdr *) pBuf;
129 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
130 wmsg->length = total_len;
131 wmsg->length = DIAG_SWAP16(wmsg->length);
132 pBuf += sizeof(tAniHdr);
133
134 /* Diag Type events or log */
135 *(uint32_t *) pBuf = DIAG_TYPE_LOGS;
136 pBuf += sizeof(uint32_t);
137
138 memcpy(pBuf, pHdr, data_len);
139 ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC,
140 INVALID_PID);
141 qdf_mem_free((void *)wmsg);
142 }
143 return;
144 }
145
146 /**
147 * host_diag_log_wlock() - This function is used to send wake lock diag events
148 * @reason: Reason why the wakelock was taken or released
149 * @wake_lock_name: Function in which the wakelock was taken or released
150 * @timeout: Timeout value in case of timed wakelocks
151 * @status: Status field indicating whether the wake lock was taken/released
152 *
153 * This function is used to send wake lock diag events to user space
154 *
155 * Return: None
156 *
157 */
host_diag_log_wlock(uint32_t reason,const char * wake_lock_name,uint32_t timeout,uint32_t status)158 void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name,
159 uint32_t timeout, uint32_t status)
160 {
161 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
162 struct host_event_wlan_wake_lock);
163
164 if ((nl_srv_is_initialized() != 0) ||
165 (cds_is_wakelock_enabled() == false))
166 return;
167
168 wlan_diag_event.status = status;
169 wlan_diag_event.reason = reason;
170 wlan_diag_event.timeout = timeout;
171 wlan_diag_event.name_len = strlen(wake_lock_name);
172 strlcpy(&wlan_diag_event.name[0],
173 wake_lock_name,
174 wlan_diag_event.name_len+1);
175
176 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK);
177 }
178
179 /**---------------------------------------------------------------------------
180
181 \brief host_diag_event_report_payload() -
182
183 This function sends the event data to the ptt socket app only if it is
184 registered with the driver.
185
186 \param - ptr - Pointer to the log header type.
187
188 \return - None
189
190 --------------------------------------------------------------------------*/
191
host_diag_event_report_payload(uint16_t event_Id,uint16_t length,void * pPayload)192 void host_diag_event_report_payload(uint16_t event_Id, uint16_t length,
193 void *pPayload)
194 {
195 tAniHdr *wmsg = NULL;
196 uint8_t *pBuf;
197 event_report_t *pEvent_report;
198 uint16_t total_len;
199 int ret;
200
201 if (cds_is_load_or_unload_in_progress())
202 return;
203
204 if (nl_srv_is_initialized() != 0)
205 return;
206
207 if (cds_is_multicast_logging()) {
208 total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length;
209
210 pBuf = (uint8_t *) qdf_mem_malloc(total_len);
211
212 if (!pBuf)
213 return;
214
215 wmsg = (tAniHdr *) pBuf;
216 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE;
217 wmsg->length = total_len;
218 wmsg->length = DIAG_SWAP16(wmsg->length);
219 pBuf += sizeof(tAniHdr);
220
221 pEvent_report = (event_report_t *) pBuf;
222 pEvent_report->diag_type = DIAG_TYPE_EVENTS;
223 pEvent_report->event_id = event_Id;
224 pEvent_report->length = length;
225
226 pBuf += sizeof(event_report_t);
227
228 memcpy(pBuf, pPayload, length);
229
230 ret = ptt_sock_send_msg_to_app
231 (wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID);
232 if ((ret < 0) && (ret != -ESRCH)) {
233 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN,
234 "Ptt Socket error sending message to the app!!");
235 qdf_mem_free((void *)wmsg);
236 return;
237 }
238
239 qdf_mem_free((void *)wmsg);
240 }
241
242 return;
243
244 }
245
246 /**
247 * host_log_low_resource_failure() - This function is used to send low
248 * resource failure event
249 * @event_sub_type: Reason why the failure was observed
250 *
251 * This function is used to send low resource failure events to user space
252 *
253 * Return: None
254 *
255 */
host_log_low_resource_failure(uint8_t event_sub_type)256 void host_log_low_resource_failure(uint8_t event_sub_type)
257 {
258 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
259 struct host_event_wlan_low_resource_failure);
260
261 wlan_diag_event.event_sub_type = event_sub_type;
262
263 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
264 EVENT_WLAN_LOW_RESOURCE_FAILURE);
265 }
266
host_log_rsn_info(uint8_t * ucast_cipher,uint8_t * mcast_cipher,uint8_t * akm_suite,uint8_t * group_mgmt)267 void host_log_rsn_info(uint8_t *ucast_cipher, uint8_t *mcast_cipher,
268 uint8_t *akm_suite, uint8_t *group_mgmt)
269 {
270 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
271 struct event_wlan_csr_rsn_info);
272
273 qdf_mem_copy(wlan_diag_event.ucast_cipher, ucast_cipher,
274 RSN_OUI_SIZE);
275 qdf_mem_copy(wlan_diag_event.mcast_cipher, mcast_cipher,
276 RSN_OUI_SIZE);
277 qdf_mem_copy(wlan_diag_event.akm_suite, akm_suite,
278 RSN_OUI_SIZE);
279 qdf_mem_copy(wlan_diag_event.group_mgmt, group_mgmt,
280 RSN_OUI_SIZE);
281
282 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
283 EVENT_WLAN_RSN_INFO);
284 }
285
286 void
host_log_wlan_auth_info(uint16_t auth_algo_num,uint16_t auth_tx_seq_num,uint16_t auth_status_code)287 host_log_wlan_auth_info(uint16_t auth_algo_num, uint16_t auth_tx_seq_num,
288 uint16_t auth_status_code)
289 {
290 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
291 struct event_wlan_lim_auth_info);
292
293 wlan_diag_event.auth_algo_num = auth_algo_num;
294 wlan_diag_event.auth_transaction_seq_num = auth_tx_seq_num;
295 wlan_diag_event.auth_status_code = auth_status_code;
296
297 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
298 EVENT_WLAN_AUTH_INFO);
299 }
300
301 #ifdef FEATURE_WLAN_DIAG_SUPPORT
302 /**
303 * qdf_wow_wakeup_host_event()- send wow wakeup event
304 * @wow_wakeup_cause: WOW wakeup reason code
305 *
306 * This function sends wow wakeup reason code diag event
307 *
308 * Return: void.
309 */
qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause)310 void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause)
311 {
312 WLAN_HOST_DIAG_EVENT_DEF(wowRequest,
313 host_event_wlan_powersave_wow_payload_type);
314 qdf_mem_zero(&wowRequest, sizeof(wowRequest));
315
316 wowRequest.event_subtype = WLAN_WOW_WAKEUP;
317 wowRequest.wow_wakeup_cause = wow_wakeup_cause;
318 WLAN_HOST_DIAG_EVENT_REPORT(&wowRequest,
319 EVENT_WLAN_POWERSAVE_WOW);
320 }
321
host_log_acs_req_event(uint8_t * intf,const uint8_t * hw_mode,uint16_t bw,uint8_t ht,uint8_t vht,uint16_t chan_start,uint16_t chan_end)322 void host_log_acs_req_event(uint8_t *intf, const uint8_t *hw_mode, uint16_t bw,
323 uint8_t ht, uint8_t vht, uint16_t chan_start,
324 uint16_t chan_end)
325 {
326 WLAN_HOST_DIAG_EVENT_DEF(acs_req, struct host_event_wlan_acs_req);
327
328 qdf_str_lcopy(acs_req.intf, intf, HOST_EVENT_INTF_STR_LEN);
329 qdf_str_lcopy(acs_req.hw_mode, hw_mode, HOST_EVENT_HW_MODE_STR_LEN);
330 acs_req.bw = bw;
331 acs_req.ht = ht;
332 acs_req.vht = vht;
333 acs_req.chan_start = chan_start;
334 acs_req.chan_end = chan_end;
335
336 WLAN_HOST_DIAG_EVENT_REPORT(&acs_req, EVENT_WLAN_ACS_REQ);
337 }
338
host_log_acs_scan_start(uint32_t scan_id,uint8_t vdev_id)339 void host_log_acs_scan_start(uint32_t scan_id, uint8_t vdev_id)
340 {
341 WLAN_HOST_DIAG_EVENT_DEF(acs_scan_start,
342 struct host_event_wlan_acs_scan_start);
343
344 acs_scan_start.scan_id = scan_id;
345 acs_scan_start.vdev_id = vdev_id;
346
347 WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_start,
348 EVENT_WLAN_ACS_SCAN_START);
349 }
350
host_log_acs_scan_done(const uint8_t * status,uint8_t vdev_id,uint32_t scan_id)351 void host_log_acs_scan_done(const uint8_t *status,
352 uint8_t vdev_id, uint32_t scan_id)
353 {
354 WLAN_HOST_DIAG_EVENT_DEF(acs_scan_done,
355 struct host_event_wlan_acs_scan_done);
356
357 qdf_str_lcopy(acs_scan_done.status, status, HOST_EVENT_STATUS_STR_LEN);
358 acs_scan_done.vdev_id = vdev_id;
359 acs_scan_done.scan_id = scan_id;
360
361 WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_done, EVENT_WLAN_ACS_SCAN_DONE);
362 }
363
host_log_acs_chan_spect_weight(uint16_t chan,uint16_t weight,int32_t rssi,uint16_t bss_count)364 void host_log_acs_chan_spect_weight(uint16_t chan, uint16_t weight,
365 int32_t rssi, uint16_t bss_count)
366 {
367 WLAN_HOST_DIAG_EVENT_DEF(
368 acs_chan_spect_weight,
369 struct host_event_wlan_acs_chan_spectral_weight);
370
371 acs_chan_spect_weight.chan = chan;
372 acs_chan_spect_weight.weight = weight;
373 acs_chan_spect_weight.rssi = rssi;
374 acs_chan_spect_weight.bss_count = bss_count;
375
376 WLAN_HOST_DIAG_EVENT_REPORT(&acs_chan_spect_weight,
377 EVENT_WLAN_ACS_CHANNEL_SPECTRAL_WEIGHT);
378 }
379
host_log_acs_best_chan(uint16_t chan,uint16_t weight)380 void host_log_acs_best_chan(uint16_t chan, uint16_t weight)
381 {
382 WLAN_HOST_DIAG_EVENT_DEF(acs_best_chan,
383 struct host_event_wlan_acs_best_chan);
384
385 acs_best_chan.chan = chan;
386 acs_best_chan.weight = weight;
387
388 WLAN_HOST_DIAG_EVENT_REPORT(&acs_best_chan,
389 EVENT_WLAN_ACS_BEST_CHANNEL);
390 }
391
host_log_device_status(uint16_t status_code)392 void host_log_device_status(uint16_t status_code)
393 {
394 WLAN_HOST_DIAG_EVENT_DEF(driver_status,
395 host_event_wlan_bringup_status_payload_type);
396
397 driver_status.wlan_status = status_code;
398
399 /* driver version not used yet, fill properly if need later */
400 qdf_mem_zero(driver_status.driver_version,
401 sizeof(driver_status.driver_version));
402
403 WLAN_HOST_DIAG_EVENT_REPORT(&driver_status,
404 EVENT_WLAN_BRINGUP_STATUS);
405 }
406
407 #endif
408