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