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