blob: 8ccdf50b30764d4a7f11879903d2759f18cfb5e2 [file] [log] [blame]
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301/*
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05302 * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05303 *
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053019/* Include Files */
20#include "wlan_ipa_core.h"
21#include "wlan_ipa_main.h"
22#include <ol_txrx.h>
23#include "cdp_txrx_ipa.h"
24#include "wal_rx_desc.h"
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +053025#include "qdf_str.h"
Jeff Johnson8feaa632018-12-07 11:56:02 -080026#include "sir_api.h"
27#include "host_diag_core_event.h"
Abhishek Singh682cf6f2019-08-19 11:45:00 +053028#include "wlan_objmgr_vdev_obj.h"
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053029
30static struct wlan_ipa_priv *gp_ipa;
31
32static struct wlan_ipa_iface_2_client {
33 qdf_ipa_client_type_t cons_client;
34 qdf_ipa_client_type_t prod_client;
Chaoli Zhoub11e18a2019-07-08 15:14:20 +080035} wlan_ipa_iface_2_client[WLAN_IPA_CLIENT_MAX_IFACE] = {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053036 {
37 QDF_IPA_CLIENT_WLAN2_CONS, QDF_IPA_CLIENT_WLAN1_PROD
38 }, {
39 QDF_IPA_CLIENT_WLAN3_CONS, QDF_IPA_CLIENT_WLAN1_PROD
40 }, {
41 QDF_IPA_CLIENT_WLAN4_CONS, QDF_IPA_CLIENT_WLAN1_PROD
42 }
43};
44
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053045/* Local Function Prototypes */
46static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
47 unsigned long data);
48static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
49 unsigned long data);
50
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053051/**
52 * wlan_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
53 * @ipa_cfg: IPA config
54 *
55 * Return: true if STA mode IPA uC offload is enabled, false otherwise
56 */
57static inline bool wlan_ipa_uc_sta_is_enabled(struct wlan_ipa_config *ipa_cfg)
58{
59 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_STA_ENABLE_MASK);
60}
61
62/**
63 * wlan_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
64 * @ipa_cfg: IPA config
65 *
66 * Return: true if pre-filter is enabled, otherwise false
67 */
68static inline
69bool wlan_ipa_is_pre_filter_enabled(struct wlan_ipa_config *ipa_cfg)
70{
71 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg,
72 WLAN_IPA_PRE_FILTER_ENABLE_MASK);
73}
74
75/**
76 * wlan_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
77 * @ipa_cfg: IPA config
78 *
79 * Return: true if IPv6 is enabled, otherwise false
80 */
81static inline bool wlan_ipa_is_ipv6_enabled(struct wlan_ipa_config *ipa_cfg)
82{
83 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_IPV6_ENABLE_MASK);
84}
85
86/**
jiad72b69a92019-04-11 17:23:10 +080087 * wlan_ipa_is_sta_only_offload_enabled() - Is IPA STA only offload enabled
88 *
89 * STA only IPA offload is needed on MDM platforms to support
90 * tethering scenarios in STA-SAP configurations when SAP is idle.
91 *
92 * Currently in STA-SAP configurations, IPA pipes are enabled only
93 * when a wifi client is connected to SAP.
94 *
95 * Impact of this API is only limited to when IPA pipes are enabled
96 * and disabled. To take effect, WLAN_IPA_UC_STA_ENABLE_MASK needs to
97 * set to 1.
98 *
99 * Return: true if MDM_PLATFORM is defined, false otherwise
100 */
101#ifdef MDM_PLATFORM
102static inline bool wlan_ipa_is_sta_only_offload_enabled(void)
103{
104 return true;
105}
106#else
107static inline bool wlan_ipa_is_sta_only_offload_enabled(void)
108{
109 return false;
110}
111#endif
112
113/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530114 * wlan_ipa_msg_free_fn() - Free an IPA message
115 * @buff: pointer to the IPA message
116 * @len: length of the IPA message
117 * @type: type of IPA message
118 *
119 * Return: None
120 */
121static void wlan_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
122{
123 ipa_debug("msg type:%d, len:%d", type, len);
124 qdf_mem_free(buff);
125}
126
127/**
128 * wlan_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
129 * @priv_ctxt: IPA context
130 *
131 * Will be called by IPA context.
132 * It's atomic context, then should be scheduled to kworker thread
133 *
134 * Return: None
135 */
136static void wlan_ipa_uc_loaded_uc_cb(void *priv_ctxt)
137{
138 struct wlan_ipa_priv *ipa_ctx;
139 struct op_msg_type *msg;
140 struct uc_op_work_struct *uc_op_work;
141
142 if (!priv_ctxt) {
143 ipa_err("Invalid IPA context");
144 return;
145 }
146
147 ipa_ctx = priv_ctxt;
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530148 ipa_ctx->uc_loaded = true;
149
150 uc_op_work = &ipa_ctx->uc_op_work[WLAN_IPA_UC_OPCODE_UC_READY];
151 if (!list_empty(&uc_op_work->work.work.entry)) {
152 /* uc_op_work is not initialized yet */
153 return;
154 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530155
156 msg = qdf_mem_malloc(sizeof(*msg));
157 if (!msg) {
158 ipa_err("op_msg allocation fails");
159 return;
160 }
161
162 msg->op_code = WLAN_IPA_UC_OPCODE_UC_READY;
163
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530164 /* When the same uC OPCODE is already pended, just return */
165 if (uc_op_work->msg)
166 goto done;
167
168 uc_op_work->msg = msg;
169 qdf_sched_work(0, &uc_op_work->work);
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530170
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530171 /* work handler will free the msg buffer */
172 return;
173
174done:
175 qdf_mem_free(msg);
176}
177
178/**
179 * wlan_ipa_uc_send_wdi_control_msg() - Set WDI control message
180 * @ctrl: WDI control value
181 *
182 * Send WLAN_WDI_ENABLE for ctrl = true and WLAN_WDI_DISABLE otherwise.
183 *
184 * Return: QDF_STATUS
185 */
186static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
187{
jiad629b2172018-05-11 15:34:22 +0800188 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530189 qdf_ipa_msg_meta_t meta;
190 qdf_ipa_wlan_msg_t *ipa_msg;
191 int ret = 0;
192
193 /* WDI enable message to IPA */
194 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
195 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
196 if (!ipa_msg) {
197 ipa_err("msg allocation failed");
198 return QDF_STATUS_E_NOMEM;
199 }
200
jiad629b2172018-05-11 15:34:22 +0800201 if (ctrl) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530202 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
jiad629b2172018-05-11 15:34:22 +0800203 ipa_ctx->stats.event[QDF_WDI_ENABLE]++;
204 } else {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530205 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
jiad629b2172018-05-11 15:34:22 +0800206 ipa_ctx->stats.event[QDF_WDI_DISABLE]++;
207 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530208
209 ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
210 ret = qdf_ipa_send_msg(&meta, ipa_msg, wlan_ipa_msg_free_fn);
211 if (ret) {
212 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
213 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
214 qdf_mem_free(ipa_msg);
215 return QDF_STATUS_E_FAILURE;
216 }
217
218 return QDF_STATUS_SUCCESS;
219}
220
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530221struct wlan_ipa_priv *wlan_ipa_get_obj_context(void)
222{
223 return gp_ipa;
224}
225
Yun Parke74e6092018-04-27 11:36:34 -0700226/**
227 * wlan_ipa_send_pkt_to_tl() - Send an IPA packet to TL
228 * @iface_context: interface-specific IPA context
229 * @ipa_tx_desc: packet data descriptor
230 *
231 * Return: None
232 */
233static void wlan_ipa_send_pkt_to_tl(
234 struct wlan_ipa_iface_context *iface_context,
235 qdf_ipa_rx_data_t *ipa_tx_desc)
236{
237 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
238 qdf_nbuf_t skb;
239 struct wlan_ipa_tx_desc *tx_desc;
240
241 qdf_spin_lock_bh(&iface_context->interface_lock);
242 /*
243 * During CAC period, data packets shouldn't be sent over the air so
244 * drop all the packets here
245 */
246 if (iface_context->device_mode == QDF_SAP_MODE ||
247 iface_context->device_mode == QDF_P2P_GO_MODE) {
248 if (ipa_ctx->dfs_cac_block_tx) {
249 ipa_free_skb(ipa_tx_desc);
250 qdf_spin_unlock_bh(&iface_context->interface_lock);
251 iface_context->stats.num_tx_cac_drop++;
252 wlan_ipa_wdi_rm_try_release(ipa_ctx);
253 return;
254 }
255 }
256 qdf_spin_unlock_bh(&iface_context->interface_lock);
257
258 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
259
hangtian127c9532019-01-12 13:29:07 +0800260 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Yun Parke74e6092018-04-27 11:36:34 -0700261
262 /* Store IPA Tx buffer ownership into SKB CB */
263 qdf_nbuf_ipa_owned_set(skb);
264 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
265 qdf_nbuf_mapped_paddr_set(skb,
jiadaf210c02018-11-20 09:40:34 +0800266 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
267 + WLAN_IPA_WLAN_FRAG_HEADER
268 + WLAN_IPA_WLAN_IPA_HEADER);
Yun Parke74e6092018-04-27 11:36:34 -0700269 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
270 WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER;
jiadaf210c02018-11-20 09:40:34 +0800271 } else
272 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
Yun Parke74e6092018-04-27 11:36:34 -0700273
274 qdf_spin_lock_bh(&ipa_ctx->q_lock);
275 /* get free Tx desc and assign ipa_tx_desc pointer */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +0530276 if (qdf_list_remove_front(&ipa_ctx->tx_desc_free_list,
277 (qdf_list_node_t **)&tx_desc) ==
Yun Parke74e6092018-04-27 11:36:34 -0700278 QDF_STATUS_SUCCESS) {
279 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
280 ipa_ctx->stats.num_tx_desc_q_cnt++;
281 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
282 /* Store Tx Desc index into SKB CB */
283 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
284 } else {
285 ipa_ctx->stats.num_tx_desc_error++;
286 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
287 qdf_ipa_free_skb(ipa_tx_desc);
288 wlan_ipa_wdi_rm_try_release(ipa_ctx);
289 return;
290 }
291
292 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
293 (struct cdp_vdev *)iface_context->tl_context,
294 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
295 if (skb) {
296 qdf_nbuf_free(skb);
297 iface_context->stats.num_tx_err++;
298 return;
299 }
300
301 atomic_inc(&ipa_ctx->tx_ref_cnt);
302
303 iface_context->stats.num_tx++;
304}
305
jiad90b17252019-03-25 15:22:42 +0800306/**
307 * wlan_ipa_forward() - handle packet forwarding to wlan tx
308 * @ipa_ctx: pointer to ipa ipa context
309 * @iface_ctx: interface context
310 * @skb: data pointer
311 *
312 * if exception packet has set forward bit, copied new packet should be
313 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
314 * put into pm queue and tx procedure will be differed
315 *
316 * Return: None
317 */
318static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
319 struct wlan_ipa_iface_context *iface_ctx,
320 qdf_nbuf_t skb)
321{
322 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
323
324 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
325
326 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
327 qdf_nbuf_ipa_owned_set(skb);
328
329 /* WLAN subsystem is in suspend, put in queue */
330 if (ipa_ctx->suspended) {
331 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
332 ipa_info_rl("Tx in suspend, put in queue");
333 qdf_mem_zero(skb->cb, sizeof(skb->cb));
334 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
335 pm_tx_cb->exception = true;
336 pm_tx_cb->iface_context = iface_ctx;
337 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
338 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
339 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
340 ipa_ctx->stats.num_tx_queued++;
341 } else {
342 /* Resume, put packet into WLAN TX */
343 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
344
345 if (ipa_ctx->softap_xmit) {
346 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
347 ipa_err_rl("packet Tx fail");
348 ipa_ctx->stats.num_tx_fwd_err++;
349 } else {
350 ipa_ctx->stats.num_tx_fwd_ok++;
351 }
352 } else {
353 dev_kfree_skb_any(skb);
354 }
355 }
356}
357
358/**
359 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
360 * @ipa_ctx: pointer to IPA IPA struct
361 * @iface_ctx: ipa interface context
362 * @desc: Firmware descriptor
363 * @skb: Data buffer
364 *
365 * Return:
366 * WLAN_IPA_FORWARD_PKT_NONE
367 * WLAN_IPA_FORWARD_PKT_DISCARD
368 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
369 *
370 */
371
372static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
373 struct wlan_ipa_priv *ipa_ctx,
374 struct wlan_ipa_iface_context *iface_ctx,
375 uint8_t desc,
376 qdf_nbuf_t skb)
377{
378 int ret = WLAN_IPA_FORWARD_PKT_NONE;
379 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
380 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
381
382 if ((desc & FW_RX_DESC_FORWARD_M)) {
383 void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
384 iface_ctx->session_id);
Mohit Khannae1b86022019-04-12 10:04:57 -0700385 if (!vdev)
386 goto drop_pkt;
387
jiad90b17252019-03-25 15:22:42 +0800388 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
389 /* Drop the packet*/
390 ipa_ctx->stats.num_tx_fwd_err++;
Mohit Khannae1b86022019-04-12 10:04:57 -0700391 goto drop_pkt;
jiad90b17252019-03-25 15:22:42 +0800392 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700393
jiad90b17252019-03-25 15:22:42 +0800394 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
395 ipa_ctx->ipa_tx_forward++;
396
397 if ((desc & FW_RX_DESC_DISCARD_M)) {
398 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
399 ipa_ctx->ipa_rx_internal_drop_count++;
400 ipa_ctx->ipa_rx_discard++;
401 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
402 } else {
403 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
404
405 if (cloned_skb)
406 wlan_ipa_forward(ipa_ctx, iface_ctx,
407 cloned_skb);
408 else
409 ipa_err_rl("tx skb alloc failed");
410 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
411 }
412 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700413 return ret;
jiad90b17252019-03-25 15:22:42 +0800414
Mohit Khannae1b86022019-04-12 10:04:57 -0700415drop_pkt:
416 dev_kfree_skb_any(skb);
417 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
jiad90b17252019-03-25 15:22:42 +0800418 return ret;
419}
420
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530421#ifdef CONFIG_IPA_WDI_UNIFIED_API
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530422/*
423 * TODO: Get WDI version through FW capabilities
424 */
Mohit Khannacabf5e72018-07-24 13:28:43 -0700425#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530426static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
427{
428 ipa_ctx->wdi_version = IPA_WDI_3;
429}
430#elif defined(QCA_WIFI_3_0)
431static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
432{
433 ipa_ctx->wdi_version = IPA_WDI_2;
434}
435#else
436static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
437{
438 ipa_ctx->wdi_version = IPA_WDI_1;
439}
440#endif
441
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530442static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
443 qdf_device_t osdev)
444{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530445 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530446}
447
448static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
449 qdf_device_t osdev)
450{
451 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
452 int i;
453
454 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
455 qdf_mem_copy(&sys_in[i],
456 &ipa_ctx->sys_pipe[i].ipa_sys_params,
457 sizeof(qdf_ipa_sys_connect_params_t));
458
459 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
460 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
461 wlan_ipa_wdi_meter_notifier_cb,
462 ipa_ctx->config->desc_size,
463 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
464 &ipa_ctx->tx_pipe_handle,
465 &ipa_ctx->rx_pipe_handle,
466 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530467 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530468}
469
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530470#ifdef FEATURE_METERING
471/**
472 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
473 * @ipa_ctx: IPA context
474 * @in: IPA WDI in param
475 *
476 * Return: QDF_STATUS
477 */
478static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
479 qdf_ipa_wdi_init_in_params_t *in)
480{
481 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
482 wlan_ipa_wdi_meter_notifier_cb;
483}
484#else
485static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
486 qdf_ipa_wdi_init_in_params_t *in)
487{
488}
489#endif
490
491/**
492 * wlan_ipa_wdi_init() - IPA WDI init
493 * @ipa_ctx: IPA context
494 *
495 * Return: QDF_STATUS
496 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530497static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
498{
499 qdf_ipa_wdi_init_in_params_t in;
500 qdf_ipa_wdi_init_out_params_t out;
501 int ret;
502
503 ipa_ctx->uc_loaded = false;
504
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530505 qdf_mem_zero(&in, sizeof(in));
506 qdf_mem_zero(&out, sizeof(out));
507
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530508 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
509 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530510 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
511 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530512
513 ret = qdf_ipa_wdi_init(&in, &out);
514 if (ret) {
515 ipa_err("ipa_wdi_init failed with ret=%d", ret);
516 return QDF_STATUS_E_FAILURE;
517 }
518
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530519 ipa_ctx->over_gsi =
520 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
521 ipa_ctx->is_smmu_enabled =
522 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
523 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
524 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
525
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530526 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700527 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530528 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530529 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530530 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530531 return QDF_STATUS_E_BUSY;
532 }
533
534 return QDF_STATUS_SUCCESS;
535}
536
537static inline int wlan_ipa_wdi_cleanup(void)
538{
539 int ret;
540
541 ret = qdf_ipa_wdi_cleanup();
542 if (ret)
543 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
544 return ret;
545}
546
547static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
548 struct ipa_sys_connect_params *sys,
549 uint32_t *handle)
550{
551 return 0;
552}
553
554static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
555 uint32_t handle)
556{
557 return 0;
558}
559
Yun Parke74e6092018-04-27 11:36:34 -0700560/**
561 * wlan_ipa_pm_flush() - flush queued packets
562 * @work: pointer to the scheduled work
563 *
564 * Called during PM resume to send packets to TL which were queued
565 * while host was in the process of suspending.
566 *
567 * Return: None
568 */
569static void wlan_ipa_pm_flush(void *data)
570{
571 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
572 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
573 qdf_nbuf_t skb;
574 uint32_t dequeued = 0;
575
576 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
577 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
578 NULL)) {
579 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
580
581 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
582 dequeued++;
583
jiadab8cea02018-05-24 09:16:14 +0800584 if (pm_tx_cb->exception) {
585 if (ipa_ctx->softap_xmit &&
586 pm_tx_cb->iface_context->dev) {
587 ipa_ctx->softap_xmit(skb,
588 pm_tx_cb->iface_context->dev);
589 ipa_ctx->stats.num_tx_fwd_ok++;
590 } else {
591 dev_kfree_skb_any(skb);
592 }
593 } else {
594 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
595 pm_tx_cb->ipa_tx_desc);
596 }
Yun Parke74e6092018-04-27 11:36:34 -0700597
598 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
599 }
600 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
601
602 ipa_ctx->stats.num_tx_dequeued += dequeued;
603 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
604 ipa_ctx->stats.num_max_pm_queue = dequeued;
605}
606
jiadae9959f2018-05-08 11:19:07 +0800607int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
608{
609 if (!num_buf) {
610 ipa_info("No buffers to map/unmap");
611 return 0;
612 }
613
614 if (map)
615 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
616 else
617 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
618}
619
Jia Ding70deca72019-07-24 18:18:57 +0800620#ifdef MDM_PLATFORM
621/**
622 * is_rx_dest_bridge_dev() - is RX skb bridge device terminated
623 * @iface_ctx: pointer to WLAN IPA interface context
624 * @nbuf: skb buffer
625 *
626 * Check if skb is destined for bridge device, where SAP is a bridge
627 * port of it.
628 *
629 * FIXME: If there's a BH lockless API to check if destination MAC
630 * address is a valid peer, this check can be deleted. Currently
631 * dp_find_peer_by_addr() is used to check if destination MAC
632 * is a valid peer. Since WLAN IPA RX is in process context,
633 * qdf_spin_lock_bh in dp_find_peer_by_addr() turns to spin_lock_bh
634 * and this BH lock hurts netif_rx.
635 *
636 * Return: true/false
637 */
638static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
639 qdf_nbuf_t nbuf)
640{
641 qdf_netdev_t master_ndev;
642 qdf_netdev_t ndev;
643 struct ethhdr *eh;
644 uint8_t da_is_bcmc;
645 bool ret;
646
647 if (iface_ctx->device_mode != QDF_SAP_MODE)
648 return false;
649
650 /*
651 * WDI 3.0 skb->cb[] info from IPA driver
652 * skb->cb[0] = vdev_id
653 * skb->cb[1].bit#1 = da_is_bcmc
654 */
655 da_is_bcmc = ((uint8_t)nbuf->cb[1]) & 0x2;
656 if (da_is_bcmc)
657 return false;
658
659 ndev = iface_ctx->dev;
660 if (!ndev)
661 return false;
662
663 if (!netif_is_bridge_port(ndev))
664 return false;
665
666 rcu_read_lock();
667
668 master_ndev = netdev_master_upper_dev_get_rcu(ndev);
669 if (!master_ndev) {
670 ret = false;
671 goto out;
672 }
673
674 eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
675 if (qdf_mem_cmp(eh->h_dest, master_ndev->dev_addr, QDF_MAC_ADDR_SIZE)) {
676 ret = false;
677 goto out;
678 }
679
680 ret = true;
681
682out:
683 rcu_read_unlock();
684 return ret;
685}
686#else /* !MDM_PLATFORM */
687static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
688 qdf_nbuf_t nbuf)
689{
690 return false;
691}
692#endif /* MDM_PLATFORM */
693
jiad90b17252019-03-25 15:22:42 +0800694static enum wlan_ipa_forward_type
695wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
696 struct wlan_ipa_iface_context *iface_ctx,
697 qdf_nbuf_t nbuf)
698{
699 uint8_t fw_desc = 0;
700 bool fwd_success;
701 int ret;
702
703 /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
704 if (ipa_ctx->wdi_version != IPA_WDI_3) {
705 fw_desc = (uint8_t)nbuf->cb[1];
706 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
707 nbuf);
708 }
709
Jia Ding70deca72019-07-24 18:18:57 +0800710 if (is_rx_dest_bridge_dev(iface_ctx, nbuf)) {
711 fwd_success = 0;
712 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
713 goto exit;
714 }
715
jiad90b17252019-03-25 15:22:42 +0800716 if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
717 nbuf, &fwd_success)) {
718 ipa_ctx->ipa_rx_internal_drop_count++;
719 ipa_ctx->ipa_rx_discard++;
720
721 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
722 } else {
723 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
724 }
725
Jia Ding70deca72019-07-24 18:18:57 +0800726exit:
jiad90b17252019-03-25 15:22:42 +0800727 if (fwd_success)
728 ipa_ctx->stats.num_tx_fwd_ok++;
729 else
730 ipa_ctx->stats.num_tx_fwd_err++;
731
732 return ret;
733}
734
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530735#else /* CONFIG_IPA_WDI_UNIFIED_API */
736
737static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
738{
739}
740
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530741static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
742 qdf_device_t osdev)
743{
744 return qdf_mem_smmu_s1_enabled(osdev);
745}
746
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530747static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
748 qdf_device_t osdev)
749{
750 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
751 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
752 wlan_ipa_wdi_meter_notifier_cb,
753 ipa_ctx->config->desc_size,
754 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
755 &ipa_ctx->tx_pipe_handle,
756 &ipa_ctx->rx_pipe_handle);
757}
758
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530759static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
760{
761 struct ipa_wdi_uc_ready_params uc_ready_param;
762
763 ipa_ctx->uc_loaded = false;
764 uc_ready_param.priv = (void *)ipa_ctx;
765 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
766 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
767 ipa_info("UC Ready CB register fail");
768 return QDF_STATUS_E_FAILURE;
769 }
770
771 if (true == uc_ready_param.is_uC_ready) {
772 ipa_info("UC Ready");
773 ipa_ctx->uc_loaded = true;
774 } else {
775 return QDF_STATUS_E_BUSY;
776 }
777
778 return QDF_STATUS_SUCCESS;
779}
780
781static inline int wlan_ipa_wdi_cleanup(void)
782{
783 int ret;
784
785 ret = qdf_ipa_uc_dereg_rdyCB();
786 if (ret)
787 ipa_info("UC Ready CB deregister fail");
788 return ret;
789}
790
791static inline int wlan_ipa_wdi_setup_sys_pipe(
792 struct wlan_ipa_priv *ipa_ctx,
793 struct ipa_sys_connect_params *sys, uint32_t *handle)
794{
795 return qdf_ipa_setup_sys_pipe(sys, handle);
796}
797
798static inline int wlan_ipa_wdi_teardown_sys_pipe(
799 struct wlan_ipa_priv *ipa_ctx,
800 uint32_t handle)
801{
802 return qdf_ipa_teardown_sys_pipe(handle);
803}
804
Yun Parke74e6092018-04-27 11:36:34 -0700805/**
806 * wlan_ipa_pm_flush() - flush queued packets
807 * @work: pointer to the scheduled work
808 *
809 * Called during PM resume to send packets to TL which were queued
810 * while host was in the process of suspending.
811 *
812 * Return: None
813 */
814static void wlan_ipa_pm_flush(void *data)
815{
816 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
817 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
818 qdf_nbuf_t skb;
819 uint32_t dequeued = 0;
820
821 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
822 WIFI_POWER_EVENT_WAKELOCK_IPA);
823 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
824 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
825 NULL)) {
826 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
827
828 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
829 dequeued++;
830
jiadab8cea02018-05-24 09:16:14 +0800831 if (pm_tx_cb->exception) {
832 if (ipa_ctx->softap_xmit &&
833 pm_tx_cb->iface_context->dev) {
834 ipa_ctx->softap_xmit(skb,
835 pm_tx_cb->iface_context->dev);
836 ipa_ctx->stats.num_tx_fwd_ok++;
837 } else {
838 dev_kfree_skb_any(skb);
839 }
840 } else {
841 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
842 pm_tx_cb->ipa_tx_desc);
843 }
Yun Parke74e6092018-04-27 11:36:34 -0700844
845 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
846 }
847 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
848 qdf_wake_lock_release(&ipa_ctx->wake_lock,
849 WIFI_POWER_EVENT_WAKELOCK_IPA);
850
851 ipa_ctx->stats.num_tx_dequeued += dequeued;
852 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
853 ipa_ctx->stats.num_max_pm_queue = dequeued;
854}
855
jiadae9959f2018-05-08 11:19:07 +0800856int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
857{
858 if (!num_buf) {
859 ipa_info("No buffers to map/unmap");
860 return 0;
861 }
862
863 if (map)
864 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
865 else
866 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
867}
868
jiad90b17252019-03-25 15:22:42 +0800869static enum wlan_ipa_forward_type
870wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
871 struct wlan_ipa_iface_context *iface_ctx,
872 qdf_nbuf_t nbuf)
873{
874 uint8_t fw_desc;
875
876 fw_desc = (uint8_t)nbuf->cb[1];
877
878 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
879}
880
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530881#endif /* CONFIG_IPA_WDI_UNIFIED_API */
882
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530883/**
884 * wlan_ipa_send_skb_to_network() - Send skb to kernel
885 * @skb: network buffer
886 * @iface_ctx: IPA interface context
887 *
888 * Called when a network buffer is received which should not be routed
889 * to the IPA module.
890 *
891 * Return: None
892 */
893static void
894wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
895 struct wlan_ipa_iface_context *iface_ctx)
896{
897 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
898
899 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800900 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530901 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800902 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530903 return;
904 }
905
906 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
907
908 if (ipa_ctx->send_to_nw)
909 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
910
911 ipa_ctx->ipa_rx_net_send_count++;
912}
913
914/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530915 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530916 * @priv: pointer to private data registered with IPA (we register a
917 * pointer to the global IPA context)
918 * @evt: the IPA event which triggered the callback
919 * @data: data associated with the event
920 *
921 * Return: None
922 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530923static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
924 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530925{
926 struct wlan_ipa_priv *ipa_ctx = NULL;
927 qdf_nbuf_t skb;
928 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700929 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530930 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530931
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530932 ipa_ctx = (struct wlan_ipa_priv *)priv;
933 if (!ipa_ctx) {
934 if (evt == IPA_RECEIVE) {
935 skb = (qdf_nbuf_t)data;
936 dev_kfree_skb_any(skb);
937 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530938 return;
939 }
940
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530941 switch (evt) {
942 case IPA_RECEIVE:
943 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530944 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
945 session_id = (uint8_t)skb->cb[0];
946 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530947 } else {
948 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
949 }
950 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700951 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
952 iface_id, session_id, (uint8_t)skb->cb[1],
953 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530954 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800955 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530956 return;
957 }
958
959 iface_context = &ipa_ctx->iface_context[iface_id];
960 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800961 ipa_err_rl("TL context of iface_id %u is NULL",
962 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530963 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800964 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530965 return;
966 }
967
968 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
969 ipa_ctx->stats.num_rx_excep++;
970 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
971 } else {
972 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
973 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530974 iface_context->stats.num_rx_ipa_excep++;
975
976 /* Disable to forward Intra-BSS Rx packets when
977 * ap_isolate=1 in hostapd.conf
978 */
979 if (!ipa_ctx->ap_intrabss_fwd) {
980 /*
981 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
982 * all Rx packets to IPA uC, which need to be forwarded
983 * to other interface.
984 * And, IPA driver will send back to WLAN host driver
985 * through exception pipe with fw_desc field set by FW.
986 * Here we are checking fw_desc field for FORWARD bit
987 * set, and forward to Tx. Then copy to kernel stack
988 * only when DISCARD bit is not set.
989 */
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530990 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
jiad90b17252019-03-25 15:22:42 +0800991 wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
992 skb))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530993 break;
994 } else {
jiadf3ecc752018-07-05 14:36:03 +0800995 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530996 }
997
998 wlan_ipa_send_skb_to_network(skb, iface_context);
999 break;
1000
1001 default:
jiadf3ecc752018-07-05 14:36:03 +08001002 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301003 return;
1004 }
1005}
1006
jiad7bac1ef2019-07-03 11:30:24 +08001007#ifndef MDM_PLATFORM
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301008/**
jitiphilfdcaaba2018-09-03 16:19:52 +05301009 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
1010 * @priv: pointer to private data registered with IPA (we register a
1011 * pointer to the global IPA context)
1012 * @evt: the IPA event which triggered the callback
1013 * @data: data associated with the event
1014 *
1015 * Return: None
1016 */
1017static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1018 unsigned long data)
1019{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001020 struct qdf_op_sync *op_sync;
1021
1022 if (qdf_op_protect(&op_sync)) {
1023 if (evt == IPA_RECEIVE) {
1024 struct wlan_ipa_priv *ipa_ctx = priv;
1025 qdf_nbuf_t skb = (qdf_nbuf_t)data;
1026
1027 ipa_ctx->ipa_rx_internal_drop_count++;
1028 dev_kfree_skb_any(skb);
1029 }
1030
1031 return;
1032 }
1033
jitiphilfdcaaba2018-09-03 16:19:52 +05301034 __wlan_ipa_w2i_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001035
1036 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301037}
jiad7bac1ef2019-07-03 11:30:24 +08001038#else /* MDM_PLATFORM */
1039static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1040 unsigned long data)
1041{
1042 __wlan_ipa_w2i_cb(priv, evt, data);
1043}
1044#endif /* MDM_PLATFORM */
jitiphilfdcaaba2018-09-03 16:19:52 +05301045
1046/**
1047 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301048 * @priv: pointer to private data registered with IPA (we register a
1049 * pointer to the interface-specific IPA context)
1050 * @evt: the IPA event which triggered the callback
1051 * @data: data associated with the event
1052 *
1053 * Return: None
1054 */
jitiphilfdcaaba2018-09-03 16:19:52 +05301055static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1056 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301057{
1058 struct wlan_ipa_priv *ipa_ctx = NULL;
1059 qdf_ipa_rx_data_t *ipa_tx_desc;
1060 struct wlan_ipa_iface_context *iface_context;
1061 qdf_nbuf_t skb;
1062 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
1063
1064 iface_context = (struct wlan_ipa_iface_context *)priv;
1065 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1066 ipa_ctx = iface_context->ipa_ctx;
1067
1068 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +08001069 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301070 ipa_free_skb(ipa_tx_desc);
1071 iface_context->stats.num_tx_drop++;
1072 return;
1073 }
1074
1075 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
1076
1077 /*
1078 * If PROD resource is not requested here then there may be cases where
1079 * IPA hardware may be clocked down because of not having proper
1080 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
1081 * workaround to request PROD resource while data is going over CONS
1082 * pipe to prevent the IPA hardware clockdown.
1083 */
1084 wlan_ipa_wdi_rm_request(ipa_ctx);
1085
1086 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1087 /*
1088 * If host is still suspended then queue the packets and these will be
1089 * drained later when resume completes. When packet is arrived here and
1090 * host is suspended, this means that there is already resume is in
1091 * progress.
1092 */
1093 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +08001094 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301095 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
1096 pm_tx_cb->iface_context = iface_context;
1097 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
1098 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
1099 ipa_ctx->stats.num_tx_queued++;
1100
1101 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1102 return;
1103 }
1104
1105 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1106
1107 /*
1108 * If we are here means, host is not suspended, wait for the work queue
1109 * to finish.
1110 */
1111 qdf_flush_work(&ipa_ctx->pm_work);
1112
1113 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
1114}
1115
jitiphilfdcaaba2018-09-03 16:19:52 +05301116/**
1117 * wlan_ipa_i2w_cb() - IPA to WLAN callback
1118 * @priv: pointer to private data registered with IPA (we register a
1119 * pointer to the interface-specific IPA context)
1120 * @evt: the IPA event which triggered the callback
1121 * @data: data associated with the event
1122 *
1123 * Return: None
1124 */
1125static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1126 unsigned long data)
1127{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001128 struct qdf_op_sync *op_sync;
1129
1130 if (qdf_op_protect(&op_sync)) {
1131 qdf_ipa_rx_data_t *ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1132 struct wlan_ipa_iface_context *iface_context = priv;
1133
1134 ipa_free_skb(ipa_tx_desc);
1135 iface_context->stats.num_tx_drop++;
1136
1137 return;
1138 }
1139
jitiphilfdcaaba2018-09-03 16:19:52 +05301140 __wlan_ipa_i2w_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001141
1142 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301143}
1144
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301145QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
1146{
1147 /*
1148 * Check if IPA is ready for suspend, If we are here means, there is
1149 * high chance that suspend would go through but just to avoid any race
1150 * condition after suspend started, these checks are conducted before
1151 * allowing to suspend.
1152 */
1153 if (atomic_read(&ipa_ctx->tx_ref_cnt))
1154 return QDF_STATUS_E_AGAIN;
1155
Yun Parke74e6092018-04-27 11:36:34 -07001156 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301157 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301158
1159 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1160 ipa_ctx->suspended = true;
1161 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1162
1163 return QDF_STATUS_SUCCESS;
1164}
1165
1166QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
1167{
1168 qdf_sched_work(0, &ipa_ctx->pm_work);
1169
1170 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1171 ipa_ctx->suspended = false;
1172 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1173
1174 return QDF_STATUS_SUCCESS;
1175}
1176
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301177QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1178{
1179 int result;
1180
1181 ipa_debug("enter");
1182
1183 if (!ipa_ctx->ipa_pipes_down) {
1184 /*
1185 * IPA WDI Pipes are already activated due to
1186 * rm deferred resources grant
1187 */
1188 ipa_warn("IPA WDI Pipes are already activated");
1189 goto end;
1190 }
1191
1192 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1193 ipa_ctx->dp_pdev);
1194 if (result) {
1195 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1196 return QDF_STATUS_E_FAILURE;
1197 }
1198
1199 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1200 ipa_ctx->ipa_pipes_down = false;
1201
1202 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1203 ipa_ctx->dp_pdev);
1204
1205end:
1206 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1207
1208 return QDF_STATUS_SUCCESS;
1209}
1210
1211QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1212{
1213 int result;
1214
1215 ipa_debug("enter");
1216
1217 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301218 ipa_warn("IPA WDI Pipes are already deactivated");
1219 goto end;
1220 }
1221
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301222 qdf_spin_lock_bh(&ipa_ctx->pipes_down_lock);
1223 if (ipa_ctx->pipes_down_in_progress || ipa_ctx->ipa_pipes_down) {
1224 ipa_warn("IPA WDI Pipes down already in progress");
1225 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1226 return QDF_STATUS_E_ALREADY;
1227 }
1228 ipa_ctx->pipes_down_in_progress = true;
1229 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1230
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301231 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1232 ipa_ctx->dp_pdev);
1233
1234 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1235 ipa_ctx->dp_pdev);
1236 if (result) {
1237 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301238 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301239 return QDF_STATUS_E_FAILURE;
1240 }
1241
1242 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301243 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301244
1245end:
1246 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1247
1248 return QDF_STATUS_SUCCESS;
1249}
1250
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301251/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301252 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1253 * @ipa_ctx: Global IPA IPA context
1254 * @sta_add: Should station be added
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301255 * @mac_addr: mac address of station being queried
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301256 *
1257 * Return: true if the station was found
1258 */
1259static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301260 bool sta_add,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301261 uint8_t *mac_addr)
1262{
1263 bool sta_found = false;
1264 uint8_t idx;
1265
1266 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1267 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301268 (qdf_is_macaddr_equal(
1269 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1270 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301271 sta_found = true;
1272 break;
1273 }
1274 }
1275 if (sta_add && sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301276 ipa_err("STA already exist, cannot add: " QDF_MAC_ADDR_STR,
1277 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301278 return sta_found;
1279 }
1280 if (sta_add) {
1281 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1282 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1283 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301284 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1285 mac_addr, mac_addr,
1286 QDF_NET_ETH_LEN);
1287 return sta_found;
1288 }
1289 }
1290 }
1291 if (!sta_add && !sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301292 ipa_err("STA does not exist, cannot delete: " QDF_MAC_ADDR_STR,
1293 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301294 return sta_found;
1295 }
1296 if (!sta_add) {
1297 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1298 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301299 (qdf_is_macaddr_equal(
1300 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1301 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301302 ipa_ctx->assoc_stas_map[idx].is_reserved =
1303 false;
hangtian127c9532019-01-12 13:29:07 +08001304 qdf_mem_zero(
1305 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1306 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301307 return sta_found;
1308 }
1309 }
1310 }
1311
1312 return sta_found;
1313}
1314
1315/**
1316 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1317 * @ipa_ctx: IPA context
1318 * @session_id: Session ID
1319 *
1320 * Return: None
1321 */
1322static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1323 uint8_t session_id)
1324{
1325 struct wlan_ipa_iface_context *iface_ctx;
1326 int i;
1327
1328 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1329 iface_ctx = &ipa_ctx->iface_context[i];
1330 if (iface_ctx->session_id == session_id)
1331 break;
1332 }
1333
1334 return i;
1335}
1336
1337/**
1338 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1339 * @iface_context: interface-specific IPA context
1340 *
1341 * Return: None
1342 */
1343static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1344{
1345 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1346
1347 ipa_debug("enter");
1348
1349 if (!iface_context->tl_context)
1350 return;
1351
1352 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1353 iface_context->dev->name,
1354 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1355
1356 qdf_spin_lock_bh(&iface_context->interface_lock);
1357 iface_context->tl_context = NULL;
1358 iface_context->dev = NULL;
1359 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1360 iface_context->session_id = WLAN_IPA_MAX_SESSION;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301361 qdf_spin_unlock_bh(&iface_context->interface_lock);
1362 iface_context->ifa_address = 0;
1363 if (!iface_context->ipa_ctx->num_iface) {
1364 ipa_err("NUM INTF 0, Invalid");
1365 QDF_ASSERT(0);
1366 }
1367 iface_context->ipa_ctx->num_iface--;
1368 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1369}
1370
1371/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301372 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1373 * @skb: packet buffer which was transmitted
1374 *
1375 * Return: None
1376 */
1377static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1378{
1379 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1380 qdf_ipa_rx_data_t *ipa_tx_desc;
1381 struct wlan_ipa_tx_desc *tx_desc;
1382 uint16_t id;
1383
1384 if (!qdf_nbuf_ipa_owned_get(skb)) {
1385 dev_kfree_skb_any(skb);
1386 return;
1387 }
1388
1389 /* Get Tx desc pointer from SKB CB */
1390 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1391 tx_desc = &ipa_ctx->tx_desc_pool[id];
1392 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1393
1394 /* Return Tx Desc to IPA */
1395 qdf_ipa_free_skb(ipa_tx_desc);
1396
1397 /* Return to free tx desc list */
1398 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1399 tx_desc->ipa_tx_desc_ptr = NULL;
1400 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1401 ipa_ctx->stats.num_tx_desc_q_cnt--;
1402 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1403
1404 ipa_ctx->stats.num_tx_comp_cnt++;
1405
1406 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1407
1408 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1409}
1410
1411/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301412 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1413 * @ipa_ctx: IPA IPA global context
1414 * @net_dev: Interface net device
1415 * @device_mode: Net interface device mode
1416 * @adapter: Interface upon which IPA is being setup
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301417 * @session_id: Station ID of the API instance
1418 *
1419 * Return: QDF STATUS
1420 */
1421static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1422 qdf_netdev_t net_dev,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301423 uint8_t device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301424 uint8_t session_id)
1425{
1426 struct wlan_ipa_iface_context *iface_context = NULL;
1427 void *tl_context = NULL;
1428 int i;
1429 QDF_STATUS status;
1430
1431 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1432 * channel change indication. Since these indications are sent by lower
1433 * layer as SAP updates and IPA doesn't have to do anything for these
1434 * updates so ignoring!
1435 */
1436 if (device_mode == QDF_SAP_MODE) {
1437 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1438 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001439 if (iface_context->dev == net_dev) {
1440 ipa_debug("found iface %u device_mode %u",
1441 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301442 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001443 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301444 }
1445 }
1446
Yun Park21ec4902018-04-24 12:11:01 -07001447 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1448 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1449 status = QDF_STATUS_E_NOMEM;
1450 QDF_ASSERT(0);
1451 goto end;
1452 }
1453
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301454 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001455 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301456 iface_context = &(ipa_ctx->iface_context[i]);
1457 break;
1458 }
1459 }
1460
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001461 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301462 ipa_err("All the IPA interfaces are in use");
1463 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001464 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301465 goto end;
1466 }
1467
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301468 tl_context = (void *)cdp_get_vdev_from_vdev_id(ipa_ctx->dp_soc,
1469 ipa_ctx->dp_pdev,
1470 session_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001471 if (!tl_context) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301472 ipa_err("Not able to get TL context session_id: %d",
1473 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301474 status = QDF_STATUS_E_INVAL;
1475 goto end;
1476 }
1477
1478 iface_context->tl_context = tl_context;
1479 iface_context->dev = net_dev;
1480 iface_context->device_mode = device_mode;
1481 iface_context->session_id = session_id;
1482
1483 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1484 net_dev->dev_addr,
1485 iface_context->prod_client,
1486 iface_context->cons_client,
1487 session_id,
1488 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1489 if (status != QDF_STATUS_SUCCESS)
1490 goto end;
1491
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301492 /* Register IPA Tx desc free callback */
1493 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1494
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301495 ipa_ctx->num_iface++;
1496
1497 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1498
1499 return status;
1500
1501end:
1502 if (iface_context)
1503 wlan_ipa_cleanup_iface(iface_context);
1504
1505 return status;
1506}
1507
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301508#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1509/**
1510 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1511 * @ipa_ctx: IPA context
1512 *
1513 * Return: QDF STATUS
1514 */
1515static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1516{
1517 ipa_debug("enter");
1518
1519 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1520 ipa_err("IPA WDI Pipe activation failed");
1521 return QDF_STATUS_E_BUSY;
1522 }
1523
1524 ipa_debug("exit");
1525
1526 return QDF_STATUS_SUCCESS;
1527}
1528
1529/**
1530 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1531 * @ipa_ctx: IPA context
1532 *
1533 * Return: None
1534 */
1535static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1536{
1537 ipa_debug("enter");
1538
1539 wlan_ipa_uc_disable_pipes(ipa_ctx);
1540
1541 ipa_debug("exit: IPA WDI Pipes deactivated");
1542}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301543
1544bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1545{
1546 return !ipa_ctx->ipa_pipes_down;
1547}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301548#else
1549
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301550/**
1551 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1552 * @ipa_ctx: IPA context
1553 *
1554 * Return: QDF STATUS
1555 */
1556static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1557{
1558 ipa_debug("enter");
1559
1560 ipa_ctx->activated_fw_pipe = 0;
1561 ipa_ctx->resource_loading = true;
1562
1563 /* If RM feature enabled
1564 * Request PROD Resource first
1565 * PROD resource may return sync or async manners
1566 */
1567 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001568 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1569 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301570 /* RM PROD request sync return
1571 * enable pipe immediately
1572 */
1573 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1574 ipa_err("IPA WDI Pipe activation failed");
1575 ipa_ctx->resource_loading = false;
1576 return QDF_STATUS_E_BUSY;
1577 }
1578 } else {
1579 ipa_err("IPA WDI Pipe activation deferred");
1580 }
1581 } else {
1582 /* RM Disabled
1583 * Just enabled all the PIPEs
1584 */
1585 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1586 ipa_err("IPA WDI Pipe activation failed");
1587 ipa_ctx->resource_loading = false;
1588 return QDF_STATUS_E_BUSY;
1589 }
1590 ipa_ctx->resource_loading = false;
1591 }
1592
1593 ipa_debug("exit");
1594
1595 return QDF_STATUS_SUCCESS;
1596}
1597
1598/**
1599 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1600 * @ipa_ctx: IPA context
1601 *
1602 * Return: None
1603 */
1604static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1605{
1606 ipa_debug("enter");
1607
1608 ipa_ctx->resource_unloading = true;
1609 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1610 ipa_info("Disable FW RX PIPE");
1611 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301612
1613 ipa_debug("exit: IPA WDI Pipes deactivated");
1614}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301615
1616bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1617{
1618 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1619}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301620#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301621
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301622static inline
1623bool wlan_sap_no_client_connected(struct wlan_ipa_priv *ipa_ctx)
1624{
1625 return !(ipa_ctx->sap_num_connected_sta);
1626}
1627
1628static inline
1629bool wlan_sta_is_connected(struct wlan_ipa_priv *ipa_ctx)
1630{
1631 return ipa_ctx->sta_connected;
1632}
1633
1634static inline
1635bool wlan_ipa_uc_is_loaded(struct wlan_ipa_priv *ipa_ctx)
1636{
1637 return ipa_ctx->uc_loaded;
1638}
1639
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301640/**
1641 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1642 * @ipa_ctx: global IPA context
1643 * @offload_type: MCC or SCC
1644 * @session_id: Session Id
1645 * @enable: TX offload enable or disable
1646 *
1647 * Return: none
1648 */
1649static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1650 uint32_t offload_type,
1651 uint8_t session_id,
1652 bool enable)
1653{
1654
1655 struct ipa_uc_offload_control_params req = {0};
1656
1657 if (session_id >= WLAN_IPA_MAX_SESSION) {
1658 ipa_err("invalid session id: %d", session_id);
1659 return;
1660 }
1661
1662 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301663 ipa_info("IPA offload status is already set");
1664 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301665 offload_type, session_id, enable);
1666 return;
1667 }
1668
1669 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1670 offload_type, session_id, enable);
1671
1672 req.offload_type = offload_type;
1673 req.vdev_id = session_id;
1674 req.enable = enable;
1675
1676 if (QDF_STATUS_SUCCESS !=
1677 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1678 ipa_err("Fail to enable IPA offload");
1679 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1680 offload_type, session_id, enable);
1681 } else {
1682 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1683 }
1684}
1685
1686/**
1687 * __wlan_ipa_wlan_evt() - IPA event handler
1688 * @net_dev: Interface net device
1689 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301690 * @session_id: session id for the event
1691 * @type: event enum of type ipa_wlan_event
1692 * @mac_address: MAC address associated with the event
1693 *
1694 * This function is meant to be called from within wlan_ipa_ctx.c
1695 *
1696 * Return: QDF STATUS
1697 */
1698static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301699 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301700 qdf_ipa_wlan_event type,
1701 uint8_t *mac_addr)
1702{
1703 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1704 struct wlan_ipa_iface_context *iface_ctx = NULL;
1705 qdf_ipa_msg_meta_t meta;
1706 qdf_ipa_wlan_msg_t *msg;
1707 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1708 int i;
1709 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001710 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301711 struct wlan_objmgr_pdev *pdev;
1712 struct wlan_objmgr_psoc *psoc;
1713 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301714
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301715 ipa_debug("%s: EVT: %d, MAC: %pM, session_id: %u",
1716 net_dev->name, type, mac_addr, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301717
1718 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1719 return QDF_STATUS_E_INVAL;
1720
1721 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1722 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1723 (device_mode != QDF_SAP_MODE)) {
1724 return QDF_STATUS_SUCCESS;
1725 }
1726
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301727 pdev = ipa_ctx->pdev;
1728 psoc = wlan_pdev_get_psoc(pdev);
1729 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1730 WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301731 QDF_BUG(session_id < WLAN_IPA_MAX_SESSION);
1732
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301733 if (vdev)
1734 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301735 else
1736 ipa_err("vdev is NULL, session_id: %u", session_id);
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301737
Ryan Hsub5783cf2018-05-14 12:13:15 -07001738 if (ipa_ctx->sta_connected) {
1739 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1740 if (iface_ctx)
1741 sta_session_id = iface_ctx->session_id;
1742 else
1743 ipa_err("sta iface_ctx is NULL");
1744 }
1745
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301746 /*
1747 * During IPA UC resource loading/unloading new events can be issued.
1748 */
1749 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1750 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1751 unsigned int pending_event_count;
1752 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1753
1754 ipa_info("Event:%d IPA resource %s inprogress", type,
1755 ipa_ctx->resource_loading ?
1756 "load" : "unload");
1757
1758 /* Wait until completion of the long/unloading */
1759 status = qdf_wait_for_event_completion(
1760 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001761 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301762 if (status != QDF_STATUS_SUCCESS) {
1763 /*
1764 * If timed out, store the events separately and
1765 * handle them later.
1766 */
1767 ipa_info("IPA resource %s timed out",
1768 ipa_ctx->resource_loading ?
1769 "load" : "unload");
1770
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301771 if (type == QDF_IPA_AP_DISCONNECT) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301772 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1773 SIR_AP_RX_DATA_OFFLOAD,
1774 session_id, false);
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301775 } else if (type == QDF_IPA_CLIENT_CONNECT_EX &&
1776 wlan_sap_no_client_connected(ipa_ctx)) {
1777 if (wlan_sta_is_connected(ipa_ctx) &&
1778 wlan_ipa_uc_is_loaded(ipa_ctx) &&
1779 wlan_ipa_uc_sta_is_enabled(ipa_ctx->
1780 config) &&
1781 !wlan_ipa_is_sta_only_offload_enabled()) {
1782 wlan_ipa_uc_offload_enable_disable(
1783 ipa_ctx,
1784 SIR_STA_RX_DATA_OFFLOAD,
1785 sta_session_id, true);
1786 }
1787 }
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301788
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301789 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1790
1791 pending_event_count =
1792 qdf_list_size(&ipa_ctx->pending_event);
1793 if (pending_event_count >=
1794 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1795 ipa_info("Reached max pending evt count");
1796 qdf_list_remove_front(
1797 &ipa_ctx->pending_event,
1798 (qdf_list_node_t **)&pending_event);
1799 } else {
1800 pending_event =
1801 (struct wlan_ipa_uc_pending_event *)
1802 qdf_mem_malloc(sizeof(
1803 struct wlan_ipa_uc_pending_event));
1804 }
1805
1806 if (!pending_event) {
1807 ipa_err("Pending event memory alloc fail");
1808 qdf_mutex_release(&ipa_ctx->ipa_lock);
1809 return QDF_STATUS_E_NOMEM;
1810 }
1811
1812 pending_event->net_dev = net_dev;
1813 pending_event->device_mode = device_mode;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301814 pending_event->session_id = session_id;
1815 pending_event->type = type;
1816 pending_event->is_loading = ipa_ctx->resource_loading;
1817 qdf_mem_copy(pending_event->mac_addr,
1818 mac_addr, QDF_MAC_ADDR_SIZE);
1819 qdf_list_insert_back(&ipa_ctx->pending_event,
1820 &pending_event->node);
1821
1822 qdf_mutex_release(&ipa_ctx->ipa_lock);
1823
Yun Park21ec4902018-04-24 12:11:01 -07001824 /* Cleanup interface */
1825 if (type == QDF_IPA_STA_DISCONNECT ||
1826 type == QDF_IPA_AP_DISCONNECT) {
1827 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1828 iface_ctx = &ipa_ctx->iface_context[i];
1829
1830 if (iface_ctx->dev == net_dev)
1831 break;
1832 }
1833 if (iface_ctx)
1834 wlan_ipa_cleanup_iface(iface_ctx);
1835 }
1836
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301837 return QDF_STATUS_SUCCESS;
1838 }
1839 ipa_info("IPA resource %s completed",
1840 ipa_ctx->resource_loading ?
1841 "load" : "unload");
1842 }
1843
1844 ipa_ctx->stats.event[type]++;
1845
1846 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1847 switch (type) {
1848 case QDF_IPA_STA_CONNECT:
1849 qdf_mutex_acquire(&ipa_ctx->event_lock);
1850
1851 /* STA already connected and without disconnect, connect again
1852 * This is Roaming scenario
1853 */
1854 if (ipa_ctx->sta_connected) {
1855 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1856 if (iface_ctx)
1857 wlan_ipa_cleanup_iface(iface_ctx);
1858 }
1859
1860 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301861 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301862 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001863 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301864 qdf_mutex_release(&ipa_ctx->event_lock);
1865 goto end;
1866 }
1867
Yu Tian0cc79c72019-09-18 15:11:32 +08001868 ipa_ctx->vdev_to_iface[session_id] =
1869 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1870
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301871 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08001872 (ipa_ctx->sap_num_connected_sta > 0 ||
1873 wlan_ipa_is_sta_only_offload_enabled()) &&
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301874 !ipa_ctx->sta_connected) {
1875 qdf_mutex_release(&ipa_ctx->event_lock);
1876 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1877 SIR_STA_RX_DATA_OFFLOAD, session_id,
1878 true);
1879 qdf_mutex_acquire(&ipa_ctx->event_lock);
1880 }
1881
jiad72b69a92019-04-11 17:23:10 +08001882 if (!wlan_ipa_is_sta_only_offload_enabled()) {
1883 ipa_debug("IPA STA only offload not enabled");
1884 } else if (ipa_ctx->uc_loaded &&
1885 !ipa_ctx->sap_num_connected_sta &&
1886 !ipa_ctx->sta_connected) {
1887 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1888 if (status) {
1889 qdf_mutex_release(&ipa_ctx->event_lock);
1890 ipa_info("handle 1st conn failed %d", status);
1891 wlan_ipa_uc_offload_enable_disable(
1892 ipa_ctx,
1893 SIR_STA_RX_DATA_OFFLOAD,
1894 session_id,
1895 false);
Yu Tian0cc79c72019-09-18 15:11:32 +08001896 ipa_ctx->vdev_to_iface[session_id] =
1897 WLAN_IPA_MAX_SESSION;
jiad72b69a92019-04-11 17:23:10 +08001898 goto end;
1899 }
1900 }
1901
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301902 ipa_ctx->sta_connected = 1;
1903
1904 qdf_mutex_release(&ipa_ctx->event_lock);
1905
Mohit Khannacabf5e72018-07-24 13:28:43 -07001906 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1907 ipa_ctx->sta_connected,
1908 session_id,
1909 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301910 break;
1911
1912 case QDF_IPA_AP_CONNECT:
1913 qdf_mutex_acquire(&ipa_ctx->event_lock);
1914
1915 /* For DFS channel we get two start_bss event (before and after
1916 * CAC). Also when ACS range includes both DFS and non DFS
1917 * channels, we could possibly change channel many times due to
1918 * RADAR detection and chosen channel may not be a DFS channels.
1919 * So dont return error here. Just discard the event.
1920 */
jiadc908ada2018-05-11 14:40:54 +08001921 if (ipa_ctx->vdev_to_iface[session_id] !=
1922 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301923 qdf_mutex_release(&ipa_ctx->event_lock);
1924 return 0;
1925 }
1926
1927 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301928 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301929 if (status != QDF_STATUS_SUCCESS) {
1930 qdf_mutex_release(&ipa_ctx->event_lock);
1931 ipa_err("%s: Evt: %d, Interface setup failed",
1932 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1933 goto end;
1934 }
1935
1936 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1937 qdf_mutex_release(&ipa_ctx->event_lock);
1938 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1939 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1940 qdf_mutex_acquire(&ipa_ctx->event_lock);
1941 }
1942
1943 ipa_ctx->vdev_to_iface[session_id] =
1944 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001945 ipa_debug("vdev_to_iface[%u]=%u",
1946 session_id,
1947 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301948 qdf_mutex_release(&ipa_ctx->event_lock);
1949 break;
1950
1951 case QDF_IPA_STA_DISCONNECT:
1952 qdf_mutex_acquire(&ipa_ctx->event_lock);
1953
1954 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301955 struct wlan_ipa_iface_context *iface;
1956
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301957 qdf_mutex_release(&ipa_ctx->event_lock);
1958 ipa_err("%s: Evt: %d, STA already disconnected",
1959 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301960
1961 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1962 if (iface && (iface->dev == net_dev))
1963 wlan_ipa_cleanup_iface(iface);
1964
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301965 return QDF_STATUS_E_INVAL;
1966 }
1967
1968 ipa_ctx->sta_connected = 0;
1969
1970 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1971 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1972 msg_ex->name);
1973 } else {
jiad72b69a92019-04-11 17:23:10 +08001974 /*
1975 * Disable IPA pipes when
1976 * 1. STA is the last interface or
1977 * 2. STA only offload enabled and no clients connected
1978 * to SAP
1979 */
1980 if ((ipa_ctx->num_iface == 1 ||
1981 (wlan_ipa_is_sta_only_offload_enabled() &&
1982 !ipa_ctx->sap_num_connected_sta)) &&
Yun Parka29974a2018-04-09 12:05:49 -07001983 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001984 !ipa_ctx->ipa_pipes_down &&
1985 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001986 if (cds_is_driver_unloading()) {
1987 /*
1988 * We disable WDI pipes directly here
1989 * since IPA_OPCODE_TX/RX_SUSPEND
1990 * message will not be processed when
1991 * unloading WLAN driver is in progress
1992 */
1993 wlan_ipa_uc_disable_pipes(ipa_ctx);
1994 } else {
1995 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1996 }
1997 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301998 }
1999
2000 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002001 (ipa_ctx->sap_num_connected_sta > 0 ||
2002 wlan_ipa_is_sta_only_offload_enabled())) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302003 qdf_mutex_release(&ipa_ctx->event_lock);
2004 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2005 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
2006 qdf_mutex_acquire(&ipa_ctx->event_lock);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302007 }
2008
Rakshith Suresh Patkara4dea902019-09-23 15:33:15 +05302009 ipa_ctx->vdev_to_iface[session_id] = WLAN_IPA_MAX_SESSION;
2010 ipa_debug("vdev_to_iface[%u]=%u", session_id,
2011 ipa_ctx->vdev_to_iface[session_id]);
2012
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302013 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2014 iface_ctx = &ipa_ctx->iface_context[i];
2015
2016 if (iface_ctx->dev == net_dev)
2017 break;
2018 }
2019 if (i < WLAN_IPA_MAX_IFACE)
2020 wlan_ipa_cleanup_iface(iface_ctx);
2021
2022 qdf_mutex_release(&ipa_ctx->event_lock);
2023
2024 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
2025 break;
2026
2027 case QDF_IPA_AP_DISCONNECT:
2028 qdf_mutex_acquire(&ipa_ctx->event_lock);
2029
2030 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07002031 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08002032 !ipa_ctx->ipa_pipes_down &&
2033 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302034 if (cds_is_driver_unloading()) {
2035 /*
2036 * We disable WDI pipes directly here since
2037 * IPA_OPCODE_TX/RX_SUSPEND message will not be
2038 * processed when unloading WLAN driver is in
2039 * progress
2040 */
2041 wlan_ipa_uc_disable_pipes(ipa_ctx);
2042 } else {
2043 /*
2044 * This shouldn't happen :
2045 * No interface left but WDI pipes are still
2046 * active - force close WDI pipes
2047 */
2048 ipa_err("No interface left but WDI pipes are still active");
2049 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2050 }
2051 }
2052
2053 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2054 qdf_mutex_release(&ipa_ctx->event_lock);
2055 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2056 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
2057 qdf_mutex_acquire(&ipa_ctx->event_lock);
2058 ipa_ctx->vdev_to_iface[session_id] =
2059 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07002060 ipa_debug("vdev_to_iface[%u]=%u",
2061 session_id,
2062 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302063 }
2064
2065 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2066 iface_ctx = &ipa_ctx->iface_context[i];
2067
2068 if (iface_ctx->dev == net_dev)
2069 break;
2070 }
2071 if (i < WLAN_IPA_MAX_IFACE)
2072 wlan_ipa_cleanup_iface(iface_ctx);
2073
2074 qdf_mutex_release(&ipa_ctx->event_lock);
2075 break;
2076
2077 case QDF_IPA_CLIENT_CONNECT_EX:
2078 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2079 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
2080 net_dev->name, type);
2081 return QDF_STATUS_SUCCESS;
2082 }
2083
2084 qdf_mutex_acquire(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302085 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302086 mac_addr)) {
2087 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302088 ipa_err("%s: STA found, addr: " QDF_MAC_ADDR_STR,
2089 net_dev->name,
2090 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302091 return QDF_STATUS_SUCCESS;
2092 }
2093
2094 /* Enable IPA UC Data PIPEs when first STA connected */
2095 if (ipa_ctx->sap_num_connected_sta == 0 &&
2096 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302097
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302098 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002099 ipa_ctx->sta_connected &&
2100 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302101 qdf_mutex_release(&ipa_ctx->event_lock);
2102 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2103 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302104 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302105 qdf_mutex_acquire(&ipa_ctx->event_lock);
2106 }
2107
jiad72b69a92019-04-11 17:23:10 +08002108 /*
2109 * IPA pipes already enabled if STA only offload
2110 * is enabled and STA is connected to remote AP.
2111 */
2112 if (wlan_ipa_is_sta_only_offload_enabled() &&
2113 ipa_ctx->sta_connected) {
2114 ipa_debug("IPA pipes already enabled");
2115 } else if (wlan_ipa_uc_handle_first_con(ipa_ctx)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302116 ipa_info("%s: handle 1st con fail",
2117 net_dev->name);
2118
2119 if (wlan_ipa_uc_sta_is_enabled(
2120 ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002121 ipa_ctx->sta_connected &&
2122 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302123 qdf_mutex_release(&ipa_ctx->event_lock);
2124 wlan_ipa_uc_offload_enable_disable(
2125 ipa_ctx,
2126 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302127 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302128 } else {
2129 qdf_mutex_release(&ipa_ctx->event_lock);
2130 }
2131
jiad72b69a92019-04-11 17:23:10 +08002132 return QDF_STATUS_E_BUSY;
2133 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302134 }
2135
2136 ipa_ctx->sap_num_connected_sta++;
2137
2138 qdf_mutex_release(&ipa_ctx->event_lock);
2139
2140 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2141 QDF_IPA_MSG_META_MSG_LEN(&meta) =
2142 (sizeof(qdf_ipa_wlan_msg_ex_t) +
2143 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
2144 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2145
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002146 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302147 ipa_err("msg_ex allocation failed");
2148 return QDF_STATUS_E_NOMEM;
2149 }
2150 strlcpy(msg_ex->name, net_dev->name,
2151 IPA_RESOURCE_NAME_MAX);
2152 msg_ex->num_of_attribs = 1;
2153 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
2154 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2155 msg_ex->attribs[0].offset =
2156 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
2157 } else {
2158 msg_ex->attribs[0].offset =
2159 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
2160 }
2161 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
2162 IPA_MAC_ADDR_SIZE);
2163
2164 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
2165 ipa_info("%s: Evt: %d send ipa msg fail",
2166 net_dev->name, type);
2167 qdf_mem_free(msg_ex);
2168 return QDF_STATUS_E_FAILURE;
2169 }
2170 ipa_ctx->stats.num_send_msg++;
2171
2172 ipa_info("sap_num_connected_sta=%d",
2173 ipa_ctx->sap_num_connected_sta);
2174
2175 return QDF_STATUS_SUCCESS;
2176
2177 case WLAN_CLIENT_DISCONNECT:
2178 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2179 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
2180 msg_ex->name);
2181 return QDF_STATUS_SUCCESS;
2182 }
2183
2184 qdf_mutex_acquire(&ipa_ctx->event_lock);
2185 if (!ipa_ctx->sap_num_connected_sta) {
2186 qdf_mutex_release(&ipa_ctx->event_lock);
2187 ipa_err("%s: Evt: %d, Client already disconnected",
2188 msg_ex->name,
2189 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2190
2191 return QDF_STATUS_SUCCESS;
2192 }
2193 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302194 mac_addr)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302195 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302196 ipa_err("%s: STA NOT found, not valid: "
2197 QDF_MAC_ADDR_STR,
2198 msg_ex->name, QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302199
2200 return QDF_STATUS_SUCCESS;
2201 }
2202 ipa_ctx->sap_num_connected_sta--;
2203
jiad72b69a92019-04-11 17:23:10 +08002204 /*
2205 * Disable IPA pipes when
2206 * 1. last client disconnected and
2207 * 2. STA is not connected if STA only offload is enabled
2208 */
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302209 if (!ipa_ctx->sap_num_connected_sta &&
jiad72b69a92019-04-11 17:23:10 +08002210 ipa_ctx->uc_loaded &&
2211 !(wlan_ipa_is_sta_only_offload_enabled() &&
2212 ipa_ctx->sta_connected)) {
Yun Parka29974a2018-04-09 12:05:49 -07002213 if ((false == ipa_ctx->resource_unloading) &&
2214 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
2215 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08002216 if (cds_is_driver_unloading()) {
2217 /*
2218 * We disable WDI pipes directly here
2219 * since IPA_OPCODE_TX/RX_SUSPEND
2220 * message will not be processed when
2221 * unloading WLAN driver is in progress
2222 */
2223 wlan_ipa_uc_disable_pipes(ipa_ctx);
2224 } else {
2225 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2226 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302227 }
2228
2229 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002230 ipa_ctx->sta_connected &&
2231 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302232 qdf_mutex_release(&ipa_ctx->event_lock);
2233 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2234 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302235 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302236 } else {
2237 qdf_mutex_release(&ipa_ctx->event_lock);
2238 }
2239 } else {
2240 qdf_mutex_release(&ipa_ctx->event_lock);
2241 }
2242
2243 ipa_info("sap_num_connected_sta=%d",
2244 ipa_ctx->sap_num_connected_sta);
2245 break;
2246
2247 default:
2248 return QDF_STATUS_SUCCESS;
2249 }
2250
2251 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2252 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2253 if (!msg) {
2254 ipa_err("msg allocation failed");
2255 return QDF_STATUS_E_NOMEM;
2256 }
2257
2258 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2259 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2260 IPA_RESOURCE_NAME_MAX);
2261 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2262
2263 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
2264 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2265
2266 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2267
2268 ipa_err("%s: Evt: %d fail",
2269 QDF_IPA_WLAN_MSG_NAME(msg),
2270 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2271 qdf_mem_free(msg);
2272
2273 return QDF_STATUS_E_FAILURE;
2274 }
2275
2276 ipa_ctx->stats.num_send_msg++;
2277
2278end:
2279 return QDF_STATUS_SUCCESS;
2280}
2281
2282/**
2283 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002284 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302285 *
2286 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2287 */
2288static qdf_ipa_wlan_event
2289wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2290{
Yun Park84fbb272018-04-02 15:31:01 -07002291 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302292
2293 switch (wlan_ipa_event_type) {
2294 case WLAN_IPA_CLIENT_CONNECT:
2295 ipa_event = QDF_IPA_CLIENT_CONNECT;
2296 break;
2297 case WLAN_IPA_CLIENT_DISCONNECT:
2298 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2299 break;
2300 case WLAN_IPA_AP_CONNECT:
2301 ipa_event = QDF_IPA_AP_CONNECT;
2302 break;
2303 case WLAN_IPA_AP_DISCONNECT:
2304 ipa_event = QDF_IPA_AP_DISCONNECT;
2305 break;
2306 case WLAN_IPA_STA_CONNECT:
2307 ipa_event = QDF_IPA_STA_CONNECT;
2308 break;
2309 case WLAN_IPA_STA_DISCONNECT:
2310 ipa_event = QDF_IPA_STA_DISCONNECT;
2311 break;
2312 case WLAN_IPA_CLIENT_CONNECT_EX:
2313 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2314 break;
2315 case WLAN_IPA_WLAN_EVENT_MAX:
2316 default:
2317 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2318 break;
2319 }
2320
2321 return ipa_event;
2322}
2323
2324/**
2325 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2326 * @net_dev: Interface net device
2327 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302328 * @session_id: session id for the event
2329 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2330 * @mac_address: MAC address associated with the event
2331 *
2332 * Return: QDF_STATUS
2333 */
2334QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302335 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302336 enum wlan_ipa_wlan_event ipa_event_type,
2337 uint8_t *mac_addr)
2338{
2339 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2340 QDF_STATUS status = QDF_STATUS_SUCCESS;
2341
2342 /* Data path offload only support for STA and SAP mode */
2343 if ((device_mode == QDF_STA_MODE) ||
2344 (device_mode == QDF_SAP_MODE))
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302345 status = __wlan_ipa_wlan_evt(net_dev, device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302346 session_id, type, mac_addr);
2347
2348 return status;
2349}
2350
2351/**
2352 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2353 * @ipa_ctx: Global IPA IPA context
2354 * @is_loading: Indicate if invoked during loading
2355 *
2356 * Return: None
2357 */
2358static void
2359wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2360{
2361 unsigned int pending_event_count;
2362 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2363
2364 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2365 ipa_debug("Pending Event Count %d", pending_event_count);
2366 if (!pending_event_count) {
2367 ipa_debug("No Pending Event");
2368 return;
2369 }
2370
2371 qdf_list_remove_front(&ipa_ctx->pending_event,
2372 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002373 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302374 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2375 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2376 struct wlan_objmgr_vdev *vdev =
2377 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2378 pending_event->session_id,
2379 WLAN_IPA_ID);
2380 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302381 __wlan_ipa_wlan_evt(pending_event->net_dev,
2382 pending_event->device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302383 pending_event->session_id,
2384 pending_event->type,
2385 pending_event->mac_addr);
2386 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302387
2388 if (vdev)
2389 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302390 qdf_mem_free(pending_event);
2391 pending_event = NULL;
2392 qdf_list_remove_front(&ipa_ctx->pending_event,
2393 (qdf_list_node_t **)&pending_event);
2394 }
2395}
2396
2397/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002398 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2399 * @ipa_ctx: IPA context
2400 *
2401 * Return: None
2402 */
2403static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2404{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302405 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002406 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302407 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002408
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302409 if (!ipa_ctx->tx_desc_pool)
2410 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002411
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302412 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2413 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2414 for (i = 0; i < pool_size; i++) {
2415 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002416 if (ipa_tx_desc)
2417 qdf_ipa_free_skb(ipa_tx_desc);
2418
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302419 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2420 &ipa_ctx->tx_desc_pool[i].node) !=
2421 QDF_STATUS_SUCCESS)
2422 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002423 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302424 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2425
2426 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2427 qdf_mem_free(ipa_ctx->tx_desc_pool);
2428 ipa_ctx->tx_desc_pool = NULL;
2429
2430 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2431 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002432}
2433
2434/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302435 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302436 * @ipa_ctx: IPA context
2437 *
2438 * Return: QDF_STATUS
2439 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302440static QDF_STATUS
2441wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302442{
2443 int i;
2444 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302445
2446 max_desc_cnt = ipa_ctx->config->txbuf_count;
2447
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302448 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2449 max_desc_cnt);
2450
2451 if (!ipa_ctx->tx_desc_pool) {
2452 ipa_err("Free Tx descriptor allocation failed");
2453 return QDF_STATUS_E_NOMEM;
2454 }
2455
2456 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302457
2458 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2459 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302460 ipa_ctx->tx_desc_pool[i].id = i;
2461 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2462 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2463 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302464 }
2465
2466 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2467 ipa_ctx->stats.num_tx_desc_error = 0;
2468
2469 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2470
2471 return QDF_STATUS_SUCCESS;
2472}
2473
2474#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2475/**
2476 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2477 * @ipa_ctx: Global IPA IPA context
2478 * @desc_fifo_sz: Number of descriptors
2479 *
2480 * Return: 0 on success, negative errno on error
2481 */
2482static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2483 int32_t desc_fifo_sz)
2484{
2485 int i, ret = 0;
2486 qdf_ipa_sys_connect_params_t *ipa;
2487
2488 /*setup TX pipes */
2489 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2490 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2491
2492 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2493 ipa->desc_fifo_sz = desc_fifo_sz;
2494 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302495 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302496
2497 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2498 ipa->ipa_ep_cfg.hdr.hdr_len =
2499 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2500 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2501 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2502 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2503 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2504 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2505 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2506 } else {
2507 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2508 }
2509 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2510
2511 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2512 &ipa_ctx->sys_pipe[i].conn_hdl);
2513 if (ret) {
2514 ipa_err("Failed for pipe %d ret: %d", i, ret);
2515 return ret;
2516 }
2517 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2518 }
2519
2520 return ret;
2521}
2522#else
2523/**
2524 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302525 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302526 * @desc_fifo_sz: Number of descriptors
2527 *
2528 * Return: 0 on success, negative errno on error
2529 */
2530static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2531 int32_t desc_fifo_sz)
2532{
2533 /*
2534 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2535 * is enabled, where per vdev descriptors are supported in firmware.
2536 */
2537 return 0;
2538}
2539#endif
2540
Sravan Kumar Kairam7efc0132019-03-25 16:13:46 +05302541#if defined(CONFIG_IPA_WDI_UNIFIED_API) && defined(IPA_WDI3_GSI)
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302542/**
2543 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2544 * @ipa_ctx: IPA context
2545 *
2546 * Return: rx ipa sys client
2547 */
2548static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2549{
2550 if (ipa_ctx->over_gsi)
2551 return IPA_CLIENT_WLAN2_PROD;
2552 else
2553 return IPA_CLIENT_WLAN1_PROD;
2554}
2555#else
2556static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2557{
2558 return IPA_CLIENT_WLAN1_PROD;
2559}
2560#endif
2561
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302562/**
2563 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2564 * @ipa_ctx: Global IPA IPA context
2565 * @desc_fifo_sz: Number of descriptors
2566 *
2567 * Return: 0 on success, negative errno on error
2568 */
2569static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2570 int32_t desc_fifo_sz)
2571{
2572 int ret = 0;
2573 qdf_ipa_sys_connect_params_t *ipa;
2574
2575 /*
2576 * Hard code it here, this can be extended if in case
2577 * PROD pipe is also per interface.
2578 * Right now there is no advantage of doing this.
2579 */
2580 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2581
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302582 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302583 ipa->desc_fifo_sz = desc_fifo_sz;
2584 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302585 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302586
2587 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2588 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2589 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2590 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2591
2592 ret = qdf_ipa_setup_sys_pipe(ipa,
2593 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2594 if (ret) {
2595 ipa_err("Failed for RX pipe: %d", ret);
2596 return ret;
2597 }
2598 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2599
2600 return ret;
2601}
2602
2603/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002604 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2605 * @ipa_ctx: Global IPA IPA context
2606 *
2607 * Return: None
2608 */
2609static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2610{
2611 int ret, i;
2612
2613 if (!ipa_ctx)
2614 return;
2615
2616 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2617 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2618 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2619 ipa_ctx->sys_pipe[i].conn_hdl);
2620 if (ret)
2621 ipa_err("Failed:%d", ret);
2622
2623 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2624 }
2625 }
2626
2627 wlan_ipa_free_tx_desc_list(ipa_ctx);
2628}
2629
2630/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302631 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2632 * @ipa_ctx: Global IPA IPA context
2633 *
2634 * Return: 0 on success, negative errno on error
2635 */
2636static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2637{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002638 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302639 uint32_t desc_fifo_sz;
2640
2641 /* The maximum number of descriptors that can be provided to a BAM at
2642 * once is one less than the total number of descriptors that the buffer
2643 * can contain.
2644 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2645 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2646 * be provided at once.
2647 * Because of above requirement, one extra descriptor will be added to
2648 * make sure hardware always has one descriptor.
2649 */
2650 desc_fifo_sz = ipa_ctx->config->desc_size
2651 + SPS_DESC_SIZE;
2652
2653 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2654 if (ret) {
2655 ipa_err("Failed for TX pipe: %d", ret);
2656 goto setup_sys_pipe_fail;
2657 }
2658
2659 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2660 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2661 if (ret) {
2662 ipa_err("Failed for RX pipe: %d", ret);
2663 goto setup_sys_pipe_fail;
2664 }
2665 }
2666
2667 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302668 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302669 if (ret)
2670 goto setup_sys_pipe_fail;
2671
2672 return ret;
2673
2674setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002675 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302676
2677 return ret;
2678}
2679
jiadbb47e132018-03-30 16:28:30 +08002680#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2681QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2682 bool mcc_mode)
2683{
2684 qdf_ipa_msg_meta_t meta;
2685 qdf_ipa_wlan_msg_t *msg;
2686 int ret;
2687
2688 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2689 return QDF_STATUS_SUCCESS;
2690
2691 /* Send SCC/MCC Switching event to IPA */
2692 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2693 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002694 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002695 ipa_err("msg allocation failed");
2696 return QDF_STATUS_E_NOMEM;
2697 }
2698
jiad629b2172018-05-11 15:34:22 +08002699 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002700 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002701 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2702 } else {
jiadbb47e132018-03-30 16:28:30 +08002703 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002704 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2705 }
2706
jiadbb47e132018-03-30 16:28:30 +08002707 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2708 "ipa_send_msg(Evt:%d)",
2709 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2710
2711 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2712
2713 if (ret) {
2714 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2715 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2716 qdf_mem_free(msg);
2717 return QDF_STATUS_E_FAILURE;
2718 }
2719
2720 return QDF_STATUS_SUCCESS;
2721}
2722
2723static void wlan_ipa_mcc_work_handler(void *data)
2724{
2725 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2726
2727 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2728}
2729#endif
2730
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302731/**
2732 * wlan_ipa_setup() - IPA initialization function
2733 * @ipa_ctx: IPA context
2734 * @ipa_cfg: IPA config
2735 *
2736 * Allocate ipa_ctx resources, ipa pipe resource and register
2737 * wlan interface with IPA module.
2738 *
2739 * Return: QDF_STATUS enumeration
2740 */
2741QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2742 struct wlan_ipa_config *ipa_cfg)
2743{
2744 int ret, i;
2745 struct wlan_ipa_iface_context *iface_context = NULL;
2746 QDF_STATUS status;
2747
2748 ipa_debug("enter");
2749
2750 gp_ipa = ipa_ctx;
2751 ipa_ctx->num_iface = 0;
2752 ipa_ctx->config = ipa_cfg;
2753
2754 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2755
2756 /* Create the interface context */
2757 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2758 iface_context = &ipa_ctx->iface_context[i];
2759 iface_context->ipa_ctx = ipa_ctx;
2760 iface_context->cons_client =
2761 wlan_ipa_iface_2_client[i].cons_client;
2762 iface_context->prod_client =
2763 wlan_ipa_iface_2_client[i].prod_client;
2764 iface_context->iface_id = i;
2765 iface_context->dev = NULL;
2766 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2767 iface_context->tl_context = NULL;
2768 qdf_spinlock_create(&iface_context->interface_lock);
2769 }
2770
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302771 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302772 qdf_spinlock_create(&ipa_ctx->pm_lock);
2773 qdf_spinlock_create(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302774 qdf_spinlock_create(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302775 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2776 qdf_list_create(&ipa_ctx->pending_event, 1000);
2777 qdf_mutex_create(&ipa_ctx->event_lock);
2778 qdf_mutex_create(&ipa_ctx->ipa_lock);
2779
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302780 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2781 if (status != QDF_STATUS_SUCCESS)
2782 goto fail_setup_rm;
2783
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302784 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2785 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2786 sizeof(struct wlan_ipa_sys_pipe));
2787
2788 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2789 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2790 ipa_ctx->sap_num_connected_sta = 0;
2791 ipa_ctx->ipa_tx_packets_diff = 0;
2792 ipa_ctx->ipa_rx_packets_diff = 0;
2793 ipa_ctx->ipa_p_tx_packets = 0;
2794 ipa_ctx->ipa_p_rx_packets = 0;
2795 ipa_ctx->resource_loading = false;
2796 ipa_ctx->resource_unloading = false;
2797 ipa_ctx->sta_connected = 0;
2798 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302799 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302800 ipa_ctx->wdi_enabled = false;
2801 /* Setup IPA system pipes */
2802 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2803 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2804 if (ret)
2805 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002806
2807 qdf_create_work(0, &ipa_ctx->mcc_work,
2808 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302809 }
2810
2811 status = wlan_ipa_wdi_init(ipa_ctx);
2812 if (status == QDF_STATUS_E_BUSY)
2813 status = wlan_ipa_uc_send_wdi_control_msg(false);
2814 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002815 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302816 goto fail_create_sys_pipe;
2817 }
2818 } else {
2819 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2820 if (ret)
2821 goto fail_create_sys_pipe;
2822 }
2823
2824 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2825
2826 ipa_debug("exit: success");
2827
2828 return QDF_STATUS_SUCCESS;
2829
2830fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302831 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2832
2833fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302834 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302835 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302836 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302837 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2838 iface_context = &ipa_ctx->iface_context[i];
2839 qdf_spinlock_destroy(&iface_context->interface_lock);
2840 }
2841 qdf_mutex_destroy(&ipa_ctx->event_lock);
2842 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2843 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302844 gp_ipa = NULL;
2845 ipa_debug("exit: fail");
2846
2847 return QDF_STATUS_E_FAILURE;
2848}
2849
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302850void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2851{
2852 qdf_nbuf_t skb;
2853 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2854
2855 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2856 return;
2857
2858 qdf_cancel_work(&ipa_ctx->pm_work);
2859
2860 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2861
2862 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2863 != NULL)) {
2864 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2865
2866 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002867
2868 if (pm_tx_cb->exception) {
2869 dev_kfree_skb_any(skb);
2870 } else {
2871 if (pm_tx_cb->ipa_tx_desc)
2872 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2873 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302874
2875 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2876 }
2877 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2878}
2879
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302880QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2881{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302882 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302883 int i;
2884
2885 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2886 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2887
2888 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002889 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302890 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002891 qdf_cancel_work(&ipa_ctx->mcc_work);
2892 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302893
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302894 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2895
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302896 wlan_ipa_flush(ipa_ctx);
2897
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302898 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2899 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302900 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302901
2902 /* destroy the interface lock */
2903 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2904 iface_context = &ipa_ctx->iface_context[i];
2905 qdf_spinlock_destroy(&iface_context->interface_lock);
2906 }
2907
2908 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2909 wlan_ipa_wdi_cleanup();
2910 qdf_mutex_destroy(&ipa_ctx->event_lock);
2911 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2912 qdf_list_destroy(&ipa_ctx->pending_event);
2913
2914 }
2915
2916 gp_ipa = NULL;
2917
2918 return QDF_STATUS_SUCCESS;
2919}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302920
2921struct wlan_ipa_iface_context
2922*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2923{
2924 struct wlan_ipa_iface_context *iface_ctx = NULL;
2925 int i;
2926
2927 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2928 iface_ctx = &ipa_ctx->iface_context[i];
2929
2930 if (iface_ctx->device_mode == mode)
2931 return iface_ctx;
2932 }
2933
2934 return NULL;
2935}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302936
jiadbb47e132018-03-30 16:28:30 +08002937void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302938{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302939 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002940 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302941
jiadbb47e132018-03-30 16:28:30 +08002942 if (ipa_ctx->mcc_mode == mcc_mode)
2943 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302944
jiadbb47e132018-03-30 16:28:30 +08002945 ipa_ctx->mcc_mode = mcc_mode;
2946 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302947}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302948
2949/**
2950 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2951 * @ipa_ctx: ipa ipa local context
2952 *
2953 * Will handle IPA UC image loaded indication comes from IPA kernel
2954 *
2955 * Return: None
2956 */
2957static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2958{
2959 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2960 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2961 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2962 QDF_STATUS status;
2963
2964 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002965
2966 if (!qdf_dev) {
2967 ipa_err("qdf device is NULL!");
2968 return;
2969 }
2970
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302971 if (true == ipa_ctx->uc_loaded) {
2972 ipa_info("UC already loaded");
2973 return;
2974 }
2975
Lihua Liu15f6e452018-05-30 17:31:06 +08002976 if (!qdf_dev) {
2977 ipa_err("qdf_dev is null");
2978 return;
2979 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302980 /* Connect pipe */
2981 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2982 if (status) {
2983 ipa_err("Failure to setup IPA pipes (status=%d)",
2984 status);
2985 return;
2986 }
2987
2988 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302989
jiad72b69a92019-04-11 17:23:10 +08002990 /*
2991 * Enable IPA/FW PIPEs if
2992 * 1. any clients connected to SAP or
2993 * 2. STA connected to remote AP if STA only offload is enabled
2994 */
2995 if (ipa_ctx->sap_num_connected_sta ||
2996 (wlan_ipa_is_sta_only_offload_enabled() &&
2997 ipa_ctx->sta_connected)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302998 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2999 wlan_ipa_uc_handle_first_con(ipa_ctx);
3000 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303001}
3002
3003/**
3004 * wlan_ipa_uc_op_cb() - IPA uC operation callback
3005 * @op_msg: operation message received from firmware
3006 * @usr_ctxt: user context registered with TL (we register the IPA Global
3007 * context)
3008 *
3009 * Return: None
3010 */
3011static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
3012 struct wlan_ipa_priv *ipa_ctx)
3013{
3014 struct op_msg_type *msg = op_msg;
3015 struct ipa_uc_fw_stats *uc_fw_stat;
3016
3017 if (!op_msg) {
3018 ipa_err("INVALID ARG");
3019 return;
3020 }
3021
3022 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3023 ipa_err("INVALID OPCODE %d", msg->op_code);
3024 qdf_mem_free(op_msg);
3025 return;
3026 }
3027
3028 ipa_debug("OPCODE=%d", msg->op_code);
3029
3030 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
3031 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
3032 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3033 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07003034 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303035 ipa_ctx->resource_loading = false;
3036 qdf_event_set(&ipa_ctx->ipa_resource_comp);
3037 if (ipa_ctx->wdi_enabled == false) {
3038 ipa_ctx->wdi_enabled = true;
3039 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
3040 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
3041 ipa_ctx->mcc_mode);
3042 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303043 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303044 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07003045 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303046 QDF_IPA_RM_RESOURCE_GRANTED,
3047 QDF_IPA_RM_RESOURCE_WLAN_CONS);
3048 ipa_ctx->pending_cons_req = false;
3049 }
3050 qdf_mutex_release(&ipa_ctx->ipa_lock);
3051 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
3052 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
3053 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05303054
3055 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
3056 wlan_ipa_uc_disable_pipes(ipa_ctx);
3057 ipa_info("Disable FW TX PIPE");
3058 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3059 false, true);
3060 }
3061
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303062 ipa_ctx->activated_fw_pipe--;
3063 if (!ipa_ctx->activated_fw_pipe) {
3064 /*
3065 * Async return success from FW
3066 * Disable/suspend all the PIPEs
3067 */
3068 ipa_ctx->resource_unloading = false;
3069 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303070 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07003071 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
3072 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303073 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303074 ipa_ctx->pending_cons_req = false;
3075 }
3076 qdf_mutex_release(&ipa_ctx->ipa_lock);
3077 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3078 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
3079 uc_fw_stat = (struct ipa_uc_fw_stats *)
3080 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3081
3082 /* WLAN FW WDI stats */
3083 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
3084 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3085 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
3086 /* STATs from FW */
3087 uc_fw_stat = (struct ipa_uc_fw_stats *)
3088 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3089 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3090 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
3091 uc_fw_stat->tx_pkts_completed,
3092 ipa_ctx->ipa_p_tx_packets);
3093 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
3094 (uc_fw_stat->rx_num_ind_drop_no_space +
3095 uc_fw_stat->rx_num_ind_drop_no_buf +
3096 uc_fw_stat->rx_num_pkts_indicated),
3097 ipa_ctx->ipa_p_rx_packets);
3098
3099 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
3100 ipa_ctx->ipa_p_rx_packets =
3101 (uc_fw_stat->rx_num_ind_drop_no_space +
3102 uc_fw_stat->rx_num_ind_drop_no_buf +
3103 uc_fw_stat->rx_num_pkts_indicated);
3104 qdf_mutex_release(&ipa_ctx->ipa_lock);
3105 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
3106 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3107 wlan_ipa_uc_loaded_handler(ipa_ctx);
3108 qdf_mutex_release(&ipa_ctx->ipa_lock);
3109 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
3110 ipa_err("Invalid message: op_code=%d, reason=%d",
3111 msg->op_code, ipa_ctx->stat_req_reason);
3112 }
3113
3114 qdf_mem_free(op_msg);
3115}
3116
3117/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303118 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
3119 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303120 *
3121 * Return: None
3122 */
jitiphilfdcaaba2018-09-03 16:19:52 +05303123static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303124{
3125 struct op_msg_type *msg;
3126 struct uc_op_work_struct *uc_op_work =
3127 (struct uc_op_work_struct *)data;
3128 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3129
3130 msg = uc_op_work->msg;
3131 uc_op_work->msg = NULL;
3132 ipa_debug("posted msg %d", msg->op_code);
3133
3134 wlan_ipa_uc_op_cb(msg, ipa_ctx);
3135}
3136
3137/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303138 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
3139 * __wlan_ipa_uc_fw_op_event_handler
3140 * @data: uC OP work
3141 *
3142 * Return: None
3143 */
3144static void wlan_ipa_uc_fw_op_event_handler(void *data)
3145{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003146 struct qdf_op_sync *op_sync;
3147
3148 if (qdf_op_protect(&op_sync))
3149 return;
3150
jitiphilfdcaaba2018-09-03 16:19:52 +05303151 __wlan_ipa_uc_fw_op_event_handler(data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003152
3153 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05303154}
3155
3156/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303157 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
3158 * @op_msg: operation message received from firmware
3159 * @ipa_ctx: Global IPA context
3160 *
3161 * Return: None
3162 */
3163static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
3164{
3165 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
3166 struct op_msg_type *msg;
3167 struct uc_op_work_struct *uc_op_work;
3168
3169 if (!ipa_ctx)
3170 goto end;
3171
3172 msg = (struct op_msg_type *)op_msg;
3173
3174 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3175 ipa_err("Invalid OP Code (%d)", msg->op_code);
3176 goto end;
3177 }
3178
3179 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
3180 if (uc_op_work->msg) {
3181 /* When the same uC OPCODE is already pended, just return */
3182 goto end;
3183 }
3184
3185 uc_op_work->msg = msg;
3186 qdf_sched_work(0, &uc_op_work->work);
3187 return;
3188
3189end:
3190 qdf_mem_free(op_msg);
3191}
3192
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303193QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
3194 qdf_device_t osdev)
3195{
3196 uint8_t i;
3197 QDF_STATUS status = QDF_STATUS_SUCCESS;
3198
3199 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3200 return QDF_STATUS_SUCCESS;
3201
3202 ipa_debug("enter");
3203
Sravan Kumar Kairam02a761e2019-07-05 17:06:27 +05303204 if (!osdev) {
3205 ipa_err("osdev null");
3206 status = QDF_STATUS_E_FAILURE;
3207 goto fail_return;
3208 }
3209
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303210 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
3211 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
3212 ipa_ctx->vdev_offload_enabled[i] = false;
3213 }
3214
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303215 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
3216 ipa_err("IPA UC resource alloc fail");
3217 status = QDF_STATUS_E_FAILURE;
3218 goto fail_return;
3219 }
3220
3221 if (true == ipa_ctx->uc_loaded) {
3222 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
3223 if (status) {
3224 ipa_err("Failure to setup IPA pipes (status=%d)",
3225 status);
3226 status = QDF_STATUS_E_FAILURE;
3227 goto fail_return;
3228 }
3229
3230 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
3231 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08003232
3233 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
3234 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303235 }
3236
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303237 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3238 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
3239
3240 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3241 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
3242 wlan_ipa_uc_fw_op_event_handler,
3243 &ipa_ctx->uc_op_work[i]);
3244 ipa_ctx->uc_op_work[i].msg = NULL;
3245 }
3246
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303247fail_return:
3248 ipa_debug("exit: status=%d", status);
3249 return status;
3250}
3251
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303252/**
3253 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3254 * @ipa_ctx: pointer to IPA IPA struct
3255 *
3256 * Return: none
3257 */
3258static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
3259{
3260 struct wlan_ipa_uc_pending_event *pending_event = NULL;
3261
3262 while (qdf_list_remove_front(&ipa_ctx->pending_event,
3263 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3264 qdf_mem_free(pending_event);
3265}
3266
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303267QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
3268{
3269 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303270 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303271
3272 ipa_debug("enter");
3273
3274 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3275 return status;
3276
3277 if (!ipa_ctx->ipa_pipes_down)
3278 wlan_ipa_uc_disable_pipes(ipa_ctx);
3279
3280 if (true == ipa_ctx->uc_loaded) {
3281 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3282 ipa_ctx->tx_pipe_handle,
3283 ipa_ctx->rx_pipe_handle);
3284 if (status)
3285 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3286 status);
3287 }
3288
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303289 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3290 wlan_ipa_cleanup_pending_event(ipa_ctx);
3291 qdf_mutex_release(&ipa_ctx->ipa_lock);
3292
3293 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3294 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3295 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3296 ipa_ctx->uc_op_work[i].msg = NULL;
3297 }
3298
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303299 ipa_debug("exit: ret=%d", status);
3300 return status;
3301}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303302
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303303/**
3304 * wlan_ipa_uc_send_evt() - send event to ipa
3305 * @net_dev: Interface net device
3306 * @type: event type
3307 * @mac_addr: pointer to mac address
3308 *
3309 * Send event to IPA driver
3310 *
3311 * Return: QDF_STATUS
3312 */
3313static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3314 qdf_ipa_wlan_event type,
3315 uint8_t *mac_addr)
3316{
3317 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3318 qdf_ipa_msg_meta_t meta;
3319 qdf_ipa_wlan_msg_t *msg;
3320
3321 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3322 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3323 if (!msg) {
3324 ipa_err("msg allocation failed");
3325 return QDF_STATUS_E_NOMEM;
3326 }
3327
3328 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3329 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3330 IPA_RESOURCE_NAME_MAX);
3331 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3332
3333 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3334 ipa_err("%s: Evt: %d fail",
3335 QDF_IPA_WLAN_MSG_NAME(msg),
3336 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3337 qdf_mem_free(msg);
3338
3339 return QDF_STATUS_E_FAILURE;
3340 }
3341
3342 ipa_ctx->stats.num_send_msg++;
3343
3344 return QDF_STATUS_SUCCESS;
3345}
3346
Vevek Venkatesane81bca82019-08-12 22:25:15 +05303347void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx,
3348 qdf_netdev_t net_dev)
3349{
3350 struct wlan_ipa_iface_context *iface_ctx;
3351 int i;
3352
3353 ipa_debug("enter");
3354
3355 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3356 iface_ctx = &ipa_ctx->iface_context[i];
3357 if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE &&
3358 iface_ctx->dev == net_dev && iface_ctx->tl_context) {
3359 wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
3360 net_dev->dev_addr);
3361 wlan_ipa_cleanup_iface(iface_ctx);
3362 }
3363 }
3364
3365 ipa_debug("exit");
3366}
3367
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303368QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3369 qdf_netdev_t net_dev)
3370{
3371 struct wlan_ipa_iface_context *iface_ctx;
3372 QDF_STATUS status;
3373
3374 ipa_debug("enter");
3375
3376 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3377 if (iface_ctx)
3378 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3379 net_dev->dev_addr);
3380 else
3381 return QDF_STATUS_E_INVAL;
3382
3383 ipa_debug("exit :%d", status);
3384
3385 return status;
3386}
3387
3388void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3389 qdf_netdev_t net_dev)
3390{
3391 struct wlan_ipa_iface_context *iface_ctx;
3392 int i;
3393
3394 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3395 iface_ctx = &ipa_ctx->iface_context[i];
3396 if (iface_ctx->dev == net_dev)
3397 break;
3398 }
3399
3400 if (iface_ctx)
3401 wlan_ipa_cleanup_iface(iface_ctx);
3402}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303403
3404void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3405{
3406 struct wlan_ipa_iface_context *iface;
3407 int i;
3408
3409 ipa_info("enter");
3410
3411 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3412 iface = &ipa_ctx->iface_context[i];
3413 if (iface->dev) {
3414 if (iface->device_mode == QDF_SAP_MODE)
3415 wlan_ipa_uc_send_evt(iface->dev,
3416 QDF_IPA_AP_DISCONNECT,
3417 iface->dev->dev_addr);
3418 else if (iface->device_mode == QDF_STA_MODE)
3419 wlan_ipa_uc_send_evt(iface->dev,
3420 QDF_IPA_STA_DISCONNECT,
3421 iface->dev->dev_addr);
3422 wlan_ipa_cleanup_iface(iface);
3423 }
3424 }
3425}
jitiphil0e3b5922018-07-24 18:43:50 +05303426
3427void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3428{
3429 qdf_ipa_msg_meta_t meta;
3430 qdf_ipa_wlan_msg_t *msg;
3431 int ret;
3432
3433 meta.msg_len = sizeof(*msg);
3434 msg = qdf_mem_malloc(meta.msg_len);
3435 if (!msg) {
3436 ipa_debug("msg allocation failed");
3437 return;
3438 }
3439
3440 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3441 ipa_debug("ipa_send_msg(Evt:%d)",
3442 meta.msg_type);
3443 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3444
3445 if (ret) {
3446 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3447 meta.msg_type, ret);
3448 qdf_mem_free(msg);
3449 }
3450 ipa_ctx->stats.num_send_msg++;
3451}