blob: 22cf649b301770c8bacd6422079ab7e1d99a991d [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),
324 sys_in);
325}
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
376 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700377 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530378 ipa_ctx->uc_loaded = true;
379 ipa_ctx->is_smmu_enabled =
380 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
Dustin Brown7e761c72018-07-31 13:50:17 -0700381 ipa_debug("is_smmu_enabled=%d", ipa_ctx->is_smmu_enabled);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530382 } else {
383 return QDF_STATUS_E_BUSY;
384 }
385
386 return QDF_STATUS_SUCCESS;
387}
388
389static inline int wlan_ipa_wdi_cleanup(void)
390{
391 int ret;
392
393 ret = qdf_ipa_wdi_cleanup();
394 if (ret)
395 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
396 return ret;
397}
398
399static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
400 struct ipa_sys_connect_params *sys,
401 uint32_t *handle)
402{
403 return 0;
404}
405
406static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
407 uint32_t handle)
408{
409 return 0;
410}
411
Yun Parke74e6092018-04-27 11:36:34 -0700412/**
413 * wlan_ipa_pm_flush() - flush queued packets
414 * @work: pointer to the scheduled work
415 *
416 * Called during PM resume to send packets to TL which were queued
417 * while host was in the process of suspending.
418 *
419 * Return: None
420 */
421static void wlan_ipa_pm_flush(void *data)
422{
423 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
424 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
425 qdf_nbuf_t skb;
426 uint32_t dequeued = 0;
427
428 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
429 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
430 NULL)) {
431 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
432
433 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
434 dequeued++;
435
jiadab8cea02018-05-24 09:16:14 +0800436 if (pm_tx_cb->exception) {
437 if (ipa_ctx->softap_xmit &&
438 pm_tx_cb->iface_context->dev) {
439 ipa_ctx->softap_xmit(skb,
440 pm_tx_cb->iface_context->dev);
441 ipa_ctx->stats.num_tx_fwd_ok++;
442 } else {
443 dev_kfree_skb_any(skb);
444 }
445 } else {
446 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
447 pm_tx_cb->ipa_tx_desc);
448 }
Yun Parke74e6092018-04-27 11:36:34 -0700449
450 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
451 }
452 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
453
454 ipa_ctx->stats.num_tx_dequeued += dequeued;
455 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
456 ipa_ctx->stats.num_max_pm_queue = dequeued;
457}
458
jiadae9959f2018-05-08 11:19:07 +0800459int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
460{
461 if (!num_buf) {
462 ipa_info("No buffers to map/unmap");
463 return 0;
464 }
465
466 if (map)
467 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
468 else
469 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
470}
471
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530472#else /* CONFIG_IPA_WDI_UNIFIED_API */
473
474static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
475{
476}
477
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530478static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
479 qdf_device_t osdev)
480{
481 return qdf_mem_smmu_s1_enabled(osdev);
482}
483
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530484static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
485 qdf_device_t osdev)
486{
487 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
488 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
489 wlan_ipa_wdi_meter_notifier_cb,
490 ipa_ctx->config->desc_size,
491 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
492 &ipa_ctx->tx_pipe_handle,
493 &ipa_ctx->rx_pipe_handle);
494}
495
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530496static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
497{
498 struct ipa_wdi_uc_ready_params uc_ready_param;
499
500 ipa_ctx->uc_loaded = false;
501 uc_ready_param.priv = (void *)ipa_ctx;
502 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
503 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
504 ipa_info("UC Ready CB register fail");
505 return QDF_STATUS_E_FAILURE;
506 }
507
508 if (true == uc_ready_param.is_uC_ready) {
509 ipa_info("UC Ready");
510 ipa_ctx->uc_loaded = true;
511 } else {
512 return QDF_STATUS_E_BUSY;
513 }
514
515 return QDF_STATUS_SUCCESS;
516}
517
518static inline int wlan_ipa_wdi_cleanup(void)
519{
520 int ret;
521
522 ret = qdf_ipa_uc_dereg_rdyCB();
523 if (ret)
524 ipa_info("UC Ready CB deregister fail");
525 return ret;
526}
527
528static inline int wlan_ipa_wdi_setup_sys_pipe(
529 struct wlan_ipa_priv *ipa_ctx,
530 struct ipa_sys_connect_params *sys, uint32_t *handle)
531{
532 return qdf_ipa_setup_sys_pipe(sys, handle);
533}
534
535static inline int wlan_ipa_wdi_teardown_sys_pipe(
536 struct wlan_ipa_priv *ipa_ctx,
537 uint32_t handle)
538{
539 return qdf_ipa_teardown_sys_pipe(handle);
540}
541
Yun Parke74e6092018-04-27 11:36:34 -0700542/**
543 * wlan_ipa_pm_flush() - flush queued packets
544 * @work: pointer to the scheduled work
545 *
546 * Called during PM resume to send packets to TL which were queued
547 * while host was in the process of suspending.
548 *
549 * Return: None
550 */
551static void wlan_ipa_pm_flush(void *data)
552{
553 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
554 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
555 qdf_nbuf_t skb;
556 uint32_t dequeued = 0;
557
558 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
559 WIFI_POWER_EVENT_WAKELOCK_IPA);
560 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
561 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
562 NULL)) {
563 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
564
565 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
566 dequeued++;
567
jiadab8cea02018-05-24 09:16:14 +0800568 if (pm_tx_cb->exception) {
569 if (ipa_ctx->softap_xmit &&
570 pm_tx_cb->iface_context->dev) {
571 ipa_ctx->softap_xmit(skb,
572 pm_tx_cb->iface_context->dev);
573 ipa_ctx->stats.num_tx_fwd_ok++;
574 } else {
575 dev_kfree_skb_any(skb);
576 }
577 } else {
578 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
579 pm_tx_cb->ipa_tx_desc);
580 }
Yun Parke74e6092018-04-27 11:36:34 -0700581
582 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
583 }
584 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
585 qdf_wake_lock_release(&ipa_ctx->wake_lock,
586 WIFI_POWER_EVENT_WAKELOCK_IPA);
587
588 ipa_ctx->stats.num_tx_dequeued += dequeued;
589 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
590 ipa_ctx->stats.num_max_pm_queue = dequeued;
591}
592
jiadae9959f2018-05-08 11:19:07 +0800593int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
594{
595 if (!num_buf) {
596 ipa_info("No buffers to map/unmap");
597 return 0;
598 }
599
600 if (map)
601 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
602 else
603 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
604}
605
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530606#endif /* CONFIG_IPA_WDI_UNIFIED_API */
607
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530608/**
609 * wlan_ipa_send_skb_to_network() - Send skb to kernel
610 * @skb: network buffer
611 * @iface_ctx: IPA interface context
612 *
613 * Called when a network buffer is received which should not be routed
614 * to the IPA module.
615 *
616 * Return: None
617 */
618static void
619wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
620 struct wlan_ipa_iface_context *iface_ctx)
621{
622 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
623
624 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800625 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530626 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800627 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530628 return;
629 }
630
631 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
632
633 if (ipa_ctx->send_to_nw)
634 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
635
636 ipa_ctx->ipa_rx_net_send_count++;
637}
638
639/**
640 * wlan_ipa_forward() - handle packet forwarding to wlan tx
641 * @ipa_ctx: pointer to ipa ipa context
642 * @iface_ctx: interface context
643 * @skb: data pointer
644 *
645 * if exception packet has set forward bit, copied new packet should be
646 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
647 * put into pm queue and tx procedure will be differed
648 *
649 * Return: None
650 */
651static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
652 struct wlan_ipa_iface_context *iface_ctx,
653 qdf_nbuf_t skb)
654{
655 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
656
657 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
658
659 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
660 qdf_nbuf_ipa_owned_set(skb);
661
662 /* WLAN subsystem is in suspend, put in queue */
663 if (ipa_ctx->suspended) {
664 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
jiadf3ecc752018-07-05 14:36:03 +0800665 ipa_info_rl("Tx in suspend, put in queue");
hangtian127c9532019-01-12 13:29:07 +0800666 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530667 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
668 pm_tx_cb->exception = true;
669 pm_tx_cb->iface_context = iface_ctx;
670 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
671 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
672 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
673 ipa_ctx->stats.num_tx_queued++;
674 } else {
675 /* Resume, put packet into WLAN TX */
676 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
677
678 if (ipa_ctx->softap_xmit) {
679 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
jiadf3ecc752018-07-05 14:36:03 +0800680 ipa_err_rl("packet Tx fail");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530681 ipa_ctx->stats.num_tx_fwd_err++;
682 } else {
683 ipa_ctx->stats.num_tx_fwd_ok++;
684 }
685 } else {
jiadab8cea02018-05-24 09:16:14 +0800686 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530687 }
688 }
689}
690
691/**
692 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
693 * @ipa_ctx: pointer to IPA IPA struct
694 * @iface_ctx: ipa interface context
695 * @desc: Firmware descriptor
696 * @skb: Data buffer
697 *
698 * Return:
699 * WLAN_IPA_FORWARD_PKT_NONE
700 * WLAN_IPA_FORWARD_PKT_DISCARD
701 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
702 *
703 */
704
705static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
706 struct wlan_ipa_priv *ipa_ctx,
707 struct wlan_ipa_iface_context *iface_ctx,
708 uint8_t desc,
709 qdf_nbuf_t skb)
710{
711 int ret = WLAN_IPA_FORWARD_PKT_NONE;
712 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Sravan Kumar Kairamf48210c2018-12-17 17:48:10 +0530713 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530714
715 if ((desc & FW_RX_DESC_FORWARD_M)) {
Sravan Kumar Kairamf48210c2018-12-17 17:48:10 +0530716 void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
717 iface_ctx->session_id);
718 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530719 /* Drop the packet*/
720 ipa_ctx->stats.num_tx_fwd_err++;
jiadab8cea02018-05-24 09:16:14 +0800721 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530722 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
723 return ret;
724 }
jiadf3ecc752018-07-05 14:36:03 +0800725 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530726 ipa_ctx->ipa_tx_forward++;
727
728 if ((desc & FW_RX_DESC_DISCARD_M)) {
729 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
730 ipa_ctx->ipa_rx_internal_drop_count++;
731 ipa_ctx->ipa_rx_discard++;
732 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
733 } else {
734 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
735
736 if (cloned_skb)
737 wlan_ipa_forward(ipa_ctx, iface_ctx,
738 cloned_skb);
739 else
jiadf3ecc752018-07-05 14:36:03 +0800740 ipa_err_rl("tx skb alloc failed");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530741 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
742 }
743 }
744
745 return ret;
746}
747
748/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530749 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530750 * @priv: pointer to private data registered with IPA (we register a
751 * pointer to the global IPA context)
752 * @evt: the IPA event which triggered the callback
753 * @data: data associated with the event
754 *
755 * Return: None
756 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530757static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
758 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530759{
760 struct wlan_ipa_priv *ipa_ctx = NULL;
761 qdf_nbuf_t skb;
762 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700763 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530764 struct wlan_ipa_iface_context *iface_context;
765 uint8_t fw_desc;
766
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530767 ipa_ctx = (struct wlan_ipa_priv *)priv;
768 if (!ipa_ctx) {
769 if (evt == IPA_RECEIVE) {
770 skb = (qdf_nbuf_t)data;
771 dev_kfree_skb_any(skb);
772 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530773 return;
774 }
775
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530776 if (qdf_is_module_state_transitioning()) {
777 ipa_err_rl("Module transition in progress");
778 if (evt == IPA_RECEIVE) {
779 skb = (qdf_nbuf_t)data;
780 ipa_ctx->ipa_rx_internal_drop_count++;
781 dev_kfree_skb_any(skb);
782 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530783 return;
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530784 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530785
786 switch (evt) {
787 case IPA_RECEIVE:
788 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530789 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
790 session_id = (uint8_t)skb->cb[0];
791 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530792 } else {
793 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
794 }
795 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700796 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
797 iface_id, session_id, (uint8_t)skb->cb[1],
798 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530799 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800800 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530801 return;
802 }
803
804 iface_context = &ipa_ctx->iface_context[iface_id];
805 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800806 ipa_err_rl("TL context of iface_id %u is NULL",
807 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530808 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800809 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530810 return;
811 }
812
813 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
814 ipa_ctx->stats.num_rx_excep++;
815 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
816 } else {
817 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
818 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530819 iface_context->stats.num_rx_ipa_excep++;
820
821 /* Disable to forward Intra-BSS Rx packets when
822 * ap_isolate=1 in hostapd.conf
823 */
824 if (!ipa_ctx->ap_intrabss_fwd) {
825 /*
826 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
827 * all Rx packets to IPA uC, which need to be forwarded
828 * to other interface.
829 * And, IPA driver will send back to WLAN host driver
830 * through exception pipe with fw_desc field set by FW.
831 * Here we are checking fw_desc field for FORWARD bit
832 * set, and forward to Tx. Then copy to kernel stack
833 * only when DISCARD bit is not set.
834 */
835 fw_desc = (uint8_t)skb->cb[1];
836 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
837 wlan_ipa_intrabss_forward(ipa_ctx, iface_context,
838 fw_desc, skb))
839 break;
840 } else {
jiadf3ecc752018-07-05 14:36:03 +0800841 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530842 }
843
844 wlan_ipa_send_skb_to_network(skb, iface_context);
845 break;
846
847 default:
jiadf3ecc752018-07-05 14:36:03 +0800848 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530849 return;
850 }
851}
852
853/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530854 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
855 * @priv: pointer to private data registered with IPA (we register a
856 * pointer to the global IPA context)
857 * @evt: the IPA event which triggered the callback
858 * @data: data associated with the event
859 *
860 * Return: None
861 */
862static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
863 unsigned long data)
864{
865 qdf_ssr_protect(__func__);
866 __wlan_ipa_w2i_cb(priv, evt, data);
867 qdf_ssr_unprotect(__func__);
868}
869
870/**
871 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530872 * @priv: pointer to private data registered with IPA (we register a
873 * pointer to the interface-specific IPA context)
874 * @evt: the IPA event which triggered the callback
875 * @data: data associated with the event
876 *
877 * Return: None
878 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530879static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
880 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530881{
882 struct wlan_ipa_priv *ipa_ctx = NULL;
883 qdf_ipa_rx_data_t *ipa_tx_desc;
884 struct wlan_ipa_iface_context *iface_context;
885 qdf_nbuf_t skb;
886 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
887
888 iface_context = (struct wlan_ipa_iface_context *)priv;
889 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
890 ipa_ctx = iface_context->ipa_ctx;
891
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530892 if (qdf_is_module_state_transitioning()) {
893 ipa_err_rl("Module transition in progress");
894 ipa_free_skb(ipa_tx_desc);
895 iface_context->stats.num_tx_drop++;
896 return;
897 }
898
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530899 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +0800900 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530901 ipa_free_skb(ipa_tx_desc);
902 iface_context->stats.num_tx_drop++;
903 return;
904 }
905
906 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
907
908 /*
909 * If PROD resource is not requested here then there may be cases where
910 * IPA hardware may be clocked down because of not having proper
911 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
912 * workaround to request PROD resource while data is going over CONS
913 * pipe to prevent the IPA hardware clockdown.
914 */
915 wlan_ipa_wdi_rm_request(ipa_ctx);
916
917 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
918 /*
919 * If host is still suspended then queue the packets and these will be
920 * drained later when resume completes. When packet is arrived here and
921 * host is suspended, this means that there is already resume is in
922 * progress.
923 */
924 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +0800925 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530926 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
927 pm_tx_cb->iface_context = iface_context;
928 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
929 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
930 ipa_ctx->stats.num_tx_queued++;
931
932 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
933 return;
934 }
935
936 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
937
938 /*
939 * If we are here means, host is not suspended, wait for the work queue
940 * to finish.
941 */
942 qdf_flush_work(&ipa_ctx->pm_work);
943
944 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
945}
946
jitiphilfdcaaba2018-09-03 16:19:52 +0530947/**
948 * wlan_ipa_i2w_cb() - IPA to WLAN callback
949 * @priv: pointer to private data registered with IPA (we register a
950 * pointer to the interface-specific IPA context)
951 * @evt: the IPA event which triggered the callback
952 * @data: data associated with the event
953 *
954 * Return: None
955 */
956static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
957 unsigned long data)
958{
959 qdf_ssr_protect(__func__);
960 __wlan_ipa_i2w_cb(priv, evt, data);
961 qdf_ssr_unprotect(__func__);
962}
963
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530964QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
965{
966 /*
967 * Check if IPA is ready for suspend, If we are here means, there is
968 * high chance that suspend would go through but just to avoid any race
969 * condition after suspend started, these checks are conducted before
970 * allowing to suspend.
971 */
972 if (atomic_read(&ipa_ctx->tx_ref_cnt))
973 return QDF_STATUS_E_AGAIN;
974
Yun Parke74e6092018-04-27 11:36:34 -0700975 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530976 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530977
978 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
979 ipa_ctx->suspended = true;
980 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
981
982 return QDF_STATUS_SUCCESS;
983}
984
985QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
986{
987 qdf_sched_work(0, &ipa_ctx->pm_work);
988
989 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
990 ipa_ctx->suspended = false;
991 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
992
993 return QDF_STATUS_SUCCESS;
994}
995
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +0530996QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
997{
998 int result;
999
1000 ipa_debug("enter");
1001
1002 if (!ipa_ctx->ipa_pipes_down) {
1003 /*
1004 * IPA WDI Pipes are already activated due to
1005 * rm deferred resources grant
1006 */
1007 ipa_warn("IPA WDI Pipes are already activated");
1008 goto end;
1009 }
1010
1011 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1012 ipa_ctx->dp_pdev);
1013 if (result) {
1014 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1015 return QDF_STATUS_E_FAILURE;
1016 }
1017
1018 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1019 ipa_ctx->ipa_pipes_down = false;
1020
1021 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1022 ipa_ctx->dp_pdev);
1023
1024end:
1025 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1026
1027 return QDF_STATUS_SUCCESS;
1028}
1029
1030QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1031{
1032 int result;
1033
1034 ipa_debug("enter");
1035
1036 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301037 ipa_warn("IPA WDI Pipes are already deactivated");
1038 goto end;
1039 }
1040
1041 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1042 ipa_ctx->dp_pdev);
1043
1044 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1045 ipa_ctx->dp_pdev);
1046 if (result) {
1047 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
1048 return QDF_STATUS_E_FAILURE;
1049 }
1050
1051 ipa_ctx->ipa_pipes_down = true;
1052
1053end:
1054 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1055
1056 return QDF_STATUS_SUCCESS;
1057}
1058
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301059/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301060 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1061 * @ipa_ctx: Global IPA IPA context
1062 * @sta_add: Should station be added
1063 * @sta_id: ID of the station being queried
1064 *
1065 * Return: true if the station was found
1066 */
1067static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
1068 bool sta_add, uint8_t sta_id,
1069 uint8_t *mac_addr)
1070{
1071 bool sta_found = false;
1072 uint8_t idx;
1073
1074 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1075 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1076 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1077 sta_found = true;
1078 break;
1079 }
1080 }
1081 if (sta_add && sta_found) {
1082 ipa_err("STA ID %d already exist, cannot add", sta_id);
1083 return sta_found;
1084 }
1085 if (sta_add) {
1086 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1087 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1088 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
1089 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
1090 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1091 mac_addr, mac_addr,
1092 QDF_NET_ETH_LEN);
1093 return sta_found;
1094 }
1095 }
1096 }
1097 if (!sta_add && !sta_found) {
1098 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
1099 return sta_found;
1100 }
1101 if (!sta_add) {
1102 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1103 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1104 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1105 ipa_ctx->assoc_stas_map[idx].is_reserved =
1106 false;
1107 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
hangtian127c9532019-01-12 13:29:07 +08001108 qdf_mem_zero(
1109 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1110 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301111 return sta_found;
1112 }
1113 }
1114 }
1115
1116 return sta_found;
1117}
1118
1119/**
1120 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1121 * @ipa_ctx: IPA context
1122 * @session_id: Session ID
1123 *
1124 * Return: None
1125 */
1126static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1127 uint8_t session_id)
1128{
1129 struct wlan_ipa_iface_context *iface_ctx;
1130 int i;
1131
1132 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1133 iface_ctx = &ipa_ctx->iface_context[i];
1134 if (iface_ctx->session_id == session_id)
1135 break;
1136 }
1137
1138 return i;
1139}
1140
1141/**
1142 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1143 * @iface_context: interface-specific IPA context
1144 *
1145 * Return: None
1146 */
1147static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1148{
1149 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1150
1151 ipa_debug("enter");
1152
1153 if (!iface_context->tl_context)
1154 return;
1155
1156 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1157 iface_context->dev->name,
1158 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1159
1160 qdf_spin_lock_bh(&iface_context->interface_lock);
1161 iface_context->tl_context = NULL;
1162 iface_context->dev = NULL;
1163 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1164 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1165 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1166 qdf_spin_unlock_bh(&iface_context->interface_lock);
1167 iface_context->ifa_address = 0;
1168 if (!iface_context->ipa_ctx->num_iface) {
1169 ipa_err("NUM INTF 0, Invalid");
1170 QDF_ASSERT(0);
1171 }
1172 iface_context->ipa_ctx->num_iface--;
1173 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1174}
1175
1176/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301177 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1178 * @skb: packet buffer which was transmitted
1179 *
1180 * Return: None
1181 */
1182static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1183{
1184 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1185 qdf_ipa_rx_data_t *ipa_tx_desc;
1186 struct wlan_ipa_tx_desc *tx_desc;
1187 uint16_t id;
1188
1189 if (!qdf_nbuf_ipa_owned_get(skb)) {
1190 dev_kfree_skb_any(skb);
1191 return;
1192 }
1193
1194 /* Get Tx desc pointer from SKB CB */
1195 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1196 tx_desc = &ipa_ctx->tx_desc_pool[id];
1197 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1198
1199 /* Return Tx Desc to IPA */
1200 qdf_ipa_free_skb(ipa_tx_desc);
1201
1202 /* Return to free tx desc list */
1203 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1204 tx_desc->ipa_tx_desc_ptr = NULL;
1205 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1206 ipa_ctx->stats.num_tx_desc_q_cnt--;
1207 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1208
1209 ipa_ctx->stats.num_tx_comp_cnt++;
1210
1211 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1212
1213 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1214}
1215
1216/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301217 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1218 * @ipa_ctx: IPA IPA global context
1219 * @net_dev: Interface net device
1220 * @device_mode: Net interface device mode
1221 * @adapter: Interface upon which IPA is being setup
1222 * @sta_id: Station ID of the API instance
1223 * @session_id: Station ID of the API instance
1224 *
1225 * Return: QDF STATUS
1226 */
1227static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1228 qdf_netdev_t net_dev,
1229 uint8_t device_mode, uint8_t sta_id,
1230 uint8_t session_id)
1231{
1232 struct wlan_ipa_iface_context *iface_context = NULL;
1233 void *tl_context = NULL;
1234 int i;
1235 QDF_STATUS status;
1236
1237 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1238 * channel change indication. Since these indications are sent by lower
1239 * layer as SAP updates and IPA doesn't have to do anything for these
1240 * updates so ignoring!
1241 */
1242 if (device_mode == QDF_SAP_MODE) {
1243 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1244 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001245 if (iface_context->dev == net_dev) {
1246 ipa_debug("found iface %u device_mode %u",
1247 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301248 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001249 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301250 }
1251 }
1252
Yun Park21ec4902018-04-24 12:11:01 -07001253 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1254 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1255 status = QDF_STATUS_E_NOMEM;
1256 QDF_ASSERT(0);
1257 goto end;
1258 }
1259
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301260 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1261 if (ipa_ctx->iface_context[i].tl_context == NULL) {
1262 iface_context = &(ipa_ctx->iface_context[i]);
1263 break;
1264 }
1265 }
1266
1267 if (iface_context == NULL) {
1268 ipa_err("All the IPA interfaces are in use");
1269 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001270 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301271 goto end;
1272 }
1273
1274 iface_context->sta_id = sta_id;
1275 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1276 ipa_ctx->dp_pdev,
1277 sta_id);
1278 if (tl_context == NULL) {
1279 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1280 status = QDF_STATUS_E_INVAL;
1281 goto end;
1282 }
1283
1284 iface_context->tl_context = tl_context;
1285 iface_context->dev = net_dev;
1286 iface_context->device_mode = device_mode;
1287 iface_context->session_id = session_id;
1288
1289 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1290 net_dev->dev_addr,
1291 iface_context->prod_client,
1292 iface_context->cons_client,
1293 session_id,
1294 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1295 if (status != QDF_STATUS_SUCCESS)
1296 goto end;
1297
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301298 /* Register IPA Tx desc free callback */
1299 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1300
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301301 ipa_ctx->num_iface++;
1302
1303 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1304
1305 return status;
1306
1307end:
1308 if (iface_context)
1309 wlan_ipa_cleanup_iface(iface_context);
1310
1311 return status;
1312}
1313
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301314#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1315/**
1316 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1317 * @ipa_ctx: IPA context
1318 *
1319 * Return: QDF STATUS
1320 */
1321static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1322{
1323 ipa_debug("enter");
1324
1325 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1326 ipa_err("IPA WDI Pipe activation failed");
1327 return QDF_STATUS_E_BUSY;
1328 }
1329
1330 ipa_debug("exit");
1331
1332 return QDF_STATUS_SUCCESS;
1333}
1334
1335/**
1336 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1337 * @ipa_ctx: IPA context
1338 *
1339 * Return: None
1340 */
1341static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1342{
1343 ipa_debug("enter");
1344
1345 wlan_ipa_uc_disable_pipes(ipa_ctx);
1346
1347 ipa_debug("exit: IPA WDI Pipes deactivated");
1348}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301349
1350bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1351{
1352 return !ipa_ctx->ipa_pipes_down;
1353}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301354#else
1355
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301356/**
1357 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1358 * @ipa_ctx: IPA context
1359 *
1360 * Return: QDF STATUS
1361 */
1362static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1363{
1364 ipa_debug("enter");
1365
1366 ipa_ctx->activated_fw_pipe = 0;
1367 ipa_ctx->resource_loading = true;
1368
1369 /* If RM feature enabled
1370 * Request PROD Resource first
1371 * PROD resource may return sync or async manners
1372 */
1373 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001374 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1375 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301376 /* RM PROD request sync return
1377 * enable pipe immediately
1378 */
1379 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1380 ipa_err("IPA WDI Pipe activation failed");
1381 ipa_ctx->resource_loading = false;
1382 return QDF_STATUS_E_BUSY;
1383 }
1384 } else {
1385 ipa_err("IPA WDI Pipe activation deferred");
1386 }
1387 } else {
1388 /* RM Disabled
1389 * Just enabled all the PIPEs
1390 */
1391 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1392 ipa_err("IPA WDI Pipe activation failed");
1393 ipa_ctx->resource_loading = false;
1394 return QDF_STATUS_E_BUSY;
1395 }
1396 ipa_ctx->resource_loading = false;
1397 }
1398
1399 ipa_debug("exit");
1400
1401 return QDF_STATUS_SUCCESS;
1402}
1403
1404/**
1405 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1406 * @ipa_ctx: IPA context
1407 *
1408 * Return: None
1409 */
1410static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1411{
1412 ipa_debug("enter");
1413
1414 ipa_ctx->resource_unloading = true;
1415 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1416 ipa_info("Disable FW RX PIPE");
1417 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301418
1419 ipa_debug("exit: IPA WDI Pipes deactivated");
1420}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301421
1422bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1423{
1424 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1425}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301426#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301427
1428/**
1429 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1430 * @ipa_ctx: global IPA context
1431 * @offload_type: MCC or SCC
1432 * @session_id: Session Id
1433 * @enable: TX offload enable or disable
1434 *
1435 * Return: none
1436 */
1437static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1438 uint32_t offload_type,
1439 uint8_t session_id,
1440 bool enable)
1441{
1442
1443 struct ipa_uc_offload_control_params req = {0};
1444
1445 if (session_id >= WLAN_IPA_MAX_SESSION) {
1446 ipa_err("invalid session id: %d", session_id);
1447 return;
1448 }
1449
1450 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301451 ipa_info("IPA offload status is already set");
1452 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301453 offload_type, session_id, enable);
1454 return;
1455 }
1456
1457 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1458 offload_type, session_id, enable);
1459
1460 req.offload_type = offload_type;
1461 req.vdev_id = session_id;
1462 req.enable = enable;
1463
1464 if (QDF_STATUS_SUCCESS !=
1465 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1466 ipa_err("Fail to enable IPA offload");
1467 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1468 offload_type, session_id, enable);
1469 } else {
1470 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1471 }
1472}
1473
1474/**
1475 * __wlan_ipa_wlan_evt() - IPA event handler
1476 * @net_dev: Interface net device
1477 * @device_mode: Net interface device mode
1478 * @sta_id: station id for the event
1479 * @session_id: session id for the event
1480 * @type: event enum of type ipa_wlan_event
1481 * @mac_address: MAC address associated with the event
1482 *
1483 * This function is meant to be called from within wlan_ipa_ctx.c
1484 *
1485 * Return: QDF STATUS
1486 */
1487static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1488 uint8_t sta_id, uint8_t session_id,
1489 qdf_ipa_wlan_event type,
1490 uint8_t *mac_addr)
1491{
1492 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1493 struct wlan_ipa_iface_context *iface_ctx = NULL;
1494 qdf_ipa_msg_meta_t meta;
1495 qdf_ipa_wlan_msg_t *msg;
1496 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1497 int i;
1498 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001499 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301500 struct wlan_objmgr_pdev *pdev;
1501 struct wlan_objmgr_psoc *psoc;
1502 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301503
Mohit Khannacabf5e72018-07-24 13:28:43 -07001504 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d session_id: %u",
1505 net_dev->name, type, mac_addr, sta_id, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301506
1507 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1508 return QDF_STATUS_E_INVAL;
1509
1510 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1511 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1512 (device_mode != QDF_SAP_MODE)) {
1513 return QDF_STATUS_SUCCESS;
1514 }
1515
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301516 pdev = ipa_ctx->pdev;
1517 psoc = wlan_pdev_get_psoc(pdev);
1518 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1519 WLAN_IPA_ID);
1520 QDF_BUG((session_id < WLAN_IPA_MAX_SESSION) && vdev);
1521 if (vdev)
1522 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
1523
Ryan Hsub5783cf2018-05-14 12:13:15 -07001524 if (ipa_ctx->sta_connected) {
1525 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1526 if (iface_ctx)
1527 sta_session_id = iface_ctx->session_id;
1528 else
1529 ipa_err("sta iface_ctx is NULL");
1530 }
1531
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301532 /*
1533 * During IPA UC resource loading/unloading new events can be issued.
1534 */
1535 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1536 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1537 unsigned int pending_event_count;
1538 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1539
1540 ipa_info("Event:%d IPA resource %s inprogress", type,
1541 ipa_ctx->resource_loading ?
1542 "load" : "unload");
1543
1544 /* Wait until completion of the long/unloading */
1545 status = qdf_wait_for_event_completion(
1546 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001547 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301548 if (status != QDF_STATUS_SUCCESS) {
1549 /*
1550 * If timed out, store the events separately and
1551 * handle them later.
1552 */
1553 ipa_info("IPA resource %s timed out",
1554 ipa_ctx->resource_loading ?
1555 "load" : "unload");
1556
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301557 if (type == QDF_IPA_AP_DISCONNECT)
1558 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1559 SIR_AP_RX_DATA_OFFLOAD,
1560 session_id, false);
1561
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301562 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1563
1564 pending_event_count =
1565 qdf_list_size(&ipa_ctx->pending_event);
1566 if (pending_event_count >=
1567 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1568 ipa_info("Reached max pending evt count");
1569 qdf_list_remove_front(
1570 &ipa_ctx->pending_event,
1571 (qdf_list_node_t **)&pending_event);
1572 } else {
1573 pending_event =
1574 (struct wlan_ipa_uc_pending_event *)
1575 qdf_mem_malloc(sizeof(
1576 struct wlan_ipa_uc_pending_event));
1577 }
1578
1579 if (!pending_event) {
1580 ipa_err("Pending event memory alloc fail");
1581 qdf_mutex_release(&ipa_ctx->ipa_lock);
1582 return QDF_STATUS_E_NOMEM;
1583 }
1584
1585 pending_event->net_dev = net_dev;
1586 pending_event->device_mode = device_mode;
1587 pending_event->sta_id = sta_id;
1588 pending_event->session_id = session_id;
1589 pending_event->type = type;
1590 pending_event->is_loading = ipa_ctx->resource_loading;
1591 qdf_mem_copy(pending_event->mac_addr,
1592 mac_addr, QDF_MAC_ADDR_SIZE);
1593 qdf_list_insert_back(&ipa_ctx->pending_event,
1594 &pending_event->node);
1595
1596 qdf_mutex_release(&ipa_ctx->ipa_lock);
1597
Yun Park21ec4902018-04-24 12:11:01 -07001598 /* Cleanup interface */
1599 if (type == QDF_IPA_STA_DISCONNECT ||
1600 type == QDF_IPA_AP_DISCONNECT) {
1601 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1602 iface_ctx = &ipa_ctx->iface_context[i];
1603
1604 if (iface_ctx->dev == net_dev)
1605 break;
1606 }
1607 if (iface_ctx)
1608 wlan_ipa_cleanup_iface(iface_ctx);
1609 }
1610
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301611 return QDF_STATUS_SUCCESS;
1612 }
1613 ipa_info("IPA resource %s completed",
1614 ipa_ctx->resource_loading ?
1615 "load" : "unload");
1616 }
1617
1618 ipa_ctx->stats.event[type]++;
1619
1620 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1621 switch (type) {
1622 case QDF_IPA_STA_CONNECT:
1623 qdf_mutex_acquire(&ipa_ctx->event_lock);
1624
1625 /* STA already connected and without disconnect, connect again
1626 * This is Roaming scenario
1627 */
1628 if (ipa_ctx->sta_connected) {
1629 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1630 if (iface_ctx)
1631 wlan_ipa_cleanup_iface(iface_ctx);
1632 }
1633
1634 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1635 sta_id, session_id);
1636 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001637 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301638 qdf_mutex_release(&ipa_ctx->event_lock);
1639 goto end;
1640 }
1641
1642 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1643 (ipa_ctx->sap_num_connected_sta > 0) &&
1644 !ipa_ctx->sta_connected) {
1645 qdf_mutex_release(&ipa_ctx->event_lock);
1646 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1647 SIR_STA_RX_DATA_OFFLOAD, session_id,
1648 true);
1649 qdf_mutex_acquire(&ipa_ctx->event_lock);
1650 }
1651
1652 ipa_ctx->vdev_to_iface[session_id] =
1653 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1654
1655 ipa_ctx->sta_connected = 1;
1656
1657 qdf_mutex_release(&ipa_ctx->event_lock);
1658
Mohit Khannacabf5e72018-07-24 13:28:43 -07001659 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1660 ipa_ctx->sta_connected,
1661 session_id,
1662 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301663 break;
1664
1665 case QDF_IPA_AP_CONNECT:
1666 qdf_mutex_acquire(&ipa_ctx->event_lock);
1667
1668 /* For DFS channel we get two start_bss event (before and after
1669 * CAC). Also when ACS range includes both DFS and non DFS
1670 * channels, we could possibly change channel many times due to
1671 * RADAR detection and chosen channel may not be a DFS channels.
1672 * So dont return error here. Just discard the event.
1673 */
jiadc908ada2018-05-11 14:40:54 +08001674 if (ipa_ctx->vdev_to_iface[session_id] !=
1675 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301676 qdf_mutex_release(&ipa_ctx->event_lock);
1677 return 0;
1678 }
1679
1680 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1681 sta_id, session_id);
1682 if (status != QDF_STATUS_SUCCESS) {
1683 qdf_mutex_release(&ipa_ctx->event_lock);
1684 ipa_err("%s: Evt: %d, Interface setup failed",
1685 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1686 goto end;
1687 }
1688
1689 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1690 qdf_mutex_release(&ipa_ctx->event_lock);
1691 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1692 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1693 qdf_mutex_acquire(&ipa_ctx->event_lock);
1694 }
1695
1696 ipa_ctx->vdev_to_iface[session_id] =
1697 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001698 ipa_debug("vdev_to_iface[%u]=%u",
1699 session_id,
1700 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301701 qdf_mutex_release(&ipa_ctx->event_lock);
1702 break;
1703
1704 case QDF_IPA_STA_DISCONNECT:
1705 qdf_mutex_acquire(&ipa_ctx->event_lock);
1706
1707 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301708 struct wlan_ipa_iface_context *iface;
1709
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301710 qdf_mutex_release(&ipa_ctx->event_lock);
1711 ipa_err("%s: Evt: %d, STA already disconnected",
1712 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301713
1714 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1715 if (iface && (iface->dev == net_dev))
1716 wlan_ipa_cleanup_iface(iface);
1717
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301718 return QDF_STATUS_E_INVAL;
1719 }
1720
1721 ipa_ctx->sta_connected = 0;
1722
1723 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1724 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1725 msg_ex->name);
1726 } else {
1727 /* Disable IPA UC TX PIPE when STA disconnected */
1728 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001729 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001730 !ipa_ctx->ipa_pipes_down &&
1731 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001732 if (cds_is_driver_unloading()) {
1733 /*
1734 * We disable WDI pipes directly here
1735 * since IPA_OPCODE_TX/RX_SUSPEND
1736 * message will not be processed when
1737 * unloading WLAN driver is in progress
1738 */
1739 wlan_ipa_uc_disable_pipes(ipa_ctx);
1740 } else {
1741 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1742 }
1743 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301744 }
1745
1746 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1747 (ipa_ctx->sap_num_connected_sta > 0)) {
1748 qdf_mutex_release(&ipa_ctx->event_lock);
1749 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1750 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1751 qdf_mutex_acquire(&ipa_ctx->event_lock);
1752 ipa_ctx->vdev_to_iface[session_id] =
1753 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001754 ipa_debug("vdev_to_iface[%u]=%u",
1755 session_id,
1756 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301757 }
1758
1759 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1760 iface_ctx = &ipa_ctx->iface_context[i];
1761
1762 if (iface_ctx->dev == net_dev)
1763 break;
1764 }
1765 if (i < WLAN_IPA_MAX_IFACE)
1766 wlan_ipa_cleanup_iface(iface_ctx);
1767
1768 qdf_mutex_release(&ipa_ctx->event_lock);
1769
1770 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1771 break;
1772
1773 case QDF_IPA_AP_DISCONNECT:
1774 qdf_mutex_acquire(&ipa_ctx->event_lock);
1775
1776 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001777 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001778 !ipa_ctx->ipa_pipes_down &&
1779 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301780 if (cds_is_driver_unloading()) {
1781 /*
1782 * We disable WDI pipes directly here since
1783 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1784 * processed when unloading WLAN driver is in
1785 * progress
1786 */
1787 wlan_ipa_uc_disable_pipes(ipa_ctx);
1788 } else {
1789 /*
1790 * This shouldn't happen :
1791 * No interface left but WDI pipes are still
1792 * active - force close WDI pipes
1793 */
1794 ipa_err("No interface left but WDI pipes are still active");
1795 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1796 }
1797 }
1798
1799 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1800 qdf_mutex_release(&ipa_ctx->event_lock);
1801 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1802 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1803 qdf_mutex_acquire(&ipa_ctx->event_lock);
1804 ipa_ctx->vdev_to_iface[session_id] =
1805 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001806 ipa_debug("vdev_to_iface[%u]=%u",
1807 session_id,
1808 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301809 }
1810
1811 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1812 iface_ctx = &ipa_ctx->iface_context[i];
1813
1814 if (iface_ctx->dev == net_dev)
1815 break;
1816 }
1817 if (i < WLAN_IPA_MAX_IFACE)
1818 wlan_ipa_cleanup_iface(iface_ctx);
1819
1820 qdf_mutex_release(&ipa_ctx->event_lock);
1821 break;
1822
1823 case QDF_IPA_CLIENT_CONNECT_EX:
1824 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1825 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1826 net_dev->name, type);
1827 return QDF_STATUS_SUCCESS;
1828 }
1829
1830 qdf_mutex_acquire(&ipa_ctx->event_lock);
1831 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1832 mac_addr)) {
1833 qdf_mutex_release(&ipa_ctx->event_lock);
1834 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1835 return QDF_STATUS_SUCCESS;
1836 }
1837
1838 /* Enable IPA UC Data PIPEs when first STA connected */
1839 if (ipa_ctx->sap_num_connected_sta == 0 &&
1840 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301841
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301842 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1843 ipa_ctx->sta_connected) {
1844 qdf_mutex_release(&ipa_ctx->event_lock);
1845 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1846 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301847 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301848 qdf_mutex_acquire(&ipa_ctx->event_lock);
1849 }
1850
1851 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1852 if (status != QDF_STATUS_SUCCESS) {
1853 ipa_info("%s: handle 1st con fail",
1854 net_dev->name);
1855
1856 if (wlan_ipa_uc_sta_is_enabled(
1857 ipa_ctx->config) &&
1858 ipa_ctx->sta_connected) {
1859 qdf_mutex_release(&ipa_ctx->event_lock);
1860 wlan_ipa_uc_offload_enable_disable(
1861 ipa_ctx,
1862 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301863 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301864 } else {
1865 qdf_mutex_release(&ipa_ctx->event_lock);
1866 }
1867
1868 return status;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001869 } else
1870 ipa_debug("%s: handle 1st con success",
1871 net_dev->name);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301872 }
1873
1874 ipa_ctx->sap_num_connected_sta++;
1875
1876 qdf_mutex_release(&ipa_ctx->event_lock);
1877
1878 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1879 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1880 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1881 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1882 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1883
1884 if (msg_ex == NULL) {
1885 ipa_err("msg_ex allocation failed");
1886 return QDF_STATUS_E_NOMEM;
1887 }
1888 strlcpy(msg_ex->name, net_dev->name,
1889 IPA_RESOURCE_NAME_MAX);
1890 msg_ex->num_of_attribs = 1;
1891 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1892 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1893 msg_ex->attribs[0].offset =
1894 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1895 } else {
1896 msg_ex->attribs[0].offset =
1897 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1898 }
1899 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1900 IPA_MAC_ADDR_SIZE);
1901
1902 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1903 ipa_info("%s: Evt: %d send ipa msg fail",
1904 net_dev->name, type);
1905 qdf_mem_free(msg_ex);
1906 return QDF_STATUS_E_FAILURE;
1907 }
1908 ipa_ctx->stats.num_send_msg++;
1909
1910 ipa_info("sap_num_connected_sta=%d",
1911 ipa_ctx->sap_num_connected_sta);
1912
1913 return QDF_STATUS_SUCCESS;
1914
1915 case WLAN_CLIENT_DISCONNECT:
1916 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1917 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1918 msg_ex->name);
1919 return QDF_STATUS_SUCCESS;
1920 }
1921
1922 qdf_mutex_acquire(&ipa_ctx->event_lock);
1923 if (!ipa_ctx->sap_num_connected_sta) {
1924 qdf_mutex_release(&ipa_ctx->event_lock);
1925 ipa_err("%s: Evt: %d, Client already disconnected",
1926 msg_ex->name,
1927 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1928
1929 return QDF_STATUS_SUCCESS;
1930 }
1931 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
1932 sta_id, mac_addr)) {
1933 qdf_mutex_release(&ipa_ctx->event_lock);
1934 ipa_err("%s: STA ID %d NOT found, not valid",
1935 msg_ex->name, sta_id);
1936
1937 return QDF_STATUS_SUCCESS;
1938 }
1939 ipa_ctx->sap_num_connected_sta--;
1940
1941 /* Disable IPA UC TX PIPE when last STA disconnected */
1942 if (!ipa_ctx->sap_num_connected_sta &&
1943 ipa_ctx->uc_loaded == true) {
Yun Parka29974a2018-04-09 12:05:49 -07001944 if ((false == ipa_ctx->resource_unloading) &&
1945 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
1946 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08001947 if (cds_is_driver_unloading()) {
1948 /*
1949 * We disable WDI pipes directly here
1950 * since IPA_OPCODE_TX/RX_SUSPEND
1951 * message will not be processed when
1952 * unloading WLAN driver is in progress
1953 */
1954 wlan_ipa_uc_disable_pipes(ipa_ctx);
1955 } else {
1956 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1957 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301958 }
1959
1960 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1961 ipa_ctx->sta_connected) {
1962 qdf_mutex_release(&ipa_ctx->event_lock);
1963 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1964 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301965 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301966 } else {
1967 qdf_mutex_release(&ipa_ctx->event_lock);
1968 }
1969 } else {
1970 qdf_mutex_release(&ipa_ctx->event_lock);
1971 }
1972
1973 ipa_info("sap_num_connected_sta=%d",
1974 ipa_ctx->sap_num_connected_sta);
1975 break;
1976
1977 default:
1978 return QDF_STATUS_SUCCESS;
1979 }
1980
1981 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
1982 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1983 if (!msg) {
1984 ipa_err("msg allocation failed");
1985 return QDF_STATUS_E_NOMEM;
1986 }
1987
1988 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1989 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
1990 IPA_RESOURCE_NAME_MAX);
1991 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
1992
1993 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
1994 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1995
1996 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
1997
1998 ipa_err("%s: Evt: %d fail",
1999 QDF_IPA_WLAN_MSG_NAME(msg),
2000 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2001 qdf_mem_free(msg);
2002
2003 return QDF_STATUS_E_FAILURE;
2004 }
2005
2006 ipa_ctx->stats.num_send_msg++;
2007
2008end:
2009 return QDF_STATUS_SUCCESS;
2010}
2011
2012/**
2013 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002014 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302015 *
2016 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2017 */
2018static qdf_ipa_wlan_event
2019wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2020{
Yun Park84fbb272018-04-02 15:31:01 -07002021 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302022
2023 switch (wlan_ipa_event_type) {
2024 case WLAN_IPA_CLIENT_CONNECT:
2025 ipa_event = QDF_IPA_CLIENT_CONNECT;
2026 break;
2027 case WLAN_IPA_CLIENT_DISCONNECT:
2028 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2029 break;
2030 case WLAN_IPA_AP_CONNECT:
2031 ipa_event = QDF_IPA_AP_CONNECT;
2032 break;
2033 case WLAN_IPA_AP_DISCONNECT:
2034 ipa_event = QDF_IPA_AP_DISCONNECT;
2035 break;
2036 case WLAN_IPA_STA_CONNECT:
2037 ipa_event = QDF_IPA_STA_CONNECT;
2038 break;
2039 case WLAN_IPA_STA_DISCONNECT:
2040 ipa_event = QDF_IPA_STA_DISCONNECT;
2041 break;
2042 case WLAN_IPA_CLIENT_CONNECT_EX:
2043 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2044 break;
2045 case WLAN_IPA_WLAN_EVENT_MAX:
2046 default:
2047 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2048 break;
2049 }
2050
2051 return ipa_event;
2052}
2053
2054/**
2055 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2056 * @net_dev: Interface net device
2057 * @device_mode: Net interface device mode
2058 * @sta_id: station id for the event
2059 * @session_id: session id for the event
2060 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2061 * @mac_address: MAC address associated with the event
2062 *
2063 * Return: QDF_STATUS
2064 */
2065QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
2066 uint8_t sta_id, uint8_t session_id,
2067 enum wlan_ipa_wlan_event ipa_event_type,
2068 uint8_t *mac_addr)
2069{
2070 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2071 QDF_STATUS status = QDF_STATUS_SUCCESS;
2072
2073 /* Data path offload only support for STA and SAP mode */
2074 if ((device_mode == QDF_STA_MODE) ||
2075 (device_mode == QDF_SAP_MODE))
2076 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
2077 session_id, type, mac_addr);
2078
2079 return status;
2080}
2081
2082/**
2083 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2084 * @ipa_ctx: Global IPA IPA context
2085 * @is_loading: Indicate if invoked during loading
2086 *
2087 * Return: None
2088 */
2089static void
2090wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2091{
2092 unsigned int pending_event_count;
2093 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2094
2095 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2096 ipa_debug("Pending Event Count %d", pending_event_count);
2097 if (!pending_event_count) {
2098 ipa_debug("No Pending Event");
2099 return;
2100 }
2101
2102 qdf_list_remove_front(&ipa_ctx->pending_event,
2103 (qdf_list_node_t **)&pending_event);
2104 while (pending_event != NULL) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302105 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2106 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2107 struct wlan_objmgr_vdev *vdev =
2108 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2109 pending_event->session_id,
2110 WLAN_IPA_ID);
2111 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302112 __wlan_ipa_wlan_evt(pending_event->net_dev,
2113 pending_event->device_mode,
2114 pending_event->sta_id,
2115 pending_event->session_id,
2116 pending_event->type,
2117 pending_event->mac_addr);
2118 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302119
2120 if (vdev)
2121 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302122 qdf_mem_free(pending_event);
2123 pending_event = NULL;
2124 qdf_list_remove_front(&ipa_ctx->pending_event,
2125 (qdf_list_node_t **)&pending_event);
2126 }
2127}
2128
2129/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002130 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2131 * @ipa_ctx: IPA context
2132 *
2133 * Return: None
2134 */
2135static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2136{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302137 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002138 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302139 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002140
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302141 if (!ipa_ctx->tx_desc_pool)
2142 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002143
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302144 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2145 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2146 for (i = 0; i < pool_size; i++) {
2147 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002148 if (ipa_tx_desc)
2149 qdf_ipa_free_skb(ipa_tx_desc);
2150
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302151 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2152 &ipa_ctx->tx_desc_pool[i].node) !=
2153 QDF_STATUS_SUCCESS)
2154 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002155 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302156 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2157
2158 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2159 qdf_mem_free(ipa_ctx->tx_desc_pool);
2160 ipa_ctx->tx_desc_pool = NULL;
2161
2162 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2163 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002164}
2165
2166/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302167 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302168 * @ipa_ctx: IPA context
2169 *
2170 * Return: QDF_STATUS
2171 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302172static QDF_STATUS
2173wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302174{
2175 int i;
2176 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302177
2178 max_desc_cnt = ipa_ctx->config->txbuf_count;
2179
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302180 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2181 max_desc_cnt);
2182
2183 if (!ipa_ctx->tx_desc_pool) {
2184 ipa_err("Free Tx descriptor allocation failed");
2185 return QDF_STATUS_E_NOMEM;
2186 }
2187
2188 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302189
2190 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2191 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302192 ipa_ctx->tx_desc_pool[i].id = i;
2193 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2194 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2195 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302196 }
2197
2198 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2199 ipa_ctx->stats.num_tx_desc_error = 0;
2200
2201 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2202
2203 return QDF_STATUS_SUCCESS;
2204}
2205
2206#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2207/**
2208 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2209 * @ipa_ctx: Global IPA IPA context
2210 * @desc_fifo_sz: Number of descriptors
2211 *
2212 * Return: 0 on success, negative errno on error
2213 */
2214static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2215 int32_t desc_fifo_sz)
2216{
2217 int i, ret = 0;
2218 qdf_ipa_sys_connect_params_t *ipa;
2219
2220 /*setup TX pipes */
2221 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2222 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2223
2224 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2225 ipa->desc_fifo_sz = desc_fifo_sz;
2226 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302227 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302228
2229 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2230 ipa->ipa_ep_cfg.hdr.hdr_len =
2231 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2232 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2233 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2234 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2235 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2236 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2237 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2238 } else {
2239 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2240 }
2241 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2242
2243 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2244 &ipa_ctx->sys_pipe[i].conn_hdl);
2245 if (ret) {
2246 ipa_err("Failed for pipe %d ret: %d", i, ret);
2247 return ret;
2248 }
2249 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2250 }
2251
2252 return ret;
2253}
2254#else
2255/**
2256 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2257 * @ipa_ctx: Global IPA IPA context
2258 * @desc_fifo_sz: Number of descriptors
2259 *
2260 * Return: 0 on success, negative errno on error
2261 */
2262static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2263 int32_t desc_fifo_sz)
2264{
2265 /*
2266 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2267 * is enabled, where per vdev descriptors are supported in firmware.
2268 */
2269 return 0;
2270}
2271#endif
2272
2273/**
2274 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2275 * @ipa_ctx: Global IPA IPA context
2276 * @desc_fifo_sz: Number of descriptors
2277 *
2278 * Return: 0 on success, negative errno on error
2279 */
2280static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2281 int32_t desc_fifo_sz)
2282{
2283 int ret = 0;
2284 qdf_ipa_sys_connect_params_t *ipa;
2285
2286 /*
2287 * Hard code it here, this can be extended if in case
2288 * PROD pipe is also per interface.
2289 * Right now there is no advantage of doing this.
2290 */
2291 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2292
2293 ipa->client = IPA_CLIENT_WLAN1_PROD;
2294
2295 ipa->desc_fifo_sz = desc_fifo_sz;
2296 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302297 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302298
2299 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2300 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2301 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2302 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2303
2304 ret = qdf_ipa_setup_sys_pipe(ipa,
2305 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2306 if (ret) {
2307 ipa_err("Failed for RX pipe: %d", ret);
2308 return ret;
2309 }
2310 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2311
2312 return ret;
2313}
2314
2315/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002316 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2317 * @ipa_ctx: Global IPA IPA context
2318 *
2319 * Return: None
2320 */
2321static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2322{
2323 int ret, i;
2324
2325 if (!ipa_ctx)
2326 return;
2327
2328 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2329 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2330 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2331 ipa_ctx->sys_pipe[i].conn_hdl);
2332 if (ret)
2333 ipa_err("Failed:%d", ret);
2334
2335 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2336 }
2337 }
2338
2339 wlan_ipa_free_tx_desc_list(ipa_ctx);
2340}
2341
2342/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302343 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2344 * @ipa_ctx: Global IPA IPA context
2345 *
2346 * Return: 0 on success, negative errno on error
2347 */
2348static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2349{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002350 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302351 uint32_t desc_fifo_sz;
2352
2353 /* The maximum number of descriptors that can be provided to a BAM at
2354 * once is one less than the total number of descriptors that the buffer
2355 * can contain.
2356 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2357 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2358 * be provided at once.
2359 * Because of above requirement, one extra descriptor will be added to
2360 * make sure hardware always has one descriptor.
2361 */
2362 desc_fifo_sz = ipa_ctx->config->desc_size
2363 + SPS_DESC_SIZE;
2364
2365 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2366 if (ret) {
2367 ipa_err("Failed for TX pipe: %d", ret);
2368 goto setup_sys_pipe_fail;
2369 }
2370
2371 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2372 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2373 if (ret) {
2374 ipa_err("Failed for RX pipe: %d", ret);
2375 goto setup_sys_pipe_fail;
2376 }
2377 }
2378
2379 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302380 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302381 if (ret)
2382 goto setup_sys_pipe_fail;
2383
2384 return ret;
2385
2386setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002387 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302388
2389 return ret;
2390}
2391
jiadbb47e132018-03-30 16:28:30 +08002392#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2393QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2394 bool mcc_mode)
2395{
2396 qdf_ipa_msg_meta_t meta;
2397 qdf_ipa_wlan_msg_t *msg;
2398 int ret;
2399
2400 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2401 return QDF_STATUS_SUCCESS;
2402
2403 /* Send SCC/MCC Switching event to IPA */
2404 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2405 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2406 if (msg == NULL) {
2407 ipa_err("msg allocation failed");
2408 return QDF_STATUS_E_NOMEM;
2409 }
2410
jiad629b2172018-05-11 15:34:22 +08002411 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002412 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002413 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2414 } else {
jiadbb47e132018-03-30 16:28:30 +08002415 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002416 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2417 }
2418
jiadbb47e132018-03-30 16:28:30 +08002419 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2420 "ipa_send_msg(Evt:%d)",
2421 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2422
2423 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2424
2425 if (ret) {
2426 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2427 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2428 qdf_mem_free(msg);
2429 return QDF_STATUS_E_FAILURE;
2430 }
2431
2432 return QDF_STATUS_SUCCESS;
2433}
2434
2435static void wlan_ipa_mcc_work_handler(void *data)
2436{
2437 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2438
2439 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2440}
2441#endif
2442
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302443/**
2444 * wlan_ipa_setup() - IPA initialization function
2445 * @ipa_ctx: IPA context
2446 * @ipa_cfg: IPA config
2447 *
2448 * Allocate ipa_ctx resources, ipa pipe resource and register
2449 * wlan interface with IPA module.
2450 *
2451 * Return: QDF_STATUS enumeration
2452 */
2453QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2454 struct wlan_ipa_config *ipa_cfg)
2455{
2456 int ret, i;
2457 struct wlan_ipa_iface_context *iface_context = NULL;
2458 QDF_STATUS status;
2459
2460 ipa_debug("enter");
2461
2462 gp_ipa = ipa_ctx;
2463 ipa_ctx->num_iface = 0;
2464 ipa_ctx->config = ipa_cfg;
2465
2466 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2467
2468 /* Create the interface context */
2469 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2470 iface_context = &ipa_ctx->iface_context[i];
2471 iface_context->ipa_ctx = ipa_ctx;
2472 iface_context->cons_client =
2473 wlan_ipa_iface_2_client[i].cons_client;
2474 iface_context->prod_client =
2475 wlan_ipa_iface_2_client[i].prod_client;
2476 iface_context->iface_id = i;
2477 iface_context->dev = NULL;
2478 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2479 iface_context->tl_context = NULL;
2480 qdf_spinlock_create(&iface_context->interface_lock);
2481 }
2482
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302483 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302484 qdf_spinlock_create(&ipa_ctx->pm_lock);
2485 qdf_spinlock_create(&ipa_ctx->q_lock);
2486 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2487 qdf_list_create(&ipa_ctx->pending_event, 1000);
2488 qdf_mutex_create(&ipa_ctx->event_lock);
2489 qdf_mutex_create(&ipa_ctx->ipa_lock);
2490
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302491 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2492 if (status != QDF_STATUS_SUCCESS)
2493 goto fail_setup_rm;
2494
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302495 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2496 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2497 sizeof(struct wlan_ipa_sys_pipe));
2498
2499 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2500 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2501 ipa_ctx->sap_num_connected_sta = 0;
2502 ipa_ctx->ipa_tx_packets_diff = 0;
2503 ipa_ctx->ipa_rx_packets_diff = 0;
2504 ipa_ctx->ipa_p_tx_packets = 0;
2505 ipa_ctx->ipa_p_rx_packets = 0;
2506 ipa_ctx->resource_loading = false;
2507 ipa_ctx->resource_unloading = false;
2508 ipa_ctx->sta_connected = 0;
2509 ipa_ctx->ipa_pipes_down = true;
2510 ipa_ctx->wdi_enabled = false;
2511 /* Setup IPA system pipes */
2512 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2513 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2514 if (ret)
2515 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002516
2517 qdf_create_work(0, &ipa_ctx->mcc_work,
2518 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302519 }
2520
2521 status = wlan_ipa_wdi_init(ipa_ctx);
2522 if (status == QDF_STATUS_E_BUSY)
2523 status = wlan_ipa_uc_send_wdi_control_msg(false);
2524 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002525 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302526 goto fail_create_sys_pipe;
2527 }
2528 } else {
2529 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2530 if (ret)
2531 goto fail_create_sys_pipe;
2532 }
2533
2534 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2535
2536 ipa_debug("exit: success");
2537
2538 return QDF_STATUS_SUCCESS;
2539
2540fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302541 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2542
2543fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302544 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302545 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2546 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2547 iface_context = &ipa_ctx->iface_context[i];
2548 qdf_spinlock_destroy(&iface_context->interface_lock);
2549 }
2550 qdf_mutex_destroy(&ipa_ctx->event_lock);
2551 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2552 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302553 gp_ipa = NULL;
2554 ipa_debug("exit: fail");
2555
2556 return QDF_STATUS_E_FAILURE;
2557}
2558
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302559void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2560{
2561 qdf_nbuf_t skb;
2562 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2563
2564 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2565 return;
2566
2567 qdf_cancel_work(&ipa_ctx->pm_work);
2568
2569 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2570
2571 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2572 != NULL)) {
2573 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2574
2575 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002576
2577 if (pm_tx_cb->exception) {
2578 dev_kfree_skb_any(skb);
2579 } else {
2580 if (pm_tx_cb->ipa_tx_desc)
2581 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2582 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302583
2584 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2585 }
2586 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2587}
2588
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302589QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2590{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302591 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302592 int i;
2593
2594 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2595 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2596
2597 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002598 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302599 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002600 qdf_cancel_work(&ipa_ctx->mcc_work);
2601 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302602
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302603 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2604
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302605 wlan_ipa_flush(ipa_ctx);
2606
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302607 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2608 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2609
2610 /* destroy the interface lock */
2611 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2612 iface_context = &ipa_ctx->iface_context[i];
2613 qdf_spinlock_destroy(&iface_context->interface_lock);
2614 }
2615
2616 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2617 wlan_ipa_wdi_cleanup();
2618 qdf_mutex_destroy(&ipa_ctx->event_lock);
2619 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2620 qdf_list_destroy(&ipa_ctx->pending_event);
2621
2622 }
2623
2624 gp_ipa = NULL;
2625
2626 return QDF_STATUS_SUCCESS;
2627}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302628
2629struct wlan_ipa_iface_context
2630*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2631{
2632 struct wlan_ipa_iface_context *iface_ctx = NULL;
2633 int i;
2634
2635 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2636 iface_ctx = &ipa_ctx->iface_context[i];
2637
2638 if (iface_ctx->device_mode == mode)
2639 return iface_ctx;
2640 }
2641
2642 return NULL;
2643}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302644
jiadbb47e132018-03-30 16:28:30 +08002645void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302646{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302647 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002648 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302649
jiadbb47e132018-03-30 16:28:30 +08002650 if (ipa_ctx->mcc_mode == mcc_mode)
2651 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302652
jiadbb47e132018-03-30 16:28:30 +08002653 ipa_ctx->mcc_mode = mcc_mode;
2654 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302655}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302656
2657/**
2658 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2659 * @ipa_ctx: ipa ipa local context
2660 *
2661 * Will handle IPA UC image loaded indication comes from IPA kernel
2662 *
2663 * Return: None
2664 */
2665static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2666{
2667 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2668 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2669 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2670 QDF_STATUS status;
2671
2672 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002673
2674 if (!qdf_dev) {
2675 ipa_err("qdf device is NULL!");
2676 return;
2677 }
2678
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302679 if (true == ipa_ctx->uc_loaded) {
2680 ipa_info("UC already loaded");
2681 return;
2682 }
2683
Lihua Liu15f6e452018-05-30 17:31:06 +08002684 if (!qdf_dev) {
2685 ipa_err("qdf_dev is null");
2686 return;
2687 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302688 /* Connect pipe */
2689 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2690 if (status) {
2691 ipa_err("Failure to setup IPA pipes (status=%d)",
2692 status);
2693 return;
2694 }
2695
2696 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302697
2698 /* If already any STA connected, enable IPA/FW PIPEs */
2699 if (ipa_ctx->sap_num_connected_sta) {
2700 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2701 wlan_ipa_uc_handle_first_con(ipa_ctx);
2702 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302703}
2704
2705/**
2706 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2707 * @op_msg: operation message received from firmware
2708 * @usr_ctxt: user context registered with TL (we register the IPA Global
2709 * context)
2710 *
2711 * Return: None
2712 */
2713static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2714 struct wlan_ipa_priv *ipa_ctx)
2715{
2716 struct op_msg_type *msg = op_msg;
2717 struct ipa_uc_fw_stats *uc_fw_stat;
2718
2719 if (!op_msg) {
2720 ipa_err("INVALID ARG");
2721 return;
2722 }
2723
2724 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2725 ipa_err("INVALID OPCODE %d", msg->op_code);
2726 qdf_mem_free(op_msg);
2727 return;
2728 }
2729
2730 ipa_debug("OPCODE=%d", msg->op_code);
2731
2732 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2733 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2734 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2735 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07002736 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302737 ipa_ctx->resource_loading = false;
2738 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2739 if (ipa_ctx->wdi_enabled == false) {
2740 ipa_ctx->wdi_enabled = true;
2741 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2742 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2743 ipa_ctx->mcc_mode);
2744 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302745 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302746 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07002747 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302748 QDF_IPA_RM_RESOURCE_GRANTED,
2749 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2750 ipa_ctx->pending_cons_req = false;
2751 }
2752 qdf_mutex_release(&ipa_ctx->ipa_lock);
2753 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2754 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2755 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05302756
2757 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
2758 wlan_ipa_uc_disable_pipes(ipa_ctx);
2759 ipa_info("Disable FW TX PIPE");
2760 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2761 false, true);
2762 }
2763
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302764 ipa_ctx->activated_fw_pipe--;
2765 if (!ipa_ctx->activated_fw_pipe) {
2766 /*
2767 * Async return success from FW
2768 * Disable/suspend all the PIPEs
2769 */
2770 ipa_ctx->resource_unloading = false;
2771 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302772 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07002773 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
2774 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302775 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302776 ipa_ctx->pending_cons_req = false;
2777 }
2778 qdf_mutex_release(&ipa_ctx->ipa_lock);
2779 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2780 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2781 uc_fw_stat = (struct ipa_uc_fw_stats *)
2782 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2783
2784 /* WLAN FW WDI stats */
2785 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2786 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2787 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2788 /* STATs from FW */
2789 uc_fw_stat = (struct ipa_uc_fw_stats *)
2790 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2791 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2792 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2793 uc_fw_stat->tx_pkts_completed,
2794 ipa_ctx->ipa_p_tx_packets);
2795 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2796 (uc_fw_stat->rx_num_ind_drop_no_space +
2797 uc_fw_stat->rx_num_ind_drop_no_buf +
2798 uc_fw_stat->rx_num_pkts_indicated),
2799 ipa_ctx->ipa_p_rx_packets);
2800
2801 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2802 ipa_ctx->ipa_p_rx_packets =
2803 (uc_fw_stat->rx_num_ind_drop_no_space +
2804 uc_fw_stat->rx_num_ind_drop_no_buf +
2805 uc_fw_stat->rx_num_pkts_indicated);
2806 qdf_mutex_release(&ipa_ctx->ipa_lock);
2807 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2808 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2809 wlan_ipa_uc_loaded_handler(ipa_ctx);
2810 qdf_mutex_release(&ipa_ctx->ipa_lock);
2811 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2812 ipa_err("Invalid message: op_code=%d, reason=%d",
2813 msg->op_code, ipa_ctx->stat_req_reason);
2814 }
2815
2816 qdf_mem_free(op_msg);
2817}
2818
2819/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302820 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2821 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302822 *
2823 * Return: None
2824 */
jitiphilfdcaaba2018-09-03 16:19:52 +05302825static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302826{
2827 struct op_msg_type *msg;
2828 struct uc_op_work_struct *uc_op_work =
2829 (struct uc_op_work_struct *)data;
2830 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2831
jitiphilfdcaaba2018-09-03 16:19:52 +05302832 if (qdf_is_module_state_transitioning()) {
2833 ipa_err("Module transition in progress");
2834 return;
2835 }
2836
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302837 msg = uc_op_work->msg;
2838 uc_op_work->msg = NULL;
2839 ipa_debug("posted msg %d", msg->op_code);
2840
2841 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2842}
2843
2844/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302845 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
2846 * __wlan_ipa_uc_fw_op_event_handler
2847 * @data: uC OP work
2848 *
2849 * Return: None
2850 */
2851static void wlan_ipa_uc_fw_op_event_handler(void *data)
2852{
2853 qdf_ssr_protect(__func__);
2854 __wlan_ipa_uc_fw_op_event_handler(data);
2855 qdf_ssr_unprotect(__func__);
2856}
2857
2858/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302859 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2860 * @op_msg: operation message received from firmware
2861 * @ipa_ctx: Global IPA context
2862 *
2863 * Return: None
2864 */
2865static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2866{
2867 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2868 struct op_msg_type *msg;
2869 struct uc_op_work_struct *uc_op_work;
2870
2871 if (!ipa_ctx)
2872 goto end;
2873
2874 msg = (struct op_msg_type *)op_msg;
2875
2876 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2877 ipa_err("Invalid OP Code (%d)", msg->op_code);
2878 goto end;
2879 }
2880
2881 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2882 if (uc_op_work->msg) {
2883 /* When the same uC OPCODE is already pended, just return */
2884 goto end;
2885 }
2886
2887 uc_op_work->msg = msg;
2888 qdf_sched_work(0, &uc_op_work->work);
2889 return;
2890
2891end:
2892 qdf_mem_free(op_msg);
2893}
2894
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302895QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2896 qdf_device_t osdev)
2897{
2898 uint8_t i;
2899 QDF_STATUS status = QDF_STATUS_SUCCESS;
2900
2901 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2902 return QDF_STATUS_SUCCESS;
2903
2904 ipa_debug("enter");
2905
2906 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
2907 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
2908 ipa_ctx->vdev_offload_enabled[i] = false;
2909 }
2910
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302911 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
2912 ipa_err("IPA UC resource alloc fail");
2913 status = QDF_STATUS_E_FAILURE;
2914 goto fail_return;
2915 }
2916
2917 if (true == ipa_ctx->uc_loaded) {
2918 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
2919 if (status) {
2920 ipa_err("Failure to setup IPA pipes (status=%d)",
2921 status);
2922 status = QDF_STATUS_E_FAILURE;
2923 goto fail_return;
2924 }
2925
2926 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
2927 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08002928
2929 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
2930 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302931 }
2932
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302933 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2934 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
2935
2936 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2937 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
2938 wlan_ipa_uc_fw_op_event_handler,
2939 &ipa_ctx->uc_op_work[i]);
2940 ipa_ctx->uc_op_work[i].msg = NULL;
2941 }
2942
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302943fail_return:
2944 ipa_debug("exit: status=%d", status);
2945 return status;
2946}
2947
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302948/**
2949 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
2950 * @ipa_ctx: pointer to IPA IPA struct
2951 *
2952 * Return: none
2953 */
2954static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
2955{
2956 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2957
2958 while (qdf_list_remove_front(&ipa_ctx->pending_event,
2959 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
2960 qdf_mem_free(pending_event);
2961}
2962
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302963QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
2964{
2965 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302966 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302967
2968 ipa_debug("enter");
2969
2970 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2971 return status;
2972
2973 if (!ipa_ctx->ipa_pipes_down)
2974 wlan_ipa_uc_disable_pipes(ipa_ctx);
2975
2976 if (true == ipa_ctx->uc_loaded) {
2977 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
2978 ipa_ctx->tx_pipe_handle,
2979 ipa_ctx->rx_pipe_handle);
2980 if (status)
2981 ipa_err("Failure to cleanup IPA pipes (status=%d)",
2982 status);
2983 }
2984
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302985 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2986 wlan_ipa_cleanup_pending_event(ipa_ctx);
2987 qdf_mutex_release(&ipa_ctx->ipa_lock);
2988
2989 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2990 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
2991 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
2992 ipa_ctx->uc_op_work[i].msg = NULL;
2993 }
2994
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302995 ipa_debug("exit: ret=%d", status);
2996 return status;
2997}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05302998
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05302999/**
3000 * wlan_ipa_uc_send_evt() - send event to ipa
3001 * @net_dev: Interface net device
3002 * @type: event type
3003 * @mac_addr: pointer to mac address
3004 *
3005 * Send event to IPA driver
3006 *
3007 * Return: QDF_STATUS
3008 */
3009static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3010 qdf_ipa_wlan_event type,
3011 uint8_t *mac_addr)
3012{
3013 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3014 qdf_ipa_msg_meta_t meta;
3015 qdf_ipa_wlan_msg_t *msg;
3016
3017 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3018 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3019 if (!msg) {
3020 ipa_err("msg allocation failed");
3021 return QDF_STATUS_E_NOMEM;
3022 }
3023
3024 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3025 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3026 IPA_RESOURCE_NAME_MAX);
3027 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3028
3029 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3030 ipa_err("%s: Evt: %d fail",
3031 QDF_IPA_WLAN_MSG_NAME(msg),
3032 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3033 qdf_mem_free(msg);
3034
3035 return QDF_STATUS_E_FAILURE;
3036 }
3037
3038 ipa_ctx->stats.num_send_msg++;
3039
3040 return QDF_STATUS_SUCCESS;
3041}
3042
3043QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3044 qdf_netdev_t net_dev)
3045{
3046 struct wlan_ipa_iface_context *iface_ctx;
3047 QDF_STATUS status;
3048
3049 ipa_debug("enter");
3050
3051 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3052 if (iface_ctx)
3053 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3054 net_dev->dev_addr);
3055 else
3056 return QDF_STATUS_E_INVAL;
3057
3058 ipa_debug("exit :%d", status);
3059
3060 return status;
3061}
3062
3063void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3064 qdf_netdev_t net_dev)
3065{
3066 struct wlan_ipa_iface_context *iface_ctx;
3067 int i;
3068
3069 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3070 iface_ctx = &ipa_ctx->iface_context[i];
3071 if (iface_ctx->dev == net_dev)
3072 break;
3073 }
3074
3075 if (iface_ctx)
3076 wlan_ipa_cleanup_iface(iface_ctx);
3077}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303078
3079void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3080{
3081 struct wlan_ipa_iface_context *iface;
3082 int i;
3083
3084 ipa_info("enter");
3085
3086 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3087 iface = &ipa_ctx->iface_context[i];
3088 if (iface->dev) {
3089 if (iface->device_mode == QDF_SAP_MODE)
3090 wlan_ipa_uc_send_evt(iface->dev,
3091 QDF_IPA_AP_DISCONNECT,
3092 iface->dev->dev_addr);
3093 else if (iface->device_mode == QDF_STA_MODE)
3094 wlan_ipa_uc_send_evt(iface->dev,
3095 QDF_IPA_STA_DISCONNECT,
3096 iface->dev->dev_addr);
3097 wlan_ipa_cleanup_iface(iface);
3098 }
3099 }
3100}
jitiphil0e3b5922018-07-24 18:43:50 +05303101
3102void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3103{
3104 qdf_ipa_msg_meta_t meta;
3105 qdf_ipa_wlan_msg_t *msg;
3106 int ret;
3107
3108 meta.msg_len = sizeof(*msg);
3109 msg = qdf_mem_malloc(meta.msg_len);
3110 if (!msg) {
3111 ipa_debug("msg allocation failed");
3112 return;
3113 }
3114
3115 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3116 ipa_debug("ipa_send_msg(Evt:%d)",
3117 meta.msg_type);
3118 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3119
3120 if (ret) {
3121 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3122 meta.msg_type, ret);
3123 qdf_mem_free(msg);
3124 }
3125 ipa_ctx->stats.num_send_msg++;
3126}