xref: /wlan-dirver/qca-wifi-host-cmn/utils/host_diag_log/src/host_diag_log.c (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
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