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 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 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 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 */ 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 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 */ 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 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 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 */ 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 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 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 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 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 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 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