1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_data_stall_detection.c
22  *
23  * WLAN Host Device Driver Data Stall detection API implementation
24  */
25 
26 #include <wlan_qct_sys.h>
27 #include <scheduler_api.h>
28 #include "wlan_hdd_data_stall_detection.h"
29 #include "wlan_hdd_main.h"
30 #include "cdp_txrx_cmn.h"
31 #include "cdp_txrx_misc.h"
32 #include "ol_txrx_types.h"
33 #include "ol_defines.h"
34 #ifdef FEATURE_WLAN_DIAG_SUPPORT
35 #include "host_diag_core_event.h"
36 #include "host_diag_core_log.h"
37 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
38 
39 #ifdef FEATURE_WLAN_DIAG_SUPPORT
40 
41 /**
42  * hdd_data_stall_send_event()- send data stall information
43  * @reason: data stall event subtype
44  * This Function sends data stall status diag event
45  *
46  * Return: void.
47  */
hdd_data_stall_send_event(uint32_t reason)48 static void hdd_data_stall_send_event(uint32_t reason)
49 {
50 	WLAN_HOST_DIAG_EVENT_DEF(sta_data_stall,
51 				struct host_event_wlan_datastall);
52 	qdf_mem_zero(&sta_data_stall, sizeof(sta_data_stall));
53 	sta_data_stall.reason = reason;
54 	hdd_debug("Posting data stall event %x", reason);
55 	WLAN_HOST_DIAG_EVENT_REPORT(&sta_data_stall, EVENT_WLAN_STA_DATASTALL);
56 
57 	cdp_display_stats(cds_get_context(QDF_MODULE_ID_SOC),
58 			  CDP_TXRX_PATH_STATS,
59 			  QDF_STATS_VERBOSITY_LEVEL_LOW);
60 }
61 #else
hdd_data_stall_send_event(uint32_t reason)62 static inline void hdd_data_stall_send_event(uint32_t reason)
63 {
64 }
65 #endif
66 
67 /**
68  * hdd_data_stall_process_event() - Process data stall event
69  * @msg: data stall message
70  *
71  * Process data stall message
72  *
73  * Return: QDF_STATUS
74  */
hdd_data_stall_process_event(struct scheduler_msg * msg)75 static QDF_STATUS hdd_data_stall_process_event(struct scheduler_msg *msg)
76 {
77 	struct data_stall_event_info *data_stall_info;
78 
79 	if (!msg)
80 		return QDF_STATUS_E_FAILURE;
81 
82 	data_stall_info = msg->bodyptr;
83 
84 	hdd_data_stall_send_event(data_stall_info->data_stall_type);
85 
86 	return QDF_STATUS_SUCCESS;
87 }
88 
89 /**
90  * hdd_data_stall_process_cb() - Process data stall message
91  * @info: data stall message
92  *
93  * Process data stall message
94  *
95  * Return: void
96  */
hdd_data_stall_process_cb(struct data_stall_event_info * info)97 static void hdd_data_stall_process_cb(
98 			struct data_stall_event_info *info)
99 {
100 	struct scheduler_msg msg = {0};
101 	struct data_stall_event_info *data_stall_event_info;
102 	QDF_STATUS status;
103 
104 	data_stall_event_info = qdf_mem_malloc(sizeof(*data_stall_event_info));
105 	if (!data_stall_event_info)
106 		return;
107 
108 	data_stall_event_info->data_stall_type = info->data_stall_type;
109 	data_stall_event_info->indicator = info->indicator;
110 	data_stall_event_info->pdev_id = info->pdev_id;
111 	data_stall_event_info->recovery_type = info->recovery_type;
112 	data_stall_event_info->vdev_id_bitmap = info->vdev_id_bitmap;
113 
114 	sys_build_message_header(SYS_MSG_ID_DATA_STALL_MSG, &msg);
115 	/* Save callback and data */
116 	msg.callback = hdd_data_stall_process_event;
117 	msg.bodyptr = data_stall_event_info;
118 	msg.bodyval = 0;
119 
120 	status = scheduler_post_message(QDF_MODULE_ID_HDD,
121 					QDF_MODULE_ID_HDD,
122 					QDF_MODULE_ID_SYS, &msg);
123 
124 	if (status != QDF_STATUS_SUCCESS)
125 		qdf_mem_free(data_stall_event_info);
126 }
127 
hdd_register_data_stall_detect_cb(void)128 int hdd_register_data_stall_detect_cb(void)
129 {
130 	QDF_STATUS status;
131 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
132 
133 	/* Register the data stall callback */
134 	hdd_debug("Register data stall detect callback");
135 	status = cdp_data_stall_cb_register(soc, OL_TXRX_PDEV_ID,
136 					    hdd_data_stall_process_cb);
137 	return qdf_status_to_os_return(status);
138 }
139 
hdd_deregister_data_stall_detect_cb(void)140 int hdd_deregister_data_stall_detect_cb(void)
141 {
142 	QDF_STATUS status;
143 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
144 
145 	/* De-Register the data stall callback */
146 	hdd_debug("De-Register data stall detect callback");
147 	status = cdp_data_stall_cb_deregister(soc, OL_TXRX_PDEV_ID,
148 					      hdd_data_stall_process_cb);
149 	return qdf_status_to_os_return(status);
150 }
151