blob: 73bc5e514572cde7e68fc449976fcb37c0f3012e [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 */
Mohit Khannacabf5e72018-07-24 13:28:43 -0700470#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530471static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
472{
473 ipa_ctx->wdi_version = IPA_WDI_3;
474}
475#elif defined(QCA_WIFI_3_0)
476static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
477{
478 ipa_ctx->wdi_version = IPA_WDI_2;
479}
480#else
481static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
482{
483 ipa_ctx->wdi_version = IPA_WDI_1;
484}
485#endif
486
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530487static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
488 qdf_device_t osdev)
489{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530490 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530491}
492
493static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
494 qdf_device_t osdev)
495{
496 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
497 int i;
498
499 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
500 qdf_mem_copy(&sys_in[i],
501 &ipa_ctx->sys_pipe[i].ipa_sys_params,
502 sizeof(qdf_ipa_sys_connect_params_t));
503
504 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
505 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
506 wlan_ipa_wdi_meter_notifier_cb,
507 ipa_ctx->config->desc_size,
508 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
509 &ipa_ctx->tx_pipe_handle,
510 &ipa_ctx->rx_pipe_handle,
511 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530512 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530513}
514
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530515#ifdef FEATURE_METERING
516/**
517 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
518 * @ipa_ctx: IPA context
519 * @in: IPA WDI in param
520 *
521 * Return: QDF_STATUS
522 */
523static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
524 qdf_ipa_wdi_init_in_params_t *in)
525{
526 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
527 wlan_ipa_wdi_meter_notifier_cb;
528}
529#else
530static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
531 qdf_ipa_wdi_init_in_params_t *in)
532{
533}
534#endif
535
536/**
537 * wlan_ipa_wdi_init() - IPA WDI init
538 * @ipa_ctx: IPA context
539 *
540 * Return: QDF_STATUS
541 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530542static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
543{
544 qdf_ipa_wdi_init_in_params_t in;
545 qdf_ipa_wdi_init_out_params_t out;
546 int ret;
547
548 ipa_ctx->uc_loaded = false;
549
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530550 qdf_mem_zero(&in, sizeof(in));
551 qdf_mem_zero(&out, sizeof(out));
552
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530553 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
554 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530555 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
556 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530557
558 ret = qdf_ipa_wdi_init(&in, &out);
559 if (ret) {
560 ipa_err("ipa_wdi_init failed with ret=%d", ret);
561 return QDF_STATUS_E_FAILURE;
562 }
563
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530564 ipa_ctx->over_gsi =
565 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
566 ipa_ctx->is_smmu_enabled =
567 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
568 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
569 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
570
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530571 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700572 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530573 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530574 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530575 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530576 return QDF_STATUS_E_BUSY;
577 }
578
579 return QDF_STATUS_SUCCESS;
580}
581
582static inline int wlan_ipa_wdi_cleanup(void)
583{
584 int ret;
585
586 ret = qdf_ipa_wdi_cleanup();
587 if (ret)
588 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
589 return ret;
590}
591
592static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
593 struct ipa_sys_connect_params *sys,
594 uint32_t *handle)
595{
596 return 0;
597}
598
599static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
600 uint32_t handle)
601{
602 return 0;
603}
604
Yun Parke74e6092018-04-27 11:36:34 -0700605/**
606 * wlan_ipa_pm_flush() - flush queued packets
607 * @work: pointer to the scheduled work
608 *
609 * Called during PM resume to send packets to TL which were queued
610 * while host was in the process of suspending.
611 *
612 * Return: None
613 */
614static void wlan_ipa_pm_flush(void *data)
615{
616 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
617 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
618 qdf_nbuf_t skb;
619 uint32_t dequeued = 0;
620
621 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
622 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
623 NULL)) {
624 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
625
626 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
627 dequeued++;
628
jiadab8cea02018-05-24 09:16:14 +0800629 if (pm_tx_cb->exception) {
630 if (ipa_ctx->softap_xmit &&
631 pm_tx_cb->iface_context->dev) {
632 ipa_ctx->softap_xmit(skb,
633 pm_tx_cb->iface_context->dev);
634 ipa_ctx->stats.num_tx_fwd_ok++;
635 } else {
636 dev_kfree_skb_any(skb);
637 }
638 } else {
639 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
640 pm_tx_cb->ipa_tx_desc);
641 }
Yun Parke74e6092018-04-27 11:36:34 -0700642
643 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
644 }
645 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
646
647 ipa_ctx->stats.num_tx_dequeued += dequeued;
648 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
649 ipa_ctx->stats.num_max_pm_queue = dequeued;
650}
651
jiadae9959f2018-05-08 11:19:07 +0800652int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
653{
654 if (!num_buf) {
655 ipa_info("No buffers to map/unmap");
656 return 0;
657 }
658
659 if (map)
660 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
661 else
662 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
663}
664
Jia Ding70deca72019-07-24 18:18:57 +0800665#ifdef MDM_PLATFORM
666/**
667 * is_rx_dest_bridge_dev() - is RX skb bridge device terminated
668 * @iface_ctx: pointer to WLAN IPA interface context
669 * @nbuf: skb buffer
670 *
671 * Check if skb is destined for bridge device, where SAP is a bridge
672 * port of it.
673 *
674 * FIXME: If there's a BH lockless API to check if destination MAC
675 * address is a valid peer, this check can be deleted. Currently
676 * dp_find_peer_by_addr() is used to check if destination MAC
677 * is a valid peer. Since WLAN IPA RX is in process context,
678 * qdf_spin_lock_bh in dp_find_peer_by_addr() turns to spin_lock_bh
679 * and this BH lock hurts netif_rx.
680 *
681 * Return: true/false
682 */
683static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
684 qdf_nbuf_t nbuf)
685{
686 qdf_netdev_t master_ndev;
687 qdf_netdev_t ndev;
688 struct ethhdr *eh;
689 uint8_t da_is_bcmc;
690 bool ret;
691
692 if (iface_ctx->device_mode != QDF_SAP_MODE)
693 return false;
694
695 /*
696 * WDI 3.0 skb->cb[] info from IPA driver
697 * skb->cb[0] = vdev_id
698 * skb->cb[1].bit#1 = da_is_bcmc
699 */
700 da_is_bcmc = ((uint8_t)nbuf->cb[1]) & 0x2;
701 if (da_is_bcmc)
702 return false;
703
704 ndev = iface_ctx->dev;
705 if (!ndev)
706 return false;
707
708 if (!netif_is_bridge_port(ndev))
709 return false;
710
711 rcu_read_lock();
712
713 master_ndev = netdev_master_upper_dev_get_rcu(ndev);
714 if (!master_ndev) {
715 ret = false;
716 goto out;
717 }
718
719 eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
720 if (qdf_mem_cmp(eh->h_dest, master_ndev->dev_addr, QDF_MAC_ADDR_SIZE)) {
721 ret = false;
722 goto out;
723 }
724
725 ret = true;
726
727out:
728 rcu_read_unlock();
729 return ret;
730}
731#else /* !MDM_PLATFORM */
732static bool is_rx_dest_bridge_dev(struct wlan_ipa_iface_context *iface_ctx,
733 qdf_nbuf_t nbuf)
734{
735 return false;
736}
737#endif /* MDM_PLATFORM */
738
jiad90b17252019-03-25 15:22:42 +0800739static enum wlan_ipa_forward_type
740wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
741 struct wlan_ipa_iface_context *iface_ctx,
742 qdf_nbuf_t nbuf)
743{
744 uint8_t fw_desc = 0;
745 bool fwd_success;
746 int ret;
747
748 /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
749 if (ipa_ctx->wdi_version != IPA_WDI_3) {
750 fw_desc = (uint8_t)nbuf->cb[1];
751 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
752 nbuf);
753 }
754
Jia Ding70deca72019-07-24 18:18:57 +0800755 if (is_rx_dest_bridge_dev(iface_ctx, nbuf)) {
756 fwd_success = 0;
757 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
758 goto exit;
759 }
760
jiad90b17252019-03-25 15:22:42 +0800761 if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
762 nbuf, &fwd_success)) {
763 ipa_ctx->ipa_rx_internal_drop_count++;
764 ipa_ctx->ipa_rx_discard++;
765
766 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
767 } else {
768 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
769 }
770
Jia Ding70deca72019-07-24 18:18:57 +0800771exit:
jiad90b17252019-03-25 15:22:42 +0800772 if (fwd_success)
773 ipa_ctx->stats.num_tx_fwd_ok++;
774 else
775 ipa_ctx->stats.num_tx_fwd_err++;
776
777 return ret;
778}
779
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530780#else /* CONFIG_IPA_WDI_UNIFIED_API */
781
782static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
783{
784}
785
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530786static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
787 qdf_device_t osdev)
788{
789 return qdf_mem_smmu_s1_enabled(osdev);
790}
791
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530792static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
793 qdf_device_t osdev)
794{
795 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
796 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
797 wlan_ipa_wdi_meter_notifier_cb,
798 ipa_ctx->config->desc_size,
799 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
800 &ipa_ctx->tx_pipe_handle,
801 &ipa_ctx->rx_pipe_handle);
802}
803
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530804static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
805{
806 struct ipa_wdi_uc_ready_params uc_ready_param;
807
808 ipa_ctx->uc_loaded = false;
809 uc_ready_param.priv = (void *)ipa_ctx;
810 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
811 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
812 ipa_info("UC Ready CB register fail");
813 return QDF_STATUS_E_FAILURE;
814 }
815
816 if (true == uc_ready_param.is_uC_ready) {
817 ipa_info("UC Ready");
818 ipa_ctx->uc_loaded = true;
819 } else {
820 return QDF_STATUS_E_BUSY;
821 }
822
823 return QDF_STATUS_SUCCESS;
824}
825
826static inline int wlan_ipa_wdi_cleanup(void)
827{
828 int ret;
829
830 ret = qdf_ipa_uc_dereg_rdyCB();
831 if (ret)
832 ipa_info("UC Ready CB deregister fail");
833 return ret;
834}
835
836static inline int wlan_ipa_wdi_setup_sys_pipe(
837 struct wlan_ipa_priv *ipa_ctx,
838 struct ipa_sys_connect_params *sys, uint32_t *handle)
839{
840 return qdf_ipa_setup_sys_pipe(sys, handle);
841}
842
843static inline int wlan_ipa_wdi_teardown_sys_pipe(
844 struct wlan_ipa_priv *ipa_ctx,
845 uint32_t handle)
846{
847 return qdf_ipa_teardown_sys_pipe(handle);
848}
849
Yun Parke74e6092018-04-27 11:36:34 -0700850/**
851 * wlan_ipa_pm_flush() - flush queued packets
852 * @work: pointer to the scheduled work
853 *
854 * Called during PM resume to send packets to TL which were queued
855 * while host was in the process of suspending.
856 *
857 * Return: None
858 */
859static void wlan_ipa_pm_flush(void *data)
860{
861 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
862 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
863 qdf_nbuf_t skb;
864 uint32_t dequeued = 0;
865
866 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
867 WIFI_POWER_EVENT_WAKELOCK_IPA);
868 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
869 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
870 NULL)) {
871 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
872
873 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
874 dequeued++;
875
jiadab8cea02018-05-24 09:16:14 +0800876 if (pm_tx_cb->exception) {
877 if (ipa_ctx->softap_xmit &&
878 pm_tx_cb->iface_context->dev) {
879 ipa_ctx->softap_xmit(skb,
880 pm_tx_cb->iface_context->dev);
881 ipa_ctx->stats.num_tx_fwd_ok++;
882 } else {
883 dev_kfree_skb_any(skb);
884 }
885 } else {
886 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
887 pm_tx_cb->ipa_tx_desc);
888 }
Yun Parke74e6092018-04-27 11:36:34 -0700889
890 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
891 }
892 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
893 qdf_wake_lock_release(&ipa_ctx->wake_lock,
894 WIFI_POWER_EVENT_WAKELOCK_IPA);
895
896 ipa_ctx->stats.num_tx_dequeued += dequeued;
897 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
898 ipa_ctx->stats.num_max_pm_queue = dequeued;
899}
900
jiadae9959f2018-05-08 11:19:07 +0800901int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
902{
903 if (!num_buf) {
904 ipa_info("No buffers to map/unmap");
905 return 0;
906 }
907
908 if (map)
909 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
910 else
911 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
912}
913
jiad90b17252019-03-25 15:22:42 +0800914static enum wlan_ipa_forward_type
915wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
916 struct wlan_ipa_iface_context *iface_ctx,
917 qdf_nbuf_t nbuf)
918{
919 uint8_t fw_desc;
920
921 fw_desc = (uint8_t)nbuf->cb[1];
922
923 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
924}
925
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530926#endif /* CONFIG_IPA_WDI_UNIFIED_API */
927
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530928/**
929 * wlan_ipa_send_skb_to_network() - Send skb to kernel
930 * @skb: network buffer
931 * @iface_ctx: IPA interface context
932 *
933 * Called when a network buffer is received which should not be routed
934 * to the IPA module.
935 *
936 * Return: None
937 */
938static void
939wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
940 struct wlan_ipa_iface_context *iface_ctx)
941{
942 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
943
944 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800945 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530946 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800947 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530948 return;
949 }
950
951 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
952
953 if (ipa_ctx->send_to_nw)
954 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
955
956 ipa_ctx->ipa_rx_net_send_count++;
957}
958
959/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530960 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530961 * @priv: pointer to private data registered with IPA (we register a
962 * pointer to the global IPA context)
963 * @evt: the IPA event which triggered the callback
964 * @data: data associated with the event
965 *
966 * Return: None
967 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530968static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
969 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530970{
971 struct wlan_ipa_priv *ipa_ctx = NULL;
972 qdf_nbuf_t skb;
973 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700974 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530975 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530976
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530977 ipa_ctx = (struct wlan_ipa_priv *)priv;
978 if (!ipa_ctx) {
979 if (evt == IPA_RECEIVE) {
980 skb = (qdf_nbuf_t)data;
981 dev_kfree_skb_any(skb);
982 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530983 return;
984 }
985
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530986 switch (evt) {
987 case IPA_RECEIVE:
988 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530989 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
990 session_id = (uint8_t)skb->cb[0];
991 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530992 } else {
993 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
994 }
995 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700996 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
997 iface_id, session_id, (uint8_t)skb->cb[1],
998 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530999 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +08001000 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301001 return;
1002 }
1003
1004 iface_context = &ipa_ctx->iface_context[iface_id];
1005 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +08001006 ipa_err_rl("TL context of iface_id %u is NULL",
1007 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301008 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +08001009 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301010 return;
1011 }
1012
1013 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1014 ipa_ctx->stats.num_rx_excep++;
1015 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
1016 } else {
1017 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
1018 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301019 iface_context->stats.num_rx_ipa_excep++;
1020
1021 /* Disable to forward Intra-BSS Rx packets when
1022 * ap_isolate=1 in hostapd.conf
1023 */
1024 if (!ipa_ctx->ap_intrabss_fwd) {
1025 /*
1026 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
1027 * all Rx packets to IPA uC, which need to be forwarded
1028 * to other interface.
1029 * And, IPA driver will send back to WLAN host driver
1030 * through exception pipe with fw_desc field set by FW.
1031 * Here we are checking fw_desc field for FORWARD bit
1032 * set, and forward to Tx. Then copy to kernel stack
1033 * only when DISCARD bit is not set.
1034 */
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301035 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
jiad90b17252019-03-25 15:22:42 +08001036 wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
1037 skb))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301038 break;
1039 } else {
jiadf3ecc752018-07-05 14:36:03 +08001040 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301041 }
1042
1043 wlan_ipa_send_skb_to_network(skb, iface_context);
1044 break;
1045
1046 default:
jiadf3ecc752018-07-05 14:36:03 +08001047 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301048 return;
1049 }
1050}
1051
jiad7bac1ef2019-07-03 11:30:24 +08001052#ifndef MDM_PLATFORM
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301053/**
jitiphilfdcaaba2018-09-03 16:19:52 +05301054 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
1055 * @priv: pointer to private data registered with IPA (we register a
1056 * pointer to the global IPA context)
1057 * @evt: the IPA event which triggered the callback
1058 * @data: data associated with the event
1059 *
1060 * Return: None
1061 */
1062static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1063 unsigned long data)
1064{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001065 struct qdf_op_sync *op_sync;
1066
1067 if (qdf_op_protect(&op_sync)) {
1068 if (evt == IPA_RECEIVE) {
1069 struct wlan_ipa_priv *ipa_ctx = priv;
1070 qdf_nbuf_t skb = (qdf_nbuf_t)data;
1071
1072 ipa_ctx->ipa_rx_internal_drop_count++;
1073 dev_kfree_skb_any(skb);
1074 }
1075
1076 return;
1077 }
1078
jitiphilfdcaaba2018-09-03 16:19:52 +05301079 __wlan_ipa_w2i_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001080
1081 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301082}
jiad7bac1ef2019-07-03 11:30:24 +08001083#else /* MDM_PLATFORM */
1084static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1085 unsigned long data)
1086{
1087 __wlan_ipa_w2i_cb(priv, evt, data);
1088}
1089#endif /* MDM_PLATFORM */
jitiphilfdcaaba2018-09-03 16:19:52 +05301090
1091/**
1092 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301093 * @priv: pointer to private data registered with IPA (we register a
1094 * pointer to the interface-specific IPA context)
1095 * @evt: the IPA event which triggered the callback
1096 * @data: data associated with the event
1097 *
1098 * Return: None
1099 */
jitiphilfdcaaba2018-09-03 16:19:52 +05301100static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1101 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301102{
1103 struct wlan_ipa_priv *ipa_ctx = NULL;
1104 qdf_ipa_rx_data_t *ipa_tx_desc;
1105 struct wlan_ipa_iface_context *iface_context;
1106 qdf_nbuf_t skb;
1107 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
1108
1109 iface_context = (struct wlan_ipa_iface_context *)priv;
1110 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1111 ipa_ctx = iface_context->ipa_ctx;
1112
1113 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +08001114 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301115 ipa_free_skb(ipa_tx_desc);
1116 iface_context->stats.num_tx_drop++;
1117 return;
1118 }
1119
1120 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
1121
1122 /*
1123 * If PROD resource is not requested here then there may be cases where
1124 * IPA hardware may be clocked down because of not having proper
1125 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
1126 * workaround to request PROD resource while data is going over CONS
1127 * pipe to prevent the IPA hardware clockdown.
1128 */
1129 wlan_ipa_wdi_rm_request(ipa_ctx);
1130
1131 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1132 /*
1133 * If host is still suspended then queue the packets and these will be
1134 * drained later when resume completes. When packet is arrived here and
1135 * host is suspended, this means that there is already resume is in
1136 * progress.
1137 */
1138 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +08001139 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301140 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
1141 pm_tx_cb->iface_context = iface_context;
1142 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
1143 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
1144 ipa_ctx->stats.num_tx_queued++;
1145
1146 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1147 return;
1148 }
1149
1150 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1151
1152 /*
1153 * If we are here means, host is not suspended, wait for the work queue
1154 * to finish.
1155 */
1156 qdf_flush_work(&ipa_ctx->pm_work);
1157
1158 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
1159}
1160
jitiphilfdcaaba2018-09-03 16:19:52 +05301161/**
1162 * wlan_ipa_i2w_cb() - IPA to WLAN callback
1163 * @priv: pointer to private data registered with IPA (we register a
1164 * pointer to the interface-specific IPA context)
1165 * @evt: the IPA event which triggered the callback
1166 * @data: data associated with the event
1167 *
1168 * Return: None
1169 */
1170static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1171 unsigned long data)
1172{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001173 struct qdf_op_sync *op_sync;
1174
1175 if (qdf_op_protect(&op_sync)) {
1176 qdf_ipa_rx_data_t *ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1177 struct wlan_ipa_iface_context *iface_context = priv;
1178
1179 ipa_free_skb(ipa_tx_desc);
1180 iface_context->stats.num_tx_drop++;
1181
1182 return;
1183 }
1184
jitiphilfdcaaba2018-09-03 16:19:52 +05301185 __wlan_ipa_i2w_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001186
1187 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301188}
1189
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301190QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
1191{
1192 /*
1193 * Check if IPA is ready for suspend, If we are here means, there is
1194 * high chance that suspend would go through but just to avoid any race
1195 * condition after suspend started, these checks are conducted before
1196 * allowing to suspend.
1197 */
1198 if (atomic_read(&ipa_ctx->tx_ref_cnt))
1199 return QDF_STATUS_E_AGAIN;
1200
Yun Parke74e6092018-04-27 11:36:34 -07001201 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301202 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301203
1204 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1205 ipa_ctx->suspended = true;
1206 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1207
Alok Kumare888e802019-09-23 18:31:09 +05301208 if (ipa_ctx->config->ipa_force_voting &&
1209 !ipa_ctx->ipa_pipes_down)
1210 wlan_ipa_set_perf_level(ipa_ctx,
1211 ipa_ctx->config->bus_bw_high,
1212 ipa_ctx->config->bus_bw_high);
1213
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301214 return QDF_STATUS_SUCCESS;
1215}
1216
1217QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
1218{
1219 qdf_sched_work(0, &ipa_ctx->pm_work);
1220
1221 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1222 ipa_ctx->suspended = false;
1223 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1224
1225 return QDF_STATUS_SUCCESS;
1226}
1227
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301228QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1229{
1230 int result;
1231
1232 ipa_debug("enter");
1233
1234 if (!ipa_ctx->ipa_pipes_down) {
1235 /*
1236 * IPA WDI Pipes are already activated due to
1237 * rm deferred resources grant
1238 */
1239 ipa_warn("IPA WDI Pipes are already activated");
1240 goto end;
1241 }
1242
1243 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1244 ipa_ctx->dp_pdev);
1245 if (result) {
1246 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1247 return QDF_STATUS_E_FAILURE;
1248 }
1249
1250 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1251 ipa_ctx->ipa_pipes_down = false;
1252
1253 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1254 ipa_ctx->dp_pdev);
1255
1256end:
1257 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1258
1259 return QDF_STATUS_SUCCESS;
1260}
1261
1262QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1263{
1264 int result;
1265
1266 ipa_debug("enter");
1267
1268 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301269 ipa_warn("IPA WDI Pipes are already deactivated");
1270 goto end;
1271 }
1272
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301273 qdf_spin_lock_bh(&ipa_ctx->pipes_down_lock);
1274 if (ipa_ctx->pipes_down_in_progress || ipa_ctx->ipa_pipes_down) {
1275 ipa_warn("IPA WDI Pipes down already in progress");
1276 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1277 return QDF_STATUS_E_ALREADY;
1278 }
1279 ipa_ctx->pipes_down_in_progress = true;
1280 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1281
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301282 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1283 ipa_ctx->dp_pdev);
1284
1285 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1286 ipa_ctx->dp_pdev);
1287 if (result) {
1288 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301289 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301290 return QDF_STATUS_E_FAILURE;
1291 }
1292
1293 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301294 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301295
1296end:
1297 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1298
1299 return QDF_STATUS_SUCCESS;
1300}
1301
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301302/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301303 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1304 * @ipa_ctx: Global IPA IPA context
1305 * @sta_add: Should station be added
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301306 * @mac_addr: mac address of station being queried
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301307 *
1308 * Return: true if the station was found
1309 */
1310static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301311 bool sta_add,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301312 uint8_t *mac_addr)
1313{
1314 bool sta_found = false;
1315 uint8_t idx;
1316
1317 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1318 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301319 (qdf_is_macaddr_equal(
1320 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1321 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301322 sta_found = true;
1323 break;
1324 }
1325 }
1326 if (sta_add && sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301327 ipa_err("STA already exist, cannot add: " QDF_MAC_ADDR_STR,
1328 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301329 return sta_found;
1330 }
1331 if (sta_add) {
1332 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1333 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1334 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301335 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1336 mac_addr, mac_addr,
1337 QDF_NET_ETH_LEN);
1338 return sta_found;
1339 }
1340 }
1341 }
1342 if (!sta_add && !sta_found) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301343 ipa_err("STA does not exist, cannot delete: " QDF_MAC_ADDR_STR,
1344 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301345 return sta_found;
1346 }
1347 if (!sta_add) {
1348 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1349 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301350 (qdf_is_macaddr_equal(
1351 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1352 (struct qdf_mac_addr *)mac_addr))) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301353 ipa_ctx->assoc_stas_map[idx].is_reserved =
1354 false;
hangtian127c9532019-01-12 13:29:07 +08001355 qdf_mem_zero(
1356 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1357 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301358 return sta_found;
1359 }
1360 }
1361 }
1362
1363 return sta_found;
1364}
1365
1366/**
1367 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1368 * @ipa_ctx: IPA context
1369 * @session_id: Session ID
1370 *
1371 * Return: None
1372 */
1373static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1374 uint8_t session_id)
1375{
1376 struct wlan_ipa_iface_context *iface_ctx;
1377 int i;
1378
1379 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1380 iface_ctx = &ipa_ctx->iface_context[i];
1381 if (iface_ctx->session_id == session_id)
1382 break;
1383 }
1384
1385 return i;
1386}
1387
1388/**
1389 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1390 * @iface_context: interface-specific IPA context
1391 *
1392 * Return: None
1393 */
1394static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1395{
1396 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1397
1398 ipa_debug("enter");
1399
1400 if (!iface_context->tl_context)
1401 return;
1402
1403 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1404 iface_context->dev->name,
1405 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1406
1407 qdf_spin_lock_bh(&iface_context->interface_lock);
1408 iface_context->tl_context = NULL;
1409 iface_context->dev = NULL;
1410 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1411 iface_context->session_id = WLAN_IPA_MAX_SESSION;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301412 qdf_spin_unlock_bh(&iface_context->interface_lock);
1413 iface_context->ifa_address = 0;
1414 if (!iface_context->ipa_ctx->num_iface) {
1415 ipa_err("NUM INTF 0, Invalid");
1416 QDF_ASSERT(0);
1417 }
1418 iface_context->ipa_ctx->num_iface--;
1419 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1420}
1421
1422/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301423 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1424 * @skb: packet buffer which was transmitted
1425 *
1426 * Return: None
1427 */
1428static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1429{
1430 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1431 qdf_ipa_rx_data_t *ipa_tx_desc;
1432 struct wlan_ipa_tx_desc *tx_desc;
1433 uint16_t id;
Chaoli Zhoufd8d2822019-09-25 15:32:04 +08001434 struct wlan_objmgr_pdev *pdev;
1435 struct wlan_objmgr_psoc *psoc;
1436 qdf_device_t osdev;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301437
1438 if (!qdf_nbuf_ipa_owned_get(skb)) {
1439 dev_kfree_skb_any(skb);
1440 return;
1441 }
1442
Chaoli Zhoufd8d2822019-09-25 15:32:04 +08001443 if (!ipa_ctx)
1444 return;
1445 pdev = ipa_ctx->pdev;
1446 psoc = wlan_pdev_get_psoc(pdev);
1447 osdev = wlan_psoc_get_qdf_dev(psoc);
1448
1449 if (osdev && qdf_mem_smmu_s1_enabled(osdev)) {
1450 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
1451 qdf_dma_addr_t paddr = QDF_NBUF_CB_PADDR(skb);
1452
1453 qdf_nbuf_mapped_paddr_set(skb,
1454 paddr -
1455 WLAN_IPA_WLAN_FRAG_HEADER -
1456 WLAN_IPA_WLAN_IPA_HEADER);
1457 }
1458
1459 qdf_nbuf_unmap(osdev, skb, QDF_DMA_TO_DEVICE);
1460 }
1461
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301462 /* Get Tx desc pointer from SKB CB */
1463 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1464 tx_desc = &ipa_ctx->tx_desc_pool[id];
1465 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1466
1467 /* Return Tx Desc to IPA */
1468 qdf_ipa_free_skb(ipa_tx_desc);
1469
1470 /* Return to free tx desc list */
1471 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1472 tx_desc->ipa_tx_desc_ptr = NULL;
1473 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1474 ipa_ctx->stats.num_tx_desc_q_cnt--;
1475 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1476
1477 ipa_ctx->stats.num_tx_comp_cnt++;
1478
1479 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1480
1481 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1482}
1483
1484/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301485 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1486 * @ipa_ctx: IPA IPA global context
1487 * @net_dev: Interface net device
1488 * @device_mode: Net interface device mode
1489 * @adapter: Interface upon which IPA is being setup
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301490 * @session_id: Station ID of the API instance
1491 *
1492 * Return: QDF STATUS
1493 */
1494static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1495 qdf_netdev_t net_dev,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301496 uint8_t device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301497 uint8_t session_id)
1498{
1499 struct wlan_ipa_iface_context *iface_context = NULL;
1500 void *tl_context = NULL;
1501 int i;
1502 QDF_STATUS status;
1503
1504 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1505 * channel change indication. Since these indications are sent by lower
1506 * layer as SAP updates and IPA doesn't have to do anything for these
1507 * updates so ignoring!
1508 */
1509 if (device_mode == QDF_SAP_MODE) {
1510 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1511 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001512 if (iface_context->dev == net_dev) {
1513 ipa_debug("found iface %u device_mode %u",
1514 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301515 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001516 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301517 }
1518 }
1519
Yun Park21ec4902018-04-24 12:11:01 -07001520 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1521 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1522 status = QDF_STATUS_E_NOMEM;
1523 QDF_ASSERT(0);
1524 goto end;
1525 }
1526
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301527 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001528 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301529 iface_context = &(ipa_ctx->iface_context[i]);
1530 break;
1531 }
1532 }
1533
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001534 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301535 ipa_err("All the IPA interfaces are in use");
1536 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001537 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301538 goto end;
1539 }
1540
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301541 tl_context = (void *)cdp_get_vdev_from_vdev_id(ipa_ctx->dp_soc,
1542 ipa_ctx->dp_pdev,
1543 session_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001544 if (!tl_context) {
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301545 ipa_err("Not able to get TL context session_id: %d",
1546 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301547 status = QDF_STATUS_E_INVAL;
1548 goto end;
1549 }
1550
1551 iface_context->tl_context = tl_context;
1552 iface_context->dev = net_dev;
1553 iface_context->device_mode = device_mode;
1554 iface_context->session_id = session_id;
1555
1556 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1557 net_dev->dev_addr,
1558 iface_context->prod_client,
1559 iface_context->cons_client,
1560 session_id,
1561 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1562 if (status != QDF_STATUS_SUCCESS)
1563 goto end;
1564
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301565 /* Register IPA Tx desc free callback */
1566 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1567
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301568 ipa_ctx->num_iface++;
1569
1570 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1571
1572 return status;
1573
1574end:
1575 if (iface_context)
1576 wlan_ipa_cleanup_iface(iface_context);
1577
1578 return status;
1579}
1580
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301581#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1582/**
1583 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1584 * @ipa_ctx: IPA context
1585 *
1586 * Return: QDF STATUS
1587 */
1588static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1589{
1590 ipa_debug("enter");
1591
1592 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1593 ipa_err("IPA WDI Pipe activation failed");
1594 return QDF_STATUS_E_BUSY;
1595 }
1596
1597 ipa_debug("exit");
1598
1599 return QDF_STATUS_SUCCESS;
1600}
1601
1602/**
1603 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1604 * @ipa_ctx: IPA context
1605 *
1606 * Return: None
1607 */
1608static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1609{
1610 ipa_debug("enter");
1611
1612 wlan_ipa_uc_disable_pipes(ipa_ctx);
1613
1614 ipa_debug("exit: IPA WDI Pipes deactivated");
1615}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301616
1617bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1618{
1619 return !ipa_ctx->ipa_pipes_down;
1620}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301621#else
1622
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301623/**
1624 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1625 * @ipa_ctx: IPA context
1626 *
1627 * Return: QDF STATUS
1628 */
1629static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1630{
1631 ipa_debug("enter");
1632
1633 ipa_ctx->activated_fw_pipe = 0;
1634 ipa_ctx->resource_loading = true;
1635
1636 /* If RM feature enabled
1637 * Request PROD Resource first
1638 * PROD resource may return sync or async manners
1639 */
1640 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001641 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1642 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301643 /* RM PROD request sync return
1644 * enable pipe immediately
1645 */
1646 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1647 ipa_err("IPA WDI Pipe activation failed");
1648 ipa_ctx->resource_loading = false;
1649 return QDF_STATUS_E_BUSY;
1650 }
1651 } else {
1652 ipa_err("IPA WDI Pipe activation deferred");
1653 }
1654 } else {
1655 /* RM Disabled
1656 * Just enabled all the PIPEs
1657 */
1658 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1659 ipa_err("IPA WDI Pipe activation failed");
1660 ipa_ctx->resource_loading = false;
1661 return QDF_STATUS_E_BUSY;
1662 }
1663 ipa_ctx->resource_loading = false;
1664 }
1665
1666 ipa_debug("exit");
1667
1668 return QDF_STATUS_SUCCESS;
1669}
1670
1671/**
1672 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1673 * @ipa_ctx: IPA context
1674 *
1675 * Return: None
1676 */
1677static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1678{
1679 ipa_debug("enter");
1680
1681 ipa_ctx->resource_unloading = true;
1682 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1683 ipa_info("Disable FW RX PIPE");
1684 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301685
1686 ipa_debug("exit: IPA WDI Pipes deactivated");
1687}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301688
1689bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1690{
1691 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1692}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301693#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301694
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301695static inline
1696bool wlan_sap_no_client_connected(struct wlan_ipa_priv *ipa_ctx)
1697{
1698 return !(ipa_ctx->sap_num_connected_sta);
1699}
1700
1701static inline
1702bool wlan_sta_is_connected(struct wlan_ipa_priv *ipa_ctx)
1703{
1704 return ipa_ctx->sta_connected;
1705}
1706
1707static inline
1708bool wlan_ipa_uc_is_loaded(struct wlan_ipa_priv *ipa_ctx)
1709{
1710 return ipa_ctx->uc_loaded;
1711}
1712
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301713/**
1714 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1715 * @ipa_ctx: global IPA context
1716 * @offload_type: MCC or SCC
1717 * @session_id: Session Id
1718 * @enable: TX offload enable or disable
1719 *
1720 * Return: none
1721 */
1722static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1723 uint32_t offload_type,
1724 uint8_t session_id,
1725 bool enable)
1726{
1727
1728 struct ipa_uc_offload_control_params req = {0};
1729
1730 if (session_id >= WLAN_IPA_MAX_SESSION) {
1731 ipa_err("invalid session id: %d", session_id);
1732 return;
1733 }
1734
1735 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301736 ipa_info("IPA offload status is already set");
1737 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301738 offload_type, session_id, enable);
1739 return;
1740 }
1741
1742 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1743 offload_type, session_id, enable);
1744
1745 req.offload_type = offload_type;
1746 req.vdev_id = session_id;
1747 req.enable = enable;
1748
1749 if (QDF_STATUS_SUCCESS !=
1750 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1751 ipa_err("Fail to enable IPA offload");
1752 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1753 offload_type, session_id, enable);
1754 } else {
1755 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1756 }
1757}
1758
1759/**
1760 * __wlan_ipa_wlan_evt() - IPA event handler
1761 * @net_dev: Interface net device
1762 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301763 * @session_id: session id for the event
1764 * @type: event enum of type ipa_wlan_event
1765 * @mac_address: MAC address associated with the event
1766 *
1767 * This function is meant to be called from within wlan_ipa_ctx.c
1768 *
1769 * Return: QDF STATUS
1770 */
1771static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301772 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301773 qdf_ipa_wlan_event type,
1774 uint8_t *mac_addr)
1775{
1776 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1777 struct wlan_ipa_iface_context *iface_ctx = NULL;
1778 qdf_ipa_msg_meta_t meta;
1779 qdf_ipa_wlan_msg_t *msg;
1780 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1781 int i;
1782 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001783 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301784 struct wlan_objmgr_pdev *pdev;
1785 struct wlan_objmgr_psoc *psoc;
1786 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301787
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301788 ipa_debug("%s: EVT: %d, MAC: %pM, session_id: %u",
1789 net_dev->name, type, mac_addr, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301790
1791 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1792 return QDF_STATUS_E_INVAL;
1793
1794 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1795 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1796 (device_mode != QDF_SAP_MODE)) {
1797 return QDF_STATUS_SUCCESS;
1798 }
1799
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301800 pdev = ipa_ctx->pdev;
1801 psoc = wlan_pdev_get_psoc(pdev);
1802 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1803 WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301804 QDF_BUG(session_id < WLAN_IPA_MAX_SESSION);
1805
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301806 if (vdev)
1807 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301808 else
1809 ipa_err("vdev is NULL, session_id: %u", session_id);
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301810
Ryan Hsub5783cf2018-05-14 12:13:15 -07001811 if (ipa_ctx->sta_connected) {
1812 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1813 if (iface_ctx)
1814 sta_session_id = iface_ctx->session_id;
1815 else
1816 ipa_err("sta iface_ctx is NULL");
1817 }
1818
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301819 /*
1820 * During IPA UC resource loading/unloading new events can be issued.
1821 */
1822 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1823 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1824 unsigned int pending_event_count;
1825 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1826
1827 ipa_info("Event:%d IPA resource %s inprogress", type,
1828 ipa_ctx->resource_loading ?
1829 "load" : "unload");
1830
1831 /* Wait until completion of the long/unloading */
1832 status = qdf_wait_for_event_completion(
1833 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001834 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301835 if (status != QDF_STATUS_SUCCESS) {
1836 /*
1837 * If timed out, store the events separately and
1838 * handle them later.
1839 */
1840 ipa_info("IPA resource %s timed out",
1841 ipa_ctx->resource_loading ?
1842 "load" : "unload");
1843
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301844 if (type == QDF_IPA_AP_DISCONNECT) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301845 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1846 SIR_AP_RX_DATA_OFFLOAD,
1847 session_id, false);
Vevek Venkatesaned315cd2019-06-10 23:35:19 +05301848 } else if (type == QDF_IPA_CLIENT_CONNECT_EX &&
1849 wlan_sap_no_client_connected(ipa_ctx)) {
1850 if (wlan_sta_is_connected(ipa_ctx) &&
1851 wlan_ipa_uc_is_loaded(ipa_ctx) &&
1852 wlan_ipa_uc_sta_is_enabled(ipa_ctx->
1853 config) &&
1854 !wlan_ipa_is_sta_only_offload_enabled()) {
1855 wlan_ipa_uc_offload_enable_disable(
1856 ipa_ctx,
1857 SIR_STA_RX_DATA_OFFLOAD,
1858 sta_session_id, true);
1859 }
1860 }
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301861
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301862 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1863
1864 pending_event_count =
1865 qdf_list_size(&ipa_ctx->pending_event);
1866 if (pending_event_count >=
1867 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1868 ipa_info("Reached max pending evt count");
1869 qdf_list_remove_front(
1870 &ipa_ctx->pending_event,
1871 (qdf_list_node_t **)&pending_event);
1872 } else {
1873 pending_event =
1874 (struct wlan_ipa_uc_pending_event *)
1875 qdf_mem_malloc(sizeof(
1876 struct wlan_ipa_uc_pending_event));
1877 }
1878
1879 if (!pending_event) {
1880 ipa_err("Pending event memory alloc fail");
1881 qdf_mutex_release(&ipa_ctx->ipa_lock);
1882 return QDF_STATUS_E_NOMEM;
1883 }
1884
1885 pending_event->net_dev = net_dev;
1886 pending_event->device_mode = device_mode;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301887 pending_event->session_id = session_id;
1888 pending_event->type = type;
1889 pending_event->is_loading = ipa_ctx->resource_loading;
1890 qdf_mem_copy(pending_event->mac_addr,
1891 mac_addr, QDF_MAC_ADDR_SIZE);
1892 qdf_list_insert_back(&ipa_ctx->pending_event,
1893 &pending_event->node);
1894
1895 qdf_mutex_release(&ipa_ctx->ipa_lock);
1896
Yun Park21ec4902018-04-24 12:11:01 -07001897 /* Cleanup interface */
1898 if (type == QDF_IPA_STA_DISCONNECT ||
1899 type == QDF_IPA_AP_DISCONNECT) {
1900 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1901 iface_ctx = &ipa_ctx->iface_context[i];
1902
1903 if (iface_ctx->dev == net_dev)
1904 break;
1905 }
1906 if (iface_ctx)
1907 wlan_ipa_cleanup_iface(iface_ctx);
1908 }
1909
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301910 return QDF_STATUS_SUCCESS;
1911 }
1912 ipa_info("IPA resource %s completed",
1913 ipa_ctx->resource_loading ?
1914 "load" : "unload");
1915 }
1916
1917 ipa_ctx->stats.event[type]++;
1918
1919 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1920 switch (type) {
1921 case QDF_IPA_STA_CONNECT:
1922 qdf_mutex_acquire(&ipa_ctx->event_lock);
1923
1924 /* STA already connected and without disconnect, connect again
1925 * This is Roaming scenario
1926 */
1927 if (ipa_ctx->sta_connected) {
1928 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1929 if (iface_ctx)
1930 wlan_ipa_cleanup_iface(iface_ctx);
1931 }
1932
1933 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05301934 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301935 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001936 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301937 qdf_mutex_release(&ipa_ctx->event_lock);
1938 goto end;
1939 }
1940
Yu Tian0cc79c72019-09-18 15:11:32 +08001941 ipa_ctx->vdev_to_iface[session_id] =
1942 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1943
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301944 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08001945 (ipa_ctx->sap_num_connected_sta > 0 ||
1946 wlan_ipa_is_sta_only_offload_enabled()) &&
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301947 !ipa_ctx->sta_connected) {
1948 qdf_mutex_release(&ipa_ctx->event_lock);
1949 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1950 SIR_STA_RX_DATA_OFFLOAD, session_id,
1951 true);
1952 qdf_mutex_acquire(&ipa_ctx->event_lock);
1953 }
1954
jiad72b69a92019-04-11 17:23:10 +08001955 if (!wlan_ipa_is_sta_only_offload_enabled()) {
1956 ipa_debug("IPA STA only offload not enabled");
1957 } else if (ipa_ctx->uc_loaded &&
1958 !ipa_ctx->sap_num_connected_sta &&
1959 !ipa_ctx->sta_connected) {
1960 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1961 if (status) {
1962 qdf_mutex_release(&ipa_ctx->event_lock);
1963 ipa_info("handle 1st conn failed %d", status);
1964 wlan_ipa_uc_offload_enable_disable(
1965 ipa_ctx,
1966 SIR_STA_RX_DATA_OFFLOAD,
1967 session_id,
1968 false);
Yu Tian0cc79c72019-09-18 15:11:32 +08001969 ipa_ctx->vdev_to_iface[session_id] =
1970 WLAN_IPA_MAX_SESSION;
jiad72b69a92019-04-11 17:23:10 +08001971 goto end;
1972 }
1973 }
1974
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301975 ipa_ctx->sta_connected = 1;
1976
1977 qdf_mutex_release(&ipa_ctx->event_lock);
1978
Mohit Khannacabf5e72018-07-24 13:28:43 -07001979 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1980 ipa_ctx->sta_connected,
1981 session_id,
1982 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301983 break;
1984
1985 case QDF_IPA_AP_CONNECT:
1986 qdf_mutex_acquire(&ipa_ctx->event_lock);
1987
1988 /* For DFS channel we get two start_bss event (before and after
1989 * CAC). Also when ACS range includes both DFS and non DFS
1990 * channels, we could possibly change channel many times due to
1991 * RADAR detection and chosen channel may not be a DFS channels.
1992 * So dont return error here. Just discard the event.
1993 */
jiadc908ada2018-05-11 14:40:54 +08001994 if (ipa_ctx->vdev_to_iface[session_id] !=
1995 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301996 qdf_mutex_release(&ipa_ctx->event_lock);
1997 return 0;
1998 }
1999
2000 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302001 session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302002 if (status != QDF_STATUS_SUCCESS) {
2003 qdf_mutex_release(&ipa_ctx->event_lock);
2004 ipa_err("%s: Evt: %d, Interface setup failed",
2005 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
2006 goto end;
2007 }
2008
2009 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2010 qdf_mutex_release(&ipa_ctx->event_lock);
2011 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2012 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
2013 qdf_mutex_acquire(&ipa_ctx->event_lock);
2014 }
2015
2016 ipa_ctx->vdev_to_iface[session_id] =
2017 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07002018 ipa_debug("vdev_to_iface[%u]=%u",
2019 session_id,
2020 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302021 qdf_mutex_release(&ipa_ctx->event_lock);
2022 break;
2023
2024 case QDF_IPA_STA_DISCONNECT:
2025 qdf_mutex_acquire(&ipa_ctx->event_lock);
2026
2027 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05302028 struct wlan_ipa_iface_context *iface;
2029
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302030 qdf_mutex_release(&ipa_ctx->event_lock);
2031 ipa_err("%s: Evt: %d, STA already disconnected",
2032 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05302033
2034 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
2035 if (iface && (iface->dev == net_dev))
2036 wlan_ipa_cleanup_iface(iface);
2037
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302038 return QDF_STATUS_E_INVAL;
2039 }
2040
2041 ipa_ctx->sta_connected = 0;
2042
2043 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2044 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
2045 msg_ex->name);
2046 } else {
jiad72b69a92019-04-11 17:23:10 +08002047 /*
2048 * Disable IPA pipes when
2049 * 1. STA is the last interface or
2050 * 2. STA only offload enabled and no clients connected
2051 * to SAP
2052 */
2053 if ((ipa_ctx->num_iface == 1 ||
2054 (wlan_ipa_is_sta_only_offload_enabled() &&
2055 !ipa_ctx->sap_num_connected_sta)) &&
Yun Parka29974a2018-04-09 12:05:49 -07002056 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08002057 !ipa_ctx->ipa_pipes_down &&
2058 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08002059 if (cds_is_driver_unloading()) {
2060 /*
2061 * We disable WDI pipes directly here
2062 * since IPA_OPCODE_TX/RX_SUSPEND
2063 * message will not be processed when
2064 * unloading WLAN driver is in progress
2065 */
2066 wlan_ipa_uc_disable_pipes(ipa_ctx);
2067 } else {
2068 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2069 }
2070 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302071 }
2072
2073 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002074 (ipa_ctx->sap_num_connected_sta > 0 ||
2075 wlan_ipa_is_sta_only_offload_enabled())) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302076 qdf_mutex_release(&ipa_ctx->event_lock);
2077 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2078 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
2079 qdf_mutex_acquire(&ipa_ctx->event_lock);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302080 }
2081
Rakshith Suresh Patkara4dea902019-09-23 15:33:15 +05302082 ipa_ctx->vdev_to_iface[session_id] = WLAN_IPA_MAX_SESSION;
2083 ipa_debug("vdev_to_iface[%u]=%u", session_id,
2084 ipa_ctx->vdev_to_iface[session_id]);
2085
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302086 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2087 iface_ctx = &ipa_ctx->iface_context[i];
2088
2089 if (iface_ctx->dev == net_dev)
2090 break;
2091 }
2092 if (i < WLAN_IPA_MAX_IFACE)
2093 wlan_ipa_cleanup_iface(iface_ctx);
2094
2095 qdf_mutex_release(&ipa_ctx->event_lock);
2096
2097 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
2098 break;
2099
2100 case QDF_IPA_AP_DISCONNECT:
2101 qdf_mutex_acquire(&ipa_ctx->event_lock);
2102
2103 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07002104 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08002105 !ipa_ctx->ipa_pipes_down &&
2106 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302107 if (cds_is_driver_unloading()) {
2108 /*
2109 * We disable WDI pipes directly here since
2110 * IPA_OPCODE_TX/RX_SUSPEND message will not be
2111 * processed when unloading WLAN driver is in
2112 * progress
2113 */
2114 wlan_ipa_uc_disable_pipes(ipa_ctx);
2115 } else {
2116 /*
2117 * This shouldn't happen :
2118 * No interface left but WDI pipes are still
2119 * active - force close WDI pipes
2120 */
2121 ipa_err("No interface left but WDI pipes are still active");
2122 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2123 }
2124 }
2125
2126 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2127 qdf_mutex_release(&ipa_ctx->event_lock);
2128 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2129 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
2130 qdf_mutex_acquire(&ipa_ctx->event_lock);
2131 ipa_ctx->vdev_to_iface[session_id] =
2132 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07002133 ipa_debug("vdev_to_iface[%u]=%u",
2134 session_id,
2135 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302136 }
2137
2138 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2139 iface_ctx = &ipa_ctx->iface_context[i];
2140
2141 if (iface_ctx->dev == net_dev)
2142 break;
2143 }
2144 if (i < WLAN_IPA_MAX_IFACE)
2145 wlan_ipa_cleanup_iface(iface_ctx);
2146
2147 qdf_mutex_release(&ipa_ctx->event_lock);
2148 break;
2149
2150 case QDF_IPA_CLIENT_CONNECT_EX:
2151 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2152 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
2153 net_dev->name, type);
2154 return QDF_STATUS_SUCCESS;
2155 }
2156
2157 qdf_mutex_acquire(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302158 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302159 mac_addr)) {
2160 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302161 ipa_err("%s: STA found, addr: " QDF_MAC_ADDR_STR,
2162 net_dev->name,
2163 QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302164 return QDF_STATUS_SUCCESS;
2165 }
2166
2167 /* Enable IPA UC Data PIPEs when first STA connected */
2168 if (ipa_ctx->sap_num_connected_sta == 0 &&
2169 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302170
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302171 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002172 ipa_ctx->sta_connected &&
2173 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302174 qdf_mutex_release(&ipa_ctx->event_lock);
2175 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2176 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302177 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302178 qdf_mutex_acquire(&ipa_ctx->event_lock);
2179 }
2180
jiad72b69a92019-04-11 17:23:10 +08002181 /*
2182 * IPA pipes already enabled if STA only offload
2183 * is enabled and STA is connected to remote AP.
2184 */
2185 if (wlan_ipa_is_sta_only_offload_enabled() &&
2186 ipa_ctx->sta_connected) {
2187 ipa_debug("IPA pipes already enabled");
2188 } else if (wlan_ipa_uc_handle_first_con(ipa_ctx)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302189 ipa_info("%s: handle 1st con fail",
2190 net_dev->name);
2191
2192 if (wlan_ipa_uc_sta_is_enabled(
2193 ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002194 ipa_ctx->sta_connected &&
2195 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302196 qdf_mutex_release(&ipa_ctx->event_lock);
2197 wlan_ipa_uc_offload_enable_disable(
2198 ipa_ctx,
2199 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302200 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302201 } else {
2202 qdf_mutex_release(&ipa_ctx->event_lock);
2203 }
2204
jiad72b69a92019-04-11 17:23:10 +08002205 return QDF_STATUS_E_BUSY;
2206 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302207 }
2208
2209 ipa_ctx->sap_num_connected_sta++;
2210
2211 qdf_mutex_release(&ipa_ctx->event_lock);
2212
2213 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2214 QDF_IPA_MSG_META_MSG_LEN(&meta) =
2215 (sizeof(qdf_ipa_wlan_msg_ex_t) +
2216 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
2217 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2218
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002219 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302220 ipa_err("msg_ex allocation failed");
2221 return QDF_STATUS_E_NOMEM;
2222 }
2223 strlcpy(msg_ex->name, net_dev->name,
2224 IPA_RESOURCE_NAME_MAX);
2225 msg_ex->num_of_attribs = 1;
2226 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
2227 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2228 msg_ex->attribs[0].offset =
2229 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
2230 } else {
2231 msg_ex->attribs[0].offset =
2232 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
2233 }
2234 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
2235 IPA_MAC_ADDR_SIZE);
2236
2237 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
2238 ipa_info("%s: Evt: %d send ipa msg fail",
2239 net_dev->name, type);
2240 qdf_mem_free(msg_ex);
2241 return QDF_STATUS_E_FAILURE;
2242 }
2243 ipa_ctx->stats.num_send_msg++;
2244
2245 ipa_info("sap_num_connected_sta=%d",
2246 ipa_ctx->sap_num_connected_sta);
2247
2248 return QDF_STATUS_SUCCESS;
2249
2250 case WLAN_CLIENT_DISCONNECT:
2251 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2252 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
2253 msg_ex->name);
2254 return QDF_STATUS_SUCCESS;
2255 }
2256
2257 qdf_mutex_acquire(&ipa_ctx->event_lock);
2258 if (!ipa_ctx->sap_num_connected_sta) {
2259 qdf_mutex_release(&ipa_ctx->event_lock);
2260 ipa_err("%s: Evt: %d, Client already disconnected",
2261 msg_ex->name,
2262 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2263
2264 return QDF_STATUS_SUCCESS;
2265 }
2266 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302267 mac_addr)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302268 qdf_mutex_release(&ipa_ctx->event_lock);
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302269 ipa_err("%s: STA NOT found, not valid: "
2270 QDF_MAC_ADDR_STR,
2271 msg_ex->name, QDF_MAC_ADDR_ARRAY(mac_addr));
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302272
2273 return QDF_STATUS_SUCCESS;
2274 }
2275 ipa_ctx->sap_num_connected_sta--;
2276
jiad72b69a92019-04-11 17:23:10 +08002277 /*
2278 * Disable IPA pipes when
2279 * 1. last client disconnected and
2280 * 2. STA is not connected if STA only offload is enabled
2281 */
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302282 if (!ipa_ctx->sap_num_connected_sta &&
jiad72b69a92019-04-11 17:23:10 +08002283 ipa_ctx->uc_loaded &&
2284 !(wlan_ipa_is_sta_only_offload_enabled() &&
2285 ipa_ctx->sta_connected)) {
Yun Parka29974a2018-04-09 12:05:49 -07002286 if ((false == ipa_ctx->resource_unloading) &&
2287 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
2288 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08002289 if (cds_is_driver_unloading()) {
2290 /*
2291 * We disable WDI pipes directly here
2292 * since IPA_OPCODE_TX/RX_SUSPEND
2293 * message will not be processed when
2294 * unloading WLAN driver is in progress
2295 */
2296 wlan_ipa_uc_disable_pipes(ipa_ctx);
2297 } else {
2298 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2299 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302300 }
2301
2302 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
jiad72b69a92019-04-11 17:23:10 +08002303 ipa_ctx->sta_connected &&
2304 !wlan_ipa_is_sta_only_offload_enabled()) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302305 qdf_mutex_release(&ipa_ctx->event_lock);
2306 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2307 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302308 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302309 } else {
2310 qdf_mutex_release(&ipa_ctx->event_lock);
2311 }
2312 } else {
2313 qdf_mutex_release(&ipa_ctx->event_lock);
2314 }
2315
2316 ipa_info("sap_num_connected_sta=%d",
2317 ipa_ctx->sap_num_connected_sta);
2318 break;
2319
2320 default:
2321 return QDF_STATUS_SUCCESS;
2322 }
2323
2324 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2325 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2326 if (!msg) {
2327 ipa_err("msg allocation failed");
2328 return QDF_STATUS_E_NOMEM;
2329 }
2330
2331 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2332 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2333 IPA_RESOURCE_NAME_MAX);
2334 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2335
2336 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
2337 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2338
2339 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2340
2341 ipa_err("%s: Evt: %d fail",
2342 QDF_IPA_WLAN_MSG_NAME(msg),
2343 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2344 qdf_mem_free(msg);
2345
2346 return QDF_STATUS_E_FAILURE;
2347 }
2348
2349 ipa_ctx->stats.num_send_msg++;
2350
2351end:
2352 return QDF_STATUS_SUCCESS;
2353}
2354
2355/**
2356 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002357 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302358 *
2359 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2360 */
2361static qdf_ipa_wlan_event
2362wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2363{
Yun Park84fbb272018-04-02 15:31:01 -07002364 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302365
2366 switch (wlan_ipa_event_type) {
2367 case WLAN_IPA_CLIENT_CONNECT:
2368 ipa_event = QDF_IPA_CLIENT_CONNECT;
2369 break;
2370 case WLAN_IPA_CLIENT_DISCONNECT:
2371 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2372 break;
2373 case WLAN_IPA_AP_CONNECT:
2374 ipa_event = QDF_IPA_AP_CONNECT;
2375 break;
2376 case WLAN_IPA_AP_DISCONNECT:
2377 ipa_event = QDF_IPA_AP_DISCONNECT;
2378 break;
2379 case WLAN_IPA_STA_CONNECT:
2380 ipa_event = QDF_IPA_STA_CONNECT;
2381 break;
2382 case WLAN_IPA_STA_DISCONNECT:
2383 ipa_event = QDF_IPA_STA_DISCONNECT;
2384 break;
2385 case WLAN_IPA_CLIENT_CONNECT_EX:
2386 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2387 break;
2388 case WLAN_IPA_WLAN_EVENT_MAX:
2389 default:
2390 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2391 break;
2392 }
2393
2394 return ipa_event;
2395}
2396
2397/**
2398 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2399 * @net_dev: Interface net device
2400 * @device_mode: Net interface device mode
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302401 * @session_id: session id for the event
2402 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2403 * @mac_address: MAC address associated with the event
2404 *
2405 * Return: QDF_STATUS
2406 */
2407QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302408 uint8_t session_id,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302409 enum wlan_ipa_wlan_event ipa_event_type,
2410 uint8_t *mac_addr)
2411{
2412 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2413 QDF_STATUS status = QDF_STATUS_SUCCESS;
2414
2415 /* Data path offload only support for STA and SAP mode */
2416 if ((device_mode == QDF_STA_MODE) ||
2417 (device_mode == QDF_SAP_MODE))
Rakshith Suresh Patkar96703f62019-08-06 14:34:36 +05302418 status = __wlan_ipa_wlan_evt(net_dev, device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302419 session_id, type, mac_addr);
2420
2421 return status;
2422}
2423
2424/**
2425 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2426 * @ipa_ctx: Global IPA IPA context
2427 * @is_loading: Indicate if invoked during loading
2428 *
2429 * Return: None
2430 */
2431static void
2432wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2433{
2434 unsigned int pending_event_count;
2435 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2436
2437 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2438 ipa_debug("Pending Event Count %d", pending_event_count);
2439 if (!pending_event_count) {
2440 ipa_debug("No Pending Event");
2441 return;
2442 }
2443
2444 qdf_list_remove_front(&ipa_ctx->pending_event,
2445 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002446 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302447 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2448 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2449 struct wlan_objmgr_vdev *vdev =
2450 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2451 pending_event->session_id,
2452 WLAN_IPA_ID);
2453 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302454 __wlan_ipa_wlan_evt(pending_event->net_dev,
2455 pending_event->device_mode,
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302456 pending_event->session_id,
2457 pending_event->type,
2458 pending_event->mac_addr);
2459 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302460
2461 if (vdev)
2462 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302463 qdf_mem_free(pending_event);
2464 pending_event = NULL;
2465 qdf_list_remove_front(&ipa_ctx->pending_event,
2466 (qdf_list_node_t **)&pending_event);
2467 }
2468}
2469
2470/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002471 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2472 * @ipa_ctx: IPA context
2473 *
2474 * Return: None
2475 */
2476static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2477{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302478 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002479 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302480 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002481
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302482 if (!ipa_ctx->tx_desc_pool)
2483 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002484
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302485 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2486 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2487 for (i = 0; i < pool_size; i++) {
2488 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002489 if (ipa_tx_desc)
2490 qdf_ipa_free_skb(ipa_tx_desc);
2491
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302492 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2493 &ipa_ctx->tx_desc_pool[i].node) !=
2494 QDF_STATUS_SUCCESS)
2495 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002496 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302497 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2498
2499 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2500 qdf_mem_free(ipa_ctx->tx_desc_pool);
2501 ipa_ctx->tx_desc_pool = NULL;
2502
2503 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2504 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002505}
2506
2507/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302508 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302509 * @ipa_ctx: IPA context
2510 *
2511 * Return: QDF_STATUS
2512 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302513static QDF_STATUS
2514wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302515{
2516 int i;
2517 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302518
2519 max_desc_cnt = ipa_ctx->config->txbuf_count;
2520
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302521 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2522 max_desc_cnt);
2523
2524 if (!ipa_ctx->tx_desc_pool) {
2525 ipa_err("Free Tx descriptor allocation failed");
2526 return QDF_STATUS_E_NOMEM;
2527 }
2528
2529 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302530
2531 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2532 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302533 ipa_ctx->tx_desc_pool[i].id = i;
2534 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2535 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2536 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302537 }
2538
2539 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2540 ipa_ctx->stats.num_tx_desc_error = 0;
2541
2542 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2543
2544 return QDF_STATUS_SUCCESS;
2545}
2546
2547#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2548/**
2549 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2550 * @ipa_ctx: Global IPA IPA context
2551 * @desc_fifo_sz: Number of descriptors
2552 *
2553 * Return: 0 on success, negative errno on error
2554 */
2555static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2556 int32_t desc_fifo_sz)
2557{
2558 int i, ret = 0;
2559 qdf_ipa_sys_connect_params_t *ipa;
2560
2561 /*setup TX pipes */
2562 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2563 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2564
2565 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2566 ipa->desc_fifo_sz = desc_fifo_sz;
2567 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302568 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302569
2570 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2571 ipa->ipa_ep_cfg.hdr.hdr_len =
2572 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2573 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2574 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2575 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2576 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2577 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2578 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2579 } else {
2580 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2581 }
2582 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2583
2584 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2585 &ipa_ctx->sys_pipe[i].conn_hdl);
2586 if (ret) {
2587 ipa_err("Failed for pipe %d ret: %d", i, ret);
2588 return ret;
2589 }
2590 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2591 }
2592
2593 return ret;
2594}
2595#else
2596/**
2597 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302598 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302599 * @desc_fifo_sz: Number of descriptors
2600 *
2601 * Return: 0 on success, negative errno on error
2602 */
2603static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2604 int32_t desc_fifo_sz)
2605{
2606 /*
2607 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2608 * is enabled, where per vdev descriptors are supported in firmware.
2609 */
2610 return 0;
2611}
2612#endif
2613
Sravan Kumar Kairam7efc0132019-03-25 16:13:46 +05302614#if defined(CONFIG_IPA_WDI_UNIFIED_API) && defined(IPA_WDI3_GSI)
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302615/**
2616 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2617 * @ipa_ctx: IPA context
2618 *
2619 * Return: rx ipa sys client
2620 */
2621static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2622{
2623 if (ipa_ctx->over_gsi)
2624 return IPA_CLIENT_WLAN2_PROD;
2625 else
2626 return IPA_CLIENT_WLAN1_PROD;
2627}
2628#else
2629static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2630{
2631 return IPA_CLIENT_WLAN1_PROD;
2632}
2633#endif
2634
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302635/**
2636 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2637 * @ipa_ctx: Global IPA IPA context
2638 * @desc_fifo_sz: Number of descriptors
2639 *
2640 * Return: 0 on success, negative errno on error
2641 */
2642static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2643 int32_t desc_fifo_sz)
2644{
2645 int ret = 0;
2646 qdf_ipa_sys_connect_params_t *ipa;
2647
2648 /*
2649 * Hard code it here, this can be extended if in case
2650 * PROD pipe is also per interface.
2651 * Right now there is no advantage of doing this.
2652 */
2653 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2654
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302655 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302656 ipa->desc_fifo_sz = desc_fifo_sz;
2657 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302658 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302659
2660 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2661 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2662 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2663 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2664
2665 ret = qdf_ipa_setup_sys_pipe(ipa,
2666 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2667 if (ret) {
2668 ipa_err("Failed for RX pipe: %d", ret);
2669 return ret;
2670 }
2671 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2672
2673 return ret;
2674}
2675
2676/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002677 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2678 * @ipa_ctx: Global IPA IPA context
2679 *
2680 * Return: None
2681 */
2682static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2683{
2684 int ret, i;
2685
2686 if (!ipa_ctx)
2687 return;
2688
2689 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2690 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2691 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2692 ipa_ctx->sys_pipe[i].conn_hdl);
2693 if (ret)
2694 ipa_err("Failed:%d", ret);
2695
2696 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2697 }
2698 }
2699
2700 wlan_ipa_free_tx_desc_list(ipa_ctx);
2701}
2702
2703/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302704 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2705 * @ipa_ctx: Global IPA IPA context
2706 *
2707 * Return: 0 on success, negative errno on error
2708 */
2709static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2710{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002711 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302712 uint32_t desc_fifo_sz;
2713
2714 /* The maximum number of descriptors that can be provided to a BAM at
2715 * once is one less than the total number of descriptors that the buffer
2716 * can contain.
2717 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2718 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2719 * be provided at once.
2720 * Because of above requirement, one extra descriptor will be added to
2721 * make sure hardware always has one descriptor.
2722 */
2723 desc_fifo_sz = ipa_ctx->config->desc_size
2724 + SPS_DESC_SIZE;
2725
2726 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2727 if (ret) {
2728 ipa_err("Failed for TX pipe: %d", ret);
2729 goto setup_sys_pipe_fail;
2730 }
2731
2732 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2733 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2734 if (ret) {
2735 ipa_err("Failed for RX pipe: %d", ret);
2736 goto setup_sys_pipe_fail;
2737 }
2738 }
2739
2740 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302741 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302742 if (ret)
2743 goto setup_sys_pipe_fail;
2744
2745 return ret;
2746
2747setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002748 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302749
2750 return ret;
2751}
2752
jiadbb47e132018-03-30 16:28:30 +08002753#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2754QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2755 bool mcc_mode)
2756{
2757 qdf_ipa_msg_meta_t meta;
2758 qdf_ipa_wlan_msg_t *msg;
2759 int ret;
2760
2761 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2762 return QDF_STATUS_SUCCESS;
2763
2764 /* Send SCC/MCC Switching event to IPA */
2765 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2766 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002767 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002768 ipa_err("msg allocation failed");
2769 return QDF_STATUS_E_NOMEM;
2770 }
2771
jiad629b2172018-05-11 15:34:22 +08002772 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002773 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002774 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2775 } else {
jiadbb47e132018-03-30 16:28:30 +08002776 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002777 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2778 }
2779
jiadbb47e132018-03-30 16:28:30 +08002780 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2781 "ipa_send_msg(Evt:%d)",
2782 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2783
2784 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2785
2786 if (ret) {
2787 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2788 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2789 qdf_mem_free(msg);
2790 return QDF_STATUS_E_FAILURE;
2791 }
2792
2793 return QDF_STATUS_SUCCESS;
2794}
2795
2796static void wlan_ipa_mcc_work_handler(void *data)
2797{
2798 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2799
2800 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2801}
2802#endif
2803
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302804/**
2805 * wlan_ipa_setup() - IPA initialization function
2806 * @ipa_ctx: IPA context
2807 * @ipa_cfg: IPA config
2808 *
2809 * Allocate ipa_ctx resources, ipa pipe resource and register
2810 * wlan interface with IPA module.
2811 *
2812 * Return: QDF_STATUS enumeration
2813 */
2814QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2815 struct wlan_ipa_config *ipa_cfg)
2816{
2817 int ret, i;
2818 struct wlan_ipa_iface_context *iface_context = NULL;
2819 QDF_STATUS status;
2820
2821 ipa_debug("enter");
2822
2823 gp_ipa = ipa_ctx;
2824 ipa_ctx->num_iface = 0;
2825 ipa_ctx->config = ipa_cfg;
2826
2827 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2828
2829 /* Create the interface context */
2830 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2831 iface_context = &ipa_ctx->iface_context[i];
2832 iface_context->ipa_ctx = ipa_ctx;
2833 iface_context->cons_client =
2834 wlan_ipa_iface_2_client[i].cons_client;
2835 iface_context->prod_client =
2836 wlan_ipa_iface_2_client[i].prod_client;
2837 iface_context->iface_id = i;
2838 iface_context->dev = NULL;
2839 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2840 iface_context->tl_context = NULL;
2841 qdf_spinlock_create(&iface_context->interface_lock);
2842 }
2843
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302844 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302845 qdf_spinlock_create(&ipa_ctx->pm_lock);
2846 qdf_spinlock_create(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302847 qdf_spinlock_create(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302848 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2849 qdf_list_create(&ipa_ctx->pending_event, 1000);
2850 qdf_mutex_create(&ipa_ctx->event_lock);
2851 qdf_mutex_create(&ipa_ctx->ipa_lock);
2852
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302853 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2854 if (status != QDF_STATUS_SUCCESS)
2855 goto fail_setup_rm;
2856
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302857 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2858 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2859 sizeof(struct wlan_ipa_sys_pipe));
2860
2861 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2862 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2863 ipa_ctx->sap_num_connected_sta = 0;
2864 ipa_ctx->ipa_tx_packets_diff = 0;
2865 ipa_ctx->ipa_rx_packets_diff = 0;
2866 ipa_ctx->ipa_p_tx_packets = 0;
2867 ipa_ctx->ipa_p_rx_packets = 0;
2868 ipa_ctx->resource_loading = false;
2869 ipa_ctx->resource_unloading = false;
2870 ipa_ctx->sta_connected = 0;
2871 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302872 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302873 ipa_ctx->wdi_enabled = false;
2874 /* Setup IPA system pipes */
2875 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2876 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2877 if (ret)
2878 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002879
2880 qdf_create_work(0, &ipa_ctx->mcc_work,
2881 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302882 }
2883
2884 status = wlan_ipa_wdi_init(ipa_ctx);
2885 if (status == QDF_STATUS_E_BUSY)
2886 status = wlan_ipa_uc_send_wdi_control_msg(false);
2887 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002888 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302889 goto fail_create_sys_pipe;
2890 }
2891 } else {
2892 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2893 if (ret)
2894 goto fail_create_sys_pipe;
2895 }
2896
2897 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2898
2899 ipa_debug("exit: success");
2900
2901 return QDF_STATUS_SUCCESS;
2902
2903fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302904 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2905
2906fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302907 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302908 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302909 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302910 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2911 iface_context = &ipa_ctx->iface_context[i];
2912 qdf_spinlock_destroy(&iface_context->interface_lock);
2913 }
2914 qdf_mutex_destroy(&ipa_ctx->event_lock);
2915 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2916 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302917 gp_ipa = NULL;
2918 ipa_debug("exit: fail");
2919
2920 return QDF_STATUS_E_FAILURE;
2921}
2922
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302923void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2924{
2925 qdf_nbuf_t skb;
2926 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2927
2928 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2929 return;
2930
2931 qdf_cancel_work(&ipa_ctx->pm_work);
2932
2933 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2934
2935 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2936 != NULL)) {
2937 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2938
2939 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002940
2941 if (pm_tx_cb->exception) {
2942 dev_kfree_skb_any(skb);
2943 } else {
2944 if (pm_tx_cb->ipa_tx_desc)
2945 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2946 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302947
2948 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2949 }
2950 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2951}
2952
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302953QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2954{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302955 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302956 int i;
2957
2958 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2959 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2960
2961 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002962 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302963 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002964 qdf_cancel_work(&ipa_ctx->mcc_work);
2965 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302966
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302967 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2968
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302969 wlan_ipa_flush(ipa_ctx);
2970
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302971 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2972 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302973 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302974
2975 /* destroy the interface lock */
2976 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2977 iface_context = &ipa_ctx->iface_context[i];
2978 qdf_spinlock_destroy(&iface_context->interface_lock);
2979 }
2980
2981 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2982 wlan_ipa_wdi_cleanup();
2983 qdf_mutex_destroy(&ipa_ctx->event_lock);
2984 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2985 qdf_list_destroy(&ipa_ctx->pending_event);
2986
2987 }
2988
2989 gp_ipa = NULL;
2990
2991 return QDF_STATUS_SUCCESS;
2992}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302993
2994struct wlan_ipa_iface_context
2995*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2996{
2997 struct wlan_ipa_iface_context *iface_ctx = NULL;
2998 int i;
2999
3000 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3001 iface_ctx = &ipa_ctx->iface_context[i];
3002
3003 if (iface_ctx->device_mode == mode)
3004 return iface_ctx;
3005 }
3006
3007 return NULL;
3008}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303009
jiadbb47e132018-03-30 16:28:30 +08003010void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303011{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303012 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08003013 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303014
jiadbb47e132018-03-30 16:28:30 +08003015 if (ipa_ctx->mcc_mode == mcc_mode)
3016 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303017
jiadbb47e132018-03-30 16:28:30 +08003018 ipa_ctx->mcc_mode = mcc_mode;
3019 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303020}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303021
3022/**
3023 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
3024 * @ipa_ctx: ipa ipa local context
3025 *
3026 * Will handle IPA UC image loaded indication comes from IPA kernel
3027 *
3028 * Return: None
3029 */
3030static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
3031{
3032 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
3033 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
3034 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
3035 QDF_STATUS status;
3036
3037 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07003038
3039 if (!qdf_dev) {
3040 ipa_err("qdf device is NULL!");
3041 return;
3042 }
3043
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303044 if (true == ipa_ctx->uc_loaded) {
3045 ipa_info("UC already loaded");
3046 return;
3047 }
3048
Lihua Liu15f6e452018-05-30 17:31:06 +08003049 if (!qdf_dev) {
3050 ipa_err("qdf_dev is null");
3051 return;
3052 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303053 /* Connect pipe */
3054 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
3055 if (status) {
3056 ipa_err("Failure to setup IPA pipes (status=%d)",
3057 status);
3058 return;
3059 }
3060
3061 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303062
jiad72b69a92019-04-11 17:23:10 +08003063 /*
3064 * Enable IPA/FW PIPEs if
3065 * 1. any clients connected to SAP or
3066 * 2. STA connected to remote AP if STA only offload is enabled
3067 */
3068 if (ipa_ctx->sap_num_connected_sta ||
3069 (wlan_ipa_is_sta_only_offload_enabled() &&
3070 ipa_ctx->sta_connected)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303071 ipa_debug("Client already connected, enable IPA/FW PIPEs");
3072 wlan_ipa_uc_handle_first_con(ipa_ctx);
3073 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303074}
3075
3076/**
3077 * wlan_ipa_uc_op_cb() - IPA uC operation callback
3078 * @op_msg: operation message received from firmware
3079 * @usr_ctxt: user context registered with TL (we register the IPA Global
3080 * context)
3081 *
3082 * Return: None
3083 */
3084static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
3085 struct wlan_ipa_priv *ipa_ctx)
3086{
3087 struct op_msg_type *msg = op_msg;
3088 struct ipa_uc_fw_stats *uc_fw_stat;
3089
3090 if (!op_msg) {
3091 ipa_err("INVALID ARG");
3092 return;
3093 }
3094
3095 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3096 ipa_err("INVALID OPCODE %d", msg->op_code);
3097 qdf_mem_free(op_msg);
3098 return;
3099 }
3100
3101 ipa_debug("OPCODE=%d", msg->op_code);
3102
3103 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
3104 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
3105 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3106 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07003107 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303108 ipa_ctx->resource_loading = false;
3109 qdf_event_set(&ipa_ctx->ipa_resource_comp);
3110 if (ipa_ctx->wdi_enabled == false) {
3111 ipa_ctx->wdi_enabled = true;
3112 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
3113 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
3114 ipa_ctx->mcc_mode);
3115 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303116 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303117 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07003118 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303119 QDF_IPA_RM_RESOURCE_GRANTED,
3120 QDF_IPA_RM_RESOURCE_WLAN_CONS);
3121 ipa_ctx->pending_cons_req = false;
3122 }
3123 qdf_mutex_release(&ipa_ctx->ipa_lock);
3124 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
3125 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
3126 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05303127
3128 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
3129 wlan_ipa_uc_disable_pipes(ipa_ctx);
3130 ipa_info("Disable FW TX PIPE");
3131 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3132 false, true);
3133 }
3134
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303135 ipa_ctx->activated_fw_pipe--;
3136 if (!ipa_ctx->activated_fw_pipe) {
3137 /*
3138 * Async return success from FW
3139 * Disable/suspend all the PIPEs
3140 */
3141 ipa_ctx->resource_unloading = false;
3142 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303143 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07003144 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
3145 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05303146 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303147 ipa_ctx->pending_cons_req = false;
3148 }
3149 qdf_mutex_release(&ipa_ctx->ipa_lock);
3150 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3151 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
3152 uc_fw_stat = (struct ipa_uc_fw_stats *)
3153 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3154
3155 /* WLAN FW WDI stats */
3156 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
3157 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
3158 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
3159 /* STATs from FW */
3160 uc_fw_stat = (struct ipa_uc_fw_stats *)
3161 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
3162 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3163 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
3164 uc_fw_stat->tx_pkts_completed,
3165 ipa_ctx->ipa_p_tx_packets);
3166 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
3167 (uc_fw_stat->rx_num_ind_drop_no_space +
3168 uc_fw_stat->rx_num_ind_drop_no_buf +
3169 uc_fw_stat->rx_num_pkts_indicated),
3170 ipa_ctx->ipa_p_rx_packets);
3171
3172 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
3173 ipa_ctx->ipa_p_rx_packets =
3174 (uc_fw_stat->rx_num_ind_drop_no_space +
3175 uc_fw_stat->rx_num_ind_drop_no_buf +
3176 uc_fw_stat->rx_num_pkts_indicated);
3177 qdf_mutex_release(&ipa_ctx->ipa_lock);
3178 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
3179 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3180 wlan_ipa_uc_loaded_handler(ipa_ctx);
3181 qdf_mutex_release(&ipa_ctx->ipa_lock);
3182 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
3183 ipa_err("Invalid message: op_code=%d, reason=%d",
3184 msg->op_code, ipa_ctx->stat_req_reason);
3185 }
3186
3187 qdf_mem_free(op_msg);
3188}
3189
3190/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303191 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
3192 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303193 *
3194 * Return: None
3195 */
jitiphilfdcaaba2018-09-03 16:19:52 +05303196static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303197{
3198 struct op_msg_type *msg;
3199 struct uc_op_work_struct *uc_op_work =
3200 (struct uc_op_work_struct *)data;
3201 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3202
3203 msg = uc_op_work->msg;
3204 uc_op_work->msg = NULL;
3205 ipa_debug("posted msg %d", msg->op_code);
3206
3207 wlan_ipa_uc_op_cb(msg, ipa_ctx);
3208}
3209
3210/**
jitiphilfdcaaba2018-09-03 16:19:52 +05303211 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
3212 * __wlan_ipa_uc_fw_op_event_handler
3213 * @data: uC OP work
3214 *
3215 * Return: None
3216 */
3217static void wlan_ipa_uc_fw_op_event_handler(void *data)
3218{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003219 struct qdf_op_sync *op_sync;
3220
3221 if (qdf_op_protect(&op_sync))
3222 return;
3223
jitiphilfdcaaba2018-09-03 16:19:52 +05303224 __wlan_ipa_uc_fw_op_event_handler(data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07003225
3226 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05303227}
3228
3229/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303230 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
3231 * @op_msg: operation message received from firmware
3232 * @ipa_ctx: Global IPA context
3233 *
3234 * Return: None
3235 */
3236static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
3237{
3238 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
3239 struct op_msg_type *msg;
3240 struct uc_op_work_struct *uc_op_work;
3241
3242 if (!ipa_ctx)
3243 goto end;
3244
3245 msg = (struct op_msg_type *)op_msg;
3246
3247 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
3248 ipa_err("Invalid OP Code (%d)", msg->op_code);
3249 goto end;
3250 }
3251
3252 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
3253 if (uc_op_work->msg) {
3254 /* When the same uC OPCODE is already pended, just return */
3255 goto end;
3256 }
3257
3258 uc_op_work->msg = msg;
3259 qdf_sched_work(0, &uc_op_work->work);
3260 return;
3261
3262end:
3263 qdf_mem_free(op_msg);
3264}
3265
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303266QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
3267 qdf_device_t osdev)
3268{
3269 uint8_t i;
3270 QDF_STATUS status = QDF_STATUS_SUCCESS;
3271
3272 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3273 return QDF_STATUS_SUCCESS;
3274
3275 ipa_debug("enter");
3276
Sravan Kumar Kairam02a761e2019-07-05 17:06:27 +05303277 if (!osdev) {
3278 ipa_err("osdev null");
3279 status = QDF_STATUS_E_FAILURE;
3280 goto fail_return;
3281 }
3282
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303283 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
3284 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
3285 ipa_ctx->vdev_offload_enabled[i] = false;
3286 }
3287
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303288 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
3289 ipa_err("IPA UC resource alloc fail");
3290 status = QDF_STATUS_E_FAILURE;
3291 goto fail_return;
3292 }
3293
3294 if (true == ipa_ctx->uc_loaded) {
3295 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
3296 if (status) {
3297 ipa_err("Failure to setup IPA pipes (status=%d)",
3298 status);
3299 status = QDF_STATUS_E_FAILURE;
3300 goto fail_return;
3301 }
3302
3303 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
3304 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08003305
3306 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
3307 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303308 }
3309
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303310 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3311 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
3312
3313 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3314 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
3315 wlan_ipa_uc_fw_op_event_handler,
3316 &ipa_ctx->uc_op_work[i]);
3317 ipa_ctx->uc_op_work[i].msg = NULL;
3318 }
3319
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303320fail_return:
3321 ipa_debug("exit: status=%d", status);
3322 return status;
3323}
3324
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303325/**
3326 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3327 * @ipa_ctx: pointer to IPA IPA struct
3328 *
3329 * Return: none
3330 */
3331static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
3332{
3333 struct wlan_ipa_uc_pending_event *pending_event = NULL;
3334
3335 while (qdf_list_remove_front(&ipa_ctx->pending_event,
3336 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3337 qdf_mem_free(pending_event);
3338}
3339
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303340QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
3341{
3342 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303343 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303344
3345 ipa_debug("enter");
3346
3347 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3348 return status;
3349
3350 if (!ipa_ctx->ipa_pipes_down)
3351 wlan_ipa_uc_disable_pipes(ipa_ctx);
3352
3353 if (true == ipa_ctx->uc_loaded) {
3354 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3355 ipa_ctx->tx_pipe_handle,
3356 ipa_ctx->rx_pipe_handle);
3357 if (status)
3358 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3359 status);
3360 }
3361
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303362 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3363 wlan_ipa_cleanup_pending_event(ipa_ctx);
3364 qdf_mutex_release(&ipa_ctx->ipa_lock);
3365
3366 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3367 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3368 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3369 ipa_ctx->uc_op_work[i].msg = NULL;
3370 }
3371
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303372 ipa_debug("exit: ret=%d", status);
3373 return status;
3374}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303375
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303376/**
3377 * wlan_ipa_uc_send_evt() - send event to ipa
3378 * @net_dev: Interface net device
3379 * @type: event type
3380 * @mac_addr: pointer to mac address
3381 *
3382 * Send event to IPA driver
3383 *
3384 * Return: QDF_STATUS
3385 */
3386static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3387 qdf_ipa_wlan_event type,
3388 uint8_t *mac_addr)
3389{
3390 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3391 qdf_ipa_msg_meta_t meta;
3392 qdf_ipa_wlan_msg_t *msg;
3393
3394 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3395 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3396 if (!msg) {
3397 ipa_err("msg allocation failed");
3398 return QDF_STATUS_E_NOMEM;
3399 }
3400
3401 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3402 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3403 IPA_RESOURCE_NAME_MAX);
3404 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3405
3406 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3407 ipa_err("%s: Evt: %d fail",
3408 QDF_IPA_WLAN_MSG_NAME(msg),
3409 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3410 qdf_mem_free(msg);
3411
3412 return QDF_STATUS_E_FAILURE;
3413 }
3414
3415 ipa_ctx->stats.num_send_msg++;
3416
3417 return QDF_STATUS_SUCCESS;
3418}
3419
Vevek Venkatesane81bca82019-08-12 22:25:15 +05303420void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx,
3421 qdf_netdev_t net_dev)
3422{
3423 struct wlan_ipa_iface_context *iface_ctx;
3424 int i;
3425
3426 ipa_debug("enter");
3427
3428 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3429 iface_ctx = &ipa_ctx->iface_context[i];
3430 if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE &&
3431 iface_ctx->dev == net_dev && iface_ctx->tl_context) {
3432 wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
3433 net_dev->dev_addr);
3434 wlan_ipa_cleanup_iface(iface_ctx);
3435 }
3436 }
3437
3438 ipa_debug("exit");
3439}
3440
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303441QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3442 qdf_netdev_t net_dev)
3443{
3444 struct wlan_ipa_iface_context *iface_ctx;
3445 QDF_STATUS status;
3446
3447 ipa_debug("enter");
3448
3449 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3450 if (iface_ctx)
3451 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3452 net_dev->dev_addr);
3453 else
3454 return QDF_STATUS_E_INVAL;
3455
3456 ipa_debug("exit :%d", status);
3457
3458 return status;
3459}
3460
3461void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3462 qdf_netdev_t net_dev)
3463{
3464 struct wlan_ipa_iface_context *iface_ctx;
3465 int i;
3466
3467 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3468 iface_ctx = &ipa_ctx->iface_context[i];
3469 if (iface_ctx->dev == net_dev)
3470 break;
3471 }
3472
3473 if (iface_ctx)
3474 wlan_ipa_cleanup_iface(iface_ctx);
3475}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303476
3477void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3478{
3479 struct wlan_ipa_iface_context *iface;
3480 int i;
3481
3482 ipa_info("enter");
3483
3484 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3485 iface = &ipa_ctx->iface_context[i];
3486 if (iface->dev) {
3487 if (iface->device_mode == QDF_SAP_MODE)
3488 wlan_ipa_uc_send_evt(iface->dev,
3489 QDF_IPA_AP_DISCONNECT,
3490 iface->dev->dev_addr);
3491 else if (iface->device_mode == QDF_STA_MODE)
3492 wlan_ipa_uc_send_evt(iface->dev,
3493 QDF_IPA_STA_DISCONNECT,
3494 iface->dev->dev_addr);
3495 wlan_ipa_cleanup_iface(iface);
3496 }
3497 }
3498}
jitiphil0e3b5922018-07-24 18:43:50 +05303499
3500void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3501{
3502 qdf_ipa_msg_meta_t meta;
3503 qdf_ipa_wlan_msg_t *msg;
3504 int ret;
3505
3506 meta.msg_len = sizeof(*msg);
3507 msg = qdf_mem_malloc(meta.msg_len);
3508 if (!msg) {
3509 ipa_debug("msg allocation failed");
3510 return;
3511 }
3512
3513 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3514 ipa_debug("ipa_send_msg(Evt:%d)",
3515 meta.msg_type);
3516 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3517
3518 if (ret) {
3519 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3520 meta.msg_type, ret);
3521 qdf_mem_free(msg);
3522 }
3523 ipa_ctx->stats.num_send_msg++;
3524}