blob: f9a15a4603412dea93fc513ec8c68f571742ccb1 [file] [log] [blame]
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301/*
2 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/* Include Files */
29#include "wlan_ipa_core.h"
30#include "wlan_ipa_main.h"
31#include <ol_txrx.h>
32#include "cdp_txrx_ipa.h"
33#include "wal_rx_desc.h"
34
35static struct wlan_ipa_priv *gp_ipa;
36
37static struct wlan_ipa_iface_2_client {
38 qdf_ipa_client_type_t cons_client;
39 qdf_ipa_client_type_t prod_client;
40} wlan_ipa_iface_2_client[WLAN_IPA_MAX_IFACE] = {
41 {
42 QDF_IPA_CLIENT_WLAN2_CONS, QDF_IPA_CLIENT_WLAN1_PROD
43 }, {
44 QDF_IPA_CLIENT_WLAN3_CONS, QDF_IPA_CLIENT_WLAN1_PROD
45 }, {
46 QDF_IPA_CLIENT_WLAN4_CONS, QDF_IPA_CLIENT_WLAN1_PROD
47 }
48};
49
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053050/* Local Function Prototypes */
51static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
52 unsigned long data);
53static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
54 unsigned long data);
55
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053056/**
57 * wlan_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
58 * @ipa_cfg: IPA config
59 *
60 * Return: true if STA mode IPA uC offload is enabled, false otherwise
61 */
62static inline bool wlan_ipa_uc_sta_is_enabled(struct wlan_ipa_config *ipa_cfg)
63{
64 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_STA_ENABLE_MASK);
65}
66
67/**
68 * wlan_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
69 * @ipa_cfg: IPA config
70 *
71 * Return: true if pre-filter is enabled, otherwise false
72 */
73static inline
74bool wlan_ipa_is_pre_filter_enabled(struct wlan_ipa_config *ipa_cfg)
75{
76 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg,
77 WLAN_IPA_PRE_FILTER_ENABLE_MASK);
78}
79
80/**
81 * wlan_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
82 * @ipa_cfg: IPA config
83 *
84 * Return: true if IPv6 is enabled, otherwise false
85 */
86static inline bool wlan_ipa_is_ipv6_enabled(struct wlan_ipa_config *ipa_cfg)
87{
88 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_IPV6_ENABLE_MASK);
89}
90
91/**
92 * wlan_ipa_msg_free_fn() - Free an IPA message
93 * @buff: pointer to the IPA message
94 * @len: length of the IPA message
95 * @type: type of IPA message
96 *
97 * Return: None
98 */
99static void wlan_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
100{
101 ipa_debug("msg type:%d, len:%d", type, len);
102 qdf_mem_free(buff);
103}
104
105/**
106 * wlan_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
107 * @priv_ctxt: IPA context
108 *
109 * Will be called by IPA context.
110 * It's atomic context, then should be scheduled to kworker thread
111 *
112 * Return: None
113 */
114static void wlan_ipa_uc_loaded_uc_cb(void *priv_ctxt)
115{
116 struct wlan_ipa_priv *ipa_ctx;
117 struct op_msg_type *msg;
118 struct uc_op_work_struct *uc_op_work;
119
120 if (!priv_ctxt) {
121 ipa_err("Invalid IPA context");
122 return;
123 }
124
125 ipa_ctx = priv_ctxt;
126
127 msg = qdf_mem_malloc(sizeof(*msg));
128 if (!msg) {
129 ipa_err("op_msg allocation fails");
130 return;
131 }
132
133 msg->op_code = WLAN_IPA_UC_OPCODE_UC_READY;
134
135 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
136
137 /* When the same uC OPCODE is already pended, just return */
138 if (uc_op_work->msg)
139 goto done;
140
141 uc_op_work->msg = msg;
142 qdf_sched_work(0, &uc_op_work->work);
143 /* 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{
160 qdf_ipa_msg_meta_t meta;
161 qdf_ipa_wlan_msg_t *ipa_msg;
162 int ret = 0;
163
164 /* WDI enable message to IPA */
165 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
166 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
167 if (!ipa_msg) {
168 ipa_err("msg allocation failed");
169 return QDF_STATUS_E_NOMEM;
170 }
171
172 if (ctrl)
173 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
174 else
175 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
176
177 ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
178 ret = qdf_ipa_send_msg(&meta, ipa_msg, wlan_ipa_msg_free_fn);
179 if (ret) {
180 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
181 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
182 qdf_mem_free(ipa_msg);
183 return QDF_STATUS_E_FAILURE;
184 }
185
186 return QDF_STATUS_SUCCESS;
187}
188
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530189struct wlan_ipa_priv *wlan_ipa_get_obj_context(void)
190{
191 return gp_ipa;
192}
193
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530194#ifdef CONFIG_IPA_WDI_UNIFIED_API
195
196/*
197 * TODO: Get WDI version through FW capabilities
198 */
199#ifdef CONFIG_LITHIUM
200static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
201{
202 ipa_ctx->wdi_version = IPA_WDI_3;
203}
204#elif defined(QCA_WIFI_3_0)
205static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
206{
207 ipa_ctx->wdi_version = IPA_WDI_2;
208}
209#else
210static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
211{
212 ipa_ctx->wdi_version = IPA_WDI_1;
213}
214#endif
215
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530216static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
217 qdf_device_t osdev)
218{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530219 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530220}
221
222static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
223 qdf_device_t osdev)
224{
225 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
226 int i;
227
228 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
229 qdf_mem_copy(&sys_in[i],
230 &ipa_ctx->sys_pipe[i].ipa_sys_params,
231 sizeof(qdf_ipa_sys_connect_params_t));
232
233 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
234 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
235 wlan_ipa_wdi_meter_notifier_cb,
236 ipa_ctx->config->desc_size,
237 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
238 &ipa_ctx->tx_pipe_handle,
239 &ipa_ctx->rx_pipe_handle,
240 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
241 sys_in);
242}
243
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530244#ifdef FEATURE_METERING
245/**
246 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
247 * @ipa_ctx: IPA context
248 * @in: IPA WDI in param
249 *
250 * Return: QDF_STATUS
251 */
252static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
253 qdf_ipa_wdi_init_in_params_t *in)
254{
255 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
256 wlan_ipa_wdi_meter_notifier_cb;
257}
258#else
259static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
260 qdf_ipa_wdi_init_in_params_t *in)
261{
262}
263#endif
264
265/**
266 * wlan_ipa_wdi_init() - IPA WDI init
267 * @ipa_ctx: IPA context
268 *
269 * Return: QDF_STATUS
270 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530271static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
272{
273 qdf_ipa_wdi_init_in_params_t in;
274 qdf_ipa_wdi_init_out_params_t out;
275 int ret;
276
277 ipa_ctx->uc_loaded = false;
278
279 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
280 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530281 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
282 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530283
284 ret = qdf_ipa_wdi_init(&in, &out);
285 if (ret) {
286 ipa_err("ipa_wdi_init failed with ret=%d", ret);
287 return QDF_STATUS_E_FAILURE;
288 }
289
290 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
291 ipa_info("IPA uC READY");
292 ipa_ctx->uc_loaded = true;
293 ipa_ctx->is_smmu_enabled =
294 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
295 ipa_info("is_smmu_enabled=%d", ipa_ctx->is_smmu_enabled);
296 } else {
297 return QDF_STATUS_E_BUSY;
298 }
299
300 return QDF_STATUS_SUCCESS;
301}
302
303static inline int wlan_ipa_wdi_cleanup(void)
304{
305 int ret;
306
307 ret = qdf_ipa_wdi_cleanup();
308 if (ret)
309 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
310 return ret;
311}
312
313static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
314 struct ipa_sys_connect_params *sys,
315 uint32_t *handle)
316{
317 return 0;
318}
319
320static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
321 uint32_t handle)
322{
323 return 0;
324}
325
326#else /* CONFIG_IPA_WDI_UNIFIED_API */
327
328static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
329{
330}
331
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530332static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
333 qdf_device_t osdev)
334{
335 return qdf_mem_smmu_s1_enabled(osdev);
336}
337
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530338static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
339 qdf_device_t osdev)
340{
341 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
342 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
343 wlan_ipa_wdi_meter_notifier_cb,
344 ipa_ctx->config->desc_size,
345 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
346 &ipa_ctx->tx_pipe_handle,
347 &ipa_ctx->rx_pipe_handle);
348}
349
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530350static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
351{
352 struct ipa_wdi_uc_ready_params uc_ready_param;
353
354 ipa_ctx->uc_loaded = false;
355 uc_ready_param.priv = (void *)ipa_ctx;
356 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
357 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
358 ipa_info("UC Ready CB register fail");
359 return QDF_STATUS_E_FAILURE;
360 }
361
362 if (true == uc_ready_param.is_uC_ready) {
363 ipa_info("UC Ready");
364 ipa_ctx->uc_loaded = true;
365 } else {
366 return QDF_STATUS_E_BUSY;
367 }
368
369 return QDF_STATUS_SUCCESS;
370}
371
372static inline int wlan_ipa_wdi_cleanup(void)
373{
374 int ret;
375
376 ret = qdf_ipa_uc_dereg_rdyCB();
377 if (ret)
378 ipa_info("UC Ready CB deregister fail");
379 return ret;
380}
381
382static inline int wlan_ipa_wdi_setup_sys_pipe(
383 struct wlan_ipa_priv *ipa_ctx,
384 struct ipa_sys_connect_params *sys, uint32_t *handle)
385{
386 return qdf_ipa_setup_sys_pipe(sys, handle);
387}
388
389static inline int wlan_ipa_wdi_teardown_sys_pipe(
390 struct wlan_ipa_priv *ipa_ctx,
391 uint32_t handle)
392{
393 return qdf_ipa_teardown_sys_pipe(handle);
394}
395
396#endif /* CONFIG_IPA_WDI_UNIFIED_API */
397
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530398/**
399 * wlan_ipa_send_skb_to_network() - Send skb to kernel
400 * @skb: network buffer
401 * @iface_ctx: IPA interface context
402 *
403 * Called when a network buffer is received which should not be routed
404 * to the IPA module.
405 *
406 * Return: None
407 */
408static void
409wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
410 struct wlan_ipa_iface_context *iface_ctx)
411{
412 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
413
414 if (!iface_ctx->dev) {
415 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Invalid interface");
416 ipa_ctx->ipa_rx_internal_drop_count++;
417 qdf_nbuf_free(skb);
418 return;
419 }
420
421 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
422
423 if (ipa_ctx->send_to_nw)
424 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
425
426 ipa_ctx->ipa_rx_net_send_count++;
427}
428
429/**
430 * wlan_ipa_forward() - handle packet forwarding to wlan tx
431 * @ipa_ctx: pointer to ipa ipa context
432 * @iface_ctx: interface context
433 * @skb: data pointer
434 *
435 * if exception packet has set forward bit, copied new packet should be
436 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
437 * put into pm queue and tx procedure will be differed
438 *
439 * Return: None
440 */
441static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
442 struct wlan_ipa_iface_context *iface_ctx,
443 qdf_nbuf_t skb)
444{
445 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
446
447 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
448
449 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
450 qdf_nbuf_ipa_owned_set(skb);
451
452 /* WLAN subsystem is in suspend, put in queue */
453 if (ipa_ctx->suspended) {
454 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
455 WLAN_IPA_LOG(QDF_TRACE_LEVEL_INFO,
456 "Tx in suspend, put in queue");
457 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
458 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
459 pm_tx_cb->exception = true;
460 pm_tx_cb->iface_context = iface_ctx;
461 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
462 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
463 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
464 ipa_ctx->stats.num_tx_queued++;
465 } else {
466 /* Resume, put packet into WLAN TX */
467 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
468
469 if (ipa_ctx->softap_xmit) {
470 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
471 WLAN_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
472 "packet Tx fail");
473 ipa_ctx->stats.num_tx_fwd_err++;
474 } else {
475 ipa_ctx->stats.num_tx_fwd_ok++;
476 }
477 } else {
478 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
479 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
480 }
481 }
482}
483
484/**
485 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
486 * @ipa_ctx: pointer to IPA IPA struct
487 * @iface_ctx: ipa interface context
488 * @desc: Firmware descriptor
489 * @skb: Data buffer
490 *
491 * Return:
492 * WLAN_IPA_FORWARD_PKT_NONE
493 * WLAN_IPA_FORWARD_PKT_DISCARD
494 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
495 *
496 */
497
498static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
499 struct wlan_ipa_priv *ipa_ctx,
500 struct wlan_ipa_iface_context *iface_ctx,
501 uint8_t desc,
502 qdf_nbuf_t skb)
503{
504 int ret = WLAN_IPA_FORWARD_PKT_NONE;
505 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
506 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
507
508 if ((desc & FW_RX_DESC_FORWARD_M)) {
509 if (!ol_txrx_fwd_desc_thresh_check(
510 (struct ol_txrx_vdev_t *)cdp_get_vdev_from_vdev_id(soc,
511 (struct cdp_pdev *)pdev,
512 iface_ctx->session_id))) {
513 /* Drop the packet*/
514 ipa_ctx->stats.num_tx_fwd_err++;
515 kfree_skb(skb);
516 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
517 return ret;
518 }
519 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
520 "Forward packet to Tx (fw_desc=%d)", desc);
521 ipa_ctx->ipa_tx_forward++;
522
523 if ((desc & FW_RX_DESC_DISCARD_M)) {
524 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
525 ipa_ctx->ipa_rx_internal_drop_count++;
526 ipa_ctx->ipa_rx_discard++;
527 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
528 } else {
529 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
530
531 if (cloned_skb)
532 wlan_ipa_forward(ipa_ctx, iface_ctx,
533 cloned_skb);
534 else
535 WLAN_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
536 "tx skb alloc failed");
537 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
538 }
539 }
540
541 return ret;
542}
543
544/**
545 * wlan_ipa_w2i_cb() - WLAN to IPA callback handler
546 * @priv: pointer to private data registered with IPA (we register a
547 * pointer to the global IPA context)
548 * @evt: the IPA event which triggered the callback
549 * @data: data associated with the event
550 *
551 * Return: None
552 */
553static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
554 unsigned long data)
555{
556 struct wlan_ipa_priv *ipa_ctx = NULL;
557 qdf_nbuf_t skb;
558 uint8_t iface_id;
559 uint8_t session_id;
560 struct wlan_ipa_iface_context *iface_context;
561 uint8_t fw_desc;
562
563 ipa_ctx = (struct wlan_ipa_priv *)priv;
564
565 if (!ipa_ctx)
566 return;
567
568 switch (evt) {
569 case IPA_RECEIVE:
570 skb = (qdf_nbuf_t) data;
571
572 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
573 session_id = (uint8_t)skb->cb[0];
574 iface_id = ipa_ctx->vdev_to_iface[session_id];
575 ipa_debug("IPA_RECEIVE: session_id=%u, iface_id=%u",
576 session_id, iface_id);
577 } else {
578 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
579 }
580 if (iface_id >= WLAN_IPA_MAX_IFACE) {
581 ipa_err("IPA_RECEIVE: Invalid iface_id: %u",
582 iface_id);
583 ipa_ctx->ipa_rx_internal_drop_count++;
584 qdf_nbuf_free(skb);
585 return;
586 }
587
588 iface_context = &ipa_ctx->iface_context[iface_id];
589 if (!iface_context->tl_context) {
590 ipa_err("IPA_RECEIVE: TL context is NULL");
591 ipa_ctx->ipa_rx_internal_drop_count++;
592 qdf_nbuf_free(skb);
593 return;
594 }
595
596 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
597 ipa_ctx->stats.num_rx_excep++;
598 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
599 } else {
600 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
601 }
602
603 iface_context->stats.num_rx_ipa_excep++;
604
605 /* Disable to forward Intra-BSS Rx packets when
606 * ap_isolate=1 in hostapd.conf
607 */
608 if (!ipa_ctx->ap_intrabss_fwd) {
609 /*
610 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
611 * all Rx packets to IPA uC, which need to be forwarded
612 * to other interface.
613 * And, IPA driver will send back to WLAN host driver
614 * through exception pipe with fw_desc field set by FW.
615 * Here we are checking fw_desc field for FORWARD bit
616 * set, and forward to Tx. Then copy to kernel stack
617 * only when DISCARD bit is not set.
618 */
619 fw_desc = (uint8_t)skb->cb[1];
620 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
621 wlan_ipa_intrabss_forward(ipa_ctx, iface_context,
622 fw_desc, skb))
623 break;
624 } else {
625 ipa_debug("Intra-BSS FWD is disabled-skip forward to Tx");
626 }
627
628 wlan_ipa_send_skb_to_network(skb, iface_context);
629 break;
630
631 default:
632 ipa_err("w2i cb wrong event: 0x%x", evt);
633 return;
634 }
635}
636
637/**
638 * wlan_ipa_send_pkt_to_tl() - Send an IPA packet to TL
639 * @iface_context: interface-specific IPA context
640 * @ipa_tx_desc: packet data descriptor
641 *
642 * Return: None
643 */
644static void wlan_ipa_send_pkt_to_tl(
645 struct wlan_ipa_iface_context *iface_context,
646 qdf_ipa_rx_data_t *ipa_tx_desc)
647{
648 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
649 qdf_nbuf_t skb;
650 struct wlan_ipa_tx_desc *tx_desc;
651
652 qdf_spin_lock_bh(&iface_context->interface_lock);
653 /*
654 * During CAC period, data packets shouldn't be sent over the air so
655 * drop all the packets here
656 */
657 if (iface_context->device_mode == QDF_SAP_MODE ||
658 iface_context->device_mode == QDF_P2P_GO_MODE) {
659 if (ipa_ctx->dfs_cac_block_tx) {
660 ipa_free_skb(ipa_tx_desc);
661 qdf_spin_unlock_bh(&iface_context->interface_lock);
662 iface_context->stats.num_tx_cac_drop++;
663 wlan_ipa_wdi_rm_try_release(ipa_ctx);
664 return;
665 }
666 }
667 qdf_spin_unlock_bh(&iface_context->interface_lock);
668
669 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
670
671 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
672
673 /* Store IPA Tx buffer ownership into SKB CB */
674 qdf_nbuf_ipa_owned_set(skb);
675 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
676 qdf_nbuf_mapped_paddr_set(skb,
677 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
678 + WLAN_IPA_WLAN_FRAG_HEADER
679 + WLAN_IPA_WLAN_IPA_HEADER);
680 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
681 WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER;
682 } else
683 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
684
685 qdf_spin_lock_bh(&ipa_ctx->q_lock);
686 /* get free Tx desc and assign ipa_tx_desc pointer */
687 if (qdf_list_remove_front(&ipa_ctx->tx_desc_list,
688 (qdf_list_node_t **)&tx_desc) ==
689 QDF_STATUS_SUCCESS) {
690 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
691 ipa_ctx->stats.num_tx_desc_q_cnt++;
692 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
693 /* Store Tx Desc index into SKB CB */
694 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
695 } else {
696 ipa_ctx->stats.num_tx_desc_error++;
697 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
698 qdf_ipa_free_skb(ipa_tx_desc);
699 wlan_ipa_wdi_rm_try_release(ipa_ctx);
700 return;
701 }
702
703 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
704 (struct cdp_vdev *)iface_context->tl_context,
705 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
706 if (skb) {
707 qdf_nbuf_free(skb);
708 iface_context->stats.num_tx_err++;
709 return;
710 }
711
712 atomic_inc(&ipa_ctx->tx_ref_cnt);
713
714 iface_context->stats.num_tx++;
715}
716
717/**
718 * wlan_ipa_i2w_cb() - IPA to WLAN callback
719 * @priv: pointer to private data registered with IPA (we register a
720 * pointer to the interface-specific IPA context)
721 * @evt: the IPA event which triggered the callback
722 * @data: data associated with the event
723 *
724 * Return: None
725 */
726static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
727 unsigned long data)
728{
729 struct wlan_ipa_priv *ipa_ctx = NULL;
730 qdf_ipa_rx_data_t *ipa_tx_desc;
731 struct wlan_ipa_iface_context *iface_context;
732 qdf_nbuf_t skb;
733 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
734
735 iface_context = (struct wlan_ipa_iface_context *)priv;
736 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
737 ipa_ctx = iface_context->ipa_ctx;
738
739 if (evt != IPA_RECEIVE) {
740 WLAN_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Event is not IPA_RECEIVE");
741 ipa_free_skb(ipa_tx_desc);
742 iface_context->stats.num_tx_drop++;
743 return;
744 }
745
746 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
747
748 /*
749 * If PROD resource is not requested here then there may be cases where
750 * IPA hardware may be clocked down because of not having proper
751 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
752 * workaround to request PROD resource while data is going over CONS
753 * pipe to prevent the IPA hardware clockdown.
754 */
755 wlan_ipa_wdi_rm_request(ipa_ctx);
756
757 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
758 /*
759 * If host is still suspended then queue the packets and these will be
760 * drained later when resume completes. When packet is arrived here and
761 * host is suspended, this means that there is already resume is in
762 * progress.
763 */
764 if (ipa_ctx->suspended) {
765 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
766 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
767 pm_tx_cb->iface_context = iface_context;
768 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
769 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
770 ipa_ctx->stats.num_tx_queued++;
771
772 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
773 return;
774 }
775
776 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
777
778 /*
779 * If we are here means, host is not suspended, wait for the work queue
780 * to finish.
781 */
782 qdf_flush_work(&ipa_ctx->pm_work);
783
784 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
785}
786
787QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
788{
789 /*
790 * Check if IPA is ready for suspend, If we are here means, there is
791 * high chance that suspend would go through but just to avoid any race
792 * condition after suspend started, these checks are conducted before
793 * allowing to suspend.
794 */
795 if (atomic_read(&ipa_ctx->tx_ref_cnt))
796 return QDF_STATUS_E_AGAIN;
797
798 qdf_spin_lock_bh(&ipa_ctx->rm_lock);
799
800 if (ipa_ctx->rm_state != WLAN_IPA_RM_RELEASED) {
801 qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
802 return QDF_STATUS_E_AGAIN;
803 }
804 qdf_spin_unlock_bh(&ipa_ctx->rm_lock);
805
806 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
807 ipa_ctx->suspended = true;
808 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
809
810 return QDF_STATUS_SUCCESS;
811}
812
813QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
814{
815 qdf_sched_work(0, &ipa_ctx->pm_work);
816
817 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
818 ipa_ctx->suspended = false;
819 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
820
821 return QDF_STATUS_SUCCESS;
822}
823
824/**
825 * wlan_ipa_pm_flush() - flush queued packets
826 * @work: pointer to the scheduled work
827 *
828 * Called during PM resume to send packets to TL which were queued
829 * while host was in the process of suspending.
830 *
831 * Return: None
832 */
833static void wlan_ipa_pm_flush(void *data)
834{
835 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
836 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
837 qdf_nbuf_t skb;
838 uint32_t dequeued = 0;
839
840 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
841 WIFI_POWER_EVENT_WAKELOCK_IPA);
842 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
843 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
844 NULL)) {
845 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
846
847 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
848 dequeued++;
849
850 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
851 pm_tx_cb->ipa_tx_desc);
852
853 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
854 }
855 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
856 qdf_wake_lock_release(&ipa_ctx->wake_lock,
857 WIFI_POWER_EVENT_WAKELOCK_IPA);
858
859 ipa_ctx->stats.num_tx_dequeued += dequeued;
860 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
861 ipa_ctx->stats.num_max_pm_queue = dequeued;
862}
863
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +0530864QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
865{
866 int result;
867
868 ipa_debug("enter");
869
870 if (!ipa_ctx->ipa_pipes_down) {
871 /*
872 * IPA WDI Pipes are already activated due to
873 * rm deferred resources grant
874 */
875 ipa_warn("IPA WDI Pipes are already activated");
876 goto end;
877 }
878
879 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
880 ipa_ctx->dp_pdev);
881 if (result) {
882 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
883 return QDF_STATUS_E_FAILURE;
884 }
885
886 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
887 ipa_ctx->ipa_pipes_down = false;
888
889 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
890 ipa_ctx->dp_pdev);
891
892end:
893 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
894
895 return QDF_STATUS_SUCCESS;
896}
897
898QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
899{
900 int result;
901
902 ipa_debug("enter");
903
904 if (ipa_ctx->ipa_pipes_down) {
905 /*
906 * This shouldn't happen :
907 * IPA WDI Pipes are already deactivated
908 */
909 QDF_ASSERT(0);
910 ipa_warn("IPA WDI Pipes are already deactivated");
911 goto end;
912 }
913
914 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
915 ipa_ctx->dp_pdev);
916
917 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
918 ipa_ctx->dp_pdev);
919 if (result) {
920 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
921 return QDF_STATUS_E_FAILURE;
922 }
923
924 ipa_ctx->ipa_pipes_down = true;
925
926end:
927 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
928
929 return QDF_STATUS_SUCCESS;
930}
931
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530932/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +0530933 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
934 * @ipa_ctx: Global IPA IPA context
935 * @sta_add: Should station be added
936 * @sta_id: ID of the station being queried
937 *
938 * Return: true if the station was found
939 */
940static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
941 bool sta_add, uint8_t sta_id,
942 uint8_t *mac_addr)
943{
944 bool sta_found = false;
945 uint8_t idx;
946
947 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
948 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
949 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
950 sta_found = true;
951 break;
952 }
953 }
954 if (sta_add && sta_found) {
955 ipa_err("STA ID %d already exist, cannot add", sta_id);
956 return sta_found;
957 }
958 if (sta_add) {
959 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
960 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
961 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
962 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
963 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
964 mac_addr, mac_addr,
965 QDF_NET_ETH_LEN);
966 return sta_found;
967 }
968 }
969 }
970 if (!sta_add && !sta_found) {
971 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
972 return sta_found;
973 }
974 if (!sta_add) {
975 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
976 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
977 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
978 ipa_ctx->assoc_stas_map[idx].is_reserved =
979 false;
980 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
981 qdf_mem_set(&ipa_ctx->assoc_stas_map[idx].
982 mac_addr, 0, QDF_NET_ETH_LEN);
983 return sta_found;
984 }
985 }
986 }
987
988 return sta_found;
989}
990
991/**
992 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
993 * @ipa_ctx: IPA context
994 * @session_id: Session ID
995 *
996 * Return: None
997 */
998static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
999 uint8_t session_id)
1000{
1001 struct wlan_ipa_iface_context *iface_ctx;
1002 int i;
1003
1004 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1005 iface_ctx = &ipa_ctx->iface_context[i];
1006 if (iface_ctx->session_id == session_id)
1007 break;
1008 }
1009
1010 return i;
1011}
1012
1013/**
1014 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1015 * @iface_context: interface-specific IPA context
1016 *
1017 * Return: None
1018 */
1019static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1020{
1021 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1022
1023 ipa_debug("enter");
1024
1025 if (!iface_context->tl_context)
1026 return;
1027
1028 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1029 iface_context->dev->name,
1030 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1031
1032 qdf_spin_lock_bh(&iface_context->interface_lock);
1033 iface_context->tl_context = NULL;
1034 iface_context->dev = NULL;
1035 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1036 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1037 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1038 qdf_spin_unlock_bh(&iface_context->interface_lock);
1039 iface_context->ifa_address = 0;
1040 if (!iface_context->ipa_ctx->num_iface) {
1041 ipa_err("NUM INTF 0, Invalid");
1042 QDF_ASSERT(0);
1043 }
1044 iface_context->ipa_ctx->num_iface--;
1045 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1046}
1047
1048/**
1049 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1050 * @ipa_ctx: IPA IPA global context
1051 * @net_dev: Interface net device
1052 * @device_mode: Net interface device mode
1053 * @adapter: Interface upon which IPA is being setup
1054 * @sta_id: Station ID of the API instance
1055 * @session_id: Station ID of the API instance
1056 *
1057 * Return: QDF STATUS
1058 */
1059static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1060 qdf_netdev_t net_dev,
1061 uint8_t device_mode, uint8_t sta_id,
1062 uint8_t session_id)
1063{
1064 struct wlan_ipa_iface_context *iface_context = NULL;
1065 void *tl_context = NULL;
1066 int i;
1067 QDF_STATUS status;
1068
1069 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1070 * channel change indication. Since these indications are sent by lower
1071 * layer as SAP updates and IPA doesn't have to do anything for these
1072 * updates so ignoring!
1073 */
1074 if (device_mode == QDF_SAP_MODE) {
1075 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1076 iface_context = &(ipa_ctx->iface_context[i]);
1077 if (iface_context->dev == net_dev)
1078 return QDF_STATUS_SUCCESS;
1079 }
1080 }
1081
1082 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1083 if (ipa_ctx->iface_context[i].tl_context == NULL) {
1084 iface_context = &(ipa_ctx->iface_context[i]);
1085 break;
1086 }
1087 }
1088
1089 if (iface_context == NULL) {
1090 ipa_err("All the IPA interfaces are in use");
1091 status = QDF_STATUS_E_NOMEM;
1092 goto end;
1093 }
1094
1095 iface_context->sta_id = sta_id;
1096 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1097 ipa_ctx->dp_pdev,
1098 sta_id);
1099 if (tl_context == NULL) {
1100 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1101 status = QDF_STATUS_E_INVAL;
1102 goto end;
1103 }
1104
1105 iface_context->tl_context = tl_context;
1106 iface_context->dev = net_dev;
1107 iface_context->device_mode = device_mode;
1108 iface_context->session_id = session_id;
1109
1110 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1111 net_dev->dev_addr,
1112 iface_context->prod_client,
1113 iface_context->cons_client,
1114 session_id,
1115 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1116 if (status != QDF_STATUS_SUCCESS)
1117 goto end;
1118
1119 ipa_ctx->num_iface++;
1120
1121 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1122
1123 return status;
1124
1125end:
1126 if (iface_context)
1127 wlan_ipa_cleanup_iface(iface_context);
1128
1129 return status;
1130}
1131
1132/**
1133 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1134 * @ipa_ctx: IPA context
1135 *
1136 * Return: QDF STATUS
1137 */
1138static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1139{
1140 ipa_debug("enter");
1141
1142 ipa_ctx->activated_fw_pipe = 0;
1143 ipa_ctx->resource_loading = true;
1144
1145 /* If RM feature enabled
1146 * Request PROD Resource first
1147 * PROD resource may return sync or async manners
1148 */
1149 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
1150 if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
1151 /* RM PROD request sync return
1152 * enable pipe immediately
1153 */
1154 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1155 ipa_err("IPA WDI Pipe activation failed");
1156 ipa_ctx->resource_loading = false;
1157 return QDF_STATUS_E_BUSY;
1158 }
1159 } else {
1160 ipa_err("IPA WDI Pipe activation deferred");
1161 }
1162 } else {
1163 /* RM Disabled
1164 * Just enabled all the PIPEs
1165 */
1166 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1167 ipa_err("IPA WDI Pipe activation failed");
1168 ipa_ctx->resource_loading = false;
1169 return QDF_STATUS_E_BUSY;
1170 }
1171 ipa_ctx->resource_loading = false;
1172 }
1173
1174 ipa_debug("exit");
1175
1176 return QDF_STATUS_SUCCESS;
1177}
1178
1179/**
1180 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1181 * @ipa_ctx: IPA context
1182 *
1183 * Return: None
1184 */
1185static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1186{
1187 ipa_debug("enter");
1188
1189 ipa_ctx->resource_unloading = true;
1190 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1191 ipa_info("Disable FW RX PIPE");
1192 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
1193 ipa_info("Disable FW TX PIPE");
1194 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, true);
1195
1196 ipa_debug("exit: IPA WDI Pipes deactivated");
1197}
1198
1199/**
1200 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1201 * @ipa_ctx: global IPA context
1202 * @offload_type: MCC or SCC
1203 * @session_id: Session Id
1204 * @enable: TX offload enable or disable
1205 *
1206 * Return: none
1207 */
1208static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1209 uint32_t offload_type,
1210 uint8_t session_id,
1211 bool enable)
1212{
1213
1214 struct ipa_uc_offload_control_params req = {0};
1215
1216 if (session_id >= WLAN_IPA_MAX_SESSION) {
1217 ipa_err("invalid session id: %d", session_id);
1218 return;
1219 }
1220
1221 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
1222 /*
1223 * This shouldn't happen :
1224 * IPA offload status is already set as desired
1225 */
1226 QDF_ASSERT(0);
1227 ipa_warn("IPA offload status is already set");
1228 ipa_warn("offload_type=%d, vdev_id=%d, enable=%d",
1229 offload_type, session_id, enable);
1230 return;
1231 }
1232
1233 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1234 offload_type, session_id, enable);
1235
1236 req.offload_type = offload_type;
1237 req.vdev_id = session_id;
1238 req.enable = enable;
1239
1240 if (QDF_STATUS_SUCCESS !=
1241 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1242 ipa_err("Fail to enable IPA offload");
1243 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1244 offload_type, session_id, enable);
1245 } else {
1246 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1247 }
1248}
1249
1250/**
1251 * __wlan_ipa_wlan_evt() - IPA event handler
1252 * @net_dev: Interface net device
1253 * @device_mode: Net interface device mode
1254 * @sta_id: station id for the event
1255 * @session_id: session id for the event
1256 * @type: event enum of type ipa_wlan_event
1257 * @mac_address: MAC address associated with the event
1258 *
1259 * This function is meant to be called from within wlan_ipa_ctx.c
1260 *
1261 * Return: QDF STATUS
1262 */
1263static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1264 uint8_t sta_id, uint8_t session_id,
1265 qdf_ipa_wlan_event type,
1266 uint8_t *mac_addr)
1267{
1268 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1269 struct wlan_ipa_iface_context *iface_ctx = NULL;
1270 qdf_ipa_msg_meta_t meta;
1271 qdf_ipa_wlan_msg_t *msg;
1272 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1273 int i;
1274 QDF_STATUS status;
1275
1276 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d",
1277 net_dev->name, type, mac_addr, sta_id);
1278
1279 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1280 return QDF_STATUS_E_INVAL;
1281
1282 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1283 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1284 (device_mode != QDF_SAP_MODE)) {
1285 return QDF_STATUS_SUCCESS;
1286 }
1287
1288 /*
1289 * During IPA UC resource loading/unloading new events can be issued.
1290 */
1291 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1292 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1293 unsigned int pending_event_count;
1294 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1295
1296 ipa_info("Event:%d IPA resource %s inprogress", type,
1297 ipa_ctx->resource_loading ?
1298 "load" : "unload");
1299
1300 /* Wait until completion of the long/unloading */
1301 status = qdf_wait_for_event_completion(
1302 &ipa_ctx->ipa_resource_comp,
1303 msecs_to_jiffies(IPA_RESOURCE_COMP_WAIT_TIME));
1304 if (status != QDF_STATUS_SUCCESS) {
1305 /*
1306 * If timed out, store the events separately and
1307 * handle them later.
1308 */
1309 ipa_info("IPA resource %s timed out",
1310 ipa_ctx->resource_loading ?
1311 "load" : "unload");
1312
1313 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1314
1315 pending_event_count =
1316 qdf_list_size(&ipa_ctx->pending_event);
1317 if (pending_event_count >=
1318 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1319 ipa_info("Reached max pending evt count");
1320 qdf_list_remove_front(
1321 &ipa_ctx->pending_event,
1322 (qdf_list_node_t **)&pending_event);
1323 } else {
1324 pending_event =
1325 (struct wlan_ipa_uc_pending_event *)
1326 qdf_mem_malloc(sizeof(
1327 struct wlan_ipa_uc_pending_event));
1328 }
1329
1330 if (!pending_event) {
1331 ipa_err("Pending event memory alloc fail");
1332 qdf_mutex_release(&ipa_ctx->ipa_lock);
1333 return QDF_STATUS_E_NOMEM;
1334 }
1335
1336 pending_event->net_dev = net_dev;
1337 pending_event->device_mode = device_mode;
1338 pending_event->sta_id = sta_id;
1339 pending_event->session_id = session_id;
1340 pending_event->type = type;
1341 pending_event->is_loading = ipa_ctx->resource_loading;
1342 qdf_mem_copy(pending_event->mac_addr,
1343 mac_addr, QDF_MAC_ADDR_SIZE);
1344 qdf_list_insert_back(&ipa_ctx->pending_event,
1345 &pending_event->node);
1346
1347 qdf_mutex_release(&ipa_ctx->ipa_lock);
1348
1349 return QDF_STATUS_SUCCESS;
1350 }
1351 ipa_info("IPA resource %s completed",
1352 ipa_ctx->resource_loading ?
1353 "load" : "unload");
1354 }
1355
1356 ipa_ctx->stats.event[type]++;
1357
1358 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1359 switch (type) {
1360 case QDF_IPA_STA_CONNECT:
1361 qdf_mutex_acquire(&ipa_ctx->event_lock);
1362
1363 /* STA already connected and without disconnect, connect again
1364 * This is Roaming scenario
1365 */
1366 if (ipa_ctx->sta_connected) {
1367 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1368 if (iface_ctx)
1369 wlan_ipa_cleanup_iface(iface_ctx);
1370 }
1371
1372 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1373 sta_id, session_id);
1374 if (status != QDF_STATUS_SUCCESS) {
1375 qdf_mutex_release(&ipa_ctx->event_lock);
1376 goto end;
1377 }
1378
1379 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1380 (ipa_ctx->sap_num_connected_sta > 0) &&
1381 !ipa_ctx->sta_connected) {
1382 qdf_mutex_release(&ipa_ctx->event_lock);
1383 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1384 SIR_STA_RX_DATA_OFFLOAD, session_id,
1385 true);
1386 qdf_mutex_acquire(&ipa_ctx->event_lock);
1387 }
1388
1389 ipa_ctx->vdev_to_iface[session_id] =
1390 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1391
1392 ipa_ctx->sta_connected = 1;
1393
1394 qdf_mutex_release(&ipa_ctx->event_lock);
1395
1396 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1397 break;
1398
1399 case QDF_IPA_AP_CONNECT:
1400 qdf_mutex_acquire(&ipa_ctx->event_lock);
1401
1402 /* For DFS channel we get two start_bss event (before and after
1403 * CAC). Also when ACS range includes both DFS and non DFS
1404 * channels, we could possibly change channel many times due to
1405 * RADAR detection and chosen channel may not be a DFS channels.
1406 * So dont return error here. Just discard the event.
1407 */
1408 if (wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE)) {
1409 qdf_mutex_release(&ipa_ctx->event_lock);
1410 return 0;
1411 }
1412
1413 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1414 sta_id, session_id);
1415 if (status != QDF_STATUS_SUCCESS) {
1416 qdf_mutex_release(&ipa_ctx->event_lock);
1417 ipa_err("%s: Evt: %d, Interface setup failed",
1418 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1419 goto end;
1420 }
1421
1422 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1423 qdf_mutex_release(&ipa_ctx->event_lock);
1424 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1425 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1426 qdf_mutex_acquire(&ipa_ctx->event_lock);
1427 }
1428
1429 ipa_ctx->vdev_to_iface[session_id] =
1430 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1431 qdf_mutex_release(&ipa_ctx->event_lock);
1432 break;
1433
1434 case QDF_IPA_STA_DISCONNECT:
1435 qdf_mutex_acquire(&ipa_ctx->event_lock);
1436
1437 if (!ipa_ctx->sta_connected) {
1438 qdf_mutex_release(&ipa_ctx->event_lock);
1439 ipa_err("%s: Evt: %d, STA already disconnected",
1440 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1441 return QDF_STATUS_E_INVAL;
1442 }
1443
1444 ipa_ctx->sta_connected = 0;
1445
1446 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1447 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1448 msg_ex->name);
1449 } else {
1450 /* Disable IPA UC TX PIPE when STA disconnected */
1451 if ((ipa_ctx->num_iface == 1) &&
1452 (ipa_ctx->activated_fw_pipe ==
1453 WLAN_IPA_UC_NUM_WDI_PIPE) &&
1454 !ipa_ctx->ipa_pipes_down)
1455 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1456 }
1457
1458 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1459 (ipa_ctx->sap_num_connected_sta > 0)) {
1460 qdf_mutex_release(&ipa_ctx->event_lock);
1461 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1462 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1463 qdf_mutex_acquire(&ipa_ctx->event_lock);
1464 ipa_ctx->vdev_to_iface[session_id] =
1465 WLAN_IPA_MAX_SESSION;
1466 }
1467
1468 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1469 iface_ctx = &ipa_ctx->iface_context[i];
1470
1471 if (iface_ctx->dev == net_dev)
1472 break;
1473 }
1474 if (i < WLAN_IPA_MAX_IFACE)
1475 wlan_ipa_cleanup_iface(iface_ctx);
1476
1477 qdf_mutex_release(&ipa_ctx->event_lock);
1478
1479 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1480 break;
1481
1482 case QDF_IPA_AP_DISCONNECT:
1483 qdf_mutex_acquire(&ipa_ctx->event_lock);
1484
1485 if ((ipa_ctx->num_iface == 1) &&
1486 (ipa_ctx->activated_fw_pipe == WLAN_IPA_UC_NUM_WDI_PIPE) &&
1487 !ipa_ctx->ipa_pipes_down) {
1488 if (cds_is_driver_unloading()) {
1489 /*
1490 * We disable WDI pipes directly here since
1491 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1492 * processed when unloading WLAN driver is in
1493 * progress
1494 */
1495 wlan_ipa_uc_disable_pipes(ipa_ctx);
1496 } else {
1497 /*
1498 * This shouldn't happen :
1499 * No interface left but WDI pipes are still
1500 * active - force close WDI pipes
1501 */
1502 ipa_err("No interface left but WDI pipes are still active");
1503 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1504 }
1505 }
1506
1507 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1508 qdf_mutex_release(&ipa_ctx->event_lock);
1509 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1510 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1511 qdf_mutex_acquire(&ipa_ctx->event_lock);
1512 ipa_ctx->vdev_to_iface[session_id] =
1513 WLAN_IPA_MAX_SESSION;
1514 }
1515
1516 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1517 iface_ctx = &ipa_ctx->iface_context[i];
1518
1519 if (iface_ctx->dev == net_dev)
1520 break;
1521 }
1522 if (i < WLAN_IPA_MAX_IFACE)
1523 wlan_ipa_cleanup_iface(iface_ctx);
1524
1525 qdf_mutex_release(&ipa_ctx->event_lock);
1526 break;
1527
1528 case QDF_IPA_CLIENT_CONNECT_EX:
1529 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1530 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1531 net_dev->name, type);
1532 return QDF_STATUS_SUCCESS;
1533 }
1534
1535 qdf_mutex_acquire(&ipa_ctx->event_lock);
1536 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1537 mac_addr)) {
1538 qdf_mutex_release(&ipa_ctx->event_lock);
1539 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1540 return QDF_STATUS_SUCCESS;
1541 }
1542
1543 /* Enable IPA UC Data PIPEs when first STA connected */
1544 if (ipa_ctx->sap_num_connected_sta == 0 &&
1545 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301546 struct wlan_ipa_iface_context *iface_ctx;
1547 uint8_t sta_session_id;
1548
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301549 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1550 ipa_ctx->sta_connected) {
1551 qdf_mutex_release(&ipa_ctx->event_lock);
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301552 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1553 sta_session_id = iface_ctx->session_id;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301554 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1555 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301556 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301557 qdf_mutex_acquire(&ipa_ctx->event_lock);
1558 }
1559
1560 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1561 if (status != QDF_STATUS_SUCCESS) {
1562 ipa_info("%s: handle 1st con fail",
1563 net_dev->name);
1564
1565 if (wlan_ipa_uc_sta_is_enabled(
1566 ipa_ctx->config) &&
1567 ipa_ctx->sta_connected) {
1568 qdf_mutex_release(&ipa_ctx->event_lock);
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301569 iface_ctx = wlan_ipa_get_iface(ipa_ctx,
1570 QDF_STA_MODE);
1571 sta_session_id = iface_ctx->session_id;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301572 wlan_ipa_uc_offload_enable_disable(
1573 ipa_ctx,
1574 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301575 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301576 } else {
1577 qdf_mutex_release(&ipa_ctx->event_lock);
1578 }
1579
1580 return status;
1581 }
1582 }
1583
1584 ipa_ctx->sap_num_connected_sta++;
1585
1586 qdf_mutex_release(&ipa_ctx->event_lock);
1587
1588 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1589 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1590 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1591 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1592 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1593
1594 if (msg_ex == NULL) {
1595 ipa_err("msg_ex allocation failed");
1596 return QDF_STATUS_E_NOMEM;
1597 }
1598 strlcpy(msg_ex->name, net_dev->name,
1599 IPA_RESOURCE_NAME_MAX);
1600 msg_ex->num_of_attribs = 1;
1601 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1602 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1603 msg_ex->attribs[0].offset =
1604 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1605 } else {
1606 msg_ex->attribs[0].offset =
1607 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1608 }
1609 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1610 IPA_MAC_ADDR_SIZE);
1611
1612 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1613 ipa_info("%s: Evt: %d send ipa msg fail",
1614 net_dev->name, type);
1615 qdf_mem_free(msg_ex);
1616 return QDF_STATUS_E_FAILURE;
1617 }
1618 ipa_ctx->stats.num_send_msg++;
1619
1620 ipa_info("sap_num_connected_sta=%d",
1621 ipa_ctx->sap_num_connected_sta);
1622
1623 return QDF_STATUS_SUCCESS;
1624
1625 case WLAN_CLIENT_DISCONNECT:
1626 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1627 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1628 msg_ex->name);
1629 return QDF_STATUS_SUCCESS;
1630 }
1631
1632 qdf_mutex_acquire(&ipa_ctx->event_lock);
1633 if (!ipa_ctx->sap_num_connected_sta) {
1634 qdf_mutex_release(&ipa_ctx->event_lock);
1635 ipa_err("%s: Evt: %d, Client already disconnected",
1636 msg_ex->name,
1637 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1638
1639 return QDF_STATUS_SUCCESS;
1640 }
1641 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
1642 sta_id, mac_addr)) {
1643 qdf_mutex_release(&ipa_ctx->event_lock);
1644 ipa_err("%s: STA ID %d NOT found, not valid",
1645 msg_ex->name, sta_id);
1646
1647 return QDF_STATUS_SUCCESS;
1648 }
1649 ipa_ctx->sap_num_connected_sta--;
1650
1651 /* Disable IPA UC TX PIPE when last STA disconnected */
1652 if (!ipa_ctx->sap_num_connected_sta &&
1653 ipa_ctx->uc_loaded == true) {
1654 if ((false == ipa_ctx->resource_unloading)
1655 && (WLAN_IPA_UC_NUM_WDI_PIPE ==
1656 ipa_ctx->activated_fw_pipe) &&
1657 !ipa_ctx->ipa_pipes_down) {
1658 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1659 }
1660
1661 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1662 ipa_ctx->sta_connected) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301663 struct wlan_ipa_iface_context *iface_ctx;
1664 uint8_t sta_session_id;
1665
1666 iface_ctx = wlan_ipa_get_iface(ipa_ctx,
1667 QDF_STA_MODE);
1668 sta_session_id = iface_ctx->session_id;
1669
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301670 qdf_mutex_release(&ipa_ctx->event_lock);
1671 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1672 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301673 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301674 } else {
1675 qdf_mutex_release(&ipa_ctx->event_lock);
1676 }
1677 } else {
1678 qdf_mutex_release(&ipa_ctx->event_lock);
1679 }
1680
1681 ipa_info("sap_num_connected_sta=%d",
1682 ipa_ctx->sap_num_connected_sta);
1683 break;
1684
1685 default:
1686 return QDF_STATUS_SUCCESS;
1687 }
1688
1689 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
1690 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1691 if (!msg) {
1692 ipa_err("msg allocation failed");
1693 return QDF_STATUS_E_NOMEM;
1694 }
1695
1696 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1697 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
1698 IPA_RESOURCE_NAME_MAX);
1699 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
1700
1701 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
1702 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1703
1704 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
1705
1706 ipa_err("%s: Evt: %d fail",
1707 QDF_IPA_WLAN_MSG_NAME(msg),
1708 QDF_IPA_MSG_META_MSG_TYPE(&meta));
1709 qdf_mem_free(msg);
1710
1711 return QDF_STATUS_E_FAILURE;
1712 }
1713
1714 ipa_ctx->stats.num_send_msg++;
1715
1716end:
1717 return QDF_STATUS_SUCCESS;
1718}
1719
1720/**
1721 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
1722 * @wlan_ipa_event_type: IPA IPA WLAN event to be converted to an ipa_wlan_event
1723 *
1724 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
1725 */
1726static qdf_ipa_wlan_event
1727wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
1728{
1729 qdf_ipa_wlan_event_t ipa_event;
1730
1731 switch (wlan_ipa_event_type) {
1732 case WLAN_IPA_CLIENT_CONNECT:
1733 ipa_event = QDF_IPA_CLIENT_CONNECT;
1734 break;
1735 case WLAN_IPA_CLIENT_DISCONNECT:
1736 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
1737 break;
1738 case WLAN_IPA_AP_CONNECT:
1739 ipa_event = QDF_IPA_AP_CONNECT;
1740 break;
1741 case WLAN_IPA_AP_DISCONNECT:
1742 ipa_event = QDF_IPA_AP_DISCONNECT;
1743 break;
1744 case WLAN_IPA_STA_CONNECT:
1745 ipa_event = QDF_IPA_STA_CONNECT;
1746 break;
1747 case WLAN_IPA_STA_DISCONNECT:
1748 ipa_event = QDF_IPA_STA_DISCONNECT;
1749 break;
1750 case WLAN_IPA_CLIENT_CONNECT_EX:
1751 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
1752 break;
1753 case WLAN_IPA_WLAN_EVENT_MAX:
1754 default:
1755 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
1756 break;
1757 }
1758
1759 return ipa_event;
1760}
1761
1762/**
1763 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
1764 * @net_dev: Interface net device
1765 * @device_mode: Net interface device mode
1766 * @sta_id: station id for the event
1767 * @session_id: session id for the event
1768 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
1769 * @mac_address: MAC address associated with the event
1770 *
1771 * Return: QDF_STATUS
1772 */
1773QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1774 uint8_t sta_id, uint8_t session_id,
1775 enum wlan_ipa_wlan_event ipa_event_type,
1776 uint8_t *mac_addr)
1777{
1778 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
1779 QDF_STATUS status = QDF_STATUS_SUCCESS;
1780
1781 /* Data path offload only support for STA and SAP mode */
1782 if ((device_mode == QDF_STA_MODE) ||
1783 (device_mode == QDF_SAP_MODE))
1784 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
1785 session_id, type, mac_addr);
1786
1787 return status;
1788}
1789
1790/**
1791 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
1792 * @ipa_ctx: Global IPA IPA context
1793 * @is_loading: Indicate if invoked during loading
1794 *
1795 * Return: None
1796 */
1797static void
1798wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
1799{
1800 unsigned int pending_event_count;
1801 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1802
1803 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
1804 ipa_debug("Pending Event Count %d", pending_event_count);
1805 if (!pending_event_count) {
1806 ipa_debug("No Pending Event");
1807 return;
1808 }
1809
1810 qdf_list_remove_front(&ipa_ctx->pending_event,
1811 (qdf_list_node_t **)&pending_event);
1812 while (pending_event != NULL) {
1813 if (pending_event->is_loading == is_loading) {
1814 __wlan_ipa_wlan_evt(pending_event->net_dev,
1815 pending_event->device_mode,
1816 pending_event->sta_id,
1817 pending_event->session_id,
1818 pending_event->type,
1819 pending_event->mac_addr);
1820 }
1821 qdf_mem_free(pending_event);
1822 pending_event = NULL;
1823 qdf_list_remove_front(&ipa_ctx->pending_event,
1824 (qdf_list_node_t **)&pending_event);
1825 }
1826}
1827
1828/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301829 * wlan_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
1830 * @ipa_ctx: IPA context
1831 *
1832 * Return: QDF_STATUS
1833 */
1834static int wlan_ipa_alloc_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
1835{
1836 int i;
1837 uint32_t max_desc_cnt;
1838 struct wlan_ipa_tx_desc *tmp_desc;
1839
1840 max_desc_cnt = ipa_ctx->config->txbuf_count;
1841
1842 qdf_list_create(&ipa_ctx->tx_desc_list, max_desc_cnt);
1843
1844 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1845 for (i = 0; i < max_desc_cnt; i++) {
1846 tmp_desc = qdf_mem_malloc(sizeof(*tmp_desc));
1847 tmp_desc->id = i;
1848 tmp_desc->ipa_tx_desc_ptr = NULL;
1849 qdf_list_insert_back(&ipa_ctx->tx_desc_list,
1850 &tmp_desc->node);
1851 tmp_desc++;
1852 }
1853
1854 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
1855 ipa_ctx->stats.num_tx_desc_error = 0;
1856
1857 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1858
1859 return QDF_STATUS_SUCCESS;
1860}
1861
1862#ifndef QCA_LL_TX_FLOW_CONTROL_V2
1863/**
1864 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
1865 * @ipa_ctx: Global IPA IPA context
1866 * @desc_fifo_sz: Number of descriptors
1867 *
1868 * Return: 0 on success, negative errno on error
1869 */
1870static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
1871 int32_t desc_fifo_sz)
1872{
1873 int i, ret = 0;
1874 qdf_ipa_sys_connect_params_t *ipa;
1875
1876 /*setup TX pipes */
1877 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1878 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
1879
1880 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
1881 ipa->desc_fifo_sz = desc_fifo_sz;
1882 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301883 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301884
1885 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
1886 ipa->ipa_ep_cfg.hdr.hdr_len =
1887 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
1888 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
1889 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
1890 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
1891 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
1892 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
1893 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
1894 } else {
1895 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
1896 }
1897 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
1898
1899 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
1900 &ipa_ctx->sys_pipe[i].conn_hdl);
1901 if (ret) {
1902 ipa_err("Failed for pipe %d ret: %d", i, ret);
1903 return ret;
1904 }
1905 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
1906 }
1907
1908 return ret;
1909}
1910#else
1911/**
1912 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
1913 * @ipa_ctx: Global IPA IPA context
1914 * @desc_fifo_sz: Number of descriptors
1915 *
1916 * Return: 0 on success, negative errno on error
1917 */
1918static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
1919 int32_t desc_fifo_sz)
1920{
1921 /*
1922 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
1923 * is enabled, where per vdev descriptors are supported in firmware.
1924 */
1925 return 0;
1926}
1927#endif
1928
1929/**
1930 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
1931 * @ipa_ctx: Global IPA IPA context
1932 * @desc_fifo_sz: Number of descriptors
1933 *
1934 * Return: 0 on success, negative errno on error
1935 */
1936static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
1937 int32_t desc_fifo_sz)
1938{
1939 int ret = 0;
1940 qdf_ipa_sys_connect_params_t *ipa;
1941
1942 /*
1943 * Hard code it here, this can be extended if in case
1944 * PROD pipe is also per interface.
1945 * Right now there is no advantage of doing this.
1946 */
1947 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
1948
1949 ipa->client = IPA_CLIENT_WLAN1_PROD;
1950
1951 ipa->desc_fifo_sz = desc_fifo_sz;
1952 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301953 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301954
1955 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
1956 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
1957 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
1958 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
1959
1960 ret = qdf_ipa_setup_sys_pipe(ipa,
1961 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
1962 if (ret) {
1963 ipa_err("Failed for RX pipe: %d", ret);
1964 return ret;
1965 }
1966 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
1967
1968 return ret;
1969}
1970
1971/**
1972 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
1973 * @ipa_ctx: Global IPA IPA context
1974 *
1975 * Return: 0 on success, negative errno on error
1976 */
1977static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
1978{
1979 int i = WLAN_IPA_MAX_IFACE, ret = 0;
1980 uint32_t desc_fifo_sz;
1981
1982 /* The maximum number of descriptors that can be provided to a BAM at
1983 * once is one less than the total number of descriptors that the buffer
1984 * can contain.
1985 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
1986 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
1987 * be provided at once.
1988 * Because of above requirement, one extra descriptor will be added to
1989 * make sure hardware always has one descriptor.
1990 */
1991 desc_fifo_sz = ipa_ctx->config->desc_size
1992 + SPS_DESC_SIZE;
1993
1994 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
1995 if (ret) {
1996 ipa_err("Failed for TX pipe: %d", ret);
1997 goto setup_sys_pipe_fail;
1998 }
1999
2000 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2001 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2002 if (ret) {
2003 ipa_err("Failed for RX pipe: %d", ret);
2004 goto setup_sys_pipe_fail;
2005 }
2006 }
2007
2008 /* Allocate free Tx desc list */
2009 ret = wlan_ipa_alloc_tx_desc_list(ipa_ctx);
2010 if (ret)
2011 goto setup_sys_pipe_fail;
2012
2013 return ret;
2014
2015setup_sys_pipe_fail:
2016
2017 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2018 if (ipa_ctx->sys_pipe[i].conn_hdl_valid)
2019 qdf_ipa_teardown_sys_pipe(
2020 ipa_ctx->sys_pipe[i].conn_hdl);
2021 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2022 sizeof(struct wlan_ipa_sys_pipe));
2023 }
2024
2025 return ret;
2026}
2027
2028/**
2029 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2030 * @ipa_ctx: Global IPA IPA context
2031 *
2032 * Return: None
2033 */
2034static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2035{
2036 int ret = 0, i;
2037 struct wlan_ipa_tx_desc *tmp_desc;
2038 qdf_ipa_rx_data_t *ipa_tx_desc;
2039 qdf_list_node_t *node;
2040
2041 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2042 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2043 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2044 ipa_ctx->sys_pipe[i].conn_hdl);
2045 if (ret)
2046 ipa_err("Failed:%d", ret);
2047
2048 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2049 }
2050 }
2051
2052 while (qdf_list_remove_front(&ipa_ctx->tx_desc_list, &node) ==
2053 QDF_STATUS_SUCCESS) {
2054 tmp_desc = qdf_container_of(node, struct wlan_ipa_tx_desc,
2055 node);
2056 ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
2057 if (ipa_tx_desc)
2058 qdf_ipa_free_skb(ipa_tx_desc);
2059
2060 qdf_mem_free(tmp_desc);
2061 }
2062}
2063
2064/**
2065 * wlan_ipa_setup() - IPA initialization function
2066 * @ipa_ctx: IPA context
2067 * @ipa_cfg: IPA config
2068 *
2069 * Allocate ipa_ctx resources, ipa pipe resource and register
2070 * wlan interface with IPA module.
2071 *
2072 * Return: QDF_STATUS enumeration
2073 */
2074QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2075 struct wlan_ipa_config *ipa_cfg)
2076{
2077 int ret, i;
2078 struct wlan_ipa_iface_context *iface_context = NULL;
2079 QDF_STATUS status;
2080
2081 ipa_debug("enter");
2082
2083 gp_ipa = ipa_ctx;
2084 ipa_ctx->num_iface = 0;
2085 ipa_ctx->config = ipa_cfg;
2086
2087 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2088
2089 /* Create the interface context */
2090 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2091 iface_context = &ipa_ctx->iface_context[i];
2092 iface_context->ipa_ctx = ipa_ctx;
2093 iface_context->cons_client =
2094 wlan_ipa_iface_2_client[i].cons_client;
2095 iface_context->prod_client =
2096 wlan_ipa_iface_2_client[i].prod_client;
2097 iface_context->iface_id = i;
2098 iface_context->dev = NULL;
2099 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2100 iface_context->tl_context = NULL;
2101 qdf_spinlock_create(&iface_context->interface_lock);
2102 }
2103
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302104 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302105 qdf_spinlock_create(&ipa_ctx->pm_lock);
2106 qdf_spinlock_create(&ipa_ctx->q_lock);
2107 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2108 qdf_list_create(&ipa_ctx->pending_event, 1000);
2109 qdf_mutex_create(&ipa_ctx->event_lock);
2110 qdf_mutex_create(&ipa_ctx->ipa_lock);
2111
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302112 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2113 if (status != QDF_STATUS_SUCCESS)
2114 goto fail_setup_rm;
2115
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302116 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2117 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2118 sizeof(struct wlan_ipa_sys_pipe));
2119
2120 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2121 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2122 ipa_ctx->sap_num_connected_sta = 0;
2123 ipa_ctx->ipa_tx_packets_diff = 0;
2124 ipa_ctx->ipa_rx_packets_diff = 0;
2125 ipa_ctx->ipa_p_tx_packets = 0;
2126 ipa_ctx->ipa_p_rx_packets = 0;
2127 ipa_ctx->resource_loading = false;
2128 ipa_ctx->resource_unloading = false;
2129 ipa_ctx->sta_connected = 0;
2130 ipa_ctx->ipa_pipes_down = true;
2131 ipa_ctx->wdi_enabled = false;
2132 /* Setup IPA system pipes */
2133 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2134 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2135 if (ret)
2136 goto fail_create_sys_pipe;
2137 }
2138
2139 status = wlan_ipa_wdi_init(ipa_ctx);
2140 if (status == QDF_STATUS_E_BUSY)
2141 status = wlan_ipa_uc_send_wdi_control_msg(false);
2142 if (status != QDF_STATUS_SUCCESS) {
2143 ipa_err("IPA WDI init failed: ret=%d", ret);
2144 goto fail_create_sys_pipe;
2145 }
2146 } else {
2147 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2148 if (ret)
2149 goto fail_create_sys_pipe;
2150 }
2151
2152 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2153
2154 ipa_debug("exit: success");
2155
2156 return QDF_STATUS_SUCCESS;
2157
2158fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302159 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2160
2161fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302162 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302163 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2164 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2165 iface_context = &ipa_ctx->iface_context[i];
2166 qdf_spinlock_destroy(&iface_context->interface_lock);
2167 }
2168 qdf_mutex_destroy(&ipa_ctx->event_lock);
2169 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2170 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302171 gp_ipa = NULL;
2172 ipa_debug("exit: fail");
2173
2174 return QDF_STATUS_E_FAILURE;
2175}
2176
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302177void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2178{
2179 qdf_nbuf_t skb;
2180 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2181
2182 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2183 return;
2184
2185 qdf_cancel_work(&ipa_ctx->pm_work);
2186
2187 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2188
2189 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2190 != NULL)) {
2191 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2192
2193 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
2194 if (pm_tx_cb->ipa_tx_desc)
2195 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2196
2197 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2198 }
2199 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2200}
2201
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302202QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2203{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302204 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302205 int i;
2206
2207 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2208 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2209
2210 /* Teardown IPA sys_pipe for MCC */
2211 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2212 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2213
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302214 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2215
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302216 wlan_ipa_flush(ipa_ctx);
2217
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302218 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2219 qdf_spinlock_destroy(&ipa_ctx->q_lock);
2220
2221 /* destroy the interface lock */
2222 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2223 iface_context = &ipa_ctx->iface_context[i];
2224 qdf_spinlock_destroy(&iface_context->interface_lock);
2225 }
2226
2227 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2228 wlan_ipa_wdi_cleanup();
2229 qdf_mutex_destroy(&ipa_ctx->event_lock);
2230 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2231 qdf_list_destroy(&ipa_ctx->pending_event);
2232
2233 }
2234
2235 gp_ipa = NULL;
2236
2237 return QDF_STATUS_SUCCESS;
2238}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302239
2240struct wlan_ipa_iface_context
2241*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2242{
2243 struct wlan_ipa_iface_context *iface_ctx = NULL;
2244 int i;
2245
2246 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2247 iface_ctx = &ipa_ctx->iface_context[i];
2248
2249 if (iface_ctx->device_mode == mode)
2250 return iface_ctx;
2251 }
2252
2253 return NULL;
2254}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302255
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302256#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2257QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2258 bool mcc_mode)
2259{
2260 qdf_ipa_msg_meta_t meta;
2261 qdf_ipa_wlan_msg_t *msg;
2262 int ret;
2263
2264 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2265 return QDF_STATUS_SUCCESS;
2266
2267 /* Send SCC/MCC Switching event to IPA */
2268 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2269 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2270 if (msg == NULL) {
2271 ipa_err("msg allocation failed");
2272 return QDF_STATUS_E_NOMEM;
2273 }
2274
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302275 if (mcc_mode)
2276 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
2277 else
2278 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302279 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2280 "ipa_send_msg(Evt:%d)",
2281 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2282
2283 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2284
2285 if (ret) {
2286 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2287 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2288 qdf_mem_free(msg);
2289 return QDF_STATUS_E_FAILURE;
2290 }
2291
2292 return QDF_STATUS_SUCCESS;
2293}
2294#endif
2295
2296/**
2297 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2298 * @ipa_ctx: ipa ipa local context
2299 *
2300 * Will handle IPA UC image loaded indication comes from IPA kernel
2301 *
2302 * Return: None
2303 */
2304static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2305{
2306 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2307 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2308 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2309 QDF_STATUS status;
2310
2311 ipa_info("UC READY");
2312 if (true == ipa_ctx->uc_loaded) {
2313 ipa_info("UC already loaded");
2314 return;
2315 }
2316
2317 ipa_ctx->uc_loaded = true;
2318
2319 /* Connect pipe */
2320 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2321 if (status) {
2322 ipa_err("Failure to setup IPA pipes (status=%d)",
2323 status);
2324 return;
2325 }
2326
2327 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302328
2329 /* If already any STA connected, enable IPA/FW PIPEs */
2330 if (ipa_ctx->sap_num_connected_sta) {
2331 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2332 wlan_ipa_uc_handle_first_con(ipa_ctx);
2333 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302334}
2335
2336/**
2337 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2338 * @op_msg: operation message received from firmware
2339 * @usr_ctxt: user context registered with TL (we register the IPA Global
2340 * context)
2341 *
2342 * Return: None
2343 */
2344static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2345 struct wlan_ipa_priv *ipa_ctx)
2346{
2347 struct op_msg_type *msg = op_msg;
2348 struct ipa_uc_fw_stats *uc_fw_stat;
2349
2350 if (!op_msg) {
2351 ipa_err("INVALID ARG");
2352 return;
2353 }
2354
2355 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2356 ipa_err("INVALID OPCODE %d", msg->op_code);
2357 qdf_mem_free(op_msg);
2358 return;
2359 }
2360
2361 ipa_debug("OPCODE=%d", msg->op_code);
2362
2363 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2364 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2365 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2366 ipa_ctx->activated_fw_pipe++;
2367 if (ipa_ctx->activated_fw_pipe == WLAN_IPA_UC_NUM_WDI_PIPE) {
2368 ipa_ctx->resource_loading = false;
2369 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2370 if (ipa_ctx->wdi_enabled == false) {
2371 ipa_ctx->wdi_enabled = true;
2372 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2373 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2374 ipa_ctx->mcc_mode);
2375 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302376 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302377 if (ipa_ctx->pending_cons_req)
2378 qdf_ipa_rm_notify_completion(
2379 QDF_IPA_RM_RESOURCE_GRANTED,
2380 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2381 ipa_ctx->pending_cons_req = false;
2382 }
2383 qdf_mutex_release(&ipa_ctx->ipa_lock);
2384 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2385 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2386 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2387 ipa_ctx->activated_fw_pipe--;
2388 if (!ipa_ctx->activated_fw_pipe) {
2389 /*
2390 * Async return success from FW
2391 * Disable/suspend all the PIPEs
2392 */
2393 ipa_ctx->resource_unloading = false;
2394 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2395 wlan_ipa_uc_disable_pipes(ipa_ctx);
2396 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
2397 qdf_ipa_rm_release_resource(
2398 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302399 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302400 ipa_ctx->pending_cons_req = false;
2401 }
2402 qdf_mutex_release(&ipa_ctx->ipa_lock);
2403 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2404 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2405 uc_fw_stat = (struct ipa_uc_fw_stats *)
2406 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2407
2408 /* WLAN FW WDI stats */
2409 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2410 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2411 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2412 /* STATs from FW */
2413 uc_fw_stat = (struct ipa_uc_fw_stats *)
2414 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2415 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2416 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2417 uc_fw_stat->tx_pkts_completed,
2418 ipa_ctx->ipa_p_tx_packets);
2419 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2420 (uc_fw_stat->rx_num_ind_drop_no_space +
2421 uc_fw_stat->rx_num_ind_drop_no_buf +
2422 uc_fw_stat->rx_num_pkts_indicated),
2423 ipa_ctx->ipa_p_rx_packets);
2424
2425 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2426 ipa_ctx->ipa_p_rx_packets =
2427 (uc_fw_stat->rx_num_ind_drop_no_space +
2428 uc_fw_stat->rx_num_ind_drop_no_buf +
2429 uc_fw_stat->rx_num_pkts_indicated);
2430 qdf_mutex_release(&ipa_ctx->ipa_lock);
2431 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2432 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2433 wlan_ipa_uc_loaded_handler(ipa_ctx);
2434 qdf_mutex_release(&ipa_ctx->ipa_lock);
2435 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2436 ipa_err("Invalid message: op_code=%d, reason=%d",
2437 msg->op_code, ipa_ctx->stat_req_reason);
2438 }
2439
2440 qdf_mem_free(op_msg);
2441}
2442
2443/**
2444 * wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2445 * @work: uC OP work
2446 *
2447 * Return: None
2448 */
2449static void wlan_ipa_uc_fw_op_event_handler(void *data)
2450{
2451 struct op_msg_type *msg;
2452 struct uc_op_work_struct *uc_op_work =
2453 (struct uc_op_work_struct *)data;
2454 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2455
2456 msg = uc_op_work->msg;
2457 uc_op_work->msg = NULL;
2458 ipa_debug("posted msg %d", msg->op_code);
2459
2460 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2461}
2462
2463/**
2464 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2465 * @op_msg: operation message received from firmware
2466 * @ipa_ctx: Global IPA context
2467 *
2468 * Return: None
2469 */
2470static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2471{
2472 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2473 struct op_msg_type *msg;
2474 struct uc_op_work_struct *uc_op_work;
2475
2476 if (!ipa_ctx)
2477 goto end;
2478
2479 msg = (struct op_msg_type *)op_msg;
2480
2481 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2482 ipa_err("Invalid OP Code (%d)", msg->op_code);
2483 goto end;
2484 }
2485
2486 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2487 if (uc_op_work->msg) {
2488 /* When the same uC OPCODE is already pended, just return */
2489 goto end;
2490 }
2491
2492 uc_op_work->msg = msg;
2493 qdf_sched_work(0, &uc_op_work->work);
2494 return;
2495
2496end:
2497 qdf_mem_free(op_msg);
2498}
2499
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302500QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2501 qdf_device_t osdev)
2502{
2503 uint8_t i;
2504 QDF_STATUS status = QDF_STATUS_SUCCESS;
2505
2506 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2507 return QDF_STATUS_SUCCESS;
2508
2509 ipa_debug("enter");
2510
2511 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
2512 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
2513 ipa_ctx->vdev_offload_enabled[i] = false;
2514 }
2515
2516 /* Set the lowest bandwidth to start with */
2517 status = wlan_ipa_set_perf_level(ipa_ctx, 0, 0);
2518 if (status != QDF_STATUS_SUCCESS) {
2519 ipa_err("Set perf level failed: %d", status);
2520 qdf_ipa_rm_inactivity_timer_destroy(
2521 QDF_IPA_RM_RESOURCE_WLAN_PROD);
2522 goto fail_return;
2523 }
2524
2525 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
2526 ipa_err("IPA UC resource alloc fail");
2527 status = QDF_STATUS_E_FAILURE;
2528 goto fail_return;
2529 }
2530
2531 if (true == ipa_ctx->uc_loaded) {
2532 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
2533 if (status) {
2534 ipa_err("Failure to setup IPA pipes (status=%d)",
2535 status);
2536 status = QDF_STATUS_E_FAILURE;
2537 goto fail_return;
2538 }
2539
2540 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
2541 wlan_ipa_init_metering(ipa_ctx);
2542 }
2543
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302544 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2545 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
2546
2547 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2548 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
2549 wlan_ipa_uc_fw_op_event_handler,
2550 &ipa_ctx->uc_op_work[i]);
2551 ipa_ctx->uc_op_work[i].msg = NULL;
2552 }
2553
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302554fail_return:
2555 ipa_debug("exit: status=%d", status);
2556 return status;
2557}
2558
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302559/**
2560 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
2561 * @ipa_ctx: pointer to IPA IPA struct
2562 *
2563 * Return: none
2564 */
2565static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
2566{
2567 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2568
2569 while (qdf_list_remove_front(&ipa_ctx->pending_event,
2570 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
2571 qdf_mem_free(pending_event);
2572}
2573
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302574QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
2575{
2576 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302577 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302578
2579 ipa_debug("enter");
2580
2581 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2582 return status;
2583
2584 if (!ipa_ctx->ipa_pipes_down)
2585 wlan_ipa_uc_disable_pipes(ipa_ctx);
2586
2587 if (true == ipa_ctx->uc_loaded) {
2588 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
2589 ipa_ctx->tx_pipe_handle,
2590 ipa_ctx->rx_pipe_handle);
2591 if (status)
2592 ipa_err("Failure to cleanup IPA pipes (status=%d)",
2593 status);
2594 }
2595
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302596 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2597 wlan_ipa_cleanup_pending_event(ipa_ctx);
2598 qdf_mutex_release(&ipa_ctx->ipa_lock);
2599
2600 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
2601 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
2602 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
2603 ipa_ctx->uc_op_work[i].msg = NULL;
2604 }
2605
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302606 ipa_debug("exit: ret=%d", status);
2607 return status;
2608}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05302609
2610int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
2611{
2612 ipa_debug("Map: %d Num_buf: %d", map, num_buf);
2613
2614 if (!num_buf) {
2615 ipa_info("No buffers to map/unmap");
2616 return 0;
2617 }
2618
2619 if (map)
2620 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
2621 else
2622 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
2623}