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