1 /*
2 * Copyright (c) 2019-2021 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 * DOC: This file contains fw offload south bound interface definitions
21 */
22
23 #include "scheduler_api.h"
24 #include "wlan_objmgr_psoc_obj.h"
25 #include "wlan_objmgr_global_obj.h"
26 #include "wlan_objmgr_pdev_obj.h"
27 #include "wlan_fwol_public_structs.h"
28 #include "wlan_fwol_ucfg_api.h"
29 #include "wlan_fwol_tgt_api.h"
30 #include "wlan_fw_offload_main.h"
31 #include "target_if.h"
32
tgt_fwol_register_ev_handler(struct wlan_objmgr_psoc * psoc)33 QDF_STATUS tgt_fwol_register_ev_handler(struct wlan_objmgr_psoc *psoc)
34 {
35 struct wlan_fwol_psoc_obj *fwol_obj;
36 struct wlan_fwol_tx_ops *tx_ops;
37 QDF_STATUS status = QDF_STATUS_E_FAILURE;
38
39 if (!psoc) {
40 fwol_err("NULL psoc handle");
41 return QDF_STATUS_E_INVAL;
42 }
43
44 fwol_obj = fwol_get_psoc_obj(psoc);
45 if (!fwol_obj) {
46 fwol_err("Failed to get FWOL Obj");
47 return QDF_STATUS_E_INVAL;
48 }
49
50 tx_ops = &fwol_obj->tx_ops;
51 if (tx_ops->reg_evt_handler) {
52 status = tx_ops->reg_evt_handler(psoc, NULL);
53 fwol_debug("reg_evt_handler, status:%d", status);
54 } else {
55 fwol_alert("No reg_evt_handler");
56 }
57
58 return status;
59 }
60
tgt_fwol_unregister_ev_handler(struct wlan_objmgr_psoc * psoc)61 QDF_STATUS tgt_fwol_unregister_ev_handler(struct wlan_objmgr_psoc *psoc)
62 {
63 struct wlan_fwol_psoc_obj *fwol_obj;
64 struct wlan_fwol_tx_ops *tx_ops;
65 QDF_STATUS status = QDF_STATUS_E_FAILURE;
66
67 if (!psoc) {
68 fwol_err("NNULL psoc handle");
69 return QDF_STATUS_E_INVAL;
70 }
71
72 fwol_obj = fwol_get_psoc_obj(psoc);
73 if (!fwol_obj) {
74 fwol_err("Failed to get FWOL Obj");
75 return QDF_STATUS_E_INVAL;
76 }
77
78 tx_ops = &fwol_obj->tx_ops;
79 if (tx_ops->unreg_evt_handler) {
80 status = tx_ops->unreg_evt_handler(psoc, NULL);
81 fwol_debug("unreg_evt_handler, status:%d", status);
82 } else {
83 fwol_alert("No unreg_evt_handler");
84 }
85
86 return status;
87 }
88
89 /**
90 * fwol_flush_callback() - fw offload message flush callback
91 * @msg: fw offload message
92 *
93 * Return: QDF_STATUS_SUCCESS on success.
94 */
95 __attribute__((unused))
fwol_flush_callback(struct scheduler_msg * msg)96 static QDF_STATUS fwol_flush_callback(struct scheduler_msg *msg)
97 {
98 struct wlan_fwol_rx_event *event;
99
100 if (!msg) {
101 fwol_err("NULL pointer for eLNA message");
102 return QDF_STATUS_E_INVAL;
103 }
104
105 event = msg->bodyptr;
106 msg->bodyptr = NULL;
107 fwol_release_rx_event(event);
108
109 return QDF_STATUS_SUCCESS;
110 }
111
112 #ifdef WLAN_FEATURE_ELNA
113 /**
114 * tgt_fwol_get_elna_bypass_resp() - handler for get eLNA bypass response
115 * @psoc: psoc handle
116 * @resp: status for last channel config
117 *
118 * Return: QDF_STATUS_SUCCESS on success
119 */
120 static QDF_STATUS
tgt_fwol_get_elna_bypass_resp(struct wlan_objmgr_psoc * psoc,struct get_elna_bypass_response * resp)121 tgt_fwol_get_elna_bypass_resp(struct wlan_objmgr_psoc *psoc,
122 struct get_elna_bypass_response *resp)
123 {
124 QDF_STATUS status;
125 struct scheduler_msg msg = {0};
126 struct wlan_fwol_rx_event *event;
127
128 event = qdf_mem_malloc(sizeof(*event));
129 if (!event)
130 return QDF_STATUS_E_NOMEM;
131
132 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FWOL_SB_ID);
133 if (QDF_IS_STATUS_ERROR(status)) {
134 fwol_err("Failed to get psoc ref");
135 fwol_release_rx_event(event);
136 return status;
137 }
138
139 event->psoc = psoc;
140 event->event_id = WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE;
141 event->get_elna_bypass_response = *resp;
142 msg.type = WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE;
143 msg.bodyptr = event;
144 msg.callback = fwol_process_event;
145 msg.flush_callback = fwol_flush_callback;
146 status = scheduler_post_message(QDF_MODULE_ID_FWOL,
147 QDF_MODULE_ID_FWOL,
148 QDF_MODULE_ID_TARGET_IF, &msg);
149
150 if (QDF_IS_STATUS_SUCCESS(status))
151 return QDF_STATUS_SUCCESS;
152
153 fwol_err("failed to send WLAN_FWOL_GET_ELNA_BYPASS_RESPONSE msg");
154 fwol_flush_callback(&msg);
155
156 return status;
157 }
158
tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops * rx_ops)159 static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
160 {
161 rx_ops->get_elna_bypass_resp = tgt_fwol_get_elna_bypass_resp;
162 }
163 #else
tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops * rx_ops)164 static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
165 {
166 }
167 #endif /* WLAN_FEATURE_ELNA */
168
169 #ifdef FW_THERMAL_THROTTLE_SUPPORT
170 /**
171 * notify_thermal_throttle_handler() - Thermal throttle stats event handler
172 * @psoc: psoc object
173 * @info: thermal throttle stats info from target if layer
174 *
175 * The handle will be registered to target if layer. Target if layer
176 * will notify the new level from firmware thermal stats event.
177 *
178 * Return: QDF_STATUS_SUCCESS for success
179 */
180 static QDF_STATUS
notify_thermal_throttle_handler(struct wlan_objmgr_psoc * psoc,struct thermal_throttle_info * info)181 notify_thermal_throttle_handler(struct wlan_objmgr_psoc *psoc,
182 struct thermal_throttle_info *info)
183 {
184 struct wlan_fwol_psoc_obj *fwol_obj;
185 QDF_STATUS status = QDF_STATUS_E_FAILURE;
186 struct fwol_thermal_callbacks *thermal_cbs;
187
188 if (!psoc) {
189 fwol_err("NULL psoc handle");
190 return QDF_STATUS_E_INVAL;
191 }
192
193 fwol_obj = fwol_get_psoc_obj(psoc);
194 if (!fwol_obj) {
195 fwol_err("Failed to get FWOL Obj");
196 return QDF_STATUS_E_INVAL;
197 }
198 thermal_cbs = &fwol_obj->thermal_cbs;
199 fwol_nofl_debug("thermal evt: pdev %d lvl %d",
200 info->pdev_id, info->level);
201 if (info->pdev_id <= fwol_obj->thermal_throttle.pdev_id ||
202 fwol_obj->thermal_throttle.pdev_id == WLAN_INVALID_PDEV_ID) {
203 fwol_obj->thermal_throttle.level = info->level;
204 fwol_obj->thermal_throttle.pdev_id = info->pdev_id;
205 if (thermal_cbs->notify_thermal_throttle_handler)
206 status =
207 thermal_cbs->notify_thermal_throttle_handler(psoc,
208 info);
209 else
210 fwol_debug("no thermal throttle handler");
211 }
212
213 return status;
214 }
215 #endif
216
217 #ifdef THERMAL_STATS_SUPPORT
218 static QDF_STATUS
tgt_fwol_get_thermal_stats_resp(struct wlan_objmgr_psoc * psoc,struct thermal_throttle_info * resp)219 tgt_fwol_get_thermal_stats_resp(struct wlan_objmgr_psoc *psoc,
220 struct thermal_throttle_info *resp)
221 {
222 QDF_STATUS status;
223 struct scheduler_msg msg = {0};
224 struct wlan_fwol_rx_event *event;
225
226 event = qdf_mem_malloc(sizeof(*event));
227 if (!event)
228 return QDF_STATUS_E_NOMEM;
229
230 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FWOL_SB_ID);
231 if (QDF_IS_STATUS_ERROR(status)) {
232 fwol_err("Failed to get psoc ref");
233 fwol_release_rx_event(event);
234 return status;
235 }
236
237 event->psoc = psoc;
238 event->event_id = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE;
239 event->get_thermal_stats_response = *resp;
240 msg.type = WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE;
241 msg.bodyptr = event;
242 msg.callback = fwol_process_event;
243 msg.flush_callback = fwol_flush_callback;
244 status = scheduler_post_message(QDF_MODULE_ID_FWOL,
245 QDF_MODULE_ID_FWOL,
246 QDF_MODULE_ID_TARGET_IF, &msg);
247
248 if (QDF_IS_STATUS_SUCCESS(status))
249 return QDF_STATUS_SUCCESS;
250
251 fwol_err("failed to send WLAN_FWOL_EVT_GET_THERMAL_STATS_RESPONSE msg");
252 fwol_flush_callback(&msg);
253
254 return status;
255
256 }
257 #endif
258
259 #ifdef THERMAL_STATS_SUPPORT
260 static void
tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops * rx_ops)261 tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops)
262 {
263 rx_ops->get_thermal_stats_resp = tgt_fwol_get_thermal_stats_resp;
264 }
265 #else
266 static void
tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops * rx_ops)267 tgt_fwol_register_thermal_stats_resp(struct wlan_fwol_rx_ops *rx_ops)
268 {
269 }
270 #endif
271 #ifdef FW_THERMAL_THROTTLE_SUPPORT
272 static void
tgt_fwol_register_notify_thermal_throttle_evt(struct wlan_fwol_rx_ops * rx_ops)273 tgt_fwol_register_notify_thermal_throttle_evt(struct wlan_fwol_rx_ops *rx_ops)
274 {
275 rx_ops->notify_thermal_throttle_handler =
276 notify_thermal_throttle_handler;
277 }
278 #else
279 static void
tgt_fwol_register_notify_thermal_throttle_evt(struct wlan_fwol_rx_ops * rx_ops)280 tgt_fwol_register_notify_thermal_throttle_evt(struct wlan_fwol_rx_ops *rx_ops)
281 {
282 }
283 #endif
284
tgt_fwol_register_thermal_rx_ops(struct wlan_fwol_rx_ops * rx_ops)285 static void tgt_fwol_register_thermal_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
286 {
287 tgt_fwol_register_notify_thermal_throttle_evt(rx_ops);
288 tgt_fwol_register_thermal_stats_resp(rx_ops);
289 }
290
tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops * rx_ops)291 QDF_STATUS tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
292 {
293 tgt_fwol_register_elna_rx_ops(rx_ops);
294 tgt_fwol_register_thermal_rx_ops(rx_ops);
295
296 return QDF_STATUS_SUCCESS;
297 }
298
tgt_fwol_pdev_param_send(struct wlan_objmgr_pdev * pdev,struct pdev_params pdev_param)299 QDF_STATUS tgt_fwol_pdev_param_send(struct wlan_objmgr_pdev *pdev,
300 struct pdev_params pdev_param)
301 {
302 struct wmi_unified *wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
303
304 if (!wmi_handle)
305 return QDF_STATUS_E_FAILURE;
306
307 return wmi_unified_pdev_param_send(wmi_handle, &pdev_param,
308 FWOL_WILDCARD_PDEV_ID);
309 }
310
tgt_fwol_vdev_param_send(struct wlan_objmgr_psoc * psoc,struct vdev_set_params vdev_param)311 QDF_STATUS tgt_fwol_vdev_param_send(struct wlan_objmgr_psoc *psoc,
312 struct vdev_set_params vdev_param)
313 {
314 wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
315
316 if (!wmi_handle)
317 return QDF_STATUS_E_FAILURE;
318
319 return wmi_unified_vdev_set_param_send(wmi_handle, &vdev_param);
320 }
321