blob: bb967053fdcb02a216d15f065e2b350413f8352e [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;
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800238 struct wlan_objmgr_pdev *pdev;
239 struct wlan_objmgr_psoc *psoc;
240 qdf_device_t osdev;
Yun Parke74e6092018-04-27 11:36:34 -0700241 qdf_nbuf_t skb;
242 struct wlan_ipa_tx_desc *tx_desc;
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800243 qdf_dma_addr_t paddr;
244 QDF_STATUS status;
245
246 if (!ipa_ctx)
247 return;
248 pdev = ipa_ctx->pdev;
249 psoc = wlan_pdev_get_psoc(pdev);
250 osdev = wlan_psoc_get_qdf_dev(psoc);
Yun Parke74e6092018-04-27 11:36:34 -0700251
252 qdf_spin_lock_bh(&iface_context->interface_lock);
253 /*
254 * During CAC period, data packets shouldn't be sent over the air so
255 * drop all the packets here
256 */
257 if (iface_context->device_mode == QDF_SAP_MODE ||
258 iface_context->device_mode == QDF_P2P_GO_MODE) {
259 if (ipa_ctx->dfs_cac_block_tx) {
260 ipa_free_skb(ipa_tx_desc);
261 qdf_spin_unlock_bh(&iface_context->interface_lock);
262 iface_context->stats.num_tx_cac_drop++;
263 wlan_ipa_wdi_rm_try_release(ipa_ctx);
264 return;
265 }
266 }
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800267
268 if (!osdev) {
269 ipa_free_skb(ipa_tx_desc);
270 iface_context->stats.num_tx_drop++;
271 qdf_spin_unlock_bh(&iface_context->interface_lock);
272 wlan_ipa_wdi_rm_try_release(ipa_ctx);
273 return;
274 }
Yun Parke74e6092018-04-27 11:36:34 -0700275 qdf_spin_unlock_bh(&iface_context->interface_lock);
276
277 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
278
hangtian127c9532019-01-12 13:29:07 +0800279 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Yun Parke74e6092018-04-27 11:36:34 -0700280
281 /* Store IPA Tx buffer ownership into SKB CB */
282 qdf_nbuf_ipa_owned_set(skb);
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800283
284 if (qdf_mem_smmu_s1_enabled(osdev)) {
285 status = qdf_nbuf_map(osdev, skb, QDF_DMA_TO_DEVICE);
286 if (QDF_IS_STATUS_SUCCESS(status)) {
287 paddr = qdf_nbuf_get_frag_paddr(skb, 0);
288 } else {
289 ipa_free_skb(ipa_tx_desc);
290 qdf_spin_lock_bh(&iface_context->interface_lock);
291 iface_context->stats.num_tx_drop++;
292 qdf_spin_unlock_bh(&iface_context->interface_lock);
293 wlan_ipa_wdi_rm_try_release(ipa_ctx);
294 return;
295 }
296 } else {
297 paddr = QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc);
298 }
299
Yun Parke74e6092018-04-27 11:36:34 -0700300 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
301 qdf_nbuf_mapped_paddr_set(skb,
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800302 paddr +
303 WLAN_IPA_WLAN_FRAG_HEADER +
304 WLAN_IPA_WLAN_IPA_HEADER);
Yun Parke74e6092018-04-27 11:36:34 -0700305 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
306 WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER;
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800307 } else {
308 qdf_nbuf_mapped_paddr_set(skb, paddr);
309 }
Yun Parke74e6092018-04-27 11:36:34 -0700310
311 qdf_spin_lock_bh(&ipa_ctx->q_lock);
312 /* get free Tx desc and assign ipa_tx_desc pointer */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +0530313 if (qdf_list_remove_front(&ipa_ctx->tx_desc_free_list,
314 (qdf_list_node_t **)&tx_desc) ==
Yun Parke74e6092018-04-27 11:36:34 -0700315 QDF_STATUS_SUCCESS) {
316 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
317 ipa_ctx->stats.num_tx_desc_q_cnt++;
318 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
319 /* Store Tx Desc index into SKB CB */
320 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
321 } else {
322 ipa_ctx->stats.num_tx_desc_error++;
323 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
Chaoli Zhoufd8d2822019-09-25 15:32:04 +0800324
325 if (qdf_mem_smmu_s1_enabled(osdev)) {
326 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
327 qdf_nbuf_mapped_paddr_set(skb, paddr);
328
329 qdf_nbuf_unmap(osdev, skb, QDF_DMA_TO_DEVICE);
330 }
331
Yun Parke74e6092018-04-27 11:36:34 -0700332 qdf_ipa_free_skb(ipa_tx_desc);
333 wlan_ipa_wdi_rm_try_release(ipa_ctx);
334 return;
335 }
336
337 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
338 (struct cdp_vdev *)iface_context->tl_context,
339 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
340 if (skb) {
341 qdf_nbuf_free(skb);
342 iface_context->stats.num_tx_err++;
343 return;
344 }
345
346 atomic_inc(&ipa_ctx->tx_ref_cnt);
347
348 iface_context->stats.num_tx++;
349}
350
jiad90b17252019-03-25 15:22:42 +0800351/**
352 * wlan_ipa_forward() - handle packet forwarding to wlan tx
353 * @ipa_ctx: pointer to ipa ipa context
354 * @iface_ctx: interface context
355 * @skb: data pointer
356 *
357 * if exception packet has set forward bit, copied new packet should be
358 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
359 * put into pm queue and tx procedure will be differed
360 *
361 * Return: None
362 */
363static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
364 struct wlan_ipa_iface_context *iface_ctx,
365 qdf_nbuf_t skb)
366{
367 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
368
369 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
370
371 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
372 qdf_nbuf_ipa_owned_set(skb);
373
374 /* WLAN subsystem is in suspend, put in queue */
375 if (ipa_ctx->suspended) {
376 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
377 ipa_info_rl("Tx in suspend, put in queue");
378 qdf_mem_zero(skb->cb, sizeof(skb->cb));
379 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
380 pm_tx_cb->exception = true;
381 pm_tx_cb->iface_context = iface_ctx;
382 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
383 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
384 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
385 ipa_ctx->stats.num_tx_queued++;
386 } else {
387 /* Resume, put packet into WLAN TX */
388 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
389
390 if (ipa_ctx->softap_xmit) {
391 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
392 ipa_err_rl("packet Tx fail");
393 ipa_ctx->stats.num_tx_fwd_err++;
394 } else {
395 ipa_ctx->stats.num_tx_fwd_ok++;
396 }
397 } else {
398 dev_kfree_skb_any(skb);
399 }
400 }
401}
402
403/**
404 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
405 * @ipa_ctx: pointer to IPA IPA struct
406 * @iface_ctx: ipa interface context
407 * @desc: Firmware descriptor
408 * @skb: Data buffer
409 *
410 * Return:
411 * WLAN_IPA_FORWARD_PKT_NONE
412 * WLAN_IPA_FORWARD_PKT_DISCARD
413 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
414 *
415 */
416
417static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
418 struct wlan_ipa_priv *ipa_ctx,
419 struct wlan_ipa_iface_context *iface_ctx,
420 uint8_t desc,
421 qdf_nbuf_t skb)
422{
423 int ret = WLAN_IPA_FORWARD_PKT_NONE;
424 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
425 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
426
427 if ((desc & FW_RX_DESC_FORWARD_M)) {
428 void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
429 iface_ctx->session_id);
Mohit Khannae1b86022019-04-12 10:04:57 -0700430 if (!vdev)
431 goto drop_pkt;
432
jiad90b17252019-03-25 15:22:42 +0800433 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
434 /* Drop the packet*/
435 ipa_ctx->stats.num_tx_fwd_err++;
Mohit Khannae1b86022019-04-12 10:04:57 -0700436 goto drop_pkt;
jiad90b17252019-03-25 15:22:42 +0800437 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700438
jiad90b17252019-03-25 15:22:42 +0800439 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
440 ipa_ctx->ipa_tx_forward++;
441
442 if ((desc & FW_RX_DESC_DISCARD_M)) {
443 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
444 ipa_ctx->ipa_rx_internal_drop_count++;
445 ipa_ctx->ipa_rx_discard++;
446 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
447 } else {
448 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
449
450 if (cloned_skb)
451 wlan_ipa_forward(ipa_ctx, iface_ctx,
452 cloned_skb);
453 else
454 ipa_err_rl("tx skb alloc failed");
455 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
456 }
457 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700458 return ret;
jiad90b17252019-03-25 15:22:42 +0800459
Mohit Khannae1b86022019-04-12 10:04:57 -0700460drop_pkt:
461 dev_kfree_skb_any(skb);
462 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
jiad90b17252019-03-25 15:22:42 +0800463 return ret;
464}
465
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530466#ifdef CONFIG_IPA_WDI_UNIFIED_API
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530467/*
468 * TODO: Get WDI version through FW capabilities
469 */
Manjunathappa Prakash458f6fe2019-05-13 18:33:01 -0700470#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
471 defined(QCA_WIFI_QCA6490)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530472static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
473{
474 ipa_ctx->wdi_version = IPA_WDI_3;
475}
476#elif defined(QCA_WIFI_3_0)
477static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
478{
479 ipa_ctx->wdi_version = IPA_WDI_2;
480}
481#else
482static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
483{
484 ipa_ctx->wdi_version = IPA_WDI_1;
485}
486#endif
487
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530488static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
489 qdf_device_t osdev)
490{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530491 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530492}
493
494static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
495 qdf_device_t osdev)
496{
497 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
498 int i;
499
500 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
501 qdf_mem_copy(&sys_in[i],
502 &ipa_ctx->sys_pipe[i].ipa_sys_params,
503 sizeof(qdf_ipa_sys_connect_params_t));
504
505 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
506 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
507 wlan_ipa_wdi_meter_notifier_cb,
508 ipa_ctx->config->desc_size,
509 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
510 &ipa_ctx->tx_pipe_handle,
511 &ipa_ctx->rx_pipe_handle,
512 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530513 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530514}
515
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530516#ifdef FEATURE_METERING
517/**
518 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
519 * @ipa_ctx: IPA context
520 * @in: IPA WDI in param
521 *
522 * Return: QDF_STATUS
523 */
524static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
525 qdf_ipa_wdi_init_in_params_t *in)
526{
527 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
528 wlan_ipa_wdi_meter_notifier_cb;
529}
530#else
531static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
532 qdf_ipa_wdi_init_in_params_t *in)
533{
534}
535#endif
536
537/**
538 * wlan_ipa_wdi_init() - IPA WDI init
539 * @ipa_ctx: IPA context
540 *
541 * Return: QDF_STATUS
542 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530543static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
544{
545 qdf_ipa_wdi_init_in_params_t in;
546 qdf_ipa_wdi_init_out_params_t out;
547 int ret;
548
549 ipa_ctx->uc_loaded = false;
550
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530551 qdf_mem_zero(&in, sizeof(in));
552 qdf_mem_zero(&out, sizeof(out));
553
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530554 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
555 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530556 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
557 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530558
559 ret = qdf_ipa_wdi_init(&in, &out);
560 if (ret) {
561 ipa_err("ipa_wdi_init failed with ret=%d", ret);
562 return QDF_STATUS_E_FAILURE;
563 }
564
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530565 ipa_ctx->over_gsi =
566 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
567 ipa_ctx->is_smmu_enabled =
568 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
569 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
570 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
571
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530572 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700573 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530574 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530575 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530576 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530577 return QDF_STATUS_E_BUSY;
578 }
579
580 return QDF_STATUS_SUCCESS;
581}
582
583static inline int wlan_ipa_wdi_cleanup(void)
584{
585 int ret;
586
587 ret = qdf_ipa_wdi_cleanup();
588 if (ret)
589 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
590 return ret;
591}
592
593static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
594 struct ipa_sys_connect_params *sys,
595 uint32_t *handle)
596{
597 return 0;
598}
599
600static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
601 uint32_t handle)
602{
603 return 0;
604}
605
Yun Parke74e6092018-04-27 11:36:34 -0700606/**
607 * wlan_ipa_pm_flush() - flush queued packets
608 * @work: pointer to the scheduled work
609 *
610 * Called during PM resume to send packets to TL which were queued
611 * while host was in the process of suspending.
612 *
613 * Return: None
614 */
615static void wlan_ipa_pm_flush(void *data)
616{
617 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
618 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
619 qdf_nbuf_t skb;
620 uint32_t dequeued = 0;
621
622 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
623 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
624 NULL)) {
625 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
626
627 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
628 dequeued++;
629
jiadab8cea02018-05-24 09:16:14 +0800630 if (pm_tx_cb->exception) {
631 if (ipa_ctx->softap_xmit &&
632 pm_tx_cb->iface_context->dev) {
633 ipa_ctx->softap_xmit(skb,
634 pm_tx_cb->iface_context->dev);
635 ipa_ctx->stats.num_tx_fwd_ok++;
636 } else {
637 dev_kfree_skb_any(skb);
638 }
639 } else {
640 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
641 pm_tx_cb->ipa_tx_desc);
642 }
Yun Parke74e6092018-04-27 11:36:34 -0700643
644 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
645 }
646 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
647
648 ipa_ctx->stats.num_tx_dequeued += dequeued;
649 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
650 ipa_ctx->stats.num_max_pm_queue = dequeued;
651}
652
jiadae9959f2018-05-08 11:19:07 +0800653int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
654{
655 if (!num_buf) {
656 ipa_info("No buffers to map/unmap");
657 return 0;
658 }
659
660 if (map)
661 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
662 else
663 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
664}
665
Jia Ding70deca72019-07-24 18:18:57 +0800666#ifdef MDM_PLATFORM
667/**
668 * is_rx_dest_bridge_dev() - is RX skb bridge device terminated
669 * @iface_ctx: pointer to WLAN IPA interface context
670 * @nbuf: skb buffer
671 *
672 * Check if skb is destined for bridge device, where SAP is a bridge
673 * port of it.
674 *
675 * FIXME: If there's a BH lockless API to check if destination MAC
676 * address is a valid peer, this check can be deleted. Currently
677 * dp_find_peer_by_addr() is used to check if destination MAC
678 * is a valid peer. Since WLAN IPA RX is in process context,
679 * qdf_spin_lock_bh in dp_find_peer_by_addr() turns to spin_lock_bh
680 * and this BH lock hurts netif_rx.
681 *
682 * Return: true/false
683 */
684static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
685 qdf_nbuf_t nbuf)
686{
687 qdf_netdev_t master_ndev;
688 qdf_netdev_t ndev;
689 struct ethhdr *eh;
690 uint8_t da_is_bcmc;
691 bool ret;
692
693 if (iface_ctx->device_mode != QDF_SAP_MODE)
694 return false;
695
696 /*
697 * WDI 3.0 skb->cb[] info from IPA driver
698 * skb->cb[0] = vdev_id
699 * skb->cb[1].bit#1 = da_is_bcmc
700 */
701 da_is_bcmc = ((uint8_t)nbuf->cb[1]) & 0x2;
702 if (da_is_bcmc)
703 return false;
704
705 ndev = iface_ctx->dev;
706 if (!ndev)
707 return false;
708
709 if (!netif_is_bridge_port(ndev))
710 return false;
711
712 rcu_read_lock();
713
714 master_ndev = netdev_master_upper_dev_get_rcu(ndev);
715 if (!master_ndev) {
716 ret = false;
717 goto out;
718 }
719
720 eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
721 if (qdf_mem_cmp(eh->h_dest, master_ndev->dev_addr, QDF_MAC_ADDR_SIZE)) {
722 ret = false;
723 goto out;
724 }
725
726 ret = true;
727
728out:
729 rcu_read_unlock();
730 return ret;
731}
732#else /* !MDM_PLATFORM */
733static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
734 qdf_nbuf_t nbuf)
735{
736 return false;
737}
738#endif /* MDM_PLATFORM */
739
jiad90b17252019-03-25 15:22:42 +0800740static enum wlan_ipa_forward_type
741wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
742 struct wlan_ipa_iface_context *iface_ctx,
743 qdf_nbuf_t nbuf)
744{
745 uint8_t fw_desc = 0;
746 bool fwd_success;
747 int ret;
748
749 /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
750 if (ipa_ctx->wdi_version != IPA_WDI_3) {
751 fw_desc = (uint8_t)nbuf->cb[1];
752 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
753 nbuf);
754 }
755
Jia Ding70deca72019-07-24 18:18:57 +0800756 if (is_rx_dest_bridge_dev(iface_ctx, nbuf)) {
757 fwd_success = 0;
758 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
759 goto exit;
760 }
761
jiad90b17252019-03-25 15:22:42 +0800762 if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
763 nbuf, &fwd_success)) {
764 ipa_ctx->ipa_rx_internal_drop_count++;
765 ipa_ctx->ipa_rx_discard++;
766
767 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
768 } else {
769 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
770 }
771
Jia Ding70deca72019-07-24 18:18:57 +0800772exit:
jiad90b17252019-03-25 15:22:42 +0800773 if (fwd_success)
774 ipa_ctx->stats.num_tx_fwd_ok++;
775 else
776 ipa_ctx->stats.num_tx_fwd_err++;
777
778 return ret;
779}
780
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530781#else /* CONFIG_IPA_WDI_UNIFIED_API */
782
783static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
784{
785}
786
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530787static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
788 qdf_device_t osdev)
789{
790 return qdf_mem_smmu_s1_enabled(osdev);
791}
792
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530793static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
794 qdf_device_t osdev)
795{
796 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
797 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
798 wlan_ipa_wdi_meter_notifier_cb,
799 ipa_ctx->config->desc_size,
800 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
801 &ipa_ctx->tx_pipe_handle,
802 &ipa_ctx->rx_pipe_handle);
803}
804
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530805static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
806{
807 struct ipa_wdi_uc_ready_params uc_ready_param;
808
809 ipa_ctx->uc_loaded = false;
810 uc_ready_param.priv = (void *)ipa_ctx;
811 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
812 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
813 ipa_info("UC Ready CB register fail");
814 return QDF_STATUS_E_FAILURE;
815 }
816
817 if (true == uc_ready_param.is_uC_ready) {
818 ipa_info("UC Ready");
819 ipa_ctx->uc_loaded = true;
820 } else {
821 return QDF_STATUS_E_BUSY;
822 }
823
824 return QDF_STATUS_SUCCESS;
825}
826
827static inline int wlan_ipa_wdi_cleanup(void)
828{
829 int ret;
830
831 ret = qdf_ipa_uc_dereg_rdyCB();
832 if (ret)
833 ipa_info("UC Ready CB deregister fail");
834 return ret;
835}
836
837static inline int wlan_ipa_wdi_setup_sys_pipe(
838 struct wlan_ipa_priv *ipa_ctx,
839 struct ipa_sys_connect_params *sys, uint32_t *handle)
840{
841 return qdf_ipa_setup_sys_pipe(sys, handle);
842}
843
844static inline int wlan_ipa_wdi_teardown_sys_pipe(
845 struct wlan_ipa_priv *ipa_ctx,
846 uint32_t handle)
847{
848 return qdf_ipa_teardown_sys_pipe(handle);
849}
850
Yun Parke74e6092018-04-27 11:36:34 -0700851/**
852 * wlan_ipa_pm_flush() - flush queued packets
853 * @work: pointer to the scheduled work
854 *
855 * Called during PM resume to send packets to TL which were queued
856 * while host was in the process of suspending.
857 *
858 * Return: None
859 */
860static void wlan_ipa_pm_flush(void *data)
861{
862 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
863 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
864 qdf_nbuf_t skb;
865 uint32_t dequeued = 0;
866
867 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
868 WIFI_POWER_EVENT_WAKELOCK_IPA);
869 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
870 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
871 NULL)) {
872 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
873
874 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
875 dequeued++;
876
jiadab8cea02018-05-24 09:16:14 +0800877 if (pm_tx_cb->exception) {
878 if (ipa_ctx->softap_xmit &&
879 pm_tx_cb->iface_context->dev) {
880 ipa_ctx->softap_xmit(skb,
881 pm_tx_cb->iface_context->dev);
882 ipa_ctx->stats.num_tx_fwd_ok++;
883 } else {
884 dev_kfree_skb_any(skb);
885 }
886 } else {
887 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
888 pm_tx_cb->ipa_tx_desc);
889 }
Yun Parke74e6092018-04-27 11:36:34 -0700890
891 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
892 }
893 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
894 qdf_wake_lock_release(&ipa_ctx->wake_lock,
895 WIFI_POWER_EVENT_WAKELOCK_IPA);
896
897 ipa_ctx->stats.num_tx_dequeued += dequeued;
898 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
899 ipa_ctx->stats.num_max_pm_queue = dequeued;
900}
901
jiadae9959f2018-05-08 11:19:07 +0800902int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
903{
904 if (!num_buf) {
905 ipa_info("No buffers to map/unmap");
906 return 0;
907 }
908
909 if (map)
910 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
911 else
912 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
913}
914
jiad90b17252019-03-25 15:22:42 +0800915static enum wlan_ipa_forward_type
916wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
917 struct wlan_ipa_iface_context *iface_ctx,
918 qdf_nbuf_t nbuf)
919{
920 uint8_t fw_desc;
921
922 fw_desc = (uint8_t)nbuf->cb[1];
923
924 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
925}
926
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530927#endif /* CONFIG_IPA_WDI_UNIFIED_API */
928
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530929/**
930 * wlan_ipa_send_skb_to_network() - Send skb to kernel
931 * @skb: network buffer
932 * @iface_ctx: IPA interface context
933 *
934 * Called when a network buffer is received which should not be routed
935 * to the IPA module.
936 *
937 * Return: None
938 */
939static void
940wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
941 struct wlan_ipa_iface_context *iface_ctx)
942{
943 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
944
945 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800946 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530947 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800948 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530949 return;
950 }
951
952 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
953
954 if (ipa_ctx->send_to_nw)
955 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
956
957 ipa_ctx->ipa_rx_net_send_count++;
958}
959
960/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530961 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530962 * @priv: pointer to private data registered with IPA (we register a
963 * pointer to the global IPA context)
964 * @evt: the IPA event which triggered the callback
965 * @data: data associated with the event
966 *
967 * Return: None
968 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530969static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
970 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530971{
972 struct wlan_ipa_priv *ipa_ctx = NULL;
973 qdf_nbuf_t skb;
974 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700975 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530976 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530977
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530978 ipa_ctx = (struct wlan_ipa_priv *)priv;
979 if (!ipa_ctx) {
980 if (evt == IPA_RECEIVE) {
981 skb = (qdf_nbuf_t)data;
982 dev_kfree_skb_any(skb);
983 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530984 return;
985 }
986
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530987 switch (evt) {
988 case IPA_RECEIVE:
989 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530990 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
991 session_id = (uint8_t)skb->cb[0];
992 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530993 } else {
994 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
995 }
996 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700997 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
998 iface_id, session_id, (uint8_t)skb->cb[1],
999 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301000 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +08001001 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301002 return;
1003 }
1004
1005 iface_context = &ipa_ctx->iface_context[iface_id];
1006 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +08001007 ipa_err_rl("TL context of iface_id %u is NULL",
1008 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301009 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +08001010 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301011 return;
1012 }
1013
1014 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1015 ipa_ctx->stats.num_rx_excep++;
1016 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
1017 } else {
1018 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
1019 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301020 iface_context->stats.num_rx_ipa_excep++;
1021
1022 /* Disable to forward Intra-BSS Rx packets when
1023 * ap_isolate=1 in hostapd.conf
1024 */
1025 if (!ipa_ctx->ap_intrabss_fwd) {
1026 /*
1027 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
1028 * all Rx packets to IPA uC, which need to be forwarded
1029 * to other interface.
1030 * And, IPA driver will send back to WLAN host driver
1031 * through exception pipe with fw_desc field set by FW.
1032 * Here we are checking fw_desc field for FORWARD bit
1033 * set, and forward to Tx. Then copy to kernel stack
1034 * only when DISCARD bit is not set.
1035 */
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301036 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
jiad90b17252019-03-25 15:22:42 +08001037 wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
1038 skb))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301039 break;
1040 } else {
jiadf3ecc752018-07-05 14:36:03 +08001041 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301042 }
1043
1044 wlan_ipa_send_skb_to_network(skb, iface_context);
1045 break;
1046
1047 default:
jiadf3ecc752018-07-05 14:36:03 +08001048 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301049 return;
1050 }
1051}
1052
jiad7bac1ef2019-07-03 11:30:24 +08001053#ifndef MDM_PLATFORM
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301054/**
jitiphilfdcaaba2018-09-03 16:19:52 +05301055 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
1056 * @priv: pointer to private data registered with IPA (we register a
1057 * pointer to the global IPA context)
1058 * @evt: the IPA event which triggered the callback
1059 * @data: data associated with the event
1060 *
1061 * Return: None
1062 */
1063static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1064 unsigned long data)
1065{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001066 struct qdf_op_sync *op_sync;
1067
1068 if (qdf_op_protect(&op_sync)) {
1069 if (evt == IPA_RECEIVE) {
1070 struct wlan_ipa_priv *ipa_ctx = priv;
1071 qdf_nbuf_t skb = (qdf_nbuf_t)data;
1072
1073 ipa_ctx->ipa_rx_internal_drop_count++;
1074 dev_kfree_skb_any(skb);
1075 }
1076
1077 return;
1078 }
1079
jitiphilfdcaaba2018-09-03 16:19:52 +05301080 __wlan_ipa_w2i_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001081
1082 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301083}
jiad7bac1ef2019-07-03 11:30:24 +08001084#else /* MDM_PLATFORM */
1085static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1086 unsigned long data)
1087{
1088 __wlan_ipa_w2i_cb(priv, evt, data);
1089}
1090#endif /* MDM_PLATFORM */
jitiphilfdcaaba2018-09-03 16:19:52 +05301091
1092/**
1093 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301094 * @priv: pointer to private data registered with IPA (we register a
1095 * pointer to the interface-specific IPA context)
1096 * @evt: the IPA event which triggered the callback
1097 * @data: data associated with the event
1098 *
1099 * Return: None
1100 */
jitiphilfdcaaba2018-09-03 16:19:52 +05301101static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1102 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301103{
1104 struct wlan_ipa_priv *ipa_ctx = NULL;
1105 qdf_ipa_rx_data_t *ipa_tx_desc;
1106 struct wlan_ipa_iface_context *iface_context;
1107 qdf_nbuf_t skb;
1108 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
1109
1110 iface_context = (struct wlan_ipa_iface_context *)priv;
1111 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1112 ipa_ctx = iface_context->ipa_ctx;
1113
1114 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +08001115 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301116 ipa_free_skb(ipa_tx_desc);
1117 iface_context->stats.num_tx_drop++;
1118 return;
1119 }
1120
1121 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
1122
1123 /*
1124 * If PROD resource is not requested here then there may be cases where
1125 * IPA hardware may be clocked down because of not having proper
1126 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
1127 * workaround to request PROD resource while data is going over CONS
1128 * pipe to prevent the IPA hardware clockdown.
1129 */
1130 wlan_ipa_wdi_rm_request(ipa_ctx);
1131
1132 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1133 /*
1134 * If host is still suspended then queue the packets and these will be
1135 * drained later when resume completes. When packet is arrived here and
1136 * host is suspended, this means that there is already resume is in
1137 * progress.
1138 */
1139 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +08001140 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301141 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
1142 pm_tx_cb->iface_context = iface_context;
1143 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
1144 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
1145 ipa_ctx->stats.num_tx_queued++;
1146
1147 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1148 return;
1149 }
1150
1151 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1152
1153 /*
1154 * If we are here means, host is not suspended, wait for the work queue
1155 * to finish.
1156 */
1157 qdf_flush_work(&ipa_ctx->pm_work);
1158
1159 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
1160}
1161
jitiphilfdcaaba2018-09-03 16:19:52 +05301162/**
1163 * wlan_ipa_i2w_cb() - IPA to WLAN callback
1164 * @priv: pointer to private data registered with IPA (we register a
1165 * pointer to the interface-specific IPA context)
1166 * @evt: the IPA event which triggered the callback
1167 * @data: data associated with the event
1168 *
1169 * Return: None
1170 */
1171static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1172 unsigned long data)
1173{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001174 struct qdf_op_sync *op_sync;
1175
1176 if (qdf_op_protect(&op_sync)) {
1177 qdf_ipa_rx_data_t *ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1178 struct wlan_ipa_iface_context *iface_context = priv;
1179
1180 ipa_free_skb(ipa_tx_desc);
1181 iface_context->stats.num_tx_drop++;
1182
1183 return;
1184 }
1185
jitiphilfdcaaba2018-09-03 16:19:52 +05301186 __wlan_ipa_i2w_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001187
1188 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301189}
1190
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301191QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
1192{
1193 /*
1194 * Check if IPA is ready for suspend, If we are here means, there is
1195 * high chance that suspend would go through but just to avoid any race
1196 * condition after suspend started, these checks are conducted before
1197 * allowing to suspend.
1198 */
1199 if (atomic_read(&ipa_ctx->tx_ref_cnt))
1200 return QDF_STATUS_E_AGAIN;
1201
Yun Parke74e6092018-04-27 11:36:34 -07001202 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301203 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301204
1205 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1206 ipa_ctx->suspended = true;
1207 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1208
Alok Kumare888e802019-09-23 18:31:09 +05301209 if (ipa_ctx->config->ipa_force_voting &&
1210 !ipa_ctx->ipa_pipes_down)
1211 wlan_ipa_set_perf_level(ipa_ctx,
1212 ipa_ctx->config->bus_bw_high,
1213 ipa_ctx->config->bus_bw_high);
1214
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301215 return QDF_STATUS_SUCCESS;
1216}
1217
1218QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
1219{
1220 qdf_sched_work(0, &ipa_ctx->pm_work);
1221
1222 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1223 ipa_ctx->suspended = false;
1224 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1225
1226 return QDF_STATUS_SUCCESS;
1227}
1228
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301229QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1230{
1231 int result;
1232
1233 ipa_debug("enter");
1234
1235 if (!ipa_ctx->ipa_pipes_down) {
1236 /*
1237 * IPA WDI Pipes are already activated due to
1238 * rm deferred resources grant
1239 */
1240 ipa_warn("IPA WDI Pipes are already activated");
1241 goto end;
1242 }
1243
1244 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1245 ipa_ctx->dp_pdev);
1246 if (result) {
1247 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1248 return QDF_STATUS_E_FAILURE;
1249 }
1250
1251 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1252 ipa_ctx->ipa_pipes_down = false;
1253
1254 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1255 ipa_ctx->dp_pdev);
1256
1257end:
1258 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1259
1260 return QDF_STATUS_SUCCESS;
1261}
1262
1263QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1264{
1265 int result;
1266
1267 ipa_debug("enter");
1268
1269 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301270 ipa_warn("IPA WDI Pipes are already deactivated");
1271 goto end;
1272 }
1273
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301274 qdf_spin_lock_bh(&ipa_ctx->pipes_down_lock);
1275 if (ipa_ctx->pipes_down_in_progress || ipa_ctx->ipa_pipes_down) {
1276 ipa_warn("IPA WDI Pipes down already in progress");
1277 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1278 return QDF_STATUS_E_ALREADY;
1279 }
1280 ipa_ctx->pipes_down_in_progress = true;
1281 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1282
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301283 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1284 ipa_ctx->dp_pdev);
1285
1286 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1287 ipa_ctx->dp_pdev);
1288 if (result) {
1289 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301290 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301291 return QDF_STATUS_E_FAILURE;
1292 }
1293
1294 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301295 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301296
1297end:
1298 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1299
1300 return QDF_STATUS_SUCCESS;
1301}
1302
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301303/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301304 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1305 * @ipa_ctx: Global IPA IPA context
1306 * @sta_add: Should station be added
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301307 * @mac_addr: mac address of station being queried
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301308 *
1309 * Return: true if the station was found
1310 */
1311static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301312 bool sta_add,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301313 uint8_t *mac_addr)
1314{
1315 bool sta_found = false;
1316 uint8_t idx;
1317
1318 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1319 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301320 (qdf_is_macaddr_equal(
1321 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1322 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301323 sta_found = true;
1324 break;
1325 }
1326 }
1327 if (sta_add && sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301328 ipa_err("STA already exist, cannot add: " QDF_MAC_ADDR_STR,
1329 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301330 return sta_found;
1331 }
1332 if (sta_add) {
1333 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1334 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1335 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301336 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1337 mac_addr, mac_addr,
1338 QDF_NET_ETH_LEN);
1339 return sta_found;
1340 }
1341 }
1342 }
1343 if (!sta_add && !sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301344 ipa_err("STA does not exist, cannot delete: " QDF_MAC_ADDR_STR,
1345 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301346 return sta_found;
1347 }
1348 if (!sta_add) {
1349 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1350 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301351 (qdf_is_macaddr_equal(
1352 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1353 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301354 ipa_ctx->assoc_stas_map[idx].is_reserved =
1355 false;
hangtian127c9532019-01-12 13:29:07 +08001356 qdf_mem_zero(
1357 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1358 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301359 return sta_found;
1360 }
1361 }
1362 }
1363
1364 return sta_found;
1365}
1366
1367/**
1368 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1369 * @ipa_ctx: IPA context
1370 * @session_id: Session ID
1371 *
1372 * Return: None
1373 */
1374static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1375 uint8_t session_id)
1376{
1377 struct wlan_ipa_iface_context *iface_ctx;
1378 int i;
1379
1380 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1381 iface_ctx = &ipa_ctx->iface_context[i];
1382 if (iface_ctx->session_id == session_id)
1383 break;
1384 }
1385
1386 return i;
1387}
1388
1389/**
1390 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1391 * @iface_context: interface-specific IPA context
1392 *
1393 * Return: None
1394 */
1395static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1396{
1397 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1398
1399 ipa_debug("enter");
1400
1401 if (!iface_context->tl_context)
1402 return;
1403
1404 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1405 iface_context->dev->name,
1406 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1407
1408 qdf_spin_lock_bh(&iface_context->interface_lock);
1409 iface_context->tl_context = NULL;
1410 iface_context->dev = NULL;
1411 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1412 iface_context->session_id = WLAN_IPA_MAX_SESSION;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301413 qdf_spin_unlock_bh(&iface_context->interface_lock);
1414 iface_context->ifa_address = 0;
1415 if (!iface_context->ipa_ctx->num_iface) {
1416 ipa_err("NUM INTF 0, Invalid");
1417 QDF_ASSERT(0);
1418 }
1419 iface_context->ipa_ctx->num_iface--;
1420 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1421}
1422
1423/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301424 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1425 * @skb: packet buffer which was transmitted
1426 *
1427 * Return: None
1428 */
1429static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1430{
1431 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1432 qdf_ipa_rx_data_t *ipa_tx_desc;
1433 struct wlan_ipa_tx_desc *tx_desc;
1434 uint16_t id;
Chaoli Zhoufd8d2822019-09-25 15:32:04 +08001435 struct wlan_objmgr_pdev *pdev;
1436 struct wlan_objmgr_psoc *psoc;
1437 qdf_device_t osdev;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301438
1439 if (!qdf_nbuf_ipa_owned_get(skb)) {
1440 dev_kfree_skb_any(skb);
1441 return;
1442 }
1443
Chaoli Zhoufd8d2822019-09-25 15:32:04 +08001444 if (!ipa_ctx)
1445 return;
1446 pdev = ipa_ctx->pdev;
1447 psoc = wlan_pdev_get_psoc(pdev);
1448 osdev = wlan_psoc_get_qdf_dev(psoc);
1449
1450 if (osdev && qdf_mem_smmu_s1_enabled(osdev)) {
1451 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
1452 qdf_dma_addr_t paddr = QDF_NBUF_CB_PADDR(skb);
1453
1454 qdf_nbuf_mapped_paddr_set(skb,
1455 paddr -
1456 WLAN_IPA_WLAN_FRAG_HEADER -
1457 WLAN_IPA_WLAN_IPA_HEADER);
1458 }
1459
1460 qdf_nbuf_unmap(osdev, skb, QDF_DMA_TO_DEVICE);
1461 }
1462
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301463 /* Get Tx desc pointer from SKB CB */
1464 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1465 tx_desc = &ipa_ctx->tx_desc_pool[id];
1466 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1467
1468 /* Return Tx Desc to IPA */
1469 qdf_ipa_free_skb(ipa_tx_desc);
1470
1471 /* Return to free tx desc list */
1472 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1473 tx_desc->ipa_tx_desc_ptr = NULL;
1474 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1475 ipa_ctx->stats.num_tx_desc_q_cnt--;
1476 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1477
1478 ipa_ctx->stats.num_tx_comp_cnt++;
1479
1480 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1481
1482 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1483}
1484
1485/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301486 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1487 * @ipa_ctx: IPA IPA global context
1488 * @net_dev: Interface net device
1489 * @device_mode: Net interface device mode
1490 * @adapter: Interface upon which IPA is being setup
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301491 * @session_id: Station ID of the API instance
1492 *
1493 * Return: QDF STATUS
1494 */
1495static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1496 qdf_netdev_t net_dev,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301497 uint8_t device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301498 uint8_t session_id)
1499{
1500 struct wlan_ipa_iface_context *iface_context = NULL;
1501 void *tl_context = NULL;
1502 int i;
1503 QDF_STATUS status;
1504
1505 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1506 * channel change indication. Since these indications are sent by lower
1507 * layer as SAP updates and IPA doesn't have to do anything for these
1508 * updates so ignoring!
1509 */
1510 if (device_mode == QDF_SAP_MODE) {
1511 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1512 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001513 if (iface_context->dev == net_dev) {
1514 ipa_debug("found iface %u device_mode %u",
1515 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301516 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001517 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301518 }
1519 }
1520
Yun Park21ec4902018-04-24 12:11:01 -07001521 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1522 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1523 status = QDF_STATUS_E_NOMEM;
1524 QDF_ASSERT(0);
1525 goto end;
1526 }
1527
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301528 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001529 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301530 iface_context = &(ipa_ctx->iface_context[i]);
1531 break;
1532 }
1533 }
1534
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001535 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301536 ipa_err("All the IPA interfaces are in use");
1537 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001538 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301539 goto end;
1540 }
1541
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301542 tl_context = (void *)cdp_get_vdev_from_vdev_id(ipa_ctx->dp_soc,
1543 ipa_ctx->dp_pdev,
1544 session_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001545 if (!tl_context) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301546 ipa_err("Not able to get TL context session_id: %d",
1547 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301548 status = QDF_STATUS_E_INVAL;
1549 goto end;
1550 }
1551
1552 iface_context->tl_context = tl_context;
1553 iface_context->dev = net_dev;
1554 iface_context->device_mode = device_mode;
1555 iface_context->session_id = session_id;
1556
1557 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1558 net_dev->dev_addr,
1559 iface_context->prod_client,
1560 iface_context->cons_client,
1561 session_id,
1562 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1563 if (status != QDF_STATUS_SUCCESS)
1564 goto end;
1565
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301566 /* Register IPA Tx desc free callback */
1567 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1568
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301569 ipa_ctx->num_iface++;
1570
1571 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1572
1573 return status;
1574
1575end:
1576 if (iface_context)
1577 wlan_ipa_cleanup_iface(iface_context);
1578
1579 return status;
1580}
1581
Manjunathappa Prakash458f6fe2019-05-13 18:33:01 -07001582#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
1583 defined(QCA_WIFI_QCA6490)
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301584/**
1585 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1586 * @ipa_ctx: IPA context
1587 *
1588 * Return: QDF STATUS
1589 */
1590static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1591{
1592 ipa_debug("enter");
1593
1594 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1595 ipa_err("IPA WDI Pipe activation failed");
1596 return QDF_STATUS_E_BUSY;
1597 }
1598
1599 ipa_debug("exit");
1600
1601 return QDF_STATUS_SUCCESS;
1602}
1603
1604/**
1605 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1606 * @ipa_ctx: IPA context
1607 *
1608 * Return: None
1609 */
1610static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1611{
1612 ipa_debug("enter");
1613
1614 wlan_ipa_uc_disable_pipes(ipa_ctx);
1615
1616 ipa_debug("exit: IPA WDI Pipes deactivated");
1617}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301618
1619bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1620{
1621 return !ipa_ctx->ipa_pipes_down;
1622}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301623#else
1624
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301625/**
1626 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1627 * @ipa_ctx: IPA context
1628 *
1629 * Return: QDF STATUS
1630 */
1631static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1632{
1633 ipa_debug("enter");
1634
1635 ipa_ctx->activated_fw_pipe = 0;
1636 ipa_ctx->resource_loading = true;
1637
1638 /* If RM feature enabled
1639 * Request PROD Resource first
1640 * PROD resource may return sync or async manners
1641 */
1642 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001643 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1644 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301645 /* RM PROD request sync return
1646 * enable pipe immediately
1647 */
1648 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1649 ipa_err("IPA WDI Pipe activation failed");
1650 ipa_ctx->resource_loading = false;
1651 return QDF_STATUS_E_BUSY;
1652 }
1653 } else {
1654 ipa_err("IPA WDI Pipe activation deferred");
1655 }
1656 } else {
1657 /* RM Disabled
1658 * Just enabled all the PIPEs
1659 */
1660 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1661 ipa_err("IPA WDI Pipe activation failed");
1662 ipa_ctx->resource_loading = false;
1663 return QDF_STATUS_E_BUSY;
1664 }
1665 ipa_ctx->resource_loading = false;
1666 }
1667
1668 ipa_debug("exit");
1669
1670 return QDF_STATUS_SUCCESS;
1671}
1672
1673/**
1674 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1675 * @ipa_ctx: IPA context
1676 *
1677 * Return: None
1678 */
1679static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1680{
1681 ipa_debug("enter");
1682
1683 ipa_ctx->resource_unloading = true;
1684 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1685 ipa_info("Disable FW RX PIPE");
1686 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301687
1688 ipa_debug("exit: IPA WDI Pipes deactivated");
1689}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301690
1691bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1692{
1693 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1694}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301695#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301696
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301697static inline
1698bool wlan_sap_no_client_connected(struct wlan_ipa_priv *ipa_ctx)
1699{
1700 return !(ipa_ctx->sap_num_connected_sta);
1701}
1702
1703static inline
1704bool wlan_sta_is_connected(struct wlan_ipa_priv *ipa_ctx)
1705{
1706 return ipa_ctx->sta_connected;
1707}
1708
1709static inline
1710bool wlan_ipa_uc_is_loaded(struct wlan_ipa_priv *ipa_ctx)
1711{
1712 return ipa_ctx->uc_loaded;
1713}
1714
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301715/**
1716 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1717 * @ipa_ctx: global IPA context
1718 * @offload_type: MCC or SCC
1719 * @session_id: Session Id
1720 * @enable: TX offload enable or disable
1721 *
1722 * Return: none
1723 */
1724static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1725 uint32_t offload_type,
1726 uint8_t session_id,
1727 bool enable)
1728{
1729
1730 struct ipa_uc_offload_control_params req = {0};
1731
1732 if (session_id >= WLAN_IPA_MAX_SESSION) {
1733 ipa_err("invalid session id: %d", session_id);
1734 return;
1735 }
1736
1737 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301738 ipa_info("IPA offload status is already set");
1739 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301740 offload_type, session_id, enable);
1741 return;
1742 }
1743
1744 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1745 offload_type, session_id, enable);
1746
1747 req.offload_type = offload_type;
1748 req.vdev_id = session_id;
1749 req.enable = enable;
1750
1751 if (QDF_STATUS_SUCCESS !=
1752 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1753 ipa_err("Fail to enable IPA offload");
1754 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1755 offload_type, session_id, enable);
1756 } else {
1757 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1758 }
1759}
1760
1761/**
1762 * __wlan_ipa_wlan_evt() - IPA event handler
1763 * @net_dev: Interface net device
1764 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301765 * @session_id: session id for the event
1766 * @type: event enum of type ipa_wlan_event
1767 * @mac_address: MAC address associated with the event
1768 *
1769 * This function is meant to be called from within wlan_ipa_ctx.c
1770 *
1771 * Return: QDF STATUS
1772 */
1773static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301774 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301775 qdf_ipa_wlan_event type,
1776 uint8_t *mac_addr)
1777{
1778 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1779 struct wlan_ipa_iface_context *iface_ctx = NULL;
1780 qdf_ipa_msg_meta_t meta;
1781 qdf_ipa_wlan_msg_t *msg;
1782 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1783 int i;
1784 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001785 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301786 struct wlan_objmgr_pdev *pdev;
1787 struct wlan_objmgr_psoc *psoc;
1788 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301789
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301790 ipa_debug("%s: EVT: %d, MAC: %pM, session_id: %u",
1791 net_dev->name, type, mac_addr, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301792
1793 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1794 return QDF_STATUS_E_INVAL;
1795
1796 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1797 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1798 (device_mode != QDF_SAP_MODE)) {
1799 return QDF_STATUS_SUCCESS;
1800 }
1801
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301802 pdev = ipa_ctx->pdev;
1803 psoc = wlan_pdev_get_psoc(pdev);
1804 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1805 WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301806 QDF_BUG(session_id < WLAN_IPA_MAX_SESSION);
1807
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301808 if (vdev)
1809 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301810 else
1811 ipa_err("vdev is NULL, session_id: %u", session_id);
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301812
Ryan Hsub5783cf2018-05-14 12:13:15 -07001813 if (ipa_ctx->sta_connected) {
1814 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1815 if (iface_ctx)
1816 sta_session_id = iface_ctx->session_id;
1817 else
1818 ipa_err("sta iface_ctx is NULL");
1819 }
1820
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301821 /*
1822 * During IPA UC resource loading/unloading new events can be issued.
1823 */
1824 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1825 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1826 unsigned int pending_event_count;
1827 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1828
1829 ipa_info("Event:%d IPA resource %s inprogress", type,
1830 ipa_ctx->resource_loading ?
1831 "load" : "unload");
1832
1833 /* Wait until completion of the long/unloading */
1834 status = qdf_wait_for_event_completion(
1835 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001836 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301837 if (status != QDF_STATUS_SUCCESS) {
1838 /*
1839 * If timed out, store the events separately and
1840 * handle them later.
1841 */
1842 ipa_info("IPA resource %s timed out",
1843 ipa_ctx->resource_loading ?
1844 "load" : "unload");
1845
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301846 if (type == QDF_IPA_AP_DISCONNECT) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301847 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1848 SIR_AP_RX_DATA_OFFLOAD,
1849 session_id, false);
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301850 } else if (type == QDF_IPA_CLIENT_CONNECT_EX &&
1851 wlan_sap_no_client_connected(ipa_ctx)) {
1852 if (wlan_sta_is_connected(ipa_ctx) &&
1853 wlan_ipa_uc_is_loaded(ipa_ctx) &&
1854 wlan_ipa_uc_sta_is_enabled(ipa_ctx->
1855 config) &&
1856 !wlan_ipa_is_sta_only_offload_enabled()) {
1857 wlan_ipa_uc_offload_enable_disable(
1858 ipa_ctx,
1859 SIR_STA_RX_DATA_OFFLOAD,
1860 sta_session_id, true);
1861 }
1862 }
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301863
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301864 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1865
1866 pending_event_count =
1867 qdf_list_size(&ipa_ctx->pending_event);
1868 if (pending_event_count >=
1869 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1870 ipa_info("Reached max pending evt count");
1871 qdf_list_remove_front(
1872 &ipa_ctx->pending_event,
1873 (qdf_list_node_t **)&pending_event);
1874 } else {
1875 pending_event =
1876 (struct wlan_ipa_uc_pending_event *)
1877 qdf_mem_malloc(sizeof(
1878 struct wlan_ipa_uc_pending_event));
1879 }
1880
1881 if (!pending_event) {
1882 ipa_err("Pending event memory alloc fail");
1883 qdf_mutex_release(&ipa_ctx->ipa_lock);
1884 return QDF_STATUS_E_NOMEM;
1885 }
1886
1887 pending_event->net_dev = net_dev;
1888 pending_event->device_mode = device_mode;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301889 pending_event->session_id = session_id;
1890 pending_event->type = type;
1891 pending_event->is_loading = ipa_ctx->resource_loading;
1892 qdf_mem_copy(pending_event->mac_addr,
1893 mac_addr, QDF_MAC_ADDR_SIZE);
1894 qdf_list_insert_back(&ipa_ctx->pending_event,
1895 &pending_event->node);
1896
1897 qdf_mutex_release(&ipa_ctx->ipa_lock);
1898
Yun Park21ec4902018-04-24 12:11:01 -07001899 /* Cleanup interface */
1900 if (type == QDF_IPA_STA_DISCONNECT ||
1901 type == QDF_IPA_AP_DISCONNECT) {
1902 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1903 iface_ctx = &ipa_ctx->iface_context[i];
1904
1905 if (iface_ctx->dev == net_dev)
1906 break;
1907 }
1908 if (iface_ctx)
1909 wlan_ipa_cleanup_iface(iface_ctx);
1910 }
1911
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301912 return QDF_STATUS_SUCCESS;
1913 }
1914 ipa_info("IPA resource %s completed",
1915 ipa_ctx->resource_loading ?
1916 "load" : "unload");
1917 }
1918
1919 ipa_ctx->stats.event[type]++;
1920
1921 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1922 switch (type) {
1923 case QDF_IPA_STA_CONNECT:
1924 qdf_mutex_acquire(&ipa_ctx->event_lock);
1925
1926 /* STA already connected and without disconnect, connect again
1927 * This is Roaming scenario
1928 */
1929 if (ipa_ctx->sta_connected) {
1930 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1931 if (iface_ctx)
1932 wlan_ipa_cleanup_iface(iface_ctx);
1933 }
1934
1935 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301936 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301937 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001938 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301939 qdf_mutex_release(&ipa_ctx->event_lock);
1940 goto end;
1941 }
1942
Yu Tian0cc79c72019-09-18 15:11:32 +08001943 ipa_ctx->vdev_to_iface[session_id] =
1944 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1945
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301946 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08001947 (ipa_ctx->sap_num_connected_sta > 0 ||
1948 wlan_ipa_is_sta_only_offload_enabled()) &&
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301949 !ipa_ctx->sta_connected) {
1950 qdf_mutex_release(&ipa_ctx->event_lock);
1951 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1952 SIR_STA_RX_DATA_OFFLOAD, session_id,
1953 true);
1954 qdf_mutex_acquire(&ipa_ctx->event_lock);
Sravan Kumar Kairam3bc886d2019-08-22 23:46:27 +05301955 qdf_atomic_set(&ipa_ctx->stats_quota, 1);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301956 }
1957
jiad72b69a92019-04-11 17:23:10 +08001958 if (!wlan_ipa_is_sta_only_offload_enabled()) {
1959 ipa_debug("IPA STA only offload not enabled");
1960 } else if (ipa_ctx->uc_loaded &&
1961 !ipa_ctx->sap_num_connected_sta &&
1962 !ipa_ctx->sta_connected) {
1963 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1964 if (status) {
1965 qdf_mutex_release(&ipa_ctx->event_lock);
1966 ipa_info("handle 1st conn failed %d", status);
1967 wlan_ipa_uc_offload_enable_disable(
1968 ipa_ctx,
1969 SIR_STA_RX_DATA_OFFLOAD,
1970 session_id,
1971 false);
Yu Tian0cc79c72019-09-18 15:11:32 +08001972 ipa_ctx->vdev_to_iface[session_id] =
1973 WLAN_IPA_MAX_SESSION;
jiad72b69a92019-04-11 17:23:10 +08001974 goto end;
1975 }
1976 }
1977
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301978 ipa_ctx->sta_connected = 1;
1979
1980 qdf_mutex_release(&ipa_ctx->event_lock);
1981
Mohit Khannacabf5e72018-07-24 13:28:43 -07001982 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1983 ipa_ctx->sta_connected,
1984 session_id,
1985 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301986 break;
1987
1988 case QDF_IPA_AP_CONNECT:
1989 qdf_mutex_acquire(&ipa_ctx->event_lock);
1990
1991 /* For DFS channel we get two start_bss event (before and after
1992 * CAC). Also when ACS range includes both DFS and non DFS
1993 * channels, we could possibly change channel many times due to
1994 * RADAR detection and chosen channel may not be a DFS channels.
1995 * So dont return error here. Just discard the event.
1996 */
jiadc908ada2018-05-11 14:40:54 +08001997 if (ipa_ctx->vdev_to_iface[session_id] !=
1998 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301999 qdf_mutex_release(&ipa_ctx->event_lock);
2000 return 0;
2001 }
2002
2003 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302004 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302005 if (status != QDF_STATUS_SUCCESS) {
2006 qdf_mutex_release(&ipa_ctx->event_lock);
2007 ipa_err("%s: Evt: %d, Interface setup failed",
2008 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
2009 goto end;
2010 }
2011
2012 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2013 qdf_mutex_release(&ipa_ctx->event_lock);
2014 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2015 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
2016 qdf_mutex_acquire(&ipa_ctx->event_lock);
2017 }
2018
2019 ipa_ctx->vdev_to_iface[session_id] =
2020 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07002021 ipa_debug("vdev_to_iface[%u]=%u",
2022 session_id,
2023 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302024 qdf_mutex_release(&ipa_ctx->event_lock);
2025 break;
2026
2027 case QDF_IPA_STA_DISCONNECT:
2028 qdf_mutex_acquire(&ipa_ctx->event_lock);
2029
2030 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05302031 struct wlan_ipa_iface_context *iface;
2032
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302033 qdf_mutex_release(&ipa_ctx->event_lock);
2034 ipa_err("%s: Evt: %d, STA already disconnected",
2035 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05302036
2037 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
2038 if (iface && (iface->dev == net_dev))
2039 wlan_ipa_cleanup_iface(iface);
2040
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302041 return QDF_STATUS_E_INVAL;
2042 }
2043
2044 ipa_ctx->sta_connected = 0;
2045
2046 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2047 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
2048 msg_ex->name);
2049 } else {
jiad72b69a92019-04-11 17:23:10 +08002050 /*
2051 * Disable IPA pipes when
2052 * 1. STA is the last interface or
2053 * 2. STA only offload enabled and no clients connected
2054 * to SAP
2055 */
2056 if ((ipa_ctx->num_iface == 1 ||
2057 (wlan_ipa_is_sta_only_offload_enabled() &&
2058 !ipa_ctx->sap_num_connected_sta)) &&
Yun Parka29974a2018-04-09 12:05:49 -07002059 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08002060 !ipa_ctx->ipa_pipes_down &&
2061 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08002062 if (cds_is_driver_unloading()) {
2063 /*
2064 * We disable WDI pipes directly here
2065 * since IPA_OPCODE_TX/RX_SUSPEND
2066 * message will not be processed when
2067 * unloading WLAN driver is in progress
2068 */
2069 wlan_ipa_uc_disable_pipes(ipa_ctx);
2070 } else {
2071 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2072 }
2073 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302074 }
2075
2076 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002077 (ipa_ctx->sap_num_connected_sta > 0 ||
2078 wlan_ipa_is_sta_only_offload_enabled())) {
Sravan Kumar Kairam3bc886d2019-08-22 23:46:27 +05302079 qdf_atomic_set(&ipa_ctx->stats_quota, 0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302080 qdf_mutex_release(&ipa_ctx->event_lock);
2081 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2082 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
2083 qdf_mutex_acquire(&ipa_ctx->event_lock);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302084 }
2085
Rakshith Suresh Patkara4dea902019-09-23 15:33:15 +05302086 ipa_ctx->vdev_to_iface[session_id] = WLAN_IPA_MAX_SESSION;
2087 ipa_debug("vdev_to_iface[%u]=%u", session_id,
2088 ipa_ctx->vdev_to_iface[session_id]);
2089
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302090 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2091 iface_ctx = &ipa_ctx->iface_context[i];
2092
2093 if (iface_ctx->dev == net_dev)
2094 break;
2095 }
2096 if (i < WLAN_IPA_MAX_IFACE)
2097 wlan_ipa_cleanup_iface(iface_ctx);
2098
2099 qdf_mutex_release(&ipa_ctx->event_lock);
2100
2101 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
2102 break;
2103
2104 case QDF_IPA_AP_DISCONNECT:
2105 qdf_mutex_acquire(&ipa_ctx->event_lock);
2106
2107 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07002108 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08002109 !ipa_ctx->ipa_pipes_down &&
2110 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302111 if (cds_is_driver_unloading()) {
2112 /*
2113 * We disable WDI pipes directly here since
2114 * IPA_OPCODE_TX/RX_SUSPEND message will not be
2115 * processed when unloading WLAN driver is in
2116 * progress
2117 */
2118 wlan_ipa_uc_disable_pipes(ipa_ctx);
2119 } else {
2120 /*
2121 * This shouldn't happen :
2122 * No interface left but WDI pipes are still
2123 * active - force close WDI pipes
2124 */
2125 ipa_err("No interface left but WDI pipes are still active");
2126 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2127 }
2128 }
2129
2130 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2131 qdf_mutex_release(&ipa_ctx->event_lock);
2132 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2133 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
2134 qdf_mutex_acquire(&ipa_ctx->event_lock);
2135 ipa_ctx->vdev_to_iface[session_id] =
2136 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07002137 ipa_debug("vdev_to_iface[%u]=%u",
2138 session_id,
2139 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302140 }
2141
2142 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2143 iface_ctx = &ipa_ctx->iface_context[i];
2144
2145 if (iface_ctx->dev == net_dev)
2146 break;
2147 }
2148 if (i < WLAN_IPA_MAX_IFACE)
2149 wlan_ipa_cleanup_iface(iface_ctx);
2150
2151 qdf_mutex_release(&ipa_ctx->event_lock);
2152 break;
2153
2154 case QDF_IPA_CLIENT_CONNECT_EX:
2155 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2156 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
2157 net_dev->name, type);
2158 return QDF_STATUS_SUCCESS;
2159 }
2160
2161 qdf_mutex_acquire(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302162 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302163 mac_addr)) {
2164 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302165 ipa_err("%s: STA found, addr: " QDF_MAC_ADDR_STR,
2166 net_dev->name,
2167 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302168 return QDF_STATUS_SUCCESS;
2169 }
2170
2171 /* Enable IPA UC Data PIPEs when first STA connected */
2172 if (ipa_ctx->sap_num_connected_sta == 0 &&
2173 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302174
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302175 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002176 ipa_ctx->sta_connected &&
2177 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302178 qdf_mutex_release(&ipa_ctx->event_lock);
2179 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2180 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302181 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302182 qdf_mutex_acquire(&ipa_ctx->event_lock);
Sravan Kumar Kairam3bc886d2019-08-22 23:46:27 +05302183 qdf_atomic_set(&ipa_ctx->stats_quota, 1);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302184 }
2185
jiad72b69a92019-04-11 17:23:10 +08002186 /*
2187 * IPA pipes already enabled if STA only offload
2188 * is enabled and STA is connected to remote AP.
2189 */
2190 if (wlan_ipa_is_sta_only_offload_enabled() &&
2191 ipa_ctx->sta_connected) {
2192 ipa_debug("IPA pipes already enabled");
2193 } else if (wlan_ipa_uc_handle_first_con(ipa_ctx)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302194 ipa_info("%s: handle 1st con fail",
2195 net_dev->name);
2196
2197 if (wlan_ipa_uc_sta_is_enabled(
2198 ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002199 ipa_ctx->sta_connected &&
2200 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam3bc886d2019-08-22 23:46:27 +05302201 qdf_atomic_set(&ipa_ctx->stats_quota,
2202 0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302203 qdf_mutex_release(&ipa_ctx->event_lock);
2204 wlan_ipa_uc_offload_enable_disable(
2205 ipa_ctx,
2206 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302207 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302208 } else {
2209 qdf_mutex_release(&ipa_ctx->event_lock);
2210 }
2211
jiad72b69a92019-04-11 17:23:10 +08002212 return QDF_STATUS_E_BUSY;
2213 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302214 }
2215
2216 ipa_ctx->sap_num_connected_sta++;
2217
2218 qdf_mutex_release(&ipa_ctx->event_lock);
2219
2220 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2221 QDF_IPA_MSG_META_MSG_LEN(&meta) =
2222 (sizeof(qdf_ipa_wlan_msg_ex_t) +
2223 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
2224 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2225
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002226 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302227 ipa_err("msg_ex allocation failed");
2228 return QDF_STATUS_E_NOMEM;
2229 }
2230 strlcpy(msg_ex->name, net_dev->name,
2231 IPA_RESOURCE_NAME_MAX);
2232 msg_ex->num_of_attribs = 1;
2233 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
2234 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2235 msg_ex->attribs[0].offset =
2236 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
2237 } else {
2238 msg_ex->attribs[0].offset =
2239 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
2240 }
2241 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
2242 IPA_MAC_ADDR_SIZE);
2243
2244 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
2245 ipa_info("%s: Evt: %d send ipa msg fail",
2246 net_dev->name, type);
2247 qdf_mem_free(msg_ex);
2248 return QDF_STATUS_E_FAILURE;
2249 }
2250 ipa_ctx->stats.num_send_msg++;
2251
2252 ipa_info("sap_num_connected_sta=%d",
2253 ipa_ctx->sap_num_connected_sta);
2254
2255 return QDF_STATUS_SUCCESS;
2256
2257 case WLAN_CLIENT_DISCONNECT:
2258 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2259 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
2260 msg_ex->name);
2261 return QDF_STATUS_SUCCESS;
2262 }
2263
2264 qdf_mutex_acquire(&ipa_ctx->event_lock);
2265 if (!ipa_ctx->sap_num_connected_sta) {
2266 qdf_mutex_release(&ipa_ctx->event_lock);
2267 ipa_err("%s: Evt: %d, Client already disconnected",
2268 msg_ex->name,
2269 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2270
2271 return QDF_STATUS_SUCCESS;
2272 }
2273 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302274 mac_addr)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302275 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302276 ipa_err("%s: STA NOT found, not valid: "
2277 QDF_MAC_ADDR_STR,
2278 msg_ex->name, QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302279
2280 return QDF_STATUS_SUCCESS;
2281 }
2282 ipa_ctx->sap_num_connected_sta--;
2283
jiad72b69a92019-04-11 17:23:10 +08002284 /*
2285 * Disable IPA pipes when
2286 * 1. last client disconnected and
2287 * 2. STA is not connected if STA only offload is enabled
2288 */
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302289 if (!ipa_ctx->sap_num_connected_sta &&
jiad72b69a92019-04-11 17:23:10 +08002290 ipa_ctx->uc_loaded &&
2291 !(wlan_ipa_is_sta_only_offload_enabled() &&
2292 ipa_ctx->sta_connected)) {
Yun Parka29974a2018-04-09 12:05:49 -07002293 if ((false == ipa_ctx->resource_unloading) &&
2294 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
2295 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08002296 if (cds_is_driver_unloading()) {
2297 /*
2298 * We disable WDI pipes directly here
2299 * since IPA_OPCODE_TX/RX_SUSPEND
2300 * message will not be processed when
2301 * unloading WLAN driver is in progress
2302 */
2303 wlan_ipa_uc_disable_pipes(ipa_ctx);
2304 } else {
2305 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2306 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302307 }
2308
2309 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002310 ipa_ctx->sta_connected &&
2311 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam3bc886d2019-08-22 23:46:27 +05302312 qdf_atomic_set(&ipa_ctx->stats_quota, 0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302313 qdf_mutex_release(&ipa_ctx->event_lock);
2314 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2315 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302316 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302317 } else {
2318 qdf_mutex_release(&ipa_ctx->event_lock);
2319 }
2320 } else {
2321 qdf_mutex_release(&ipa_ctx->event_lock);
2322 }
2323
2324 ipa_info("sap_num_connected_sta=%d",
2325 ipa_ctx->sap_num_connected_sta);
2326 break;
2327
2328 default:
2329 return QDF_STATUS_SUCCESS;
2330 }
2331
2332 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2333 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2334 if (!msg) {
2335 ipa_err("msg allocation failed");
2336 return QDF_STATUS_E_NOMEM;
2337 }
2338
2339 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2340 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2341 IPA_RESOURCE_NAME_MAX);
2342 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2343
2344 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
2345 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2346
2347 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2348
2349 ipa_err("%s: Evt: %d fail",
2350 QDF_IPA_WLAN_MSG_NAME(msg),
2351 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2352 qdf_mem_free(msg);
2353
2354 return QDF_STATUS_E_FAILURE;
2355 }
2356
2357 ipa_ctx->stats.num_send_msg++;
2358
2359end:
2360 return QDF_STATUS_SUCCESS;
2361}
2362
2363/**
2364 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002365 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302366 *
2367 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2368 */
2369static qdf_ipa_wlan_event
2370wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2371{
Yun Park84fbb272018-04-02 15:31:01 -07002372 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302373
2374 switch (wlan_ipa_event_type) {
2375 case WLAN_IPA_CLIENT_CONNECT:
2376 ipa_event = QDF_IPA_CLIENT_CONNECT;
2377 break;
2378 case WLAN_IPA_CLIENT_DISCONNECT:
2379 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2380 break;
2381 case WLAN_IPA_AP_CONNECT:
2382 ipa_event = QDF_IPA_AP_CONNECT;
2383 break;
2384 case WLAN_IPA_AP_DISCONNECT:
2385 ipa_event = QDF_IPA_AP_DISCONNECT;
2386 break;
2387 case WLAN_IPA_STA_CONNECT:
2388 ipa_event = QDF_IPA_STA_CONNECT;
2389 break;
2390 case WLAN_IPA_STA_DISCONNECT:
2391 ipa_event = QDF_IPA_STA_DISCONNECT;
2392 break;
2393 case WLAN_IPA_CLIENT_CONNECT_EX:
2394 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2395 break;
2396 case WLAN_IPA_WLAN_EVENT_MAX:
2397 default:
2398 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2399 break;
2400 }
2401
2402 return ipa_event;
2403}
2404
2405/**
2406 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2407 * @net_dev: Interface net device
2408 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302409 * @session_id: session id for the event
2410 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2411 * @mac_address: MAC address associated with the event
2412 *
2413 * Return: QDF_STATUS
2414 */
2415QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302416 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302417 enum wlan_ipa_wlan_event ipa_event_type,
2418 uint8_t *mac_addr)
2419{
2420 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2421 QDF_STATUS status = QDF_STATUS_SUCCESS;
2422
2423 /* Data path offload only support for STA and SAP mode */
2424 if ((device_mode == QDF_STA_MODE) ||
2425 (device_mode == QDF_SAP_MODE))
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302426 status = __wlan_ipa_wlan_evt(net_dev, device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302427 session_id, type, mac_addr);
2428
2429 return status;
2430}
2431
2432/**
2433 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2434 * @ipa_ctx: Global IPA IPA context
2435 * @is_loading: Indicate if invoked during loading
2436 *
2437 * Return: None
2438 */
2439static void
2440wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2441{
2442 unsigned int pending_event_count;
2443 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2444
2445 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2446 ipa_debug("Pending Event Count %d", pending_event_count);
2447 if (!pending_event_count) {
2448 ipa_debug("No Pending Event");
2449 return;
2450 }
2451
2452 qdf_list_remove_front(&ipa_ctx->pending_event,
2453 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002454 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302455 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2456 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2457 struct wlan_objmgr_vdev *vdev =
2458 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2459 pending_event->session_id,
2460 WLAN_IPA_ID);
2461 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302462 __wlan_ipa_wlan_evt(pending_event->net_dev,
2463 pending_event->device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302464 pending_event->session_id,
2465 pending_event->type,
2466 pending_event->mac_addr);
2467 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302468
2469 if (vdev)
2470 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302471 qdf_mem_free(pending_event);
2472 pending_event = NULL;
2473 qdf_list_remove_front(&ipa_ctx->pending_event,
2474 (qdf_list_node_t **)&pending_event);
2475 }
2476}
2477
2478/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002479 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2480 * @ipa_ctx: IPA context
2481 *
2482 * Return: None
2483 */
2484static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2485{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302486 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002487 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302488 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002489
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302490 if (!ipa_ctx->tx_desc_pool)
2491 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002492
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302493 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2494 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2495 for (i = 0; i < pool_size; i++) {
2496 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002497 if (ipa_tx_desc)
2498 qdf_ipa_free_skb(ipa_tx_desc);
2499
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302500 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2501 &ipa_ctx->tx_desc_pool[i].node) !=
2502 QDF_STATUS_SUCCESS)
2503 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002504 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302505 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2506
2507 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2508 qdf_mem_free(ipa_ctx->tx_desc_pool);
2509 ipa_ctx->tx_desc_pool = NULL;
2510
2511 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2512 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002513}
2514
2515/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302516 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302517 * @ipa_ctx: IPA context
2518 *
2519 * Return: QDF_STATUS
2520 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302521static QDF_STATUS
2522wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302523{
2524 int i;
2525 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302526
2527 max_desc_cnt = ipa_ctx->config->txbuf_count;
2528
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302529 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2530 max_desc_cnt);
2531
2532 if (!ipa_ctx->tx_desc_pool) {
2533 ipa_err("Free Tx descriptor allocation failed");
2534 return QDF_STATUS_E_NOMEM;
2535 }
2536
2537 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302538
2539 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2540 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302541 ipa_ctx->tx_desc_pool[i].id = i;
2542 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2543 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2544 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302545 }
2546
2547 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2548 ipa_ctx->stats.num_tx_desc_error = 0;
2549
2550 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2551
2552 return QDF_STATUS_SUCCESS;
2553}
2554
2555#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2556/**
2557 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2558 * @ipa_ctx: Global IPA IPA context
2559 * @desc_fifo_sz: Number of descriptors
2560 *
2561 * Return: 0 on success, negative errno on error
2562 */
2563static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2564 int32_t desc_fifo_sz)
2565{
2566 int i, ret = 0;
2567 qdf_ipa_sys_connect_params_t *ipa;
2568
2569 /*setup TX pipes */
2570 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2571 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2572
2573 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2574 ipa->desc_fifo_sz = desc_fifo_sz;
2575 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302576 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302577
2578 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2579 ipa->ipa_ep_cfg.hdr.hdr_len =
2580 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2581 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2582 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2583 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2584 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2585 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2586 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2587 } else {
2588 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2589 }
2590 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2591
2592 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2593 &ipa_ctx->sys_pipe[i].conn_hdl);
2594 if (ret) {
2595 ipa_err("Failed for pipe %d ret: %d", i, ret);
2596 return ret;
2597 }
2598 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2599 }
2600
2601 return ret;
2602}
2603#else
2604/**
2605 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302606 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302607 * @desc_fifo_sz: Number of descriptors
2608 *
2609 * Return: 0 on success, negative errno on error
2610 */
2611static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2612 int32_t desc_fifo_sz)
2613{
2614 /*
2615 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2616 * is enabled, where per vdev descriptors are supported in firmware.
2617 */
2618 return 0;
2619}
2620#endif
2621
Sravan Kumar Kairam7efc0132019-03-25 16:13:46 +05302622#if defined(CONFIG_IPA_WDI_UNIFIED_API) && defined(IPA_WDI3_GSI)
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302623/**
2624 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2625 * @ipa_ctx: IPA context
2626 *
2627 * Return: rx ipa sys client
2628 */
2629static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2630{
2631 if (ipa_ctx->over_gsi)
2632 return IPA_CLIENT_WLAN2_PROD;
2633 else
2634 return IPA_CLIENT_WLAN1_PROD;
2635}
2636#else
2637static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2638{
2639 return IPA_CLIENT_WLAN1_PROD;
2640}
2641#endif
2642
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302643/**
2644 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2645 * @ipa_ctx: Global IPA IPA context
2646 * @desc_fifo_sz: Number of descriptors
2647 *
2648 * Return: 0 on success, negative errno on error
2649 */
2650static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2651 int32_t desc_fifo_sz)
2652{
2653 int ret = 0;
2654 qdf_ipa_sys_connect_params_t *ipa;
2655
2656 /*
2657 * Hard code it here, this can be extended if in case
2658 * PROD pipe is also per interface.
2659 * Right now there is no advantage of doing this.
2660 */
2661 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2662
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302663 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302664 ipa->desc_fifo_sz = desc_fifo_sz;
2665 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302666 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302667
2668 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2669 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2670 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2671 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2672
2673 ret = qdf_ipa_setup_sys_pipe(ipa,
2674 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2675 if (ret) {
2676 ipa_err("Failed for RX pipe: %d", ret);
2677 return ret;
2678 }
2679 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2680
2681 return ret;
2682}
2683
2684/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002685 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2686 * @ipa_ctx: Global IPA IPA context
2687 *
2688 * Return: None
2689 */
2690static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2691{
2692 int ret, i;
2693
2694 if (!ipa_ctx)
2695 return;
2696
2697 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2698 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2699 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2700 ipa_ctx->sys_pipe[i].conn_hdl);
2701 if (ret)
2702 ipa_err("Failed:%d", ret);
2703
2704 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2705 }
2706 }
2707
2708 wlan_ipa_free_tx_desc_list(ipa_ctx);
2709}
2710
2711/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302712 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2713 * @ipa_ctx: Global IPA IPA context
2714 *
2715 * Return: 0 on success, negative errno on error
2716 */
2717static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2718{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002719 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302720 uint32_t desc_fifo_sz;
2721
2722 /* The maximum number of descriptors that can be provided to a BAM at
2723 * once is one less than the total number of descriptors that the buffer
2724 * can contain.
2725 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2726 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2727 * be provided at once.
2728 * Because of above requirement, one extra descriptor will be added to
2729 * make sure hardware always has one descriptor.
2730 */
2731 desc_fifo_sz = ipa_ctx->config->desc_size
2732 + SPS_DESC_SIZE;
2733
2734 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2735 if (ret) {
2736 ipa_err("Failed for TX pipe: %d", ret);
2737 goto setup_sys_pipe_fail;
2738 }
2739
2740 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2741 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2742 if (ret) {
2743 ipa_err("Failed for RX pipe: %d", ret);
2744 goto setup_sys_pipe_fail;
2745 }
2746 }
2747
2748 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302749 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302750 if (ret)
2751 goto setup_sys_pipe_fail;
2752
2753 return ret;
2754
2755setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002756 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302757
2758 return ret;
2759}
2760
jiadbb47e132018-03-30 16:28:30 +08002761#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2762QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2763 bool mcc_mode)
2764{
2765 qdf_ipa_msg_meta_t meta;
2766 qdf_ipa_wlan_msg_t *msg;
2767 int ret;
2768
2769 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2770 return QDF_STATUS_SUCCESS;
2771
2772 /* Send SCC/MCC Switching event to IPA */
2773 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2774 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002775 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002776 ipa_err("msg allocation failed");
2777 return QDF_STATUS_E_NOMEM;
2778 }
2779
jiad629b2172018-05-11 15:34:22 +08002780 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002781 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002782 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2783 } else {
jiadbb47e132018-03-30 16:28:30 +08002784 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002785 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2786 }
2787
jiadbb47e132018-03-30 16:28:30 +08002788 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2789 "ipa_send_msg(Evt:%d)",
2790 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2791
2792 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2793
2794 if (ret) {
2795 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2796 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2797 qdf_mem_free(msg);
2798 return QDF_STATUS_E_FAILURE;
2799 }
2800
2801 return QDF_STATUS_SUCCESS;
2802}
2803
2804static void wlan_ipa_mcc_work_handler(void *data)
2805{
2806 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2807
2808 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2809}
2810#endif
2811
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302812/**
2813 * wlan_ipa_setup() - IPA initialization function
2814 * @ipa_ctx: IPA context
2815 * @ipa_cfg: IPA config
2816 *
2817 * Allocate ipa_ctx resources, ipa pipe resource and register
2818 * wlan interface with IPA module.
2819 *
2820 * Return: QDF_STATUS enumeration
2821 */
2822QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2823 struct wlan_ipa_config *ipa_cfg)
2824{
2825 int ret, i;
2826 struct wlan_ipa_iface_context *iface_context = NULL;
2827 QDF_STATUS status;
2828
2829 ipa_debug("enter");
2830
2831 gp_ipa = ipa_ctx;
2832 ipa_ctx->num_iface = 0;
2833 ipa_ctx->config = ipa_cfg;
2834
2835 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2836
2837 /* Create the interface context */
2838 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2839 iface_context = &ipa_ctx->iface_context[i];
2840 iface_context->ipa_ctx = ipa_ctx;
2841 iface_context->cons_client =
2842 wlan_ipa_iface_2_client[i].cons_client;
2843 iface_context->prod_client =
2844 wlan_ipa_iface_2_client[i].prod_client;
2845 iface_context->iface_id = i;
2846 iface_context->dev = NULL;
2847 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2848 iface_context->tl_context = NULL;
2849 qdf_spinlock_create(&iface_context->interface_lock);
2850 }
2851
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302852 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302853 qdf_spinlock_create(&ipa_ctx->pm_lock);
2854 qdf_spinlock_create(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302855 qdf_spinlock_create(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302856 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2857 qdf_list_create(&ipa_ctx->pending_event, 1000);
2858 qdf_mutex_create(&ipa_ctx->event_lock);
2859 qdf_mutex_create(&ipa_ctx->ipa_lock);
2860
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302861 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2862 if (status != QDF_STATUS_SUCCESS)
2863 goto fail_setup_rm;
2864
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302865 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2866 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2867 sizeof(struct wlan_ipa_sys_pipe));
2868
2869 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2870 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2871 ipa_ctx->sap_num_connected_sta = 0;
2872 ipa_ctx->ipa_tx_packets_diff = 0;
2873 ipa_ctx->ipa_rx_packets_diff = 0;
2874 ipa_ctx->ipa_p_tx_packets = 0;
2875 ipa_ctx->ipa_p_rx_packets = 0;
2876 ipa_ctx->resource_loading = false;
2877 ipa_ctx->resource_unloading = false;
2878 ipa_ctx->sta_connected = 0;
2879 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302880 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302881 ipa_ctx->wdi_enabled = false;
2882 /* Setup IPA system pipes */
2883 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2884 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2885 if (ret)
2886 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002887
2888 qdf_create_work(0, &ipa_ctx->mcc_work,
2889 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302890 }
2891
2892 status = wlan_ipa_wdi_init(ipa_ctx);
2893 if (status == QDF_STATUS_E_BUSY)
2894 status = wlan_ipa_uc_send_wdi_control_msg(false);
2895 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002896 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302897 goto fail_create_sys_pipe;
2898 }
2899 } else {
2900 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2901 if (ret)
2902 goto fail_create_sys_pipe;
2903 }
2904
2905 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2906
2907 ipa_debug("exit: success");
2908
2909 return QDF_STATUS_SUCCESS;
2910
2911fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302912 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2913
2914fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302915 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302916 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302917 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302918 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2919 iface_context = &ipa_ctx->iface_context[i];
2920 qdf_spinlock_destroy(&iface_context->interface_lock);
2921 }
2922 qdf_mutex_destroy(&ipa_ctx->event_lock);
2923 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2924 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302925 gp_ipa = NULL;
2926 ipa_debug("exit: fail");
2927
2928 return QDF_STATUS_E_FAILURE;
2929}
2930
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302931void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2932{
2933 qdf_nbuf_t skb;
2934 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2935
2936 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2937 return;
2938
2939 qdf_cancel_work(&ipa_ctx->pm_work);
2940
2941 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2942
2943 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2944 != NULL)) {
2945 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2946
2947 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002948
2949 if (pm_tx_cb->exception) {
2950 dev_kfree_skb_any(skb);
2951 } else {
2952 if (pm_tx_cb->ipa_tx_desc)
2953 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2954 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302955
2956 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2957 }
2958 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2959}
2960
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302961QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2962{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302963 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302964 int i;
2965
2966 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2967 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2968
2969 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002970 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302971 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002972 qdf_cancel_work(&ipa_ctx->mcc_work);
2973 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302974
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302975 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2976
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302977 wlan_ipa_flush(ipa_ctx);
2978
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302979 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2980 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302981 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302982
2983 /* destroy the interface lock */
2984 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2985 iface_context = &ipa_ctx->iface_context[i];
2986 qdf_spinlock_destroy(&iface_context->interface_lock);
2987 }
2988
2989 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2990 wlan_ipa_wdi_cleanup();
2991 qdf_mutex_destroy(&ipa_ctx->event_lock);
2992 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2993 qdf_list_destroy(&ipa_ctx->pending_event);
2994
2995 }
2996
2997 gp_ipa = NULL;
2998
2999 return QDF_STATUS_SUCCESS;
3000}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05303001
3002struct wlan_ipa_iface_context
3003*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
3004{
3005 struct wlan_ipa_iface_context *iface_ctx = NULL;
3006 int i;
3007
3008 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3009 iface_ctx = &ipa_ctx->iface_context[i];
3010
3011 if (iface_ctx->device_mode == mode)
3012 return iface_ctx;
3013 }
3014
3015 return NULL;
3016}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303017
jiadbb47e132018-03-30 16:28:30 +08003018void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303019{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303020 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08003021 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303022
jiadbb47e132018-03-30 16:28:30 +08003023 if (ipa_ctx->mcc_mode == mcc_mode)
3024 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303025
jiadbb47e132018-03-30 16:28:30 +08003026 ipa_ctx->mcc_mode = mcc_mode;
3027 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303028}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303029
3030/**
3031 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
3032 * @ipa_ctx: ipa ipa local context
3033 *
3034 * Will handle IPA UC image loaded indication comes from IPA kernel
3035 *
3036 * Return: None
3037 */
3038static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
3039{
3040 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
3041 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
3042 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
3043 QDF_STATUS status;
3044
3045 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07003046
3047 if (!qdf_dev) {
3048 ipa_err("qdf device is NULL!");
3049 return;
3050 }
3051
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303052 if (true == ipa_ctx->uc_loaded) {
3053 ipa_info("UC already loaded");
3054 return;
3055 }
3056
Lihua Liu15f6e452018-05-30 17:31:06 +08003057 if (!qdf_dev) {
3058 ipa_err("qdf_dev is null");
3059 return;
3060 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303061 /* Connect pipe */
3062 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
3063 if (status) {
3064 ipa_err("Failure to setup IPA pipes (status=%d)",
3065 status);
3066 return;
3067 }
3068
3069 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303070
jiad72b69a92019-04-11 17:23:10 +08003071 /*
3072 * Enable IPA/FW PIPEs if
3073 * 1. any clients connected to SAP or
3074 * 2. STA connected to remote AP if STA only offload is enabled
3075 */
3076 if (ipa_ctx->sap_num_connected_sta ||
3077 (wlan_ipa_is_sta_only_offload_enabled() &&
3078 ipa_ctx->sta_connected)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303079 ipa_debug("Client already connected, enable IPA/FW PIPEs");
3080 wlan_ipa_uc_handle_first_con(ipa_ctx);
3081 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303082}
3083
3084/**
3085 * wlan_ipa_uc_op_cb() - IPA uC operation callback
3086 * @op_msg: operation message received from firmware
3087 * @usr_ctxt: user context registered with TL (we register the IPA Global
3088 * context)
3089 *
3090 * Return: None
3091 */
3092static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
3093 struct wlan_ipa_priv *ipa_ctx)
3094{
3095 struct op_msg_type *msg = op_msg;
3096 struct ipa_uc_fw_stats *uc_fw_stat;
3097
3098 if (!op_msg) {
3099 ipa_err("INVALID ARG");
3100 return;
3101 }
3102
3103 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3104 ipa_err("INVALID OPCODE %d", msg->op_code);
3105 qdf_mem_free(op_msg);
3106 return;
3107 }
3108
3109 ipa_debug("OPCODE=%d", msg->op_code);
3110
3111 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
3112 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
3113 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3114 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07003115 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303116 ipa_ctx->resource_loading = false;
3117 qdf_event_set(&ipa_ctx->ipa_resource_comp);
3118 if (ipa_ctx->wdi_enabled == false) {
3119 ipa_ctx->wdi_enabled = true;
3120 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
3121 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
3122 ipa_ctx->mcc_mode);
3123 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303124 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303125 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07003126 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303127 QDF_IPA_RM_RESOURCE_GRANTED,
3128 QDF_IPA_RM_RESOURCE_WLAN_CONS);
3129 ipa_ctx->pending_cons_req = false;
3130 }
3131 qdf_mutex_release(&ipa_ctx->ipa_lock);
3132 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
3133 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
3134 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05303135
3136 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
3137 wlan_ipa_uc_disable_pipes(ipa_ctx);
3138 ipa_info("Disable FW TX PIPE");
3139 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3140 false, true);
3141 }
3142
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303143 ipa_ctx->activated_fw_pipe--;
3144 if (!ipa_ctx->activated_fw_pipe) {
3145 /*
3146 * Async return success from FW
3147 * Disable/suspend all the PIPEs
3148 */
3149 ipa_ctx->resource_unloading = false;
3150 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303151 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07003152 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
3153 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303154 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303155 ipa_ctx->pending_cons_req = false;
3156 }
3157 qdf_mutex_release(&ipa_ctx->ipa_lock);
3158 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3159 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
3160 uc_fw_stat = (struct ipa_uc_fw_stats *)
3161 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3162
3163 /* WLAN FW WDI stats */
3164 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
3165 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3166 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
3167 /* STATs from FW */
3168 uc_fw_stat = (struct ipa_uc_fw_stats *)
3169 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3170 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3171 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
3172 uc_fw_stat->tx_pkts_completed,
3173 ipa_ctx->ipa_p_tx_packets);
3174 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
3175 (uc_fw_stat->rx_num_ind_drop_no_space +
3176 uc_fw_stat->rx_num_ind_drop_no_buf +
3177 uc_fw_stat->rx_num_pkts_indicated),
3178 ipa_ctx->ipa_p_rx_packets);
3179
3180 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
3181 ipa_ctx->ipa_p_rx_packets =
3182 (uc_fw_stat->rx_num_ind_drop_no_space +
3183 uc_fw_stat->rx_num_ind_drop_no_buf +
3184 uc_fw_stat->rx_num_pkts_indicated);
3185 qdf_mutex_release(&ipa_ctx->ipa_lock);
3186 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
3187 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3188 wlan_ipa_uc_loaded_handler(ipa_ctx);
3189 qdf_mutex_release(&ipa_ctx->ipa_lock);
3190 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
3191 ipa_err("Invalid message: op_code=%d, reason=%d",
3192 msg->op_code, ipa_ctx->stat_req_reason);
3193 }
3194
3195 qdf_mem_free(op_msg);
3196}
3197
3198/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303199 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
3200 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303201 *
3202 * Return: None
3203 */
jitiphilfdcaaba2018-09-03 16:19:52 +05303204static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303205{
3206 struct op_msg_type *msg;
3207 struct uc_op_work_struct *uc_op_work =
3208 (struct uc_op_work_struct *)data;
3209 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3210
3211 msg = uc_op_work->msg;
3212 uc_op_work->msg = NULL;
3213 ipa_debug("posted msg %d", msg->op_code);
3214
3215 wlan_ipa_uc_op_cb(msg, ipa_ctx);
3216}
3217
3218/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303219 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
3220 * __wlan_ipa_uc_fw_op_event_handler
3221 * @data: uC OP work
3222 *
3223 * Return: None
3224 */
3225static void wlan_ipa_uc_fw_op_event_handler(void *data)
3226{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003227 struct qdf_op_sync *op_sync;
3228
3229 if (qdf_op_protect(&op_sync))
3230 return;
3231
jitiphilfdcaaba2018-09-03 16:19:52 +05303232 __wlan_ipa_uc_fw_op_event_handler(data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003233
3234 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05303235}
3236
3237/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303238 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
3239 * @op_msg: operation message received from firmware
3240 * @ipa_ctx: Global IPA context
3241 *
3242 * Return: None
3243 */
3244static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
3245{
3246 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
3247 struct op_msg_type *msg;
3248 struct uc_op_work_struct *uc_op_work;
3249
3250 if (!ipa_ctx)
3251 goto end;
3252
3253 msg = (struct op_msg_type *)op_msg;
3254
3255 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3256 ipa_err("Invalid OP Code (%d)", msg->op_code);
3257 goto end;
3258 }
3259
3260 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
3261 if (uc_op_work->msg) {
3262 /* When the same uC OPCODE is already pended, just return */
3263 goto end;
3264 }
3265
3266 uc_op_work->msg = msg;
3267 qdf_sched_work(0, &uc_op_work->work);
3268 return;
3269
3270end:
3271 qdf_mem_free(op_msg);
3272}
3273
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303274QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
3275 qdf_device_t osdev)
3276{
3277 uint8_t i;
3278 QDF_STATUS status = QDF_STATUS_SUCCESS;
3279
3280 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3281 return QDF_STATUS_SUCCESS;
3282
3283 ipa_debug("enter");
3284
Sravan Kumar Kairam02a761e2019-07-05 17:06:27 +05303285 if (!osdev) {
3286 ipa_err("osdev null");
3287 status = QDF_STATUS_E_FAILURE;
3288 goto fail_return;
3289 }
3290
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303291 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
3292 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
3293 ipa_ctx->vdev_offload_enabled[i] = false;
3294 }
3295
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303296 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
3297 ipa_err("IPA UC resource alloc fail");
3298 status = QDF_STATUS_E_FAILURE;
3299 goto fail_return;
3300 }
3301
3302 if (true == ipa_ctx->uc_loaded) {
3303 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
3304 if (status) {
3305 ipa_err("Failure to setup IPA pipes (status=%d)",
3306 status);
3307 status = QDF_STATUS_E_FAILURE;
3308 goto fail_return;
3309 }
3310
3311 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
3312 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08003313
3314 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
3315 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303316 }
3317
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303318 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3319 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
3320
3321 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3322 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
3323 wlan_ipa_uc_fw_op_event_handler,
3324 &ipa_ctx->uc_op_work[i]);
3325 ipa_ctx->uc_op_work[i].msg = NULL;
3326 }
3327
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303328fail_return:
3329 ipa_debug("exit: status=%d", status);
3330 return status;
3331}
3332
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303333/**
3334 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3335 * @ipa_ctx: pointer to IPA IPA struct
3336 *
3337 * Return: none
3338 */
3339static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
3340{
3341 struct wlan_ipa_uc_pending_event *pending_event = NULL;
3342
3343 while (qdf_list_remove_front(&ipa_ctx->pending_event,
3344 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3345 qdf_mem_free(pending_event);
3346}
3347
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303348QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
3349{
3350 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303351 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303352
3353 ipa_debug("enter");
3354
3355 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3356 return status;
3357
3358 if (!ipa_ctx->ipa_pipes_down)
3359 wlan_ipa_uc_disable_pipes(ipa_ctx);
3360
3361 if (true == ipa_ctx->uc_loaded) {
3362 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3363 ipa_ctx->tx_pipe_handle,
3364 ipa_ctx->rx_pipe_handle);
3365 if (status)
3366 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3367 status);
3368 }
3369
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303370 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3371 wlan_ipa_cleanup_pending_event(ipa_ctx);
3372 qdf_mutex_release(&ipa_ctx->ipa_lock);
3373
3374 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3375 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3376 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3377 ipa_ctx->uc_op_work[i].msg = NULL;
3378 }
3379
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303380 ipa_debug("exit: ret=%d", status);
3381 return status;
3382}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303383
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303384/**
3385 * wlan_ipa_uc_send_evt() - send event to ipa
3386 * @net_dev: Interface net device
3387 * @type: event type
3388 * @mac_addr: pointer to mac address
3389 *
3390 * Send event to IPA driver
3391 *
3392 * Return: QDF_STATUS
3393 */
3394static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3395 qdf_ipa_wlan_event type,
3396 uint8_t *mac_addr)
3397{
3398 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3399 qdf_ipa_msg_meta_t meta;
3400 qdf_ipa_wlan_msg_t *msg;
3401
3402 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3403 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3404 if (!msg) {
3405 ipa_err("msg allocation failed");
3406 return QDF_STATUS_E_NOMEM;
3407 }
3408
3409 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3410 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3411 IPA_RESOURCE_NAME_MAX);
3412 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3413
3414 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3415 ipa_err("%s: Evt: %d fail",
3416 QDF_IPA_WLAN_MSG_NAME(msg),
3417 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3418 qdf_mem_free(msg);
3419
3420 return QDF_STATUS_E_FAILURE;
3421 }
3422
3423 ipa_ctx->stats.num_send_msg++;
3424
3425 return QDF_STATUS_SUCCESS;
3426}
3427
Vevek Venkatesane81bca82019-08-12 22:25:15 +05303428void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx,
3429 qdf_netdev_t net_dev)
3430{
3431 struct wlan_ipa_iface_context *iface_ctx;
3432 int i;
3433
3434 ipa_debug("enter");
3435
3436 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3437 iface_ctx = &ipa_ctx->iface_context[i];
3438 if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE &&
3439 iface_ctx->dev == net_dev && iface_ctx->tl_context) {
3440 wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
3441 net_dev->dev_addr);
3442 wlan_ipa_cleanup_iface(iface_ctx);
3443 }
3444 }
3445
3446 ipa_debug("exit");
3447}
3448
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303449QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3450 qdf_netdev_t net_dev)
3451{
3452 struct wlan_ipa_iface_context *iface_ctx;
3453 QDF_STATUS status;
3454
3455 ipa_debug("enter");
3456
3457 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3458 if (iface_ctx)
3459 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3460 net_dev->dev_addr);
3461 else
3462 return QDF_STATUS_E_INVAL;
3463
3464 ipa_debug("exit :%d", status);
3465
3466 return status;
3467}
3468
3469void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3470 qdf_netdev_t net_dev)
3471{
3472 struct wlan_ipa_iface_context *iface_ctx;
3473 int i;
3474
3475 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3476 iface_ctx = &ipa_ctx->iface_context[i];
3477 if (iface_ctx->dev == net_dev)
3478 break;
3479 }
3480
3481 if (iface_ctx)
3482 wlan_ipa_cleanup_iface(iface_ctx);
3483}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303484
3485void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3486{
3487 struct wlan_ipa_iface_context *iface;
3488 int i;
3489
3490 ipa_info("enter");
3491
3492 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3493 iface = &ipa_ctx->iface_context[i];
3494 if (iface->dev) {
3495 if (iface->device_mode == QDF_SAP_MODE)
3496 wlan_ipa_uc_send_evt(iface->dev,
3497 QDF_IPA_AP_DISCONNECT,
3498 iface->dev->dev_addr);
3499 else if (iface->device_mode == QDF_STA_MODE)
3500 wlan_ipa_uc_send_evt(iface->dev,
3501 QDF_IPA_STA_DISCONNECT,
3502 iface->dev->dev_addr);
3503 wlan_ipa_cleanup_iface(iface);
3504 }
3505 }
3506}
jitiphil0e3b5922018-07-24 18:43:50 +05303507
3508void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3509{
3510 qdf_ipa_msg_meta_t meta;
3511 qdf_ipa_wlan_msg_t *msg;
3512 int ret;
3513
3514 meta.msg_len = sizeof(*msg);
3515 msg = qdf_mem_malloc(meta.msg_len);
3516 if (!msg) {
3517 ipa_debug("msg allocation failed");
3518 return;
3519 }
3520
3521 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3522 ipa_debug("ipa_send_msg(Evt:%d)",
3523 meta.msg_type);
3524 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3525
3526 if (ret) {
3527 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3528 meta.msg_type, ret);
3529 qdf_mem_free(msg);
3530 }
3531 ipa_ctx->stats.num_send_msg++;
3532}