blob: 5dda9123837738b000ee584b92f602592b4e84f7 [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);
Mohit Khannae1b86022019-04-12 10:04:57 -0700357 if (!vdev)
358 goto drop_pkt;
359
jiad90b17252019-03-25 15:22:42 +0800360 if (cdp_tx_desc_thresh_reached(soc, vdev)) {
361 /* Drop the packet*/
362 ipa_ctx->stats.num_tx_fwd_err++;
Mohit Khannae1b86022019-04-12 10:04:57 -0700363 goto drop_pkt;
jiad90b17252019-03-25 15:22:42 +0800364 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700365
jiad90b17252019-03-25 15:22:42 +0800366 ipa_debug_rl("Forward packet to Tx (fw_desc=%d)", desc);
367 ipa_ctx->ipa_tx_forward++;
368
369 if ((desc & FW_RX_DESC_DISCARD_M)) {
370 wlan_ipa_forward(ipa_ctx, iface_ctx, skb);
371 ipa_ctx->ipa_rx_internal_drop_count++;
372 ipa_ctx->ipa_rx_discard++;
373 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
374 } else {
375 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
376
377 if (cloned_skb)
378 wlan_ipa_forward(ipa_ctx, iface_ctx,
379 cloned_skb);
380 else
381 ipa_err_rl("tx skb alloc failed");
382 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
383 }
384 }
Mohit Khannae1b86022019-04-12 10:04:57 -0700385 return ret;
jiad90b17252019-03-25 15:22:42 +0800386
Mohit Khannae1b86022019-04-12 10:04:57 -0700387drop_pkt:
388 dev_kfree_skb_any(skb);
389 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
jiad90b17252019-03-25 15:22:42 +0800390 return ret;
391}
392
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530393#ifdef CONFIG_IPA_WDI_UNIFIED_API
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530394/*
395 * TODO: Get WDI version through FW capabilities
396 */
Mohit Khannacabf5e72018-07-24 13:28:43 -0700397#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530398static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
399{
400 ipa_ctx->wdi_version = IPA_WDI_3;
401}
402#elif defined(QCA_WIFI_3_0)
403static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
404{
405 ipa_ctx->wdi_version = IPA_WDI_2;
406}
407#else
408static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
409{
410 ipa_ctx->wdi_version = IPA_WDI_1;
411}
412#endif
413
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530414static inline bool wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
415 qdf_device_t osdev)
416{
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530417 return ipa_ctx->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530418}
419
420static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
421 qdf_device_t osdev)
422{
423 qdf_ipa_sys_connect_params_t sys_in[WLAN_IPA_MAX_IFACE];
424 int i;
425
426 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++)
427 qdf_mem_copy(&sys_in[i],
428 &ipa_ctx->sys_pipe[i].ipa_sys_params,
429 sizeof(qdf_ipa_sys_connect_params_t));
430
431 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
432 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
433 wlan_ipa_wdi_meter_notifier_cb,
434 ipa_ctx->config->desc_size,
435 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
436 &ipa_ctx->tx_pipe_handle,
437 &ipa_ctx->rx_pipe_handle,
438 wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530439 sys_in, ipa_ctx->over_gsi);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530440}
441
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530442#ifdef FEATURE_METERING
443/**
444 * wlan_ipa_wdi_init_metering() - IPA WDI metering init
445 * @ipa_ctx: IPA context
446 * @in: IPA WDI in param
447 *
448 * Return: QDF_STATUS
449 */
450static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
451 qdf_ipa_wdi_init_in_params_t *in)
452{
453 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(in) =
454 wlan_ipa_wdi_meter_notifier_cb;
455}
456#else
457static inline void wlan_ipa_wdi_init_metering(struct wlan_ipa_priv *ipa_ctxt,
458 qdf_ipa_wdi_init_in_params_t *in)
459{
460}
461#endif
462
463/**
464 * wlan_ipa_wdi_init() - IPA WDI init
465 * @ipa_ctx: IPA context
466 *
467 * Return: QDF_STATUS
468 */
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530469static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
470{
471 qdf_ipa_wdi_init_in_params_t in;
472 qdf_ipa_wdi_init_out_params_t out;
473 int ret;
474
475 ipa_ctx->uc_loaded = false;
476
Sravan Kumar Kairameab90a02018-10-03 17:24:57 +0530477 qdf_mem_zero(&in, sizeof(in));
478 qdf_mem_zero(&out, sizeof(out));
479
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530480 QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
481 QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +0530482 QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
483 wlan_ipa_wdi_init_metering(ipa_ctx, &in);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530484
485 ret = qdf_ipa_wdi_init(&in, &out);
486 if (ret) {
487 ipa_err("ipa_wdi_init failed with ret=%d", ret);
488 return QDF_STATUS_E_FAILURE;
489 }
490
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530491 ipa_ctx->over_gsi =
492 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
493 ipa_ctx->is_smmu_enabled =
494 QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
495 ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
496 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
497
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530498 if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
Dustin Brown7e761c72018-07-31 13:50:17 -0700499 ipa_debug("IPA uC READY");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530500 ipa_ctx->uc_loaded = true;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530501 } else {
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530502 ipa_info("IPA uc not ready");
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530503 return QDF_STATUS_E_BUSY;
504 }
505
506 return QDF_STATUS_SUCCESS;
507}
508
509static inline int wlan_ipa_wdi_cleanup(void)
510{
511 int ret;
512
513 ret = qdf_ipa_wdi_cleanup();
514 if (ret)
515 ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
516 return ret;
517}
518
519static inline int wlan_ipa_wdi_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
520 struct ipa_sys_connect_params *sys,
521 uint32_t *handle)
522{
523 return 0;
524}
525
526static inline int wlan_ipa_wdi_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
527 uint32_t handle)
528{
529 return 0;
530}
531
Yun Parke74e6092018-04-27 11:36:34 -0700532/**
533 * wlan_ipa_pm_flush() - flush queued packets
534 * @work: pointer to the scheduled work
535 *
536 * Called during PM resume to send packets to TL which were queued
537 * while host was in the process of suspending.
538 *
539 * Return: None
540 */
541static void wlan_ipa_pm_flush(void *data)
542{
543 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
544 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
545 qdf_nbuf_t skb;
546 uint32_t dequeued = 0;
547
548 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
549 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
550 NULL)) {
551 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
552
553 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
554 dequeued++;
555
jiadab8cea02018-05-24 09:16:14 +0800556 if (pm_tx_cb->exception) {
557 if (ipa_ctx->softap_xmit &&
558 pm_tx_cb->iface_context->dev) {
559 ipa_ctx->softap_xmit(skb,
560 pm_tx_cb->iface_context->dev);
561 ipa_ctx->stats.num_tx_fwd_ok++;
562 } else {
563 dev_kfree_skb_any(skb);
564 }
565 } else {
566 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
567 pm_tx_cb->ipa_tx_desc);
568 }
Yun Parke74e6092018-04-27 11:36:34 -0700569
570 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
571 }
572 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
573
574 ipa_ctx->stats.num_tx_dequeued += dequeued;
575 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
576 ipa_ctx->stats.num_max_pm_queue = dequeued;
577}
578
jiadae9959f2018-05-08 11:19:07 +0800579int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
580{
581 if (!num_buf) {
582 ipa_info("No buffers to map/unmap");
583 return 0;
584 }
585
586 if (map)
587 return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
588 else
589 return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
590}
591
jiad90b17252019-03-25 15:22:42 +0800592static enum wlan_ipa_forward_type
593wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
594 struct wlan_ipa_iface_context *iface_ctx,
595 qdf_nbuf_t nbuf)
596{
597 uint8_t fw_desc = 0;
598 bool fwd_success;
599 int ret;
600
601 /* legacy intra-bss fowarding for WDI 1.0 and 2.0 */
602 if (ipa_ctx->wdi_version != IPA_WDI_3) {
603 fw_desc = (uint8_t)nbuf->cb[1];
604 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc,
605 nbuf);
606 }
607
608 if (cdp_ipa_rx_intrabss_fwd(ipa_ctx->dp_soc, iface_ctx->tl_context,
609 nbuf, &fwd_success)) {
610 ipa_ctx->ipa_rx_internal_drop_count++;
611 ipa_ctx->ipa_rx_discard++;
612
613 ret = WLAN_IPA_FORWARD_PKT_DISCARD;
614 } else {
615 ret = WLAN_IPA_FORWARD_PKT_LOCAL_STACK;
616 }
617
618 if (fwd_success)
619 ipa_ctx->stats.num_tx_fwd_ok++;
620 else
621 ipa_ctx->stats.num_tx_fwd_err++;
622
623 return ret;
624}
625
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530626#else /* CONFIG_IPA_WDI_UNIFIED_API */
627
628static inline void wlan_ipa_wdi_get_wdi_version(struct wlan_ipa_priv *ipa_ctx)
629{
630}
631
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +0530632static inline int wlan_ipa_wdi_is_smmu_enabled(struct wlan_ipa_priv *ipa_ctx,
633 qdf_device_t osdev)
634{
635 return qdf_mem_smmu_s1_enabled(osdev);
636}
637
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530638static inline QDF_STATUS wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
639 qdf_device_t osdev)
640{
641 return cdp_ipa_setup(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
642 wlan_ipa_i2w_cb, wlan_ipa_w2i_cb,
643 wlan_ipa_wdi_meter_notifier_cb,
644 ipa_ctx->config->desc_size,
645 ipa_ctx, wlan_ipa_is_rm_enabled(ipa_ctx->config),
646 &ipa_ctx->tx_pipe_handle,
647 &ipa_ctx->rx_pipe_handle);
648}
649
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530650static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
651{
652 struct ipa_wdi_uc_ready_params uc_ready_param;
653
654 ipa_ctx->uc_loaded = false;
655 uc_ready_param.priv = (void *)ipa_ctx;
656 uc_ready_param.notify = wlan_ipa_uc_loaded_uc_cb;
657 if (qdf_ipa_uc_reg_rdyCB(&uc_ready_param)) {
658 ipa_info("UC Ready CB register fail");
659 return QDF_STATUS_E_FAILURE;
660 }
661
662 if (true == uc_ready_param.is_uC_ready) {
663 ipa_info("UC Ready");
664 ipa_ctx->uc_loaded = true;
665 } else {
666 return QDF_STATUS_E_BUSY;
667 }
668
669 return QDF_STATUS_SUCCESS;
670}
671
672static inline int wlan_ipa_wdi_cleanup(void)
673{
674 int ret;
675
676 ret = qdf_ipa_uc_dereg_rdyCB();
677 if (ret)
678 ipa_info("UC Ready CB deregister fail");
679 return ret;
680}
681
682static inline int wlan_ipa_wdi_setup_sys_pipe(
683 struct wlan_ipa_priv *ipa_ctx,
684 struct ipa_sys_connect_params *sys, uint32_t *handle)
685{
686 return qdf_ipa_setup_sys_pipe(sys, handle);
687}
688
689static inline int wlan_ipa_wdi_teardown_sys_pipe(
690 struct wlan_ipa_priv *ipa_ctx,
691 uint32_t handle)
692{
693 return qdf_ipa_teardown_sys_pipe(handle);
694}
695
Yun Parke74e6092018-04-27 11:36:34 -0700696/**
697 * wlan_ipa_pm_flush() - flush queued packets
698 * @work: pointer to the scheduled work
699 *
700 * Called during PM resume to send packets to TL which were queued
701 * while host was in the process of suspending.
702 *
703 * Return: None
704 */
705static void wlan_ipa_pm_flush(void *data)
706{
707 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
708 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
709 qdf_nbuf_t skb;
710 uint32_t dequeued = 0;
711
712 qdf_wake_lock_acquire(&ipa_ctx->wake_lock,
713 WIFI_POWER_EVENT_WAKELOCK_IPA);
714 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
715 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head)) !=
716 NULL)) {
717 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
718
719 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
720 dequeued++;
721
jiadab8cea02018-05-24 09:16:14 +0800722 if (pm_tx_cb->exception) {
723 if (ipa_ctx->softap_xmit &&
724 pm_tx_cb->iface_context->dev) {
725 ipa_ctx->softap_xmit(skb,
726 pm_tx_cb->iface_context->dev);
727 ipa_ctx->stats.num_tx_fwd_ok++;
728 } else {
729 dev_kfree_skb_any(skb);
730 }
731 } else {
732 wlan_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
733 pm_tx_cb->ipa_tx_desc);
734 }
Yun Parke74e6092018-04-27 11:36:34 -0700735
736 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
737 }
738 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
739 qdf_wake_lock_release(&ipa_ctx->wake_lock,
740 WIFI_POWER_EVENT_WAKELOCK_IPA);
741
742 ipa_ctx->stats.num_tx_dequeued += dequeued;
743 if (dequeued > ipa_ctx->stats.num_max_pm_queue)
744 ipa_ctx->stats.num_max_pm_queue = dequeued;
745}
746
jiadae9959f2018-05-08 11:19:07 +0800747int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
748{
749 if (!num_buf) {
750 ipa_info("No buffers to map/unmap");
751 return 0;
752 }
753
754 if (map)
755 return qdf_ipa_create_wdi_mapping(num_buf, buf_arr);
756 else
757 return qdf_ipa_release_wdi_mapping(num_buf, buf_arr);
758}
759
jiad90b17252019-03-25 15:22:42 +0800760static enum wlan_ipa_forward_type
761wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
762 struct wlan_ipa_iface_context *iface_ctx,
763 qdf_nbuf_t nbuf)
764{
765 uint8_t fw_desc;
766
767 fw_desc = (uint8_t)nbuf->cb[1];
768
769 return wlan_ipa_intrabss_forward(ipa_ctx, iface_ctx, fw_desc, nbuf);
770}
771
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +0530772#endif /* CONFIG_IPA_WDI_UNIFIED_API */
773
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530774/**
775 * wlan_ipa_send_skb_to_network() - Send skb to kernel
776 * @skb: network buffer
777 * @iface_ctx: IPA interface context
778 *
779 * Called when a network buffer is received which should not be routed
780 * to the IPA module.
781 *
782 * Return: None
783 */
784static void
785wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
786 struct wlan_ipa_iface_context *iface_ctx)
787{
788 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
789
790 if (!iface_ctx->dev) {
jiadf3ecc752018-07-05 14:36:03 +0800791 ipa_debug_rl("Invalid interface");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530792 ipa_ctx->ipa_rx_internal_drop_count++;
jiadf3ecc752018-07-05 14:36:03 +0800793 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530794 return;
795 }
796
797 skb->destructor = wlan_ipa_uc_rt_debug_destructor;
798
799 if (ipa_ctx->send_to_nw)
800 ipa_ctx->send_to_nw(skb, iface_ctx->dev);
801
802 ipa_ctx->ipa_rx_net_send_count++;
803}
804
805/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530806 * __wlan_ipa_w2i_cb() - WLAN to IPA callback handler
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530807 * @priv: pointer to private data registered with IPA (we register a
808 * pointer to the global IPA context)
809 * @evt: the IPA event which triggered the callback
810 * @data: data associated with the event
811 *
812 * Return: None
813 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530814static void __wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
815 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530816{
817 struct wlan_ipa_priv *ipa_ctx = NULL;
818 qdf_nbuf_t skb;
819 uint8_t iface_id;
Mohit Khannacabf5e72018-07-24 13:28:43 -0700820 uint8_t session_id = 0xff;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530821 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530822
Sravan Kumar Kairam9cd68d02019-01-14 12:51:59 +0530823 ipa_ctx = (struct wlan_ipa_priv *)priv;
824 if (!ipa_ctx) {
825 if (evt == IPA_RECEIVE) {
826 skb = (qdf_nbuf_t)data;
827 dev_kfree_skb_any(skb);
828 }
jitiphilfdcaaba2018-09-03 16:19:52 +0530829 return;
830 }
831
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530832 switch (evt) {
833 case IPA_RECEIVE:
834 skb = (qdf_nbuf_t) data;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530835 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
836 session_id = (uint8_t)skb->cb[0];
837 iface_id = ipa_ctx->vdev_to_iface[session_id];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530838 } else {
839 iface_id = WLAN_IPA_GET_IFACE_ID(skb->data);
840 }
841 if (iface_id >= WLAN_IPA_MAX_IFACE) {
Mohit Khannacabf5e72018-07-24 13:28:43 -0700842 ipa_err_rl("Invalid iface_id: %u,session id: %x %x %x %x. Dropped!",
843 iface_id, session_id, (uint8_t)skb->cb[1],
844 (uint8_t)skb->cb[2], (uint8_t)skb->cb[3]);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530845 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800846 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530847 return;
848 }
849
850 iface_context = &ipa_ctx->iface_context[iface_id];
851 if (!iface_context->tl_context) {
jiadf3ecc752018-07-05 14:36:03 +0800852 ipa_err_rl("TL context of iface_id %u is NULL",
853 iface_id);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530854 ipa_ctx->ipa_rx_internal_drop_count++;
jiadab8cea02018-05-24 09:16:14 +0800855 dev_kfree_skb_any(skb);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530856 return;
857 }
858
859 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
860 ipa_ctx->stats.num_rx_excep++;
861 qdf_nbuf_pull_head(skb, WLAN_IPA_UC_WLAN_CLD_HDR_LEN);
862 } else {
863 qdf_nbuf_pull_head(skb, WLAN_IPA_WLAN_CLD_HDR_LEN);
864 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530865 iface_context->stats.num_rx_ipa_excep++;
866
867 /* Disable to forward Intra-BSS Rx packets when
868 * ap_isolate=1 in hostapd.conf
869 */
870 if (!ipa_ctx->ap_intrabss_fwd) {
871 /*
872 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
873 * all Rx packets to IPA uC, which need to be forwarded
874 * to other interface.
875 * And, IPA driver will send back to WLAN host driver
876 * through exception pipe with fw_desc field set by FW.
877 * Here we are checking fw_desc field for FORWARD bit
878 * set, and forward to Tx. Then copy to kernel stack
879 * only when DISCARD bit is not set.
880 */
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530881 if (WLAN_IPA_FORWARD_PKT_DISCARD ==
jiad90b17252019-03-25 15:22:42 +0800882 wlan_ipa_rx_intrabss_fwd(ipa_ctx, iface_context,
883 skb))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530884 break;
885 } else {
jiadf3ecc752018-07-05 14:36:03 +0800886 ipa_debug_rl("Intra-BSS forwarding is disabled");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530887 }
888
889 wlan_ipa_send_skb_to_network(skb, iface_context);
890 break;
891
892 default:
jiadf3ecc752018-07-05 14:36:03 +0800893 ipa_err_rl("w2i cb wrong event: 0x%x", evt);
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530894 return;
895 }
896}
897
898/**
jitiphilfdcaaba2018-09-03 16:19:52 +0530899 * wlan_ipa_w2i_cb() - SSR wrapper for __wlan_ipa_w2i_cb
900 * @priv: pointer to private data registered with IPA (we register a
901 * pointer to the global IPA context)
902 * @evt: the IPA event which triggered the callback
903 * @data: data associated with the event
904 *
905 * Return: None
906 */
907static void wlan_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
908 unsigned long data)
909{
Dustin Brown3fdaaf62019-03-18 14:00:16 -0700910 struct qdf_op_sync *op_sync;
911
912 if (qdf_op_protect(&op_sync)) {
913 if (evt == IPA_RECEIVE) {
914 struct wlan_ipa_priv *ipa_ctx = priv;
915 qdf_nbuf_t skb = (qdf_nbuf_t)data;
916
917 ipa_ctx->ipa_rx_internal_drop_count++;
918 dev_kfree_skb_any(skb);
919 }
920
921 return;
922 }
923
jitiphilfdcaaba2018-09-03 16:19:52 +0530924 __wlan_ipa_w2i_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -0700925
926 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +0530927}
928
929/**
930 * __wlan_ipa_i2w_cb() - IPA to WLAN callback
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530931 * @priv: pointer to private data registered with IPA (we register a
932 * pointer to the interface-specific IPA context)
933 * @evt: the IPA event which triggered the callback
934 * @data: data associated with the event
935 *
936 * Return: None
937 */
jitiphilfdcaaba2018-09-03 16:19:52 +0530938static void __wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
939 unsigned long data)
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530940{
941 struct wlan_ipa_priv *ipa_ctx = NULL;
942 qdf_ipa_rx_data_t *ipa_tx_desc;
943 struct wlan_ipa_iface_context *iface_context;
944 qdf_nbuf_t skb;
945 struct wlan_ipa_pm_tx_cb *pm_tx_cb = NULL;
946
947 iface_context = (struct wlan_ipa_iface_context *)priv;
948 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
949 ipa_ctx = iface_context->ipa_ctx;
950
951 if (evt != IPA_RECEIVE) {
jiadf3ecc752018-07-05 14:36:03 +0800952 ipa_err_rl("Event is not IPA_RECEIVE");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530953 ipa_free_skb(ipa_tx_desc);
954 iface_context->stats.num_tx_drop++;
955 return;
956 }
957
958 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
959
960 /*
961 * If PROD resource is not requested here then there may be cases where
962 * IPA hardware may be clocked down because of not having proper
963 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
964 * workaround to request PROD resource while data is going over CONS
965 * pipe to prevent the IPA hardware clockdown.
966 */
967 wlan_ipa_wdi_rm_request(ipa_ctx);
968
969 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
970 /*
971 * If host is still suspended then queue the packets and these will be
972 * drained later when resume completes. When packet is arrived here and
973 * host is suspended, this means that there is already resume is in
974 * progress.
975 */
976 if (ipa_ctx->suspended) {
hangtian127c9532019-01-12 13:29:07 +0800977 qdf_mem_zero(skb->cb, sizeof(skb->cb));
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +0530978 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
979 pm_tx_cb->iface_context = iface_context;
980 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
981 qdf_nbuf_queue_add(&ipa_ctx->pm_queue_head, skb);
982 ipa_ctx->stats.num_tx_queued++;
983
984 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
985 return;
986 }
987
988 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
989
990 /*
991 * If we are here means, host is not suspended, wait for the work queue
992 * to finish.
993 */
994 qdf_flush_work(&ipa_ctx->pm_work);
995
996 return wlan_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
997}
998
jitiphilfdcaaba2018-09-03 16:19:52 +0530999/**
1000 * wlan_ipa_i2w_cb() - IPA to WLAN callback
1001 * @priv: pointer to private data registered with IPA (we register a
1002 * pointer to the interface-specific IPA context)
1003 * @evt: the IPA event which triggered the callback
1004 * @data: data associated with the event
1005 *
1006 * Return: None
1007 */
1008static void wlan_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
1009 unsigned long data)
1010{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001011 struct qdf_op_sync *op_sync;
1012
1013 if (qdf_op_protect(&op_sync)) {
1014 qdf_ipa_rx_data_t *ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
1015 struct wlan_ipa_iface_context *iface_context = priv;
1016
1017 ipa_free_skb(ipa_tx_desc);
1018 iface_context->stats.num_tx_drop++;
1019
1020 return;
1021 }
1022
jitiphilfdcaaba2018-09-03 16:19:52 +05301023 __wlan_ipa_i2w_cb(priv, evt, data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07001024
1025 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05301026}
1027
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301028QDF_STATUS wlan_ipa_suspend(struct wlan_ipa_priv *ipa_ctx)
1029{
1030 /*
1031 * Check if IPA is ready for suspend, If we are here means, there is
1032 * high chance that suspend would go through but just to avoid any race
1033 * condition after suspend started, these checks are conducted before
1034 * allowing to suspend.
1035 */
1036 if (atomic_read(&ipa_ctx->tx_ref_cnt))
1037 return QDF_STATUS_E_AGAIN;
1038
Yun Parke74e6092018-04-27 11:36:34 -07001039 if (!wlan_ipa_is_rm_released(ipa_ctx))
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301040 return QDF_STATUS_E_AGAIN;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05301041
1042 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1043 ipa_ctx->suspended = true;
1044 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1045
1046 return QDF_STATUS_SUCCESS;
1047}
1048
1049QDF_STATUS wlan_ipa_resume(struct wlan_ipa_priv *ipa_ctx)
1050{
1051 qdf_sched_work(0, &ipa_ctx->pm_work);
1052
1053 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
1054 ipa_ctx->suspended = false;
1055 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
1056
1057 return QDF_STATUS_SUCCESS;
1058}
1059
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301060QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
1061{
1062 int result;
1063
1064 ipa_debug("enter");
1065
1066 if (!ipa_ctx->ipa_pipes_down) {
1067 /*
1068 * IPA WDI Pipes are already activated due to
1069 * rm deferred resources grant
1070 */
1071 ipa_warn("IPA WDI Pipes are already activated");
1072 goto end;
1073 }
1074
1075 result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
1076 ipa_ctx->dp_pdev);
1077 if (result) {
1078 ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
1079 return QDF_STATUS_E_FAILURE;
1080 }
1081
1082 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1083 ipa_ctx->ipa_pipes_down = false;
1084
1085 cdp_ipa_enable_autonomy(ipa_ctx->dp_soc,
1086 ipa_ctx->dp_pdev);
1087
1088end:
1089 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1090
1091 return QDF_STATUS_SUCCESS;
1092}
1093
1094QDF_STATUS wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx)
1095{
1096 int result;
1097
1098 ipa_debug("enter");
1099
1100 if (ipa_ctx->ipa_pipes_down) {
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301101 ipa_warn("IPA WDI Pipes are already deactivated");
1102 goto end;
1103 }
1104
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301105 qdf_spin_lock_bh(&ipa_ctx->pipes_down_lock);
1106 if (ipa_ctx->pipes_down_in_progress || ipa_ctx->ipa_pipes_down) {
1107 ipa_warn("IPA WDI Pipes down already in progress");
1108 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1109 return QDF_STATUS_E_ALREADY;
1110 }
1111 ipa_ctx->pipes_down_in_progress = true;
1112 qdf_spin_unlock_bh(&ipa_ctx->pipes_down_lock);
1113
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301114 cdp_ipa_disable_autonomy(ipa_ctx->dp_soc,
1115 ipa_ctx->dp_pdev);
1116
1117 result = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
1118 ipa_ctx->dp_pdev);
1119 if (result) {
1120 ipa_err("Disable IPA WDI PIPE failed: ret=%d", result);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301121 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301122 return QDF_STATUS_E_FAILURE;
1123 }
1124
1125 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05301126 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05301127
1128end:
1129 ipa_debug("exit: ipa_pipes_down=%d", ipa_ctx->ipa_pipes_down);
1130
1131 return QDF_STATUS_SUCCESS;
1132}
1133
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05301134/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301135 * wlan_ipa_uc_find_add_assoc_sta() - Find associated station
1136 * @ipa_ctx: Global IPA IPA context
1137 * @sta_add: Should station be added
1138 * @sta_id: ID of the station being queried
1139 *
1140 * Return: true if the station was found
1141 */
1142static bool wlan_ipa_uc_find_add_assoc_sta(struct wlan_ipa_priv *ipa_ctx,
1143 bool sta_add, uint8_t sta_id,
1144 uint8_t *mac_addr)
1145{
1146 bool sta_found = false;
1147 uint8_t idx;
1148
1149 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1150 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1151 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1152 sta_found = true;
1153 break;
1154 }
1155 }
1156 if (sta_add && sta_found) {
1157 ipa_err("STA ID %d already exist, cannot add", sta_id);
1158 return sta_found;
1159 }
1160 if (sta_add) {
1161 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1162 if (!ipa_ctx->assoc_stas_map[idx].is_reserved) {
1163 ipa_ctx->assoc_stas_map[idx].is_reserved = true;
1164 ipa_ctx->assoc_stas_map[idx].sta_id = sta_id;
1165 qdf_mem_copy(&ipa_ctx->assoc_stas_map[idx].
1166 mac_addr, mac_addr,
1167 QDF_NET_ETH_LEN);
1168 return sta_found;
1169 }
1170 }
1171 }
1172 if (!sta_add && !sta_found) {
1173 ipa_err("STA ID %d does not exist, cannot delete", sta_id);
1174 return sta_found;
1175 }
1176 if (!sta_add) {
1177 for (idx = 0; idx < WLAN_IPA_MAX_STA_COUNT; idx++) {
1178 if ((ipa_ctx->assoc_stas_map[idx].is_reserved) &&
1179 (ipa_ctx->assoc_stas_map[idx].sta_id == sta_id)) {
1180 ipa_ctx->assoc_stas_map[idx].is_reserved =
1181 false;
1182 ipa_ctx->assoc_stas_map[idx].sta_id = 0xFF;
hangtian127c9532019-01-12 13:29:07 +08001183 qdf_mem_zero(
1184 &ipa_ctx->assoc_stas_map[idx].mac_addr,
1185 QDF_NET_ETH_LEN);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301186 return sta_found;
1187 }
1188 }
1189 }
1190
1191 return sta_found;
1192}
1193
1194/**
1195 * wlan_ipa_get_ifaceid() - Get IPA context interface ID
1196 * @ipa_ctx: IPA context
1197 * @session_id: Session ID
1198 *
1199 * Return: None
1200 */
1201static int wlan_ipa_get_ifaceid(struct wlan_ipa_priv *ipa_ctx,
1202 uint8_t session_id)
1203{
1204 struct wlan_ipa_iface_context *iface_ctx;
1205 int i;
1206
1207 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1208 iface_ctx = &ipa_ctx->iface_context[i];
1209 if (iface_ctx->session_id == session_id)
1210 break;
1211 }
1212
1213 return i;
1214}
1215
1216/**
1217 * wlan_ipa_cleanup_iface() - Cleanup IPA on a given interface
1218 * @iface_context: interface-specific IPA context
1219 *
1220 * Return: None
1221 */
1222static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context)
1223{
1224 struct wlan_ipa_priv *ipa_ctx = iface_context->ipa_ctx;
1225
1226 ipa_debug("enter");
1227
1228 if (!iface_context->tl_context)
1229 return;
1230
1231 cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
1232 iface_context->dev->name,
1233 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1234
1235 qdf_spin_lock_bh(&iface_context->interface_lock);
1236 iface_context->tl_context = NULL;
1237 iface_context->dev = NULL;
1238 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
1239 iface_context->session_id = WLAN_IPA_MAX_SESSION;
1240 iface_context->sta_id = WLAN_IPA_MAX_STA_COUNT;
1241 qdf_spin_unlock_bh(&iface_context->interface_lock);
1242 iface_context->ifa_address = 0;
1243 if (!iface_context->ipa_ctx->num_iface) {
1244 ipa_err("NUM INTF 0, Invalid");
1245 QDF_ASSERT(0);
1246 }
1247 iface_context->ipa_ctx->num_iface--;
1248 ipa_debug("exit: num_iface=%d", iface_context->ipa_ctx->num_iface);
1249}
1250
1251/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301252 * wlan_ipa_nbuf_cb() - IPA TX complete callback
1253 * @skb: packet buffer which was transmitted
1254 *
1255 * Return: None
1256 */
1257static void wlan_ipa_nbuf_cb(qdf_nbuf_t skb)
1258{
1259 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1260 qdf_ipa_rx_data_t *ipa_tx_desc;
1261 struct wlan_ipa_tx_desc *tx_desc;
1262 uint16_t id;
1263
1264 if (!qdf_nbuf_ipa_owned_get(skb)) {
1265 dev_kfree_skb_any(skb);
1266 return;
1267 }
1268
1269 /* Get Tx desc pointer from SKB CB */
1270 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
1271 tx_desc = &ipa_ctx->tx_desc_pool[id];
1272 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
1273
1274 /* Return Tx Desc to IPA */
1275 qdf_ipa_free_skb(ipa_tx_desc);
1276
1277 /* Return to free tx desc list */
1278 qdf_spin_lock_bh(&ipa_ctx->q_lock);
1279 tx_desc->ipa_tx_desc_ptr = NULL;
1280 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list, &tx_desc->node);
1281 ipa_ctx->stats.num_tx_desc_q_cnt--;
1282 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
1283
1284 ipa_ctx->stats.num_tx_comp_cnt++;
1285
1286 qdf_atomic_dec(&ipa_ctx->tx_ref_cnt);
1287
1288 wlan_ipa_wdi_rm_try_release(ipa_ctx);
1289}
1290
1291/**
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301292 * wlan_ipa_setup_iface() - Setup IPA on a given interface
1293 * @ipa_ctx: IPA IPA global context
1294 * @net_dev: Interface net device
1295 * @device_mode: Net interface device mode
1296 * @adapter: Interface upon which IPA is being setup
1297 * @sta_id: Station ID of the API instance
1298 * @session_id: Station ID of the API instance
1299 *
1300 * Return: QDF STATUS
1301 */
1302static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
1303 qdf_netdev_t net_dev,
1304 uint8_t device_mode, uint8_t sta_id,
1305 uint8_t session_id)
1306{
1307 struct wlan_ipa_iface_context *iface_context = NULL;
1308 void *tl_context = NULL;
1309 int i;
1310 QDF_STATUS status;
1311
1312 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
1313 * channel change indication. Since these indications are sent by lower
1314 * layer as SAP updates and IPA doesn't have to do anything for these
1315 * updates so ignoring!
1316 */
1317 if (device_mode == QDF_SAP_MODE) {
1318 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1319 iface_context = &(ipa_ctx->iface_context[i]);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001320 if (iface_context->dev == net_dev) {
1321 ipa_debug("found iface %u device_mode %u",
1322 i, device_mode);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301323 return QDF_STATUS_SUCCESS;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001324 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301325 }
1326 }
1327
Yun Park21ec4902018-04-24 12:11:01 -07001328 if (WLAN_IPA_MAX_IFACE == ipa_ctx->num_iface) {
1329 ipa_err("Max interface reached %d", WLAN_IPA_MAX_IFACE);
1330 status = QDF_STATUS_E_NOMEM;
1331 QDF_ASSERT(0);
1332 goto end;
1333 }
1334
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301335 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001336 if (!ipa_ctx->iface_context[i].tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301337 iface_context = &(ipa_ctx->iface_context[i]);
1338 break;
1339 }
1340 }
1341
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001342 if (!iface_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301343 ipa_err("All the IPA interfaces are in use");
1344 status = QDF_STATUS_E_NOMEM;
Yun Park21ec4902018-04-24 12:11:01 -07001345 QDF_ASSERT(0);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301346 goto end;
1347 }
1348
1349 iface_context->sta_id = sta_id;
1350 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(ipa_ctx->dp_soc,
1351 ipa_ctx->dp_pdev,
1352 sta_id);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001353 if (!tl_context) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301354 ipa_err("Not able to get TL context sta_id: %d", sta_id);
1355 status = QDF_STATUS_E_INVAL;
1356 goto end;
1357 }
1358
1359 iface_context->tl_context = tl_context;
1360 iface_context->dev = net_dev;
1361 iface_context->device_mode = device_mode;
1362 iface_context->session_id = session_id;
1363
1364 status = cdp_ipa_setup_iface(ipa_ctx->dp_soc, net_dev->name,
1365 net_dev->dev_addr,
1366 iface_context->prod_client,
1367 iface_context->cons_client,
1368 session_id,
1369 wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
1370 if (status != QDF_STATUS_SUCCESS)
1371 goto end;
1372
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05301373 /* Register IPA Tx desc free callback */
1374 qdf_nbuf_reg_free_cb(wlan_ipa_nbuf_cb);
1375
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301376 ipa_ctx->num_iface++;
1377
1378 ipa_debug("exit: num_iface=%d", ipa_ctx->num_iface);
1379
1380 return status;
1381
1382end:
1383 if (iface_context)
1384 wlan_ipa_cleanup_iface(iface_context);
1385
1386 return status;
1387}
1388
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301389#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390)
1390/**
1391 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1392 * @ipa_ctx: IPA context
1393 *
1394 * Return: QDF STATUS
1395 */
1396static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1397{
1398 ipa_debug("enter");
1399
1400 if (wlan_ipa_uc_enable_pipes(ipa_ctx) != QDF_STATUS_SUCCESS) {
1401 ipa_err("IPA WDI Pipe activation failed");
1402 return QDF_STATUS_E_BUSY;
1403 }
1404
1405 ipa_debug("exit");
1406
1407 return QDF_STATUS_SUCCESS;
1408}
1409
1410/**
1411 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1412 * @ipa_ctx: IPA context
1413 *
1414 * Return: None
1415 */
1416static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1417{
1418 ipa_debug("enter");
1419
1420 wlan_ipa_uc_disable_pipes(ipa_ctx);
1421
1422 ipa_debug("exit: IPA WDI Pipes deactivated");
1423}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301424
1425bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1426{
1427 return !ipa_ctx->ipa_pipes_down;
1428}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301429#else
1430
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301431/**
1432 * wlan_ipa_uc_handle_first_con() - Handle first uC IPA connection
1433 * @ipa_ctx: IPA context
1434 *
1435 * Return: QDF STATUS
1436 */
1437static QDF_STATUS wlan_ipa_uc_handle_first_con(struct wlan_ipa_priv *ipa_ctx)
1438{
1439 ipa_debug("enter");
1440
1441 ipa_ctx->activated_fw_pipe = 0;
1442 ipa_ctx->resource_loading = true;
1443
1444 /* If RM feature enabled
1445 * Request PROD Resource first
1446 * PROD resource may return sync or async manners
1447 */
1448 if (wlan_ipa_is_rm_enabled(ipa_ctx->config)) {
Yun Parke114fbf2018-04-05 20:02:12 -07001449 if (!wlan_ipa_wdi_rm_request_resource(ipa_ctx,
1450 IPA_RM_RESOURCE_WLAN_PROD)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301451 /* RM PROD request sync return
1452 * enable pipe immediately
1453 */
1454 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1455 ipa_err("IPA WDI Pipe activation failed");
1456 ipa_ctx->resource_loading = false;
1457 return QDF_STATUS_E_BUSY;
1458 }
1459 } else {
1460 ipa_err("IPA WDI Pipe activation deferred");
1461 }
1462 } else {
1463 /* RM Disabled
1464 * Just enabled all the PIPEs
1465 */
1466 if (wlan_ipa_uc_enable_pipes(ipa_ctx)) {
1467 ipa_err("IPA WDI Pipe activation failed");
1468 ipa_ctx->resource_loading = false;
1469 return QDF_STATUS_E_BUSY;
1470 }
1471 ipa_ctx->resource_loading = false;
1472 }
1473
1474 ipa_debug("exit");
1475
1476 return QDF_STATUS_SUCCESS;
1477}
1478
1479/**
1480 * wlan_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
1481 * @ipa_ctx: IPA context
1482 *
1483 * Return: None
1484 */
1485static void wlan_ipa_uc_handle_last_discon(struct wlan_ipa_priv *ipa_ctx)
1486{
1487 ipa_debug("enter");
1488
1489 ipa_ctx->resource_unloading = true;
1490 qdf_event_reset(&ipa_ctx->ipa_resource_comp);
1491 ipa_info("Disable FW RX PIPE");
1492 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev, false, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301493
1494 ipa_debug("exit: IPA WDI Pipes deactivated");
1495}
Sravan Kumar Kairam78870222018-12-31 12:47:17 +05301496
1497bool wlan_ipa_is_fw_wdi_activated(struct wlan_ipa_priv *ipa_ctx)
1498{
1499 return (WLAN_IPA_UC_NUM_WDI_PIPE == ipa_ctx->activated_fw_pipe);
1500}
Sravan Kumar Kairam361f4102018-12-17 18:47:04 +05301501#endif
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301502
1503/**
1504 * wlan_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
1505 * @ipa_ctx: global IPA context
1506 * @offload_type: MCC or SCC
1507 * @session_id: Session Id
1508 * @enable: TX offload enable or disable
1509 *
1510 * Return: none
1511 */
1512static void wlan_ipa_uc_offload_enable_disable(struct wlan_ipa_priv *ipa_ctx,
1513 uint32_t offload_type,
1514 uint8_t session_id,
1515 bool enable)
1516{
1517
1518 struct ipa_uc_offload_control_params req = {0};
1519
1520 if (session_id >= WLAN_IPA_MAX_SESSION) {
1521 ipa_err("invalid session id: %d", session_id);
1522 return;
1523 }
1524
1525 if (enable == ipa_ctx->vdev_offload_enabled[session_id]) {
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301526 ipa_info("IPA offload status is already set");
1527 ipa_info("offload_type=%d, vdev_id=%d, enable=%d",
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301528 offload_type, session_id, enable);
1529 return;
1530 }
1531
1532 ipa_info("offload_type=%d, session_id=%d, enable=%d",
1533 offload_type, session_id, enable);
1534
1535 req.offload_type = offload_type;
1536 req.vdev_id = session_id;
1537 req.enable = enable;
1538
1539 if (QDF_STATUS_SUCCESS !=
1540 ipa_send_uc_offload_enable_disable(ipa_ctx->pdev, &req)) {
1541 ipa_err("Fail to enable IPA offload");
1542 ipa_err("offload type=%d, vdev_id=%d, enable=%d",
1543 offload_type, session_id, enable);
1544 } else {
1545 ipa_ctx->vdev_offload_enabled[session_id] = enable;
1546 }
1547}
1548
1549/**
1550 * __wlan_ipa_wlan_evt() - IPA event handler
1551 * @net_dev: Interface net device
1552 * @device_mode: Net interface device mode
1553 * @sta_id: station id for the event
1554 * @session_id: session id for the event
1555 * @type: event enum of type ipa_wlan_event
1556 * @mac_address: MAC address associated with the event
1557 *
1558 * This function is meant to be called from within wlan_ipa_ctx.c
1559 *
1560 * Return: QDF STATUS
1561 */
1562static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
1563 uint8_t sta_id, uint8_t session_id,
1564 qdf_ipa_wlan_event type,
1565 uint8_t *mac_addr)
1566{
1567 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
1568 struct wlan_ipa_iface_context *iface_ctx = NULL;
1569 qdf_ipa_msg_meta_t meta;
1570 qdf_ipa_wlan_msg_t *msg;
1571 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
1572 int i;
1573 QDF_STATUS status;
Ryan Hsub5783cf2018-05-14 12:13:15 -07001574 uint8_t sta_session_id = WLAN_IPA_MAX_SESSION;
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301575 struct wlan_objmgr_pdev *pdev;
1576 struct wlan_objmgr_psoc *psoc;
1577 struct wlan_objmgr_vdev *vdev;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301578
Mohit Khannacabf5e72018-07-24 13:28:43 -07001579 ipa_debug("%s: EVT: %d, MAC: %pM, sta_id: %d session_id: %u",
1580 net_dev->name, type, mac_addr, sta_id, session_id);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301581
1582 if (type >= QDF_IPA_WLAN_EVENT_MAX)
1583 return QDF_STATUS_E_INVAL;
1584
1585 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1586 !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1587 (device_mode != QDF_SAP_MODE)) {
1588 return QDF_STATUS_SUCCESS;
1589 }
1590
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301591 pdev = ipa_ctx->pdev;
1592 psoc = wlan_pdev_get_psoc(pdev);
1593 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
1594 WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301595 QDF_BUG(session_id < WLAN_IPA_MAX_SESSION);
1596
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301597 if (vdev)
1598 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Rakshith Suresh Patkar80094432019-04-15 18:15:07 +05301599 else
1600 ipa_err("vdev is NULL, session_id: %u", session_id);
Rakshith Suresh Patkar107a6592019-02-08 16:17:27 +05301601
Ryan Hsub5783cf2018-05-14 12:13:15 -07001602 if (ipa_ctx->sta_connected) {
1603 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1604 if (iface_ctx)
1605 sta_session_id = iface_ctx->session_id;
1606 else
1607 ipa_err("sta iface_ctx is NULL");
1608 }
1609
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301610 /*
1611 * During IPA UC resource loading/unloading new events can be issued.
1612 */
1613 if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
1614 (ipa_ctx->resource_loading || ipa_ctx->resource_unloading)) {
1615 unsigned int pending_event_count;
1616 struct wlan_ipa_uc_pending_event *pending_event = NULL;
1617
1618 ipa_info("Event:%d IPA resource %s inprogress", type,
1619 ipa_ctx->resource_loading ?
1620 "load" : "unload");
1621
1622 /* Wait until completion of the long/unloading */
1623 status = qdf_wait_for_event_completion(
1624 &ipa_ctx->ipa_resource_comp,
jiada8c542c2018-05-29 16:24:13 +08001625 IPA_RESOURCE_COMP_WAIT_TIME);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301626 if (status != QDF_STATUS_SUCCESS) {
1627 /*
1628 * If timed out, store the events separately and
1629 * handle them later.
1630 */
1631 ipa_info("IPA resource %s timed out",
1632 ipa_ctx->resource_loading ?
1633 "load" : "unload");
1634
Sravan Kumar Kairamcd430b62018-08-23 18:35:50 +05301635 if (type == QDF_IPA_AP_DISCONNECT)
1636 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1637 SIR_AP_RX_DATA_OFFLOAD,
1638 session_id, false);
1639
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301640 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
1641
1642 pending_event_count =
1643 qdf_list_size(&ipa_ctx->pending_event);
1644 if (pending_event_count >=
1645 WLAN_IPA_MAX_PENDING_EVENT_COUNT) {
1646 ipa_info("Reached max pending evt count");
1647 qdf_list_remove_front(
1648 &ipa_ctx->pending_event,
1649 (qdf_list_node_t **)&pending_event);
1650 } else {
1651 pending_event =
1652 (struct wlan_ipa_uc_pending_event *)
1653 qdf_mem_malloc(sizeof(
1654 struct wlan_ipa_uc_pending_event));
1655 }
1656
1657 if (!pending_event) {
1658 ipa_err("Pending event memory alloc fail");
1659 qdf_mutex_release(&ipa_ctx->ipa_lock);
1660 return QDF_STATUS_E_NOMEM;
1661 }
1662
1663 pending_event->net_dev = net_dev;
1664 pending_event->device_mode = device_mode;
1665 pending_event->sta_id = sta_id;
1666 pending_event->session_id = session_id;
1667 pending_event->type = type;
1668 pending_event->is_loading = ipa_ctx->resource_loading;
1669 qdf_mem_copy(pending_event->mac_addr,
1670 mac_addr, QDF_MAC_ADDR_SIZE);
1671 qdf_list_insert_back(&ipa_ctx->pending_event,
1672 &pending_event->node);
1673
1674 qdf_mutex_release(&ipa_ctx->ipa_lock);
1675
Yun Park21ec4902018-04-24 12:11:01 -07001676 /* Cleanup interface */
1677 if (type == QDF_IPA_STA_DISCONNECT ||
1678 type == QDF_IPA_AP_DISCONNECT) {
1679 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1680 iface_ctx = &ipa_ctx->iface_context[i];
1681
1682 if (iface_ctx->dev == net_dev)
1683 break;
1684 }
1685 if (iface_ctx)
1686 wlan_ipa_cleanup_iface(iface_ctx);
1687 }
1688
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301689 return QDF_STATUS_SUCCESS;
1690 }
1691 ipa_info("IPA resource %s completed",
1692 ipa_ctx->resource_loading ?
1693 "load" : "unload");
1694 }
1695
1696 ipa_ctx->stats.event[type]++;
1697
1698 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1699 switch (type) {
1700 case QDF_IPA_STA_CONNECT:
1701 qdf_mutex_acquire(&ipa_ctx->event_lock);
1702
1703 /* STA already connected and without disconnect, connect again
1704 * This is Roaming scenario
1705 */
1706 if (ipa_ctx->sta_connected) {
1707 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1708 if (iface_ctx)
1709 wlan_ipa_cleanup_iface(iface_ctx);
1710 }
1711
1712 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1713 sta_id, session_id);
1714 if (status != QDF_STATUS_SUCCESS) {
Mohit Khannacabf5e72018-07-24 13:28:43 -07001715 ipa_err("wlan_ipa_setup_iface failed %u", status);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301716 qdf_mutex_release(&ipa_ctx->event_lock);
1717 goto end;
1718 }
1719
1720 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1721 (ipa_ctx->sap_num_connected_sta > 0) &&
1722 !ipa_ctx->sta_connected) {
1723 qdf_mutex_release(&ipa_ctx->event_lock);
1724 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1725 SIR_STA_RX_DATA_OFFLOAD, session_id,
1726 true);
1727 qdf_mutex_acquire(&ipa_ctx->event_lock);
1728 }
1729
1730 ipa_ctx->vdev_to_iface[session_id] =
1731 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
1732
1733 ipa_ctx->sta_connected = 1;
1734
1735 qdf_mutex_release(&ipa_ctx->event_lock);
1736
Mohit Khannacabf5e72018-07-24 13:28:43 -07001737 ipa_debug("sta_connected=%d vdev_to_iface[%u] %u",
1738 ipa_ctx->sta_connected,
1739 session_id,
1740 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301741 break;
1742
1743 case QDF_IPA_AP_CONNECT:
1744 qdf_mutex_acquire(&ipa_ctx->event_lock);
1745
1746 /* For DFS channel we get two start_bss event (before and after
1747 * CAC). Also when ACS range includes both DFS and non DFS
1748 * channels, we could possibly change channel many times due to
1749 * RADAR detection and chosen channel may not be a DFS channels.
1750 * So dont return error here. Just discard the event.
1751 */
jiadc908ada2018-05-11 14:40:54 +08001752 if (ipa_ctx->vdev_to_iface[session_id] !=
1753 WLAN_IPA_MAX_SESSION) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301754 qdf_mutex_release(&ipa_ctx->event_lock);
1755 return 0;
1756 }
1757
1758 status = wlan_ipa_setup_iface(ipa_ctx, net_dev, device_mode,
1759 sta_id, session_id);
1760 if (status != QDF_STATUS_SUCCESS) {
1761 qdf_mutex_release(&ipa_ctx->event_lock);
1762 ipa_err("%s: Evt: %d, Interface setup failed",
1763 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
1764 goto end;
1765 }
1766
1767 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1768 qdf_mutex_release(&ipa_ctx->event_lock);
1769 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1770 SIR_AP_RX_DATA_OFFLOAD, session_id, true);
1771 qdf_mutex_acquire(&ipa_ctx->event_lock);
1772 }
1773
1774 ipa_ctx->vdev_to_iface[session_id] =
1775 wlan_ipa_get_ifaceid(ipa_ctx, session_id);
Mohit Khannacabf5e72018-07-24 13:28:43 -07001776 ipa_debug("vdev_to_iface[%u]=%u",
1777 session_id,
1778 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301779 qdf_mutex_release(&ipa_ctx->event_lock);
1780 break;
1781
1782 case QDF_IPA_STA_DISCONNECT:
1783 qdf_mutex_acquire(&ipa_ctx->event_lock);
1784
1785 if (!ipa_ctx->sta_connected) {
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301786 struct wlan_ipa_iface_context *iface;
1787
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301788 qdf_mutex_release(&ipa_ctx->event_lock);
1789 ipa_err("%s: Evt: %d, STA already disconnected",
1790 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Sravan Kumar Kairam47578192019-01-14 17:13:09 +05301791
1792 iface = wlan_ipa_get_iface(ipa_ctx, QDF_STA_MODE);
1793 if (iface && (iface->dev == net_dev))
1794 wlan_ipa_cleanup_iface(iface);
1795
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301796 return QDF_STATUS_E_INVAL;
1797 }
1798
1799 ipa_ctx->sta_connected = 0;
1800
1801 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1802 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1803 msg_ex->name);
1804 } else {
1805 /* Disable IPA UC TX PIPE when STA disconnected */
1806 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001807 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001808 !ipa_ctx->ipa_pipes_down &&
1809 (ipa_ctx->resource_unloading == false)) {
jiad3a321f32018-07-16 18:16:39 +08001810 if (cds_is_driver_unloading()) {
1811 /*
1812 * We disable WDI pipes directly here
1813 * since IPA_OPCODE_TX/RX_SUSPEND
1814 * message will not be processed when
1815 * unloading WLAN driver is in progress
1816 */
1817 wlan_ipa_uc_disable_pipes(ipa_ctx);
1818 } else {
1819 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1820 }
1821 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301822 }
1823
1824 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1825 (ipa_ctx->sap_num_connected_sta > 0)) {
1826 qdf_mutex_release(&ipa_ctx->event_lock);
1827 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1828 SIR_STA_RX_DATA_OFFLOAD, session_id, false);
1829 qdf_mutex_acquire(&ipa_ctx->event_lock);
1830 ipa_ctx->vdev_to_iface[session_id] =
1831 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001832 ipa_debug("vdev_to_iface[%u]=%u",
1833 session_id,
1834 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301835 }
1836
1837 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1838 iface_ctx = &ipa_ctx->iface_context[i];
1839
1840 if (iface_ctx->dev == net_dev)
1841 break;
1842 }
1843 if (i < WLAN_IPA_MAX_IFACE)
1844 wlan_ipa_cleanup_iface(iface_ctx);
1845
1846 qdf_mutex_release(&ipa_ctx->event_lock);
1847
1848 ipa_debug("sta_connected=%d", ipa_ctx->sta_connected);
1849 break;
1850
1851 case QDF_IPA_AP_DISCONNECT:
1852 qdf_mutex_acquire(&ipa_ctx->event_lock);
1853
1854 if ((ipa_ctx->num_iface == 1) &&
Yun Parka29974a2018-04-09 12:05:49 -07001855 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
jiadfa131fe2018-08-06 13:41:36 +08001856 !ipa_ctx->ipa_pipes_down &&
1857 (ipa_ctx->resource_unloading == false)) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301858 if (cds_is_driver_unloading()) {
1859 /*
1860 * We disable WDI pipes directly here since
1861 * IPA_OPCODE_TX/RX_SUSPEND message will not be
1862 * processed when unloading WLAN driver is in
1863 * progress
1864 */
1865 wlan_ipa_uc_disable_pipes(ipa_ctx);
1866 } else {
1867 /*
1868 * This shouldn't happen :
1869 * No interface left but WDI pipes are still
1870 * active - force close WDI pipes
1871 */
1872 ipa_err("No interface left but WDI pipes are still active");
1873 wlan_ipa_uc_handle_last_discon(ipa_ctx);
1874 }
1875 }
1876
1877 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1878 qdf_mutex_release(&ipa_ctx->event_lock);
1879 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1880 SIR_AP_RX_DATA_OFFLOAD, session_id, false);
1881 qdf_mutex_acquire(&ipa_ctx->event_lock);
1882 ipa_ctx->vdev_to_iface[session_id] =
1883 WLAN_IPA_MAX_SESSION;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001884 ipa_debug("vdev_to_iface[%u]=%u",
1885 session_id,
1886 ipa_ctx->vdev_to_iface[session_id]);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301887 }
1888
1889 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
1890 iface_ctx = &ipa_ctx->iface_context[i];
1891
1892 if (iface_ctx->dev == net_dev)
1893 break;
1894 }
1895 if (i < WLAN_IPA_MAX_IFACE)
1896 wlan_ipa_cleanup_iface(iface_ctx);
1897
1898 qdf_mutex_release(&ipa_ctx->event_lock);
1899 break;
1900
1901 case QDF_IPA_CLIENT_CONNECT_EX:
1902 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1903 ipa_debug("%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
1904 net_dev->name, type);
1905 return QDF_STATUS_SUCCESS;
1906 }
1907
1908 qdf_mutex_acquire(&ipa_ctx->event_lock);
1909 if (wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, true, sta_id,
1910 mac_addr)) {
1911 qdf_mutex_release(&ipa_ctx->event_lock);
1912 ipa_err("%s: STA ID %d found", net_dev->name, sta_id);
1913 return QDF_STATUS_SUCCESS;
1914 }
1915
1916 /* Enable IPA UC Data PIPEs when first STA connected */
1917 if (ipa_ctx->sap_num_connected_sta == 0 &&
1918 ipa_ctx->uc_loaded == true) {
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301919
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301920 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
1921 ipa_ctx->sta_connected) {
1922 qdf_mutex_release(&ipa_ctx->event_lock);
1923 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
1924 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301925 sta_session_id, true);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301926 qdf_mutex_acquire(&ipa_ctx->event_lock);
1927 }
1928
1929 status = wlan_ipa_uc_handle_first_con(ipa_ctx);
1930 if (status != QDF_STATUS_SUCCESS) {
1931 ipa_info("%s: handle 1st con fail",
1932 net_dev->name);
1933
1934 if (wlan_ipa_uc_sta_is_enabled(
1935 ipa_ctx->config) &&
1936 ipa_ctx->sta_connected) {
1937 qdf_mutex_release(&ipa_ctx->event_lock);
1938 wlan_ipa_uc_offload_enable_disable(
1939 ipa_ctx,
1940 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05301941 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301942 } else {
1943 qdf_mutex_release(&ipa_ctx->event_lock);
1944 }
1945
1946 return status;
Mohit Khannacabf5e72018-07-24 13:28:43 -07001947 } else
1948 ipa_debug("%s: handle 1st con success",
1949 net_dev->name);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301950 }
1951
1952 ipa_ctx->sap_num_connected_sta++;
1953
1954 qdf_mutex_release(&ipa_ctx->event_lock);
1955
1956 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
1957 QDF_IPA_MSG_META_MSG_LEN(&meta) =
1958 (sizeof(qdf_ipa_wlan_msg_ex_t) +
1959 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
1960 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
1961
Jeff Johnson1d44fee52019-03-18 14:02:06 -07001962 if (!msg_ex) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05301963 ipa_err("msg_ex allocation failed");
1964 return QDF_STATUS_E_NOMEM;
1965 }
1966 strlcpy(msg_ex->name, net_dev->name,
1967 IPA_RESOURCE_NAME_MAX);
1968 msg_ex->num_of_attribs = 1;
1969 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
1970 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1971 msg_ex->attribs[0].offset =
1972 WLAN_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1973 } else {
1974 msg_ex->attribs[0].offset =
1975 WLAN_IPA_WLAN_HDR_DES_MAC_OFFSET;
1976 }
1977 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
1978 IPA_MAC_ADDR_SIZE);
1979
1980 if (qdf_ipa_send_msg(&meta, msg_ex, wlan_ipa_msg_free_fn)) {
1981 ipa_info("%s: Evt: %d send ipa msg fail",
1982 net_dev->name, type);
1983 qdf_mem_free(msg_ex);
1984 return QDF_STATUS_E_FAILURE;
1985 }
1986 ipa_ctx->stats.num_send_msg++;
1987
1988 ipa_info("sap_num_connected_sta=%d",
1989 ipa_ctx->sap_num_connected_sta);
1990
1991 return QDF_STATUS_SUCCESS;
1992
1993 case WLAN_CLIENT_DISCONNECT:
1994 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
1995 ipa_debug("%s: IPA UC OFFLOAD NOT ENABLED",
1996 msg_ex->name);
1997 return QDF_STATUS_SUCCESS;
1998 }
1999
2000 qdf_mutex_acquire(&ipa_ctx->event_lock);
2001 if (!ipa_ctx->sap_num_connected_sta) {
2002 qdf_mutex_release(&ipa_ctx->event_lock);
2003 ipa_err("%s: Evt: %d, Client already disconnected",
2004 msg_ex->name,
2005 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2006
2007 return QDF_STATUS_SUCCESS;
2008 }
2009 if (!wlan_ipa_uc_find_add_assoc_sta(ipa_ctx, false,
2010 sta_id, mac_addr)) {
2011 qdf_mutex_release(&ipa_ctx->event_lock);
2012 ipa_err("%s: STA ID %d NOT found, not valid",
2013 msg_ex->name, sta_id);
2014
2015 return QDF_STATUS_SUCCESS;
2016 }
2017 ipa_ctx->sap_num_connected_sta--;
2018
2019 /* Disable IPA UC TX PIPE when last STA disconnected */
2020 if (!ipa_ctx->sap_num_connected_sta &&
2021 ipa_ctx->uc_loaded == true) {
Yun Parka29974a2018-04-09 12:05:49 -07002022 if ((false == ipa_ctx->resource_unloading) &&
2023 wlan_ipa_is_fw_wdi_activated(ipa_ctx) &&
2024 !ipa_ctx->ipa_pipes_down) {
jiad3a321f32018-07-16 18:16:39 +08002025 if (cds_is_driver_unloading()) {
2026 /*
2027 * We disable WDI pipes directly here
2028 * since IPA_OPCODE_TX/RX_SUSPEND
2029 * message will not be processed when
2030 * unloading WLAN driver is in progress
2031 */
2032 wlan_ipa_uc_disable_pipes(ipa_ctx);
2033 } else {
2034 wlan_ipa_uc_handle_last_discon(ipa_ctx);
2035 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302036 }
2037
2038 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
2039 ipa_ctx->sta_connected) {
2040 qdf_mutex_release(&ipa_ctx->event_lock);
2041 wlan_ipa_uc_offload_enable_disable(ipa_ctx,
2042 SIR_STA_RX_DATA_OFFLOAD,
Sravan Kumar Kairamf59aec12018-03-23 19:35:01 +05302043 sta_session_id, false);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302044 } else {
2045 qdf_mutex_release(&ipa_ctx->event_lock);
2046 }
2047 } else {
2048 qdf_mutex_release(&ipa_ctx->event_lock);
2049 }
2050
2051 ipa_info("sap_num_connected_sta=%d",
2052 ipa_ctx->sap_num_connected_sta);
2053 break;
2054
2055 default:
2056 return QDF_STATUS_SUCCESS;
2057 }
2058
2059 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
2060 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
2061 if (!msg) {
2062 ipa_err("msg allocation failed");
2063 return QDF_STATUS_E_NOMEM;
2064 }
2065
2066 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
2067 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
2068 IPA_RESOURCE_NAME_MAX);
2069 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
2070
2071 ipa_debug("%s: Evt: %d", QDF_IPA_WLAN_MSG_NAME(msg),
2072 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2073
2074 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
2075
2076 ipa_err("%s: Evt: %d fail",
2077 QDF_IPA_WLAN_MSG_NAME(msg),
2078 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2079 qdf_mem_free(msg);
2080
2081 return QDF_STATUS_E_FAILURE;
2082 }
2083
2084 ipa_ctx->stats.num_send_msg++;
2085
2086end:
2087 return QDF_STATUS_SUCCESS;
2088}
2089
2090/**
2091 * wlan_host_to_ipa_wlan_event() - convert wlan_ipa_wlan_event to ipa_wlan_event
Yun Park84fbb272018-04-02 15:31:01 -07002092 * @wlan_ipa_event_type: event to be converted to an ipa_wlan_event
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302093 *
2094 * Return: qdf_ipa_wlan_event representing the wlan_ipa_wlan_event
2095 */
2096static qdf_ipa_wlan_event
2097wlan_host_to_ipa_wlan_event(enum wlan_ipa_wlan_event wlan_ipa_event_type)
2098{
Yun Park84fbb272018-04-02 15:31:01 -07002099 qdf_ipa_wlan_event ipa_event;
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302100
2101 switch (wlan_ipa_event_type) {
2102 case WLAN_IPA_CLIENT_CONNECT:
2103 ipa_event = QDF_IPA_CLIENT_CONNECT;
2104 break;
2105 case WLAN_IPA_CLIENT_DISCONNECT:
2106 ipa_event = QDF_IPA_CLIENT_DISCONNECT;
2107 break;
2108 case WLAN_IPA_AP_CONNECT:
2109 ipa_event = QDF_IPA_AP_CONNECT;
2110 break;
2111 case WLAN_IPA_AP_DISCONNECT:
2112 ipa_event = QDF_IPA_AP_DISCONNECT;
2113 break;
2114 case WLAN_IPA_STA_CONNECT:
2115 ipa_event = QDF_IPA_STA_CONNECT;
2116 break;
2117 case WLAN_IPA_STA_DISCONNECT:
2118 ipa_event = QDF_IPA_STA_DISCONNECT;
2119 break;
2120 case WLAN_IPA_CLIENT_CONNECT_EX:
2121 ipa_event = QDF_IPA_CLIENT_CONNECT_EX;
2122 break;
2123 case WLAN_IPA_WLAN_EVENT_MAX:
2124 default:
2125 ipa_event = QDF_IPA_WLAN_EVENT_MAX;
2126 break;
2127 }
2128
2129 return ipa_event;
2130}
2131
2132/**
2133 * wlan_ipa_wlan_evt() - SSR wrapper for __wlan_ipa_wlan_evt
2134 * @net_dev: Interface net device
2135 * @device_mode: Net interface device mode
2136 * @sta_id: station id for the event
2137 * @session_id: session id for the event
2138 * @ipa_event_type: event enum of type wlan_ipa_wlan_event
2139 * @mac_address: MAC address associated with the event
2140 *
2141 * Return: QDF_STATUS
2142 */
2143QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
2144 uint8_t sta_id, uint8_t session_id,
2145 enum wlan_ipa_wlan_event ipa_event_type,
2146 uint8_t *mac_addr)
2147{
2148 qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
2149 QDF_STATUS status = QDF_STATUS_SUCCESS;
2150
2151 /* Data path offload only support for STA and SAP mode */
2152 if ((device_mode == QDF_STA_MODE) ||
2153 (device_mode == QDF_SAP_MODE))
2154 status = __wlan_ipa_wlan_evt(net_dev, device_mode, sta_id,
2155 session_id, type, mac_addr);
2156
2157 return status;
2158}
2159
2160/**
2161 * wlan_ipa_uc_proc_pending_event() - Process IPA uC pending events
2162 * @ipa_ctx: Global IPA IPA context
2163 * @is_loading: Indicate if invoked during loading
2164 *
2165 * Return: None
2166 */
2167static void
2168wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
2169{
2170 unsigned int pending_event_count;
2171 struct wlan_ipa_uc_pending_event *pending_event = NULL;
2172
2173 pending_event_count = qdf_list_size(&ipa_ctx->pending_event);
2174 ipa_debug("Pending Event Count %d", pending_event_count);
2175 if (!pending_event_count) {
2176 ipa_debug("No Pending Event");
2177 return;
2178 }
2179
2180 qdf_list_remove_front(&ipa_ctx->pending_event,
2181 (qdf_list_node_t **)&pending_event);
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002182 while (pending_event) {
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302183 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2184 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2185 struct wlan_objmgr_vdev *vdev =
2186 wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
2187 pending_event->session_id,
2188 WLAN_IPA_ID);
2189 if (pending_event->is_loading == is_loading && vdev) {
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302190 __wlan_ipa_wlan_evt(pending_event->net_dev,
2191 pending_event->device_mode,
2192 pending_event->sta_id,
2193 pending_event->session_id,
2194 pending_event->type,
2195 pending_event->mac_addr);
2196 }
Sravan Kumar Kairam8c151e22018-06-15 16:35:39 +05302197
2198 if (vdev)
2199 wlan_objmgr_vdev_release_ref(vdev, WLAN_IPA_ID);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302200 qdf_mem_free(pending_event);
2201 pending_event = NULL;
2202 qdf_list_remove_front(&ipa_ctx->pending_event,
2203 (qdf_list_node_t **)&pending_event);
2204 }
2205}
2206
2207/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002208 * wlan_ipa_free_tx_desc_list() - Free IPA Tx desc list
2209 * @ipa_ctx: IPA context
2210 *
2211 * Return: None
2212 */
2213static inline void wlan_ipa_free_tx_desc_list(struct wlan_ipa_priv *ipa_ctx)
2214{
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302215 int i;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002216 qdf_ipa_rx_data_t *ipa_tx_desc;
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302217 uint32_t pool_size;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002218
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302219 if (!ipa_ctx->tx_desc_pool)
2220 return;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002221
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302222 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2223 pool_size = ipa_ctx->tx_desc_free_list.max_size;
2224 for (i = 0; i < pool_size; i++) {
2225 ipa_tx_desc = ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002226 if (ipa_tx_desc)
2227 qdf_ipa_free_skb(ipa_tx_desc);
2228
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302229 if (qdf_list_remove_node(&ipa_ctx->tx_desc_free_list,
2230 &ipa_ctx->tx_desc_pool[i].node) !=
2231 QDF_STATUS_SUCCESS)
2232 ipa_err("Failed to remove node from tx desc freelist");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002233 }
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302234 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2235
2236 qdf_list_destroy(&ipa_ctx->tx_desc_free_list);
2237 qdf_mem_free(ipa_ctx->tx_desc_pool);
2238 ipa_ctx->tx_desc_pool = NULL;
2239
2240 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2241 ipa_ctx->stats.num_tx_desc_error = 0;
Ryan Hsub5783cf2018-05-14 12:13:15 -07002242}
2243
2244/**
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302245 * wlan_ipa_alloc_tx_desc_free_list() - Allocate IPA Tx desc list
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302246 * @ipa_ctx: IPA context
2247 *
2248 * Return: QDF_STATUS
2249 */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302250static QDF_STATUS
2251wlan_ipa_alloc_tx_desc_free_list(struct wlan_ipa_priv *ipa_ctx)
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302252{
2253 int i;
2254 uint32_t max_desc_cnt;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302255
2256 max_desc_cnt = ipa_ctx->config->txbuf_count;
2257
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302258 ipa_ctx->tx_desc_pool = qdf_mem_malloc(sizeof(struct wlan_ipa_tx_desc) *
2259 max_desc_cnt);
2260
2261 if (!ipa_ctx->tx_desc_pool) {
2262 ipa_err("Free Tx descriptor allocation failed");
2263 return QDF_STATUS_E_NOMEM;
2264 }
2265
2266 qdf_list_create(&ipa_ctx->tx_desc_free_list, max_desc_cnt);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302267
2268 qdf_spin_lock_bh(&ipa_ctx->q_lock);
2269 for (i = 0; i < max_desc_cnt; i++) {
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302270 ipa_ctx->tx_desc_pool[i].id = i;
2271 ipa_ctx->tx_desc_pool[i].ipa_tx_desc_ptr = NULL;
2272 qdf_list_insert_back(&ipa_ctx->tx_desc_free_list,
2273 &ipa_ctx->tx_desc_pool[i].node);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302274 }
2275
2276 ipa_ctx->stats.num_tx_desc_q_cnt = 0;
2277 ipa_ctx->stats.num_tx_desc_error = 0;
2278
2279 qdf_spin_unlock_bh(&ipa_ctx->q_lock);
2280
2281 return QDF_STATUS_SUCCESS;
2282}
2283
2284#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2285/**
2286 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
2287 * @ipa_ctx: Global IPA IPA context
2288 * @desc_fifo_sz: Number of descriptors
2289 *
2290 * Return: 0 on success, negative errno on error
2291 */
2292static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2293 int32_t desc_fifo_sz)
2294{
2295 int i, ret = 0;
2296 qdf_ipa_sys_connect_params_t *ipa;
2297
2298 /*setup TX pipes */
2299 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2300 ipa = &ipa_ctx->sys_pipe[i].ipa_sys_params;
2301
2302 ipa->client = wlan_ipa_iface_2_client[i].cons_client;
2303 ipa->desc_fifo_sz = desc_fifo_sz;
2304 ipa->priv = &ipa_ctx->iface_context[i];
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302305 ipa->notify = wlan_ipa_i2w_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302306
2307 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2308 ipa->ipa_ep_cfg.hdr.hdr_len =
2309 WLAN_IPA_UC_WLAN_TX_HDR_LEN;
2310 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2311 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
2312 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
2313 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
2314 WLAN_IPA_UC_WLAN_8023_HDR_SIZE;
2315 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
2316 } else {
2317 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_TX_HDR_LEN;
2318 }
2319 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2320
2321 ret = wlan_ipa_wdi_setup_sys_pipe(ipa_ctx, ipa,
2322 &ipa_ctx->sys_pipe[i].conn_hdl);
2323 if (ret) {
2324 ipa_err("Failed for pipe %d ret: %d", i, ret);
2325 return ret;
2326 }
2327 ipa_ctx->sys_pipe[i].conn_hdl_valid = 1;
2328 }
2329
2330 return ret;
2331}
2332#else
2333/**
2334 * wlan_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302335 * @ipa_ctx: IPA context
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302336 * @desc_fifo_sz: Number of descriptors
2337 *
2338 * Return: 0 on success, negative errno on error
2339 */
2340static int wlan_ipa_setup_tx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2341 int32_t desc_fifo_sz)
2342{
2343 /*
2344 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
2345 * is enabled, where per vdev descriptors are supported in firmware.
2346 */
2347 return 0;
2348}
2349#endif
2350
Sravan Kumar Kairam7efc0132019-03-25 16:13:46 +05302351#if defined(CONFIG_IPA_WDI_UNIFIED_API) && defined(IPA_WDI3_GSI)
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302352/**
2353 * wlan_ipa_get_rx_ipa_client() - Get IPA RX ipa client
2354 * @ipa_ctx: IPA context
2355 *
2356 * Return: rx ipa sys client
2357 */
2358static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2359{
2360 if (ipa_ctx->over_gsi)
2361 return IPA_CLIENT_WLAN2_PROD;
2362 else
2363 return IPA_CLIENT_WLAN1_PROD;
2364}
2365#else
2366static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
2367{
2368 return IPA_CLIENT_WLAN1_PROD;
2369}
2370#endif
2371
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302372/**
2373 * wlan_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
2374 * @ipa_ctx: Global IPA IPA context
2375 * @desc_fifo_sz: Number of descriptors
2376 *
2377 * Return: 0 on success, negative errno on error
2378 */
2379static int wlan_ipa_setup_rx_sys_pipe(struct wlan_ipa_priv *ipa_ctx,
2380 int32_t desc_fifo_sz)
2381{
2382 int ret = 0;
2383 qdf_ipa_sys_connect_params_t *ipa;
2384
2385 /*
2386 * Hard code it here, this can be extended if in case
2387 * PROD pipe is also per interface.
2388 * Right now there is no advantage of doing this.
2389 */
2390 ipa = &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].ipa_sys_params;
2391
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302392 ipa->client = wlan_ipa_get_rx_ipa_client(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302393 ipa->desc_fifo_sz = desc_fifo_sz;
2394 ipa->priv = ipa_ctx;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302395 ipa->notify = wlan_ipa_w2i_cb;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302396
2397 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
2398 ipa->ipa_ep_cfg.hdr.hdr_len = WLAN_IPA_WLAN_RX_HDR_LEN;
2399 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
2400 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
2401
2402 ret = qdf_ipa_setup_sys_pipe(ipa,
2403 &ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl);
2404 if (ret) {
2405 ipa_err("Failed for RX pipe: %d", ret);
2406 return ret;
2407 }
2408 ipa_ctx->sys_pipe[WLAN_IPA_RX_PIPE].conn_hdl_valid = 1;
2409
2410 return ret;
2411}
2412
2413/**
Ryan Hsub5783cf2018-05-14 12:13:15 -07002414 * wlan_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
2415 * @ipa_ctx: Global IPA IPA context
2416 *
2417 * Return: None
2418 */
2419static void wlan_ipa_teardown_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2420{
2421 int ret, i;
2422
2423 if (!ipa_ctx)
2424 return;
2425
2426 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++) {
2427 if (ipa_ctx->sys_pipe[i].conn_hdl_valid) {
2428 ret = wlan_ipa_wdi_teardown_sys_pipe(ipa_ctx,
2429 ipa_ctx->sys_pipe[i].conn_hdl);
2430 if (ret)
2431 ipa_err("Failed:%d", ret);
2432
2433 ipa_ctx->sys_pipe[i].conn_hdl_valid = 0;
2434 }
2435 }
2436
2437 wlan_ipa_free_tx_desc_list(ipa_ctx);
2438}
2439
2440/**
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302441 * wlan_ipa_setup_sys_pipe() - Setup all IPA system pipes
2442 * @ipa_ctx: Global IPA IPA context
2443 *
2444 * Return: 0 on success, negative errno on error
2445 */
2446static int wlan_ipa_setup_sys_pipe(struct wlan_ipa_priv *ipa_ctx)
2447{
Ryan Hsub5783cf2018-05-14 12:13:15 -07002448 int ret = 0;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302449 uint32_t desc_fifo_sz;
2450
2451 /* The maximum number of descriptors that can be provided to a BAM at
2452 * once is one less than the total number of descriptors that the buffer
2453 * can contain.
2454 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
2455 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
2456 * be provided at once.
2457 * Because of above requirement, one extra descriptor will be added to
2458 * make sure hardware always has one descriptor.
2459 */
2460 desc_fifo_sz = ipa_ctx->config->desc_size
2461 + SPS_DESC_SIZE;
2462
2463 ret = wlan_ipa_setup_tx_sys_pipe(ipa_ctx, desc_fifo_sz);
2464 if (ret) {
2465 ipa_err("Failed for TX pipe: %d", ret);
2466 goto setup_sys_pipe_fail;
2467 }
2468
2469 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2470 ret = wlan_ipa_setup_rx_sys_pipe(ipa_ctx, desc_fifo_sz);
2471 if (ret) {
2472 ipa_err("Failed for RX pipe: %d", ret);
2473 goto setup_sys_pipe_fail;
2474 }
2475 }
2476
2477 /* Allocate free Tx desc list */
Sravan Kumar Kairam1f8f8b32018-07-06 16:05:24 +05302478 ret = wlan_ipa_alloc_tx_desc_free_list(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302479 if (ret)
2480 goto setup_sys_pipe_fail;
2481
2482 return ret;
2483
2484setup_sys_pipe_fail:
Ryan Hsub5783cf2018-05-14 12:13:15 -07002485 wlan_ipa_teardown_sys_pipe(ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302486
2487 return ret;
2488}
2489
jiadbb47e132018-03-30 16:28:30 +08002490#ifndef QCA_LL_TX_FLOW_CONTROL_V2
2491QDF_STATUS wlan_ipa_send_mcc_scc_msg(struct wlan_ipa_priv *ipa_ctx,
2492 bool mcc_mode)
2493{
2494 qdf_ipa_msg_meta_t meta;
2495 qdf_ipa_wlan_msg_t *msg;
2496 int ret;
2497
2498 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
2499 return QDF_STATUS_SUCCESS;
2500
2501 /* Send SCC/MCC Switching event to IPA */
2502 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
2503 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Jeff Johnson1d44fee52019-03-18 14:02:06 -07002504 if (!msg) {
jiadbb47e132018-03-30 16:28:30 +08002505 ipa_err("msg allocation failed");
2506 return QDF_STATUS_E_NOMEM;
2507 }
2508
jiad629b2172018-05-11 15:34:22 +08002509 if (mcc_mode) {
jiadbb47e132018-03-30 16:28:30 +08002510 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_MCC);
jiad629b2172018-05-11 15:34:22 +08002511 ipa_ctx->stats.event[QDF_SWITCH_TO_MCC]++;
2512 } else {
jiadbb47e132018-03-30 16:28:30 +08002513 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_SWITCH_TO_SCC);
jiad629b2172018-05-11 15:34:22 +08002514 ipa_ctx->stats.event[QDF_SWITCH_TO_SCC]++;
2515 }
2516
jiadbb47e132018-03-30 16:28:30 +08002517 WLAN_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
2518 "ipa_send_msg(Evt:%d)",
2519 QDF_IPA_MSG_META_MSG_TYPE(&meta));
2520
2521 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
2522
2523 if (ret) {
2524 ipa_err("ipa_send_msg(Evt:%d) - fail=%d",
2525 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
2526 qdf_mem_free(msg);
2527 return QDF_STATUS_E_FAILURE;
2528 }
2529
2530 return QDF_STATUS_SUCCESS;
2531}
2532
2533static void wlan_ipa_mcc_work_handler(void *data)
2534{
2535 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)data;
2536
2537 wlan_ipa_send_mcc_scc_msg(ipa_ctx, ipa_ctx->mcc_mode);
2538}
2539#endif
2540
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302541/**
2542 * wlan_ipa_setup() - IPA initialization function
2543 * @ipa_ctx: IPA context
2544 * @ipa_cfg: IPA config
2545 *
2546 * Allocate ipa_ctx resources, ipa pipe resource and register
2547 * wlan interface with IPA module.
2548 *
2549 * Return: QDF_STATUS enumeration
2550 */
2551QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
2552 struct wlan_ipa_config *ipa_cfg)
2553{
2554 int ret, i;
2555 struct wlan_ipa_iface_context *iface_context = NULL;
2556 QDF_STATUS status;
2557
2558 ipa_debug("enter");
2559
2560 gp_ipa = ipa_ctx;
2561 ipa_ctx->num_iface = 0;
2562 ipa_ctx->config = ipa_cfg;
2563
2564 wlan_ipa_wdi_get_wdi_version(ipa_ctx);
2565
2566 /* Create the interface context */
2567 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2568 iface_context = &ipa_ctx->iface_context[i];
2569 iface_context->ipa_ctx = ipa_ctx;
2570 iface_context->cons_client =
2571 wlan_ipa_iface_2_client[i].cons_client;
2572 iface_context->prod_client =
2573 wlan_ipa_iface_2_client[i].prod_client;
2574 iface_context->iface_id = i;
2575 iface_context->dev = NULL;
2576 iface_context->device_mode = QDF_MAX_NO_OF_MODE;
2577 iface_context->tl_context = NULL;
2578 qdf_spinlock_create(&iface_context->interface_lock);
2579 }
2580
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302581 qdf_create_work(0, &ipa_ctx->pm_work, wlan_ipa_pm_flush, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302582 qdf_spinlock_create(&ipa_ctx->pm_lock);
2583 qdf_spinlock_create(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302584 qdf_spinlock_create(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302585 qdf_nbuf_queue_init(&ipa_ctx->pm_queue_head);
2586 qdf_list_create(&ipa_ctx->pending_event, 1000);
2587 qdf_mutex_create(&ipa_ctx->event_lock);
2588 qdf_mutex_create(&ipa_ctx->ipa_lock);
2589
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302590 status = wlan_ipa_wdi_setup_rm(ipa_ctx);
2591 if (status != QDF_STATUS_SUCCESS)
2592 goto fail_setup_rm;
2593
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302594 for (i = 0; i < WLAN_IPA_MAX_SYSBAM_PIPE; i++)
2595 qdf_mem_zero(&ipa_ctx->sys_pipe[i],
2596 sizeof(struct wlan_ipa_sys_pipe));
2597
2598 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2599 qdf_mem_zero(&ipa_ctx->stats, sizeof(ipa_ctx->stats));
2600 ipa_ctx->sap_num_connected_sta = 0;
2601 ipa_ctx->ipa_tx_packets_diff = 0;
2602 ipa_ctx->ipa_rx_packets_diff = 0;
2603 ipa_ctx->ipa_p_tx_packets = 0;
2604 ipa_ctx->ipa_p_rx_packets = 0;
2605 ipa_ctx->resource_loading = false;
2606 ipa_ctx->resource_unloading = false;
2607 ipa_ctx->sta_connected = 0;
2608 ipa_ctx->ipa_pipes_down = true;
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302609 ipa_ctx->pipes_down_in_progress = false;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302610 ipa_ctx->wdi_enabled = false;
2611 /* Setup IPA system pipes */
2612 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
2613 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2614 if (ret)
2615 goto fail_create_sys_pipe;
jiadbb47e132018-03-30 16:28:30 +08002616
2617 qdf_create_work(0, &ipa_ctx->mcc_work,
2618 wlan_ipa_mcc_work_handler, ipa_ctx);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302619 }
2620
2621 status = wlan_ipa_wdi_init(ipa_ctx);
2622 if (status == QDF_STATUS_E_BUSY)
2623 status = wlan_ipa_uc_send_wdi_control_msg(false);
2624 if (status != QDF_STATUS_SUCCESS) {
Ryan Hsub5783cf2018-05-14 12:13:15 -07002625 ipa_err("IPA WDI init failed: ret=%d", status);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302626 goto fail_create_sys_pipe;
2627 }
2628 } else {
2629 ret = wlan_ipa_setup_sys_pipe(ipa_ctx);
2630 if (ret)
2631 goto fail_create_sys_pipe;
2632 }
2633
2634 qdf_event_create(&ipa_ctx->ipa_resource_comp);
2635
2636 ipa_debug("exit: success");
2637
2638 return QDF_STATUS_SUCCESS;
2639
2640fail_create_sys_pipe:
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302641 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2642
2643fail_setup_rm:
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302644 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302645 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302646 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302647 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2648 iface_context = &ipa_ctx->iface_context[i];
2649 qdf_spinlock_destroy(&iface_context->interface_lock);
2650 }
2651 qdf_mutex_destroy(&ipa_ctx->event_lock);
2652 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2653 qdf_list_destroy(&ipa_ctx->pending_event);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302654 gp_ipa = NULL;
2655 ipa_debug("exit: fail");
2656
2657 return QDF_STATUS_E_FAILURE;
2658}
2659
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302660void wlan_ipa_flush(struct wlan_ipa_priv *ipa_ctx)
2661{
2662 qdf_nbuf_t skb;
2663 struct wlan_ipa_pm_tx_cb *pm_tx_cb;
2664
2665 if (!wlan_ipa_is_enabled(ipa_ctx->config))
2666 return;
2667
2668 qdf_cancel_work(&ipa_ctx->pm_work);
2669
2670 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2671
2672 while (((skb = qdf_nbuf_queue_remove(&ipa_ctx->pm_queue_head))
2673 != NULL)) {
2674 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2675
2676 pm_tx_cb = (struct wlan_ipa_pm_tx_cb *)skb->cb;
jiadab8cea02018-05-24 09:16:14 +08002677
2678 if (pm_tx_cb->exception) {
2679 dev_kfree_skb_any(skb);
2680 } else {
2681 if (pm_tx_cb->ipa_tx_desc)
2682 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
2683 }
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302684
2685 qdf_spin_lock_bh(&ipa_ctx->pm_lock);
2686 }
2687 qdf_spin_unlock_bh(&ipa_ctx->pm_lock);
2688}
2689
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302690QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
2691{
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302692 struct wlan_ipa_iface_context *iface_context;
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302693 int i;
2694
2695 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
2696 wlan_ipa_teardown_sys_pipe(ipa_ctx);
2697
2698 /* Teardown IPA sys_pipe for MCC */
jiadbb47e132018-03-30 16:28:30 +08002699 if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302700 wlan_ipa_teardown_sys_pipe(ipa_ctx);
jiadbb47e132018-03-30 16:28:30 +08002701 qdf_cancel_work(&ipa_ctx->mcc_work);
2702 }
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302703
Sravan Kumar Kairam2e7aae92018-03-06 19:32:49 +05302704 wlan_ipa_wdi_destroy_rm(ipa_ctx);
2705
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302706 wlan_ipa_flush(ipa_ctx);
2707
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302708 qdf_spinlock_destroy(&ipa_ctx->pm_lock);
2709 qdf_spinlock_destroy(&ipa_ctx->q_lock);
Rakshith Suresh Patkar785b8452019-03-18 13:36:02 +05302710 qdf_spinlock_destroy(&ipa_ctx->pipes_down_lock);
Sravan Kumar Kairamd01b4452018-03-07 17:37:09 +05302711
2712 /* destroy the interface lock */
2713 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2714 iface_context = &ipa_ctx->iface_context[i];
2715 qdf_spinlock_destroy(&iface_context->interface_lock);
2716 }
2717
2718 if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
2719 wlan_ipa_wdi_cleanup();
2720 qdf_mutex_destroy(&ipa_ctx->event_lock);
2721 qdf_mutex_destroy(&ipa_ctx->ipa_lock);
2722 qdf_list_destroy(&ipa_ctx->pending_event);
2723
2724 }
2725
2726 gp_ipa = NULL;
2727
2728 return QDF_STATUS_SUCCESS;
2729}
Sravan Kumar Kairam271fab22018-03-07 18:57:41 +05302730
2731struct wlan_ipa_iface_context
2732*wlan_ipa_get_iface(struct wlan_ipa_priv *ipa_ctx, uint8_t mode)
2733{
2734 struct wlan_ipa_iface_context *iface_ctx = NULL;
2735 int i;
2736
2737 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
2738 iface_ctx = &ipa_ctx->iface_context[i];
2739
2740 if (iface_ctx->device_mode == mode)
2741 return iface_ctx;
2742 }
2743
2744 return NULL;
2745}
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302746
jiadbb47e132018-03-30 16:28:30 +08002747void wlan_ipa_set_mcc_mode(struct wlan_ipa_priv *ipa_ctx, bool mcc_mode)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302748{
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302749 if (!wlan_ipa_uc_sta_is_enabled(ipa_ctx->config))
jiadbb47e132018-03-30 16:28:30 +08002750 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302751
jiadbb47e132018-03-30 16:28:30 +08002752 if (ipa_ctx->mcc_mode == mcc_mode)
2753 return;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302754
jiadbb47e132018-03-30 16:28:30 +08002755 ipa_ctx->mcc_mode = mcc_mode;
2756 qdf_sched_work(0, &ipa_ctx->mcc_work);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302757}
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302758
2759/**
2760 * wlan_ipa_uc_loaded_handler() - Process IPA uC loaded indication
2761 * @ipa_ctx: ipa ipa local context
2762 *
2763 * Will handle IPA UC image loaded indication comes from IPA kernel
2764 *
2765 * Return: None
2766 */
2767static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
2768{
2769 struct wlan_objmgr_pdev *pdev = ipa_ctx->pdev;
2770 struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
2771 qdf_device_t qdf_dev = wlan_psoc_get_qdf_dev(psoc);
2772 QDF_STATUS status;
2773
2774 ipa_info("UC READY");
Ryan Hsub5783cf2018-05-14 12:13:15 -07002775
2776 if (!qdf_dev) {
2777 ipa_err("qdf device is NULL!");
2778 return;
2779 }
2780
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302781 if (true == ipa_ctx->uc_loaded) {
2782 ipa_info("UC already loaded");
2783 return;
2784 }
2785
Lihua Liu15f6e452018-05-30 17:31:06 +08002786 if (!qdf_dev) {
2787 ipa_err("qdf_dev is null");
2788 return;
2789 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302790 /* Connect pipe */
2791 status = wlan_ipa_wdi_setup(ipa_ctx, qdf_dev);
2792 if (status) {
2793 ipa_err("Failure to setup IPA pipes (status=%d)",
2794 status);
2795 return;
2796 }
2797
2798 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302799
2800 /* If already any STA connected, enable IPA/FW PIPEs */
2801 if (ipa_ctx->sap_num_connected_sta) {
2802 ipa_debug("Client already connected, enable IPA/FW PIPEs");
2803 wlan_ipa_uc_handle_first_con(ipa_ctx);
2804 }
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302805}
2806
2807/**
2808 * wlan_ipa_uc_op_cb() - IPA uC operation callback
2809 * @op_msg: operation message received from firmware
2810 * @usr_ctxt: user context registered with TL (we register the IPA Global
2811 * context)
2812 *
2813 * Return: None
2814 */
2815static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
2816 struct wlan_ipa_priv *ipa_ctx)
2817{
2818 struct op_msg_type *msg = op_msg;
2819 struct ipa_uc_fw_stats *uc_fw_stat;
2820
2821 if (!op_msg) {
2822 ipa_err("INVALID ARG");
2823 return;
2824 }
2825
2826 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2827 ipa_err("INVALID OPCODE %d", msg->op_code);
2828 qdf_mem_free(op_msg);
2829 return;
2830 }
2831
2832 ipa_debug("OPCODE=%d", msg->op_code);
2833
2834 if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_RESUME) ||
2835 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_RESUME)) {
2836 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2837 ipa_ctx->activated_fw_pipe++;
Yun Parka29974a2018-04-09 12:05:49 -07002838 if (wlan_ipa_is_fw_wdi_activated(ipa_ctx)) {
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302839 ipa_ctx->resource_loading = false;
2840 qdf_event_set(&ipa_ctx->ipa_resource_comp);
2841 if (ipa_ctx->wdi_enabled == false) {
2842 ipa_ctx->wdi_enabled = true;
2843 if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
2844 wlan_ipa_send_mcc_scc_msg(ipa_ctx,
2845 ipa_ctx->mcc_mode);
2846 }
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302847 wlan_ipa_uc_proc_pending_event(ipa_ctx, true);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302848 if (ipa_ctx->pending_cons_req)
Yun Parke114fbf2018-04-05 20:02:12 -07002849 wlan_ipa_wdi_rm_notify_completion(
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302850 QDF_IPA_RM_RESOURCE_GRANTED,
2851 QDF_IPA_RM_RESOURCE_WLAN_CONS);
2852 ipa_ctx->pending_cons_req = false;
2853 }
2854 qdf_mutex_release(&ipa_ctx->ipa_lock);
2855 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_TX_SUSPEND) ||
2856 (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND)) {
2857 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
Sravan Kumar Kairama61e5a92018-06-18 13:01:05 +05302858
2859 if (msg->op_code == WLAN_IPA_UC_OPCODE_RX_SUSPEND) {
2860 wlan_ipa_uc_disable_pipes(ipa_ctx);
2861 ipa_info("Disable FW TX PIPE");
2862 cdp_ipa_set_active(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
2863 false, true);
2864 }
2865
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302866 ipa_ctx->activated_fw_pipe--;
2867 if (!ipa_ctx->activated_fw_pipe) {
2868 /*
2869 * Async return success from FW
2870 * Disable/suspend all the PIPEs
2871 */
2872 ipa_ctx->resource_unloading = false;
2873 qdf_event_set(&ipa_ctx->ipa_resource_comp);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302874 if (wlan_ipa_is_rm_enabled(ipa_ctx->config))
Yun Parke114fbf2018-04-05 20:02:12 -07002875 wlan_ipa_wdi_rm_release_resource(ipa_ctx,
2876 QDF_IPA_RM_RESOURCE_WLAN_PROD);
Sravan Kumar Kairam5214f652018-03-13 09:52:31 +05302877 wlan_ipa_uc_proc_pending_event(ipa_ctx, false);
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302878 ipa_ctx->pending_cons_req = false;
2879 }
2880 qdf_mutex_release(&ipa_ctx->ipa_lock);
2881 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2882 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_DEBUG)) {
2883 uc_fw_stat = (struct ipa_uc_fw_stats *)
2884 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2885
2886 /* WLAN FW WDI stats */
2887 wlan_ipa_print_fw_wdi_stats(ipa_ctx, uc_fw_stat);
2888 } else if ((msg->op_code == WLAN_IPA_UC_OPCODE_STATS) &&
2889 (ipa_ctx->stat_req_reason == WLAN_IPA_UC_STAT_REASON_BW_CAL)) {
2890 /* STATs from FW */
2891 uc_fw_stat = (struct ipa_uc_fw_stats *)
2892 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2893 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2894 ipa_ctx->ipa_tx_packets_diff = BW_GET_DIFF(
2895 uc_fw_stat->tx_pkts_completed,
2896 ipa_ctx->ipa_p_tx_packets);
2897 ipa_ctx->ipa_rx_packets_diff = BW_GET_DIFF(
2898 (uc_fw_stat->rx_num_ind_drop_no_space +
2899 uc_fw_stat->rx_num_ind_drop_no_buf +
2900 uc_fw_stat->rx_num_pkts_indicated),
2901 ipa_ctx->ipa_p_rx_packets);
2902
2903 ipa_ctx->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2904 ipa_ctx->ipa_p_rx_packets =
2905 (uc_fw_stat->rx_num_ind_drop_no_space +
2906 uc_fw_stat->rx_num_ind_drop_no_buf +
2907 uc_fw_stat->rx_num_pkts_indicated);
2908 qdf_mutex_release(&ipa_ctx->ipa_lock);
2909 } else if (msg->op_code == WLAN_IPA_UC_OPCODE_UC_READY) {
2910 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
2911 wlan_ipa_uc_loaded_handler(ipa_ctx);
2912 qdf_mutex_release(&ipa_ctx->ipa_lock);
2913 } else if (wlan_ipa_uc_op_metering(ipa_ctx, op_msg)) {
2914 ipa_err("Invalid message: op_code=%d, reason=%d",
2915 msg->op_code, ipa_ctx->stat_req_reason);
2916 }
2917
2918 qdf_mem_free(op_msg);
2919}
2920
2921/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302922 * __wlan_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2923 * @data: uC OP work
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302924 *
2925 * Return: None
2926 */
jitiphilfdcaaba2018-09-03 16:19:52 +05302927static void __wlan_ipa_uc_fw_op_event_handler(void *data)
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302928{
2929 struct op_msg_type *msg;
2930 struct uc_op_work_struct *uc_op_work =
2931 (struct uc_op_work_struct *)data;
2932 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
2933
2934 msg = uc_op_work->msg;
2935 uc_op_work->msg = NULL;
2936 ipa_debug("posted msg %d", msg->op_code);
2937
2938 wlan_ipa_uc_op_cb(msg, ipa_ctx);
2939}
2940
2941/**
jitiphilfdcaaba2018-09-03 16:19:52 +05302942 * wlan_ipa_uc_fw_op_event_handler - SSR wrapper for
2943 * __wlan_ipa_uc_fw_op_event_handler
2944 * @data: uC OP work
2945 *
2946 * Return: None
2947 */
2948static void wlan_ipa_uc_fw_op_event_handler(void *data)
2949{
Dustin Brown3fdaaf62019-03-18 14:00:16 -07002950 struct qdf_op_sync *op_sync;
2951
2952 if (qdf_op_protect(&op_sync))
2953 return;
2954
jitiphilfdcaaba2018-09-03 16:19:52 +05302955 __wlan_ipa_uc_fw_op_event_handler(data);
Dustin Brown3fdaaf62019-03-18 14:00:16 -07002956
2957 qdf_op_unprotect(op_sync);
jitiphilfdcaaba2018-09-03 16:19:52 +05302958}
2959
2960/**
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05302961 * wlan_ipa_uc_op_event_handler() - IPA UC OP event handler
2962 * @op_msg: operation message received from firmware
2963 * @ipa_ctx: Global IPA context
2964 *
2965 * Return: None
2966 */
2967static void wlan_ipa_uc_op_event_handler(uint8_t *op_msg, void *ctx)
2968{
2969 struct wlan_ipa_priv *ipa_ctx = (struct wlan_ipa_priv *)ctx;
2970 struct op_msg_type *msg;
2971 struct uc_op_work_struct *uc_op_work;
2972
2973 if (!ipa_ctx)
2974 goto end;
2975
2976 msg = (struct op_msg_type *)op_msg;
2977
2978 if (msg->op_code >= WLAN_IPA_UC_OPCODE_MAX) {
2979 ipa_err("Invalid OP Code (%d)", msg->op_code);
2980 goto end;
2981 }
2982
2983 uc_op_work = &ipa_ctx->uc_op_work[msg->op_code];
2984 if (uc_op_work->msg) {
2985 /* When the same uC OPCODE is already pended, just return */
2986 goto end;
2987 }
2988
2989 uc_op_work->msg = msg;
2990 qdf_sched_work(0, &uc_op_work->work);
2991 return;
2992
2993end:
2994 qdf_mem_free(op_msg);
2995}
2996
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05302997QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
2998 qdf_device_t osdev)
2999{
3000 uint8_t i;
3001 QDF_STATUS status = QDF_STATUS_SUCCESS;
3002
3003 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3004 return QDF_STATUS_SUCCESS;
3005
3006 ipa_debug("enter");
3007
3008 for (i = 0; i < WLAN_IPA_MAX_SESSION; i++) {
3009 ipa_ctx->vdev_to_iface[i] = WLAN_IPA_MAX_SESSION;
3010 ipa_ctx->vdev_offload_enabled[i] = false;
3011 }
3012
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303013 if (cdp_ipa_get_resource(ipa_ctx->dp_soc, ipa_ctx->dp_pdev)) {
3014 ipa_err("IPA UC resource alloc fail");
3015 status = QDF_STATUS_E_FAILURE;
3016 goto fail_return;
3017 }
3018
3019 if (true == ipa_ctx->uc_loaded) {
3020 status = wlan_ipa_wdi_setup(ipa_ctx, osdev);
3021 if (status) {
3022 ipa_err("Failure to setup IPA pipes (status=%d)",
3023 status);
3024 status = QDF_STATUS_E_FAILURE;
3025 goto fail_return;
3026 }
3027
3028 cdp_ipa_set_doorbell_paddr(ipa_ctx->dp_soc, ipa_ctx->dp_pdev);
3029 wlan_ipa_init_metering(ipa_ctx);
jiadf9771182018-06-12 12:43:40 +08003030
3031 if (wlan_ipa_init_perf_level(ipa_ctx) != QDF_STATUS_SUCCESS)
3032 ipa_err("Failed to init perf level");
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303033 }
3034
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303035 cdp_ipa_register_op_cb(ipa_ctx->dp_soc, ipa_ctx->dp_pdev,
3036 wlan_ipa_uc_op_event_handler, (void *)ipa_ctx);
3037
3038 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3039 qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
3040 wlan_ipa_uc_fw_op_event_handler,
3041 &ipa_ctx->uc_op_work[i]);
3042 ipa_ctx->uc_op_work[i].msg = NULL;
3043 }
3044
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303045fail_return:
3046 ipa_debug("exit: status=%d", status);
3047 return status;
3048}
3049
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303050/**
3051 * wlan_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3052 * @ipa_ctx: pointer to IPA IPA struct
3053 *
3054 * Return: none
3055 */
3056static void wlan_ipa_cleanup_pending_event(struct wlan_ipa_priv *ipa_ctx)
3057{
3058 struct wlan_ipa_uc_pending_event *pending_event = NULL;
3059
3060 while (qdf_list_remove_front(&ipa_ctx->pending_event,
3061 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3062 qdf_mem_free(pending_event);
3063}
3064
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303065QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
3066{
3067 QDF_STATUS status = QDF_STATUS_SUCCESS;
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303068 int i;
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303069
3070 ipa_debug("enter");
3071
3072 if (!wlan_ipa_uc_is_enabled(ipa_ctx->config))
3073 return status;
3074
3075 if (!ipa_ctx->ipa_pipes_down)
3076 wlan_ipa_uc_disable_pipes(ipa_ctx);
3077
3078 if (true == ipa_ctx->uc_loaded) {
3079 status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
3080 ipa_ctx->tx_pipe_handle,
3081 ipa_ctx->rx_pipe_handle);
3082 if (status)
3083 ipa_err("Failure to cleanup IPA pipes (status=%d)",
3084 status);
3085 }
3086
Sravan Kumar Kairam7d931ff2018-03-13 09:42:02 +05303087 qdf_mutex_acquire(&ipa_ctx->ipa_lock);
3088 wlan_ipa_cleanup_pending_event(ipa_ctx);
3089 qdf_mutex_release(&ipa_ctx->ipa_lock);
3090
3091 for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
3092 qdf_cancel_work(&ipa_ctx->uc_op_work[i].work);
3093 qdf_mem_free(ipa_ctx->uc_op_work[i].msg);
3094 ipa_ctx->uc_op_work[i].msg = NULL;
3095 }
3096
Sravan Kumar Kairam1309e7e2018-03-13 09:29:52 +05303097 ipa_debug("exit: ret=%d", status);
3098 return status;
3099}
Sravan Kumar Kairam983a4452018-03-20 13:30:22 +05303100
Sravan Kumar Kairamce792eb2018-06-15 15:07:11 +05303101/**
3102 * wlan_ipa_uc_send_evt() - send event to ipa
3103 * @net_dev: Interface net device
3104 * @type: event type
3105 * @mac_addr: pointer to mac address
3106 *
3107 * Send event to IPA driver
3108 *
3109 * Return: QDF_STATUS
3110 */
3111static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
3112 qdf_ipa_wlan_event type,
3113 uint8_t *mac_addr)
3114{
3115 struct wlan_ipa_priv *ipa_ctx = gp_ipa;
3116 qdf_ipa_msg_meta_t meta;
3117 qdf_ipa_wlan_msg_t *msg;
3118
3119 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3120 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
3121 if (!msg) {
3122 ipa_err("msg allocation failed");
3123 return QDF_STATUS_E_NOMEM;
3124 }
3125
3126 QDF_IPA_SET_META_MSG_TYPE(&meta, type);
3127 qdf_str_lcopy(QDF_IPA_WLAN_MSG_NAME(msg), net_dev->name,
3128 IPA_RESOURCE_NAME_MAX);
3129 qdf_mem_copy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, QDF_NET_ETH_LEN);
3130
3131 if (qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn)) {
3132 ipa_err("%s: Evt: %d fail",
3133 QDF_IPA_WLAN_MSG_NAME(msg),
3134 QDF_IPA_MSG_META_MSG_TYPE(&meta));
3135 qdf_mem_free(msg);
3136
3137 return QDF_STATUS_E_FAILURE;
3138 }
3139
3140 ipa_ctx->stats.num_send_msg++;
3141
3142 return QDF_STATUS_SUCCESS;
3143}
3144
3145QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
3146 qdf_netdev_t net_dev)
3147{
3148 struct wlan_ipa_iface_context *iface_ctx;
3149 QDF_STATUS status;
3150
3151 ipa_debug("enter");
3152
3153 iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
3154 if (iface_ctx)
3155 status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
3156 net_dev->dev_addr);
3157 else
3158 return QDF_STATUS_E_INVAL;
3159
3160 ipa_debug("exit :%d", status);
3161
3162 return status;
3163}
3164
3165void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
3166 qdf_netdev_t net_dev)
3167{
3168 struct wlan_ipa_iface_context *iface_ctx;
3169 int i;
3170
3171 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3172 iface_ctx = &ipa_ctx->iface_context[i];
3173 if (iface_ctx->dev == net_dev)
3174 break;
3175 }
3176
3177 if (iface_ctx)
3178 wlan_ipa_cleanup_iface(iface_ctx);
3179}
Sravan Kumar Kairam657f89e2018-09-18 10:13:37 +05303180
3181void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
3182{
3183 struct wlan_ipa_iface_context *iface;
3184 int i;
3185
3186 ipa_info("enter");
3187
3188 for (i = 0; i < WLAN_IPA_MAX_IFACE; i++) {
3189 iface = &ipa_ctx->iface_context[i];
3190 if (iface->dev) {
3191 if (iface->device_mode == QDF_SAP_MODE)
3192 wlan_ipa_uc_send_evt(iface->dev,
3193 QDF_IPA_AP_DISCONNECT,
3194 iface->dev->dev_addr);
3195 else if (iface->device_mode == QDF_STA_MODE)
3196 wlan_ipa_uc_send_evt(iface->dev,
3197 QDF_IPA_STA_DISCONNECT,
3198 iface->dev->dev_addr);
3199 wlan_ipa_cleanup_iface(iface);
3200 }
3201 }
3202}
jitiphil0e3b5922018-07-24 18:43:50 +05303203
3204void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
3205{
3206 qdf_ipa_msg_meta_t meta;
3207 qdf_ipa_wlan_msg_t *msg;
3208 int ret;
3209
3210 meta.msg_len = sizeof(*msg);
3211 msg = qdf_mem_malloc(meta.msg_len);
3212 if (!msg) {
3213 ipa_debug("msg allocation failed");
3214 return;
3215 }
3216
3217 QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
3218 ipa_debug("ipa_send_msg(Evt:%d)",
3219 meta.msg_type);
3220 ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
3221
3222 if (ret) {
3223 ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
3224 meta.msg_type, ret);
3225 qdf_mem_free(msg);
3226 }
3227 ipa_ctx->stats.num_send_msg++;
3228}