1 /* 2 * Copyright (c) 2014-2019 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 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 114 "%s: Unloading/Loading in Progress. Ignore!!!", 115 __func__); 116 return; 117 } 118 119 if (nl_srv_is_initialized() != 0) 120 return; 121 122 if (cds_is_multicast_logging()) { 123 data_len = pHdr->len; 124 125 total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len; 126 127 pBuf = (uint8_t *) qdf_mem_malloc(total_len); 128 129 if (!pBuf) 130 return; 131 132 wmsg = (tAniHdr *) pBuf; 133 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; 134 wmsg->length = total_len; 135 wmsg->length = DIAG_SWAP16(wmsg->length); 136 pBuf += sizeof(tAniHdr); 137 138 /* Diag Type events or log */ 139 *(uint32_t *) pBuf = DIAG_TYPE_LOGS; 140 pBuf += sizeof(uint32_t); 141 142 memcpy(pBuf, pHdr, data_len); 143 ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC, 144 INVALID_PID); 145 qdf_mem_free((void *)wmsg); 146 } 147 return; 148 } 149 150 /** 151 * host_diag_log_wlock() - This function is used to send wake lock diag events 152 * @reason: Reason why the wakelock was taken or released 153 * @wake_lock_name: Function in which the wakelock was taken or released 154 * @timeout: Timeout value in case of timed wakelocks 155 * @status: Status field indicating whether the wake lock was taken/released 156 * 157 * This function is used to send wake lock diag events to user space 158 * 159 * Return: None 160 * 161 */ 162 void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name, 163 uint32_t timeout, uint32_t status) 164 { 165 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 166 struct host_event_wlan_wake_lock); 167 168 if ((nl_srv_is_initialized() != 0) || 169 (cds_is_wakelock_enabled() == false)) 170 return; 171 172 wlan_diag_event.status = status; 173 wlan_diag_event.reason = reason; 174 wlan_diag_event.timeout = timeout; 175 wlan_diag_event.name_len = strlen(wake_lock_name); 176 strlcpy(&wlan_diag_event.name[0], 177 wake_lock_name, 178 wlan_diag_event.name_len+1); 179 180 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK); 181 } 182 183 /**--------------------------------------------------------------------------- 184 185 \brief host_diag_event_report_payload() - 186 187 This function sends the event data to the ptt socket app only if it is 188 registered with the driver. 189 190 \param - ptr - Pointer to the log header type. 191 192 \return - None 193 194 --------------------------------------------------------------------------*/ 195 196 void host_diag_event_report_payload(uint16_t event_Id, uint16_t length, 197 void *pPayload) 198 { 199 tAniHdr *wmsg = NULL; 200 uint8_t *pBuf; 201 event_report_t *pEvent_report; 202 uint16_t total_len; 203 204 if (cds_is_load_or_unload_in_progress()) { 205 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 206 "%s: Unloading/Loading in Progress. Ignore!!!", 207 __func__); 208 return; 209 } 210 211 if (nl_srv_is_initialized() != 0) 212 return; 213 214 if (cds_is_multicast_logging()) { 215 total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length; 216 217 pBuf = (uint8_t *) qdf_mem_malloc(total_len); 218 219 if (!pBuf) 220 return; 221 222 wmsg = (tAniHdr *) pBuf; 223 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; 224 wmsg->length = total_len; 225 wmsg->length = DIAG_SWAP16(wmsg->length); 226 pBuf += sizeof(tAniHdr); 227 228 pEvent_report = (event_report_t *) pBuf; 229 pEvent_report->diag_type = DIAG_TYPE_EVENTS; 230 pEvent_report->event_id = event_Id; 231 pEvent_report->length = length; 232 233 pBuf += sizeof(event_report_t); 234 235 memcpy(pBuf, pPayload, length); 236 237 if (ptt_sock_send_msg_to_app 238 (wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID) < 0) { 239 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN, 240 "Ptt Socket error sending message to the app!!"); 241 qdf_mem_free((void *)wmsg); 242 return; 243 } 244 245 qdf_mem_free((void *)wmsg); 246 } 247 248 return; 249 250 } 251 252 /** 253 * host_log_low_resource_failure() - This function is used to send low 254 * resource failure event 255 * @event_sub_type: Reason why the failure was observed 256 * 257 * This function is used to send low resource failure events to user space 258 * 259 * Return: None 260 * 261 */ 262 void host_log_low_resource_failure(uint8_t event_sub_type) 263 { 264 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 265 struct host_event_wlan_low_resource_failure); 266 267 wlan_diag_event.event_sub_type = event_sub_type; 268 269 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 270 EVENT_WLAN_LOW_RESOURCE_FAILURE); 271 } 272 273 void host_log_rsn_info(uint8_t *ucast_cipher, uint8_t *mcast_cipher, 274 uint8_t *akm_suite, uint8_t *group_mgmt) 275 { 276 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 277 struct event_wlan_csr_rsn_info); 278 279 qdf_mem_copy(wlan_diag_event.ucast_cipher, ucast_cipher, 280 RSN_OUI_SIZE); 281 qdf_mem_copy(wlan_diag_event.mcast_cipher, mcast_cipher, 282 RSN_OUI_SIZE); 283 qdf_mem_copy(wlan_diag_event.akm_suite, akm_suite, 284 RSN_OUI_SIZE); 285 qdf_mem_copy(wlan_diag_event.group_mgmt, group_mgmt, 286 RSN_OUI_SIZE); 287 288 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 289 EVENT_WLAN_RSN_INFO); 290 } 291 292 void 293 host_log_wlan_auth_info(uint16_t auth_algo_num, uint16_t auth_tx_seq_num, 294 uint16_t auth_status_code) 295 { 296 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 297 struct event_wlan_lim_auth_info); 298 299 wlan_diag_event.auth_algo_num = auth_algo_num; 300 wlan_diag_event.auth_transaction_seq_num = auth_tx_seq_num; 301 wlan_diag_event.auth_status_code = auth_status_code; 302 303 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 304 EVENT_WLAN_AUTH_INFO); 305 } 306 307 #ifdef FEATURE_WLAN_DIAG_SUPPORT 308 /** 309 * qdf_wow_wakeup_host_event()- send wow wakeup event 310 * @wow_wakeup_cause: WOW wakeup reason code 311 * 312 * This function sends wow wakeup reason code diag event 313 * 314 * Return: void. 315 */ 316 void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause) 317 { 318 WLAN_HOST_DIAG_EVENT_DEF(wowRequest, 319 host_event_wlan_powersave_wow_payload_type); 320 qdf_mem_zero(&wowRequest, sizeof(wowRequest)); 321 322 wowRequest.event_subtype = WLAN_WOW_WAKEUP; 323 wowRequest.wow_wakeup_cause = wow_wakeup_cause; 324 WLAN_HOST_DIAG_EVENT_REPORT(&wowRequest, 325 EVENT_WLAN_POWERSAVE_WOW); 326 } 327 328 void host_log_acs_req_event(uint8_t *intf, const uint8_t *hw_mode, uint16_t bw, 329 uint8_t ht, uint8_t vht, uint16_t chan_start, 330 uint16_t chan_end) 331 { 332 WLAN_HOST_DIAG_EVENT_DEF(acs_req, struct host_event_wlan_acs_req); 333 334 qdf_str_lcopy(acs_req.intf, intf, HOST_EVENT_INTF_STR_LEN); 335 qdf_str_lcopy(acs_req.hw_mode, hw_mode, HOST_EVENT_HW_MODE_STR_LEN); 336 acs_req.bw = bw; 337 acs_req.ht = ht; 338 acs_req.vht = vht; 339 acs_req.chan_start = chan_start; 340 acs_req.chan_end = chan_end; 341 342 WLAN_HOST_DIAG_EVENT_REPORT(&acs_req, EVENT_WLAN_ACS_REQ); 343 } 344 345 void host_log_acs_scan_start(uint32_t scan_id, uint8_t vdev_id) 346 { 347 WLAN_HOST_DIAG_EVENT_DEF(acs_scan_start, 348 struct host_event_wlan_acs_scan_start); 349 350 acs_scan_start.scan_id = scan_id; 351 acs_scan_start.vdev_id = vdev_id; 352 353 WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_start, 354 EVENT_WLAN_ACS_SCAN_START); 355 } 356 357 void host_log_acs_scan_done(const uint8_t *status, 358 uint8_t vdev_id, uint32_t scan_id) 359 { 360 WLAN_HOST_DIAG_EVENT_DEF(acs_scan_done, 361 struct host_event_wlan_acs_scan_done); 362 363 qdf_str_lcopy(acs_scan_done.status, status, HOST_EVENT_STATUS_STR_LEN); 364 acs_scan_done.vdev_id = vdev_id; 365 acs_scan_done.scan_id = scan_id; 366 367 WLAN_HOST_DIAG_EVENT_REPORT(&acs_scan_done, EVENT_WLAN_ACS_SCAN_DONE); 368 } 369 370 void host_log_acs_chan_spect_weight(uint16_t chan, uint16_t weight, 371 int32_t rssi, uint16_t bss_count) 372 { 373 WLAN_HOST_DIAG_EVENT_DEF( 374 acs_chan_spect_weight, 375 struct host_event_wlan_acs_chan_spectral_weight); 376 377 acs_chan_spect_weight.chan = chan; 378 acs_chan_spect_weight.weight = weight; 379 acs_chan_spect_weight.rssi = rssi; 380 acs_chan_spect_weight.bss_count = bss_count; 381 382 WLAN_HOST_DIAG_EVENT_REPORT(&acs_chan_spect_weight, 383 EVENT_WLAN_ACS_CHANNEL_SPECTRAL_WEIGHT); 384 } 385 386 void host_log_acs_best_chan(uint16_t chan, uint16_t weight) 387 { 388 WLAN_HOST_DIAG_EVENT_DEF(acs_best_chan, 389 struct host_event_wlan_acs_best_chan); 390 391 acs_best_chan.chan = chan; 392 acs_best_chan.weight = weight; 393 394 WLAN_HOST_DIAG_EVENT_REPORT(&acs_best_chan, 395 EVENT_WLAN_ACS_BEST_CHANNEL); 396 } 397 398 #endif 399