blob: 21f8a1d4d3a6a14c952a956462a73325df7c1d8a [file] [log] [blame]
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301/*
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05302 * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05303 *
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05304 * 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
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053019/* Include Files */
20#include "wlan_ipa_core.h"
21#include "wlan_ipa_main.h"
22#include <ol_txrx.h>
23#include "cdp_txrx_ipa.h"
24#include "wal_rx_desc.h"
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +053025#include "qdf_str.h"
Jeff Johnson8feaa632018-12-07 11:56:02 -080026#include "sir_api.h"
27#include "host_diag_core_event.h"
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053028
29static struct wlan_ipa_priv *gp_ipa;
30
31static struct wlan_ipa_iface_2_client {
32 qdf_ipa_client_type_t cons_client;
33 qdf_ipa_client_type_t prod_client;
34} wlan_ipa_iface_2_client[WLAN_IPA_MAX_IFACE] = {
35 {
36 QDF_IPA_CLIENT_WLAN2_CONS, QDF_IPA_CLIENT_WLAN1_PROD
37 }, {
38 QDF_IPA_CLIENT_WLAN3_CONS, QDF_IPA_CLIENT_WLAN1_PROD
39 }, {
40 QDF_IPA_CLIENT_WLAN4_CONS, QDF_IPA_CLIENT_WLAN1_PROD
41 }
42};
43
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053044/* Local Function Prototypes */
45static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
46 unsigned long data);
47static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
48 unsigned long data);
49
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053050/**
51 * wlan_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
52 * @ipa_cfg: IPA config
53 *
54 * Return: true if STA mode IPA uC offload is enabled, false otherwise
55 */
56static inline bool wlan_ipa_uc_sta_is_enabled(struct wlan_ipa_config *ipa_cfg)
57{
58 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_STA_ENABLE_MASK);
59}
60
61/**
62 * wlan_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
63 * @ipa_cfg: IPA config
64 *
65 * Return: true if pre-filter is enabled, otherwise false
66 */
67static inline
68bool wlan_ipa_is_pre_filter_enabled(struct wlan_ipa_config *ipa_cfg)
69{
70 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg,
71 WLAN_IPA_PRE_FILTER_ENABLE_MASK);
72}
73
74/**
75 * wlan_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
76 * @ipa_cfg: IPA config
77 *
78 * Return: true if IPv6 is enabled, otherwise false
79 */
80static inline bool wlan_ipa_is_ipv6_enabled(struct wlan_ipa_config *ipa_cfg)
81{
82 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_IPV6_ENABLE_MASK);
83}
84
85/**
86 * wlan_ipa_msg_free_fn() - Free an IPA message
87 * @buff: pointer to the IPA message
88 * @len: length of the IPA message
89 * @type: type of IPA message
90 *
91 * Return: None
92 */
93static void wlan_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
94{
95 ipa_debug("msg type:%d, len:%d", type, len);
96 qdf_mem_free(buff);
97}
98
99/**
100 * wlan_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
101 * @priv_ctxt: IPA context
102 *
103 * Will be called by IPA context.
104 * It's atomic context, then should be scheduled to kworker thread
105 *
106 * Return: None
107 */
108static void wlan_ipa_uc_loaded_uc_cb(void *priv_ctxt)
109{
110 struct wlan_ipa_priv *ipa_ctx;
111 struct op_msg_type *msg;
112 struct uc_op_work_struct *uc_op_work;
113
114 if (!priv_ctxt) {
115 ipa_err("Invalid IPA context");
116 return;
117 }
118
119 ipa_ctx = priv_ctxt;
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530120 ipa_ctx->uc_loaded = true;
121
122 uc_op_work = &ipa_ctx->uc_op_work[WLAN_IPA_UC_OPCODE_UC_READY];
123 if (!list_empty(&uc_op_work->work.work.entry)) {
124 /* uc_op_work is not initialized yet */
125 return;
126 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530127
128 msg = qdf_mem_malloc(sizeof(*msg));
129 if (!msg) {
130 ipa_err("op_msg allocation fails");
131 return;
132 }
133
134 msg->op_code = WLAN_IPA_UC_OPCODE_UC_READY;
135
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530136 /* When the same uC OPCODE is already pended, just return */
137 if (uc_op_work->msg)
138 goto done;
139
140 uc_op_work->msg = msg;
141 qdf_sched_work(0, &uc_op_work->work);
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530142
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530143 /* work handler will free the msg buffer */
144 return;
145
146done:
147 qdf_mem_free(msg);
148}
149
150/**
151 * wlan_ipa_uc_send_wdi_control_msg() - Set WDI control message
152 * @ctrl: WDI control value
153 *
154 * Send WLAN_WDI_ENABLE for ctrl = true and WLAN_WDI_DISABLE otherwise.
155 *
156 * Return: QDF_STATUS
157 */
158static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
159{
jiad629b2172018-05-11 15:34:22 +0800160 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530161 qdf_ipa_msg_meta_t meta;
162 qdf_ipa_wlan_msg_t *ipa_msg;
163 int ret = 0;
164
165 /* WDI enable message to IPA */
166 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
167 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
168 if (!ipa_msg) {
169 ipa_err("msg allocation failed");
170 return QDF_STATUS_E_NOMEM;
171 }
172
jiad629b2172018-05-11 15:34:22 +0800173 if (ctrl) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530174 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
jiad629b2172018-05-11 15:34:22 +0800175 ipa_ctx->stats.event[QDF_WDI_ENABLE]++;
176 } else {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530177 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
jiad629b2172018-05-11 15:34:22 +0800178 ipa_ctx->stats.event[QDF_WDI_DISABLE]++;
179 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530180
181 ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
182 ret = qdf_ipa_send_msg(&meta, ipa_msg, wlan_ipa_msg_free_fn);
183 if (ret) {
184 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
185 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
186 qdf_mem_free(ipa_msg);
187 return QDF_STATUS_E_FAILURE;
188 }
189
190 return QDF_STATUS_SUCCESS;
191}
192
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530193struct wlan_ipa_priv *wlan_ipa_get_obj_context(void)
194{
195 return gp_ipa;
196}
197
Yun Parke74e6092018-04-27 11:36:34 -0700198/**
199 * wlan_ipa_send_pkt_to_tl() - Send an IPA packet to TL
200 * @iface_context: interface-specific IPA context
201 * @ipa_tx_desc: packet data descriptor
202 *
203 * Return: None
204 */
205static void wlan_ipa_send_pkt_to_tl(
206 struct wlan_ipa_iface_context *iface_context,
207 qdf_ipa_rx_data_t *ipa_tx_desc)
208{
209 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
210 qdf_nbuf_t skb;
211 struct wlan_ipa_tx_desc *tx_desc;
212
213 qdf_spin_lock_bh(&iface_context->interface_lock);
214 /*
215 * During CAC period, data packets shouldn't be sent over the air so
216 * drop all the packets here
217 */
218 if (iface_context->device_mode == QDF_SAP_MODE ||
219 iface_context->device_mode == QDF_P2P_GO_MODE) {
220 if (ipa_ctx->dfs_cac_block_tx) {
221 ipa_free_skb(ipa_tx_desc);
222 qdf_spin_unlock_bh(&iface_context->interface_lock);
223 iface_context->stats.num_tx_cac_drop++;
224 wlan_ipa_wdi_rm_try_release(ipa_ctx);
225 return;
226 }
227 }
228 qdf_spin_unlock_bh(&iface_context->interface_lock);
229
230 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
231
hangtian127c9532019-01-12 13:29:07 +0800232 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Yun Parke74e6092018-04-27 11:36:34 -0700233
234 /* Store IPA Tx buffer ownership into SKB CB */
235 qdf_nbuf_ipa_owned_set(skb);
236 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
237 qdf_nbuf_mapped_paddr_set(skb,
jiadaf210c02018-11-20 09:40:34 +0800238 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
239 + WLAN_IPA_WLAN_FRAG_HEADER
240 + WLAN_IPA_WLAN_IPA_HEADER);
Yun Parke74e6092018-04-27 11:36:34 -0700241 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
242 WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER;
jiadaf210c02018-11-20 09:40:34 +0800243 } else
244 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
Yun Parke74e6092018-04-27 11:36:34 -0700245
246 qdf_spin_lock_bh(&ipa_ctx->q_lock);
247 /* get free Tx desc and assign ipa_tx_desc pointer */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +0530248 if (qdf_list_remove_front(&ipa_ctx->tx_desc_free_list,
249 (qdf_list_node_t **)&tx_desc) ==
Yun Parke74e6092018-04-27 11:36:34 -0700250 QDF_STATUS_SUCCESS) {
251 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
252 ipa_ctx->stats.num_tx_desc_q_cnt++;
253 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
254 /* Store Tx Desc index into SKB CB */
255 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
256 } else {
257 ipa_ctx->stats.num_tx_desc_error++;
258 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
259 qdf_ipa_free_skb(ipa_tx_desc);
260 wlan_ipa_wdi_rm_try_release(ipa_ctx);
261 return;
262 }
263
264 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
265 (struct cdp_vdev *)iface_context->tl_context,
266 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
267 if (skb) {
268 qdf_nbuf_free(skb);
269 iface_context->stats.num_tx_err++;
270 return;
271 }
272
273 atomic_inc(&ipa_ctx->tx_ref_cnt);
274
275 iface_context->stats.num_tx++;
276}
277
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530278#ifdef CONFIG_IPA_WDI_UNIFIED_API
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530279/*
280 * TODO: Get WDI version through FW capabilities
281 */
Mohit Khannacabf5e72018-07-24 13:28:43 -0700282#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530283static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
284{
285 ipa_ctx->wdi_version = IPA_WDI_3;
286}
287#elif defined(QCA_WIFI_3_0)
288static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
289{
290 ipa_ctx->wdi_version = IPA_WDI_2;
291}
292#else
293static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
294{
295 ipa_ctx->wdi_version = IPA_WDI_1;
296}
297#endif
298
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530299static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
300 qdf_device_t osdev)
301{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530302 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530303}
304
305static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
306 qdf_device_t osdev)
307{
308 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
309 int i;
310
311 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
312 qdf_mem_copy(&sys_in[i],
313 &ipa_ctx->sys_pipe[i].ipa_sys_params,
314 sizeof(qdf_ipa_sys_connect_params_t));
315
316 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
317 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
318 wlan_ipa_wdi_meter_notifier_cb,
319 ipa_ctx->config->desc_size,
320 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
321 &ipa_ctx->tx_pipe_handle,
322 &ipa_ctx->rx_pipe_handle,
323 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530324 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530325}
326
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530327#ifdef FEATURE_METERING
328/**
329 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
330 * @ipa_ctx: IPA context
331 * @in: IPA WDI in param
332 *
333 * Return: QDF_STATUS
334 */
335static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
336 qdf_ipa_wdi_init_in_params_t *in)
337{
338 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
339 wlan_ipa_wdi_meter_notifier_cb;
340}
341#else
342static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
343 qdf_ipa_wdi_init_in_params_t *in)
344{
345}
346#endif
347
348/**
349 * wlan_ipa_wdi_init() - IPA WDI init
350 * @ipa_ctx: IPA context
351 *
352 * Return: QDF_STATUS
353 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530354static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
355{
356 qdf_ipa_wdi_init_in_params_t in;
357 qdf_ipa_wdi_init_out_params_t out;
358 int ret;
359
360 ipa_ctx->uc_loaded = false;
361
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530362 qdf_mem_zero(&in, sizeof(in));
363 qdf_mem_zero(&out, sizeof(out));
364
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530365 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
366 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530367 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
368 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530369
370 ret = qdf_ipa_wdi_init(&in, &out);
371 if (ret) {
372 ipa_err("ipa_wdi_init failed with ret=%d", ret);
373 return QDF_STATUS_E_FAILURE;
374 }
375
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530376 ipa_ctx->over_gsi =
377 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
378 ipa_ctx->is_smmu_enabled =
379 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
380 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
381 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
382
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530383 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700384 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530385 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530386 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530387 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530388 return QDF_STATUS_E_BUSY;
389 }
390
391 return QDF_STATUS_SUCCESS;
392}
393
394static inline int wlan_ipa_wdi_cleanup(void)
395{
396 int ret;
397
398 ret = qdf_ipa_wdi_cleanup();
399 if (ret)
400 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
401 return ret;
402}
403
404static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
405 struct ipa_sys_connect_params *sys,
406 uint32_t *handle)
407{
408 return 0;
409}
410
411static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
412 uint32_t handle)
413{
414 return 0;
415}
416
Yun Parke74e6092018-04-27 11:36:34 -0700417/**
418 * wlan_ipa_pm_flush() - flush queued packets
419 * @work: pointer to the scheduled work
420 *
421 * Called during PM resume to send packets to TL which were queued
422 * while host was in the process of suspending.
423 *
424 * Return: None
425 */
426static void wlan_ipa_pm_flush(void *data)
427{
428 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
429 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
430 qdf_nbuf_t skb;
431 uint32_t dequeued = 0;
432
433 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
434 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
435 NULL)) {
436 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
437
438 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
439 dequeued++;
440
jiadab8cea02018-05-24 09:16:14 +0800441 if (pm_tx_cb->exception) {
442 if (ipa_ctx->softap_xmit &&
443 pm_tx_cb->iface_context->dev) {
444 ipa_ctx->softap_xmit(skb,
445 pm_tx_cb->iface_context->dev);
446 ipa_ctx->stats.num_tx_fwd_ok++;
447 } else {
448 dev_kfree_skb_any(skb);
449 }
450 } else {
451 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
452 pm_tx_cb->ipa_tx_desc);
453 }
Yun Parke74e6092018-04-27 11:36:34 -0700454
455 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
456 }
457 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
458
459 ipa_ctx->stats.num_tx_dequeued += dequeued;
460 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
461 ipa_ctx->stats.num_max_pm_queue = dequeued;
462}
463
jiadae9959f2018-05-08 11:19:07 +0800464int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
465{
466 if (!num_buf) {
467 ipa_info("No buffers to map/unmap");
468 return 0;
469 }
470
471 if (map)
472 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
473 else
474 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
475}
476
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530477#else /* CONFIG_IPA_WDI_UNIFIED_API */
478
479static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
480{
481}
482
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530483static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
484 qdf_device_t osdev)
485{
486 return qdf_mem_smmu_s1_enabled(osdev);
487}
488
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530489static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
490 qdf_device_t osdev)
491{
492 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
493 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
494 wlan_ipa_wdi_meter_notifier_cb,
495 ipa_ctx->config->desc_size,
496 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
497 &ipa_ctx->tx_pipe_handle,
498 &ipa_ctx->rx_pipe_handle);
499}
500
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530501static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
502{
503 struct ipa_wdi_uc_ready_params uc_ready_param;
504
505 ipa_ctx->uc_loaded = false;
506 uc_ready_param.priv = (void *)ipa_ctx;
507 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
508 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
509 ipa_info("UC Ready CB register fail");
510 return QDF_STATUS_E_FAILURE;
511 }
512
513 if (true == uc_ready_param.is_uC_ready) {
514 ipa_info("UC Ready");
515 ipa_ctx->uc_loaded = true;
516 } else {
517 return QDF_STATUS_E_BUSY;
518 }
519
520 return QDF_STATUS_SUCCESS;
521}
522
523static inline int wlan_ipa_wdi_cleanup(void)
524{
525 int ret;
526
527 ret = qdf_ipa_uc_dereg_rdyCB();
528 if (ret)
529 ipa_info("UC Ready CB deregister fail");
530 return ret;
531}
532
533static inline int wlan_ipa_wdi_setup_sys_pipe(
534 struct wlan_ipa_priv *ipa_ctx,
535 struct ipa_sys_connect_params *sys, uint32_t *handle)
536{
537 return qdf_ipa_setup_sys_pipe(sys, handle);
538}
539
540static inline int wlan_ipa_wdi_teardown_sys_pipe(
541 struct wlan_ipa_priv *ipa_ctx,
542 uint32_t handle)
543{
544 return qdf_ipa_teardown_sys_pipe(handle);
545}
546
Yun Parke74e6092018-04-27 11:36:34 -0700547/**
548 * wlan_ipa_pm_flush() - flush queued packets
549 * @work: pointer to the scheduled work
550 *
551 * Called during PM resume to send packets to TL which were queued
552 * while host was in the process of suspending.
553 *
554 * Return: None
555 */
556static void wlan_ipa_pm_flush(void *data)
557{
558 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
559 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
560 qdf_nbuf_t skb;
561 uint32_t dequeued = 0;
562
563 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
564 WIFI_POWER_EVENT_WAKELOCK_IPA);
565 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
566 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
567 NULL)) {
568 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
569
570 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
571 dequeued++;
572
jiadab8cea02018-05-24 09:16:14 +0800573 if (pm_tx_cb->exception) {
574 if (ipa_ctx->softap_xmit &&
575 pm_tx_cb->iface_context->dev) {
576 ipa_ctx->softap_xmit(skb,
577 pm_tx_cb->iface_context->dev);
578 ipa_ctx->stats.num_tx_fwd_ok++;
579 } else {
580 dev_kfree_skb_any(skb);
581 }
582 } else {
583 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
584 pm_tx_cb->ipa_tx_desc);
585 }
Yun Parke74e6092018-04-27 11:36:34 -0700586
587 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
588 }
589 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
590 qdf_wake_lock_release(&ipa_ctx->wake_lock,
591 WIFI_POWER_EVENT_WAKELOCK_IPA);
592
593 ipa_ctx->stats.num_tx_dequeued += dequeued;
594 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
595 ipa_ctx->stats.num_max_pm_queue = dequeued;
596}
597
jiadae9959f2018-05-08 11:19:07 +0800598int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
599{
600 if (!num_buf) {
601 ipa_info("No buffers to map/unmap");
602 return 0;
603 }
604
605 if (map)
606 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
607 else
608 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
609}
610
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530611#endif /* CONFIG_IPA_WDI_UNIFIED_API */
612
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530613/**
614 * wlan_ipa_send_skb_to_network() - Send skb to kernel
615 * @skb: network buffer
616 * @iface_ctx: IPA interface context
617 *
618 * Called when a network buffer is received which should not be routed
619 * to the IPA module.
620 *
621 * Return: None
622 */
623static void
624wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
625 struct wlan_ipa_iface_context *iface_ctx)
626{
627 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
628
629 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800630 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530631 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800632 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530633 return;
634 }
635
636 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
637
638 if (ipa_ctx->send_to_nw)
639 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
640
641 ipa_ctx->ipa_rx_net_send_count++;
642}
643
644/**
645 * wlan_ipa_forward() - handle packet forwarding to wlan tx
646 * @ipa_ctx: pointer to ipa ipa context
647 * @iface_ctx: interface context
648 * @skb: data pointer
649 *
650 * if exception packet has set forward bit, copied new packet should be
651 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
652 * put into pm queue and tx procedure will be differed
653 *
654 * Return: None
655 */
656static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
657 struct wlan_ipa_iface_context *iface_ctx,
658 qdf_nbuf_t skb)
659{
660 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
661
662 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
663
664 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
665 qdf_nbuf_ipa_owned_set(skb);
666
667 /* WLAN subsystem is in suspend, put in queue */
668 if (ipa_ctx->suspended) {
669 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
jiadf3ecc752018-07-05 14:36:03 +0800670 ipa_info_rl("Tx in suspend, put in queue");
hangtian127c9532019-01-12 13:29:07 +0800671 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530672 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
673 pm_tx_cb->exception = true;
674 pm_tx_cb->iface_context = iface_ctx;
675 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
676 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
677 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
678 ipa_ctx->stats.num_tx_queued++;
679 } else {
680 /* Resume, put packet into WLAN TX */
681 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
682
683 if (ipa_ctx->softap_xmit) {
684 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
jiadf3ecc752018-07-05 14:36:03 +0800685 ipa_err_rl("packet Tx fail");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530686 ipa_ctx->stats.num_tx_fwd_err++;
687 } else {
688 ipa_ctx->stats.num_tx_fwd_ok++;
689 }
690 } else {
jiadab8cea02018-05-24 09:16:14 +0800691 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530692 }
693 }
694}
695
696/**
697 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
698 * @ipa_ctx: pointer to IPA IPA struct
699 * @iface_ctx: ipa interface context
700 * @desc: Firmware descriptor
701 * @skb: Data buffer
702 *
703 * Return:
704 * WLAN_IPA_FORWARD_PKT_NONE
705 * WLAN_IPA_FORWARD_PKT_DISCARD
706 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
707 *
708 */
709
710static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
711 struct wlan_ipa_priv *ipa_ctx,
712 struct wlan_ipa_iface_context *iface_ctx,
713 uint8_t desc,
714 qdf_nbuf_t skb)
715{
716 int ret = WLAN_IPA_FORWARD_PKT_NONE;
717 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Sravan Kumar Kairamf48210c2018-12-17 17:48:10 +0530718 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530719
720 if ((desc & FW_RX_DESC_FORWARD_M)) {
Sravan Kumar Kairamf48210c2018-12-17 17:48:10 +0530721 void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
722 iface_ctx->session_id);
723 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530724 /* Drop the packet*/
725 ipa_ctx->stats.num_tx_fwd_err++;
jiadab8cea02018-05-24 09:16:14 +0800726 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530727 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
728 return ret;
729 }
jiadf3ecc752018-07-05 14:36:03 +0800730 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530731 ipa_ctx->ipa_tx_forward++;
732
733 if ((desc & FW_RX_DESC_DISCARD_M)) {
734 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
735 ipa_ctx->ipa_rx_internal_drop_count++;
736 ipa_ctx->ipa_rx_discard++;
737 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
738 } else {
739 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
740
741 if (cloned_skb)
742 wlan_ipa_forward(ipa_ctx, iface_ctx,
743 cloned_skb);
744 else
jiadf3ecc752018-07-05 14:36:03 +0800745 ipa_err_rl("tx skb alloc failed");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530746 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
747 }
748 }
749
750 return ret;
751}
752
753/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530754 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530755 * @priv: pointer to private data registered with IPA (we register a
756 * pointer to the global IPA context)
757 * @evt: the IPA event which triggered the callback
758 * @data: data associated with the event
759 *
760 * Return: None
761 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530762static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
763 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530764{
765 struct wlan_ipa_priv *ipa_ctx = NULL;
766 qdf_nbuf_t skb;
767 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700768 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530769 struct wlan_ipa_iface_context *iface_context;
770 uint8_t fw_desc;
771
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530772 ipa_ctx = (struct wlan_ipa_priv *)priv;
773 if (!ipa_ctx) {
774 if (evt == IPA_RECEIVE) {
775 skb = (qdf_nbuf_t)data;
776 dev_kfree_skb_any(skb);
777 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530778 return;
779 }
780
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530781 if (qdf_is_module_state_transitioning()) {
782 ipa_err_rl("Module transition in progress");
783 if (evt == IPA_RECEIVE) {
784 skb = (qdf_nbuf_t)data;
785 ipa_ctx->ipa_rx_internal_drop_count++;
786 dev_kfree_skb_any(skb);
787 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530788 return;
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530789 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530790
791 switch (evt) {
792 case IPA_RECEIVE:
793 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530794 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
795 session_id = (uint8_t)skb->cb[0];
796 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530797 } else {
798 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
799 }
800 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700801 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
802 iface_id, session_id, (uint8_t)skb->cb[1],
803 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530804 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800805 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530806 return;
807 }
808
809 iface_context = &ipa_ctx->iface_context[iface_id];
810 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800811 ipa_err_rl("TL context of iface_id %u is NULL",
812 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530813 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800814 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530815 return;
816 }
817
818 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
819 ipa_ctx->stats.num_rx_excep++;
820 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
821 } else {
822 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
823 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530824 iface_context->stats.num_rx_ipa_excep++;
825
826 /* Disable to forward Intra-BSS Rx packets when
827 * ap_isolate=1 in hostapd.conf
828 */
829 if (!ipa_ctx->ap_intrabss_fwd) {
830 /*
831 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
832 * all Rx packets to IPA uC, which need to be forwarded
833 * to other interface.
834 * And, IPA driver will send back to WLAN host driver
835 * through exception pipe with fw_desc field set by FW.
836 * Here we are checking fw_desc field for FORWARD bit
837 * set, and forward to Tx. Then copy to kernel stack
838 * only when DISCARD bit is not set.
839 */
840 fw_desc = (uint8_t)skb->cb[1];
841 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
842 wlan_ipa_intrabss_forward(ipa_ctx, iface_context,
843 fw_desc, skb))
844 break;
845 } else {
jiadf3ecc752018-07-05 14:36:03 +0800846 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530847 }
848
849 wlan_ipa_send_skb_to_network(skb, iface_context);
850 break;
851
852 default:
jiadf3ecc752018-07-05 14:36:03 +0800853 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530854 return;
855 }
856}
857
858/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530859 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
860 * @priv: pointer to private data registered with IPA (we register a
861 * pointer to the global IPA context)
862 * @evt: the IPA event which triggered the callback
863 * @data: data associated with the event
864 *
865 * Return: None
866 */
867static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
868 unsigned long data)
869{
870 qdf_ssr_protect(__func__);
871 __wlan_ipa_w2i_cb(priv, evt, data);
872 qdf_ssr_unprotect(__func__);
873}
874
875/**
876 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530877 * @priv: pointer to private data registered with IPA (we register a
878 * pointer to the interface-specific IPA context)
879 * @evt: the IPA event which triggered the callback
880 * @data: data associated with the event
881 *
882 * Return: None
883 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530884static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
885 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530886{
887 struct wlan_ipa_priv *ipa_ctx = NULL;
888 qdf_ipa_rx_data_t *ipa_tx_desc;
889 struct wlan_ipa_iface_context *iface_context;
890 qdf_nbuf_t skb;
891 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
892
893 iface_context = (struct wlan_ipa_iface_context *)priv;
894 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
895 ipa_ctx = iface_context->ipa_ctx;
896
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530897 if (qdf_is_module_state_transitioning()) {
898 ipa_err_rl("Module transition in progress");
899 ipa_free_skb(ipa_tx_desc);
900 iface_context->stats.num_tx_drop++;
901 return;
902 }
903
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530904 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +0800905 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530906 ipa_free_skb(ipa_tx_desc);
907 iface_context->stats.num_tx_drop++;
908 return;
909 }
910
911 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
912
913 /*
914 * If PROD resource is not requested here then there may be cases where
915 * IPA hardware may be clocked down because of not having proper
916 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
917 * workaround to request PROD resource while data is going over CONS
918 * pipe to prevent the IPA hardware clockdown.
919 */
920 wlan_ipa_wdi_rm_request(ipa_ctx);
921
922 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
923 /*
924 * If host is still suspended then queue the packets and these will be
925 * drained later when resume completes. When packet is arrived here and
926 * host is suspended, this means that there is already resume is in
927 * progress.
928 */
929 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +0800930 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530931 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
932 pm_tx_cb->iface_context = iface_context;
933 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
934 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
935 ipa_ctx->stats.num_tx_queued++;
936
937 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
938 return;
939 }
940
941 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
942
943 /*
944 * If we are here means, host is not suspended, wait for the work queue
945 * to finish.
946 */
947 qdf_flush_work(&ipa_ctx->pm_work);
948
949 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
950}
951
jitiphilfdcaaba2018-09-03 16:19:52 +0530952/**
953 * wlan_ipa_i2w_cb() - IPA to WLAN callback
954 * @priv: pointer to private data registered with IPA (we register a
955 * pointer to the interface-specific IPA context)
956 * @evt: the IPA event which triggered the callback
957 * @data: data associated with the event
958 *
959 * Return: None
960 */
961static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
962 unsigned long data)
963{
964 qdf_ssr_protect(__func__);
965 __wlan_ipa_i2w_cb(priv, evt, data);
966 qdf_ssr_unprotect(__func__);
967}
968
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530969QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
970{
971 /*
972 * Check if IPA is ready for suspend, If we are here means, there is
973 * high chance that suspend would go through but just to avoid any race
974 * condition after suspend started, these checks are conducted before
975 * allowing to suspend.
976 */
977 if (atomic_read(&ipa_ctx->tx_ref_cnt))
978 return QDF_STATUS_E_AGAIN;
979
Yun Parke74e6092018-04-27 11:36:34 -0700980 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530981 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530982
983 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
984 ipa_ctx->suspended = true;
985 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
986
987 return QDF_STATUS_SUCCESS;
988}
989
990QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
991{
992 qdf_sched_work(0, &ipa_ctx->pm_work);
993
994 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
995 ipa_ctx->suspended = false;
996 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
997
998 return QDF_STATUS_SUCCESS;
999}
1000
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301001QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1002{
1003 int result;
1004
1005 ipa_debug("enter");
1006
1007 if (!ipa_ctx->ipa_pipes_down) {
1008 /*
1009 * IPA WDI Pipes are already activated due to
1010 * rm deferred resources grant
1011 */
1012 ipa_warn("IPA WDI Pipes are already activated");
1013 goto end;
1014 }
1015
1016 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1017 ipa_ctx->dp_pdev);
1018 if (result) {
1019 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1020 return QDF_STATUS_E_FAILURE;
1021 }
1022
1023 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1024 ipa_ctx->ipa_pipes_down = false;
1025
1026 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1027 ipa_ctx->dp_pdev);
1028
1029end:
1030 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1031
1032 return QDF_STATUS_SUCCESS;
1033}
1034
1035QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1036{
1037 int result;
1038
1039 ipa_debug("enter");
1040
1041 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301042 ipa_warn("IPA WDI Pipes are already deactivated");
1043 goto end;
1044 }
1045
1046 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1047 ipa_ctx->dp_pdev);
1048
1049 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1050 ipa_ctx->dp_pdev);
1051 if (result) {
1052 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
1053 return QDF_STATUS_E_FAILURE;
1054 }
1055
1056 ipa_ctx->ipa_pipes_down = true;
1057
1058end:
1059 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1060
1061 return QDF_STATUS_SUCCESS;
1062}
1063
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301064/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301065 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1066 * @ipa_ctx: Global IPA IPA context
1067 * @sta_add: Should station be added
1068 * @sta_id: ID of the station being queried
1069 *
1070 * Return: true if the station was found
1071 */
1072static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
1073 bool sta_add, uint8_t sta_id,
1074 uint8_t *mac_addr)
1075{
1076 bool sta_found = false;
1077 uint8_t idx;
1078
1079 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1080 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1081 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1082 sta_found = true;
1083 break;
1084 }
1085 }
1086 if (sta_add && sta_found) {
1087 ipa_err("STA ID %d already exist, cannot add", sta_id);
1088 return sta_found;
1089 }
1090 if (sta_add) {
1091 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1092 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1093 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
1094 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
1095 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1096 mac_addr, mac_addr,
1097 QDF_NET_ETH_LEN);
1098 return sta_found;
1099 }
1100 }
1101 }
1102 if (!sta_add && !sta_found) {
1103 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
1104 return sta_found;
1105 }
1106 if (!sta_add) {
1107 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1108 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1109 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1110 ipa_ctx->assoc_stas_map[idx].is_reserved =
1111 false;
1112 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
hangtian127c9532019-01-12 13:29:07 +08001113 qdf_mem_zero(
1114 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1115 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301116 return sta_found;
1117 }
1118 }
1119 }
1120
1121 return sta_found;
1122}
1123
1124/**
1125 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1126 * @ipa_ctx: IPA context
1127 * @session_id: Session ID
1128 *
1129 * Return: None
1130 */
1131static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1132 uint8_t session_id)
1133{
1134 struct wlan_ipa_iface_context *iface_ctx;
1135 int i;
1136
1137 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1138 iface_ctx = &ipa_ctx->iface_context[i];
1139 if (iface_ctx->session_id == session_id)
1140 break;
1141 }
1142
1143 return i;
1144}
1145
1146/**
1147 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1148 * @iface_context: interface-specific IPA context
1149 *
1150 * Return: None
1151 */
1152static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1153{
1154 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1155
1156 ipa_debug("enter");
1157
1158 if (!iface_context->tl_context)
1159 return;
1160
1161 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1162 iface_context->dev->name,
1163 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1164
1165 qdf_spin_lock_bh(&iface_context->interface_lock);
1166 iface_context->tl_context = NULL;
1167 iface_context->dev = NULL;
1168 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1169 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1170 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1171 qdf_spin_unlock_bh(&iface_context->interface_lock);
1172 iface_context->ifa_address = 0;
1173 if (!iface_context->ipa_ctx->num_iface) {
1174 ipa_err("NUM INTF 0, Invalid");
1175 QDF_ASSERT(0);
1176 }
1177 iface_context->ipa_ctx->num_iface--;
1178 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1179}
1180
1181/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301182 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1183 * @skb: packet buffer which was transmitted
1184 *
1185 * Return: None
1186 */
1187static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1188{
1189 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1190 qdf_ipa_rx_data_t *ipa_tx_desc;
1191 struct wlan_ipa_tx_desc *tx_desc;
1192 uint16_t id;
1193
1194 if (!qdf_nbuf_ipa_owned_get(skb)) {
1195 dev_kfree_skb_any(skb);
1196 return;
1197 }
1198
1199 /* Get Tx desc pointer from SKB CB */
1200 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1201 tx_desc = &ipa_ctx->tx_desc_pool[id];
1202 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1203
1204 /* Return Tx Desc to IPA */
1205 qdf_ipa_free_skb(ipa_tx_desc);
1206
1207 /* Return to free tx desc list */
1208 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1209 tx_desc->ipa_tx_desc_ptr = NULL;
1210 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1211 ipa_ctx->stats.num_tx_desc_q_cnt--;
1212 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1213
1214 ipa_ctx->stats.num_tx_comp_cnt++;
1215
1216 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1217
1218 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1219}
1220
1221/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301222 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1223 * @ipa_ctx: IPA IPA global context
1224 * @net_dev: Interface net device
1225 * @device_mode: Net interface device mode
1226 * @adapter: Interface upon which IPA is being setup
1227 * @sta_id: Station ID of the API instance
1228 * @session_id: Station ID of the API instance
1229 *
1230 * Return: QDF STATUS
1231 */
1232static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1233 qdf_netdev_t net_dev,
1234 uint8_t device_mode, uint8_t sta_id,
1235 uint8_t session_id)
1236{
1237 struct wlan_ipa_iface_context *iface_context = NULL;
1238 void *tl_context = NULL;
1239 int i;
1240 QDF_STATUS status;
1241
1242 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1243 * channel change indication. Since these indications are sent by lower
1244 * layer as SAP updates and IPA doesn't have to do anything for these
1245 * updates so ignoring!
1246 */
1247 if (device_mode == QDF_SAP_MODE) {
1248 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1249 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001250 if (iface_context->dev == net_dev) {
1251 ipa_debug("found iface %u device_mode %u",
1252 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301253 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001254 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301255 }
1256 }
1257
Yun Park21ec4902018-04-24 12:11:01 -07001258 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1259 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1260 status = QDF_STATUS_E_NOMEM;
1261 QDF_ASSERT(0);
1262 goto end;
1263 }
1264
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301265 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001266 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301267 iface_context = &(ipa_ctx->iface_context[i]);
1268 break;
1269 }
1270 }
1271
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001272 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301273 ipa_err("All the IPA interfaces are in use");
1274 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001275 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301276 goto end;
1277 }
1278
1279 iface_context->sta_id = sta_id;
1280 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1281 ipa_ctx->dp_pdev,
1282 sta_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001283 if (!tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301284 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1285 status = QDF_STATUS_E_INVAL;
1286 goto end;
1287 }
1288
1289 iface_context->tl_context = tl_context;
1290 iface_context->dev = net_dev;
1291 iface_context->device_mode = device_mode;
1292 iface_context->session_id = session_id;
1293
1294 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1295 net_dev->dev_addr,
1296 iface_context->prod_client,
1297 iface_context->cons_client,
1298 session_id,
1299 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1300 if (status != QDF_STATUS_SUCCESS)
1301 goto end;
1302
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301303 /* Register IPA Tx desc free callback */
1304 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1305
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301306 ipa_ctx->num_iface++;
1307
1308 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1309
1310 return status;
1311
1312end:
1313 if (iface_context)
1314 wlan_ipa_cleanup_iface(iface_context);
1315
1316 return status;
1317}
1318
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301319#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1320/**
1321 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1322 * @ipa_ctx: IPA context
1323 *
1324 * Return: QDF STATUS
1325 */
1326static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1327{
1328 ipa_debug("enter");
1329
1330 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1331 ipa_err("IPA WDI Pipe activation failed");
1332 return QDF_STATUS_E_BUSY;
1333 }
1334
1335 ipa_debug("exit");
1336
1337 return QDF_STATUS_SUCCESS;
1338}
1339
1340/**
1341 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1342 * @ipa_ctx: IPA context
1343 *
1344 * Return: None
1345 */
1346static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1347{
1348 ipa_debug("enter");
1349
1350 wlan_ipa_uc_disable_pipes(ipa_ctx);
1351
1352 ipa_debug("exit: IPA WDI Pipes deactivated");
1353}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301354
1355bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1356{
1357 return !ipa_ctx->ipa_pipes_down;
1358}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301359#else
1360
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301361/**
1362 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1363 * @ipa_ctx: IPA context
1364 *
1365 * Return: QDF STATUS
1366 */
1367static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1368{
1369 ipa_debug("enter");
1370
1371 ipa_ctx->activated_fw_pipe = 0;
1372 ipa_ctx->resource_loading = true;
1373
1374 /* If RM feature enabled
1375 * Request PROD Resource first
1376 * PROD resource may return sync or async manners
1377 */
1378 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001379 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1380 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301381 /* RM PROD request sync return
1382 * enable pipe immediately
1383 */
1384 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1385 ipa_err("IPA WDI Pipe activation failed");
1386 ipa_ctx->resource_loading = false;
1387 return QDF_STATUS_E_BUSY;
1388 }
1389 } else {
1390 ipa_err("IPA WDI Pipe activation deferred");
1391 }
1392 } else {
1393 /* RM Disabled
1394 * Just enabled all the PIPEs
1395 */
1396 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1397 ipa_err("IPA WDI Pipe activation failed");
1398 ipa_ctx->resource_loading = false;
1399 return QDF_STATUS_E_BUSY;
1400 }
1401 ipa_ctx->resource_loading = false;
1402 }
1403
1404 ipa_debug("exit");
1405
1406 return QDF_STATUS_SUCCESS;
1407}
1408
1409/**
1410 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1411 * @ipa_ctx: IPA context
1412 *
1413 * Return: None
1414 */
1415static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1416{
1417 ipa_debug("enter");
1418
1419 ipa_ctx->resource_unloading = true;
1420 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1421 ipa_info("Disable FW RX PIPE");
1422 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301423
1424 ipa_debug("exit: IPA WDI Pipes deactivated");
1425}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301426
1427bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1428{
1429 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1430}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301431#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301432
1433/**
1434 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1435 * @ipa_ctx: global IPA context
1436 * @offload_type: MCC or SCC
1437 * @session_id: Session Id
1438 * @enable: TX offload enable or disable
1439 *
1440 * Return: none
1441 */
1442static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1443 uint32_t offload_type,
1444 uint8_t session_id,
1445 bool enable)
1446{
1447
1448 struct ipa_uc_offload_control_params req = {0};
1449
1450 if (session_id >= WLAN_IPA_MAX_SESSION) {
1451 ipa_err("invalid session id: %d", session_id);
1452 return;
1453 }
1454
1455 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301456 ipa_info("IPA offload status is already set");
1457 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301458 offload_type, session_id, enable);
1459 return;
1460 }
1461
1462 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1463 offload_type, session_id, enable);
1464
1465 req.offload_type = offload_type;
1466 req.vdev_id = session_id;
1467 req.enable = enable;
1468
1469 if (QDF_STATUS_SUCCESS !=
1470 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1471 ipa_err("Fail to enable IPA offload");
1472 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1473 offload_type, session_id, enable);
1474 } else {
1475 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1476 }
1477}
1478
1479/**
1480 * __wlan_ipa_wlan_evt() - IPA event handler
1481 * @net_dev: Interface net device
1482 * @device_mode: Net interface device mode
1483 * @sta_id: station id for the event
1484 * @session_id: session id for the event
1485 * @type: event enum of type ipa_wlan_event
1486 * @mac_address: MAC address associated with the event
1487 *
1488 * This function is meant to be called from within wlan_ipa_ctx.c
1489 *
1490 * Return: QDF STATUS
1491 */
1492static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1493 uint8_t sta_id, uint8_t session_id,
1494 qdf_ipa_wlan_event type,
1495 uint8_t *mac_addr)
1496{
1497 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1498 struct wlan_ipa_iface_context *iface_ctx = NULL;
1499 qdf_ipa_msg_meta_t meta;
1500 qdf_ipa_wlan_msg_t *msg;
1501 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1502 int i;
1503 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001504 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301505 struct wlan_objmgr_pdev *pdev;
1506 struct wlan_objmgr_psoc *psoc;
1507 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301508
Mohit Khannacabf5e72018-07-24 13:28:43 -07001509 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d session_id: %u",
1510 net_dev->name, type, mac_addr, sta_id, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301511
1512 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1513 return QDF_STATUS_E_INVAL;
1514
1515 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1516 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1517 (device_mode != QDF_SAP_MODE)) {
1518 return QDF_STATUS_SUCCESS;
1519 }
1520
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301521 pdev = ipa_ctx->pdev;
1522 psoc = wlan_pdev_get_psoc(pdev);
1523 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1524 WLAN_IPA_ID);
1525 QDF_BUG((session_id < WLAN_IPA_MAX_SESSION) && vdev);
1526 if (vdev)
1527 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
1528
Ryan Hsub5783cf2018-05-14 12:13:15 -07001529 if (ipa_ctx->sta_connected) {
1530 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1531 if (iface_ctx)
1532 sta_session_id = iface_ctx->session_id;
1533 else
1534 ipa_err("sta iface_ctx is NULL");
1535 }
1536
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301537 /*
1538 * During IPA UC resource loading/unloading new events can be issued.
1539 */
1540 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1541 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1542 unsigned int pending_event_count;
1543 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1544
1545 ipa_info("Event:%d IPA resource %s inprogress", type,
1546 ipa_ctx->resource_loading ?
1547 "load" : "unload");
1548
1549 /* Wait until completion of the long/unloading */
1550 status = qdf_wait_for_event_completion(
1551 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001552 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301553 if (status != QDF_STATUS_SUCCESS) {
1554 /*
1555 * If timed out, store the events separately and
1556 * handle them later.
1557 */
1558 ipa_info("IPA resource %s timed out",
1559 ipa_ctx->resource_loading ?
1560 "load" : "unload");
1561
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301562 if (type == QDF_IPA_AP_DISCONNECT)
1563 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1564 SIR_AP_RX_DATA_OFFLOAD,
1565 session_id, false);
1566
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301567 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1568
1569 pending_event_count =
1570 qdf_list_size(&ipa_ctx->pending_event);
1571 if (pending_event_count >=
1572 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1573 ipa_info("Reached max pending evt count");
1574 qdf_list_remove_front(
1575 &ipa_ctx->pending_event,
1576 (qdf_list_node_t **)&pending_event);
1577 } else {
1578 pending_event =
1579 (struct wlan_ipa_uc_pending_event *)
1580 qdf_mem_malloc(sizeof(
1581 struct wlan_ipa_uc_pending_event));
1582 }
1583
1584 if (!pending_event) {
1585 ipa_err("Pending event memory alloc fail");
1586 qdf_mutex_release(&ipa_ctx->ipa_lock);
1587 return QDF_STATUS_E_NOMEM;
1588 }
1589
1590 pending_event->net_dev = net_dev;
1591 pending_event->device_mode = device_mode;
1592 pending_event->sta_id = sta_id;
1593 pending_event->session_id = session_id;
1594 pending_event->type = type;
1595 pending_event->is_loading = ipa_ctx->resource_loading;
1596 qdf_mem_copy(pending_event->mac_addr,
1597 mac_addr, QDF_MAC_ADDR_SIZE);
1598 qdf_list_insert_back(&ipa_ctx->pending_event,
1599 &pending_event->node);
1600
1601 qdf_mutex_release(&ipa_ctx->ipa_lock);
1602
Yun Park21ec4902018-04-24 12:11:01 -07001603 /* Cleanup interface */
1604 if (type == QDF_IPA_STA_DISCONNECT ||
1605 type == QDF_IPA_AP_DISCONNECT) {
1606 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1607 iface_ctx = &ipa_ctx->iface_context[i];
1608
1609 if (iface_ctx->dev == net_dev)
1610 break;
1611 }
1612 if (iface_ctx)
1613 wlan_ipa_cleanup_iface(iface_ctx);
1614 }
1615
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301616 return QDF_STATUS_SUCCESS;
1617 }
1618 ipa_info("IPA resource %s completed",
1619 ipa_ctx->resource_loading ?
1620 "load" : "unload");
1621 }
1622
1623 ipa_ctx->stats.event[type]++;
1624
1625 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1626 switch (type) {
1627 case QDF_IPA_STA_CONNECT:
1628 qdf_mutex_acquire(&ipa_ctx->event_lock);
1629
1630 /* STA already connected and without disconnect, connect again
1631 * This is Roaming scenario
1632 */
1633 if (ipa_ctx->sta_connected) {
1634 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1635 if (iface_ctx)
1636 wlan_ipa_cleanup_iface(iface_ctx);
1637 }
1638
1639 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1640 sta_id, session_id);
1641 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001642 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301643 qdf_mutex_release(&ipa_ctx->event_lock);
1644 goto end;
1645 }
1646
1647 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1648 (ipa_ctx->sap_num_connected_sta > 0) &&
1649 !ipa_ctx->sta_connected) {
1650 qdf_mutex_release(&ipa_ctx->event_lock);
1651 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1652 SIR_STA_RX_DATA_OFFLOAD, session_id,
1653 true);
1654 qdf_mutex_acquire(&ipa_ctx->event_lock);
1655 }
1656
1657 ipa_ctx->vdev_to_iface[session_id] =
1658 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1659
1660 ipa_ctx->sta_connected = 1;
1661
1662 qdf_mutex_release(&ipa_ctx->event_lock);
1663
Mohit Khannacabf5e72018-07-24 13:28:43 -07001664 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1665 ipa_ctx->sta_connected,
1666 session_id,
1667 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301668 break;
1669
1670 case QDF_IPA_AP_CONNECT:
1671 qdf_mutex_acquire(&ipa_ctx->event_lock);
1672
1673 /* For DFS channel we get two start_bss event (before and after
1674 * CAC). Also when ACS range includes both DFS and non DFS
1675 * channels, we could possibly change channel many times due to
1676 * RADAR detection and chosen channel may not be a DFS channels.
1677 * So dont return error here. Just discard the event.
1678 */
jiadc908ada2018-05-11 14:40:54 +08001679 if (ipa_ctx->vdev_to_iface[session_id] !=
1680 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301681 qdf_mutex_release(&ipa_ctx->event_lock);
1682 return 0;
1683 }
1684
1685 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1686 sta_id, session_id);
1687 if (status != QDF_STATUS_SUCCESS) {
1688 qdf_mutex_release(&ipa_ctx->event_lock);
1689 ipa_err("%s: Evt: %d, Interface setup failed",
1690 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1691 goto end;
1692 }
1693
1694 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1695 qdf_mutex_release(&ipa_ctx->event_lock);
1696 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1697 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1698 qdf_mutex_acquire(&ipa_ctx->event_lock);
1699 }
1700
1701 ipa_ctx->vdev_to_iface[session_id] =
1702 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001703 ipa_debug("vdev_to_iface[%u]=%u",
1704 session_id,
1705 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301706 qdf_mutex_release(&ipa_ctx->event_lock);
1707 break;
1708
1709 case QDF_IPA_STA_DISCONNECT:
1710 qdf_mutex_acquire(&ipa_ctx->event_lock);
1711
1712 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301713 struct wlan_ipa_iface_context *iface;
1714
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301715 qdf_mutex_release(&ipa_ctx->event_lock);
1716 ipa_err("%s: Evt: %d, STA already disconnected",
1717 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301718
1719 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1720 if (iface && (iface->dev == net_dev))
1721 wlan_ipa_cleanup_iface(iface);
1722
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301723 return QDF_STATUS_E_INVAL;
1724 }
1725
1726 ipa_ctx->sta_connected = 0;
1727
1728 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1729 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1730 msg_ex->name);
1731 } else {
1732 /* Disable IPA UC TX PIPE when STA disconnected */
1733 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001734 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001735 !ipa_ctx->ipa_pipes_down &&
1736 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001737 if (cds_is_driver_unloading()) {
1738 /*
1739 * We disable WDI pipes directly here
1740 * since IPA_OPCODE_TX/RX_SUSPEND
1741 * message will not be processed when
1742 * unloading WLAN driver is in progress
1743 */
1744 wlan_ipa_uc_disable_pipes(ipa_ctx);
1745 } else {
1746 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1747 }
1748 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301749 }
1750
1751 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1752 (ipa_ctx->sap_num_connected_sta > 0)) {
1753 qdf_mutex_release(&ipa_ctx->event_lock);
1754 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1755 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1756 qdf_mutex_acquire(&ipa_ctx->event_lock);
1757 ipa_ctx->vdev_to_iface[session_id] =
1758 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001759 ipa_debug("vdev_to_iface[%u]=%u",
1760 session_id,
1761 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301762 }
1763
1764 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1765 iface_ctx = &ipa_ctx->iface_context[i];
1766
1767 if (iface_ctx->dev == net_dev)
1768 break;
1769 }
1770 if (i < WLAN_IPA_MAX_IFACE)
1771 wlan_ipa_cleanup_iface(iface_ctx);
1772
1773 qdf_mutex_release(&ipa_ctx->event_lock);
1774
1775 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1776 break;
1777
1778 case QDF_IPA_AP_DISCONNECT:
1779 qdf_mutex_acquire(&ipa_ctx->event_lock);
1780
1781 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001782 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001783 !ipa_ctx->ipa_pipes_down &&
1784 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301785 if (cds_is_driver_unloading()) {
1786 /*
1787 * We disable WDI pipes directly here since
1788 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1789 * processed when unloading WLAN driver is in
1790 * progress
1791 */
1792 wlan_ipa_uc_disable_pipes(ipa_ctx);
1793 } else {
1794 /*
1795 * This shouldn't happen :
1796 * No interface left but WDI pipes are still
1797 * active - force close WDI pipes
1798 */
1799 ipa_err("No interface left but WDI pipes are still active");
1800 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1801 }
1802 }
1803
1804 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1805 qdf_mutex_release(&ipa_ctx->event_lock);
1806 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1807 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1808 qdf_mutex_acquire(&ipa_ctx->event_lock);
1809 ipa_ctx->vdev_to_iface[session_id] =
1810 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001811 ipa_debug("vdev_to_iface[%u]=%u",
1812 session_id,
1813 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301814 }
1815
1816 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1817 iface_ctx = &ipa_ctx->iface_context[i];
1818
1819 if (iface_ctx->dev == net_dev)
1820 break;
1821 }
1822 if (i < WLAN_IPA_MAX_IFACE)
1823 wlan_ipa_cleanup_iface(iface_ctx);
1824
1825 qdf_mutex_release(&ipa_ctx->event_lock);
1826 break;
1827
1828 case QDF_IPA_CLIENT_CONNECT_EX:
1829 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1830 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1831 net_dev->name, type);
1832 return QDF_STATUS_SUCCESS;
1833 }
1834
1835 qdf_mutex_acquire(&ipa_ctx->event_lock);
1836 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1837 mac_addr)) {
1838 qdf_mutex_release(&ipa_ctx->event_lock);
1839 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1840 return QDF_STATUS_SUCCESS;
1841 }
1842
1843 /* Enable IPA UC Data PIPEs when first STA connected */
1844 if (ipa_ctx->sap_num_connected_sta == 0 &&
1845 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301846
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301847 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1848 ipa_ctx->sta_connected) {
1849 qdf_mutex_release(&ipa_ctx->event_lock);
1850 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1851 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301852 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301853 qdf_mutex_acquire(&ipa_ctx->event_lock);
1854 }
1855
1856 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1857 if (status != QDF_STATUS_SUCCESS) {
1858 ipa_info("%s: handle 1st con fail",
1859 net_dev->name);
1860
1861 if (wlan_ipa_uc_sta_is_enabled(
1862 ipa_ctx->config) &&
1863 ipa_ctx->sta_connected) {
1864 qdf_mutex_release(&ipa_ctx->event_lock);
1865 wlan_ipa_uc_offload_enable_disable(
1866 ipa_ctx,
1867 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301868 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301869 } else {
1870 qdf_mutex_release(&ipa_ctx->event_lock);
1871 }
1872
1873 return status;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001874 } else
1875 ipa_debug("%s: handle 1st con success",
1876 net_dev->name);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301877 }
1878
1879 ipa_ctx->sap_num_connected_sta++;
1880
1881 qdf_mutex_release(&ipa_ctx->event_lock);
1882
1883 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1884 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1885 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1886 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1887 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1888
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001889 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301890 ipa_err("msg_ex allocation failed");
1891 return QDF_STATUS_E_NOMEM;
1892 }
1893 strlcpy(msg_ex->name, net_dev->name,
1894 IPA_RESOURCE_NAME_MAX);
1895 msg_ex->num_of_attribs = 1;
1896 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1897 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1898 msg_ex->attribs[0].offset =
1899 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1900 } else {
1901 msg_ex->attribs[0].offset =
1902 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1903 }
1904 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1905 IPA_MAC_ADDR_SIZE);
1906
1907 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1908 ipa_info("%s: Evt: %d send ipa msg fail",
1909 net_dev->name, type);
1910 qdf_mem_free(msg_ex);
1911 return QDF_STATUS_E_FAILURE;
1912 }
1913 ipa_ctx->stats.num_send_msg++;
1914
1915 ipa_info("sap_num_connected_sta=%d",
1916 ipa_ctx->sap_num_connected_sta);
1917
1918 return QDF_STATUS_SUCCESS;
1919
1920 case WLAN_CLIENT_DISCONNECT:
1921 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1922 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1923 msg_ex->name);
1924 return QDF_STATUS_SUCCESS;
1925 }
1926
1927 qdf_mutex_acquire(&ipa_ctx->event_lock);
1928 if (!ipa_ctx->sap_num_connected_sta) {
1929 qdf_mutex_release(&ipa_ctx->event_lock);
1930 ipa_err("%s: Evt: %d, Client already disconnected",
1931 msg_ex->name,
1932 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1933
1934 return QDF_STATUS_SUCCESS;
1935 }
1936 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
1937 sta_id, mac_addr)) {
1938 qdf_mutex_release(&ipa_ctx->event_lock);
1939 ipa_err("%s: STA ID %d NOT found, not valid",
1940 msg_ex->name, sta_id);
1941
1942 return QDF_STATUS_SUCCESS;
1943 }
1944 ipa_ctx->sap_num_connected_sta--;
1945
1946 /* Disable IPA UC TX PIPE when last STA disconnected */
1947 if (!ipa_ctx->sap_num_connected_sta &&
1948 ipa_ctx->uc_loaded == true) {
Yun Parka29974a2018-04-09 12:05:49 -07001949 if ((false == ipa_ctx->resource_unloading) &&
1950 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
1951 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08001952 if (cds_is_driver_unloading()) {
1953 /*
1954 * We disable WDI pipes directly here
1955 * since IPA_OPCODE_TX/RX_SUSPEND
1956 * message will not be processed when
1957 * unloading WLAN driver is in progress
1958 */
1959 wlan_ipa_uc_disable_pipes(ipa_ctx);
1960 } else {
1961 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1962 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301963 }
1964
1965 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1966 ipa_ctx->sta_connected) {
1967 qdf_mutex_release(&ipa_ctx->event_lock);
1968 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1969 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301970 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301971 } else {
1972 qdf_mutex_release(&ipa_ctx->event_lock);
1973 }
1974 } else {
1975 qdf_mutex_release(&ipa_ctx->event_lock);
1976 }
1977
1978 ipa_info("sap_num_connected_sta=%d",
1979 ipa_ctx->sap_num_connected_sta);
1980 break;
1981
1982 default:
1983 return QDF_STATUS_SUCCESS;
1984 }
1985
1986 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
1987 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1988 if (!msg) {
1989 ipa_err("msg allocation failed");
1990 return QDF_STATUS_E_NOMEM;
1991 }
1992
1993 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1994 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
1995 IPA_RESOURCE_NAME_MAX);
1996 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
1997
1998 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
1999 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2000
2001 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2002
2003 ipa_err("%s: Evt: %d fail",
2004 QDF_IPA_WLAN_MSG_NAME(msg),
2005 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2006 qdf_mem_free(msg);
2007
2008 return QDF_STATUS_E_FAILURE;
2009 }
2010
2011 ipa_ctx->stats.num_send_msg++;
2012
2013end:
2014 return QDF_STATUS_SUCCESS;
2015}
2016
2017/**
2018 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002019 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302020 *
2021 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2022 */
2023static qdf_ipa_wlan_event
2024wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2025{
Yun Park84fbb272018-04-02 15:31:01 -07002026 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302027
2028 switch (wlan_ipa_event_type) {
2029 case WLAN_IPA_CLIENT_CONNECT:
2030 ipa_event = QDF_IPA_CLIENT_CONNECT;
2031 break;
2032 case WLAN_IPA_CLIENT_DISCONNECT:
2033 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2034 break;
2035 case WLAN_IPA_AP_CONNECT:
2036 ipa_event = QDF_IPA_AP_CONNECT;
2037 break;
2038 case WLAN_IPA_AP_DISCONNECT:
2039 ipa_event = QDF_IPA_AP_DISCONNECT;
2040 break;
2041 case WLAN_IPA_STA_CONNECT:
2042 ipa_event = QDF_IPA_STA_CONNECT;
2043 break;
2044 case WLAN_IPA_STA_DISCONNECT:
2045 ipa_event = QDF_IPA_STA_DISCONNECT;
2046 break;
2047 case WLAN_IPA_CLIENT_CONNECT_EX:
2048 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2049 break;
2050 case WLAN_IPA_WLAN_EVENT_MAX:
2051 default:
2052 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2053 break;
2054 }
2055
2056 return ipa_event;
2057}
2058
2059/**
2060 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2061 * @net_dev: Interface net device
2062 * @device_mode: Net interface device mode
2063 * @sta_id: station id for the event
2064 * @session_id: session id for the event
2065 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2066 * @mac_address: MAC address associated with the event
2067 *
2068 * Return: QDF_STATUS
2069 */
2070QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
2071 uint8_t sta_id, uint8_t session_id,
2072 enum wlan_ipa_wlan_event ipa_event_type,
2073 uint8_t *mac_addr)
2074{
2075 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2076 QDF_STATUS status = QDF_STATUS_SUCCESS;
2077
2078 /* Data path offload only support for STA and SAP mode */
2079 if ((device_mode == QDF_STA_MODE) ||
2080 (device_mode == QDF_SAP_MODE))
2081 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
2082 session_id, type, mac_addr);
2083
2084 return status;
2085}
2086
2087/**
2088 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2089 * @ipa_ctx: Global IPA IPA context
2090 * @is_loading: Indicate if invoked during loading
2091 *
2092 * Return: None
2093 */
2094static void
2095wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2096{
2097 unsigned int pending_event_count;
2098 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2099
2100 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2101 ipa_debug("Pending Event Count %d", pending_event_count);
2102 if (!pending_event_count) {
2103 ipa_debug("No Pending Event");
2104 return;
2105 }
2106
2107 qdf_list_remove_front(&ipa_ctx->pending_event,
2108 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002109 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302110 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2111 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2112 struct wlan_objmgr_vdev *vdev =
2113 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2114 pending_event->session_id,
2115 WLAN_IPA_ID);
2116 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302117 __wlan_ipa_wlan_evt(pending_event->net_dev,
2118 pending_event->device_mode,
2119 pending_event->sta_id,
2120 pending_event->session_id,
2121 pending_event->type,
2122 pending_event->mac_addr);
2123 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302124
2125 if (vdev)
2126 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302127 qdf_mem_free(pending_event);
2128 pending_event = NULL;
2129 qdf_list_remove_front(&ipa_ctx->pending_event,
2130 (qdf_list_node_t **)&pending_event);
2131 }
2132}
2133
2134/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002135 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2136 * @ipa_ctx: IPA context
2137 *
2138 * Return: None
2139 */
2140static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2141{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302142 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002143 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302144 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002145
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302146 if (!ipa_ctx->tx_desc_pool)
2147 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002148
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302149 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2150 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2151 for (i = 0; i < pool_size; i++) {
2152 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002153 if (ipa_tx_desc)
2154 qdf_ipa_free_skb(ipa_tx_desc);
2155
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302156 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2157 &ipa_ctx->tx_desc_pool[i].node) !=
2158 QDF_STATUS_SUCCESS)
2159 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002160 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302161 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2162
2163 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2164 qdf_mem_free(ipa_ctx->tx_desc_pool);
2165 ipa_ctx->tx_desc_pool = NULL;
2166
2167 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2168 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002169}
2170
2171/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302172 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302173 * @ipa_ctx: IPA context
2174 *
2175 * Return: QDF_STATUS
2176 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302177static QDF_STATUS
2178wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302179{
2180 int i;
2181 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302182
2183 max_desc_cnt = ipa_ctx->config->txbuf_count;
2184
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302185 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2186 max_desc_cnt);
2187
2188 if (!ipa_ctx->tx_desc_pool) {
2189 ipa_err("Free Tx descriptor allocation failed");
2190 return QDF_STATUS_E_NOMEM;
2191 }
2192
2193 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302194
2195 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2196 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302197 ipa_ctx->tx_desc_pool[i].id = i;
2198 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2199 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2200 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302201 }
2202
2203 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2204 ipa_ctx->stats.num_tx_desc_error = 0;
2205
2206 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2207
2208 return QDF_STATUS_SUCCESS;
2209}
2210
2211#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2212/**
2213 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2214 * @ipa_ctx: Global IPA IPA context
2215 * @desc_fifo_sz: Number of descriptors
2216 *
2217 * Return: 0 on success, negative errno on error
2218 */
2219static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2220 int32_t desc_fifo_sz)
2221{
2222 int i, ret = 0;
2223 qdf_ipa_sys_connect_params_t *ipa;
2224
2225 /*setup TX pipes */
2226 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2227 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2228
2229 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2230 ipa->desc_fifo_sz = desc_fifo_sz;
2231 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302232 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302233
2234 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2235 ipa->ipa_ep_cfg.hdr.hdr_len =
2236 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2237 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2238 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2239 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2240 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2241 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2242 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2243 } else {
2244 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2245 }
2246 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2247
2248 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2249 &ipa_ctx->sys_pipe[i].conn_hdl);
2250 if (ret) {
2251 ipa_err("Failed for pipe %d ret: %d", i, ret);
2252 return ret;
2253 }
2254 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2255 }
2256
2257 return ret;
2258}
2259#else
2260/**
2261 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302262 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302263 * @desc_fifo_sz: Number of descriptors
2264 *
2265 * Return: 0 on success, negative errno on error
2266 */
2267static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2268 int32_t desc_fifo_sz)
2269{
2270 /*
2271 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2272 * is enabled, where per vdev descriptors are supported in firmware.
2273 */
2274 return 0;
2275}
2276#endif
2277
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302278#ifdef CONFIG_IPA_WDI_UNIFIED_API
2279/**
2280 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2281 * @ipa_ctx: IPA context
2282 *
2283 * Return: rx ipa sys client
2284 */
2285static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2286{
2287 if (ipa_ctx->over_gsi)
2288 return IPA_CLIENT_WLAN2_PROD;
2289 else
2290 return IPA_CLIENT_WLAN1_PROD;
2291}
2292#else
2293static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2294{
2295 return IPA_CLIENT_WLAN1_PROD;
2296}
2297#endif
2298
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302299/**
2300 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2301 * @ipa_ctx: Global IPA IPA context
2302 * @desc_fifo_sz: Number of descriptors
2303 *
2304 * Return: 0 on success, negative errno on error
2305 */
2306static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2307 int32_t desc_fifo_sz)
2308{
2309 int ret = 0;
2310 qdf_ipa_sys_connect_params_t *ipa;
2311
2312 /*
2313 * Hard code it here, this can be extended if in case
2314 * PROD pipe is also per interface.
2315 * Right now there is no advantage of doing this.
2316 */
2317 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2318
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302319 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302320 ipa->desc_fifo_sz = desc_fifo_sz;
2321 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302322 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302323
2324 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2325 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2326 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2327 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2328
2329 ret = qdf_ipa_setup_sys_pipe(ipa,
2330 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2331 if (ret) {
2332 ipa_err("Failed for RX pipe: %d", ret);
2333 return ret;
2334 }
2335 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2336
2337 return ret;
2338}
2339
2340/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002341 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2342 * @ipa_ctx: Global IPA IPA context
2343 *
2344 * Return: None
2345 */
2346static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2347{
2348 int ret, i;
2349
2350 if (!ipa_ctx)
2351 return;
2352
2353 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2354 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2355 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2356 ipa_ctx->sys_pipe[i].conn_hdl);
2357 if (ret)
2358 ipa_err("Failed:%d", ret);
2359
2360 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2361 }
2362 }
2363
2364 wlan_ipa_free_tx_desc_list(ipa_ctx);
2365}
2366
2367/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302368 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2369 * @ipa_ctx: Global IPA IPA context
2370 *
2371 * Return: 0 on success, negative errno on error
2372 */
2373static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2374{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002375 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302376 uint32_t desc_fifo_sz;
2377
2378 /* The maximum number of descriptors that can be provided to a BAM at
2379 * once is one less than the total number of descriptors that the buffer
2380 * can contain.
2381 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2382 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2383 * be provided at once.
2384 * Because of above requirement, one extra descriptor will be added to
2385 * make sure hardware always has one descriptor.
2386 */
2387 desc_fifo_sz = ipa_ctx->config->desc_size
2388 + SPS_DESC_SIZE;
2389
2390 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2391 if (ret) {
2392 ipa_err("Failed for TX pipe: %d", ret);
2393 goto setup_sys_pipe_fail;
2394 }
2395
2396 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2397 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2398 if (ret) {
2399 ipa_err("Failed for RX pipe: %d", ret);
2400 goto setup_sys_pipe_fail;
2401 }
2402 }
2403
2404 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302405 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302406 if (ret)
2407 goto setup_sys_pipe_fail;
2408
2409 return ret;
2410
2411setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002412 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302413
2414 return ret;
2415}
2416
jiadbb47e132018-03-30 16:28:30 +08002417#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2418QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2419 bool mcc_mode)
2420{
2421 qdf_ipa_msg_meta_t meta;
2422 qdf_ipa_wlan_msg_t *msg;
2423 int ret;
2424
2425 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2426 return QDF_STATUS_SUCCESS;
2427
2428 /* Send SCC/MCC Switching event to IPA */
2429 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2430 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002431 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002432 ipa_err("msg allocation failed");
2433 return QDF_STATUS_E_NOMEM;
2434 }
2435
jiad629b2172018-05-11 15:34:22 +08002436 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002437 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002438 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2439 } else {
jiadbb47e132018-03-30 16:28:30 +08002440 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002441 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2442 }
2443
jiadbb47e132018-03-30 16:28:30 +08002444 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2445 "ipa_send_msg(Evt:%d)",
2446 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2447
2448 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2449
2450 if (ret) {
2451 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2452 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2453 qdf_mem_free(msg);
2454 return QDF_STATUS_E_FAILURE;
2455 }
2456
2457 return QDF_STATUS_SUCCESS;
2458}
2459
2460static void wlan_ipa_mcc_work_handler(void *data)
2461{
2462 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2463
2464 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2465}
2466#endif
2467
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302468/**
2469 * wlan_ipa_setup() - IPA initialization function
2470 * @ipa_ctx: IPA context
2471 * @ipa_cfg: IPA config
2472 *
2473 * Allocate ipa_ctx resources, ipa pipe resource and register
2474 * wlan interface with IPA module.
2475 *
2476 * Return: QDF_STATUS enumeration
2477 */
2478QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2479 struct wlan_ipa_config *ipa_cfg)
2480{
2481 int ret, i;
2482 struct wlan_ipa_iface_context *iface_context = NULL;
2483 QDF_STATUS status;
2484
2485 ipa_debug("enter");
2486
2487 gp_ipa = ipa_ctx;
2488 ipa_ctx->num_iface = 0;
2489 ipa_ctx->config = ipa_cfg;
2490
2491 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2492
2493 /* Create the interface context */
2494 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2495 iface_context = &ipa_ctx->iface_context[i];
2496 iface_context->ipa_ctx = ipa_ctx;
2497 iface_context->cons_client =
2498 wlan_ipa_iface_2_client[i].cons_client;
2499 iface_context->prod_client =
2500 wlan_ipa_iface_2_client[i].prod_client;
2501 iface_context->iface_id = i;
2502 iface_context->dev = NULL;
2503 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2504 iface_context->tl_context = NULL;
2505 qdf_spinlock_create(&iface_context->interface_lock);
2506 }
2507
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302508 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302509 qdf_spinlock_create(&ipa_ctx->pm_lock);
2510 qdf_spinlock_create(&ipa_ctx->q_lock);
2511 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2512 qdf_list_create(&ipa_ctx->pending_event, 1000);
2513 qdf_mutex_create(&ipa_ctx->event_lock);
2514 qdf_mutex_create(&ipa_ctx->ipa_lock);
2515
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302516 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2517 if (status != QDF_STATUS_SUCCESS)
2518 goto fail_setup_rm;
2519
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302520 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2521 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2522 sizeof(struct wlan_ipa_sys_pipe));
2523
2524 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2525 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2526 ipa_ctx->sap_num_connected_sta = 0;
2527 ipa_ctx->ipa_tx_packets_diff = 0;
2528 ipa_ctx->ipa_rx_packets_diff = 0;
2529 ipa_ctx->ipa_p_tx_packets = 0;
2530 ipa_ctx->ipa_p_rx_packets = 0;
2531 ipa_ctx->resource_loading = false;
2532 ipa_ctx->resource_unloading = false;
2533 ipa_ctx->sta_connected = 0;
2534 ipa_ctx->ipa_pipes_down = true;
2535 ipa_ctx->wdi_enabled = false;
2536 /* Setup IPA system pipes */
2537 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2538 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2539 if (ret)
2540 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002541
2542 qdf_create_work(0, &ipa_ctx->mcc_work,
2543 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302544 }
2545
2546 status = wlan_ipa_wdi_init(ipa_ctx);
2547 if (status == QDF_STATUS_E_BUSY)
2548 status = wlan_ipa_uc_send_wdi_control_msg(false);
2549 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002550 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302551 goto fail_create_sys_pipe;
2552 }
2553 } else {
2554 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2555 if (ret)
2556 goto fail_create_sys_pipe;
2557 }
2558
2559 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2560
2561 ipa_debug("exit: success");
2562
2563 return QDF_STATUS_SUCCESS;
2564
2565fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302566 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2567
2568fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302569 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302570 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2571 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2572 iface_context = &ipa_ctx->iface_context[i];
2573 qdf_spinlock_destroy(&iface_context->interface_lock);
2574 }
2575 qdf_mutex_destroy(&ipa_ctx->event_lock);
2576 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2577 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302578 gp_ipa = NULL;
2579 ipa_debug("exit: fail");
2580
2581 return QDF_STATUS_E_FAILURE;
2582}
2583
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302584void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2585{
2586 qdf_nbuf_t skb;
2587 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2588
2589 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2590 return;
2591
2592 qdf_cancel_work(&ipa_ctx->pm_work);
2593
2594 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2595
2596 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2597 != NULL)) {
2598 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2599
2600 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002601
2602 if (pm_tx_cb->exception) {
2603 dev_kfree_skb_any(skb);
2604 } else {
2605 if (pm_tx_cb->ipa_tx_desc)
2606 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2607 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302608
2609 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2610 }
2611 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2612}
2613
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302614QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2615{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302616 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302617 int i;
2618
2619 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2620 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2621
2622 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002623 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302624 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002625 qdf_cancel_work(&ipa_ctx->mcc_work);
2626 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302627
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302628 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2629
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302630 wlan_ipa_flush(ipa_ctx);
2631
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302632 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2633 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2634
2635 /* destroy the interface lock */
2636 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2637 iface_context = &ipa_ctx->iface_context[i];
2638 qdf_spinlock_destroy(&iface_context->interface_lock);
2639 }
2640
2641 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2642 wlan_ipa_wdi_cleanup();
2643 qdf_mutex_destroy(&ipa_ctx->event_lock);
2644 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2645 qdf_list_destroy(&ipa_ctx->pending_event);
2646
2647 }
2648
2649 gp_ipa = NULL;
2650
2651 return QDF_STATUS_SUCCESS;
2652}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302653
2654struct wlan_ipa_iface_context
2655*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2656{
2657 struct wlan_ipa_iface_context *iface_ctx = NULL;
2658 int i;
2659
2660 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2661 iface_ctx = &ipa_ctx->iface_context[i];
2662
2663 if (iface_ctx->device_mode == mode)
2664 return iface_ctx;
2665 }
2666
2667 return NULL;
2668}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302669
jiadbb47e132018-03-30 16:28:30 +08002670void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302671{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302672 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002673 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302674
jiadbb47e132018-03-30 16:28:30 +08002675 if (ipa_ctx->mcc_mode == mcc_mode)
2676 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302677
jiadbb47e132018-03-30 16:28:30 +08002678 ipa_ctx->mcc_mode = mcc_mode;
2679 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302680}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302681
2682/**
2683 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2684 * @ipa_ctx: ipa ipa local context
2685 *
2686 * Will handle IPA UC image loaded indication comes from IPA kernel
2687 *
2688 * Return: None
2689 */
2690static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2691{
2692 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2693 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2694 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2695 QDF_STATUS status;
2696
2697 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002698
2699 if (!qdf_dev) {
2700 ipa_err("qdf device is NULL!");
2701 return;
2702 }
2703
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302704 if (true == ipa_ctx->uc_loaded) {
2705 ipa_info("UC already loaded");
2706 return;
2707 }
2708
Lihua Liu15f6e452018-05-30 17:31:06 +08002709 if (!qdf_dev) {
2710 ipa_err("qdf_dev is null");
2711 return;
2712 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302713 /* Connect pipe */
2714 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2715 if (status) {
2716 ipa_err("Failure to setup IPA pipes (status=%d)",
2717 status);
2718 return;
2719 }
2720
2721 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302722
2723 /* If already any STA connected, enable IPA/FW PIPEs */
2724 if (ipa_ctx->sap_num_connected_sta) {
2725 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2726 wlan_ipa_uc_handle_first_con(ipa_ctx);
2727 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302728}
2729
2730/**
2731 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2732 * @op_msg: operation message received from firmware
2733 * @usr_ctxt: user context registered with TL (we register the IPA Global
2734 * context)
2735 *
2736 * Return: None
2737 */
2738static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2739 struct wlan_ipa_priv *ipa_ctx)
2740{
2741 struct op_msg_type *msg = op_msg;
2742 struct ipa_uc_fw_stats *uc_fw_stat;
2743
2744 if (!op_msg) {
2745 ipa_err("INVALID ARG");
2746 return;
2747 }
2748
2749 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2750 ipa_err("INVALID OPCODE %d", msg->op_code);
2751 qdf_mem_free(op_msg);
2752 return;
2753 }
2754
2755 ipa_debug("OPCODE=%d", msg->op_code);
2756
2757 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2758 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2759 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2760 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07002761 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302762 ipa_ctx->resource_loading = false;
2763 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2764 if (ipa_ctx->wdi_enabled == false) {
2765 ipa_ctx->wdi_enabled = true;
2766 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2767 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2768 ipa_ctx->mcc_mode);
2769 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302770 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302771 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07002772 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302773 QDF_IPA_RM_RESOURCE_GRANTED,
2774 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2775 ipa_ctx->pending_cons_req = false;
2776 }
2777 qdf_mutex_release(&ipa_ctx->ipa_lock);
2778 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2779 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2780 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05302781
2782 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
2783 wlan_ipa_uc_disable_pipes(ipa_ctx);
2784 ipa_info("Disable FW TX PIPE");
2785 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2786 false, true);
2787 }
2788
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302789 ipa_ctx->activated_fw_pipe--;
2790 if (!ipa_ctx->activated_fw_pipe) {
2791 /*
2792 * Async return success from FW
2793 * Disable/suspend all the PIPEs
2794 */
2795 ipa_ctx->resource_unloading = false;
2796 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302797 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07002798 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
2799 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302800 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302801 ipa_ctx->pending_cons_req = false;
2802 }
2803 qdf_mutex_release(&ipa_ctx->ipa_lock);
2804 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2805 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2806 uc_fw_stat = (struct ipa_uc_fw_stats *)
2807 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2808
2809 /* WLAN FW WDI stats */
2810 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2811 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2812 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2813 /* STATs from FW */
2814 uc_fw_stat = (struct ipa_uc_fw_stats *)
2815 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2816 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2817 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2818 uc_fw_stat->tx_pkts_completed,
2819 ipa_ctx->ipa_p_tx_packets);
2820 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2821 (uc_fw_stat->rx_num_ind_drop_no_space +
2822 uc_fw_stat->rx_num_ind_drop_no_buf +
2823 uc_fw_stat->rx_num_pkts_indicated),
2824 ipa_ctx->ipa_p_rx_packets);
2825
2826 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2827 ipa_ctx->ipa_p_rx_packets =
2828 (uc_fw_stat->rx_num_ind_drop_no_space +
2829 uc_fw_stat->rx_num_ind_drop_no_buf +
2830 uc_fw_stat->rx_num_pkts_indicated);
2831 qdf_mutex_release(&ipa_ctx->ipa_lock);
2832 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2833 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2834 wlan_ipa_uc_loaded_handler(ipa_ctx);
2835 qdf_mutex_release(&ipa_ctx->ipa_lock);
2836 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2837 ipa_err("Invalid message: op_code=%d, reason=%d",
2838 msg->op_code, ipa_ctx->stat_req_reason);
2839 }
2840
2841 qdf_mem_free(op_msg);
2842}
2843
2844/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302845 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2846 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302847 *
2848 * Return: None
2849 */
jitiphilfdcaaba2018-09-03 16:19:52 +05302850static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302851{
2852 struct op_msg_type *msg;
2853 struct uc_op_work_struct *uc_op_work =
2854 (struct uc_op_work_struct *)data;
2855 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2856
jitiphilfdcaaba2018-09-03 16:19:52 +05302857 if (qdf_is_module_state_transitioning()) {
2858 ipa_err("Module transition in progress");
2859 return;
2860 }
2861
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302862 msg = uc_op_work->msg;
2863 uc_op_work->msg = NULL;
2864 ipa_debug("posted msg %d", msg->op_code);
2865
2866 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2867}
2868
2869/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302870 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
2871 * __wlan_ipa_uc_fw_op_event_handler
2872 * @data: uC OP work
2873 *
2874 * Return: None
2875 */
2876static void wlan_ipa_uc_fw_op_event_handler(void *data)
2877{
2878 qdf_ssr_protect(__func__);
2879 __wlan_ipa_uc_fw_op_event_handler(data);
2880 qdf_ssr_unprotect(__func__);
2881}
2882
2883/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302884 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2885 * @op_msg: operation message received from firmware
2886 * @ipa_ctx: Global IPA context
2887 *
2888 * Return: None
2889 */
2890static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2891{
2892 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2893 struct op_msg_type *msg;
2894 struct uc_op_work_struct *uc_op_work;
2895
2896 if (!ipa_ctx)
2897 goto end;
2898
2899 msg = (struct op_msg_type *)op_msg;
2900
2901 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2902 ipa_err("Invalid OP Code (%d)", msg->op_code);
2903 goto end;
2904 }
2905
2906 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2907 if (uc_op_work->msg) {
2908 /* When the same uC OPCODE is already pended, just return */
2909 goto end;
2910 }
2911
2912 uc_op_work->msg = msg;
2913 qdf_sched_work(0, &uc_op_work->work);
2914 return;
2915
2916end:
2917 qdf_mem_free(op_msg);
2918}
2919
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302920QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2921 qdf_device_t osdev)
2922{
2923 uint8_t i;
2924 QDF_STATUS status = QDF_STATUS_SUCCESS;
2925
2926 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2927 return QDF_STATUS_SUCCESS;
2928
2929 ipa_debug("enter");
2930
2931 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
2932 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
2933 ipa_ctx->vdev_offload_enabled[i] = false;
2934 }
2935
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302936 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
2937 ipa_err("IPA UC resource alloc fail");
2938 status = QDF_STATUS_E_FAILURE;
2939 goto fail_return;
2940 }
2941
2942 if (true == ipa_ctx->uc_loaded) {
2943 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
2944 if (status) {
2945 ipa_err("Failure to setup IPA pipes (status=%d)",
2946 status);
2947 status = QDF_STATUS_E_FAILURE;
2948 goto fail_return;
2949 }
2950
2951 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
2952 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08002953
2954 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
2955 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302956 }
2957
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302958 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2959 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
2960
2961 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2962 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
2963 wlan_ipa_uc_fw_op_event_handler,
2964 &ipa_ctx->uc_op_work[i]);
2965 ipa_ctx->uc_op_work[i].msg = NULL;
2966 }
2967
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302968fail_return:
2969 ipa_debug("exit: status=%d", status);
2970 return status;
2971}
2972
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302973/**
2974 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
2975 * @ipa_ctx: pointer to IPA IPA struct
2976 *
2977 * Return: none
2978 */
2979static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
2980{
2981 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2982
2983 while (qdf_list_remove_front(&ipa_ctx->pending_event,
2984 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
2985 qdf_mem_free(pending_event);
2986}
2987
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302988QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
2989{
2990 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302991 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302992
2993 ipa_debug("enter");
2994
2995 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2996 return status;
2997
2998 if (!ipa_ctx->ipa_pipes_down)
2999 wlan_ipa_uc_disable_pipes(ipa_ctx);
3000
3001 if (true == ipa_ctx->uc_loaded) {
3002 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3003 ipa_ctx->tx_pipe_handle,
3004 ipa_ctx->rx_pipe_handle);
3005 if (status)
3006 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3007 status);
3008 }
3009
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303010 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3011 wlan_ipa_cleanup_pending_event(ipa_ctx);
3012 qdf_mutex_release(&ipa_ctx->ipa_lock);
3013
3014 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3015 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3016 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3017 ipa_ctx->uc_op_work[i].msg = NULL;
3018 }
3019
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303020 ipa_debug("exit: ret=%d", status);
3021 return status;
3022}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303023
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303024/**
3025 * wlan_ipa_uc_send_evt() - send event to ipa
3026 * @net_dev: Interface net device
3027 * @type: event type
3028 * @mac_addr: pointer to mac address
3029 *
3030 * Send event to IPA driver
3031 *
3032 * Return: QDF_STATUS
3033 */
3034static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3035 qdf_ipa_wlan_event type,
3036 uint8_t *mac_addr)
3037{
3038 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3039 qdf_ipa_msg_meta_t meta;
3040 qdf_ipa_wlan_msg_t *msg;
3041
3042 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3043 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3044 if (!msg) {
3045 ipa_err("msg allocation failed");
3046 return QDF_STATUS_E_NOMEM;
3047 }
3048
3049 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3050 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3051 IPA_RESOURCE_NAME_MAX);
3052 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3053
3054 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3055 ipa_err("%s: Evt: %d fail",
3056 QDF_IPA_WLAN_MSG_NAME(msg),
3057 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3058 qdf_mem_free(msg);
3059
3060 return QDF_STATUS_E_FAILURE;
3061 }
3062
3063 ipa_ctx->stats.num_send_msg++;
3064
3065 return QDF_STATUS_SUCCESS;
3066}
3067
3068QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3069 qdf_netdev_t net_dev)
3070{
3071 struct wlan_ipa_iface_context *iface_ctx;
3072 QDF_STATUS status;
3073
3074 ipa_debug("enter");
3075
3076 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3077 if (iface_ctx)
3078 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3079 net_dev->dev_addr);
3080 else
3081 return QDF_STATUS_E_INVAL;
3082
3083 ipa_debug("exit :%d", status);
3084
3085 return status;
3086}
3087
3088void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3089 qdf_netdev_t net_dev)
3090{
3091 struct wlan_ipa_iface_context *iface_ctx;
3092 int i;
3093
3094 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3095 iface_ctx = &ipa_ctx->iface_context[i];
3096 if (iface_ctx->dev == net_dev)
3097 break;
3098 }
3099
3100 if (iface_ctx)
3101 wlan_ipa_cleanup_iface(iface_ctx);
3102}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303103
3104void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3105{
3106 struct wlan_ipa_iface_context *iface;
3107 int i;
3108
3109 ipa_info("enter");
3110
3111 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3112 iface = &ipa_ctx->iface_context[i];
3113 if (iface->dev) {
3114 if (iface->device_mode == QDF_SAP_MODE)
3115 wlan_ipa_uc_send_evt(iface->dev,
3116 QDF_IPA_AP_DISCONNECT,
3117 iface->dev->dev_addr);
3118 else if (iface->device_mode == QDF_STA_MODE)
3119 wlan_ipa_uc_send_evt(iface->dev,
3120 QDF_IPA_STA_DISCONNECT,
3121 iface->dev->dev_addr);
3122 wlan_ipa_cleanup_iface(iface);
3123 }
3124 }
3125}
jitiphil0e3b5922018-07-24 18:43:50 +05303126
3127void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3128{
3129 qdf_ipa_msg_meta_t meta;
3130 qdf_ipa_wlan_msg_t *msg;
3131 int ret;
3132
3133 meta.msg_len = sizeof(*msg);
3134 msg = qdf_mem_malloc(meta.msg_len);
3135 if (!msg) {
3136 ipa_debug("msg allocation failed");
3137 return;
3138 }
3139
3140 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3141 ipa_debug("ipa_send_msg(Evt:%d)",
3142 meta.msg_type);
3143 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3144
3145 if (ret) {
3146 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3147 meta.msg_type, ret);
3148 qdf_mem_free(msg);
3149 }
3150 ipa_ctx->stats.num_send_msg++;
3151}