blob: bd647ad5955a2b8032ebdfd46c882eb246d5afe8 [file] [log] [blame]
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301/*
2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3 *
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
232 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
233
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");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530666 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
667 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);
713 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
714
715 if ((desc & FW_RX_DESC_FORWARD_M)) {
716 if (!ol_txrx_fwd_desc_thresh_check(
717 (struct ol_txrx_vdev_t *)cdp_get_vdev_from_vdev_id(soc,
718 (struct cdp_pdev *)pdev,
719 iface_ctx->session_id))) {
720 /* Drop the packet*/
721 ipa_ctx->stats.num_tx_fwd_err++;
jiadab8cea02018-05-24 09:16:14 +0800722 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530723 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
724 return ret;
725 }
jiadf3ecc752018-07-05 14:36:03 +0800726 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530727 ipa_ctx->ipa_tx_forward++;
728
729 if ((desc & FW_RX_DESC_DISCARD_M)) {
730 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
731 ipa_ctx->ipa_rx_internal_drop_count++;
732 ipa_ctx->ipa_rx_discard++;
733 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
734 } else {
735 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
736
737 if (cloned_skb)
738 wlan_ipa_forward(ipa_ctx, iface_ctx,
739 cloned_skb);
740 else
jiadf3ecc752018-07-05 14:36:03 +0800741 ipa_err_rl("tx skb alloc failed");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530742 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
743 }
744 }
745
746 return ret;
747}
748
749/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530750 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530751 * @priv: pointer to private data registered with IPA (we register a
752 * pointer to the global IPA context)
753 * @evt: the IPA event which triggered the callback
754 * @data: data associated with the event
755 *
756 * Return: None
757 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530758static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
759 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530760{
761 struct wlan_ipa_priv *ipa_ctx = NULL;
762 qdf_nbuf_t skb;
763 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700764 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530765 struct wlan_ipa_iface_context *iface_context;
766 uint8_t fw_desc;
767
jitiphilfdcaaba2018-09-03 16:19:52 +0530768 if (qdf_is_module_state_transitioning()) {
769 ipa_err("Module transition in progress");
770 return;
771 }
772
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530773 ipa_ctx = (struct wlan_ipa_priv *)priv;
774
775 if (!ipa_ctx)
776 return;
777
778 switch (evt) {
779 case IPA_RECEIVE:
780 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530781 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
782 session_id = (uint8_t)skb->cb[0];
783 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530784 } else {
785 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
786 }
787 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700788 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
789 iface_id, session_id, (uint8_t)skb->cb[1],
790 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530791 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800792 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530793 return;
794 }
795
796 iface_context = &ipa_ctx->iface_context[iface_id];
797 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800798 ipa_err_rl("TL context of iface_id %u is NULL",
799 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530800 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800801 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530802 return;
803 }
804
805 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
806 ipa_ctx->stats.num_rx_excep++;
807 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
808 } else {
809 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
810 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530811 iface_context->stats.num_rx_ipa_excep++;
812
813 /* Disable to forward Intra-BSS Rx packets when
814 * ap_isolate=1 in hostapd.conf
815 */
816 if (!ipa_ctx->ap_intrabss_fwd) {
817 /*
818 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
819 * all Rx packets to IPA uC, which need to be forwarded
820 * to other interface.
821 * And, IPA driver will send back to WLAN host driver
822 * through exception pipe with fw_desc field set by FW.
823 * Here we are checking fw_desc field for FORWARD bit
824 * set, and forward to Tx. Then copy to kernel stack
825 * only when DISCARD bit is not set.
826 */
827 fw_desc = (uint8_t)skb->cb[1];
828 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
829 wlan_ipa_intrabss_forward(ipa_ctx, iface_context,
830 fw_desc, skb))
831 break;
832 } else {
jiadf3ecc752018-07-05 14:36:03 +0800833 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530834 }
835
836 wlan_ipa_send_skb_to_network(skb, iface_context);
837 break;
838
839 default:
jiadf3ecc752018-07-05 14:36:03 +0800840 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530841 return;
842 }
843}
844
845/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530846 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
847 * @priv: pointer to private data registered with IPA (we register a
848 * pointer to the global IPA context)
849 * @evt: the IPA event which triggered the callback
850 * @data: data associated with the event
851 *
852 * Return: None
853 */
854static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
855 unsigned long data)
856{
857 qdf_ssr_protect(__func__);
858 __wlan_ipa_w2i_cb(priv, evt, data);
859 qdf_ssr_unprotect(__func__);
860}
861
862/**
863 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530864 * @priv: pointer to private data registered with IPA (we register a
865 * pointer to the interface-specific IPA context)
866 * @evt: the IPA event which triggered the callback
867 * @data: data associated with the event
868 *
869 * Return: None
870 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530871static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
872 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530873{
874 struct wlan_ipa_priv *ipa_ctx = NULL;
875 qdf_ipa_rx_data_t *ipa_tx_desc;
876 struct wlan_ipa_iface_context *iface_context;
877 qdf_nbuf_t skb;
878 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
879
jitiphilfdcaaba2018-09-03 16:19:52 +0530880 if (qdf_is_module_state_transitioning()) {
881 ipa_err("Module transition in progress");
882 return;
883 }
884
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530885 iface_context = (struct wlan_ipa_iface_context *)priv;
886 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
887 ipa_ctx = iface_context->ipa_ctx;
888
889 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +0800890 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530891 ipa_free_skb(ipa_tx_desc);
892 iface_context->stats.num_tx_drop++;
893 return;
894 }
895
896 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
897
898 /*
899 * If PROD resource is not requested here then there may be cases where
900 * IPA hardware may be clocked down because of not having proper
901 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
902 * workaround to request PROD resource while data is going over CONS
903 * pipe to prevent the IPA hardware clockdown.
904 */
905 wlan_ipa_wdi_rm_request(ipa_ctx);
906
907 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
908 /*
909 * If host is still suspended then queue the packets and these will be
910 * drained later when resume completes. When packet is arrived here and
911 * host is suspended, this means that there is already resume is in
912 * progress.
913 */
914 if (ipa_ctx->suspended) {
915 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
916 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
917 pm_tx_cb->iface_context = iface_context;
918 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
919 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
920 ipa_ctx->stats.num_tx_queued++;
921
922 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
923 return;
924 }
925
926 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
927
928 /*
929 * If we are here means, host is not suspended, wait for the work queue
930 * to finish.
931 */
932 qdf_flush_work(&ipa_ctx->pm_work);
933
934 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
935}
936
jitiphilfdcaaba2018-09-03 16:19:52 +0530937/**
938 * wlan_ipa_i2w_cb() - IPA to WLAN callback
939 * @priv: pointer to private data registered with IPA (we register a
940 * pointer to the interface-specific IPA context)
941 * @evt: the IPA event which triggered the callback
942 * @data: data associated with the event
943 *
944 * Return: None
945 */
946static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
947 unsigned long data)
948{
949 qdf_ssr_protect(__func__);
950 __wlan_ipa_i2w_cb(priv, evt, data);
951 qdf_ssr_unprotect(__func__);
952}
953
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530954QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
955{
956 /*
957 * Check if IPA is ready for suspend, If we are here means, there is
958 * high chance that suspend would go through but just to avoid any race
959 * condition after suspend started, these checks are conducted before
960 * allowing to suspend.
961 */
962 if (atomic_read(&ipa_ctx->tx_ref_cnt))
963 return QDF_STATUS_E_AGAIN;
964
Yun Parke74e6092018-04-27 11:36:34 -0700965 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530966 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530967
968 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
969 ipa_ctx->suspended = true;
970 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
971
972 return QDF_STATUS_SUCCESS;
973}
974
975QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
976{
977 qdf_sched_work(0, &ipa_ctx->pm_work);
978
979 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
980 ipa_ctx->suspended = false;
981 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
982
983 return QDF_STATUS_SUCCESS;
984}
985
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +0530986QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
987{
988 int result;
989
990 ipa_debug("enter");
991
992 if (!ipa_ctx->ipa_pipes_down) {
993 /*
994 * IPA WDI Pipes are already activated due to
995 * rm deferred resources grant
996 */
997 ipa_warn("IPA WDI Pipes are already activated");
998 goto end;
999 }
1000
1001 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1002 ipa_ctx->dp_pdev);
1003 if (result) {
1004 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1005 return QDF_STATUS_E_FAILURE;
1006 }
1007
1008 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1009 ipa_ctx->ipa_pipes_down = false;
1010
1011 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1012 ipa_ctx->dp_pdev);
1013
1014end:
1015 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1016
1017 return QDF_STATUS_SUCCESS;
1018}
1019
1020QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1021{
1022 int result;
1023
1024 ipa_debug("enter");
1025
1026 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301027 ipa_warn("IPA WDI Pipes are already deactivated");
1028 goto end;
1029 }
1030
1031 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1032 ipa_ctx->dp_pdev);
1033
1034 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1035 ipa_ctx->dp_pdev);
1036 if (result) {
1037 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
1038 return QDF_STATUS_E_FAILURE;
1039 }
1040
1041 ipa_ctx->ipa_pipes_down = true;
1042
1043end:
1044 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1045
1046 return QDF_STATUS_SUCCESS;
1047}
1048
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301049/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301050 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1051 * @ipa_ctx: Global IPA IPA context
1052 * @sta_add: Should station be added
1053 * @sta_id: ID of the station being queried
1054 *
1055 * Return: true if the station was found
1056 */
1057static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
1058 bool sta_add, uint8_t sta_id,
1059 uint8_t *mac_addr)
1060{
1061 bool sta_found = false;
1062 uint8_t idx;
1063
1064 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1065 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1066 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1067 sta_found = true;
1068 break;
1069 }
1070 }
1071 if (sta_add && sta_found) {
1072 ipa_err("STA ID %d already exist, cannot add", sta_id);
1073 return sta_found;
1074 }
1075 if (sta_add) {
1076 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1077 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1078 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
1079 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
1080 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1081 mac_addr, mac_addr,
1082 QDF_NET_ETH_LEN);
1083 return sta_found;
1084 }
1085 }
1086 }
1087 if (!sta_add && !sta_found) {
1088 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
1089 return sta_found;
1090 }
1091 if (!sta_add) {
1092 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1093 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1094 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1095 ipa_ctx->assoc_stas_map[idx].is_reserved =
1096 false;
1097 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
1098 qdf_mem_set(&ipa_ctx->assoc_stas_map[idx].
1099 mac_addr, 0, QDF_NET_ETH_LEN);
1100 return sta_found;
1101 }
1102 }
1103 }
1104
1105 return sta_found;
1106}
1107
1108/**
1109 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1110 * @ipa_ctx: IPA context
1111 * @session_id: Session ID
1112 *
1113 * Return: None
1114 */
1115static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1116 uint8_t session_id)
1117{
1118 struct wlan_ipa_iface_context *iface_ctx;
1119 int i;
1120
1121 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1122 iface_ctx = &ipa_ctx->iface_context[i];
1123 if (iface_ctx->session_id == session_id)
1124 break;
1125 }
1126
1127 return i;
1128}
1129
1130/**
1131 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1132 * @iface_context: interface-specific IPA context
1133 *
1134 * Return: None
1135 */
1136static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1137{
1138 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1139
1140 ipa_debug("enter");
1141
1142 if (!iface_context->tl_context)
1143 return;
1144
1145 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1146 iface_context->dev->name,
1147 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1148
1149 qdf_spin_lock_bh(&iface_context->interface_lock);
1150 iface_context->tl_context = NULL;
1151 iface_context->dev = NULL;
1152 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1153 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1154 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1155 qdf_spin_unlock_bh(&iface_context->interface_lock);
1156 iface_context->ifa_address = 0;
1157 if (!iface_context->ipa_ctx->num_iface) {
1158 ipa_err("NUM INTF 0, Invalid");
1159 QDF_ASSERT(0);
1160 }
1161 iface_context->ipa_ctx->num_iface--;
1162 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1163}
1164
1165/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301166 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1167 * @skb: packet buffer which was transmitted
1168 *
1169 * Return: None
1170 */
1171static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1172{
1173 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1174 qdf_ipa_rx_data_t *ipa_tx_desc;
1175 struct wlan_ipa_tx_desc *tx_desc;
1176 uint16_t id;
1177
1178 if (!qdf_nbuf_ipa_owned_get(skb)) {
1179 dev_kfree_skb_any(skb);
1180 return;
1181 }
1182
1183 /* Get Tx desc pointer from SKB CB */
1184 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1185 tx_desc = &ipa_ctx->tx_desc_pool[id];
1186 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1187
1188 /* Return Tx Desc to IPA */
1189 qdf_ipa_free_skb(ipa_tx_desc);
1190
1191 /* Return to free tx desc list */
1192 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1193 tx_desc->ipa_tx_desc_ptr = NULL;
1194 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1195 ipa_ctx->stats.num_tx_desc_q_cnt--;
1196 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1197
1198 ipa_ctx->stats.num_tx_comp_cnt++;
1199
1200 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1201
1202 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1203}
1204
1205/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301206 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1207 * @ipa_ctx: IPA IPA global context
1208 * @net_dev: Interface net device
1209 * @device_mode: Net interface device mode
1210 * @adapter: Interface upon which IPA is being setup
1211 * @sta_id: Station ID of the API instance
1212 * @session_id: Station ID of the API instance
1213 *
1214 * Return: QDF STATUS
1215 */
1216static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1217 qdf_netdev_t net_dev,
1218 uint8_t device_mode, uint8_t sta_id,
1219 uint8_t session_id)
1220{
1221 struct wlan_ipa_iface_context *iface_context = NULL;
1222 void *tl_context = NULL;
1223 int i;
1224 QDF_STATUS status;
1225
1226 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1227 * channel change indication. Since these indications are sent by lower
1228 * layer as SAP updates and IPA doesn't have to do anything for these
1229 * updates so ignoring!
1230 */
1231 if (device_mode == QDF_SAP_MODE) {
1232 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1233 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001234 if (iface_context->dev == net_dev) {
1235 ipa_debug("found iface %u device_mode %u",
1236 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301237 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001238 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301239 }
1240 }
1241
Yun Park21ec4902018-04-24 12:11:01 -07001242 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1243 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1244 status = QDF_STATUS_E_NOMEM;
1245 QDF_ASSERT(0);
1246 goto end;
1247 }
1248
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301249 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1250 if (ipa_ctx->iface_context[i].tl_context == NULL) {
1251 iface_context = &(ipa_ctx->iface_context[i]);
1252 break;
1253 }
1254 }
1255
1256 if (iface_context == NULL) {
1257 ipa_err("All the IPA interfaces are in use");
1258 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001259 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301260 goto end;
1261 }
1262
1263 iface_context->sta_id = sta_id;
1264 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1265 ipa_ctx->dp_pdev,
1266 sta_id);
1267 if (tl_context == NULL) {
1268 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1269 status = QDF_STATUS_E_INVAL;
1270 goto end;
1271 }
1272
1273 iface_context->tl_context = tl_context;
1274 iface_context->dev = net_dev;
1275 iface_context->device_mode = device_mode;
1276 iface_context->session_id = session_id;
1277
1278 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1279 net_dev->dev_addr,
1280 iface_context->prod_client,
1281 iface_context->cons_client,
1282 session_id,
1283 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1284 if (status != QDF_STATUS_SUCCESS)
1285 goto end;
1286
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301287 /* Register IPA Tx desc free callback */
1288 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1289
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301290 ipa_ctx->num_iface++;
1291
1292 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1293
1294 return status;
1295
1296end:
1297 if (iface_context)
1298 wlan_ipa_cleanup_iface(iface_context);
1299
1300 return status;
1301}
1302
1303/**
1304 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1305 * @ipa_ctx: IPA context
1306 *
1307 * Return: QDF STATUS
1308 */
1309static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1310{
1311 ipa_debug("enter");
1312
1313 ipa_ctx->activated_fw_pipe = 0;
1314 ipa_ctx->resource_loading = true;
1315
1316 /* If RM feature enabled
1317 * Request PROD Resource first
1318 * PROD resource may return sync or async manners
1319 */
1320 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001321 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1322 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301323 /* RM PROD request sync return
1324 * enable pipe immediately
1325 */
1326 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1327 ipa_err("IPA WDI Pipe activation failed");
1328 ipa_ctx->resource_loading = false;
1329 return QDF_STATUS_E_BUSY;
1330 }
1331 } else {
1332 ipa_err("IPA WDI Pipe activation deferred");
1333 }
1334 } else {
1335 /* RM Disabled
1336 * Just enabled all the PIPEs
1337 */
1338 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1339 ipa_err("IPA WDI Pipe activation failed");
1340 ipa_ctx->resource_loading = false;
1341 return QDF_STATUS_E_BUSY;
1342 }
1343 ipa_ctx->resource_loading = false;
1344 }
1345
1346 ipa_debug("exit");
1347
1348 return QDF_STATUS_SUCCESS;
1349}
1350
1351/**
1352 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1353 * @ipa_ctx: IPA context
1354 *
1355 * Return: None
1356 */
1357static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1358{
1359 ipa_debug("enter");
1360
1361 ipa_ctx->resource_unloading = true;
1362 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1363 ipa_info("Disable FW RX PIPE");
1364 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301365
1366 ipa_debug("exit: IPA WDI Pipes deactivated");
1367}
1368
1369/**
1370 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1371 * @ipa_ctx: global IPA context
1372 * @offload_type: MCC or SCC
1373 * @session_id: Session Id
1374 * @enable: TX offload enable or disable
1375 *
1376 * Return: none
1377 */
1378static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1379 uint32_t offload_type,
1380 uint8_t session_id,
1381 bool enable)
1382{
1383
1384 struct ipa_uc_offload_control_params req = {0};
1385
1386 if (session_id >= WLAN_IPA_MAX_SESSION) {
1387 ipa_err("invalid session id: %d", session_id);
1388 return;
1389 }
1390
1391 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301392 ipa_info("IPA offload status is already set");
1393 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301394 offload_type, session_id, enable);
1395 return;
1396 }
1397
1398 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1399 offload_type, session_id, enable);
1400
1401 req.offload_type = offload_type;
1402 req.vdev_id = session_id;
1403 req.enable = enable;
1404
1405 if (QDF_STATUS_SUCCESS !=
1406 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1407 ipa_err("Fail to enable IPA offload");
1408 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1409 offload_type, session_id, enable);
1410 } else {
1411 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1412 }
1413}
1414
1415/**
1416 * __wlan_ipa_wlan_evt() - IPA event handler
1417 * @net_dev: Interface net device
1418 * @device_mode: Net interface device mode
1419 * @sta_id: station id for the event
1420 * @session_id: session id for the event
1421 * @type: event enum of type ipa_wlan_event
1422 * @mac_address: MAC address associated with the event
1423 *
1424 * This function is meant to be called from within wlan_ipa_ctx.c
1425 *
1426 * Return: QDF STATUS
1427 */
1428static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1429 uint8_t sta_id, uint8_t session_id,
1430 qdf_ipa_wlan_event type,
1431 uint8_t *mac_addr)
1432{
1433 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1434 struct wlan_ipa_iface_context *iface_ctx = NULL;
1435 qdf_ipa_msg_meta_t meta;
1436 qdf_ipa_wlan_msg_t *msg;
1437 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1438 int i;
1439 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001440 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301441
Mohit Khannacabf5e72018-07-24 13:28:43 -07001442 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d session_id: %u",
1443 net_dev->name, type, mac_addr, sta_id, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301444
1445 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1446 return QDF_STATUS_E_INVAL;
1447
1448 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1449 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1450 (device_mode != QDF_SAP_MODE)) {
1451 return QDF_STATUS_SUCCESS;
1452 }
1453
Ryan Hsub5783cf2018-05-14 12:13:15 -07001454 if (ipa_ctx->sta_connected) {
1455 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1456 if (iface_ctx)
1457 sta_session_id = iface_ctx->session_id;
1458 else
1459 ipa_err("sta iface_ctx is NULL");
1460 }
1461
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301462 /*
1463 * During IPA UC resource loading/unloading new events can be issued.
1464 */
1465 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1466 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1467 unsigned int pending_event_count;
1468 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1469
1470 ipa_info("Event:%d IPA resource %s inprogress", type,
1471 ipa_ctx->resource_loading ?
1472 "load" : "unload");
1473
1474 /* Wait until completion of the long/unloading */
1475 status = qdf_wait_for_event_completion(
1476 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001477 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301478 if (status != QDF_STATUS_SUCCESS) {
1479 /*
1480 * If timed out, store the events separately and
1481 * handle them later.
1482 */
1483 ipa_info("IPA resource %s timed out",
1484 ipa_ctx->resource_loading ?
1485 "load" : "unload");
1486
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301487 if (type == QDF_IPA_AP_DISCONNECT)
1488 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1489 SIR_AP_RX_DATA_OFFLOAD,
1490 session_id, false);
1491
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301492 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1493
1494 pending_event_count =
1495 qdf_list_size(&ipa_ctx->pending_event);
1496 if (pending_event_count >=
1497 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1498 ipa_info("Reached max pending evt count");
1499 qdf_list_remove_front(
1500 &ipa_ctx->pending_event,
1501 (qdf_list_node_t **)&pending_event);
1502 } else {
1503 pending_event =
1504 (struct wlan_ipa_uc_pending_event *)
1505 qdf_mem_malloc(sizeof(
1506 struct wlan_ipa_uc_pending_event));
1507 }
1508
1509 if (!pending_event) {
1510 ipa_err("Pending event memory alloc fail");
1511 qdf_mutex_release(&ipa_ctx->ipa_lock);
1512 return QDF_STATUS_E_NOMEM;
1513 }
1514
1515 pending_event->net_dev = net_dev;
1516 pending_event->device_mode = device_mode;
1517 pending_event->sta_id = sta_id;
1518 pending_event->session_id = session_id;
1519 pending_event->type = type;
1520 pending_event->is_loading = ipa_ctx->resource_loading;
1521 qdf_mem_copy(pending_event->mac_addr,
1522 mac_addr, QDF_MAC_ADDR_SIZE);
1523 qdf_list_insert_back(&ipa_ctx->pending_event,
1524 &pending_event->node);
1525
1526 qdf_mutex_release(&ipa_ctx->ipa_lock);
1527
Yun Park21ec4902018-04-24 12:11:01 -07001528 /* Cleanup interface */
1529 if (type == QDF_IPA_STA_DISCONNECT ||
1530 type == QDF_IPA_AP_DISCONNECT) {
1531 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1532 iface_ctx = &ipa_ctx->iface_context[i];
1533
1534 if (iface_ctx->dev == net_dev)
1535 break;
1536 }
1537 if (iface_ctx)
1538 wlan_ipa_cleanup_iface(iface_ctx);
1539 }
1540
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301541 return QDF_STATUS_SUCCESS;
1542 }
1543 ipa_info("IPA resource %s completed",
1544 ipa_ctx->resource_loading ?
1545 "load" : "unload");
1546 }
1547
1548 ipa_ctx->stats.event[type]++;
1549
1550 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1551 switch (type) {
1552 case QDF_IPA_STA_CONNECT:
1553 qdf_mutex_acquire(&ipa_ctx->event_lock);
1554
1555 /* STA already connected and without disconnect, connect again
1556 * This is Roaming scenario
1557 */
1558 if (ipa_ctx->sta_connected) {
1559 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1560 if (iface_ctx)
1561 wlan_ipa_cleanup_iface(iface_ctx);
1562 }
1563
1564 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1565 sta_id, session_id);
1566 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001567 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301568 qdf_mutex_release(&ipa_ctx->event_lock);
1569 goto end;
1570 }
1571
1572 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1573 (ipa_ctx->sap_num_connected_sta > 0) &&
1574 !ipa_ctx->sta_connected) {
1575 qdf_mutex_release(&ipa_ctx->event_lock);
1576 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1577 SIR_STA_RX_DATA_OFFLOAD, session_id,
1578 true);
1579 qdf_mutex_acquire(&ipa_ctx->event_lock);
1580 }
1581
1582 ipa_ctx->vdev_to_iface[session_id] =
1583 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1584
1585 ipa_ctx->sta_connected = 1;
1586
1587 qdf_mutex_release(&ipa_ctx->event_lock);
1588
Mohit Khannacabf5e72018-07-24 13:28:43 -07001589 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1590 ipa_ctx->sta_connected,
1591 session_id,
1592 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301593 break;
1594
1595 case QDF_IPA_AP_CONNECT:
1596 qdf_mutex_acquire(&ipa_ctx->event_lock);
1597
1598 /* For DFS channel we get two start_bss event (before and after
1599 * CAC). Also when ACS range includes both DFS and non DFS
1600 * channels, we could possibly change channel many times due to
1601 * RADAR detection and chosen channel may not be a DFS channels.
1602 * So dont return error here. Just discard the event.
1603 */
jiadc908ada2018-05-11 14:40:54 +08001604 if (ipa_ctx->vdev_to_iface[session_id] !=
1605 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301606 qdf_mutex_release(&ipa_ctx->event_lock);
1607 return 0;
1608 }
1609
1610 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1611 sta_id, session_id);
1612 if (status != QDF_STATUS_SUCCESS) {
1613 qdf_mutex_release(&ipa_ctx->event_lock);
1614 ipa_err("%s: Evt: %d, Interface setup failed",
1615 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1616 goto end;
1617 }
1618
1619 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1620 qdf_mutex_release(&ipa_ctx->event_lock);
1621 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1622 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1623 qdf_mutex_acquire(&ipa_ctx->event_lock);
1624 }
1625
1626 ipa_ctx->vdev_to_iface[session_id] =
1627 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001628 ipa_debug("vdev_to_iface[%u]=%u",
1629 session_id,
1630 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301631 qdf_mutex_release(&ipa_ctx->event_lock);
1632 break;
1633
1634 case QDF_IPA_STA_DISCONNECT:
1635 qdf_mutex_acquire(&ipa_ctx->event_lock);
1636
1637 if (!ipa_ctx->sta_connected) {
1638 qdf_mutex_release(&ipa_ctx->event_lock);
1639 ipa_err("%s: Evt: %d, STA already disconnected",
1640 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1641 return QDF_STATUS_E_INVAL;
1642 }
1643
1644 ipa_ctx->sta_connected = 0;
1645
1646 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1647 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1648 msg_ex->name);
1649 } else {
1650 /* Disable IPA UC TX PIPE when STA disconnected */
1651 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001652 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001653 !ipa_ctx->ipa_pipes_down &&
1654 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001655 if (cds_is_driver_unloading()) {
1656 /*
1657 * We disable WDI pipes directly here
1658 * since IPA_OPCODE_TX/RX_SUSPEND
1659 * message will not be processed when
1660 * unloading WLAN driver is in progress
1661 */
1662 wlan_ipa_uc_disable_pipes(ipa_ctx);
1663 } else {
1664 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1665 }
1666 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301667 }
1668
1669 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1670 (ipa_ctx->sap_num_connected_sta > 0)) {
1671 qdf_mutex_release(&ipa_ctx->event_lock);
1672 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1673 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1674 qdf_mutex_acquire(&ipa_ctx->event_lock);
1675 ipa_ctx->vdev_to_iface[session_id] =
1676 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001677 ipa_debug("vdev_to_iface[%u]=%u",
1678 session_id,
1679 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301680 }
1681
1682 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1683 iface_ctx = &ipa_ctx->iface_context[i];
1684
1685 if (iface_ctx->dev == net_dev)
1686 break;
1687 }
1688 if (i < WLAN_IPA_MAX_IFACE)
1689 wlan_ipa_cleanup_iface(iface_ctx);
1690
1691 qdf_mutex_release(&ipa_ctx->event_lock);
1692
1693 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1694 break;
1695
1696 case QDF_IPA_AP_DISCONNECT:
1697 qdf_mutex_acquire(&ipa_ctx->event_lock);
1698
1699 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001700 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001701 !ipa_ctx->ipa_pipes_down &&
1702 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301703 if (cds_is_driver_unloading()) {
1704 /*
1705 * We disable WDI pipes directly here since
1706 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1707 * processed when unloading WLAN driver is in
1708 * progress
1709 */
1710 wlan_ipa_uc_disable_pipes(ipa_ctx);
1711 } else {
1712 /*
1713 * This shouldn't happen :
1714 * No interface left but WDI pipes are still
1715 * active - force close WDI pipes
1716 */
1717 ipa_err("No interface left but WDI pipes are still active");
1718 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1719 }
1720 }
1721
1722 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1723 qdf_mutex_release(&ipa_ctx->event_lock);
1724 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1725 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1726 qdf_mutex_acquire(&ipa_ctx->event_lock);
1727 ipa_ctx->vdev_to_iface[session_id] =
1728 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001729 ipa_debug("vdev_to_iface[%u]=%u",
1730 session_id,
1731 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301732 }
1733
1734 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1735 iface_ctx = &ipa_ctx->iface_context[i];
1736
1737 if (iface_ctx->dev == net_dev)
1738 break;
1739 }
1740 if (i < WLAN_IPA_MAX_IFACE)
1741 wlan_ipa_cleanup_iface(iface_ctx);
1742
1743 qdf_mutex_release(&ipa_ctx->event_lock);
1744 break;
1745
1746 case QDF_IPA_CLIENT_CONNECT_EX:
1747 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1748 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1749 net_dev->name, type);
1750 return QDF_STATUS_SUCCESS;
1751 }
1752
1753 qdf_mutex_acquire(&ipa_ctx->event_lock);
1754 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1755 mac_addr)) {
1756 qdf_mutex_release(&ipa_ctx->event_lock);
1757 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1758 return QDF_STATUS_SUCCESS;
1759 }
1760
1761 /* Enable IPA UC Data PIPEs when first STA connected */
1762 if (ipa_ctx->sap_num_connected_sta == 0 &&
1763 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301764
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301765 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1766 ipa_ctx->sta_connected) {
1767 qdf_mutex_release(&ipa_ctx->event_lock);
1768 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1769 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301770 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301771 qdf_mutex_acquire(&ipa_ctx->event_lock);
1772 }
1773
1774 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1775 if (status != QDF_STATUS_SUCCESS) {
1776 ipa_info("%s: handle 1st con fail",
1777 net_dev->name);
1778
1779 if (wlan_ipa_uc_sta_is_enabled(
1780 ipa_ctx->config) &&
1781 ipa_ctx->sta_connected) {
1782 qdf_mutex_release(&ipa_ctx->event_lock);
1783 wlan_ipa_uc_offload_enable_disable(
1784 ipa_ctx,
1785 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301786 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301787 } else {
1788 qdf_mutex_release(&ipa_ctx->event_lock);
1789 }
1790
1791 return status;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001792 } else
1793 ipa_debug("%s: handle 1st con success",
1794 net_dev->name);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301795 }
1796
1797 ipa_ctx->sap_num_connected_sta++;
1798
1799 qdf_mutex_release(&ipa_ctx->event_lock);
1800
1801 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1802 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1803 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1804 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1805 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1806
1807 if (msg_ex == NULL) {
1808 ipa_err("msg_ex allocation failed");
1809 return QDF_STATUS_E_NOMEM;
1810 }
1811 strlcpy(msg_ex->name, net_dev->name,
1812 IPA_RESOURCE_NAME_MAX);
1813 msg_ex->num_of_attribs = 1;
1814 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1815 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1816 msg_ex->attribs[0].offset =
1817 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1818 } else {
1819 msg_ex->attribs[0].offset =
1820 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1821 }
1822 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1823 IPA_MAC_ADDR_SIZE);
1824
1825 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1826 ipa_info("%s: Evt: %d send ipa msg fail",
1827 net_dev->name, type);
1828 qdf_mem_free(msg_ex);
1829 return QDF_STATUS_E_FAILURE;
1830 }
1831 ipa_ctx->stats.num_send_msg++;
1832
1833 ipa_info("sap_num_connected_sta=%d",
1834 ipa_ctx->sap_num_connected_sta);
1835
1836 return QDF_STATUS_SUCCESS;
1837
1838 case WLAN_CLIENT_DISCONNECT:
1839 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1840 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1841 msg_ex->name);
1842 return QDF_STATUS_SUCCESS;
1843 }
1844
1845 qdf_mutex_acquire(&ipa_ctx->event_lock);
1846 if (!ipa_ctx->sap_num_connected_sta) {
1847 qdf_mutex_release(&ipa_ctx->event_lock);
1848 ipa_err("%s: Evt: %d, Client already disconnected",
1849 msg_ex->name,
1850 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1851
1852 return QDF_STATUS_SUCCESS;
1853 }
1854 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
1855 sta_id, mac_addr)) {
1856 qdf_mutex_release(&ipa_ctx->event_lock);
1857 ipa_err("%s: STA ID %d NOT found, not valid",
1858 msg_ex->name, sta_id);
1859
1860 return QDF_STATUS_SUCCESS;
1861 }
1862 ipa_ctx->sap_num_connected_sta--;
1863
1864 /* Disable IPA UC TX PIPE when last STA disconnected */
1865 if (!ipa_ctx->sap_num_connected_sta &&
1866 ipa_ctx->uc_loaded == true) {
Yun Parka29974a2018-04-09 12:05:49 -07001867 if ((false == ipa_ctx->resource_unloading) &&
1868 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
1869 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08001870 if (cds_is_driver_unloading()) {
1871 /*
1872 * We disable WDI pipes directly here
1873 * since IPA_OPCODE_TX/RX_SUSPEND
1874 * message will not be processed when
1875 * unloading WLAN driver is in progress
1876 */
1877 wlan_ipa_uc_disable_pipes(ipa_ctx);
1878 } else {
1879 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1880 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301881 }
1882
1883 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1884 ipa_ctx->sta_connected) {
1885 qdf_mutex_release(&ipa_ctx->event_lock);
1886 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1887 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301888 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301889 } else {
1890 qdf_mutex_release(&ipa_ctx->event_lock);
1891 }
1892 } else {
1893 qdf_mutex_release(&ipa_ctx->event_lock);
1894 }
1895
1896 ipa_info("sap_num_connected_sta=%d",
1897 ipa_ctx->sap_num_connected_sta);
1898 break;
1899
1900 default:
1901 return QDF_STATUS_SUCCESS;
1902 }
1903
1904 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
1905 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1906 if (!msg) {
1907 ipa_err("msg allocation failed");
1908 return QDF_STATUS_E_NOMEM;
1909 }
1910
1911 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1912 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
1913 IPA_RESOURCE_NAME_MAX);
1914 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
1915
1916 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
1917 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1918
1919 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
1920
1921 ipa_err("%s: Evt: %d fail",
1922 QDF_IPA_WLAN_MSG_NAME(msg),
1923 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1924 qdf_mem_free(msg);
1925
1926 return QDF_STATUS_E_FAILURE;
1927 }
1928
1929 ipa_ctx->stats.num_send_msg++;
1930
1931end:
1932 return QDF_STATUS_SUCCESS;
1933}
1934
1935/**
1936 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07001937 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301938 *
1939 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
1940 */
1941static qdf_ipa_wlan_event
1942wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
1943{
Yun Park84fbb272018-04-02 15:31:01 -07001944 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301945
1946 switch (wlan_ipa_event_type) {
1947 case WLAN_IPA_CLIENT_CONNECT:
1948 ipa_event = QDF_IPA_CLIENT_CONNECT;
1949 break;
1950 case WLAN_IPA_CLIENT_DISCONNECT:
1951 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
1952 break;
1953 case WLAN_IPA_AP_CONNECT:
1954 ipa_event = QDF_IPA_AP_CONNECT;
1955 break;
1956 case WLAN_IPA_AP_DISCONNECT:
1957 ipa_event = QDF_IPA_AP_DISCONNECT;
1958 break;
1959 case WLAN_IPA_STA_CONNECT:
1960 ipa_event = QDF_IPA_STA_CONNECT;
1961 break;
1962 case WLAN_IPA_STA_DISCONNECT:
1963 ipa_event = QDF_IPA_STA_DISCONNECT;
1964 break;
1965 case WLAN_IPA_CLIENT_CONNECT_EX:
1966 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
1967 break;
1968 case WLAN_IPA_WLAN_EVENT_MAX:
1969 default:
1970 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
1971 break;
1972 }
1973
1974 return ipa_event;
1975}
1976
1977/**
1978 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
1979 * @net_dev: Interface net device
1980 * @device_mode: Net interface device mode
1981 * @sta_id: station id for the event
1982 * @session_id: session id for the event
1983 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
1984 * @mac_address: MAC address associated with the event
1985 *
1986 * Return: QDF_STATUS
1987 */
1988QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1989 uint8_t sta_id, uint8_t session_id,
1990 enum wlan_ipa_wlan_event ipa_event_type,
1991 uint8_t *mac_addr)
1992{
1993 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
1994 QDF_STATUS status = QDF_STATUS_SUCCESS;
1995
1996 /* Data path offload only support for STA and SAP mode */
1997 if ((device_mode == QDF_STA_MODE) ||
1998 (device_mode == QDF_SAP_MODE))
1999 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
2000 session_id, type, mac_addr);
2001
2002 return status;
2003}
2004
2005/**
2006 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2007 * @ipa_ctx: Global IPA IPA context
2008 * @is_loading: Indicate if invoked during loading
2009 *
2010 * Return: None
2011 */
2012static void
2013wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2014{
2015 unsigned int pending_event_count;
2016 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2017
2018 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2019 ipa_debug("Pending Event Count %d", pending_event_count);
2020 if (!pending_event_count) {
2021 ipa_debug("No Pending Event");
2022 return;
2023 }
2024
2025 qdf_list_remove_front(&ipa_ctx->pending_event,
2026 (qdf_list_node_t **)&pending_event);
2027 while (pending_event != NULL) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302028 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2029 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2030 struct wlan_objmgr_vdev *vdev =
2031 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2032 pending_event->session_id,
2033 WLAN_IPA_ID);
2034 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302035 __wlan_ipa_wlan_evt(pending_event->net_dev,
2036 pending_event->device_mode,
2037 pending_event->sta_id,
2038 pending_event->session_id,
2039 pending_event->type,
2040 pending_event->mac_addr);
2041 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302042
2043 if (vdev)
2044 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302045 qdf_mem_free(pending_event);
2046 pending_event = NULL;
2047 qdf_list_remove_front(&ipa_ctx->pending_event,
2048 (qdf_list_node_t **)&pending_event);
2049 }
2050}
2051
2052/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002053 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2054 * @ipa_ctx: IPA context
2055 *
2056 * Return: None
2057 */
2058static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2059{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302060 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002061 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302062 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002063
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302064 if (!ipa_ctx->tx_desc_pool)
2065 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002066
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302067 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2068 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2069 for (i = 0; i < pool_size; i++) {
2070 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002071 if (ipa_tx_desc)
2072 qdf_ipa_free_skb(ipa_tx_desc);
2073
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302074 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2075 &ipa_ctx->tx_desc_pool[i].node) !=
2076 QDF_STATUS_SUCCESS)
2077 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002078 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302079 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2080
2081 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2082 qdf_mem_free(ipa_ctx->tx_desc_pool);
2083 ipa_ctx->tx_desc_pool = NULL;
2084
2085 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2086 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002087}
2088
2089/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302090 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302091 * @ipa_ctx: IPA context
2092 *
2093 * Return: QDF_STATUS
2094 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302095static QDF_STATUS
2096wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302097{
2098 int i;
2099 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302100
2101 max_desc_cnt = ipa_ctx->config->txbuf_count;
2102
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302103 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2104 max_desc_cnt);
2105
2106 if (!ipa_ctx->tx_desc_pool) {
2107 ipa_err("Free Tx descriptor allocation failed");
2108 return QDF_STATUS_E_NOMEM;
2109 }
2110
2111 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302112
2113 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2114 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302115 ipa_ctx->tx_desc_pool[i].id = i;
2116 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2117 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2118 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302119 }
2120
2121 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2122 ipa_ctx->stats.num_tx_desc_error = 0;
2123
2124 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2125
2126 return QDF_STATUS_SUCCESS;
2127}
2128
2129#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2130/**
2131 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2132 * @ipa_ctx: Global IPA IPA context
2133 * @desc_fifo_sz: Number of descriptors
2134 *
2135 * Return: 0 on success, negative errno on error
2136 */
2137static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2138 int32_t desc_fifo_sz)
2139{
2140 int i, ret = 0;
2141 qdf_ipa_sys_connect_params_t *ipa;
2142
2143 /*setup TX pipes */
2144 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2145 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2146
2147 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2148 ipa->desc_fifo_sz = desc_fifo_sz;
2149 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302150 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302151
2152 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2153 ipa->ipa_ep_cfg.hdr.hdr_len =
2154 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2155 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2156 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2157 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2158 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2159 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2160 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2161 } else {
2162 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2163 }
2164 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2165
2166 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2167 &ipa_ctx->sys_pipe[i].conn_hdl);
2168 if (ret) {
2169 ipa_err("Failed for pipe %d ret: %d", i, ret);
2170 return ret;
2171 }
2172 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2173 }
2174
2175 return ret;
2176}
2177#else
2178/**
2179 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2180 * @ipa_ctx: Global IPA IPA context
2181 * @desc_fifo_sz: Number of descriptors
2182 *
2183 * Return: 0 on success, negative errno on error
2184 */
2185static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2186 int32_t desc_fifo_sz)
2187{
2188 /*
2189 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2190 * is enabled, where per vdev descriptors are supported in firmware.
2191 */
2192 return 0;
2193}
2194#endif
2195
2196/**
2197 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2198 * @ipa_ctx: Global IPA IPA context
2199 * @desc_fifo_sz: Number of descriptors
2200 *
2201 * Return: 0 on success, negative errno on error
2202 */
2203static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2204 int32_t desc_fifo_sz)
2205{
2206 int ret = 0;
2207 qdf_ipa_sys_connect_params_t *ipa;
2208
2209 /*
2210 * Hard code it here, this can be extended if in case
2211 * PROD pipe is also per interface.
2212 * Right now there is no advantage of doing this.
2213 */
2214 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2215
2216 ipa->client = IPA_CLIENT_WLAN1_PROD;
2217
2218 ipa->desc_fifo_sz = desc_fifo_sz;
2219 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302220 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302221
2222 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2223 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2224 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2225 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2226
2227 ret = qdf_ipa_setup_sys_pipe(ipa,
2228 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2229 if (ret) {
2230 ipa_err("Failed for RX pipe: %d", ret);
2231 return ret;
2232 }
2233 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2234
2235 return ret;
2236}
2237
2238/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002239 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2240 * @ipa_ctx: Global IPA IPA context
2241 *
2242 * Return: None
2243 */
2244static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2245{
2246 int ret, i;
2247
2248 if (!ipa_ctx)
2249 return;
2250
2251 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2252 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2253 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2254 ipa_ctx->sys_pipe[i].conn_hdl);
2255 if (ret)
2256 ipa_err("Failed:%d", ret);
2257
2258 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2259 }
2260 }
2261
2262 wlan_ipa_free_tx_desc_list(ipa_ctx);
2263}
2264
2265/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302266 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2267 * @ipa_ctx: Global IPA IPA context
2268 *
2269 * Return: 0 on success, negative errno on error
2270 */
2271static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2272{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002273 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302274 uint32_t desc_fifo_sz;
2275
2276 /* The maximum number of descriptors that can be provided to a BAM at
2277 * once is one less than the total number of descriptors that the buffer
2278 * can contain.
2279 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2280 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2281 * be provided at once.
2282 * Because of above requirement, one extra descriptor will be added to
2283 * make sure hardware always has one descriptor.
2284 */
2285 desc_fifo_sz = ipa_ctx->config->desc_size
2286 + SPS_DESC_SIZE;
2287
2288 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2289 if (ret) {
2290 ipa_err("Failed for TX pipe: %d", ret);
2291 goto setup_sys_pipe_fail;
2292 }
2293
2294 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2295 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2296 if (ret) {
2297 ipa_err("Failed for RX pipe: %d", ret);
2298 goto setup_sys_pipe_fail;
2299 }
2300 }
2301
2302 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302303 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302304 if (ret)
2305 goto setup_sys_pipe_fail;
2306
2307 return ret;
2308
2309setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002310 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302311
2312 return ret;
2313}
2314
jiadbb47e132018-03-30 16:28:30 +08002315#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2316QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2317 bool mcc_mode)
2318{
2319 qdf_ipa_msg_meta_t meta;
2320 qdf_ipa_wlan_msg_t *msg;
2321 int ret;
2322
2323 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2324 return QDF_STATUS_SUCCESS;
2325
2326 /* Send SCC/MCC Switching event to IPA */
2327 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2328 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2329 if (msg == NULL) {
2330 ipa_err("msg allocation failed");
2331 return QDF_STATUS_E_NOMEM;
2332 }
2333
jiad629b2172018-05-11 15:34:22 +08002334 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002335 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002336 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2337 } else {
jiadbb47e132018-03-30 16:28:30 +08002338 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002339 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2340 }
2341
jiadbb47e132018-03-30 16:28:30 +08002342 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2343 "ipa_send_msg(Evt:%d)",
2344 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2345
2346 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2347
2348 if (ret) {
2349 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2350 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2351 qdf_mem_free(msg);
2352 return QDF_STATUS_E_FAILURE;
2353 }
2354
2355 return QDF_STATUS_SUCCESS;
2356}
2357
2358static void wlan_ipa_mcc_work_handler(void *data)
2359{
2360 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2361
2362 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2363}
2364#endif
2365
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302366/**
2367 * wlan_ipa_setup() - IPA initialization function
2368 * @ipa_ctx: IPA context
2369 * @ipa_cfg: IPA config
2370 *
2371 * Allocate ipa_ctx resources, ipa pipe resource and register
2372 * wlan interface with IPA module.
2373 *
2374 * Return: QDF_STATUS enumeration
2375 */
2376QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2377 struct wlan_ipa_config *ipa_cfg)
2378{
2379 int ret, i;
2380 struct wlan_ipa_iface_context *iface_context = NULL;
2381 QDF_STATUS status;
2382
2383 ipa_debug("enter");
2384
2385 gp_ipa = ipa_ctx;
2386 ipa_ctx->num_iface = 0;
2387 ipa_ctx->config = ipa_cfg;
2388
2389 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2390
2391 /* Create the interface context */
2392 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2393 iface_context = &ipa_ctx->iface_context[i];
2394 iface_context->ipa_ctx = ipa_ctx;
2395 iface_context->cons_client =
2396 wlan_ipa_iface_2_client[i].cons_client;
2397 iface_context->prod_client =
2398 wlan_ipa_iface_2_client[i].prod_client;
2399 iface_context->iface_id = i;
2400 iface_context->dev = NULL;
2401 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2402 iface_context->tl_context = NULL;
2403 qdf_spinlock_create(&iface_context->interface_lock);
2404 }
2405
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302406 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302407 qdf_spinlock_create(&ipa_ctx->pm_lock);
2408 qdf_spinlock_create(&ipa_ctx->q_lock);
2409 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2410 qdf_list_create(&ipa_ctx->pending_event, 1000);
2411 qdf_mutex_create(&ipa_ctx->event_lock);
2412 qdf_mutex_create(&ipa_ctx->ipa_lock);
2413
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302414 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2415 if (status != QDF_STATUS_SUCCESS)
2416 goto fail_setup_rm;
2417
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302418 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2419 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2420 sizeof(struct wlan_ipa_sys_pipe));
2421
2422 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2423 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2424 ipa_ctx->sap_num_connected_sta = 0;
2425 ipa_ctx->ipa_tx_packets_diff = 0;
2426 ipa_ctx->ipa_rx_packets_diff = 0;
2427 ipa_ctx->ipa_p_tx_packets = 0;
2428 ipa_ctx->ipa_p_rx_packets = 0;
2429 ipa_ctx->resource_loading = false;
2430 ipa_ctx->resource_unloading = false;
2431 ipa_ctx->sta_connected = 0;
2432 ipa_ctx->ipa_pipes_down = true;
2433 ipa_ctx->wdi_enabled = false;
2434 /* Setup IPA system pipes */
2435 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2436 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2437 if (ret)
2438 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002439
2440 qdf_create_work(0, &ipa_ctx->mcc_work,
2441 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302442 }
2443
2444 status = wlan_ipa_wdi_init(ipa_ctx);
2445 if (status == QDF_STATUS_E_BUSY)
2446 status = wlan_ipa_uc_send_wdi_control_msg(false);
2447 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002448 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302449 goto fail_create_sys_pipe;
2450 }
2451 } else {
2452 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2453 if (ret)
2454 goto fail_create_sys_pipe;
2455 }
2456
2457 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2458
2459 ipa_debug("exit: success");
2460
2461 return QDF_STATUS_SUCCESS;
2462
2463fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302464 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2465
2466fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302467 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302468 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2469 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2470 iface_context = &ipa_ctx->iface_context[i];
2471 qdf_spinlock_destroy(&iface_context->interface_lock);
2472 }
2473 qdf_mutex_destroy(&ipa_ctx->event_lock);
2474 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2475 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302476 gp_ipa = NULL;
2477 ipa_debug("exit: fail");
2478
2479 return QDF_STATUS_E_FAILURE;
2480}
2481
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302482void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2483{
2484 qdf_nbuf_t skb;
2485 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2486
2487 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2488 return;
2489
2490 qdf_cancel_work(&ipa_ctx->pm_work);
2491
2492 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2493
2494 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2495 != NULL)) {
2496 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2497
2498 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002499
2500 if (pm_tx_cb->exception) {
2501 dev_kfree_skb_any(skb);
2502 } else {
2503 if (pm_tx_cb->ipa_tx_desc)
2504 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2505 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302506
2507 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2508 }
2509 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2510}
2511
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302512QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2513{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302514 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302515 int i;
2516
2517 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2518 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2519
2520 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002521 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302522 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002523 qdf_cancel_work(&ipa_ctx->mcc_work);
2524 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302525
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302526 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2527
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302528 wlan_ipa_flush(ipa_ctx);
2529
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302530 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2531 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2532
2533 /* destroy the interface lock */
2534 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2535 iface_context = &ipa_ctx->iface_context[i];
2536 qdf_spinlock_destroy(&iface_context->interface_lock);
2537 }
2538
2539 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2540 wlan_ipa_wdi_cleanup();
2541 qdf_mutex_destroy(&ipa_ctx->event_lock);
2542 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2543 qdf_list_destroy(&ipa_ctx->pending_event);
2544
2545 }
2546
2547 gp_ipa = NULL;
2548
2549 return QDF_STATUS_SUCCESS;
2550}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302551
2552struct wlan_ipa_iface_context
2553*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2554{
2555 struct wlan_ipa_iface_context *iface_ctx = NULL;
2556 int i;
2557
2558 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2559 iface_ctx = &ipa_ctx->iface_context[i];
2560
2561 if (iface_ctx->device_mode == mode)
2562 return iface_ctx;
2563 }
2564
2565 return NULL;
2566}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302567
jiadbb47e132018-03-30 16:28:30 +08002568void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302569{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302570 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002571 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302572
jiadbb47e132018-03-30 16:28:30 +08002573 if (ipa_ctx->mcc_mode == mcc_mode)
2574 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302575
jiadbb47e132018-03-30 16:28:30 +08002576 ipa_ctx->mcc_mode = mcc_mode;
2577 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302578}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302579
2580/**
2581 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2582 * @ipa_ctx: ipa ipa local context
2583 *
2584 * Will handle IPA UC image loaded indication comes from IPA kernel
2585 *
2586 * Return: None
2587 */
2588static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2589{
2590 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2591 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2592 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2593 QDF_STATUS status;
2594
2595 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002596
2597 if (!qdf_dev) {
2598 ipa_err("qdf device is NULL!");
2599 return;
2600 }
2601
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302602 if (true == ipa_ctx->uc_loaded) {
2603 ipa_info("UC already loaded");
2604 return;
2605 }
2606
Lihua Liu15f6e452018-05-30 17:31:06 +08002607 if (!qdf_dev) {
2608 ipa_err("qdf_dev is null");
2609 return;
2610 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302611 /* Connect pipe */
2612 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2613 if (status) {
2614 ipa_err("Failure to setup IPA pipes (status=%d)",
2615 status);
2616 return;
2617 }
2618
2619 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302620
2621 /* If already any STA connected, enable IPA/FW PIPEs */
2622 if (ipa_ctx->sap_num_connected_sta) {
2623 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2624 wlan_ipa_uc_handle_first_con(ipa_ctx);
2625 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302626}
2627
2628/**
2629 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2630 * @op_msg: operation message received from firmware
2631 * @usr_ctxt: user context registered with TL (we register the IPA Global
2632 * context)
2633 *
2634 * Return: None
2635 */
2636static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2637 struct wlan_ipa_priv *ipa_ctx)
2638{
2639 struct op_msg_type *msg = op_msg;
2640 struct ipa_uc_fw_stats *uc_fw_stat;
2641
2642 if (!op_msg) {
2643 ipa_err("INVALID ARG");
2644 return;
2645 }
2646
2647 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2648 ipa_err("INVALID OPCODE %d", msg->op_code);
2649 qdf_mem_free(op_msg);
2650 return;
2651 }
2652
2653 ipa_debug("OPCODE=%d", msg->op_code);
2654
2655 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2656 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2657 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2658 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07002659 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302660 ipa_ctx->resource_loading = false;
2661 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2662 if (ipa_ctx->wdi_enabled == false) {
2663 ipa_ctx->wdi_enabled = true;
2664 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2665 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2666 ipa_ctx->mcc_mode);
2667 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302668 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302669 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07002670 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302671 QDF_IPA_RM_RESOURCE_GRANTED,
2672 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2673 ipa_ctx->pending_cons_req = false;
2674 }
2675 qdf_mutex_release(&ipa_ctx->ipa_lock);
2676 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2677 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2678 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05302679
2680 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
2681 wlan_ipa_uc_disable_pipes(ipa_ctx);
2682 ipa_info("Disable FW TX PIPE");
2683 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2684 false, true);
2685 }
2686
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302687 ipa_ctx->activated_fw_pipe--;
2688 if (!ipa_ctx->activated_fw_pipe) {
2689 /*
2690 * Async return success from FW
2691 * Disable/suspend all the PIPEs
2692 */
2693 ipa_ctx->resource_unloading = false;
2694 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302695 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07002696 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
2697 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302698 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302699 ipa_ctx->pending_cons_req = false;
2700 }
2701 qdf_mutex_release(&ipa_ctx->ipa_lock);
2702 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2703 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2704 uc_fw_stat = (struct ipa_uc_fw_stats *)
2705 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2706
2707 /* WLAN FW WDI stats */
2708 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2709 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2710 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2711 /* STATs from FW */
2712 uc_fw_stat = (struct ipa_uc_fw_stats *)
2713 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2714 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2715 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2716 uc_fw_stat->tx_pkts_completed,
2717 ipa_ctx->ipa_p_tx_packets);
2718 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2719 (uc_fw_stat->rx_num_ind_drop_no_space +
2720 uc_fw_stat->rx_num_ind_drop_no_buf +
2721 uc_fw_stat->rx_num_pkts_indicated),
2722 ipa_ctx->ipa_p_rx_packets);
2723
2724 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2725 ipa_ctx->ipa_p_rx_packets =
2726 (uc_fw_stat->rx_num_ind_drop_no_space +
2727 uc_fw_stat->rx_num_ind_drop_no_buf +
2728 uc_fw_stat->rx_num_pkts_indicated);
2729 qdf_mutex_release(&ipa_ctx->ipa_lock);
2730 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2731 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2732 wlan_ipa_uc_loaded_handler(ipa_ctx);
2733 qdf_mutex_release(&ipa_ctx->ipa_lock);
2734 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2735 ipa_err("Invalid message: op_code=%d, reason=%d",
2736 msg->op_code, ipa_ctx->stat_req_reason);
2737 }
2738
2739 qdf_mem_free(op_msg);
2740}
2741
2742/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302743 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2744 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302745 *
2746 * Return: None
2747 */
jitiphilfdcaaba2018-09-03 16:19:52 +05302748static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302749{
2750 struct op_msg_type *msg;
2751 struct uc_op_work_struct *uc_op_work =
2752 (struct uc_op_work_struct *)data;
2753 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2754
jitiphilfdcaaba2018-09-03 16:19:52 +05302755 if (qdf_is_module_state_transitioning()) {
2756 ipa_err("Module transition in progress");
2757 return;
2758 }
2759
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302760 msg = uc_op_work->msg;
2761 uc_op_work->msg = NULL;
2762 ipa_debug("posted msg %d", msg->op_code);
2763
2764 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2765}
2766
2767/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302768 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
2769 * __wlan_ipa_uc_fw_op_event_handler
2770 * @data: uC OP work
2771 *
2772 * Return: None
2773 */
2774static void wlan_ipa_uc_fw_op_event_handler(void *data)
2775{
2776 qdf_ssr_protect(__func__);
2777 __wlan_ipa_uc_fw_op_event_handler(data);
2778 qdf_ssr_unprotect(__func__);
2779}
2780
2781/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302782 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2783 * @op_msg: operation message received from firmware
2784 * @ipa_ctx: Global IPA context
2785 *
2786 * Return: None
2787 */
2788static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2789{
2790 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2791 struct op_msg_type *msg;
2792 struct uc_op_work_struct *uc_op_work;
2793
2794 if (!ipa_ctx)
2795 goto end;
2796
2797 msg = (struct op_msg_type *)op_msg;
2798
2799 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2800 ipa_err("Invalid OP Code (%d)", msg->op_code);
2801 goto end;
2802 }
2803
2804 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2805 if (uc_op_work->msg) {
2806 /* When the same uC OPCODE is already pended, just return */
2807 goto end;
2808 }
2809
2810 uc_op_work->msg = msg;
2811 qdf_sched_work(0, &uc_op_work->work);
2812 return;
2813
2814end:
2815 qdf_mem_free(op_msg);
2816}
2817
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302818QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2819 qdf_device_t osdev)
2820{
2821 uint8_t i;
2822 QDF_STATUS status = QDF_STATUS_SUCCESS;
2823
2824 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2825 return QDF_STATUS_SUCCESS;
2826
2827 ipa_debug("enter");
2828
2829 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
2830 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
2831 ipa_ctx->vdev_offload_enabled[i] = false;
2832 }
2833
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302834 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
2835 ipa_err("IPA UC resource alloc fail");
2836 status = QDF_STATUS_E_FAILURE;
2837 goto fail_return;
2838 }
2839
2840 if (true == ipa_ctx->uc_loaded) {
2841 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
2842 if (status) {
2843 ipa_err("Failure to setup IPA pipes (status=%d)",
2844 status);
2845 status = QDF_STATUS_E_FAILURE;
2846 goto fail_return;
2847 }
2848
2849 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
2850 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08002851
2852 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
2853 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302854 }
2855
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302856 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2857 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
2858
2859 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2860 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
2861 wlan_ipa_uc_fw_op_event_handler,
2862 &ipa_ctx->uc_op_work[i]);
2863 ipa_ctx->uc_op_work[i].msg = NULL;
2864 }
2865
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302866fail_return:
2867 ipa_debug("exit: status=%d", status);
2868 return status;
2869}
2870
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302871/**
2872 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
2873 * @ipa_ctx: pointer to IPA IPA struct
2874 *
2875 * Return: none
2876 */
2877static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
2878{
2879 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2880
2881 while (qdf_list_remove_front(&ipa_ctx->pending_event,
2882 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
2883 qdf_mem_free(pending_event);
2884}
2885
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302886QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
2887{
2888 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302889 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302890
2891 ipa_debug("enter");
2892
2893 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2894 return status;
2895
2896 if (!ipa_ctx->ipa_pipes_down)
2897 wlan_ipa_uc_disable_pipes(ipa_ctx);
2898
2899 if (true == ipa_ctx->uc_loaded) {
2900 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
2901 ipa_ctx->tx_pipe_handle,
2902 ipa_ctx->rx_pipe_handle);
2903 if (status)
2904 ipa_err("Failure to cleanup IPA pipes (status=%d)",
2905 status);
2906 }
2907
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302908 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2909 wlan_ipa_cleanup_pending_event(ipa_ctx);
2910 qdf_mutex_release(&ipa_ctx->ipa_lock);
2911
2912 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2913 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
2914 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
2915 ipa_ctx->uc_op_work[i].msg = NULL;
2916 }
2917
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302918 ipa_debug("exit: ret=%d", status);
2919 return status;
2920}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05302921
Yun Parka29974a2018-04-09 12:05:49 -07002922bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
2923{
2924 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
2925}
2926
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05302927/**
2928 * wlan_ipa_uc_send_evt() - send event to ipa
2929 * @net_dev: Interface net device
2930 * @type: event type
2931 * @mac_addr: pointer to mac address
2932 *
2933 * Send event to IPA driver
2934 *
2935 * Return: QDF_STATUS
2936 */
2937static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
2938 qdf_ipa_wlan_event type,
2939 uint8_t *mac_addr)
2940{
2941 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2942 qdf_ipa_msg_meta_t meta;
2943 qdf_ipa_wlan_msg_t *msg;
2944
2945 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2946 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2947 if (!msg) {
2948 ipa_err("msg allocation failed");
2949 return QDF_STATUS_E_NOMEM;
2950 }
2951
2952 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2953 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2954 IPA_RESOURCE_NAME_MAX);
2955 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2956
2957 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2958 ipa_err("%s: Evt: %d fail",
2959 QDF_IPA_WLAN_MSG_NAME(msg),
2960 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2961 qdf_mem_free(msg);
2962
2963 return QDF_STATUS_E_FAILURE;
2964 }
2965
2966 ipa_ctx->stats.num_send_msg++;
2967
2968 return QDF_STATUS_SUCCESS;
2969}
2970
2971QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
2972 qdf_netdev_t net_dev)
2973{
2974 struct wlan_ipa_iface_context *iface_ctx;
2975 QDF_STATUS status;
2976
2977 ipa_debug("enter");
2978
2979 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
2980 if (iface_ctx)
2981 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
2982 net_dev->dev_addr);
2983 else
2984 return QDF_STATUS_E_INVAL;
2985
2986 ipa_debug("exit :%d", status);
2987
2988 return status;
2989}
2990
2991void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
2992 qdf_netdev_t net_dev)
2993{
2994 struct wlan_ipa_iface_context *iface_ctx;
2995 int i;
2996
2997 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2998 iface_ctx = &ipa_ctx->iface_context[i];
2999 if (iface_ctx->dev == net_dev)
3000 break;
3001 }
3002
3003 if (iface_ctx)
3004 wlan_ipa_cleanup_iface(iface_ctx);
3005}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303006
3007void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3008{
3009 struct wlan_ipa_iface_context *iface;
3010 int i;
3011
3012 ipa_info("enter");
3013
3014 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3015 iface = &ipa_ctx->iface_context[i];
3016 if (iface->dev) {
3017 if (iface->device_mode == QDF_SAP_MODE)
3018 wlan_ipa_uc_send_evt(iface->dev,
3019 QDF_IPA_AP_DISCONNECT,
3020 iface->dev->dev_addr);
3021 else if (iface->device_mode == QDF_STA_MODE)
3022 wlan_ipa_uc_send_evt(iface->dev,
3023 QDF_IPA_STA_DISCONNECT,
3024 iface->dev->dev_addr);
3025 wlan_ipa_cleanup_iface(iface);
3026 }
3027 }
3028}
jitiphil0e3b5922018-07-24 18:43:50 +05303029
3030void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3031{
3032 qdf_ipa_msg_meta_t meta;
3033 qdf_ipa_wlan_msg_t *msg;
3034 int ret;
3035
3036 meta.msg_len = sizeof(*msg);
3037 msg = qdf_mem_malloc(meta.msg_len);
3038 if (!msg) {
3039 ipa_debug("msg allocation failed");
3040 return;
3041 }
3042
3043 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3044 ipa_debug("ipa_send_msg(Evt:%d)",
3045 meta.msg_type);
3046 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3047
3048 if (ret) {
3049 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3050 meta.msg_type, ret);
3051 qdf_mem_free(msg);
3052 }
3053 ipa_ctx->stats.num_send_msg++;
3054}