blob: 71532f8a41266c8be82088a5e27b27aa6ca44b4c [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"
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053028
29static struct wlan_ipa_priv *gp_ipa;
30
31static struct wlan_ipa_iface_2_client {
32 qdf_ipa_client_type_t cons_client;
33 qdf_ipa_client_type_t prod_client;
34} wlan_ipa_iface_2_client[WLAN_IPA_MAX_IFACE] = {
35 {
36 QDF_IPA_CLIENT_WLAN2_CONS, QDF_IPA_CLIENT_WLAN1_PROD
37 }, {
38 QDF_IPA_CLIENT_WLAN3_CONS, QDF_IPA_CLIENT_WLAN1_PROD
39 }, {
40 QDF_IPA_CLIENT_WLAN4_CONS, QDF_IPA_CLIENT_WLAN1_PROD
41 }
42};
43
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +053044/* Local Function Prototypes */
45static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
46 unsigned long data);
47static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
48 unsigned long data);
49
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +053050/**
51 * wlan_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
52 * @ipa_cfg: IPA config
53 *
54 * Return: true if STA mode IPA uC offload is enabled, false otherwise
55 */
56static inline bool wlan_ipa_uc_sta_is_enabled(struct wlan_ipa_config *ipa_cfg)
57{
58 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_UC_STA_ENABLE_MASK);
59}
60
61/**
62 * wlan_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
63 * @ipa_cfg: IPA config
64 *
65 * Return: true if pre-filter is enabled, otherwise false
66 */
67static inline
68bool wlan_ipa_is_pre_filter_enabled(struct wlan_ipa_config *ipa_cfg)
69{
70 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg,
71 WLAN_IPA_PRE_FILTER_ENABLE_MASK);
72}
73
74/**
75 * wlan_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
76 * @ipa_cfg: IPA config
77 *
78 * Return: true if IPv6 is enabled, otherwise false
79 */
80static inline bool wlan_ipa_is_ipv6_enabled(struct wlan_ipa_config *ipa_cfg)
81{
82 return WLAN_IPA_IS_CONFIG_ENABLED(ipa_cfg, WLAN_IPA_IPV6_ENABLE_MASK);
83}
84
85/**
86 * wlan_ipa_msg_free_fn() - Free an IPA message
87 * @buff: pointer to the IPA message
88 * @len: length of the IPA message
89 * @type: type of IPA message
90 *
91 * Return: None
92 */
93static void wlan_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
94{
95 ipa_debug("msg type:%d, len:%d", type, len);
96 qdf_mem_free(buff);
97}
98
99/**
100 * wlan_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
101 * @priv_ctxt: IPA context
102 *
103 * Will be called by IPA context.
104 * It's atomic context, then should be scheduled to kworker thread
105 *
106 * Return: None
107 */
108static void wlan_ipa_uc_loaded_uc_cb(void *priv_ctxt)
109{
110 struct wlan_ipa_priv *ipa_ctx;
111 struct op_msg_type *msg;
112 struct uc_op_work_struct *uc_op_work;
113
114 if (!priv_ctxt) {
115 ipa_err("Invalid IPA context");
116 return;
117 }
118
119 ipa_ctx = priv_ctxt;
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530120 ipa_ctx->uc_loaded = true;
121
122 uc_op_work = &ipa_ctx->uc_op_work[WLAN_IPA_UC_OPCODE_UC_READY];
123 if (!list_empty(&uc_op_work->work.work.entry)) {
124 /* uc_op_work is not initialized yet */
125 return;
126 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530127
128 msg = qdf_mem_malloc(sizeof(*msg));
129 if (!msg) {
130 ipa_err("op_msg allocation fails");
131 return;
132 }
133
134 msg->op_code = WLAN_IPA_UC_OPCODE_UC_READY;
135
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530136 /* When the same uC OPCODE is already pended, just return */
137 if (uc_op_work->msg)
138 goto done;
139
140 uc_op_work->msg = msg;
141 qdf_sched_work(0, &uc_op_work->work);
Sravan Kumar Kairam7eb6e4c2018-04-26 15:35:47 +0530142
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530143 /* work handler will free the msg buffer */
144 return;
145
146done:
147 qdf_mem_free(msg);
148}
149
150/**
151 * wlan_ipa_uc_send_wdi_control_msg() - Set WDI control message
152 * @ctrl: WDI control value
153 *
154 * Send WLAN_WDI_ENABLE for ctrl = true and WLAN_WDI_DISABLE otherwise.
155 *
156 * Return: QDF_STATUS
157 */
158static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
159{
jiad629b2172018-05-11 15:34:22 +0800160 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530161 qdf_ipa_msg_meta_t meta;
162 qdf_ipa_wlan_msg_t *ipa_msg;
163 int ret = 0;
164
165 /* WDI enable message to IPA */
166 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
167 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
168 if (!ipa_msg) {
169 ipa_err("msg allocation failed");
170 return QDF_STATUS_E_NOMEM;
171 }
172
jiad629b2172018-05-11 15:34:22 +0800173 if (ctrl) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530174 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
jiad629b2172018-05-11 15:34:22 +0800175 ipa_ctx->stats.event[QDF_WDI_ENABLE]++;
176 } else {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530177 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
jiad629b2172018-05-11 15:34:22 +0800178 ipa_ctx->stats.event[QDF_WDI_DISABLE]++;
179 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530180
181 ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
182 ret = qdf_ipa_send_msg(&meta, ipa_msg, wlan_ipa_msg_free_fn);
183 if (ret) {
184 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
185 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
186 qdf_mem_free(ipa_msg);
187 return QDF_STATUS_E_FAILURE;
188 }
189
190 return QDF_STATUS_SUCCESS;
191}
192
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530193struct wlan_ipa_priv *wlan_ipa_get_obj_context(void)
194{
195 return gp_ipa;
196}
197
Yun Parke74e6092018-04-27 11:36:34 -0700198/**
199 * wlan_ipa_send_pkt_to_tl() - Send an IPA packet to TL
200 * @iface_context: interface-specific IPA context
201 * @ipa_tx_desc: packet data descriptor
202 *
203 * Return: None
204 */
205static void wlan_ipa_send_pkt_to_tl(
206 struct wlan_ipa_iface_context *iface_context,
207 qdf_ipa_rx_data_t *ipa_tx_desc)
208{
209 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
210 qdf_nbuf_t skb;
211 struct wlan_ipa_tx_desc *tx_desc;
212
213 qdf_spin_lock_bh(&iface_context->interface_lock);
214 /*
215 * During CAC period, data packets shouldn't be sent over the air so
216 * drop all the packets here
217 */
218 if (iface_context->device_mode == QDF_SAP_MODE ||
219 iface_context->device_mode == QDF_P2P_GO_MODE) {
220 if (ipa_ctx->dfs_cac_block_tx) {
221 ipa_free_skb(ipa_tx_desc);
222 qdf_spin_unlock_bh(&iface_context->interface_lock);
223 iface_context->stats.num_tx_cac_drop++;
224 wlan_ipa_wdi_rm_try_release(ipa_ctx);
225 return;
226 }
227 }
228 qdf_spin_unlock_bh(&iface_context->interface_lock);
229
230 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
231
hangtian127c9532019-01-12 13:29:07 +0800232 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Yun Parke74e6092018-04-27 11:36:34 -0700233
234 /* Store IPA Tx buffer ownership into SKB CB */
235 qdf_nbuf_ipa_owned_set(skb);
236 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
237 qdf_nbuf_mapped_paddr_set(skb,
jiadaf210c02018-11-20 09:40:34 +0800238 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
239 + WLAN_IPA_WLAN_FRAG_HEADER
240 + WLAN_IPA_WLAN_IPA_HEADER);
Yun Parke74e6092018-04-27 11:36:34 -0700241 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
242 WLAN_IPA_WLAN_FRAG_HEADER + WLAN_IPA_WLAN_IPA_HEADER;
jiadaf210c02018-11-20 09:40:34 +0800243 } else
244 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
Yun Parke74e6092018-04-27 11:36:34 -0700245
246 qdf_spin_lock_bh(&ipa_ctx->q_lock);
247 /* get free Tx desc and assign ipa_tx_desc pointer */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +0530248 if (qdf_list_remove_front(&ipa_ctx->tx_desc_free_list,
249 (qdf_list_node_t **)&tx_desc) ==
Yun Parke74e6092018-04-27 11:36:34 -0700250 QDF_STATUS_SUCCESS) {
251 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
252 ipa_ctx->stats.num_tx_desc_q_cnt++;
253 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
254 /* Store Tx Desc index into SKB CB */
255 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
256 } else {
257 ipa_ctx->stats.num_tx_desc_error++;
258 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
259 qdf_ipa_free_skb(ipa_tx_desc);
260 wlan_ipa_wdi_rm_try_release(ipa_ctx);
261 return;
262 }
263
264 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
265 (struct cdp_vdev *)iface_context->tl_context,
266 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
267 if (skb) {
268 qdf_nbuf_free(skb);
269 iface_context->stats.num_tx_err++;
270 return;
271 }
272
273 atomic_inc(&ipa_ctx->tx_ref_cnt);
274
275 iface_context->stats.num_tx++;
276}
277
jiad90b17252019-03-25 15:22:42 +0800278/**
279 * wlan_ipa_forward() - handle packet forwarding to wlan tx
280 * @ipa_ctx: pointer to ipa ipa context
281 * @iface_ctx: interface context
282 * @skb: data pointer
283 *
284 * if exception packet has set forward bit, copied new packet should be
285 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
286 * put into pm queue and tx procedure will be differed
287 *
288 * Return: None
289 */
290static void wlan_ipa_forward(struct wlan_ipa_priv *ipa_ctx,
291 struct wlan_ipa_iface_context *iface_ctx,
292 qdf_nbuf_t skb)
293{
294 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
295
296 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
297
298 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
299 qdf_nbuf_ipa_owned_set(skb);
300
301 /* WLAN subsystem is in suspend, put in queue */
302 if (ipa_ctx->suspended) {
303 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
304 ipa_info_rl("Tx in suspend, put in queue");
305 qdf_mem_zero(skb->cb, sizeof(skb->cb));
306 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
307 pm_tx_cb->exception = true;
308 pm_tx_cb->iface_context = iface_ctx;
309 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
310 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
311 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
312 ipa_ctx->stats.num_tx_queued++;
313 } else {
314 /* Resume, put packet into WLAN TX */
315 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
316
317 if (ipa_ctx->softap_xmit) {
318 if (ipa_ctx->softap_xmit(skb, iface_ctx->dev)) {
319 ipa_err_rl("packet Tx fail");
320 ipa_ctx->stats.num_tx_fwd_err++;
321 } else {
322 ipa_ctx->stats.num_tx_fwd_ok++;
323 }
324 } else {
325 dev_kfree_skb_any(skb);
326 }
327 }
328}
329
330/**
331 * wlan_ipa_intrabss_forward() - Forward intra bss packets.
332 * @ipa_ctx: pointer to IPA IPA struct
333 * @iface_ctx: ipa interface context
334 * @desc: Firmware descriptor
335 * @skb: Data buffer
336 *
337 * Return:
338 * WLAN_IPA_FORWARD_PKT_NONE
339 * WLAN_IPA_FORWARD_PKT_DISCARD
340 * WLAN_IPA_FORWARD_PKT_LOCAL_STACK
341 *
342 */
343
344static enum wlan_ipa_forward_type wlan_ipa_intrabss_forward(
345 struct wlan_ipa_priv *ipa_ctx,
346 struct wlan_ipa_iface_context *iface_ctx,
347 uint8_t desc,
348 qdf_nbuf_t skb)
349{
350 int ret = WLAN_IPA_FORWARD_PKT_NONE;
351 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
352 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
353
354 if ((desc & FW_RX_DESC_FORWARD_M)) {
355 void *vdev = cdp_get_vdev_from_vdev_id(soc, pdev,
356 iface_ctx->session_id);
357 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
358 /* Drop the packet*/
359 ipa_ctx->stats.num_tx_fwd_err++;
360 dev_kfree_skb_any(skb);
361 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
362 return ret;
363 }
364 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
365 ipa_ctx->ipa_tx_forward++;
366
367 if ((desc & FW_RX_DESC_DISCARD_M)) {
368 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
369 ipa_ctx->ipa_rx_internal_drop_count++;
370 ipa_ctx->ipa_rx_discard++;
371 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
372 } else {
373 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
374
375 if (cloned_skb)
376 wlan_ipa_forward(ipa_ctx, iface_ctx,
377 cloned_skb);
378 else
379 ipa_err_rl("tx skb alloc failed");
380 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
381 }
382 }
383
384 return ret;
385}
386
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530387#ifdef CONFIG_IPA_WDI_UNIFIED_API
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530388/*
389 * TODO: Get WDI version through FW capabilities
390 */
Mohit Khannacabf5e72018-07-24 13:28:43 -0700391#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530392static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
393{
394 ipa_ctx->wdi_version = IPA_WDI_3;
395}
396#elif defined(QCA_WIFI_3_0)
397static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
398{
399 ipa_ctx->wdi_version = IPA_WDI_2;
400}
401#else
402static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
403{
404 ipa_ctx->wdi_version = IPA_WDI_1;
405}
406#endif
407
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530408static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
409 qdf_device_t osdev)
410{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530411 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530412}
413
414static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
415 qdf_device_t osdev)
416{
417 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
418 int i;
419
420 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
421 qdf_mem_copy(&sys_in[i],
422 &ipa_ctx->sys_pipe[i].ipa_sys_params,
423 sizeof(qdf_ipa_sys_connect_params_t));
424
425 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
426 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
427 wlan_ipa_wdi_meter_notifier_cb,
428 ipa_ctx->config->desc_size,
429 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
430 &ipa_ctx->tx_pipe_handle,
431 &ipa_ctx->rx_pipe_handle,
432 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530433 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530434}
435
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530436#ifdef FEATURE_METERING
437/**
438 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
439 * @ipa_ctx: IPA context
440 * @in: IPA WDI in param
441 *
442 * Return: QDF_STATUS
443 */
444static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
445 qdf_ipa_wdi_init_in_params_t *in)
446{
447 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
448 wlan_ipa_wdi_meter_notifier_cb;
449}
450#else
451static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
452 qdf_ipa_wdi_init_in_params_t *in)
453{
454}
455#endif
456
457/**
458 * wlan_ipa_wdi_init() - IPA WDI init
459 * @ipa_ctx: IPA context
460 *
461 * Return: QDF_STATUS
462 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530463static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
464{
465 qdf_ipa_wdi_init_in_params_t in;
466 qdf_ipa_wdi_init_out_params_t out;
467 int ret;
468
469 ipa_ctx->uc_loaded = false;
470
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530471 qdf_mem_zero(&in, sizeof(in));
472 qdf_mem_zero(&out, sizeof(out));
473
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530474 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
475 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530476 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
477 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530478
479 ret = qdf_ipa_wdi_init(&in, &out);
480 if (ret) {
481 ipa_err("ipa_wdi_init failed with ret=%d", ret);
482 return QDF_STATUS_E_FAILURE;
483 }
484
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530485 ipa_ctx->over_gsi =
486 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
487 ipa_ctx->is_smmu_enabled =
488 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
489 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
490 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
491
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530492 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700493 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530494 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530495 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530496 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530497 return QDF_STATUS_E_BUSY;
498 }
499
500 return QDF_STATUS_SUCCESS;
501}
502
503static inline int wlan_ipa_wdi_cleanup(void)
504{
505 int ret;
506
507 ret = qdf_ipa_wdi_cleanup();
508 if (ret)
509 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
510 return ret;
511}
512
513static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
514 struct ipa_sys_connect_params *sys,
515 uint32_t *handle)
516{
517 return 0;
518}
519
520static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
521 uint32_t handle)
522{
523 return 0;
524}
525
Yun Parke74e6092018-04-27 11:36:34 -0700526/**
527 * wlan_ipa_pm_flush() - flush queued packets
528 * @work: pointer to the scheduled work
529 *
530 * Called during PM resume to send packets to TL which were queued
531 * while host was in the process of suspending.
532 *
533 * Return: None
534 */
535static void wlan_ipa_pm_flush(void *data)
536{
537 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
538 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
539 qdf_nbuf_t skb;
540 uint32_t dequeued = 0;
541
542 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
543 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
544 NULL)) {
545 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
546
547 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
548 dequeued++;
549
jiadab8cea02018-05-24 09:16:14 +0800550 if (pm_tx_cb->exception) {
551 if (ipa_ctx->softap_xmit &&
552 pm_tx_cb->iface_context->dev) {
553 ipa_ctx->softap_xmit(skb,
554 pm_tx_cb->iface_context->dev);
555 ipa_ctx->stats.num_tx_fwd_ok++;
556 } else {
557 dev_kfree_skb_any(skb);
558 }
559 } else {
560 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
561 pm_tx_cb->ipa_tx_desc);
562 }
Yun Parke74e6092018-04-27 11:36:34 -0700563
564 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
565 }
566 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
567
568 ipa_ctx->stats.num_tx_dequeued += dequeued;
569 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
570 ipa_ctx->stats.num_max_pm_queue = dequeued;
571}
572
jiadae9959f2018-05-08 11:19:07 +0800573int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
574{
575 if (!num_buf) {
576 ipa_info("No buffers to map/unmap");
577 return 0;
578 }
579
580 if (map)
581 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
582 else
583 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
584}
585
jiad90b17252019-03-25 15:22:42 +0800586static enum wlan_ipa_forward_type
587wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
588 struct wlan_ipa_iface_context *iface_ctx,
589 qdf_nbuf_t nbuf)
590{
591 uint8_t fw_desc = 0;
592 bool fwd_success;
593 int ret;
594
595 /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
596 if (ipa_ctx->wdi_version != IPA_WDI_3) {
597 fw_desc = (uint8_t)nbuf->cb[1];
598 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
599 nbuf);
600 }
601
602 if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
603 nbuf, &fwd_success)) {
604 ipa_ctx->ipa_rx_internal_drop_count++;
605 ipa_ctx->ipa_rx_discard++;
606
607 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
608 } else {
609 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
610 }
611
612 if (fwd_success)
613 ipa_ctx->stats.num_tx_fwd_ok++;
614 else
615 ipa_ctx->stats.num_tx_fwd_err++;
616
617 return ret;
618}
619
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530620#else /* CONFIG_IPA_WDI_UNIFIED_API */
621
622static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
623{
624}
625
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530626static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
627 qdf_device_t osdev)
628{
629 return qdf_mem_smmu_s1_enabled(osdev);
630}
631
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530632static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
633 qdf_device_t osdev)
634{
635 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
636 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
637 wlan_ipa_wdi_meter_notifier_cb,
638 ipa_ctx->config->desc_size,
639 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
640 &ipa_ctx->tx_pipe_handle,
641 &ipa_ctx->rx_pipe_handle);
642}
643
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530644static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
645{
646 struct ipa_wdi_uc_ready_params uc_ready_param;
647
648 ipa_ctx->uc_loaded = false;
649 uc_ready_param.priv = (void *)ipa_ctx;
650 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
651 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
652 ipa_info("UC Ready CB register fail");
653 return QDF_STATUS_E_FAILURE;
654 }
655
656 if (true == uc_ready_param.is_uC_ready) {
657 ipa_info("UC Ready");
658 ipa_ctx->uc_loaded = true;
659 } else {
660 return QDF_STATUS_E_BUSY;
661 }
662
663 return QDF_STATUS_SUCCESS;
664}
665
666static inline int wlan_ipa_wdi_cleanup(void)
667{
668 int ret;
669
670 ret = qdf_ipa_uc_dereg_rdyCB();
671 if (ret)
672 ipa_info("UC Ready CB deregister fail");
673 return ret;
674}
675
676static inline int wlan_ipa_wdi_setup_sys_pipe(
677 struct wlan_ipa_priv *ipa_ctx,
678 struct ipa_sys_connect_params *sys, uint32_t *handle)
679{
680 return qdf_ipa_setup_sys_pipe(sys, handle);
681}
682
683static inline int wlan_ipa_wdi_teardown_sys_pipe(
684 struct wlan_ipa_priv *ipa_ctx,
685 uint32_t handle)
686{
687 return qdf_ipa_teardown_sys_pipe(handle);
688}
689
Yun Parke74e6092018-04-27 11:36:34 -0700690/**
691 * wlan_ipa_pm_flush() - flush queued packets
692 * @work: pointer to the scheduled work
693 *
694 * Called during PM resume to send packets to TL which were queued
695 * while host was in the process of suspending.
696 *
697 * Return: None
698 */
699static void wlan_ipa_pm_flush(void *data)
700{
701 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
702 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
703 qdf_nbuf_t skb;
704 uint32_t dequeued = 0;
705
706 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
707 WIFI_POWER_EVENT_WAKELOCK_IPA);
708 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
709 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
710 NULL)) {
711 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
712
713 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
714 dequeued++;
715
jiadab8cea02018-05-24 09:16:14 +0800716 if (pm_tx_cb->exception) {
717 if (ipa_ctx->softap_xmit &&
718 pm_tx_cb->iface_context->dev) {
719 ipa_ctx->softap_xmit(skb,
720 pm_tx_cb->iface_context->dev);
721 ipa_ctx->stats.num_tx_fwd_ok++;
722 } else {
723 dev_kfree_skb_any(skb);
724 }
725 } else {
726 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
727 pm_tx_cb->ipa_tx_desc);
728 }
Yun Parke74e6092018-04-27 11:36:34 -0700729
730 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
731 }
732 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
733 qdf_wake_lock_release(&ipa_ctx->wake_lock,
734 WIFI_POWER_EVENT_WAKELOCK_IPA);
735
736 ipa_ctx->stats.num_tx_dequeued += dequeued;
737 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
738 ipa_ctx->stats.num_max_pm_queue = dequeued;
739}
740
jiadae9959f2018-05-08 11:19:07 +0800741int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
742{
743 if (!num_buf) {
744 ipa_info("No buffers to map/unmap");
745 return 0;
746 }
747
748 if (map)
749 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
750 else
751 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
752}
753
jiad90b17252019-03-25 15:22:42 +0800754static enum wlan_ipa_forward_type
755wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
756 struct wlan_ipa_iface_context *iface_ctx,
757 qdf_nbuf_t nbuf)
758{
759 uint8_t fw_desc;
760
761 fw_desc = (uint8_t)nbuf->cb[1];
762
763 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
764}
765
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530766#endif /* CONFIG_IPA_WDI_UNIFIED_API */
767
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530768/**
769 * wlan_ipa_send_skb_to_network() - Send skb to kernel
770 * @skb: network buffer
771 * @iface_ctx: IPA interface context
772 *
773 * Called when a network buffer is received which should not be routed
774 * to the IPA module.
775 *
776 * Return: None
777 */
778static void
779wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
780 struct wlan_ipa_iface_context *iface_ctx)
781{
782 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
783
784 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800785 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530786 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800787 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530788 return;
789 }
790
791 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
792
793 if (ipa_ctx->send_to_nw)
794 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
795
796 ipa_ctx->ipa_rx_net_send_count++;
797}
798
799/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530800 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530801 * @priv: pointer to private data registered with IPA (we register a
802 * pointer to the global IPA context)
803 * @evt: the IPA event which triggered the callback
804 * @data: data associated with the event
805 *
806 * Return: None
807 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530808static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
809 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530810{
811 struct wlan_ipa_priv *ipa_ctx = NULL;
812 qdf_nbuf_t skb;
813 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700814 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530815 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530816
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530817 ipa_ctx = (struct wlan_ipa_priv *)priv;
818 if (!ipa_ctx) {
819 if (evt == IPA_RECEIVE) {
820 skb = (qdf_nbuf_t)data;
821 dev_kfree_skb_any(skb);
822 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530823 return;
824 }
825
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530826 switch (evt) {
827 case IPA_RECEIVE:
828 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530829 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
830 session_id = (uint8_t)skb->cb[0];
831 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530832 } else {
833 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
834 }
835 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700836 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
837 iface_id, session_id, (uint8_t)skb->cb[1],
838 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530839 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800840 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530841 return;
842 }
843
844 iface_context = &ipa_ctx->iface_context[iface_id];
845 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800846 ipa_err_rl("TL context of iface_id %u is NULL",
847 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530848 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800849 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530850 return;
851 }
852
853 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
854 ipa_ctx->stats.num_rx_excep++;
855 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
856 } else {
857 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
858 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530859 iface_context->stats.num_rx_ipa_excep++;
860
861 /* Disable to forward Intra-BSS Rx packets when
862 * ap_isolate=1 in hostapd.conf
863 */
864 if (!ipa_ctx->ap_intrabss_fwd) {
865 /*
866 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
867 * all Rx packets to IPA uC, which need to be forwarded
868 * to other interface.
869 * And, IPA driver will send back to WLAN host driver
870 * through exception pipe with fw_desc field set by FW.
871 * Here we are checking fw_desc field for FORWARD bit
872 * set, and forward to Tx. Then copy to kernel stack
873 * only when DISCARD bit is not set.
874 */
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530875 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
jiad90b17252019-03-25 15:22:42 +0800876 wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
877 skb))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530878 break;
879 } else {
jiadf3ecc752018-07-05 14:36:03 +0800880 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530881 }
882
883 wlan_ipa_send_skb_to_network(skb, iface_context);
884 break;
885
886 default:
jiadf3ecc752018-07-05 14:36:03 +0800887 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530888 return;
889 }
890}
891
892/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530893 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
894 * @priv: pointer to private data registered with IPA (we register a
895 * pointer to the global IPA context)
896 * @evt: the IPA event which triggered the callback
897 * @data: data associated with the event
898 *
899 * Return: None
900 */
901static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
902 unsigned long data)
903{
Dustin Brown3fdaaf62019-03-18 14:00:16 -0700904 struct qdf_op_sync *op_sync;
905
906 if (qdf_op_protect(&op_sync)) {
907 if (evt == IPA_RECEIVE) {
908 struct wlan_ipa_priv *ipa_ctx = priv;
909 qdf_nbuf_t skb = (qdf_nbuf_t)data;
910
911 ipa_ctx->ipa_rx_internal_drop_count++;
912 dev_kfree_skb_any(skb);
913 }
914
915 return;
916 }
917
jitiphilfdcaaba2018-09-03 16:19:52 +0530918 __wlan_ipa_w2i_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -0700919
920 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +0530921}
922
923/**
924 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530925 * @priv: pointer to private data registered with IPA (we register a
926 * pointer to the interface-specific IPA context)
927 * @evt: the IPA event which triggered the callback
928 * @data: data associated with the event
929 *
930 * Return: None
931 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530932static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
933 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530934{
935 struct wlan_ipa_priv *ipa_ctx = NULL;
936 qdf_ipa_rx_data_t *ipa_tx_desc;
937 struct wlan_ipa_iface_context *iface_context;
938 qdf_nbuf_t skb;
939 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
940
941 iface_context = (struct wlan_ipa_iface_context *)priv;
942 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
943 ipa_ctx = iface_context->ipa_ctx;
944
945 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +0800946 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530947 ipa_free_skb(ipa_tx_desc);
948 iface_context->stats.num_tx_drop++;
949 return;
950 }
951
952 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
953
954 /*
955 * If PROD resource is not requested here then there may be cases where
956 * IPA hardware may be clocked down because of not having proper
957 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
958 * workaround to request PROD resource while data is going over CONS
959 * pipe to prevent the IPA hardware clockdown.
960 */
961 wlan_ipa_wdi_rm_request(ipa_ctx);
962
963 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
964 /*
965 * If host is still suspended then queue the packets and these will be
966 * drained later when resume completes. When packet is arrived here and
967 * host is suspended, this means that there is already resume is in
968 * progress.
969 */
970 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +0800971 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530972 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
973 pm_tx_cb->iface_context = iface_context;
974 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
975 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
976 ipa_ctx->stats.num_tx_queued++;
977
978 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
979 return;
980 }
981
982 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
983
984 /*
985 * If we are here means, host is not suspended, wait for the work queue
986 * to finish.
987 */
988 qdf_flush_work(&ipa_ctx->pm_work);
989
990 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
991}
992
jitiphilfdcaaba2018-09-03 16:19:52 +0530993/**
994 * wlan_ipa_i2w_cb() - IPA to WLAN callback
995 * @priv: pointer to private data registered with IPA (we register a
996 * pointer to the interface-specific IPA context)
997 * @evt: the IPA event which triggered the callback
998 * @data: data associated with the event
999 *
1000 * Return: None
1001 */
1002static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1003 unsigned long data)
1004{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001005 struct qdf_op_sync *op_sync;
1006
1007 if (qdf_op_protect(&op_sync)) {
1008 qdf_ipa_rx_data_t *ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1009 struct wlan_ipa_iface_context *iface_context = priv;
1010
1011 ipa_free_skb(ipa_tx_desc);
1012 iface_context->stats.num_tx_drop++;
1013
1014 return;
1015 }
1016
jitiphilfdcaaba2018-09-03 16:19:52 +05301017 __wlan_ipa_i2w_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001018
1019 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301020}
1021
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301022QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
1023{
1024 /*
1025 * Check if IPA is ready for suspend, If we are here means, there is
1026 * high chance that suspend would go through but just to avoid any race
1027 * condition after suspend started, these checks are conducted before
1028 * allowing to suspend.
1029 */
1030 if (atomic_read(&ipa_ctx->tx_ref_cnt))
1031 return QDF_STATUS_E_AGAIN;
1032
Yun Parke74e6092018-04-27 11:36:34 -07001033 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301034 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301035
1036 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1037 ipa_ctx->suspended = true;
1038 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1039
1040 return QDF_STATUS_SUCCESS;
1041}
1042
1043QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
1044{
1045 qdf_sched_work(0, &ipa_ctx->pm_work);
1046
1047 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1048 ipa_ctx->suspended = false;
1049 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1050
1051 return QDF_STATUS_SUCCESS;
1052}
1053
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301054QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1055{
1056 int result;
1057
1058 ipa_debug("enter");
1059
1060 if (!ipa_ctx->ipa_pipes_down) {
1061 /*
1062 * IPA WDI Pipes are already activated due to
1063 * rm deferred resources grant
1064 */
1065 ipa_warn("IPA WDI Pipes are already activated");
1066 goto end;
1067 }
1068
1069 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1070 ipa_ctx->dp_pdev);
1071 if (result) {
1072 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1073 return QDF_STATUS_E_FAILURE;
1074 }
1075
1076 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1077 ipa_ctx->ipa_pipes_down = false;
1078
1079 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1080 ipa_ctx->dp_pdev);
1081
1082end:
1083 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1084
1085 return QDF_STATUS_SUCCESS;
1086}
1087
1088QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1089{
1090 int result;
1091
1092 ipa_debug("enter");
1093
1094 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301095 ipa_warn("IPA WDI Pipes are already deactivated");
1096 goto end;
1097 }
1098
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301099 qdf_spin_lock_bh(&ipa_ctx->pipes_down_lock);
1100 if (ipa_ctx->pipes_down_in_progress || ipa_ctx->ipa_pipes_down) {
1101 ipa_warn("IPA WDI Pipes down already in progress");
1102 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1103 return QDF_STATUS_E_ALREADY;
1104 }
1105 ipa_ctx->pipes_down_in_progress = true;
1106 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1107
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301108 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1109 ipa_ctx->dp_pdev);
1110
1111 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1112 ipa_ctx->dp_pdev);
1113 if (result) {
1114 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301115 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301116 return QDF_STATUS_E_FAILURE;
1117 }
1118
1119 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301120 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301121
1122end:
1123 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1124
1125 return QDF_STATUS_SUCCESS;
1126}
1127
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301128/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301129 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1130 * @ipa_ctx: Global IPA IPA context
1131 * @sta_add: Should station be added
1132 * @sta_id: ID of the station being queried
1133 *
1134 * Return: true if the station was found
1135 */
1136static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
1137 bool sta_add, uint8_t sta_id,
1138 uint8_t *mac_addr)
1139{
1140 bool sta_found = false;
1141 uint8_t idx;
1142
1143 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1144 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1145 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1146 sta_found = true;
1147 break;
1148 }
1149 }
1150 if (sta_add && sta_found) {
1151 ipa_err("STA ID %d already exist, cannot add", sta_id);
1152 return sta_found;
1153 }
1154 if (sta_add) {
1155 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1156 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1157 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
1158 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
1159 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1160 mac_addr, mac_addr,
1161 QDF_NET_ETH_LEN);
1162 return sta_found;
1163 }
1164 }
1165 }
1166 if (!sta_add && !sta_found) {
1167 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
1168 return sta_found;
1169 }
1170 if (!sta_add) {
1171 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1172 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1173 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1174 ipa_ctx->assoc_stas_map[idx].is_reserved =
1175 false;
1176 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
hangtian127c9532019-01-12 13:29:07 +08001177 qdf_mem_zero(
1178 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1179 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301180 return sta_found;
1181 }
1182 }
1183 }
1184
1185 return sta_found;
1186}
1187
1188/**
1189 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1190 * @ipa_ctx: IPA context
1191 * @session_id: Session ID
1192 *
1193 * Return: None
1194 */
1195static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1196 uint8_t session_id)
1197{
1198 struct wlan_ipa_iface_context *iface_ctx;
1199 int i;
1200
1201 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1202 iface_ctx = &ipa_ctx->iface_context[i];
1203 if (iface_ctx->session_id == session_id)
1204 break;
1205 }
1206
1207 return i;
1208}
1209
1210/**
1211 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1212 * @iface_context: interface-specific IPA context
1213 *
1214 * Return: None
1215 */
1216static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1217{
1218 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1219
1220 ipa_debug("enter");
1221
1222 if (!iface_context->tl_context)
1223 return;
1224
1225 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1226 iface_context->dev->name,
1227 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1228
1229 qdf_spin_lock_bh(&iface_context->interface_lock);
1230 iface_context->tl_context = NULL;
1231 iface_context->dev = NULL;
1232 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1233 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1234 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1235 qdf_spin_unlock_bh(&iface_context->interface_lock);
1236 iface_context->ifa_address = 0;
1237 if (!iface_context->ipa_ctx->num_iface) {
1238 ipa_err("NUM INTF 0, Invalid");
1239 QDF_ASSERT(0);
1240 }
1241 iface_context->ipa_ctx->num_iface--;
1242 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1243}
1244
1245/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301246 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1247 * @skb: packet buffer which was transmitted
1248 *
1249 * Return: None
1250 */
1251static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1252{
1253 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1254 qdf_ipa_rx_data_t *ipa_tx_desc;
1255 struct wlan_ipa_tx_desc *tx_desc;
1256 uint16_t id;
1257
1258 if (!qdf_nbuf_ipa_owned_get(skb)) {
1259 dev_kfree_skb_any(skb);
1260 return;
1261 }
1262
1263 /* Get Tx desc pointer from SKB CB */
1264 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1265 tx_desc = &ipa_ctx->tx_desc_pool[id];
1266 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1267
1268 /* Return Tx Desc to IPA */
1269 qdf_ipa_free_skb(ipa_tx_desc);
1270
1271 /* Return to free tx desc list */
1272 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1273 tx_desc->ipa_tx_desc_ptr = NULL;
1274 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1275 ipa_ctx->stats.num_tx_desc_q_cnt--;
1276 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1277
1278 ipa_ctx->stats.num_tx_comp_cnt++;
1279
1280 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1281
1282 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1283}
1284
1285/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301286 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1287 * @ipa_ctx: IPA IPA global context
1288 * @net_dev: Interface net device
1289 * @device_mode: Net interface device mode
1290 * @adapter: Interface upon which IPA is being setup
1291 * @sta_id: Station ID of the API instance
1292 * @session_id: Station ID of the API instance
1293 *
1294 * Return: QDF STATUS
1295 */
1296static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1297 qdf_netdev_t net_dev,
1298 uint8_t device_mode, uint8_t sta_id,
1299 uint8_t session_id)
1300{
1301 struct wlan_ipa_iface_context *iface_context = NULL;
1302 void *tl_context = NULL;
1303 int i;
1304 QDF_STATUS status;
1305
1306 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1307 * channel change indication. Since these indications are sent by lower
1308 * layer as SAP updates and IPA doesn't have to do anything for these
1309 * updates so ignoring!
1310 */
1311 if (device_mode == QDF_SAP_MODE) {
1312 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1313 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001314 if (iface_context->dev == net_dev) {
1315 ipa_debug("found iface %u device_mode %u",
1316 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301317 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001318 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301319 }
1320 }
1321
Yun Park21ec4902018-04-24 12:11:01 -07001322 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1323 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1324 status = QDF_STATUS_E_NOMEM;
1325 QDF_ASSERT(0);
1326 goto end;
1327 }
1328
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301329 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001330 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301331 iface_context = &(ipa_ctx->iface_context[i]);
1332 break;
1333 }
1334 }
1335
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001336 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301337 ipa_err("All the IPA interfaces are in use");
1338 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001339 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301340 goto end;
1341 }
1342
1343 iface_context->sta_id = sta_id;
1344 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1345 ipa_ctx->dp_pdev,
1346 sta_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001347 if (!tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301348 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1349 status = QDF_STATUS_E_INVAL;
1350 goto end;
1351 }
1352
1353 iface_context->tl_context = tl_context;
1354 iface_context->dev = net_dev;
1355 iface_context->device_mode = device_mode;
1356 iface_context->session_id = session_id;
1357
1358 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1359 net_dev->dev_addr,
1360 iface_context->prod_client,
1361 iface_context->cons_client,
1362 session_id,
1363 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1364 if (status != QDF_STATUS_SUCCESS)
1365 goto end;
1366
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301367 /* Register IPA Tx desc free callback */
1368 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1369
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301370 ipa_ctx->num_iface++;
1371
1372 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1373
1374 return status;
1375
1376end:
1377 if (iface_context)
1378 wlan_ipa_cleanup_iface(iface_context);
1379
1380 return status;
1381}
1382
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301383#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1384/**
1385 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1386 * @ipa_ctx: IPA context
1387 *
1388 * Return: QDF STATUS
1389 */
1390static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1391{
1392 ipa_debug("enter");
1393
1394 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1395 ipa_err("IPA WDI Pipe activation failed");
1396 return QDF_STATUS_E_BUSY;
1397 }
1398
1399 ipa_debug("exit");
1400
1401 return QDF_STATUS_SUCCESS;
1402}
1403
1404/**
1405 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1406 * @ipa_ctx: IPA context
1407 *
1408 * Return: None
1409 */
1410static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1411{
1412 ipa_debug("enter");
1413
1414 wlan_ipa_uc_disable_pipes(ipa_ctx);
1415
1416 ipa_debug("exit: IPA WDI Pipes deactivated");
1417}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301418
1419bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1420{
1421 return !ipa_ctx->ipa_pipes_down;
1422}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301423#else
1424
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301425/**
1426 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1427 * @ipa_ctx: IPA context
1428 *
1429 * Return: QDF STATUS
1430 */
1431static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1432{
1433 ipa_debug("enter");
1434
1435 ipa_ctx->activated_fw_pipe = 0;
1436 ipa_ctx->resource_loading = true;
1437
1438 /* If RM feature enabled
1439 * Request PROD Resource first
1440 * PROD resource may return sync or async manners
1441 */
1442 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001443 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1444 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301445 /* RM PROD request sync return
1446 * enable pipe immediately
1447 */
1448 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1449 ipa_err("IPA WDI Pipe activation failed");
1450 ipa_ctx->resource_loading = false;
1451 return QDF_STATUS_E_BUSY;
1452 }
1453 } else {
1454 ipa_err("IPA WDI Pipe activation deferred");
1455 }
1456 } else {
1457 /* RM Disabled
1458 * Just enabled all the PIPEs
1459 */
1460 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1461 ipa_err("IPA WDI Pipe activation failed");
1462 ipa_ctx->resource_loading = false;
1463 return QDF_STATUS_E_BUSY;
1464 }
1465 ipa_ctx->resource_loading = false;
1466 }
1467
1468 ipa_debug("exit");
1469
1470 return QDF_STATUS_SUCCESS;
1471}
1472
1473/**
1474 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1475 * @ipa_ctx: IPA context
1476 *
1477 * Return: None
1478 */
1479static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1480{
1481 ipa_debug("enter");
1482
1483 ipa_ctx->resource_unloading = true;
1484 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1485 ipa_info("Disable FW RX PIPE");
1486 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301487
1488 ipa_debug("exit: IPA WDI Pipes deactivated");
1489}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301490
1491bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1492{
1493 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1494}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301495#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301496
1497/**
1498 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1499 * @ipa_ctx: global IPA context
1500 * @offload_type: MCC or SCC
1501 * @session_id: Session Id
1502 * @enable: TX offload enable or disable
1503 *
1504 * Return: none
1505 */
1506static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1507 uint32_t offload_type,
1508 uint8_t session_id,
1509 bool enable)
1510{
1511
1512 struct ipa_uc_offload_control_params req = {0};
1513
1514 if (session_id >= WLAN_IPA_MAX_SESSION) {
1515 ipa_err("invalid session id: %d", session_id);
1516 return;
1517 }
1518
1519 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301520 ipa_info("IPA offload status is already set");
1521 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301522 offload_type, session_id, enable);
1523 return;
1524 }
1525
1526 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1527 offload_type, session_id, enable);
1528
1529 req.offload_type = offload_type;
1530 req.vdev_id = session_id;
1531 req.enable = enable;
1532
1533 if (QDF_STATUS_SUCCESS !=
1534 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1535 ipa_err("Fail to enable IPA offload");
1536 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1537 offload_type, session_id, enable);
1538 } else {
1539 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1540 }
1541}
1542
1543/**
1544 * __wlan_ipa_wlan_evt() - IPA event handler
1545 * @net_dev: Interface net device
1546 * @device_mode: Net interface device mode
1547 * @sta_id: station id for the event
1548 * @session_id: session id for the event
1549 * @type: event enum of type ipa_wlan_event
1550 * @mac_address: MAC address associated with the event
1551 *
1552 * This function is meant to be called from within wlan_ipa_ctx.c
1553 *
1554 * Return: QDF STATUS
1555 */
1556static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1557 uint8_t sta_id, uint8_t session_id,
1558 qdf_ipa_wlan_event type,
1559 uint8_t *mac_addr)
1560{
1561 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1562 struct wlan_ipa_iface_context *iface_ctx = NULL;
1563 qdf_ipa_msg_meta_t meta;
1564 qdf_ipa_wlan_msg_t *msg;
1565 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1566 int i;
1567 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001568 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301569 struct wlan_objmgr_pdev *pdev;
1570 struct wlan_objmgr_psoc *psoc;
1571 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301572
Mohit Khannacabf5e72018-07-24 13:28:43 -07001573 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d session_id: %u",
1574 net_dev->name, type, mac_addr, sta_id, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301575
1576 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1577 return QDF_STATUS_E_INVAL;
1578
1579 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1580 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1581 (device_mode != QDF_SAP_MODE)) {
1582 return QDF_STATUS_SUCCESS;
1583 }
1584
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301585 pdev = ipa_ctx->pdev;
1586 psoc = wlan_pdev_get_psoc(pdev);
1587 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1588 WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301589 QDF_BUG(session_id < WLAN_IPA_MAX_SESSION);
1590
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301591 if (vdev)
1592 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301593 else
1594 ipa_err("vdev is NULL, session_id: %u", session_id);
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301595
Ryan Hsub5783cf2018-05-14 12:13:15 -07001596 if (ipa_ctx->sta_connected) {
1597 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1598 if (iface_ctx)
1599 sta_session_id = iface_ctx->session_id;
1600 else
1601 ipa_err("sta iface_ctx is NULL");
1602 }
1603
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301604 /*
1605 * During IPA UC resource loading/unloading new events can be issued.
1606 */
1607 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1608 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1609 unsigned int pending_event_count;
1610 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1611
1612 ipa_info("Event:%d IPA resource %s inprogress", type,
1613 ipa_ctx->resource_loading ?
1614 "load" : "unload");
1615
1616 /* Wait until completion of the long/unloading */
1617 status = qdf_wait_for_event_completion(
1618 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001619 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301620 if (status != QDF_STATUS_SUCCESS) {
1621 /*
1622 * If timed out, store the events separately and
1623 * handle them later.
1624 */
1625 ipa_info("IPA resource %s timed out",
1626 ipa_ctx->resource_loading ?
1627 "load" : "unload");
1628
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301629 if (type == QDF_IPA_AP_DISCONNECT)
1630 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1631 SIR_AP_RX_DATA_OFFLOAD,
1632 session_id, false);
1633
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301634 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1635
1636 pending_event_count =
1637 qdf_list_size(&ipa_ctx->pending_event);
1638 if (pending_event_count >=
1639 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1640 ipa_info("Reached max pending evt count");
1641 qdf_list_remove_front(
1642 &ipa_ctx->pending_event,
1643 (qdf_list_node_t **)&pending_event);
1644 } else {
1645 pending_event =
1646 (struct wlan_ipa_uc_pending_event *)
1647 qdf_mem_malloc(sizeof(
1648 struct wlan_ipa_uc_pending_event));
1649 }
1650
1651 if (!pending_event) {
1652 ipa_err("Pending event memory alloc fail");
1653 qdf_mutex_release(&ipa_ctx->ipa_lock);
1654 return QDF_STATUS_E_NOMEM;
1655 }
1656
1657 pending_event->net_dev = net_dev;
1658 pending_event->device_mode = device_mode;
1659 pending_event->sta_id = sta_id;
1660 pending_event->session_id = session_id;
1661 pending_event->type = type;
1662 pending_event->is_loading = ipa_ctx->resource_loading;
1663 qdf_mem_copy(pending_event->mac_addr,
1664 mac_addr, QDF_MAC_ADDR_SIZE);
1665 qdf_list_insert_back(&ipa_ctx->pending_event,
1666 &pending_event->node);
1667
1668 qdf_mutex_release(&ipa_ctx->ipa_lock);
1669
Yun Park21ec4902018-04-24 12:11:01 -07001670 /* Cleanup interface */
1671 if (type == QDF_IPA_STA_DISCONNECT ||
1672 type == QDF_IPA_AP_DISCONNECT) {
1673 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1674 iface_ctx = &ipa_ctx->iface_context[i];
1675
1676 if (iface_ctx->dev == net_dev)
1677 break;
1678 }
1679 if (iface_ctx)
1680 wlan_ipa_cleanup_iface(iface_ctx);
1681 }
1682
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301683 return QDF_STATUS_SUCCESS;
1684 }
1685 ipa_info("IPA resource %s completed",
1686 ipa_ctx->resource_loading ?
1687 "load" : "unload");
1688 }
1689
1690 ipa_ctx->stats.event[type]++;
1691
1692 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1693 switch (type) {
1694 case QDF_IPA_STA_CONNECT:
1695 qdf_mutex_acquire(&ipa_ctx->event_lock);
1696
1697 /* STA already connected and without disconnect, connect again
1698 * This is Roaming scenario
1699 */
1700 if (ipa_ctx->sta_connected) {
1701 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1702 if (iface_ctx)
1703 wlan_ipa_cleanup_iface(iface_ctx);
1704 }
1705
1706 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1707 sta_id, session_id);
1708 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001709 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301710 qdf_mutex_release(&ipa_ctx->event_lock);
1711 goto end;
1712 }
1713
1714 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1715 (ipa_ctx->sap_num_connected_sta > 0) &&
1716 !ipa_ctx->sta_connected) {
1717 qdf_mutex_release(&ipa_ctx->event_lock);
1718 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1719 SIR_STA_RX_DATA_OFFLOAD, session_id,
1720 true);
1721 qdf_mutex_acquire(&ipa_ctx->event_lock);
1722 }
1723
1724 ipa_ctx->vdev_to_iface[session_id] =
1725 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1726
1727 ipa_ctx->sta_connected = 1;
1728
1729 qdf_mutex_release(&ipa_ctx->event_lock);
1730
Mohit Khannacabf5e72018-07-24 13:28:43 -07001731 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1732 ipa_ctx->sta_connected,
1733 session_id,
1734 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301735 break;
1736
1737 case QDF_IPA_AP_CONNECT:
1738 qdf_mutex_acquire(&ipa_ctx->event_lock);
1739
1740 /* For DFS channel we get two start_bss event (before and after
1741 * CAC). Also when ACS range includes both DFS and non DFS
1742 * channels, we could possibly change channel many times due to
1743 * RADAR detection and chosen channel may not be a DFS channels.
1744 * So dont return error here. Just discard the event.
1745 */
jiadc908ada2018-05-11 14:40:54 +08001746 if (ipa_ctx->vdev_to_iface[session_id] !=
1747 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301748 qdf_mutex_release(&ipa_ctx->event_lock);
1749 return 0;
1750 }
1751
1752 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1753 sta_id, session_id);
1754 if (status != QDF_STATUS_SUCCESS) {
1755 qdf_mutex_release(&ipa_ctx->event_lock);
1756 ipa_err("%s: Evt: %d, Interface setup failed",
1757 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1758 goto end;
1759 }
1760
1761 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1762 qdf_mutex_release(&ipa_ctx->event_lock);
1763 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1764 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1765 qdf_mutex_acquire(&ipa_ctx->event_lock);
1766 }
1767
1768 ipa_ctx->vdev_to_iface[session_id] =
1769 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001770 ipa_debug("vdev_to_iface[%u]=%u",
1771 session_id,
1772 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301773 qdf_mutex_release(&ipa_ctx->event_lock);
1774 break;
1775
1776 case QDF_IPA_STA_DISCONNECT:
1777 qdf_mutex_acquire(&ipa_ctx->event_lock);
1778
1779 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301780 struct wlan_ipa_iface_context *iface;
1781
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301782 qdf_mutex_release(&ipa_ctx->event_lock);
1783 ipa_err("%s: Evt: %d, STA already disconnected",
1784 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301785
1786 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1787 if (iface && (iface->dev == net_dev))
1788 wlan_ipa_cleanup_iface(iface);
1789
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301790 return QDF_STATUS_E_INVAL;
1791 }
1792
1793 ipa_ctx->sta_connected = 0;
1794
1795 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1796 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1797 msg_ex->name);
1798 } else {
1799 /* Disable IPA UC TX PIPE when STA disconnected */
1800 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001801 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001802 !ipa_ctx->ipa_pipes_down &&
1803 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001804 if (cds_is_driver_unloading()) {
1805 /*
1806 * We disable WDI pipes directly here
1807 * since IPA_OPCODE_TX/RX_SUSPEND
1808 * message will not be processed when
1809 * unloading WLAN driver is in progress
1810 */
1811 wlan_ipa_uc_disable_pipes(ipa_ctx);
1812 } else {
1813 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1814 }
1815 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301816 }
1817
1818 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1819 (ipa_ctx->sap_num_connected_sta > 0)) {
1820 qdf_mutex_release(&ipa_ctx->event_lock);
1821 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1822 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1823 qdf_mutex_acquire(&ipa_ctx->event_lock);
1824 ipa_ctx->vdev_to_iface[session_id] =
1825 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001826 ipa_debug("vdev_to_iface[%u]=%u",
1827 session_id,
1828 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301829 }
1830
1831 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1832 iface_ctx = &ipa_ctx->iface_context[i];
1833
1834 if (iface_ctx->dev == net_dev)
1835 break;
1836 }
1837 if (i < WLAN_IPA_MAX_IFACE)
1838 wlan_ipa_cleanup_iface(iface_ctx);
1839
1840 qdf_mutex_release(&ipa_ctx->event_lock);
1841
1842 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1843 break;
1844
1845 case QDF_IPA_AP_DISCONNECT:
1846 qdf_mutex_acquire(&ipa_ctx->event_lock);
1847
1848 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001849 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001850 !ipa_ctx->ipa_pipes_down &&
1851 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301852 if (cds_is_driver_unloading()) {
1853 /*
1854 * We disable WDI pipes directly here since
1855 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1856 * processed when unloading WLAN driver is in
1857 * progress
1858 */
1859 wlan_ipa_uc_disable_pipes(ipa_ctx);
1860 } else {
1861 /*
1862 * This shouldn't happen :
1863 * No interface left but WDI pipes are still
1864 * active - force close WDI pipes
1865 */
1866 ipa_err("No interface left but WDI pipes are still active");
1867 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1868 }
1869 }
1870
1871 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1872 qdf_mutex_release(&ipa_ctx->event_lock);
1873 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1874 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1875 qdf_mutex_acquire(&ipa_ctx->event_lock);
1876 ipa_ctx->vdev_to_iface[session_id] =
1877 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001878 ipa_debug("vdev_to_iface[%u]=%u",
1879 session_id,
1880 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301881 }
1882
1883 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1884 iface_ctx = &ipa_ctx->iface_context[i];
1885
1886 if (iface_ctx->dev == net_dev)
1887 break;
1888 }
1889 if (i < WLAN_IPA_MAX_IFACE)
1890 wlan_ipa_cleanup_iface(iface_ctx);
1891
1892 qdf_mutex_release(&ipa_ctx->event_lock);
1893 break;
1894
1895 case QDF_IPA_CLIENT_CONNECT_EX:
1896 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1897 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1898 net_dev->name, type);
1899 return QDF_STATUS_SUCCESS;
1900 }
1901
1902 qdf_mutex_acquire(&ipa_ctx->event_lock);
1903 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1904 mac_addr)) {
1905 qdf_mutex_release(&ipa_ctx->event_lock);
1906 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1907 return QDF_STATUS_SUCCESS;
1908 }
1909
1910 /* Enable IPA UC Data PIPEs when first STA connected */
1911 if (ipa_ctx->sap_num_connected_sta == 0 &&
1912 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301913
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301914 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1915 ipa_ctx->sta_connected) {
1916 qdf_mutex_release(&ipa_ctx->event_lock);
1917 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1918 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301919 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301920 qdf_mutex_acquire(&ipa_ctx->event_lock);
1921 }
1922
1923 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1924 if (status != QDF_STATUS_SUCCESS) {
1925 ipa_info("%s: handle 1st con fail",
1926 net_dev->name);
1927
1928 if (wlan_ipa_uc_sta_is_enabled(
1929 ipa_ctx->config) &&
1930 ipa_ctx->sta_connected) {
1931 qdf_mutex_release(&ipa_ctx->event_lock);
1932 wlan_ipa_uc_offload_enable_disable(
1933 ipa_ctx,
1934 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301935 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301936 } else {
1937 qdf_mutex_release(&ipa_ctx->event_lock);
1938 }
1939
1940 return status;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001941 } else
1942 ipa_debug("%s: handle 1st con success",
1943 net_dev->name);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301944 }
1945
1946 ipa_ctx->sap_num_connected_sta++;
1947
1948 qdf_mutex_release(&ipa_ctx->event_lock);
1949
1950 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1951 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1952 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1953 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1954 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1955
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001956 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301957 ipa_err("msg_ex allocation failed");
1958 return QDF_STATUS_E_NOMEM;
1959 }
1960 strlcpy(msg_ex->name, net_dev->name,
1961 IPA_RESOURCE_NAME_MAX);
1962 msg_ex->num_of_attribs = 1;
1963 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1964 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1965 msg_ex->attribs[0].offset =
1966 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1967 } else {
1968 msg_ex->attribs[0].offset =
1969 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1970 }
1971 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1972 IPA_MAC_ADDR_SIZE);
1973
1974 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1975 ipa_info("%s: Evt: %d send ipa msg fail",
1976 net_dev->name, type);
1977 qdf_mem_free(msg_ex);
1978 return QDF_STATUS_E_FAILURE;
1979 }
1980 ipa_ctx->stats.num_send_msg++;
1981
1982 ipa_info("sap_num_connected_sta=%d",
1983 ipa_ctx->sap_num_connected_sta);
1984
1985 return QDF_STATUS_SUCCESS;
1986
1987 case WLAN_CLIENT_DISCONNECT:
1988 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1989 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1990 msg_ex->name);
1991 return QDF_STATUS_SUCCESS;
1992 }
1993
1994 qdf_mutex_acquire(&ipa_ctx->event_lock);
1995 if (!ipa_ctx->sap_num_connected_sta) {
1996 qdf_mutex_release(&ipa_ctx->event_lock);
1997 ipa_err("%s: Evt: %d, Client already disconnected",
1998 msg_ex->name,
1999 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2000
2001 return QDF_STATUS_SUCCESS;
2002 }
2003 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
2004 sta_id, mac_addr)) {
2005 qdf_mutex_release(&ipa_ctx->event_lock);
2006 ipa_err("%s: STA ID %d NOT found, not valid",
2007 msg_ex->name, sta_id);
2008
2009 return QDF_STATUS_SUCCESS;
2010 }
2011 ipa_ctx->sap_num_connected_sta--;
2012
2013 /* Disable IPA UC TX PIPE when last STA disconnected */
2014 if (!ipa_ctx->sap_num_connected_sta &&
2015 ipa_ctx->uc_loaded == true) {
Yun Parka29974a2018-04-09 12:05:49 -07002016 if ((false == ipa_ctx->resource_unloading) &&
2017 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
2018 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08002019 if (cds_is_driver_unloading()) {
2020 /*
2021 * We disable WDI pipes directly here
2022 * since IPA_OPCODE_TX/RX_SUSPEND
2023 * message will not be processed when
2024 * unloading WLAN driver is in progress
2025 */
2026 wlan_ipa_uc_disable_pipes(ipa_ctx);
2027 } else {
2028 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2029 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302030 }
2031
2032 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
2033 ipa_ctx->sta_connected) {
2034 qdf_mutex_release(&ipa_ctx->event_lock);
2035 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2036 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302037 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302038 } else {
2039 qdf_mutex_release(&ipa_ctx->event_lock);
2040 }
2041 } else {
2042 qdf_mutex_release(&ipa_ctx->event_lock);
2043 }
2044
2045 ipa_info("sap_num_connected_sta=%d",
2046 ipa_ctx->sap_num_connected_sta);
2047 break;
2048
2049 default:
2050 return QDF_STATUS_SUCCESS;
2051 }
2052
2053 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2054 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2055 if (!msg) {
2056 ipa_err("msg allocation failed");
2057 return QDF_STATUS_E_NOMEM;
2058 }
2059
2060 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2061 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2062 IPA_RESOURCE_NAME_MAX);
2063 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2064
2065 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
2066 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2067
2068 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2069
2070 ipa_err("%s: Evt: %d fail",
2071 QDF_IPA_WLAN_MSG_NAME(msg),
2072 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2073 qdf_mem_free(msg);
2074
2075 return QDF_STATUS_E_FAILURE;
2076 }
2077
2078 ipa_ctx->stats.num_send_msg++;
2079
2080end:
2081 return QDF_STATUS_SUCCESS;
2082}
2083
2084/**
2085 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002086 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302087 *
2088 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2089 */
2090static qdf_ipa_wlan_event
2091wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2092{
Yun Park84fbb272018-04-02 15:31:01 -07002093 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302094
2095 switch (wlan_ipa_event_type) {
2096 case WLAN_IPA_CLIENT_CONNECT:
2097 ipa_event = QDF_IPA_CLIENT_CONNECT;
2098 break;
2099 case WLAN_IPA_CLIENT_DISCONNECT:
2100 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2101 break;
2102 case WLAN_IPA_AP_CONNECT:
2103 ipa_event = QDF_IPA_AP_CONNECT;
2104 break;
2105 case WLAN_IPA_AP_DISCONNECT:
2106 ipa_event = QDF_IPA_AP_DISCONNECT;
2107 break;
2108 case WLAN_IPA_STA_CONNECT:
2109 ipa_event = QDF_IPA_STA_CONNECT;
2110 break;
2111 case WLAN_IPA_STA_DISCONNECT:
2112 ipa_event = QDF_IPA_STA_DISCONNECT;
2113 break;
2114 case WLAN_IPA_CLIENT_CONNECT_EX:
2115 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2116 break;
2117 case WLAN_IPA_WLAN_EVENT_MAX:
2118 default:
2119 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2120 break;
2121 }
2122
2123 return ipa_event;
2124}
2125
2126/**
2127 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2128 * @net_dev: Interface net device
2129 * @device_mode: Net interface device mode
2130 * @sta_id: station id for the event
2131 * @session_id: session id for the event
2132 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2133 * @mac_address: MAC address associated with the event
2134 *
2135 * Return: QDF_STATUS
2136 */
2137QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
2138 uint8_t sta_id, uint8_t session_id,
2139 enum wlan_ipa_wlan_event ipa_event_type,
2140 uint8_t *mac_addr)
2141{
2142 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2143 QDF_STATUS status = QDF_STATUS_SUCCESS;
2144
2145 /* Data path offload only support for STA and SAP mode */
2146 if ((device_mode == QDF_STA_MODE) ||
2147 (device_mode == QDF_SAP_MODE))
2148 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
2149 session_id, type, mac_addr);
2150
2151 return status;
2152}
2153
2154/**
2155 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2156 * @ipa_ctx: Global IPA IPA context
2157 * @is_loading: Indicate if invoked during loading
2158 *
2159 * Return: None
2160 */
2161static void
2162wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2163{
2164 unsigned int pending_event_count;
2165 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2166
2167 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2168 ipa_debug("Pending Event Count %d", pending_event_count);
2169 if (!pending_event_count) {
2170 ipa_debug("No Pending Event");
2171 return;
2172 }
2173
2174 qdf_list_remove_front(&ipa_ctx->pending_event,
2175 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002176 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302177 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2178 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2179 struct wlan_objmgr_vdev *vdev =
2180 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2181 pending_event->session_id,
2182 WLAN_IPA_ID);
2183 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302184 __wlan_ipa_wlan_evt(pending_event->net_dev,
2185 pending_event->device_mode,
2186 pending_event->sta_id,
2187 pending_event->session_id,
2188 pending_event->type,
2189 pending_event->mac_addr);
2190 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302191
2192 if (vdev)
2193 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302194 qdf_mem_free(pending_event);
2195 pending_event = NULL;
2196 qdf_list_remove_front(&ipa_ctx->pending_event,
2197 (qdf_list_node_t **)&pending_event);
2198 }
2199}
2200
2201/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002202 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2203 * @ipa_ctx: IPA context
2204 *
2205 * Return: None
2206 */
2207static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2208{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302209 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002210 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302211 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002212
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302213 if (!ipa_ctx->tx_desc_pool)
2214 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002215
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302216 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2217 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2218 for (i = 0; i < pool_size; i++) {
2219 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002220 if (ipa_tx_desc)
2221 qdf_ipa_free_skb(ipa_tx_desc);
2222
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302223 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2224 &ipa_ctx->tx_desc_pool[i].node) !=
2225 QDF_STATUS_SUCCESS)
2226 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002227 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302228 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2229
2230 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2231 qdf_mem_free(ipa_ctx->tx_desc_pool);
2232 ipa_ctx->tx_desc_pool = NULL;
2233
2234 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2235 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002236}
2237
2238/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302239 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302240 * @ipa_ctx: IPA context
2241 *
2242 * Return: QDF_STATUS
2243 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302244static QDF_STATUS
2245wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302246{
2247 int i;
2248 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302249
2250 max_desc_cnt = ipa_ctx->config->txbuf_count;
2251
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302252 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2253 max_desc_cnt);
2254
2255 if (!ipa_ctx->tx_desc_pool) {
2256 ipa_err("Free Tx descriptor allocation failed");
2257 return QDF_STATUS_E_NOMEM;
2258 }
2259
2260 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302261
2262 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2263 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302264 ipa_ctx->tx_desc_pool[i].id = i;
2265 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2266 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2267 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302268 }
2269
2270 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2271 ipa_ctx->stats.num_tx_desc_error = 0;
2272
2273 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2274
2275 return QDF_STATUS_SUCCESS;
2276}
2277
2278#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2279/**
2280 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2281 * @ipa_ctx: Global IPA IPA context
2282 * @desc_fifo_sz: Number of descriptors
2283 *
2284 * Return: 0 on success, negative errno on error
2285 */
2286static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2287 int32_t desc_fifo_sz)
2288{
2289 int i, ret = 0;
2290 qdf_ipa_sys_connect_params_t *ipa;
2291
2292 /*setup TX pipes */
2293 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2294 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2295
2296 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2297 ipa->desc_fifo_sz = desc_fifo_sz;
2298 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302299 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302300
2301 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2302 ipa->ipa_ep_cfg.hdr.hdr_len =
2303 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2304 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2305 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2306 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2307 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2308 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2309 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2310 } else {
2311 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2312 }
2313 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2314
2315 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2316 &ipa_ctx->sys_pipe[i].conn_hdl);
2317 if (ret) {
2318 ipa_err("Failed for pipe %d ret: %d", i, ret);
2319 return ret;
2320 }
2321 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2322 }
2323
2324 return ret;
2325}
2326#else
2327/**
2328 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302329 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302330 * @desc_fifo_sz: Number of descriptors
2331 *
2332 * Return: 0 on success, negative errno on error
2333 */
2334static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2335 int32_t desc_fifo_sz)
2336{
2337 /*
2338 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2339 * is enabled, where per vdev descriptors are supported in firmware.
2340 */
2341 return 0;
2342}
2343#endif
2344
Sravan Kumar Kairam7efc0132019-03-25 16:13:46 +05302345#if defined(CONFIG_IPA_WDI_UNIFIED_API) && defined(IPA_WDI3_GSI)
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302346/**
2347 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2348 * @ipa_ctx: IPA context
2349 *
2350 * Return: rx ipa sys client
2351 */
2352static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2353{
2354 if (ipa_ctx->over_gsi)
2355 return IPA_CLIENT_WLAN2_PROD;
2356 else
2357 return IPA_CLIENT_WLAN1_PROD;
2358}
2359#else
2360static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2361{
2362 return IPA_CLIENT_WLAN1_PROD;
2363}
2364#endif
2365
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302366/**
2367 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2368 * @ipa_ctx: Global IPA IPA context
2369 * @desc_fifo_sz: Number of descriptors
2370 *
2371 * Return: 0 on success, negative errno on error
2372 */
2373static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2374 int32_t desc_fifo_sz)
2375{
2376 int ret = 0;
2377 qdf_ipa_sys_connect_params_t *ipa;
2378
2379 /*
2380 * Hard code it here, this can be extended if in case
2381 * PROD pipe is also per interface.
2382 * Right now there is no advantage of doing this.
2383 */
2384 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2385
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302386 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302387 ipa->desc_fifo_sz = desc_fifo_sz;
2388 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302389 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302390
2391 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2392 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2393 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2394 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2395
2396 ret = qdf_ipa_setup_sys_pipe(ipa,
2397 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2398 if (ret) {
2399 ipa_err("Failed for RX pipe: %d", ret);
2400 return ret;
2401 }
2402 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2403
2404 return ret;
2405}
2406
2407/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002408 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2409 * @ipa_ctx: Global IPA IPA context
2410 *
2411 * Return: None
2412 */
2413static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2414{
2415 int ret, i;
2416
2417 if (!ipa_ctx)
2418 return;
2419
2420 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2421 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2422 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2423 ipa_ctx->sys_pipe[i].conn_hdl);
2424 if (ret)
2425 ipa_err("Failed:%d", ret);
2426
2427 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2428 }
2429 }
2430
2431 wlan_ipa_free_tx_desc_list(ipa_ctx);
2432}
2433
2434/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302435 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2436 * @ipa_ctx: Global IPA IPA context
2437 *
2438 * Return: 0 on success, negative errno on error
2439 */
2440static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2441{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002442 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302443 uint32_t desc_fifo_sz;
2444
2445 /* The maximum number of descriptors that can be provided to a BAM at
2446 * once is one less than the total number of descriptors that the buffer
2447 * can contain.
2448 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2449 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2450 * be provided at once.
2451 * Because of above requirement, one extra descriptor will be added to
2452 * make sure hardware always has one descriptor.
2453 */
2454 desc_fifo_sz = ipa_ctx->config->desc_size
2455 + SPS_DESC_SIZE;
2456
2457 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2458 if (ret) {
2459 ipa_err("Failed for TX pipe: %d", ret);
2460 goto setup_sys_pipe_fail;
2461 }
2462
2463 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2464 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2465 if (ret) {
2466 ipa_err("Failed for RX pipe: %d", ret);
2467 goto setup_sys_pipe_fail;
2468 }
2469 }
2470
2471 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302472 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302473 if (ret)
2474 goto setup_sys_pipe_fail;
2475
2476 return ret;
2477
2478setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002479 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302480
2481 return ret;
2482}
2483
jiadbb47e132018-03-30 16:28:30 +08002484#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2485QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2486 bool mcc_mode)
2487{
2488 qdf_ipa_msg_meta_t meta;
2489 qdf_ipa_wlan_msg_t *msg;
2490 int ret;
2491
2492 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2493 return QDF_STATUS_SUCCESS;
2494
2495 /* Send SCC/MCC Switching event to IPA */
2496 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2497 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002498 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002499 ipa_err("msg allocation failed");
2500 return QDF_STATUS_E_NOMEM;
2501 }
2502
jiad629b2172018-05-11 15:34:22 +08002503 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002504 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002505 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2506 } else {
jiadbb47e132018-03-30 16:28:30 +08002507 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002508 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2509 }
2510
jiadbb47e132018-03-30 16:28:30 +08002511 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2512 "ipa_send_msg(Evt:%d)",
2513 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2514
2515 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2516
2517 if (ret) {
2518 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2519 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2520 qdf_mem_free(msg);
2521 return QDF_STATUS_E_FAILURE;
2522 }
2523
2524 return QDF_STATUS_SUCCESS;
2525}
2526
2527static void wlan_ipa_mcc_work_handler(void *data)
2528{
2529 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2530
2531 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2532}
2533#endif
2534
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302535/**
2536 * wlan_ipa_setup() - IPA initialization function
2537 * @ipa_ctx: IPA context
2538 * @ipa_cfg: IPA config
2539 *
2540 * Allocate ipa_ctx resources, ipa pipe resource and register
2541 * wlan interface with IPA module.
2542 *
2543 * Return: QDF_STATUS enumeration
2544 */
2545QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2546 struct wlan_ipa_config *ipa_cfg)
2547{
2548 int ret, i;
2549 struct wlan_ipa_iface_context *iface_context = NULL;
2550 QDF_STATUS status;
2551
2552 ipa_debug("enter");
2553
2554 gp_ipa = ipa_ctx;
2555 ipa_ctx->num_iface = 0;
2556 ipa_ctx->config = ipa_cfg;
2557
2558 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2559
2560 /* Create the interface context */
2561 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2562 iface_context = &ipa_ctx->iface_context[i];
2563 iface_context->ipa_ctx = ipa_ctx;
2564 iface_context->cons_client =
2565 wlan_ipa_iface_2_client[i].cons_client;
2566 iface_context->prod_client =
2567 wlan_ipa_iface_2_client[i].prod_client;
2568 iface_context->iface_id = i;
2569 iface_context->dev = NULL;
2570 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2571 iface_context->tl_context = NULL;
2572 qdf_spinlock_create(&iface_context->interface_lock);
2573 }
2574
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302575 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302576 qdf_spinlock_create(&ipa_ctx->pm_lock);
2577 qdf_spinlock_create(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302578 qdf_spinlock_create(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302579 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2580 qdf_list_create(&ipa_ctx->pending_event, 1000);
2581 qdf_mutex_create(&ipa_ctx->event_lock);
2582 qdf_mutex_create(&ipa_ctx->ipa_lock);
2583
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302584 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2585 if (status != QDF_STATUS_SUCCESS)
2586 goto fail_setup_rm;
2587
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302588 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2589 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2590 sizeof(struct wlan_ipa_sys_pipe));
2591
2592 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2593 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2594 ipa_ctx->sap_num_connected_sta = 0;
2595 ipa_ctx->ipa_tx_packets_diff = 0;
2596 ipa_ctx->ipa_rx_packets_diff = 0;
2597 ipa_ctx->ipa_p_tx_packets = 0;
2598 ipa_ctx->ipa_p_rx_packets = 0;
2599 ipa_ctx->resource_loading = false;
2600 ipa_ctx->resource_unloading = false;
2601 ipa_ctx->sta_connected = 0;
2602 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302603 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302604 ipa_ctx->wdi_enabled = false;
2605 /* Setup IPA system pipes */
2606 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2607 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2608 if (ret)
2609 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002610
2611 qdf_create_work(0, &ipa_ctx->mcc_work,
2612 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302613 }
2614
2615 status = wlan_ipa_wdi_init(ipa_ctx);
2616 if (status == QDF_STATUS_E_BUSY)
2617 status = wlan_ipa_uc_send_wdi_control_msg(false);
2618 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002619 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302620 goto fail_create_sys_pipe;
2621 }
2622 } else {
2623 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2624 if (ret)
2625 goto fail_create_sys_pipe;
2626 }
2627
2628 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2629
2630 ipa_debug("exit: success");
2631
2632 return QDF_STATUS_SUCCESS;
2633
2634fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302635 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2636
2637fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302638 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302639 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302640 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302641 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2642 iface_context = &ipa_ctx->iface_context[i];
2643 qdf_spinlock_destroy(&iface_context->interface_lock);
2644 }
2645 qdf_mutex_destroy(&ipa_ctx->event_lock);
2646 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2647 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302648 gp_ipa = NULL;
2649 ipa_debug("exit: fail");
2650
2651 return QDF_STATUS_E_FAILURE;
2652}
2653
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302654void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2655{
2656 qdf_nbuf_t skb;
2657 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2658
2659 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2660 return;
2661
2662 qdf_cancel_work(&ipa_ctx->pm_work);
2663
2664 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2665
2666 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2667 != NULL)) {
2668 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2669
2670 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002671
2672 if (pm_tx_cb->exception) {
2673 dev_kfree_skb_any(skb);
2674 } else {
2675 if (pm_tx_cb->ipa_tx_desc)
2676 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2677 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302678
2679 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2680 }
2681 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2682}
2683
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302684QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2685{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302686 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302687 int i;
2688
2689 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2690 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2691
2692 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002693 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302694 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002695 qdf_cancel_work(&ipa_ctx->mcc_work);
2696 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302697
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302698 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2699
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302700 wlan_ipa_flush(ipa_ctx);
2701
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302702 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2703 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302704 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302705
2706 /* destroy the interface lock */
2707 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2708 iface_context = &ipa_ctx->iface_context[i];
2709 qdf_spinlock_destroy(&iface_context->interface_lock);
2710 }
2711
2712 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2713 wlan_ipa_wdi_cleanup();
2714 qdf_mutex_destroy(&ipa_ctx->event_lock);
2715 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2716 qdf_list_destroy(&ipa_ctx->pending_event);
2717
2718 }
2719
2720 gp_ipa = NULL;
2721
2722 return QDF_STATUS_SUCCESS;
2723}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302724
2725struct wlan_ipa_iface_context
2726*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2727{
2728 struct wlan_ipa_iface_context *iface_ctx = NULL;
2729 int i;
2730
2731 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2732 iface_ctx = &ipa_ctx->iface_context[i];
2733
2734 if (iface_ctx->device_mode == mode)
2735 return iface_ctx;
2736 }
2737
2738 return NULL;
2739}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302740
jiadbb47e132018-03-30 16:28:30 +08002741void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302742{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302743 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002744 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302745
jiadbb47e132018-03-30 16:28:30 +08002746 if (ipa_ctx->mcc_mode == mcc_mode)
2747 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302748
jiadbb47e132018-03-30 16:28:30 +08002749 ipa_ctx->mcc_mode = mcc_mode;
2750 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302751}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302752
2753/**
2754 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2755 * @ipa_ctx: ipa ipa local context
2756 *
2757 * Will handle IPA UC image loaded indication comes from IPA kernel
2758 *
2759 * Return: None
2760 */
2761static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2762{
2763 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2764 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2765 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2766 QDF_STATUS status;
2767
2768 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002769
2770 if (!qdf_dev) {
2771 ipa_err("qdf device is NULL!");
2772 return;
2773 }
2774
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302775 if (true == ipa_ctx->uc_loaded) {
2776 ipa_info("UC already loaded");
2777 return;
2778 }
2779
Lihua Liu15f6e452018-05-30 17:31:06 +08002780 if (!qdf_dev) {
2781 ipa_err("qdf_dev is null");
2782 return;
2783 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302784 /* Connect pipe */
2785 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2786 if (status) {
2787 ipa_err("Failure to setup IPA pipes (status=%d)",
2788 status);
2789 return;
2790 }
2791
2792 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302793
2794 /* If already any STA connected, enable IPA/FW PIPEs */
2795 if (ipa_ctx->sap_num_connected_sta) {
2796 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2797 wlan_ipa_uc_handle_first_con(ipa_ctx);
2798 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302799}
2800
2801/**
2802 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2803 * @op_msg: operation message received from firmware
2804 * @usr_ctxt: user context registered with TL (we register the IPA Global
2805 * context)
2806 *
2807 * Return: None
2808 */
2809static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2810 struct wlan_ipa_priv *ipa_ctx)
2811{
2812 struct op_msg_type *msg = op_msg;
2813 struct ipa_uc_fw_stats *uc_fw_stat;
2814
2815 if (!op_msg) {
2816 ipa_err("INVALID ARG");
2817 return;
2818 }
2819
2820 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2821 ipa_err("INVALID OPCODE %d", msg->op_code);
2822 qdf_mem_free(op_msg);
2823 return;
2824 }
2825
2826 ipa_debug("OPCODE=%d", msg->op_code);
2827
2828 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2829 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2830 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2831 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07002832 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302833 ipa_ctx->resource_loading = false;
2834 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2835 if (ipa_ctx->wdi_enabled == false) {
2836 ipa_ctx->wdi_enabled = true;
2837 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2838 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2839 ipa_ctx->mcc_mode);
2840 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302841 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302842 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07002843 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302844 QDF_IPA_RM_RESOURCE_GRANTED,
2845 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2846 ipa_ctx->pending_cons_req = false;
2847 }
2848 qdf_mutex_release(&ipa_ctx->ipa_lock);
2849 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2850 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2851 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05302852
2853 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
2854 wlan_ipa_uc_disable_pipes(ipa_ctx);
2855 ipa_info("Disable FW TX PIPE");
2856 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2857 false, true);
2858 }
2859
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302860 ipa_ctx->activated_fw_pipe--;
2861 if (!ipa_ctx->activated_fw_pipe) {
2862 /*
2863 * Async return success from FW
2864 * Disable/suspend all the PIPEs
2865 */
2866 ipa_ctx->resource_unloading = false;
2867 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302868 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07002869 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
2870 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302871 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302872 ipa_ctx->pending_cons_req = false;
2873 }
2874 qdf_mutex_release(&ipa_ctx->ipa_lock);
2875 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2876 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2877 uc_fw_stat = (struct ipa_uc_fw_stats *)
2878 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2879
2880 /* WLAN FW WDI stats */
2881 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2882 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2883 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2884 /* STATs from FW */
2885 uc_fw_stat = (struct ipa_uc_fw_stats *)
2886 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2887 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2888 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2889 uc_fw_stat->tx_pkts_completed,
2890 ipa_ctx->ipa_p_tx_packets);
2891 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2892 (uc_fw_stat->rx_num_ind_drop_no_space +
2893 uc_fw_stat->rx_num_ind_drop_no_buf +
2894 uc_fw_stat->rx_num_pkts_indicated),
2895 ipa_ctx->ipa_p_rx_packets);
2896
2897 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2898 ipa_ctx->ipa_p_rx_packets =
2899 (uc_fw_stat->rx_num_ind_drop_no_space +
2900 uc_fw_stat->rx_num_ind_drop_no_buf +
2901 uc_fw_stat->rx_num_pkts_indicated);
2902 qdf_mutex_release(&ipa_ctx->ipa_lock);
2903 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2904 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2905 wlan_ipa_uc_loaded_handler(ipa_ctx);
2906 qdf_mutex_release(&ipa_ctx->ipa_lock);
2907 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2908 ipa_err("Invalid message: op_code=%d, reason=%d",
2909 msg->op_code, ipa_ctx->stat_req_reason);
2910 }
2911
2912 qdf_mem_free(op_msg);
2913}
2914
2915/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302916 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2917 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302918 *
2919 * Return: None
2920 */
jitiphilfdcaaba2018-09-03 16:19:52 +05302921static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302922{
2923 struct op_msg_type *msg;
2924 struct uc_op_work_struct *uc_op_work =
2925 (struct uc_op_work_struct *)data;
2926 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2927
2928 msg = uc_op_work->msg;
2929 uc_op_work->msg = NULL;
2930 ipa_debug("posted msg %d", msg->op_code);
2931
2932 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2933}
2934
2935/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302936 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
2937 * __wlan_ipa_uc_fw_op_event_handler
2938 * @data: uC OP work
2939 *
2940 * Return: None
2941 */
2942static void wlan_ipa_uc_fw_op_event_handler(void *data)
2943{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07002944 struct qdf_op_sync *op_sync;
2945
2946 if (qdf_op_protect(&op_sync))
2947 return;
2948
jitiphilfdcaaba2018-09-03 16:19:52 +05302949 __wlan_ipa_uc_fw_op_event_handler(data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07002950
2951 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05302952}
2953
2954/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302955 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2956 * @op_msg: operation message received from firmware
2957 * @ipa_ctx: Global IPA context
2958 *
2959 * Return: None
2960 */
2961static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2962{
2963 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2964 struct op_msg_type *msg;
2965 struct uc_op_work_struct *uc_op_work;
2966
2967 if (!ipa_ctx)
2968 goto end;
2969
2970 msg = (struct op_msg_type *)op_msg;
2971
2972 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2973 ipa_err("Invalid OP Code (%d)", msg->op_code);
2974 goto end;
2975 }
2976
2977 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2978 if (uc_op_work->msg) {
2979 /* When the same uC OPCODE is already pended, just return */
2980 goto end;
2981 }
2982
2983 uc_op_work->msg = msg;
2984 qdf_sched_work(0, &uc_op_work->work);
2985 return;
2986
2987end:
2988 qdf_mem_free(op_msg);
2989}
2990
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302991QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2992 qdf_device_t osdev)
2993{
2994 uint8_t i;
2995 QDF_STATUS status = QDF_STATUS_SUCCESS;
2996
2997 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2998 return QDF_STATUS_SUCCESS;
2999
3000 ipa_debug("enter");
3001
3002 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
3003 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
3004 ipa_ctx->vdev_offload_enabled[i] = false;
3005 }
3006
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303007 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
3008 ipa_err("IPA UC resource alloc fail");
3009 status = QDF_STATUS_E_FAILURE;
3010 goto fail_return;
3011 }
3012
3013 if (true == ipa_ctx->uc_loaded) {
3014 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
3015 if (status) {
3016 ipa_err("Failure to setup IPA pipes (status=%d)",
3017 status);
3018 status = QDF_STATUS_E_FAILURE;
3019 goto fail_return;
3020 }
3021
3022 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
3023 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08003024
3025 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
3026 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303027 }
3028
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303029 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3030 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
3031
3032 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3033 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
3034 wlan_ipa_uc_fw_op_event_handler,
3035 &ipa_ctx->uc_op_work[i]);
3036 ipa_ctx->uc_op_work[i].msg = NULL;
3037 }
3038
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303039fail_return:
3040 ipa_debug("exit: status=%d", status);
3041 return status;
3042}
3043
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303044/**
3045 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3046 * @ipa_ctx: pointer to IPA IPA struct
3047 *
3048 * Return: none
3049 */
3050static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
3051{
3052 struct wlan_ipa_uc_pending_event *pending_event = NULL;
3053
3054 while (qdf_list_remove_front(&ipa_ctx->pending_event,
3055 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3056 qdf_mem_free(pending_event);
3057}
3058
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303059QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
3060{
3061 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303062 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303063
3064 ipa_debug("enter");
3065
3066 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3067 return status;
3068
3069 if (!ipa_ctx->ipa_pipes_down)
3070 wlan_ipa_uc_disable_pipes(ipa_ctx);
3071
3072 if (true == ipa_ctx->uc_loaded) {
3073 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3074 ipa_ctx->tx_pipe_handle,
3075 ipa_ctx->rx_pipe_handle);
3076 if (status)
3077 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3078 status);
3079 }
3080
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303081 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3082 wlan_ipa_cleanup_pending_event(ipa_ctx);
3083 qdf_mutex_release(&ipa_ctx->ipa_lock);
3084
3085 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3086 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3087 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3088 ipa_ctx->uc_op_work[i].msg = NULL;
3089 }
3090
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303091 ipa_debug("exit: ret=%d", status);
3092 return status;
3093}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303094
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303095/**
3096 * wlan_ipa_uc_send_evt() - send event to ipa
3097 * @net_dev: Interface net device
3098 * @type: event type
3099 * @mac_addr: pointer to mac address
3100 *
3101 * Send event to IPA driver
3102 *
3103 * Return: QDF_STATUS
3104 */
3105static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3106 qdf_ipa_wlan_event type,
3107 uint8_t *mac_addr)
3108{
3109 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3110 qdf_ipa_msg_meta_t meta;
3111 qdf_ipa_wlan_msg_t *msg;
3112
3113 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3114 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3115 if (!msg) {
3116 ipa_err("msg allocation failed");
3117 return QDF_STATUS_E_NOMEM;
3118 }
3119
3120 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3121 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3122 IPA_RESOURCE_NAME_MAX);
3123 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3124
3125 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3126 ipa_err("%s: Evt: %d fail",
3127 QDF_IPA_WLAN_MSG_NAME(msg),
3128 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3129 qdf_mem_free(msg);
3130
3131 return QDF_STATUS_E_FAILURE;
3132 }
3133
3134 ipa_ctx->stats.num_send_msg++;
3135
3136 return QDF_STATUS_SUCCESS;
3137}
3138
3139QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3140 qdf_netdev_t net_dev)
3141{
3142 struct wlan_ipa_iface_context *iface_ctx;
3143 QDF_STATUS status;
3144
3145 ipa_debug("enter");
3146
3147 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3148 if (iface_ctx)
3149 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3150 net_dev->dev_addr);
3151 else
3152 return QDF_STATUS_E_INVAL;
3153
3154 ipa_debug("exit :%d", status);
3155
3156 return status;
3157}
3158
3159void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3160 qdf_netdev_t net_dev)
3161{
3162 struct wlan_ipa_iface_context *iface_ctx;
3163 int i;
3164
3165 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3166 iface_ctx = &ipa_ctx->iface_context[i];
3167 if (iface_ctx->dev == net_dev)
3168 break;
3169 }
3170
3171 if (iface_ctx)
3172 wlan_ipa_cleanup_iface(iface_ctx);
3173}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303174
3175void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3176{
3177 struct wlan_ipa_iface_context *iface;
3178 int i;
3179
3180 ipa_info("enter");
3181
3182 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3183 iface = &ipa_ctx->iface_context[i];
3184 if (iface->dev) {
3185 if (iface->device_mode == QDF_SAP_MODE)
3186 wlan_ipa_uc_send_evt(iface->dev,
3187 QDF_IPA_AP_DISCONNECT,
3188 iface->dev->dev_addr);
3189 else if (iface->device_mode == QDF_STA_MODE)
3190 wlan_ipa_uc_send_evt(iface->dev,
3191 QDF_IPA_STA_DISCONNECT,
3192 iface->dev->dev_addr);
3193 wlan_ipa_cleanup_iface(iface);
3194 }
3195 }
3196}
jitiphil0e3b5922018-07-24 18:43:50 +05303197
3198void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3199{
3200 qdf_ipa_msg_meta_t meta;
3201 qdf_ipa_wlan_msg_t *msg;
3202 int ret;
3203
3204 meta.msg_len = sizeof(*msg);
3205 msg = qdf_mem_malloc(meta.msg_len);
3206 if (!msg) {
3207 ipa_debug("msg allocation failed");
3208 return;
3209 }
3210
3211 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3212 ipa_debug("ipa_send_msg(Evt:%d)",
3213 meta.msg_type);
3214 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3215
3216 if (ret) {
3217 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3218 meta.msg_type, ret);
3219 qdf_mem_free(msg);
3220 }
3221 ipa_ctx->stats.num_send_msg++;
3222}