1 /* 2 * Copyright (c) 2014-2017 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 37 #define PTT_MSG_DIAG_CMDS_TYPE (0x5050) 38 39 #define DIAG_TYPE_LOGS (1) 40 #define DIAG_TYPE_EVENTS (2) 41 42 #define DIAG_SWAP16(A) ((((uint16_t)(A) & 0xff00) >> 8) | (((uint16_t)(A) & 0x00ff) << 8)) 43 44 typedef struct event_report_s { 45 uint32_t diag_type; 46 uint16_t event_id; 47 uint16_t length; 48 } event_report_t; 49 50 /**--------------------------------------------------------------------------- 51 52 \brief host_diag_log_set_code() - 53 54 This function sets the logging code in the given log record. 55 56 \param - ptr - Pointer to the log header type. 57 - code - log code. 58 \return - None 59 60 --------------------------------------------------------------------------*/ 61 62 void host_diag_log_set_code(void *ptr, uint16_t code) 63 { 64 if (ptr) { 65 /* All log packets are required to start with 'log_header_type' */ 66 ((log_hdr_type *) ptr)->code = code; 67 } 68 } 69 70 /**--------------------------------------------------------------------------- 71 72 \brief host_diag_log_set_length() - 73 74 This function sets the length field in the given log record. 75 76 \param - ptr - Pointer to the log header type. 77 - length - log length. 78 79 \return - None 80 81 --------------------------------------------------------------------------*/ 82 83 void host_diag_log_set_length(void *ptr, uint16_t length) 84 { 85 if (ptr) { 86 /* All log packets are required to start with 'log_header_type' */ 87 ((log_hdr_type *) ptr)->len = (uint16_t) length; 88 } 89 } 90 91 /**--------------------------------------------------------------------------- 92 93 \brief host_diag_log_submit() - 94 95 This function sends the log data to the ptt socket app only if it is registered with the driver. 96 97 \param - ptr - Pointer to the log header type. 98 99 \return - None 100 101 --------------------------------------------------------------------------*/ 102 103 void host_diag_log_submit(void *plog_hdr_ptr) 104 { 105 log_hdr_type *pHdr = (log_hdr_type *) plog_hdr_ptr; 106 tAniHdr *wmsg = NULL; 107 uint8_t *pBuf; 108 uint16_t data_len; 109 uint16_t total_len; 110 111 if (cds_is_load_or_unload_in_progress()) { 112 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 113 "%s: Unloading/Loading in Progress. Ignore!!!", 114 __func__); 115 return; 116 } 117 118 if (nl_srv_is_initialized() != 0) 119 return; 120 121 if (cds_is_multicast_logging()) { 122 data_len = pHdr->len; 123 124 total_len = sizeof(tAniHdr) + sizeof(uint32_t) + data_len; 125 126 pBuf = (uint8_t *) qdf_mem_malloc(total_len); 127 128 if (!pBuf) { 129 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, 130 "qdf_mem_malloc failed"); 131 return; 132 } 133 134 wmsg = (tAniHdr *) pBuf; 135 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; 136 wmsg->length = total_len; 137 wmsg->length = DIAG_SWAP16(wmsg->length); 138 pBuf += sizeof(tAniHdr); 139 140 /* Diag Type events or log */ 141 *(uint32_t *) pBuf = DIAG_TYPE_LOGS; 142 pBuf += sizeof(uint32_t); 143 144 memcpy(pBuf, pHdr, data_len); 145 ptt_sock_send_msg_to_app (wmsg, 0, ANI_NL_MSG_PUMAC, 146 INVALID_PID); 147 qdf_mem_free((void *)wmsg); 148 } 149 return; 150 } 151 152 /** 153 * host_diag_log_wlock() - This function is used to send wake lock diag events 154 * @reason: Reason why the wakelock was taken or released 155 * @wake_lock_name: Function in which the wakelock was taken or released 156 * @timeout: Timeout value in case of timed wakelocks 157 * @status: Status field indicating whether the wake lock was taken/released 158 * 159 * This function is used to send wake lock diag events to user space 160 * 161 * Return: None 162 * 163 */ 164 void host_diag_log_wlock(uint32_t reason, const char *wake_lock_name, 165 uint32_t timeout, uint32_t status) 166 { 167 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 168 struct host_event_wlan_wake_lock); 169 170 if ((nl_srv_is_initialized() != 0) || 171 (cds_is_wakelock_enabled() == false)) 172 return; 173 174 wlan_diag_event.status = status; 175 wlan_diag_event.reason = reason; 176 wlan_diag_event.timeout = timeout; 177 wlan_diag_event.name_len = strlen(wake_lock_name); 178 strlcpy(&wlan_diag_event.name[0], 179 wake_lock_name, 180 wlan_diag_event.name_len+1); 181 182 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_WAKE_LOCK); 183 } 184 185 /**--------------------------------------------------------------------------- 186 187 \brief host_diag_event_report_payload() - 188 189 This function sends the event data to the ptt socket app only if it is 190 registered with the driver. 191 192 \param - ptr - Pointer to the log header type. 193 194 \return - None 195 196 --------------------------------------------------------------------------*/ 197 198 void host_diag_event_report_payload(uint16_t event_Id, uint16_t length, 199 void *pPayload) 200 { 201 tAniHdr *wmsg = NULL; 202 uint8_t *pBuf; 203 event_report_t *pEvent_report; 204 uint16_t total_len; 205 206 if (cds_is_load_or_unload_in_progress()) { 207 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 208 "%s: Unloading/Loading in Progress. Ignore!!!", 209 __func__); 210 return; 211 } 212 213 if (nl_srv_is_initialized() != 0) 214 return; 215 216 if (cds_is_multicast_logging()) { 217 total_len = sizeof(tAniHdr) + sizeof(event_report_t) + length; 218 219 pBuf = (uint8_t *) qdf_mem_malloc(total_len); 220 221 if (!pBuf) { 222 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, 223 "qdf_mem_malloc failed"); 224 return; 225 } 226 wmsg = (tAniHdr *) pBuf; 227 wmsg->type = PTT_MSG_DIAG_CMDS_TYPE; 228 wmsg->length = total_len; 229 wmsg->length = DIAG_SWAP16(wmsg->length); 230 pBuf += sizeof(tAniHdr); 231 232 pEvent_report = (event_report_t *) pBuf; 233 pEvent_report->diag_type = DIAG_TYPE_EVENTS; 234 pEvent_report->event_id = event_Id; 235 pEvent_report->length = length; 236 237 pBuf += sizeof(event_report_t); 238 239 memcpy(pBuf, pPayload, length); 240 241 if (ptt_sock_send_msg_to_app 242 (wmsg, 0, ANI_NL_MSG_PUMAC, INVALID_PID) < 0) { 243 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN, 244 "Ptt Socket error sending message to the app!!"); 245 qdf_mem_free((void *)wmsg); 246 return; 247 } 248 249 qdf_mem_free((void *)wmsg); 250 } 251 252 return; 253 254 } 255 256 /** 257 * host_log_low_resource_failure() - This function is used to send low 258 * resource failure event 259 * @event_sub_type: Reason why the failure was observed 260 * 261 * This function is used to send low resource failure events to user space 262 * 263 * Return: None 264 * 265 */ 266 void host_log_low_resource_failure(uint8_t event_sub_type) 267 { 268 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 269 struct host_event_wlan_low_resource_failure); 270 271 wlan_diag_event.event_sub_type = event_sub_type; 272 273 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 274 EVENT_WLAN_LOW_RESOURCE_FAILURE); 275 } 276 277 #ifdef FEATURE_WLAN_DIAG_SUPPORT 278 /** 279 * qdf_wow_wakeup_host_event()- send wow wakeup event 280 * @wow_wakeup_cause: WOW wakeup reason code 281 * 282 * This function sends wow wakeup reason code diag event 283 * 284 * Return: void. 285 */ 286 void qdf_wow_wakeup_host_event(uint8_t wow_wakeup_cause) 287 { 288 WLAN_HOST_DIAG_EVENT_DEF(wowRequest, 289 host_event_wlan_powersave_wow_payload_type); 290 qdf_mem_zero(&wowRequest, sizeof(wowRequest)); 291 292 wowRequest.event_subtype = WLAN_WOW_WAKEUP; 293 wowRequest.wow_wakeup_cause = wow_wakeup_cause; 294 WLAN_HOST_DIAG_EVENT_REPORT(&wowRequest, 295 EVENT_WLAN_POWERSAVE_WOW); 296 } 297 #endif 298