blob: 026f40f2053d0260e9ddea646e9db27e8fb98c56 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Rajeev Kumar3887f9b2018-01-10 11:24:01 -08002 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_ipa.c
30 *
31 * WLAN HDD and ipa interface implementation
32 * Originally written by Qualcomm Atheros, Inc
33 */
34
35#ifdef IPA_OFFLOAD
36
37/* Include Files */
Yun Park6c86a662017-10-05 16:09:15 -070038#include <qdf_ipa.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080039#include <wlan_hdd_includes.h>
40#include <wlan_hdd_ipa.h>
41
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080042#include <linux/inetdevice.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080043#include <wlan_hdd_softap_tx_rx.h>
Poddar, Siddarth8e3ee2d2016-11-29 20:17:01 +053044#include <ol_txrx.h>
Manjunathappa Prakash3454fd62016-04-01 08:52:06 -070045#include <cdp_txrx_peer_ops.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080046
47#include "cds_sched.h"
48
49#include "wma.h"
50#include "wma_api.h"
Prakash Dhavali87b38e32016-11-14 16:22:53 -080051#include "wal_rx_desc.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080052
Dhanashri Atreb08959a2016-03-01 17:28:03 -080053#include "cdp_txrx_ipa.h"
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080054#include "wlan_policy_mgr_api.h"
55
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#define HDD_IPA_RX_INACTIVITY_MSEC_DELAY 1000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080057#define HDD_IPA_UC_WLAN_8023_HDR_SIZE 14
Yun Parkb4f591d2017-03-29 15:51:01 -070058
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059#define HDD_IPA_UC_NUM_WDI_PIPE 2
60#define HDD_IPA_UC_MAX_PENDING_EVENT 33
61
62#define HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE 32000
63#define HDD_IPA_UC_RT_DEBUG_PERIOD 300
64#define HDD_IPA_UC_RT_DEBUG_BUF_COUNT 30
65#define HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL 10000
66
67#define HDD_IPA_WLAN_HDR_DES_MAC_OFFSET 0
68#define HDD_IPA_MAX_IFACE 3
69#define HDD_IPA_MAX_SYSBAM_PIPE 4
Yun Parkb4f591d2017-03-29 15:51:01 -070070
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071#define HDD_IPA_RX_PIPE HDD_IPA_MAX_IFACE
72#define HDD_IPA_ENABLE_MASK BIT(0)
73#define HDD_IPA_PRE_FILTER_ENABLE_MASK BIT(1)
74#define HDD_IPA_IPV6_ENABLE_MASK BIT(2)
75#define HDD_IPA_RM_ENABLE_MASK BIT(3)
76#define HDD_IPA_CLK_SCALING_ENABLE_MASK BIT(4)
77#define HDD_IPA_UC_ENABLE_MASK BIT(5)
78#define HDD_IPA_UC_STA_ENABLE_MASK BIT(6)
79#define HDD_IPA_REAL_TIME_DEBUGGING BIT(8)
80
Yun Parkf19e07d2015-11-20 11:34:27 -080081#define HDD_IPA_MAX_PENDING_EVENT_COUNT 20
82
tfyu0380a972017-07-13 18:19:37 +080083#define IPA_WLAN_RX_SOFTIRQ_THRESH 16
84
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -070085enum hdd_ipa_uc_op_code {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080086 HDD_IPA_UC_OPCODE_TX_SUSPEND = 0,
87 HDD_IPA_UC_OPCODE_TX_RESUME = 1,
88 HDD_IPA_UC_OPCODE_RX_SUSPEND = 2,
89 HDD_IPA_UC_OPCODE_RX_RESUME = 3,
90 HDD_IPA_UC_OPCODE_STATS = 4,
Yun Park637d6482016-10-05 10:51:33 -070091#ifdef FEATURE_METERING
92 HDD_IPA_UC_OPCODE_SHARING_STATS = 5,
93 HDD_IPA_UC_OPCODE_QUOTA_RSP = 6,
94 HDD_IPA_UC_OPCODE_QUOTA_IND = 7,
95#endif
Manikandan Mohan153a4c32017-02-16 15:04:30 -080096 HDD_IPA_UC_OPCODE_UC_READY = 8,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097 /* keep this last */
98 HDD_IPA_UC_OPCODE_MAX
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -070099};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100
101/**
102 * enum - Reason codes for stat query
103 *
104 * @HDD_IPA_UC_STAT_REASON_NONE: Initial value
105 * @HDD_IPA_UC_STAT_REASON_DEBUG: For debug/info
106 * @HDD_IPA_UC_STAT_REASON_BW_CAL: For bandwidth calibration
Yun Parkb187d542016-11-14 18:10:04 -0800107 * @HDD_IPA_UC_STAT_REASON_DUMP_INFO: For debug info dump
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108 */
109enum {
110 HDD_IPA_UC_STAT_REASON_NONE,
111 HDD_IPA_UC_STAT_REASON_DEBUG,
Yun Park46255682017-10-09 15:56:34 -0700112 HDD_IPA_UC_STAT_REASON_BW_CAL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800113};
114
115/**
116 * enum hdd_ipa_rm_state - IPA resource manager state
117 * @HDD_IPA_RM_RELEASED: PROD pipe resource released
118 * @HDD_IPA_RM_GRANT_PENDING: PROD pipe resource requested but not granted yet
119 * @HDD_IPA_RM_GRANTED: PROD pipe resource granted
120 */
121enum hdd_ipa_rm_state {
122 HDD_IPA_RM_RELEASED,
123 HDD_IPA_RM_GRANT_PENDING,
124 HDD_IPA_RM_GRANTED,
125};
126
127struct llc_snap_hdr {
128 uint8_t dsap;
129 uint8_t ssap;
130 uint8_t resv[4];
131 __be16 eth_type;
132} __packed;
133
Leo Chang3bc8fed2015-11-13 10:59:47 -0800134/**
135 * struct hdd_ipa_tx_hdr - header type which IPA should handle to TX packet
136 * @eth: ether II header
137 * @llc_snap: LLC snap header
138 *
139 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140struct hdd_ipa_tx_hdr {
141 struct ethhdr eth;
142 struct llc_snap_hdr llc_snap;
143} __packed;
144
Leo Chang3bc8fed2015-11-13 10:59:47 -0800145/**
146 * struct frag_header - fragment header type registered to IPA hardware
147 * @length: fragment length
148 * @reserved1: Reserved not used
149 * @reserved2: Reserved not used
150 *
151 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152struct frag_header {
Leo Chang3bc8fed2015-11-13 10:59:47 -0800153 uint16_t length;
154 uint32_t reserved1;
155 uint32_t reserved2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156} __packed;
157
Leo Chang3bc8fed2015-11-13 10:59:47 -0800158/**
159 * struct ipa_header - ipa header type registered to IPA hardware
160 * @vdev_id: vdev id
161 * @reserved: Reserved not used
162 *
163 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164struct ipa_header {
165 uint32_t
166 vdev_id:8, /* vdev_id field is LSB of IPA DESC */
167 reserved:24;
168} __packed;
169
Leo Chang3bc8fed2015-11-13 10:59:47 -0800170/**
171 * struct hdd_ipa_uc_tx_hdr - full tx header registered to IPA hardware
172 * @frag_hd: fragment header
173 * @ipa_hd: ipa header
174 * @eth: ether II header
175 *
176 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177struct hdd_ipa_uc_tx_hdr {
178 struct frag_header frag_hd;
179 struct ipa_header ipa_hd;
180 struct ethhdr eth;
181} __packed;
182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183/**
184 * struct hdd_ipa_cld_hdr - IPA CLD Header
185 * @reserved: reserved fields
186 * @iface_id: interface ID
187 * @sta_id: Station ID
188 *
189 * Packed 32-bit structure
190 * +----------+----------+--------------+--------+
191 * | Reserved | QCMAP ID | interface id | STA ID |
192 * +----------+----------+--------------+--------+
193 */
194struct hdd_ipa_cld_hdr {
195 uint8_t reserved[2];
196 uint8_t iface_id;
197 uint8_t sta_id;
198} __packed;
199
200struct hdd_ipa_rx_hdr {
201 struct hdd_ipa_cld_hdr cld_hdr;
202 struct ethhdr eth;
203} __packed;
204
205struct hdd_ipa_pm_tx_cb {
Leo Chang69c39692016-10-12 20:11:12 -0700206 bool exception;
Jeff Johnson49d45e62017-08-29 14:30:42 -0700207 struct hdd_adapter *adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 struct hdd_ipa_iface_context *iface_context;
Yun Park6c86a662017-10-05 16:09:15 -0700209 qdf_ipa_rx_data_t *ipa_tx_desc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210};
211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212struct hdd_ipa_sys_pipe {
213 uint32_t conn_hdl;
214 uint8_t conn_hdl_valid;
Yun Park6c86a662017-10-05 16:09:15 -0700215 qdf_ipa_sys_connect_params_t ipa_sys_params;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216};
217
218struct hdd_ipa_iface_stats {
219 uint64_t num_tx;
220 uint64_t num_tx_drop;
221 uint64_t num_tx_err;
222 uint64_t num_tx_cac_drop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 uint64_t num_rx_ipa_excep;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800224};
225
226struct hdd_ipa_priv;
227
228struct hdd_ipa_iface_context {
229 struct hdd_ipa_priv *hdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -0700230 struct hdd_adapter *adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 void *tl_context;
232
Yun Park6c86a662017-10-05 16:09:15 -0700233 qdf_ipa_client_type_t cons_client;
234 qdf_ipa_client_type_t prod_client;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235
236 uint8_t iface_id; /* This iface ID */
237 uint8_t sta_id; /* This iface station ID */
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530238 qdf_spinlock_t interface_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800239 uint32_t ifa_address;
240 struct hdd_ipa_iface_stats stats;
241};
242
243struct hdd_ipa_stats {
244 uint32_t event[IPA_WLAN_EVENT_MAX];
245 uint64_t num_send_msg;
246 uint64_t num_free_msg;
247
248 uint64_t num_rm_grant;
249 uint64_t num_rm_release;
250 uint64_t num_rm_grant_imm;
251 uint64_t num_cons_perf_req;
252 uint64_t num_prod_perf_req;
253
254 uint64_t num_rx_drop;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800255
Yun Park52b2b992016-09-22 15:49:51 -0700256 uint64_t num_tx_desc_q_cnt;
257 uint64_t num_tx_desc_error;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800258 uint64_t num_tx_comp_cnt;
259 uint64_t num_tx_queued;
260 uint64_t num_tx_dequeued;
261 uint64_t num_max_pm_queue;
262
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800263 uint64_t num_rx_excep;
Yun Parkb187d542016-11-14 18:10:04 -0800264 uint64_t num_tx_fwd_ok;
265 uint64_t num_tx_fwd_err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800266};
267
268struct ipa_uc_stas_map {
269 bool is_reserved;
270 uint8_t sta_id;
271};
272struct op_msg_type {
273 uint8_t msg_t;
274 uint8_t rsvd;
275 uint16_t op_code;
276 uint16_t len;
277 uint16_t rsvd_snd;
278};
279
280struct ipa_uc_fw_stats {
281 uint32_t tx_comp_ring_base;
282 uint32_t tx_comp_ring_size;
283 uint32_t tx_comp_ring_dbell_addr;
284 uint32_t tx_comp_ring_dbell_ind_val;
285 uint32_t tx_comp_ring_dbell_cached_val;
286 uint32_t tx_pkts_enqueued;
287 uint32_t tx_pkts_completed;
288 uint32_t tx_is_suspend;
289 uint32_t tx_reserved;
290 uint32_t rx_ind_ring_base;
291 uint32_t rx_ind_ring_size;
292 uint32_t rx_ind_ring_dbell_addr;
293 uint32_t rx_ind_ring_dbell_ind_val;
294 uint32_t rx_ind_ring_dbell_ind_cached_val;
295 uint32_t rx_ind_ring_rdidx_addr;
296 uint32_t rx_ind_ring_rd_idx_cached_val;
297 uint32_t rx_refill_idx;
298 uint32_t rx_num_pkts_indicated;
299 uint32_t rx_buf_refilled;
300 uint32_t rx_num_ind_drop_no_space;
301 uint32_t rx_num_ind_drop_no_buf;
302 uint32_t rx_is_suspend;
303 uint32_t rx_reserved;
304};
305
306struct ipa_uc_pending_event {
Anurag Chouhanffb21542016-02-17 14:33:03 +0530307 qdf_list_node_t node;
Jeff Johnson49d45e62017-08-29 14:30:42 -0700308 struct hdd_adapter *adapter;
Yun Park6c86a662017-10-05 16:09:15 -0700309 qdf_ipa_wlan_event_t type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310 uint8_t sta_id;
Anurag Chouhan6d760662016-02-20 16:05:43 +0530311 uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
Yun Parka4bb37c2017-12-08 16:14:22 -0800312 bool is_loading;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800313};
314
315/**
316 * struct uc_rm_work_struct
317 * @work: uC RM work
318 * @event: IPA RM event
319 */
320struct uc_rm_work_struct {
321 struct work_struct work;
Yun Park6c86a662017-10-05 16:09:15 -0700322 qdf_ipa_rm_event_t event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323};
324
325/**
326 * struct uc_op_work_struct
327 * @work: uC OP work
328 * @msg: OP message
329 */
330struct uc_op_work_struct {
331 struct work_struct work;
332 struct op_msg_type *msg;
333};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800334
335/**
336 * struct uc_rt_debug_info
337 * @time: system time
338 * @ipa_excep_count: IPA exception packet count
339 * @rx_drop_count: IPA Rx drop packet count
340 * @net_sent_count: IPA Rx packet sent to network stack count
341 * @rx_discard_count: IPA Rx discard packet count
Yun Parkb187d542016-11-14 18:10:04 -0800342 * @tx_fwd_ok_count: IPA Tx forward success packet count
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 * @tx_fwd_count: IPA Tx forward packet count
344 * @rx_destructor_call: IPA Rx packet destructor count
345 */
346struct uc_rt_debug_info {
Deepthi Gowri6acee342016-10-28 15:00:38 +0530347 uint64_t time;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800348 uint64_t ipa_excep_count;
349 uint64_t rx_drop_count;
350 uint64_t net_sent_count;
351 uint64_t rx_discard_count;
Yun Parkb187d542016-11-14 18:10:04 -0800352 uint64_t tx_fwd_ok_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800353 uint64_t tx_fwd_count;
354 uint64_t rx_destructor_call;
355};
356
Yun Park637d6482016-10-05 10:51:33 -0700357#ifdef FEATURE_METERING
358struct ipa_uc_sharing_stats {
359 uint64_t ipv4_rx_packets;
360 uint64_t ipv4_rx_bytes;
361 uint64_t ipv6_rx_packets;
362 uint64_t ipv6_rx_bytes;
363 uint64_t ipv4_tx_packets;
364 uint64_t ipv4_tx_bytes;
365 uint64_t ipv6_tx_packets;
366 uint64_t ipv6_tx_bytes;
367};
368
369struct ipa_uc_quota_rsp {
370 uint8_t success;
371 uint8_t reserved[3];
372 uint32_t quota_lo; /* quota limit low bytes */
373 uint32_t quota_hi; /* quota limit high bytes */
374};
375
376struct ipa_uc_quota_ind {
377 uint64_t quota_bytes; /* quota limit in bytes */
378};
379#endif
380
Yun Park52b2b992016-09-22 15:49:51 -0700381/**
382 * struct hdd_ipa_tx_desc
383 * @link: link to list head
384 * @priv: pointer to priv list entry
385 * @id: Tx desc idex
386 * @ipa_tx_desc_ptr: pointer to IPA Tx descriptor
387 */
388struct hdd_ipa_tx_desc {
389 struct list_head link;
390 void *priv;
391 uint32_t id;
Yun Park6c86a662017-10-05 16:09:15 -0700392 qdf_ipa_rx_data_t *ipa_tx_desc_ptr;
Yun Park52b2b992016-09-22 15:49:51 -0700393};
394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395struct hdd_ipa_priv {
396 struct hdd_ipa_sys_pipe sys_pipe[HDD_IPA_MAX_SYSBAM_PIPE];
397 struct hdd_ipa_iface_context iface_context[HDD_IPA_MAX_IFACE];
398 uint8_t num_iface;
399 enum hdd_ipa_rm_state rm_state;
400 /*
Nirav Shahcbc6d722016-03-01 16:24:53 +0530401 * IPA driver can send RM notifications with IRQ disabled so using qdf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 * APIs as it is taken care gracefully. Without this, kernel would throw
403 * an warning if spin_lock_bh is used while IRQ is disabled
404 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530405 qdf_spinlock_t rm_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406 struct uc_rm_work_struct uc_rm_work;
407 struct uc_op_work_struct uc_op_work[HDD_IPA_UC_OPCODE_MAX];
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530408 qdf_wake_lock_t wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800409 struct delayed_work wake_lock_work;
410 bool wake_lock_released;
411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412 atomic_t tx_ref_cnt;
Nirav Shahcbc6d722016-03-01 16:24:53 +0530413 qdf_nbuf_queue_t pm_queue_head;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800414 struct work_struct pm_work;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530415 qdf_spinlock_t pm_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800416 bool suspended;
417
Yun Park52b2b992016-09-22 15:49:51 -0700418 qdf_spinlock_t q_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 struct list_head pend_desc_head;
Yun Park52b2b992016-09-22 15:49:51 -0700421 struct hdd_ipa_tx_desc *tx_desc_list;
422 struct list_head free_tx_desc_head;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800423
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700424 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 struct hdd_ipa_stats stats;
426
427 struct notifier_block ipv4_notifier;
428 uint32_t curr_prod_bw;
429 uint32_t curr_cons_bw;
430
431 uint8_t activated_fw_pipe;
432 uint8_t sap_num_connected_sta;
433 uint8_t sta_connected;
434 uint32_t tx_pipe_handle;
435 uint32_t rx_pipe_handle;
436 bool resource_loading;
437 bool resource_unloading;
438 bool pending_cons_req;
439 struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT];
Anurag Chouhanffb21542016-02-17 14:33:03 +0530440 qdf_list_t pending_event;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530441 qdf_mutex_t event_lock;
Leo Change3e49442015-10-26 20:07:13 -0700442 bool ipa_pipes_down;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 uint32_t ipa_tx_packets_diff;
444 uint32_t ipa_rx_packets_diff;
445 uint32_t ipa_p_tx_packets;
446 uint32_t ipa_p_rx_packets;
447 uint32_t stat_req_reason;
448 uint64_t ipa_tx_forward;
449 uint64_t ipa_rx_discard;
450 uint64_t ipa_rx_net_send_count;
Yun Park46255682017-10-09 15:56:34 -0700451 uint64_t ipa_rx_internal_drop_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800452 uint64_t ipa_rx_destructor_count;
Anurag Chouhan210db072016-02-22 18:42:15 +0530453 qdf_mc_timer_t rt_debug_timer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 struct uc_rt_debug_info rt_bug_buffer[HDD_IPA_UC_RT_DEBUG_BUF_COUNT];
455 unsigned int rt_buf_fill_index;
Yun Park6c86a662017-10-05 16:09:15 -0700456 qdf_ipa_wdi_in_params_t cons_pipe_in;
457 qdf_ipa_wdi_in_params_t prod_pipe_in;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800458 bool uc_loaded;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800459 bool wdi_enabled;
Anurag Chouhan210db072016-02-22 18:42:15 +0530460 qdf_mc_timer_t rt_debug_fill_timer;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530461 qdf_mutex_t rt_debug_lock;
462 qdf_mutex_t ipa_lock;
Yun Parkb4f591d2017-03-29 15:51:01 -0700463
Prakash Dhavali89d406d2016-11-23 11:11:00 -0800464 uint8_t vdev_to_iface[CSR_ROAM_SESSION_MAX];
465 bool vdev_offload_enabled[CSR_ROAM_SESSION_MAX];
Yun Park637d6482016-10-05 10:51:33 -0700466#ifdef FEATURE_METERING
467 struct ipa_uc_sharing_stats ipa_sharing_stats;
468 struct ipa_uc_quota_rsp ipa_quota_rsp;
469 struct ipa_uc_quota_ind ipa_quota_ind;
470 struct completion ipa_uc_sharing_stats_comp;
471 struct completion ipa_uc_set_quota_comp;
472#endif
Yun Park777d7242017-03-30 15:38:33 -0700473 struct completion ipa_resource_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474};
475
Leo Changcc923e22016-06-16 15:29:03 -0700476#define HDD_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header)
477#define HDD_IPA_WLAN_IPA_HEADER sizeof(struct ipa_header)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478#define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr)
479#define HDD_IPA_UC_WLAN_CLD_HDR_LEN 0
480#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_tx_hdr)
481#define HDD_IPA_UC_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_uc_tx_hdr)
482#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr)
Leo Changcc923e22016-06-16 15:29:03 -0700483#define HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET \
484 (HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485
486#define HDD_IPA_GET_IFACE_ID(_data) \
487 (((struct hdd_ipa_cld_hdr *) (_data))->iface_id)
488
489#define HDD_IPA_LOG(LVL, fmt, args ...) \
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530490 QDF_TRACE(QDF_MODULE_ID_HDD, LVL, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800491 "%s:%d: "fmt, __func__, __LINE__, ## args)
492
Govind Singhb6a89772016-08-12 11:23:35 +0530493#define HDD_IPA_DP_LOG(LVL, fmt, args...) \
494 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, LVL, \
495 "%s:%d: "fmt, __func__, __LINE__, ## args)
496
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497#define HDD_IPA_DBG_DUMP(_lvl, _prefix, _buf, _len) \
498 do { \
Yun Parkec845302016-12-15 09:22:57 -0800499 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, _lvl, "%s:", _prefix); \
500 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD_DATA, _lvl, _buf, _len); \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501 } while (0)
502
503#define HDD_IPA_IS_CONFIG_ENABLED(_hdd_ctx, _mask) \
504 (((_hdd_ctx)->config->IpaConfig & (_mask)) == (_mask))
505
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
507
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -0700508#if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
Leo Chang63d73612016-10-18 18:09:43 -0700509#define HDD_IPA_CHECK_HW() ipa_uc_reg_rdyCB(NULL)
Leo Chang3bc8fed2015-11-13 10:59:47 -0800510#else
511/* Do nothing */
Leo Chang63d73612016-10-18 18:09:43 -0700512#define HDD_IPA_CHECK_HW() 0
Leo Chang07b28f62016-05-11 12:29:22 -0700513#endif /* IPA3 */
Leo Chang3bc8fed2015-11-13 10:59:47 -0800514
Yun Park0dad1002017-07-14 14:57:01 -0700515#define HDD_IPA_DBG_DUMP_RX_LEN 84
Yun Parkb187d542016-11-14 18:10:04 -0800516#define HDD_IPA_DBG_DUMP_TX_LEN 48
517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518static struct hdd_ipa_adapter_2_client {
Yun Park6c86a662017-10-05 16:09:15 -0700519 qdf_ipa_client_type_t cons_client;
520 qdf_ipa_client_type_t prod_client;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521} hdd_ipa_adapter_2_client[HDD_IPA_MAX_IFACE] = {
522 {
523 IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD
524 }, {
525 IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD
526 }, {
527 IPA_CLIENT_WLAN4_CONS, IPA_CLIENT_WLAN1_PROD
528 },
529};
530
Yun Park637d6482016-10-05 10:51:33 -0700531#ifdef FEATURE_METERING
532#define IPA_UC_SHARING_STATES_WAIT_TIME 500
533#define IPA_UC_SET_QUOTA_WAIT_TIME 500
534#endif
535
Yun Park777d7242017-03-30 15:38:33 -0700536#define IPA_RESOURCE_COMP_WAIT_TIME 100
537
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538static struct hdd_ipa_priv *ghdd_ipa;
539
540/* Local Function Prototypes */
Yun Park6c86a662017-10-05 16:09:15 -0700541static void hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 unsigned long data);
Yun Park6c86a662017-10-05 16:09:15 -0700543static void hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544 unsigned long data);
Yun Parkb4f591d2017-03-29 15:51:01 -0700545#ifdef FEATURE_METERING
Yun Park6c86a662017-10-05 16:09:15 -0700546static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Parkb4f591d2017-03-29 15:51:01 -0700547 void *data);
548#else
549static void hdd_ipa_wdi_meter_notifier_cb(void);
550#endif
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800551static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552
553static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context);
Yun Parka4bb37c2017-12-08 16:14:22 -0800554static void hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa,
555 bool is_loading);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800557#if ((defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)) || \
558 defined(IPA_CLIENT_IS_MHI_CONS))
559/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800560 * hdd_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
561 * @priv_ctxt: hdd ipa local context
562 *
563 * Will be called by IPA context.
564 * It's atomic context, then should be scheduled to kworker thread
565 *
566 * Return: None
567 */
568static void hdd_ipa_uc_loaded_uc_cb(void *priv_ctxt)
569{
570 struct hdd_ipa_priv *hdd_ipa;
571 struct op_msg_type *msg;
572 struct uc_op_work_struct *uc_op_work;
573
574 if (priv_ctxt == NULL) {
575 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Invalid IPA context");
576 return;
577 }
578
579 hdd_ipa = (struct hdd_ipa_priv *)priv_ctxt;
580 msg = (struct op_msg_type *)qdf_mem_malloc(sizeof(*msg));
581 if (!msg) {
582 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "op_msg allocation fails");
583 return;
584 }
585
586 msg->op_code = HDD_IPA_UC_OPCODE_UC_READY;
587
588 uc_op_work = &hdd_ipa->uc_op_work[msg->op_code];
589
590 /* When the same uC OPCODE is already pended, just return */
591 if (uc_op_work->msg)
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530592 goto done;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800593
594 uc_op_work->msg = msg;
595 schedule_work(&uc_op_work->work);
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530596
jiadd91a6842017-08-01 14:46:02 +0800597 /* work handler will free the msg buffer */
598 return;
599
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530600done:
601 qdf_mem_free(msg);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800602}
603
604/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800605 * hdd_ipa_uc_send_wdi_control_msg() - Set WDI control message
606 * @ctrl: WDI control value
607 *
608 * Send WLAN_WDI_ENABLE for ctrl = true and WLAN_WDI_DISABLE otherwise.
609 *
610 * Return: 0 on message send to ipa, -1 on failure
611 */
612static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
613{
Yun Park6c86a662017-10-05 16:09:15 -0700614 qdf_ipa_msg_meta_t meta;
615 qdf_ipa_wlan_msg_t *ipa_msg;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800616 int ret = 0;
617
618 /* WDI enable message to IPA */
Yun Park6c86a662017-10-05 16:09:15 -0700619 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
620 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800621 if (ipa_msg == NULL) {
622 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
623 "msg allocation failed");
624 return -ENOMEM;
625 }
626
627 if (ctrl == true)
Yun Park6c86a662017-10-05 16:09:15 -0700628 QDF_IPA_MSG_META_MSG_TYPE(&meta) = WLAN_WDI_ENABLE;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800629 else
Yun Park6c86a662017-10-05 16:09:15 -0700630 QDF_IPA_MSG_META_MSG_TYPE(&meta) = WLAN_WDI_DISABLE;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800631
Srinivas Girigowda97852372017-03-06 16:52:59 -0800632 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park6c86a662017-10-05 16:09:15 -0700633 "ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
634 ret = qdf_ipa_send_msg(&meta, ipa_msg, hdd_ipa_msg_free_fn);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800635 if (ret) {
636 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
637 "ipa_send_msg(Evt:%d)-fail=%d",
Yun Park6c86a662017-10-05 16:09:15 -0700638 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800639 qdf_mem_free(ipa_msg);
640 }
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800641 return ret;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800642}
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800643
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800644/**
645 * hdd_ipa_uc_register_uc_ready() - Register UC ready callback function to IPA
646 * @hdd_ipa: HDD IPA local context
647 *
648 * Register IPA UC ready callback function to IPA kernel driver
649 * Even IPA UC loaded later than WLAN kernel driver, WLAN kernel driver will
650 * open WDI pipe after WLAN driver loading finished
651 *
652 * Return: 0 Success
653 * -EPERM Registration fail
654 */
655static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
656{
Yun Park6c86a662017-10-05 16:09:15 -0700657 qdf_ipa_wdi_uc_ready_params_t uc_ready_param;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800658 int ret = 0;
659
660 hdd_ipa->uc_loaded = false;
Yun Park6c86a662017-10-05 16:09:15 -0700661 QDF_IPA_UC_READY_PARAMS_PRIV(&uc_ready_param) = (void *)hdd_ipa;
662 QDF_IPA_UC_READY_PARAMS_NOTIFY(&uc_ready_param) =
663 hdd_ipa_uc_loaded_uc_cb;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800664 if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
665 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
666 "UC Ready CB register fail");
667 return -EPERM;
668 }
Yun Park6c86a662017-10-05 16:09:15 -0700669 if (false != QDF_IPA_UC_READY_PARAMS_IS_UC_READY(&uc_ready_param)) {
Srinivas Girigowda2b5d47c2017-03-29 00:28:46 -0700670 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800671 hdd_ipa->uc_loaded = true;
672 } else {
673 ret = hdd_ipa_uc_send_wdi_control_msg(false);
674 }
675
676 return ret;
677}
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800678#else
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800679static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
680{
681 hdd_ipa->uc_loaded = true;
682 return 0;
683}
684
685static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
686{
687 return 0;
688}
689#endif
690
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691/**
692 * hdd_ipa_is_enabled() - Is IPA enabled?
693 * @hdd_ctx: Global HDD context
694 *
695 * Return: true if IPA is enabled, false otherwise
696 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700697bool hdd_ipa_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698{
699 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_ENABLE_MASK);
700}
701
702/**
703 * hdd_ipa_uc_is_enabled() - Is IPA uC offload enabled?
704 * @hdd_ctx: Global HDD context
705 *
706 * Return: true if IPA uC offload is enabled, false otherwise
707 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700708bool hdd_ipa_uc_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709{
710 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_ENABLE_MASK);
711}
712
713/**
714 * hdd_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
715 * @hdd_ctx: Global HDD context
716 *
717 * Return: true if STA mode IPA uC offload is enabled, false otherwise
718 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700719static inline bool hdd_ipa_uc_sta_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720{
721 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_STA_ENABLE_MASK);
722}
723
724/**
Guolei Bianca144d82016-11-10 11:07:42 +0800725 * hdd_ipa_uc_sta_reset_sta_connected() - Reset sta_connected flag
726 * @hdd_ipa: Global HDD IPA context
727 *
728 * Return: None
729 */
Guolei Bianca144d82016-11-10 11:07:42 +0800730static inline void hdd_ipa_uc_sta_reset_sta_connected(
731 struct hdd_ipa_priv *hdd_ipa)
732{
Yun Park637d6482016-10-05 10:51:33 -0700733 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Guolei Bianca144d82016-11-10 11:07:42 +0800734 hdd_ipa->sta_connected = 0;
Yun Park637d6482016-10-05 10:51:33 -0700735 qdf_mutex_release(&hdd_ipa->ipa_lock);
Guolei Bianca144d82016-11-10 11:07:42 +0800736}
Guolei Bianca144d82016-11-10 11:07:42 +0800737
738/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739 * hdd_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
740 * @hdd_ipa: Global HDD IPA context
741 *
742 * Return: true if pre-filter is enabled, otherwise false
743 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700744static inline bool hdd_ipa_is_pre_filter_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745{
746 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx,
747 HDD_IPA_PRE_FILTER_ENABLE_MASK);
748}
749
750/**
751 * hdd_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
752 * @hdd_ipa: Global HDD IPA context
753 *
754 * Return: true if IPv6 is enabled, otherwise false
755 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700756static inline bool hdd_ipa_is_ipv6_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757{
758 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_IPV6_ENABLE_MASK);
759}
760
761/**
762 * hdd_ipa_is_rm_enabled() - Is IPA resource manager enabled?
763 * @hdd_ipa: Global HDD IPA context
764 *
765 * Return: true if resource manager is enabled, otherwise false
766 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700767static inline bool hdd_ipa_is_rm_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800768{
769 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_RM_ENABLE_MASK);
770}
771
772/**
773 * hdd_ipa_is_rt_debugging_enabled() - Is IPA real-time debug enabled?
774 * @hdd_ipa: Global HDD IPA context
775 *
776 * Return: true if resource manager is enabled, otherwise false
777 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700778static inline bool hdd_ipa_is_rt_debugging_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779{
780 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_REAL_TIME_DEBUGGING);
781}
782
783/**
784 * hdd_ipa_is_clk_scaling_enabled() - Is IPA clock scaling enabled?
785 * @hdd_ipa: Global HDD IPA context
786 *
787 * Return: true if clock scaling is enabled, otherwise false
788 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700789static inline bool hdd_ipa_is_clk_scaling_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790{
791 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx,
792 HDD_IPA_CLK_SCALING_ENABLE_MASK |
793 HDD_IPA_RM_ENABLE_MASK);
794}
795
796/**
797 * hdd_ipa_uc_rt_debug_host_fill - fill rt debug buffer
798 * @ctext: pointer to hdd context.
799 *
800 * If rt debug enabled, periodically called, and fill debug buffer
801 *
802 * Return: none
803 */
804static void hdd_ipa_uc_rt_debug_host_fill(void *ctext)
805{
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700806 struct hdd_context *hdd_ctx = (struct hdd_context *)ctext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 struct hdd_ipa_priv *hdd_ipa;
808 struct uc_rt_debug_info *dump_info = NULL;
809
810 if (wlan_hdd_validate_context(hdd_ctx))
811 return;
812
813 if (!hdd_ctx->hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700814 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "IPA UC is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 return;
816 }
817
818 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
819
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530820 qdf_mutex_acquire(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 dump_info = &hdd_ipa->rt_bug_buffer[
822 hdd_ipa->rt_buf_fill_index % HDD_IPA_UC_RT_DEBUG_BUF_COUNT];
823
Deepthi Gowri6acee342016-10-28 15:00:38 +0530824 dump_info->time = (uint64_t)qdf_mc_timer_get_system_time();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 dump_info->ipa_excep_count = hdd_ipa->stats.num_rx_excep;
Yun Park46255682017-10-09 15:56:34 -0700826 dump_info->rx_drop_count = hdd_ipa->ipa_rx_internal_drop_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 dump_info->net_sent_count = hdd_ipa->ipa_rx_net_send_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 dump_info->tx_fwd_count = hdd_ipa->ipa_tx_forward;
Yun Parkb187d542016-11-14 18:10:04 -0800829 dump_info->tx_fwd_ok_count = hdd_ipa->stats.num_tx_fwd_ok;
830 dump_info->rx_discard_count = hdd_ipa->ipa_rx_discard;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800831 dump_info->rx_destructor_call = hdd_ipa->ipa_rx_destructor_count;
832 hdd_ipa->rt_buf_fill_index++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530833 qdf_mutex_release(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834
Anurag Chouhan210db072016-02-22 18:42:15 +0530835 qdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836 HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
837}
838
839/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700840 * __hdd_ipa_uc_rt_debug_host_dump - dump rt debug buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 * @hdd_ctx: pointer to hdd context.
842 *
843 * If rt debug enabled, dump debug buffer contents based on requirement
844 *
845 * Return: none
846 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700847static void __hdd_ipa_uc_rt_debug_host_dump(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848{
849 struct hdd_ipa_priv *hdd_ipa;
850 unsigned int dump_count;
851 unsigned int dump_index;
852 struct uc_rt_debug_info *dump_info = NULL;
853
854 if (wlan_hdd_validate_context(hdd_ctx))
855 return;
856
857 hdd_ipa = hdd_ctx->hdd_ipa;
858 if (!hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700859 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "IPA UC is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800860 return;
861 }
862
Chris Guo1751acf2017-07-03 14:09:01 +0800863 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
864 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -0700865 "IPA RT debug is not enabled");
Chris Guo1751acf2017-07-03 14:09:01 +0800866 return;
867 }
868
Yun Park46255682017-10-09 15:56:34 -0700869 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870 "========= WLAN-IPA DEBUG BUF DUMP ==========\n");
Yun Park46255682017-10-09 15:56:34 -0700871 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Parkb187d542016-11-14 18:10:04 -0800872 " TM : EXEP : DROP : NETS : FWOK : TXFD : DSTR : DSCD\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530874 qdf_mutex_acquire(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 for (dump_count = 0;
876 dump_count < HDD_IPA_UC_RT_DEBUG_BUF_COUNT;
877 dump_count++) {
878 dump_index = (hdd_ipa->rt_buf_fill_index + dump_count) %
879 HDD_IPA_UC_RT_DEBUG_BUF_COUNT;
880 dump_info = &hdd_ipa->rt_bug_buffer[dump_index];
Yun Park46255682017-10-09 15:56:34 -0700881 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Deepthi Gowri6acee342016-10-28 15:00:38 +0530882 "%12llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883 dump_info->time, dump_info->ipa_excep_count,
884 dump_info->rx_drop_count, dump_info->net_sent_count,
Yun Parkb187d542016-11-14 18:10:04 -0800885 dump_info->tx_fwd_ok_count, dump_info->tx_fwd_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 dump_info->rx_destructor_call,
887 dump_info->rx_discard_count);
888 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530889 qdf_mutex_release(&hdd_ipa->rt_debug_lock);
Yun Park46255682017-10-09 15:56:34 -0700890 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891 "======= WLAN-IPA DEBUG BUF DUMP END ========\n");
892}
893
894/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700895 * hdd_ipa_uc_rt_debug_host_dump - SSR wrapper for
896 * __hdd_ipa_uc_rt_debug_host_dump
897 * @hdd_ctx: pointer to hdd context.
898 *
899 * If rt debug enabled, dump debug buffer contents based on requirement
900 *
901 * Return: none
902 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700903void hdd_ipa_uc_rt_debug_host_dump(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700904{
905 cds_ssr_protect(__func__);
906 __hdd_ipa_uc_rt_debug_host_dump(hdd_ctx);
907 cds_ssr_unprotect(__func__);
908}
909
910/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911 * hdd_ipa_uc_rt_debug_handler - periodic memory health monitor handler
912 * @ctext: pointer to hdd context.
913 *
914 * periodically called by timer expire
915 * will try to alloc dummy memory and detect out of memory condition
916 * if out of memory detected, dump wlan-ipa stats
917 *
918 * Return: none
919 */
920static void hdd_ipa_uc_rt_debug_handler(void *ctext)
921{
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700922 struct hdd_context *hdd_ctx = (struct hdd_context *)ctext;
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700923 struct hdd_ipa_priv *hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800924 void *dummy_ptr = NULL;
925
926 if (wlan_hdd_validate_context(hdd_ctx))
927 return;
928
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700929 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700932 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
933 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 return;
935 }
936
937 /* Allocate dummy buffer periodically and free immediately. this will
938 * proactively detect OOM and if allocation fails dump ipa stats
939 */
940 dummy_ptr = kmalloc(HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE,
941 GFP_KERNEL | GFP_ATOMIC);
942 if (!dummy_ptr) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943 hdd_ipa_uc_rt_debug_host_dump(hdd_ctx);
944 hdd_ipa_uc_stat_request(
Yun Park637d6482016-10-05 10:51:33 -0700945 hdd_get_adapter(hdd_ctx, QDF_SAP_MODE),
946 HDD_IPA_UC_STAT_REASON_DEBUG);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947 } else {
948 kfree(dummy_ptr);
949 }
950
Anurag Chouhan210db072016-02-22 18:42:15 +0530951 qdf_mc_timer_start(&hdd_ipa->rt_debug_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 HDD_IPA_UC_RT_DEBUG_PERIOD);
953}
954
955/**
Yun Parkb187d542016-11-14 18:10:04 -0800956 * hdd_ipa_uc_rt_debug_destructor() - called by data packet free
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 * @skb: packet pinter
958 *
959 * when free data packet, will be invoked by wlan client and will increase
960 * free counter
961 *
962 * Return: none
963 */
Jeff Johnsond7720632016-10-05 16:04:32 -0700964static void hdd_ipa_uc_rt_debug_destructor(struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800965{
966 if (!ghdd_ipa) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700967 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "invalid hdd context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 return;
969 }
970
971 ghdd_ipa->ipa_rx_destructor_count++;
972}
973
974/**
Yun Parkb187d542016-11-14 18:10:04 -0800975 * hdd_ipa_uc_rt_debug_deinit() - remove resources to handle rt debugging
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 * @hdd_ctx: hdd main context
977 *
978 * free all rt debugging resources
979 *
980 * Return: none
981 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700982static void hdd_ipa_uc_rt_debug_deinit(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800983{
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700984 struct hdd_ipa_priv *hdd_ipa;
985
986 if (wlan_hdd_validate_context(hdd_ctx))
987 return;
988
989 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800990
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530991 qdf_mutex_destroy(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
993 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700994 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
995 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996 return;
997 }
998
Anurag Chouhan210db072016-02-22 18:42:15 +0530999 if (QDF_TIMER_STATE_STOPPED !=
Prakash Dhavali169de302016-11-30 12:52:49 -08001000 qdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_fill_timer)) {
1001 qdf_mc_timer_stop(&hdd_ipa->rt_debug_fill_timer);
1002 }
1003 qdf_mc_timer_destroy(&hdd_ipa->rt_debug_fill_timer);
1004
1005 if (QDF_TIMER_STATE_STOPPED !=
Anurag Chouhan210db072016-02-22 18:42:15 +05301006 qdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_timer)) {
1007 qdf_mc_timer_stop(&hdd_ipa->rt_debug_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008 }
Anurag Chouhan210db072016-02-22 18:42:15 +05301009 qdf_mc_timer_destroy(&hdd_ipa->rt_debug_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010}
1011
1012/**
Yun Parkb187d542016-11-14 18:10:04 -08001013 * hdd_ipa_uc_rt_debug_init() - intialize resources to handle rt debugging
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001014 * @hdd_ctx: hdd main context
1015 *
1016 * alloc and initialize all rt debugging resources
1017 *
1018 * Return: none
1019 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001020static void hdd_ipa_uc_rt_debug_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001022 struct hdd_ipa_priv *hdd_ipa;
1023
Chris Guo1751acf2017-07-03 14:09:01 +08001024 if (wlan_hdd_validate_context_in_loading(hdd_ctx))
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001025 return;
1026
1027 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001028
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301029 qdf_mutex_create(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030 hdd_ipa->rt_buf_fill_index = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301031 qdf_mem_zero(hdd_ipa->rt_bug_buffer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032 sizeof(struct uc_rt_debug_info) *
1033 HDD_IPA_UC_RT_DEBUG_BUF_COUNT);
1034 hdd_ipa->ipa_tx_forward = 0;
1035 hdd_ipa->ipa_rx_discard = 0;
1036 hdd_ipa->ipa_rx_net_send_count = 0;
Yun Park46255682017-10-09 15:56:34 -07001037 hdd_ipa->ipa_rx_internal_drop_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 hdd_ipa->ipa_rx_destructor_count = 0;
1039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 /* Reatime debug enable on feature enable */
1041 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -07001042 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
1043 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 return;
1045 }
Yun Parkdfc1da52016-11-15 14:50:11 -08001046
1047 qdf_mc_timer_init(&hdd_ipa->rt_debug_fill_timer, QDF_TIMER_TYPE_SW,
1048 hdd_ipa_uc_rt_debug_host_fill, (void *)hdd_ctx);
1049 qdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer,
1050 HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
1051
Anurag Chouhan210db072016-02-22 18:42:15 +05301052 qdf_mc_timer_init(&hdd_ipa->rt_debug_timer, QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 hdd_ipa_uc_rt_debug_handler, (void *)hdd_ctx);
Anurag Chouhan210db072016-02-22 18:42:15 +05301054 qdf_mc_timer_start(&hdd_ipa->rt_debug_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001055 HDD_IPA_UC_RT_DEBUG_PERIOD);
1056
1057}
1058
1059/**
Yun Parkb187d542016-11-14 18:10:04 -08001060 * hdd_ipa_dump_hdd_ipa() - dump entries in HDD IPA struct
1061 * @hdd_ipa: HDD IPA struct
1062 *
1063 * Dump entries in struct hdd_ipa
1064 *
1065 * Return: none
1066 */
1067static void hdd_ipa_dump_hdd_ipa(struct hdd_ipa_priv *hdd_ipa)
1068{
1069 int i;
1070
1071 /* HDD IPA */
Yun Park46255682017-10-09 15:56:34 -07001072 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1073 "\n==== HDD IPA ====\n"
Yun Parkb187d542016-11-14 18:10:04 -08001074 "num_iface: %d\n"
1075 "rm_state: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001076 "rm_lock: %pK\n"
1077 "uc_rm_work: %pK\n"
1078 "uc_op_work: %pK\n"
1079 "wake_lock: %pK\n"
1080 "wake_lock_work: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001081 "wake_lock_released: %d\n"
Yun Parkb187d542016-11-14 18:10:04 -08001082 "tx_ref_cnt: %d\n"
1083 "pm_queue_head----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001084 "\thead: %pK\n"
1085 "\ttail: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001086 "\tqlen: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001087 "pm_work: %pK\n"
1088 "pm_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001089 "suspended: %d\n",
1090 hdd_ipa->num_iface,
1091 hdd_ipa->rm_state,
1092 &hdd_ipa->rm_lock,
1093 &hdd_ipa->uc_rm_work,
1094 &hdd_ipa->uc_op_work,
1095 &hdd_ipa->wake_lock,
1096 &hdd_ipa->wake_lock_work,
1097 hdd_ipa->wake_lock_released,
Yun Parkb187d542016-11-14 18:10:04 -08001098 hdd_ipa->tx_ref_cnt.counter,
1099 hdd_ipa->pm_queue_head.head,
1100 hdd_ipa->pm_queue_head.tail,
1101 hdd_ipa->pm_queue_head.qlen,
1102 &hdd_ipa->pm_work,
1103 &hdd_ipa->pm_lock,
1104 hdd_ipa->suspended);
Yun Park46255682017-10-09 15:56:34 -07001105
1106 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1107 "\nq_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001108 "pend_desc_head----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001109 "\tnext: %pK\n"
1110 "\tprev: %pK\n"
1111 "hdd_ctx: %pK\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001112 "stats: %pK\n"
1113 "ipv4_notifier: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001114 "curr_prod_bw: %d\n"
1115 "curr_cons_bw: %d\n"
1116 "activated_fw_pipe: %d\n"
1117 "sap_num_connected_sta: %d\n"
1118 "sta_connected: %d\n",
Yun Parkb187d542016-11-14 18:10:04 -08001119 &hdd_ipa->q_lock,
Yun Parkb187d542016-11-14 18:10:04 -08001120 hdd_ipa->pend_desc_head.next,
1121 hdd_ipa->pend_desc_head.prev,
1122 hdd_ipa->hdd_ctx,
Yun Parkb187d542016-11-14 18:10:04 -08001123 &hdd_ipa->stats,
1124 &hdd_ipa->ipv4_notifier,
1125 hdd_ipa->curr_prod_bw,
1126 hdd_ipa->curr_cons_bw,
1127 hdd_ipa->activated_fw_pipe,
1128 hdd_ipa->sap_num_connected_sta,
Yun Park46255682017-10-09 15:56:34 -07001129 (unsigned int)hdd_ipa->sta_connected);
1130
1131 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1132 "\ntx_pipe_handle: 0x%x\n"
Yun Parkb187d542016-11-14 18:10:04 -08001133 "rx_pipe_handle: 0x%x\n"
1134 "resource_loading: %d\n"
1135 "resource_unloading: %d\n"
1136 "pending_cons_req: %d\n"
1137 "pending_event----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001138 "\tanchor.next: %pK\n"
1139 "\tanchor.prev: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001140 "\tcount: %d\n"
1141 "\tmax_size: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001142 "event_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001143 "ipa_tx_packets_diff: %d\n"
1144 "ipa_rx_packets_diff: %d\n"
1145 "ipa_p_tx_packets: %d\n"
1146 "ipa_p_rx_packets: %d\n"
1147 "stat_req_reason: %d\n",
1148 hdd_ipa->tx_pipe_handle,
1149 hdd_ipa->rx_pipe_handle,
1150 hdd_ipa->resource_loading,
1151 hdd_ipa->resource_unloading,
1152 hdd_ipa->pending_cons_req,
1153 hdd_ipa->pending_event.anchor.next,
1154 hdd_ipa->pending_event.anchor.prev,
1155 hdd_ipa->pending_event.count,
1156 hdd_ipa->pending_event.max_size,
1157 &hdd_ipa->event_lock,
1158 hdd_ipa->ipa_tx_packets_diff,
1159 hdd_ipa->ipa_rx_packets_diff,
1160 hdd_ipa->ipa_p_tx_packets,
1161 hdd_ipa->ipa_p_rx_packets,
1162 hdd_ipa->stat_req_reason);
1163
Yun Park46255682017-10-09 15:56:34 -07001164 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1165 "\ncons_pipe_in----\n"
1166 "\tsys: %pK\n"
1167 "\tdl.comp_ring_base_pa: 0x%x\n"
1168 "\tdl.comp_ring_size: %d\n"
1169 "\tdl.ce_ring_base_pa: 0x%x\n"
1170 "\tdl.ce_door_bell_pa: 0x%x\n"
1171 "\tdl.ce_ring_size: %d\n"
1172 "\tdl.num_tx_buffers: %d\n"
1173 "prod_pipe_in----\n"
1174 "\tsys: %pK\n"
1175 "\tul.rdy_ring_base_pa: 0x%x\n"
1176 "\tul.rdy_ring_size: %d\n"
1177 "\tul.rdy_ring_rp_pa: 0x%x\n"
1178 "uc_loaded: %d\n"
1179 "wdi_enabled: %d\n"
1180 "rt_debug_fill_timer: %pK\n"
1181 "rt_debug_lock: %pK\n"
1182 "ipa_lock: %pK\n",
1183 &hdd_ipa->cons_pipe_in.sys,
1184 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.comp_ring_base_pa,
1185 hdd_ipa->cons_pipe_in.u.dl.comp_ring_size,
1186 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.ce_ring_base_pa,
1187 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.ce_door_bell_pa,
1188 hdd_ipa->cons_pipe_in.u.dl.ce_ring_size,
1189 hdd_ipa->cons_pipe_in.u.dl.num_tx_buffers,
1190 &hdd_ipa->prod_pipe_in.sys,
1191 (unsigned int)hdd_ipa->prod_pipe_in.u.ul.rdy_ring_base_pa,
1192 hdd_ipa->prod_pipe_in.u.ul.rdy_ring_size,
1193 (unsigned int)hdd_ipa->prod_pipe_in.u.ul.rdy_ring_rp_pa,
1194 hdd_ipa->uc_loaded,
1195 hdd_ipa->wdi_enabled,
1196 &hdd_ipa->rt_debug_fill_timer,
1197 &hdd_ipa->rt_debug_lock,
1198 &hdd_ipa->ipa_lock);
1199
1200 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1201 "\nvdev_to_iface----");
1202 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
1203 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1204 "\n\t[%d]=%d", i, hdd_ipa->vdev_to_iface[i]);
1205 }
1206 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1207 "\nvdev_offload_enabled----");
1208 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
1209 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1210 "\n\t[%d]=%d", i, hdd_ipa->vdev_offload_enabled[i]);
1211 }
1212 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1213 "\nassoc_stas_map ----");
Yun Parkb187d542016-11-14 18:10:04 -08001214 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Yun Park46255682017-10-09 15:56:34 -07001215 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1216 "\n\t[%d]: is_reserved=%d, sta_id=%d", i,
Yun Parkb187d542016-11-14 18:10:04 -08001217 hdd_ipa->assoc_stas_map[i].is_reserved,
1218 hdd_ipa->assoc_stas_map[i].sta_id);
1219 }
1220}
1221
1222/**
1223 * hdd_ipa_dump_sys_pipe() - dump HDD IPA SYS Pipe struct
1224 * @hdd_ipa: HDD IPA struct
1225 *
1226 * Dump entire struct hdd_ipa_sys_pipe
1227 *
1228 * Return: none
1229 */
1230static void hdd_ipa_dump_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
1231{
1232 int i;
1233
1234 /* IPA SYS Pipes */
Yun Park46255682017-10-09 15:56:34 -07001235 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1236 "\n==== IPA SYS Pipes ====\n");
Yun Parkb187d542016-11-14 18:10:04 -08001237
1238 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
1239 struct hdd_ipa_sys_pipe *sys_pipe;
Yun Park6c86a662017-10-05 16:09:15 -07001240 qdf_ipa_sys_connect_params_t *ipa_sys_params;
Yun Parkb187d542016-11-14 18:10:04 -08001241
1242 sys_pipe = &hdd_ipa->sys_pipe[i];
1243 ipa_sys_params = &sys_pipe->ipa_sys_params;
1244
Yun Park46255682017-10-09 15:56:34 -07001245 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1246 "\nsys_pipe[%d]----\n"
Yun Parkb187d542016-11-14 18:10:04 -08001247 "\tconn_hdl: 0x%x\n"
1248 "\tconn_hdl_valid: %d\n"
1249 "\tnat_en: %d\n"
1250 "\thdr_len %d\n"
1251 "\thdr_additional_const_len: %d\n"
1252 "\thdr_ofst_pkt_size_valid: %d\n"
1253 "\thdr_ofst_pkt_size: %d\n"
1254 "\thdr_little_endian: %d\n"
1255 "\tmode: %d\n"
1256 "\tclient: %d\n"
1257 "\tdesc_fifo_sz: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001258 "\tpriv: %pK\n"
1259 "\tnotify: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001260 "\tskip_ep_cfg: %d\n"
1261 "\tkeep_ipa_awake: %d\n",
1262 i,
1263 sys_pipe->conn_hdl,
1264 sys_pipe->conn_hdl_valid,
Yun Park6c86a662017-10-05 16:09:15 -07001265 QDF_IPA_SYS_PARAMS_NAT_EN(ipa_sys_params),
1266 QDF_IPA_SYS_PARAMS_HDR_LEN(ipa_sys_params),
1267 QDF_IPA_SYS_PARAMS_HDR_ADDITIONAL_CONST_LEN(
1268 ipa_sys_params),
1269 QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE_VALID(
1270 ipa_sys_params),
1271 QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE(ipa_sys_params),
1272 QDF_IPA_SYS_PARAMS_HDR_LITTLE_ENDIAN(ipa_sys_params),
1273 QDF_IPA_SYS_PARAMS_MODE(ipa_sys_params),
1274 QDF_IPA_SYS_PARAMS_CLIENT(ipa_sys_params),
1275 QDF_IPA_SYS_PARAMS_DESC_FIFO_SZ(ipa_sys_params),
1276 QDF_IPA_SYS_PARAMS_PRIV(ipa_sys_params),
1277 QDF_IPA_SYS_PARAMS_NOTIFY(ipa_sys_params),
1278 QDF_IPA_SYS_PARAMS_SKIP_EP_CFG(ipa_sys_params),
1279 QDF_IPA_SYS_PARAMS_KEEP_IPA_AWAKE(ipa_sys_params));
Yun Parkb187d542016-11-14 18:10:04 -08001280 }
1281}
1282
1283/**
1284 * hdd_ipa_dump_iface_context() - dump HDD IPA Interface Context struct
1285 * @hdd_ipa: HDD IPA struct
1286 *
1287 * Dump entire struct hdd_ipa_iface_context
1288 *
1289 * Return: none
1290 */
1291static void hdd_ipa_dump_iface_context(struct hdd_ipa_priv *hdd_ipa)
1292{
1293 int i;
1294
1295 /* IPA Interface Contexts */
Yun Park46255682017-10-09 15:56:34 -07001296 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1297 "\n==== IPA Interface Contexts ====\n");
Yun Parkb187d542016-11-14 18:10:04 -08001298
1299 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
1300 struct hdd_ipa_iface_context *iface_context;
1301
1302 iface_context = &hdd_ipa->iface_context[i];
1303
Yun Park46255682017-10-09 15:56:34 -07001304 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1305 "\niface_context[%d]----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001306 "\thdd_ipa: %pK\n"
1307 "\tadapter: %pK\n"
1308 "\ttl_context: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001309 "\tcons_client: %d\n"
1310 "\tprod_client: %d\n"
1311 "\tiface_id: %d\n"
1312 "\tsta_id: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001313 "\tinterface_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001314 "\tifa_address: 0x%x\n",
1315 i,
1316 iface_context->hdd_ipa,
1317 iface_context->adapter,
1318 iface_context->tl_context,
1319 iface_context->cons_client,
1320 iface_context->prod_client,
1321 iface_context->iface_id,
1322 iface_context->sta_id,
1323 &iface_context->interface_lock,
1324 iface_context->ifa_address);
1325 }
1326}
1327
1328/**
1329 * hdd_ipa_dump_info() - dump HDD IPA struct
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001330 * @hdd_ctx: hdd main context
Yun Parkb187d542016-11-14 18:10:04 -08001331 *
1332 * Dump entire struct hdd_ipa
1333 *
1334 * Return: none
1335 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001336void hdd_ipa_dump_info(struct hdd_context *hdd_ctx)
Yun Parkb187d542016-11-14 18:10:04 -08001337{
1338 struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1339
1340 hdd_ipa_dump_hdd_ipa(hdd_ipa);
1341 hdd_ipa_dump_sys_pipe(hdd_ipa);
1342 hdd_ipa_dump_iface_context(hdd_ipa);
1343}
1344
1345/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001346 * hdd_ipa_set_tx_flow_info() - To set TX flow info if IPA is
1347 * enabled
1348 *
1349 * This routine is called to set TX flow info if IPA is enabled
1350 *
1351 * Return: None
1352 */
1353void hdd_ipa_set_tx_flow_info(void)
1354{
Jeff Johnson49d45e62017-08-29 14:30:42 -07001355 struct hdd_adapter *adapter;
Jeff Johnsond377dce2017-10-04 10:32:42 -07001356 struct hdd_station_ctx *sta_ctx;
Jeff Johnson87251032017-08-29 13:31:11 -07001357 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -07001358 struct hdd_hostapd_state *hostapd_state;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001359 struct qdf_mac_addr staBssid = QDF_MAC_ADDR_ZERO_INITIALIZER;
1360 struct qdf_mac_addr p2pBssid = QDF_MAC_ADDR_ZERO_INITIALIZER;
1361 struct qdf_mac_addr apBssid = QDF_MAC_ADDR_ZERO_INITIALIZER;
1362 uint8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
1363 const char *p2pMode = "DEV";
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001364 struct hdd_context *hdd_ctx;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001365 cds_context_type *cds_ctx;
1366#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1367 uint8_t targetChannel = 0;
1368 uint8_t preAdapterChannel = 0;
1369 uint8_t channel24;
1370 uint8_t channel5;
Jeff Johnson49d45e62017-08-29 14:30:42 -07001371 struct hdd_adapter *preAdapterContext = NULL;
1372 struct hdd_adapter *adapter2_4 = NULL;
1373 struct hdd_adapter *adapter5 = NULL;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001374 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1375#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1376 struct wlan_objmgr_psoc *psoc;
1377
1378 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1379 if (!hdd_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001380 hdd_err("HDD context is NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001381 return;
1382 }
1383
1384 cds_ctx = cds_get_context(QDF_MODULE_ID_QDF);
1385 if (!cds_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001386 hdd_err("Invalid CDS Context");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001387 return;
1388 }
1389
1390 psoc = hdd_ctx->hdd_psoc;
Dustin Brown920397d2017-12-13 16:27:50 -08001391
1392 hdd_for_each_adapter(hdd_ctx, adapter) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001393 switch (adapter->device_mode) {
1394 case QDF_STA_MODE:
Jeff Johnsond377dce2017-10-04 10:32:42 -07001395 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001396 if (eConnectionState_Associated ==
Jeff Johnsond377dce2017-10-04 10:32:42 -07001397 sta_ctx->conn_info.connState) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001398 staChannel =
Jeff Johnsond377dce2017-10-04 10:32:42 -07001399 sta_ctx->conn_info.operationChannel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001400 qdf_copy_macaddr(&staBssid,
Jeff Johnsond377dce2017-10-04 10:32:42 -07001401 &sta_ctx->conn_info.bssId);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001402#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1403 targetChannel = staChannel;
1404#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1405 }
1406 break;
1407 case QDF_P2P_CLIENT_MODE:
Jeff Johnsond377dce2017-10-04 10:32:42 -07001408 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001409 if (eConnectionState_Associated ==
Jeff Johnsond377dce2017-10-04 10:32:42 -07001410 sta_ctx->conn_info.connState) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001411 p2pChannel =
Jeff Johnsond377dce2017-10-04 10:32:42 -07001412 sta_ctx->conn_info.operationChannel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001413 qdf_copy_macaddr(&p2pBssid,
Jeff Johnsond377dce2017-10-04 10:32:42 -07001414 &sta_ctx->conn_info.bssId);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001415 p2pMode = "CLI";
1416#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1417 targetChannel = p2pChannel;
1418#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1419 }
1420 break;
1421 case QDF_P2P_GO_MODE:
1422 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1423 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001424 if (hostapd_state->bss_state == BSS_START
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001425 && hostapd_state->qdf_status ==
1426 QDF_STATUS_SUCCESS) {
Jeff Johnson01206862017-10-27 20:55:59 -07001427 p2pChannel = hdd_ap_ctx->operating_channel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001428 qdf_copy_macaddr(&p2pBssid,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001429 &adapter->mac_addr);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001430#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1431 targetChannel = p2pChannel;
1432#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1433 }
1434 p2pMode = "GO";
1435 break;
1436 case QDF_SAP_MODE:
1437 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1438 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001439 if (hostapd_state->bss_state == BSS_START
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001440 && hostapd_state->qdf_status ==
1441 QDF_STATUS_SUCCESS) {
Jeff Johnson01206862017-10-27 20:55:59 -07001442 apChannel = hdd_ap_ctx->operating_channel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001443 qdf_copy_macaddr(&apBssid,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001444 &adapter->mac_addr);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001445#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1446 targetChannel = apChannel;
1447#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1448 }
1449 break;
1450 case QDF_IBSS_MODE:
1451 default:
1452 break;
1453 }
1454#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1455 if (targetChannel) {
1456 /*
1457 * This is first adapter detected as active
1458 * set as default for none concurrency case
1459 */
1460 if (!preAdapterChannel) {
1461 /* If IPA UC data path is enabled,
1462 * target should reserve extra tx descriptors
1463 * for IPA data path.
1464 * Then host data path should allow less TX
1465 * packet pumping in case IPA
1466 * data path enabled
1467 */
1468 if (hdd_ipa_uc_is_enabled(hdd_ctx) &&
1469 (QDF_SAP_MODE == adapter->device_mode)) {
1470 adapter->tx_flow_low_watermark =
1471 hdd_ctx->config->TxFlowLowWaterMark +
1472 WLAN_TFC_IPAUC_TX_DESC_RESERVE;
1473 } else {
1474 adapter->tx_flow_low_watermark =
1475 hdd_ctx->config->
1476 TxFlowLowWaterMark;
1477 }
1478 adapter->tx_flow_high_watermark_offset =
1479 hdd_ctx->config->TxFlowHighWaterMarkOffset;
1480 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001481 adapter->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001482 hdd_ctx->config->TxFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001483 hdd_info("MODE %d,CH %d,LWM %d,HWM %d,TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001484 adapter->device_mode,
1485 targetChannel,
1486 adapter->tx_flow_low_watermark,
1487 adapter->tx_flow_low_watermark +
1488 adapter->tx_flow_high_watermark_offset,
1489 hdd_ctx->config->TxFlowMaxQueueDepth);
1490 preAdapterChannel = targetChannel;
1491 preAdapterContext = adapter;
1492 } else {
1493 /*
1494 * SCC, disable TX flow control for both
1495 * SCC each adapter cannot reserve dedicated
1496 * channel resource, as a result, if any adapter
1497 * blocked OS Q by flow control,
1498 * blocked adapter will lost chance to recover
1499 */
1500 if (preAdapterChannel == targetChannel) {
1501 /* Current adapter */
1502 adapter->tx_flow_low_watermark = 0;
1503 adapter->
1504 tx_flow_high_watermark_offset = 0;
1505 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001506 adapter->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001507 hdd_ctx->config->
1508 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001509 hdd_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001510 hdd_device_mode_to_string(
1511 adapter->device_mode),
1512 adapter->device_mode,
1513 targetChannel,
1514 adapter->tx_flow_low_watermark,
1515 adapter->tx_flow_low_watermark +
1516 adapter->
1517 tx_flow_high_watermark_offset,
1518 hdd_ctx->config->
1519 TxHbwFlowMaxQueueDepth);
1520
1521 if (!preAdapterContext) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001522 hdd_err("SCC: Previous adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001523 continue;
1524 }
1525
1526 /* Previous adapter */
1527 preAdapterContext->
1528 tx_flow_low_watermark = 0;
1529 preAdapterContext->
1530 tx_flow_high_watermark_offset = 0;
1531 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001532 preAdapterContext->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001533 hdd_ctx->config->
1534 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001535 hdd_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001536 hdd_device_mode_to_string(
1537 preAdapterContext->device_mode
1538 ),
1539 preAdapterContext->device_mode,
1540 targetChannel,
1541 preAdapterContext->
1542 tx_flow_low_watermark,
1543 preAdapterContext->
1544 tx_flow_low_watermark +
1545 preAdapterContext->
1546 tx_flow_high_watermark_offset,
1547 hdd_ctx->config->
1548 TxHbwFlowMaxQueueDepth);
1549 }
1550 /*
1551 * MCC, each adapter will have dedicated
1552 * resource
1553 */
1554 else {
1555 /* current channel is 2.4 */
1556 if (targetChannel <=
1557 WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH) {
1558 channel24 = targetChannel;
1559 channel5 = preAdapterChannel;
1560 adapter2_4 = adapter;
1561 adapter5 = preAdapterContext;
1562 } else {
1563 /* Current channel is 5 */
1564 channel24 = preAdapterChannel;
1565 channel5 = targetChannel;
1566 adapter2_4 = preAdapterContext;
1567 adapter5 = adapter;
1568 }
1569
1570 if (!adapter5) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001571 hdd_err("MCC: 5GHz adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001572 continue;
1573 }
1574 adapter5->tx_flow_low_watermark =
1575 hdd_ctx->config->
1576 TxHbwFlowLowWaterMark;
1577 adapter5->
1578 tx_flow_high_watermark_offset =
1579 hdd_ctx->config->
1580 TxHbwFlowHighWaterMarkOffset;
1581 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001582 adapter5->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001583 hdd_ctx->config->
1584 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001585 hdd_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001586 hdd_device_mode_to_string(
1587 adapter5->device_mode),
1588 adapter5->device_mode,
1589 channel5,
1590 adapter5->tx_flow_low_watermark,
1591 adapter5->
1592 tx_flow_low_watermark +
1593 adapter5->
1594 tx_flow_high_watermark_offset,
1595 hdd_ctx->config->
1596 TxHbwFlowMaxQueueDepth);
1597
1598 if (!adapter2_4) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001599 hdd_err("MCC: 2.4GHz adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001600 continue;
1601 }
1602 adapter2_4->tx_flow_low_watermark =
1603 hdd_ctx->config->
1604 TxLbwFlowLowWaterMark;
1605 adapter2_4->
1606 tx_flow_high_watermark_offset =
1607 hdd_ctx->config->
1608 TxLbwFlowHighWaterMarkOffset;
1609 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001610 adapter2_4->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001611 hdd_ctx->config->
1612 TxLbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001613 hdd_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001614 hdd_device_mode_to_string(
1615 adapter2_4->device_mode),
1616 adapter2_4->device_mode,
1617 channel24,
1618 adapter2_4->
1619 tx_flow_low_watermark,
1620 adapter2_4->
1621 tx_flow_low_watermark +
1622 adapter2_4->
1623 tx_flow_high_watermark_offset,
1624 hdd_ctx->config->
1625 TxLbwFlowMaxQueueDepth);
1626
1627 }
1628 }
1629 }
1630 targetChannel = 0;
1631#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001632 }
Dustin Brown920397d2017-12-13 16:27:50 -08001633
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001634 hdd_ctx->mcc_mode = policy_mgr_current_concurrency_is_mcc(psoc);
1635}
1636
1637/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001638 * __hdd_ipa_uc_stat_query() - Query the IPA stats
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639 * @hdd_ctx: Global HDD context
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001640 * @ipa_tx_diff: tx packet count diff from previous tx packet count
1641 * @ipa_rx_diff: rx packet count diff from previous rx packet count
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001642 *
1643 * Return: true if IPA is enabled, false otherwise
1644 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001645static void __hdd_ipa_uc_stat_query(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff)
1647{
1648 struct hdd_ipa_priv *hdd_ipa;
1649
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 *ipa_tx_diff = 0;
1651 *ipa_rx_diff = 0;
1652
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001653 if (wlan_hdd_validate_context(hdd_ctx))
1654 return;
1655
1656 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1657
1658 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1659 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660 return;
1661 }
1662
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301663 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
1665 (false == hdd_ipa->resource_loading)) {
1666 *ipa_tx_diff = hdd_ipa->ipa_tx_packets_diff;
1667 *ipa_rx_diff = hdd_ipa->ipa_rx_packets_diff;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301669 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670}
1671
1672/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001673 * hdd_ipa_uc_stat_query() - SSR wrapper for __hdd_ipa_uc_stat_query
1674 * @hdd_ctx: Global HDD context
1675 * @ipa_tx_diff: tx packet count diff from previous tx packet count
1676 * @ipa_rx_diff: rx packet count diff from previous rx packet count
1677 *
1678 * Return: true if IPA is enabled, false otherwise
1679 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001680void hdd_ipa_uc_stat_query(struct hdd_context *hdd_ctx,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001681 uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff)
1682{
1683 cds_ssr_protect(__func__);
1684 __hdd_ipa_uc_stat_query(hdd_ctx, ipa_tx_diff, ipa_rx_diff);
1685 cds_ssr_unprotect(__func__);
1686}
1687
1688/**
1689 * __hdd_ipa_uc_stat_request() - Get IPA stats from IPA.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 * @adapter: network adapter
1691 * @reason: STAT REQ Reason
1692 *
1693 * Return: None
1694 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07001695static void __hdd_ipa_uc_stat_request(struct hdd_adapter *adapter,
1696 uint8_t reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001697{
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001698 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699 struct hdd_ipa_priv *hdd_ipa;
1700
Yun Park637d6482016-10-05 10:51:33 -07001701 if (!adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001702 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001703
Jeff Johnson399c6272017-08-30 10:51:00 -07001704 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001705
1706 if (wlan_hdd_validate_context(hdd_ctx))
1707 return;
1708
1709 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1710 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1711 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 return;
1713 }
1714
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301715 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001716 if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
1717 (false == hdd_ipa->resource_loading)) {
1718 hdd_ipa->stat_req_reason = reason;
Yun Park637d6482016-10-05 10:51:33 -07001719 qdf_mutex_release(&hdd_ipa->ipa_lock);
Sandeep Puligillaf587adf2017-04-27 19:53:21 -07001720 sme_ipa_uc_stat_request(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -07001721 adapter->session_id,
Sandeep Puligillaf587adf2017-04-27 19:53:21 -07001722 WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001723 0, VDEV_CMD);
Yun Park637d6482016-10-05 10:51:33 -07001724 } else {
1725 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001726 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001727}
1728
1729/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001730 * hdd_ipa_uc_stat_request() - SSR wrapper for __hdd_ipa_uc_stat_request
1731 * @adapter: network adapter
1732 * @reason: STAT REQ Reason
1733 *
1734 * Return: None
1735 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001736void hdd_ipa_uc_stat_request(struct hdd_adapter *adapter, uint8_t reason)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001737{
1738 cds_ssr_protect(__func__);
1739 __hdd_ipa_uc_stat_request(adapter, reason);
1740 cds_ssr_unprotect(__func__);
1741}
1742
Yun Park637d6482016-10-05 10:51:33 -07001743#ifdef FEATURE_METERING
1744/**
1745 * hdd_ipa_uc_sharing_stats_request() - Get IPA stats from IPA.
1746 * @adapter: network adapter
1747 * @reset_stats: reset stat countis after response
1748 *
1749 * Return: None
1750 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001751void hdd_ipa_uc_sharing_stats_request(struct hdd_adapter *adapter,
Yun Park637d6482016-10-05 10:51:33 -07001752 uint8_t reset_stats)
1753{
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001754 struct hdd_context *hdd_ctx;
Yun Park637d6482016-10-05 10:51:33 -07001755 struct hdd_ipa_priv *hdd_ipa;
1756
1757 if (!adapter)
1758 return;
1759
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001760 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1761 hdd_ipa = hdd_ctx->hdd_ipa;
1762 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1763 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Yun Park637d6482016-10-05 10:51:33 -07001764 return;
1765 }
1766
1767 HDD_IPA_LOG(LOG1, "SHARING_STATS: reset_stats=%d", reset_stats);
1768 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Park3374a4b2016-12-15 16:52:15 -08001769 if (false == hdd_ipa->resource_loading) {
Yun Park637d6482016-10-05 10:51:33 -07001770 qdf_mutex_release(&hdd_ipa->ipa_lock);
1771 wma_cli_set_command(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001772 (int)adapter->session_id,
Yun Park637d6482016-10-05 10:51:33 -07001773 (int)WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID,
1774 reset_stats, VDEV_CMD);
1775 } else {
1776 qdf_mutex_release(&hdd_ipa->ipa_lock);
1777 }
1778}
1779
1780/**
1781 * hdd_ipa_uc_set_quota() - Set quota limit bytes from IPA.
1782 * @adapter: network adapter
1783 * @set_quota: when 1, FW starts quota monitoring
1784 * @quota_bytes: quota limit in bytes
1785 *
1786 * Return: None
1787 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001788void hdd_ipa_uc_set_quota(struct hdd_adapter *adapter, uint8_t set_quota,
Yun Park637d6482016-10-05 10:51:33 -07001789 uint64_t quota_bytes)
1790{
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001791 struct hdd_context *hdd_ctx;
Yun Park637d6482016-10-05 10:51:33 -07001792 struct hdd_ipa_priv *hdd_ipa;
1793
1794 if (!adapter)
1795 return;
1796
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001797 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1798 hdd_ipa = hdd_ctx->hdd_ipa;
1799 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1800 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Yun Park637d6482016-10-05 10:51:33 -07001801 return;
1802 }
1803
1804 HDD_IPA_LOG(LOG1, "SET_QUOTA: set_quota=%d, quota_bytes=%llu",
1805 set_quota, quota_bytes);
1806
1807 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Park3374a4b2016-12-15 16:52:15 -08001808 if (false == hdd_ipa->resource_loading) {
Yun Park637d6482016-10-05 10:51:33 -07001809 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park327e7812017-02-14 15:18:10 -08001810 wma_cli_set2_command(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001811 (int)adapter->session_id,
Yun Park637d6482016-10-05 10:51:33 -07001812 (int)WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID,
Yun Park327e7812017-02-14 15:18:10 -08001813 (set_quota ? quota_bytes&0xffffffff : 0),
1814 (set_quota ? quota_bytes>>32 : 0),
1815 VDEV_CMD);
Yun Park637d6482016-10-05 10:51:33 -07001816 } else {
1817 qdf_mutex_release(&hdd_ipa->ipa_lock);
1818 }
1819}
1820#endif
1821
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001822/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001823 * hdd_ipa_uc_find_add_assoc_sta() - Find associated station
1824 * @hdd_ipa: Global HDD IPA context
1825 * @sta_add: Should station be added
1826 * @sta_id: ID of the station being queried
1827 *
1828 * Return: true if the station was found
1829 */
1830static bool hdd_ipa_uc_find_add_assoc_sta(struct hdd_ipa_priv *hdd_ipa,
1831 bool sta_add, uint8_t sta_id)
1832{
1833 bool sta_found = false;
1834 uint8_t idx;
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07001835
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1837 if ((hdd_ipa->assoc_stas_map[idx].is_reserved) &&
1838 (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) {
1839 sta_found = true;
1840 break;
1841 }
1842 }
1843 if (sta_add && sta_found) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301844 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001845 "STA ID %d already exist, cannot add", sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001846 return sta_found;
1847 }
1848 if (sta_add) {
1849 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1850 if (!hdd_ipa->assoc_stas_map[idx].is_reserved) {
1851 hdd_ipa->assoc_stas_map[idx].is_reserved = true;
1852 hdd_ipa->assoc_stas_map[idx].sta_id = sta_id;
1853 return sta_found;
1854 }
1855 }
1856 }
1857 if (!sta_add && !sta_found) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301858 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001859 "STA ID %d does not exist, cannot delete", sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 return sta_found;
1861 }
1862 if (!sta_add) {
1863 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1864 if ((hdd_ipa->assoc_stas_map[idx].is_reserved) &&
1865 (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) {
1866 hdd_ipa->assoc_stas_map[idx].is_reserved =
1867 false;
1868 hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF;
1869 return sta_found;
1870 }
1871 }
1872 }
1873 return sta_found;
1874}
1875
1876/**
1877 * hdd_ipa_uc_enable_pipes() - Enable IPA uC pipes
1878 * @hdd_ipa: Global HDD IPA context
1879 *
1880 * Return: 0 on success, negative errno if error
1881 */
1882static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
1883{
Yun Parkfec73dc2017-09-06 10:40:07 -07001884 int result = 0;
Leo Changfdb45c32016-10-28 11:09:23 -07001885 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkb4f591d2017-03-29 15:51:01 -07001886 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887
Yun Parke4239802018-01-09 11:01:40 -08001888 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Park199c2ed2017-10-02 11:24:22 -07001889
1890 if (!hdd_ipa->ipa_pipes_down) {
1891 /*
1892 * This shouldn't happen :
1893 * IPA WDI Pipes are already activated
1894 */
1895 WARN_ON(1);
1896 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
1897 "IPA WDI Pipes are already activated");
1898 goto end;
1899 }
Yun Parkfec73dc2017-09-06 10:40:07 -07001900
Yun Parkb4f591d2017-03-29 15:51:01 -07001901 result = cdp_ipa_enable_pipes(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 if (result) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301903 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001904 "Enable PIPE fail, code %d", result);
Yun Parkfec73dc2017-09-06 10:40:07 -07001905 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907
Yun Park777d7242017-03-30 15:38:33 -07001908 INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
Leo Change3e49442015-10-26 20:07:13 -07001909 hdd_ipa->ipa_pipes_down = false;
Yun Parkb4f591d2017-03-29 15:51:01 -07001910
1911 cdp_ipa_enable_autonomy(soc, (struct cdp_pdev *)pdev);
1912
Yun Parkfec73dc2017-09-06 10:40:07 -07001913end:
Yun Parke4239802018-01-09 11:01:40 -08001914 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: ipa_pipes_down=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07001915 hdd_ipa->ipa_pipes_down);
Yun Park199c2ed2017-10-02 11:24:22 -07001916
Yun Parkfec73dc2017-09-06 10:40:07 -07001917 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001918}
1919
1920/**
1921 * hdd_ipa_uc_disable_pipes() - Disable IPA uC pipes
1922 * @hdd_ipa: Global HDD IPA context
1923 *
1924 * Return: 0 on success, negative errno if error
1925 */
1926static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa)
1927{
Yun Parkb4f591d2017-03-29 15:51:01 -07001928 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1929 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Parkfec73dc2017-09-06 10:40:07 -07001930 int result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001931
Yun Parke4239802018-01-09 11:01:40 -08001932 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Park199c2ed2017-10-02 11:24:22 -07001933
1934 if (hdd_ipa->ipa_pipes_down) {
1935 /*
1936 * This shouldn't happen :
1937 * IPA WDI Pipes are already deactivated
1938 */
1939 WARN_ON(1);
1940 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
1941 "IPA WDI Pipes are already deactivated");
1942 goto end;
1943 }
Leo Change3e49442015-10-26 20:07:13 -07001944
Yun Parkb4f591d2017-03-29 15:51:01 -07001945 cdp_ipa_disable_autonomy(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946
Yun Parkb4f591d2017-03-29 15:51:01 -07001947 result = cdp_ipa_disable_pipes(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948 if (result) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301949 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001950 "Disable WDI PIPE fail, code %d", result);
Yun Parkfec73dc2017-09-06 10:40:07 -07001951 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952 }
1953
Yun Parkfec73dc2017-09-06 10:40:07 -07001954 hdd_ipa->ipa_pipes_down = true;
1955
1956end:
Yun Parke4239802018-01-09 11:01:40 -08001957 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: ipa_pipes_down=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07001958 hdd_ipa->ipa_pipes_down);
1959 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960}
1961
1962/**
1963 * hdd_ipa_uc_handle_first_con() - Handle first uC IPA connection
1964 * @hdd_ipa: Global HDD IPA context
1965 *
1966 * Return: 0 on success, negative errno if error
1967 */
1968static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa)
1969{
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001970 struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
Yun Parkb4f591d2017-03-29 15:51:01 -07001971
Yun Parke4239802018-01-09 11:01:40 -08001972 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07001973
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001974 hdd_ipa->activated_fw_pipe = 0;
1975 hdd_ipa->resource_loading = true;
Yun Park4cab6ee2015-10-27 11:43:40 -07001976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001977 /* If RM feature enabled
1978 * Request PROD Resource first
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001979 * PROD resource may return sync or async manners
1980 */
Yun Parkb4f591d2017-03-29 15:51:01 -07001981 if (hdd_ipa_is_rm_enabled(hdd_ctx)) {
Yun Park4cab6ee2015-10-27 11:43:40 -07001982 if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
1983 /* RM PROD request sync return
1984 * enable pipe immediately
1985 */
1986 if (hdd_ipa_uc_enable_pipes(hdd_ipa)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301987 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001988 "IPA WDI Pipe activation failed");
Yun Park4cab6ee2015-10-27 11:43:40 -07001989 hdd_ipa->resource_loading = false;
1990 return -EBUSY;
1991 }
Sravan Kumar Kairamc76f28a2017-07-25 19:03:40 +05301992 } else {
1993 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park199c2ed2017-10-02 11:24:22 -07001994 "IPA WDI Pipe activation deferred");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001995 }
1996 } else {
1997 /* RM Disabled
Yun Park4cab6ee2015-10-27 11:43:40 -07001998 * Just enabled all the PIPEs
1999 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 if (hdd_ipa_uc_enable_pipes(hdd_ipa)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302001 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07002002 "IPA WDI Pipe activation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002003 hdd_ipa->resource_loading = false;
2004 return -EBUSY;
2005 }
2006 hdd_ipa->resource_loading = false;
2007 }
Yun Park4cab6ee2015-10-27 11:43:40 -07002008
Yun Parke4239802018-01-09 11:01:40 -08002009 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 return 0;
2011}
2012
2013/**
2014 * hdd_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
2015 * @hdd_ipa: Global HDD IPA context
2016 *
2017 * Return: None
2018 */
2019static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa)
2020{
Leo Changfdb45c32016-10-28 11:09:23 -07002021 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkb4f591d2017-03-29 15:51:01 -07002022 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023
Yun Parke4239802018-01-09 11:01:40 -08002024 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07002025
Yun Parkb4f591d2017-03-29 15:51:01 -07002026 if (!pdev) {
Yun Park7c4f31b2016-11-30 10:09:21 -08002027 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "txrx context is NULL");
2028 QDF_ASSERT(0);
2029 return;
2030 }
2031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 hdd_ipa->resource_unloading = true;
Yun Park777d7242017-03-30 15:38:33 -07002033 INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
Yun Parkb4f591d2017-03-29 15:51:01 -07002034 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable FW RX PIPE");
2035 cdp_ipa_set_active(soc, (struct cdp_pdev *)pdev, false, false);
2036 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable FW TX PIPE");
2037 cdp_ipa_set_active(soc, (struct cdp_pdev *)pdev, false, true);
Yun Parkfec73dc2017-09-06 10:40:07 -07002038
Yun Parke4239802018-01-09 11:01:40 -08002039 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: IPA WDI Pipes deactivated");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040}
2041
2042/**
2043 * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
2044 * @context: User context registered with TL (the IPA Global context is
2045 * registered
2046 * @rxpkt: Packet containing the notification
2047 * @staid: ID of the station associated with the packet
2048 *
2049 * Return: None
2050 */
2051static void
Yun Park6c86a662017-10-05 16:09:15 -07002052hdd_ipa_uc_rm_notify_handler(void *context, qdf_ipa_rm_event_t event)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053{
2054 struct hdd_ipa_priv *hdd_ipa = context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302055 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002056 struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057
2058 /*
2059 * When SSR is going on or driver is unloading, just return.
2060 */
Yun Parkb4f591d2017-03-29 15:51:01 -07002061 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302062 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064
Yun Parkb4f591d2017-03-29 15:51:01 -07002065 if (!hdd_ipa_is_rm_enabled(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 return;
2067
Yun Park46255682017-10-09 15:56:34 -07002068 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d",
2069 event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002070
2071 switch (event) {
2072 case IPA_RM_RESOURCE_GRANTED:
2073 /* Differed RM Granted */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302074 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002075 if ((false == hdd_ipa->resource_unloading) &&
2076 (!hdd_ipa->activated_fw_pipe)) {
2077 hdd_ipa_uc_enable_pipes(hdd_ipa);
2078 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302079 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002080 break;
2081
2082 case IPA_RM_RESOURCE_RELEASED:
2083 /* Differed RM Released */
2084 hdd_ipa->resource_unloading = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002085 break;
2086
2087 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302088 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002089 "invalid event code %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090 break;
2091 }
2092}
2093
2094/**
2095 * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
2096 * @hdd_ipa: Global HDD IPA context
2097 * @event: IPA resource manager event to be deferred
2098 *
2099 * This function is called when a resource manager event is received
2100 * from firmware in interrupt context. This function will defer the
2101 * handling to the OL RX thread
2102 *
2103 * Return: None
2104 */
2105static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
2106{
Yun Park6c86a662017-10-05 16:09:15 -07002107 qdf_ipa_rm_event_t event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002108 struct uc_rm_work_struct *uc_rm_work = container_of(work,
2109 struct uc_rm_work_struct, work);
2110 struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
2111 struct hdd_ipa_priv, uc_rm_work);
2112
2113 cds_ssr_protect(__func__);
2114 event = uc_rm_work->event;
Srinivas Girigowda97852372017-03-06 16:52:59 -08002115 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07002116 "posted event %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117
2118 hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
2119 cds_ssr_unprotect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002120}
2121
2122/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002123 * hdd_ipa_uc_loaded_handler() - Process IPA uC loaded indication
Yun Parkb4f591d2017-03-29 15:51:01 -07002124 * @hdd_ipa: hdd ipa local context
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002125 *
2126 * Will handle IPA UC image loaded indication comes from IPA kernel
2127 *
2128 * Return: None
2129 */
Yun Parkb4f591d2017-03-29 15:51:01 -07002130static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *hdd_ipa)
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002131{
Yun Parkb4f591d2017-03-29 15:51:01 -07002132 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2133 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002134 struct hdd_context *hdd_ctx;
Yun Parkb4f591d2017-03-29 15:51:01 -07002135 QDF_STATUS status;
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002136
Yun Park46255682017-10-09 15:56:34 -07002137 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC READY");
Yun Parkb4f591d2017-03-29 15:51:01 -07002138 if (true == hdd_ipa->uc_loaded) {
Yun Park46255682017-10-09 15:56:34 -07002139 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "UC already loaded");
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002140 return;
2141 }
2142
Yun Parkb4f591d2017-03-29 15:51:01 -07002143 hdd_ctx = hdd_ipa->hdd_ctx;
2144 hdd_ipa->uc_loaded = true;
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002145
Yun Parkb4f591d2017-03-29 15:51:01 -07002146 /* Connect pipe */
2147 status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
2148 hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
2149 hdd_ipa_wdi_meter_notifier_cb,
2150 hdd_ctx->config->IpaDescSize,
2151 hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
2152 &hdd_ipa->tx_pipe_handle,
2153 &hdd_ipa->rx_pipe_handle);
2154 if (status) {
2155 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2156 "Failure to setup IPA pipes (status=%d)",
2157 status);
2158 return;
2159 }
2160
2161 cdp_ipa_set_doorbell_paddr(soc, (struct cdp_pdev *)pdev);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002162
2163 /* If already any STA connected, enable IPA/FW PIPEs */
Yun Parkb4f591d2017-03-29 15:51:01 -07002164 if (hdd_ipa->sap_num_connected_sta) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08002165 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002166 "Client already connected, enable IPA/FW PIPEs");
Yun Parkb4f591d2017-03-29 15:51:01 -07002167 hdd_ipa_uc_handle_first_con(hdd_ipa);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002168 }
2169}
2170
2171/**
Yun Park637d6482016-10-05 10:51:33 -07002172 * hdd_ipa_uc_op_metering() - IPA uC operation for stats and quota limit
2173 * @hdd_ctx: Global HDD context
2174 * @op_msg: operation message received from firmware
2175 *
2176 * Return: QDF_STATUS enumeration
2177 */
2178#ifdef FEATURE_METERING
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002179static QDF_STATUS hdd_ipa_uc_op_metering(struct hdd_context *hdd_ctx,
Yun Park637d6482016-10-05 10:51:33 -07002180 struct op_msg_type *op_msg)
2181{
2182 struct op_msg_type *msg = op_msg;
2183 struct ipa_uc_sharing_stats *uc_sharing_stats;
2184 struct ipa_uc_quota_rsp *uc_quota_rsp;
2185 struct ipa_uc_quota_ind *uc_quota_ind;
2186 struct hdd_ipa_priv *hdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07002187 struct hdd_adapter *adapter;
Yun Park637d6482016-10-05 10:51:33 -07002188
2189 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
2190
2191 if (HDD_IPA_UC_OPCODE_SHARING_STATS == msg->op_code) {
2192 /* fill-up ipa_uc_sharing_stats structure from FW */
2193 uc_sharing_stats = (struct ipa_uc_sharing_stats *)
2194 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2195
2196 memcpy(&(hdd_ipa->ipa_sharing_stats), uc_sharing_stats,
2197 sizeof(struct ipa_uc_sharing_stats));
2198
2199 complete(&hdd_ipa->ipa_uc_sharing_stats_comp);
2200
2201 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2202 "%s: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
2203 "HDD_IPA_UC_OPCODE_SHARING_STATS",
2204 hdd_ipa->ipa_sharing_stats.ipv4_rx_packets,
2205 hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes,
2206 hdd_ipa->ipa_sharing_stats.ipv6_rx_packets,
2207 hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes,
2208 hdd_ipa->ipa_sharing_stats.ipv4_tx_packets,
2209 hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes,
2210 hdd_ipa->ipa_sharing_stats.ipv6_tx_packets,
2211 hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes);
2212 } else if (HDD_IPA_UC_OPCODE_QUOTA_RSP == msg->op_code) {
2213 /* received set quota response */
2214 uc_quota_rsp = (struct ipa_uc_quota_rsp *)
2215 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2216
2217 memcpy(&(hdd_ipa->ipa_quota_rsp), uc_quota_rsp,
2218 sizeof(struct ipa_uc_quota_rsp));
2219
2220 complete(&hdd_ipa->ipa_uc_set_quota_comp);
2221 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2222 "%s: success=%d, quota_bytes=%llu",
2223 "HDD_IPA_UC_OPCODE_QUOTA_RSP",
2224 hdd_ipa->ipa_quota_rsp.success,
2225 ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)<<32)|
2226 hdd_ipa->ipa_quota_rsp.quota_lo);
2227 } else if (HDD_IPA_UC_OPCODE_QUOTA_IND == msg->op_code) {
2228 /* hit quota limit */
2229 uc_quota_ind = (struct ipa_uc_quota_ind *)
2230 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2231
2232 hdd_ipa->ipa_quota_ind.quota_bytes =
2233 uc_quota_ind->quota_bytes;
2234
2235 /* send quota exceeded indication to IPA */
2236 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2237 "OPCODE_QUOTA_IND: quota exceed! (quota_bytes=%llu)",
2238 hdd_ipa->ipa_quota_ind.quota_bytes);
2239
2240 adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
2241 if (adapter)
2242 ipa_broadcast_wdi_quota_reach_ind(
2243 adapter->dev->ifindex,
2244 uc_quota_ind->quota_bytes);
2245 else
2246 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2247 "Failed quota_reach_ind: NULL adapter");
2248 } else {
2249 return QDF_STATUS_E_INVAL;
2250 }
2251
2252 return QDF_STATUS_SUCCESS;
2253}
2254#else
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002255static QDF_STATUS hdd_ipa_uc_op_metering(struct hdd_context *hdd_ctx,
Yun Park637d6482016-10-05 10:51:33 -07002256 struct op_msg_type *op_msg)
2257{
2258 return QDF_STATUS_E_INVAL;
2259}
2260#endif
2261
Yun Park657c7d72017-06-07 15:44:59 -07002262#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
2263/* older versions had a typo */
2264#define num_bam_int_in_non_running_state num_bam_int_in_non_runnning_state
2265#endif
2266
Yun Park637d6482016-10-05 10:51:33 -07002267/**
Yun Park46255682017-10-09 15:56:34 -07002268 * hdd_ipa_wlan_event_to_str() - convert IPA WLAN event to string
2269 * @event: IPA WLAN event to be converted to a string
2270 *
2271 * Return: ASCII string representing the IPA WLAN event
2272 */
Yun Park6c86a662017-10-05 16:09:15 -07002273static inline char *hdd_ipa_wlan_event_to_str(qdf_ipa_wlan_event_t event)
Yun Park46255682017-10-09 15:56:34 -07002274{
2275 switch (event) {
2276 CASE_RETURN_STRING(WLAN_CLIENT_CONNECT);
2277 CASE_RETURN_STRING(WLAN_CLIENT_DISCONNECT);
2278 CASE_RETURN_STRING(WLAN_CLIENT_POWER_SAVE_MODE);
2279 CASE_RETURN_STRING(WLAN_CLIENT_NORMAL_MODE);
2280 CASE_RETURN_STRING(SW_ROUTING_ENABLE);
2281 CASE_RETURN_STRING(SW_ROUTING_DISABLE);
2282 CASE_RETURN_STRING(WLAN_AP_CONNECT);
2283 CASE_RETURN_STRING(WLAN_AP_DISCONNECT);
2284 CASE_RETURN_STRING(WLAN_STA_CONNECT);
2285 CASE_RETURN_STRING(WLAN_STA_DISCONNECT);
2286 CASE_RETURN_STRING(WLAN_CLIENT_CONNECT_EX);
2287 default:
2288 return "UNKNOWN";
2289 }
2290}
2291
2292/**
2293 * hdd_ipa_print_session_info - Print IPA session info
2294 * @hdd_ipa: HDD IPA local context
2295 *
2296 * Return: None
2297 */
2298static void hdd_ipa_print_session_info(struct hdd_ipa_priv *hdd_ipa)
2299{
2300 uint8_t session_id;
2301 int device_mode;
2302 struct ipa_uc_pending_event *event = NULL, *next = NULL;
2303 struct hdd_ipa_iface_context *iface_context = NULL;
2304 int i;
2305
2306 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2307 "\n==== IPA SESSION INFO ====\n"
2308 "NUM IFACE: %d\n"
2309 "RM STATE: %d\n"
2310 "ACTIVATED FW PIPE: %d\n"
2311 "SAP NUM STAs: %d\n"
2312 "STA CONNECTED: %d\n"
2313 "CONCURRENT MODE: %s\n"
2314 "RSC LOADING: %d\n"
2315 "RSC UNLOADING: %d\n"
2316 "PENDING CONS REQ: %d\n"
2317 "IPA PIPES DOWN: %d\n"
2318 "IPA UC LOADED: %d\n"
2319 "IPA WDI ENABLED: %d\n"
2320 "NUM SEND MSG: %d\n"
2321 "NUM FREE MSG: %d\n",
2322 hdd_ipa->num_iface,
2323 hdd_ipa->rm_state,
2324 hdd_ipa->activated_fw_pipe,
2325 hdd_ipa->sap_num_connected_sta,
2326 hdd_ipa->sta_connected,
2327 (hdd_ipa->hdd_ctx->mcc_mode ? "MCC" : "SCC"),
2328 hdd_ipa->resource_loading,
2329 hdd_ipa->resource_unloading,
2330 hdd_ipa->pending_cons_req,
2331 hdd_ipa->ipa_pipes_down,
2332 hdd_ipa->uc_loaded,
2333 hdd_ipa->wdi_enabled,
2334 (unsigned int)hdd_ipa->stats.num_send_msg,
2335 (unsigned int)hdd_ipa->stats.num_free_msg);
2336
2337 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
2338 iface_context = &hdd_ipa->iface_context[i];
2339 if (!iface_context || !iface_context->adapter)
2340 continue;
2341
Jeff Johnson1b780e42017-10-31 14:11:45 -07002342 session_id = iface_context->adapter->session_id;
Yun Park46255682017-10-09 15:56:34 -07002343 if (session_id >= CSR_ROAM_SESSION_MAX)
2344 continue;
2345
2346 device_mode = iface_context->adapter->device_mode;
2347 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2348 "\nIFACE[%d]: session:%d, sta_id:%d, mode:%s, offload:%d",
2349 i, session_id,
2350 iface_context->sta_id,
2351 hdd_device_mode_to_string(device_mode),
2352 hdd_ipa->vdev_offload_enabled[session_id]);
2353 }
2354
2355 for (i = 0; i < IPA_WLAN_EVENT_MAX; i++)
2356 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2357 "\nEVENT[%d]=%d",
2358 i, hdd_ipa->stats.event[i]);
2359
2360 i = 0;
2361 qdf_list_peek_front(&hdd_ipa->pending_event,
2362 (qdf_list_node_t **)&event);
2363 while (event != NULL) {
2364 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2365 "\nPENDING EVENT[%d]: DEV:%s, EVT:%s, sta_id:%d, MAC:%pM",
2366 i, event->adapter->dev->name,
2367 hdd_ipa_wlan_event_to_str(event->type),
2368 event->sta_id, event->mac_addr);
2369
2370 qdf_list_peek_next(&hdd_ipa->pending_event,
2371 (qdf_list_node_t *)event, (qdf_list_node_t **)&next);
2372 event = next;
2373 next = NULL;
2374 i++;
2375 }
2376}
2377
2378/**
2379 * hdd_ipa_print_txrx_stats - Print HDD IPA TX/RX stats
2380 * @hdd_ipa: HDD IPA local context
2381 *
2382 * Return: None
2383 */
2384static void hdd_ipa_print_txrx_stats(struct hdd_ipa_priv *hdd_ipa)
2385{
2386 int i;
2387 struct hdd_ipa_iface_context *iface_context = NULL;
2388
2389 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2390 "\n==== HDD IPA TX/RX STATS ====\n"
2391 "NUM RM GRANT: %llu\n"
2392 "NUM RM RELEASE: %llu\n"
2393 "NUM RM GRANT IMM: %llu\n"
2394 "NUM CONS PERF REQ: %llu\n"
2395 "NUM PROD PERF REQ: %llu\n"
2396 "NUM RX DROP: %llu\n"
2397 "NUM EXCP PKT: %llu\n"
2398 "NUM TX FWD OK: %llu\n"
2399 "NUM TX FWD ERR: %llu\n"
2400 "NUM TX DESC Q CNT: %llu\n"
2401 "NUM TX DESC ERROR: %llu\n"
2402 "NUM TX COMP CNT: %llu\n"
2403 "NUM TX QUEUED: %llu\n"
2404 "NUM TX DEQUEUED: %llu\n"
2405 "NUM MAX PM QUEUE: %llu\n"
2406 "TX REF CNT: %d\n"
2407 "SUSPENDED: %d\n"
2408 "PEND DESC HEAD: %pK\n"
2409 "TX DESC LIST: %pK\n"
2410 "FREE TX DESC HEAD: %pK\n",
2411 hdd_ipa->stats.num_rm_grant,
2412 hdd_ipa->stats.num_rm_release,
2413 hdd_ipa->stats.num_rm_grant_imm,
2414 hdd_ipa->stats.num_cons_perf_req,
2415 hdd_ipa->stats.num_prod_perf_req,
2416 hdd_ipa->stats.num_rx_drop,
2417 hdd_ipa->stats.num_rx_excep,
2418 hdd_ipa->stats.num_tx_fwd_ok,
2419 hdd_ipa->stats.num_tx_fwd_err,
2420 hdd_ipa->stats.num_tx_desc_q_cnt,
2421 hdd_ipa->stats.num_tx_desc_error,
2422 hdd_ipa->stats.num_tx_comp_cnt,
2423 hdd_ipa->stats.num_tx_queued,
2424 hdd_ipa->stats.num_tx_dequeued,
2425 hdd_ipa->stats.num_max_pm_queue,
2426 hdd_ipa->tx_ref_cnt.counter,
2427 hdd_ipa->suspended,
2428 &hdd_ipa->pend_desc_head,
2429 hdd_ipa->tx_desc_list,
2430 &hdd_ipa->free_tx_desc_head);
2431
2432 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
2433 iface_context = &hdd_ipa->iface_context[i];
2434 if (!iface_context || !iface_context->adapter)
2435 continue;
2436
2437 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2438 "IFACE[%d]: TX:%llu, TX DROP:%llu, TX ERR:%llu, TX CAC DROP:%llu, RX IPA EXCEP:%llu",
2439 i,
2440 iface_context->stats.num_tx,
2441 iface_context->stats.num_tx_drop,
2442 iface_context->stats.num_tx_err,
2443 iface_context->stats.num_tx_cac_drop,
2444 iface_context->stats.num_rx_ipa_excep);
2445 }
2446}
2447
2448/**
2449 * hdd_ipa_print_fw_wdi_stats - Print WLAN FW WDI stats
2450 * @hdd_ipa: HDD IPA local context
2451 *
2452 * Return: None
2453 */
2454static void hdd_ipa_print_fw_wdi_stats(struct hdd_ipa_priv *hdd_ipa,
2455 struct ipa_uc_fw_stats *uc_fw_stat)
2456{
2457 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2458 "\n==== WLAN FW WDI TX STATS ====\n"
2459 "COMP RING BASE: 0x%x\n"
2460 "COMP RING SIZE: %d\n"
2461 "COMP RING DBELL : 0x%x\n"
2462 "COMP RING DBELL IND VAL : %d\n"
2463 "COMP RING DBELL CACHED VAL : %d\n"
2464 "PKTS ENQ : %d\n"
2465 "PKTS COMP : %d\n"
2466 "IS SUSPEND : %d\n",
2467 uc_fw_stat->tx_comp_ring_base,
2468 uc_fw_stat->tx_comp_ring_size,
2469 uc_fw_stat->tx_comp_ring_dbell_addr,
2470 uc_fw_stat->tx_comp_ring_dbell_ind_val,
2471 uc_fw_stat->tx_comp_ring_dbell_cached_val,
2472 uc_fw_stat->tx_pkts_enqueued,
2473 uc_fw_stat->tx_pkts_completed,
2474 uc_fw_stat->tx_is_suspend);
2475
2476 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2477 "\n==== WLAN FW WDI RX STATS ====\n"
2478 "IND RING BASE: 0x%x\n"
2479 "IND RING SIZE: %d\n"
2480 "IND RING DBELL : 0x%x\n"
2481 "IND RING DBELL IND VAL : %d\n"
2482 "IND RING DBELL CACHED VAL : %d\n"
2483 "RDY IND ADDR : 0x%x\n"
2484 "RDY IND CACHE VAL : %d\n"
2485 "RFIL IND : %d\n"
2486 "NUM PKT INDICAT : %d\n"
2487 "BUF REFIL : %d\n"
2488 "NUM DROP NO SPC : %d\n"
2489 "NUM DROP NO BUF : %d\n"
2490 "IS SUSPND : %d\n",
2491 uc_fw_stat->rx_ind_ring_base,
2492 uc_fw_stat->rx_ind_ring_size,
2493 uc_fw_stat->rx_ind_ring_dbell_addr,
2494 uc_fw_stat->rx_ind_ring_dbell_ind_val,
2495 uc_fw_stat->rx_ind_ring_dbell_ind_cached_val,
2496 uc_fw_stat->rx_ind_ring_rdidx_addr,
2497 uc_fw_stat->rx_ind_ring_rd_idx_cached_val,
2498 uc_fw_stat->rx_refill_idx,
2499 uc_fw_stat->rx_num_pkts_indicated,
2500 uc_fw_stat->rx_buf_refilled,
2501 uc_fw_stat->rx_num_ind_drop_no_space,
2502 uc_fw_stat->rx_num_ind_drop_no_buf,
2503 uc_fw_stat->rx_is_suspend);
2504}
2505
2506/**
2507 * hdd_ipa_print_ipa_wdi_stats - Print IPA WDI stats
2508 * @hdd_ipa: HDD IPA local context
2509 *
2510 * Return: None
2511 */
2512static void hdd_ipa_print_ipa_wdi_stats(struct hdd_ipa_priv *hdd_ipa)
2513{
2514 struct IpaHwStatsWDIInfoData_t ipa_stat;
2515
2516 ipa_get_wdi_stats(&ipa_stat);
2517
2518 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2519 "\n==== IPA WDI TX STATS ====\n"
2520 "NUM PROCD : %d\n"
2521 "CE DBELL : 0x%x\n"
2522 "NUM DBELL FIRED : %d\n"
2523 "COMP RNG FULL : %d\n"
2524 "COMP RNG EMPT : %d\n"
2525 "COMP RNG USE HGH : %d\n"
2526 "COMP RNG USE LOW : %d\n"
2527 "BAM FIFO FULL : %d\n"
2528 "BAM FIFO EMPT : %d\n"
2529 "BAM FIFO USE HGH : %d\n"
2530 "BAM FIFO USE LOW : %d\n"
2531 "NUM DBELL : %d\n"
2532 "NUM UNEXP DBELL : %d\n"
2533 "NUM BAM INT HDL : 0x%x\n"
2534 "NUM BAM INT NON-RUN : 0x%x\n"
2535 "NUM QMB INT HDL : 0x%x\n",
2536 ipa_stat.tx_ch_stats.num_pkts_processed,
2537 ipa_stat.tx_ch_stats.copy_engine_doorbell_value,
2538 ipa_stat.tx_ch_stats.num_db_fired,
2539 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringFull,
2540 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringEmpty,
2541 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh,
2542 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageLow,
2543 ipa_stat.tx_ch_stats.bam_stats.bamFifoFull,
2544 ipa_stat.tx_ch_stats.bam_stats.bamFifoEmpty,
2545 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageHigh,
2546 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageLow,
2547 ipa_stat.tx_ch_stats.num_db,
2548 ipa_stat.tx_ch_stats.num_unexpected_db,
2549 ipa_stat.tx_ch_stats.num_bam_int_handled,
2550 ipa_stat.tx_ch_stats.
2551#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2552 num_bam_int_in_non_running_state,
2553#else
2554 num_bam_int_in_non_runnning_state,
2555#endif
2556 ipa_stat.tx_ch_stats.num_qmb_int_handled);
2557
2558 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2559 "\n==== IPA WDI RX STATS ====\n"
2560 "MAX OST PKT : %d\n"
2561 "NUM PKT PRCSD : %d\n"
2562 "RNG RP : 0x%x\n"
2563 "IND RNG FULL : %d\n"
2564 "IND RNG EMPT : %d\n"
2565 "IND RNG USE HGH : %d\n"
2566 "IND RNG USE LOW : %d\n"
2567 "BAM FIFO FULL : %d\n"
2568 "BAM FIFO EMPT : %d\n"
2569 "BAM FIFO USE HGH : %d\n"
2570 "BAM FIFO USE LOW : %d\n"
2571 "NUM DB : %d\n"
2572 "NUM UNEXP DB : %d\n"
2573 "NUM BAM INT HNDL : 0x%x\n",
2574 ipa_stat.rx_ch_stats.max_outstanding_pkts,
2575 ipa_stat.rx_ch_stats.num_pkts_processed,
2576 ipa_stat.rx_ch_stats.rx_ring_rp_value,
2577 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringFull,
2578 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringEmpty,
2579 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh,
2580 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageLow,
2581 ipa_stat.rx_ch_stats.bam_stats.bamFifoFull,
2582 ipa_stat.rx_ch_stats.bam_stats.bamFifoEmpty,
2583 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageHigh,
2584 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageLow,
2585 ipa_stat.rx_ch_stats.num_db,
2586 ipa_stat.rx_ch_stats.num_unexpected_db,
2587 ipa_stat.rx_ch_stats.num_bam_int_handled);
2588}
2589
2590/**
2591 * hdd_ipa_uc_info() - Print IPA uC resource and session information
2592 * @adapter: network adapter
2593 *
2594 * Return: None
2595 */
2596void hdd_ipa_uc_info(struct hdd_context *hdd_ctx)
2597{
2598 struct hdd_ipa_priv *hdd_ipa;
2599
2600 hdd_ipa = hdd_ctx->hdd_ipa;
2601
2602 if (!hdd_ipa) {
2603 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2604 "HDD IPA context is NULL");
2605 return;
2606 }
2607
2608 /* IPA session info */
2609 hdd_ipa_print_session_info(hdd_ipa);
2610}
2611
2612/**
2613 * hdd_ipa_uc_stat() - Print IPA uC stats
2614 * @adapter: network adapter
2615 *
2616 * Return: None
2617 */
2618void hdd_ipa_uc_stat(struct hdd_adapter *adapter)
2619{
2620 struct hdd_context *hdd_ctx;
2621 struct hdd_ipa_priv *hdd_ipa;
2622
2623 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2624 hdd_ipa = hdd_ctx->hdd_ipa;
2625
2626 if (!hdd_ipa) {
2627 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2628 "HDD IPA context is NULL");
2629 return;
2630 }
2631
2632 /* HDD IPA TX/RX stats */
2633 hdd_ipa_print_txrx_stats(hdd_ipa);
2634 /* IPA WDI stats */
2635 hdd_ipa_print_ipa_wdi_stats(hdd_ipa);
2636 /* WLAN FW WDI stats */
2637 hdd_ipa_uc_stat_request(adapter, HDD_IPA_UC_STAT_REASON_DEBUG);
2638}
2639
2640/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641 * hdd_ipa_uc_op_cb() - IPA uC operation callback
2642 * @op_msg: operation message received from firmware
2643 * @usr_ctxt: user context registered with TL (we register the HDD Global
2644 * context)
2645 *
2646 * Return: None
2647 */
2648static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
2649{
2650 struct op_msg_type *msg = op_msg;
2651 struct ipa_uc_fw_stats *uc_fw_stat;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002652 struct hdd_ipa_priv *hdd_ipa;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002653 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302654 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655
2656 if (!op_msg || !usr_ctxt) {
Yun Park46255682017-10-09 15:56:34 -07002657 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "INVALID ARG");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658 return;
2659 }
2660
2661 if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302662 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002663 "INVALID OPCODE %d", msg->op_code);
jiadd91a6842017-08-01 14:46:02 +08002664 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 return;
2666 }
2667
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002668 hdd_ctx = (struct hdd_context *) usr_ctxt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669
2670 /*
2671 * When SSR is going on or driver is unloading, just return.
2672 */
2673 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302674 if (status) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302675 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002676 return;
2677 }
2678
2679 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
2680
Govind Singhb6a89772016-08-12 11:23:35 +05302681 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park5f0fc232017-02-10 10:34:57 -08002682 "OPCODE=%d", msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683
2684 if ((HDD_IPA_UC_OPCODE_TX_RESUME == msg->op_code) ||
2685 (HDD_IPA_UC_OPCODE_RX_RESUME == msg->op_code)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302686 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002687 hdd_ipa->activated_fw_pipe++;
2688 if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) {
2689 hdd_ipa->resource_loading = false;
Yun Park777d7242017-03-30 15:38:33 -07002690 complete(&hdd_ipa->ipa_resource_comp);
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08002691 if (hdd_ipa->wdi_enabled == false) {
2692 hdd_ipa->wdi_enabled = true;
2693 if (hdd_ipa_uc_send_wdi_control_msg(true) == 0)
2694 hdd_ipa_send_mcc_scc_msg(hdd_ctx,
2695 hdd_ctx->mcc_mode);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002696 }
Yun Parka4bb37c2017-12-08 16:14:22 -08002697 hdd_ipa_uc_proc_pending_event(hdd_ipa, true);
Yun Parkccc6d7a2015-12-02 14:50:13 -08002698 if (hdd_ipa->pending_cons_req)
2699 ipa_rm_notify_completion(
2700 IPA_RM_RESOURCE_GRANTED,
2701 IPA_RM_RESOURCE_WLAN_CONS);
Yun Park5b635012015-12-02 15:05:01 -08002702 hdd_ipa->pending_cons_req = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302704 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park8292dcb2016-10-07 16:46:06 -07002705 } else if ((HDD_IPA_UC_OPCODE_TX_SUSPEND == msg->op_code) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002706 (HDD_IPA_UC_OPCODE_RX_SUSPEND == msg->op_code)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302707 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 hdd_ipa->activated_fw_pipe--;
2709 if (!hdd_ipa->activated_fw_pipe) {
Yun Park777d7242017-03-30 15:38:33 -07002710 /*
2711 * Async return success from FW
2712 * Disable/suspend all the PIPEs
2713 */
Yun Parka4bb37c2017-12-08 16:14:22 -08002714 hdd_ipa->resource_unloading = false;
2715 complete(&hdd_ipa->ipa_resource_comp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002716 hdd_ipa_uc_disable_pipes(hdd_ipa);
Yun Park5b635012015-12-02 15:05:01 -08002717 if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
2718 ipa_rm_release_resource(
2719 IPA_RM_RESOURCE_WLAN_PROD);
Yun Parka4bb37c2017-12-08 16:14:22 -08002720 hdd_ipa_uc_proc_pending_event(hdd_ipa, false);
Yun Park5b635012015-12-02 15:05:01 -08002721 hdd_ipa->pending_cons_req = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302723 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park8292dcb2016-10-07 16:46:06 -07002724 } else if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725 (HDD_IPA_UC_STAT_REASON_DEBUG == hdd_ipa->stat_req_reason)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002726 uc_fw_stat = (struct ipa_uc_fw_stats *)
Yun Park46255682017-10-09 15:56:34 -07002727 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728
Yun Park46255682017-10-09 15:56:34 -07002729 /* WLAN FW WDI stats */
2730 hdd_ipa_print_fw_wdi_stats(hdd_ipa, uc_fw_stat);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 } else if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) &&
2732 (HDD_IPA_UC_STAT_REASON_BW_CAL == hdd_ipa->stat_req_reason)) {
2733 /* STATs from FW */
2734 uc_fw_stat = (struct ipa_uc_fw_stats *)
2735 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302736 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002737 hdd_ipa->ipa_tx_packets_diff = HDD_BW_GET_DIFF(
2738 uc_fw_stat->tx_pkts_completed,
2739 hdd_ipa->ipa_p_tx_packets);
2740 hdd_ipa->ipa_rx_packets_diff = HDD_BW_GET_DIFF(
2741 (uc_fw_stat->rx_num_ind_drop_no_space +
2742 uc_fw_stat->rx_num_ind_drop_no_buf +
2743 uc_fw_stat->rx_num_pkts_indicated),
2744 hdd_ipa->ipa_p_rx_packets);
2745
2746 hdd_ipa->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2747 hdd_ipa->ipa_p_rx_packets =
2748 (uc_fw_stat->rx_num_ind_drop_no_space +
2749 uc_fw_stat->rx_num_ind_drop_no_buf +
2750 uc_fw_stat->rx_num_pkts_indicated);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302751 qdf_mutex_release(&hdd_ipa->ipa_lock);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002752 } else if (msg->op_code == HDD_IPA_UC_OPCODE_UC_READY) {
2753 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
2754 hdd_ipa_uc_loaded_handler(hdd_ipa);
2755 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park637d6482016-10-05 10:51:33 -07002756 } else if (hdd_ipa_uc_op_metering(hdd_ctx, op_msg)) {
2757 HDD_IPA_LOG(LOGE, "Invalid message: op_code=%d, reason=%d",
2758 msg->op_code, hdd_ipa->stat_req_reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002759 }
Yun Park8957d802017-01-25 12:27:29 -08002760
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302761 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002762}
2763
2764
2765/**
2766 * hdd_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
2767 * @adapter: device adapter instance
2768 * @offload_type: MCC or SCC
2769 * @enable: TX offload enable or disable
2770 *
2771 * Return: none
2772 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07002773static void hdd_ipa_uc_offload_enable_disable(struct hdd_adapter *adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002774 uint32_t offload_type, bool enable)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002775{
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002776 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 struct sir_ipa_offload_enable_disable ipa_offload_enable_disable;
Yun Park8292dcb2016-10-07 16:46:06 -07002778 struct hdd_ipa_iface_context *iface_context = NULL;
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002779 uint8_t session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002781 if (!adapter || !hdd_ipa)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 return;
2783
Yun Park8292dcb2016-10-07 16:46:06 -07002784 iface_context = adapter->ipa_context;
Jeff Johnson1b780e42017-10-31 14:11:45 -07002785 session_id = adapter->session_id;
Yun Park8292dcb2016-10-07 16:46:06 -07002786
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002787 if (!iface_context) {
2788 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2789 "Interface context is NULL");
2790 return;
2791 }
Zhu Jianminded9d2d2017-06-22 09:39:36 +08002792 if (session_id >= CSR_ROAM_SESSION_MAX) {
2793 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2794 "invalid session id: %d", session_id);
2795 return;
2796 }
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002797 if (enable == hdd_ipa->vdev_offload_enabled[session_id]) {
Yun Park199c2ed2017-10-02 11:24:22 -07002798 /*
2799 * This shouldn't happen :
2800 * IPA offload status is already set as desired
2801 */
2802 WARN_ON(1);
2803 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
Yun Parkb4f591d2017-03-29 15:51:01 -07002804 "%s (offload_type=%d, vdev_id=%d, enable=%d)",
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002805 "IPA offload status is already set",
2806 offload_type, session_id, enable);
Yun Park8292dcb2016-10-07 16:46:06 -07002807 return;
2808 }
2809
Jeff Johnson1b780e42017-10-31 14:11:45 -07002810 if (wlan_hdd_validate_session_id(adapter->session_id)) {
Yun Park4540e862016-11-10 16:30:06 -08002811 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2812 "invalid session id: %d, offload_type=%d, enable=%d",
Jeff Johnson1b780e42017-10-31 14:11:45 -07002813 adapter->session_id, offload_type, enable);
Yun Park4540e862016-11-10 16:30:06 -08002814 return;
2815 }
2816
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302817 qdf_mem_zero(&ipa_offload_enable_disable,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 sizeof(ipa_offload_enable_disable));
2819 ipa_offload_enable_disable.offload_type = offload_type;
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002820 ipa_offload_enable_disable.vdev_id = session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 ipa_offload_enable_disable.enable = enable;
2822
Yun Park199c2ed2017-10-02 11:24:22 -07002823 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park8292dcb2016-10-07 16:46:06 -07002824 "offload_type=%d, vdev_id=%d, enable=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 ipa_offload_enable_disable.offload_type,
2826 ipa_offload_enable_disable.vdev_id,
2827 ipa_offload_enable_disable.enable);
2828
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302829 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 sme_ipa_offload_enable_disable(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -07002831 adapter->session_id, &ipa_offload_enable_disable)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302832 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002833 "Failure to enable IPA offload (offload_type=%d, vdev_id=%d, enable=%d)",
2834 ipa_offload_enable_disable.offload_type,
2835 ipa_offload_enable_disable.vdev_id,
2836 ipa_offload_enable_disable.enable);
Yun Park8292dcb2016-10-07 16:46:06 -07002837 } else {
2838 /* Update the IPA offload status */
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002839 hdd_ipa->vdev_offload_enabled[session_id] =
Yun Park8292dcb2016-10-07 16:46:06 -07002840 ipa_offload_enable_disable.enable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 }
2842}
2843
2844/**
2845 * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2846 * @work: uC OP work
2847 *
2848 * Return: None
2849 */
2850static void hdd_ipa_uc_fw_op_event_handler(struct work_struct *work)
2851{
2852 struct op_msg_type *msg;
2853 struct uc_op_work_struct *uc_op_work = container_of(work,
2854 struct uc_op_work_struct, work);
2855 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
2856
2857 cds_ssr_protect(__func__);
2858
2859 msg = uc_op_work->msg;
2860 uc_op_work->msg = NULL;
Srinivas Girigowda97852372017-03-06 16:52:59 -08002861 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07002862 "posted msg %d", msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863
2864 hdd_ipa_uc_op_cb(msg, hdd_ipa->hdd_ctx);
2865
2866 cds_ssr_unprotect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867}
2868
2869/**
2870 * hdd_ipa_uc_op_event_handler() - Adapter lookup
2871 * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2872 * @op_msg: operation message received from firmware
2873 * @hdd_ctx: Global HDD context
2874 *
2875 * Return: None
2876 */
2877static void hdd_ipa_uc_op_event_handler(uint8_t *op_msg, void *hdd_ctx)
2878{
2879 struct hdd_ipa_priv *hdd_ipa;
2880 struct op_msg_type *msg;
2881 struct uc_op_work_struct *uc_op_work;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302882 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883
2884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302885 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002887
2888 msg = (struct op_msg_type *)op_msg;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002889 hdd_ipa = ((struct hdd_context *)hdd_ctx)->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890
2891 if (unlikely(!hdd_ipa))
2892 goto end;
2893
2894 if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) {
Yun Parkb4f591d2017-03-29 15:51:01 -07002895 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Invalid OP Code (%d)",
2896 msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 goto end;
2898 }
2899
2900 uc_op_work = &hdd_ipa->uc_op_work[msg->op_code];
2901 if (uc_op_work->msg)
2902 /* When the same uC OPCODE is already pended, just return */
2903 goto end;
2904
2905 uc_op_work->msg = msg;
2906 schedule_work(&uc_op_work->work);
2907 return;
2908
2909end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302910 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911}
2912
2913/**
Rajeev Kumar217f2172016-01-06 18:11:55 -08002914 * hdd_ipa_init_uc_op_work - init ipa uc op work
2915 * @work: struct work_struct
2916 * @work_handler: work_handler
2917 *
2918 * Return: none
2919 */
Rajeev Kumar217f2172016-01-06 18:11:55 -08002920static void hdd_ipa_init_uc_op_work(struct work_struct *work,
Yun Park637d6482016-10-05 10:51:33 -07002921 work_func_t work_handler)
Rajeev Kumar217f2172016-01-06 18:11:55 -08002922{
2923 INIT_WORK(work, work_handler);
2924}
Rajeev Kumar217f2172016-01-06 18:11:55 -08002925
Yun Park637d6482016-10-05 10:51:33 -07002926#ifdef FEATURE_METERING
2927/**
2928 * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
2929 * IPA calls to get WLAN stats or set quota limit.
2930 * @priv: pointer to private data registered with IPA (we register a
2931 *» pointer to the global IPA context)
2932 * @evt: the IPA event which triggered the callback
2933 * @data: data associated with the event
2934 *
2935 * Return: None
2936 */
Yun Park6c86a662017-10-05 16:09:15 -07002937static void __hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Park637d6482016-10-05 10:51:33 -07002938 void *data)
2939{
2940 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07002941 struct hdd_adapter *adapter = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07002942 qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats;
2943 qdf_ipa_set_wifi_quota_t *ipa_set_quota;
Yun Park637d6482016-10-05 10:51:33 -07002944 int ret = 0;
2945
2946 if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
2947 return;
2948
2949 adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
2950
2951 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "event=%d", evt);
2952
2953 switch (evt) {
2954 case IPA_GET_WDI_SAP_STATS:
2955 /* fill-up ipa_get_wdi_sap_stats structure after getting
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07002956 * ipa_uc_fw_stats from FW
2957 */
Yun Park637d6482016-10-05 10:51:33 -07002958 wdi_sap_stats = data;
2959
2960 if (!adapter) {
2961 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2962 "IPA uC share stats failed - no adapter");
Yun Park6c86a662017-10-05 16:09:15 -07002963 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) =
2964 0;
Yun Park637d6482016-10-05 10:51:33 -07002965 return;
2966 }
2967
2968 INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
Yun Park637d6482016-10-05 10:51:33 -07002969 hdd_ipa_uc_sharing_stats_request(adapter,
Yun Park6c86a662017-10-05 16:09:15 -07002970 QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats));
Yun Park637d6482016-10-05 10:51:33 -07002971 ret = wait_for_completion_timeout(
2972 &hdd_ipa->ipa_uc_sharing_stats_comp,
2973 msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
2974 if (!ret) {
2975 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2976 "IPA uC share stats request timed out");
Yun Park6c86a662017-10-05 16:09:15 -07002977 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
2978 = 0;
Yun Park637d6482016-10-05 10:51:33 -07002979 } else {
Yun Park6c86a662017-10-05 16:09:15 -07002980 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
2981 = 1;
Yun Park637d6482016-10-05 10:51:33 -07002982
Yun Park6c86a662017-10-05 16:09:15 -07002983 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats)
2984 = hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
2985 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats)
2986 = hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
2987 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats)
2988 = hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
2989 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats)
2990 = hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
2991 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats)
2992 = hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
2993 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats)
2994 = hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
2995 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats)
2996 = hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
2997 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats)
2998 = hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
Yun Park637d6482016-10-05 10:51:33 -07002999 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
3000 "%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
3001 "IPA_GET_WDI_SAP_STATS",
Yun Park6c86a662017-10-05 16:09:15 -07003002 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(
3003 wdi_sap_stats),
3004 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(
3005 wdi_sap_stats),
3006 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(
3007 wdi_sap_stats),
3008 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(
3009 wdi_sap_stats),
3010 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(
3011 wdi_sap_stats),
3012 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(
3013 wdi_sap_stats),
3014 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(
3015 wdi_sap_stats),
3016 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(
3017 wdi_sap_stats),
3018 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(
3019 wdi_sap_stats));
Yun Park637d6482016-10-05 10:51:33 -07003020 }
3021 break;
3022 case IPA_SET_WIFI_QUOTA:
3023 /* get ipa_set_wifi_quota structure from IPA and pass to FW
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07003024 * through quota_exceeded field in ipa_uc_fw_stats
3025 */
Yun Park637d6482016-10-05 10:51:33 -07003026 ipa_set_quota = data;
3027
3028 if (!adapter) {
3029 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3030 "IPA uC set quota failed - no adapter");
3031 ipa_set_quota->set_valid = 0;
3032 return;
3033 }
3034
Yun Park777d7242017-03-30 15:38:33 -07003035 INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
Yun Park637d6482016-10-05 10:51:33 -07003036 hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
3037 ipa_set_quota->quota_bytes);
3038
3039 ret = wait_for_completion_timeout(
3040 &hdd_ipa->ipa_uc_set_quota_comp,
3041 msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
3042 if (!ret) {
3043 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3044 "IPA uC set quota request timed out");
Yun Park6c86a662017-10-05 16:09:15 -07003045 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) = 0;
Yun Park637d6482016-10-05 10:51:33 -07003046 } else {
Yun Park6c86a662017-10-05 16:09:15 -07003047 QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) =
Yun Park637d6482016-10-05 10:51:33 -07003048 ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
3049 <<32)|hdd_ipa->ipa_quota_rsp.quota_lo;
Yun Park6c86a662017-10-05 16:09:15 -07003050 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) =
Yun Park637d6482016-10-05 10:51:33 -07003051 hdd_ipa->ipa_quota_rsp.success;
3052 }
3053
3054 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
3055 ipa_set_quota->quota_bytes,
3056 ipa_set_quota->set_valid);
3057 break;
3058 }
3059}
3060
3061/**
3062 * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
3063 * IPA calls to get WLAN stats or set quota limit.
3064 * @priv: pointer to private data registered with IPA (we register a
Yun Parkb4f591d2017-03-29 15:51:01 -07003065 * pointer to the global IPA context)
Yun Park637d6482016-10-05 10:51:33 -07003066 * @evt: the IPA event which triggered the callback
3067 * @data: data associated with the event
3068 *
3069 * Return: None
3070 */
Yun Park6c86a662017-10-05 16:09:15 -07003071static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Park637d6482016-10-05 10:51:33 -07003072 void *data)
3073{
3074 cds_ssr_protect(__func__);
3075 __hdd_ipa_wdi_meter_notifier_cb(evt, data);
3076 cds_ssr_unprotect(__func__);
3077}
3078
Yun Parkb4f591d2017-03-29 15:51:01 -07003079static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
Yun Park637d6482016-10-05 10:51:33 -07003080{
Yun Park637d6482016-10-05 10:51:33 -07003081 init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
3082 init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
3083}
3084#else
Yun Parkb4f591d2017-03-29 15:51:01 -07003085static void hdd_ipa_wdi_meter_notifier_cb(void)
3086{
3087}
3088
3089static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
Yun Park637d6482016-10-05 10:51:33 -07003090{
3091}
3092#endif
3093
Rajeev Kumar217f2172016-01-06 18:11:55 -08003094/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003095 * hdd_ipa_uc_ol_init() - Initialize IPA uC offload
3096 * @hdd_ctx: Global HDD context
3097 *
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003098 * This function is called to update IPA pipe configuration with resources
3099 * allocated by wlan driver (cds_pre_enable) before enabling it in FW
3100 * (cds_enable)
3101 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303102 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003103 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003104QDF_STATUS hdd_ipa_uc_ol_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105{
Yun Parkb4f591d2017-03-29 15:51:01 -07003106 struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Leo Changfdb45c32016-10-28 11:09:23 -07003107 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkbaa62862017-01-18 13:43:34 -08003108 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Parkb4f591d2017-03-29 15:51:01 -07003109 uint8_t i;
3110 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003111
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003112 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
3113 return QDF_STATUS_SUCCESS;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003114
Rajeev Kumar3887f9b2018-01-10 11:24:01 -08003115 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003116
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003117 /* Do only IPA Pipe specific configuration here. All one time
3118 * initialization wrt IPA UC shall in hdd_ipa_init and those need
3119 * to be reinit at SSR shall in be SSR deinit / reinit functions.
3120 */
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003121 if (!pdev || !soc) {
3122 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "DP context is NULL");
Yun Parkb4f591d2017-03-29 15:51:01 -07003123 status = QDF_STATUS_E_FAILURE;
Yun Parkbaa62862017-01-18 13:43:34 -08003124 goto fail_return;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003125 }
Yun Parka4bb37c2017-12-08 16:14:22 -08003126
3127 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
3128 hdd_ipa->vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
3129 hdd_ipa->vdev_offload_enabled[i] = false;
3130 }
3131
Yun Parkb4f591d2017-03-29 15:51:01 -07003132 if (cdp_ipa_get_resource(soc, (struct cdp_pdev *)pdev)) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003133 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
3134 "IPA UC resource alloc fail");
Yun Park199c2ed2017-10-02 11:24:22 -07003135 status = QDF_STATUS_E_FAILURE;
3136 goto fail_return;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003137 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138
Yun Parkb4f591d2017-03-29 15:51:01 -07003139 if (true == hdd_ipa->uc_loaded) {
3140 status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
3141 hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
3142 hdd_ipa_wdi_meter_notifier_cb,
3143 hdd_ctx->config->IpaDescSize,
3144 hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
3145 &hdd_ipa->tx_pipe_handle,
3146 &hdd_ipa->rx_pipe_handle);
3147 if (status) {
Yun Parkbaa62862017-01-18 13:43:34 -08003148 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07003149 "Failure to setup IPA pipes (status=%d)",
3150 status);
Yun Park199c2ed2017-10-02 11:24:22 -07003151 status = QDF_STATUS_E_FAILURE;
3152 goto fail_return;
Yun Parkbaa62862017-01-18 13:43:34 -08003153 }
Yun Park637d6482016-10-05 10:51:33 -07003154
Yun Parkb4f591d2017-03-29 15:51:01 -07003155 cdp_ipa_set_doorbell_paddr(soc, (struct cdp_pdev *)pdev);
3156 hdd_ipa_init_metering(hdd_ipa);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08003157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158
Yun Parkb4f591d2017-03-29 15:51:01 -07003159 cdp_ipa_register_op_cb(soc, (struct cdp_pdev *)pdev,
Yun Parkbaa62862017-01-18 13:43:34 -08003160 hdd_ipa_uc_op_event_handler, (void *)hdd_ctx);
3161
Yun Parkb4f591d2017-03-29 15:51:01 -07003162 for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
3163 hdd_ipa_init_uc_op_work(&hdd_ipa->uc_op_work[i].work,
Yun Parka4bb37c2017-12-08 16:14:22 -08003164 hdd_ipa_uc_fw_op_event_handler);
Yun Parkb4f591d2017-03-29 15:51:01 -07003165 hdd_ipa->uc_op_work[i].msg = NULL;
3166 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167
Yun Parkbaa62862017-01-18 13:43:34 -08003168fail_return:
Rajeev Kumar3887f9b2018-01-10 11:24:01 -08003169 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: status=%d", status);
Yun Parkb4f591d2017-03-29 15:51:01 -07003170 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171}
3172
Leo Change3e49442015-10-26 20:07:13 -07003173/**
Yun Parkd8fb1a82017-10-13 16:48:20 -07003174 * hdd_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3175 * @hdd_ipa: pointer to HDD IPA struct
3176 *
3177 * Return: none
3178 */
3179static void hdd_ipa_cleanup_pending_event(struct hdd_ipa_priv *hdd_ipa)
3180{
3181 struct ipa_uc_pending_event *pending_event = NULL;
3182
3183 while (qdf_list_remove_front(&hdd_ipa->pending_event,
3184 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3185 qdf_mem_free(pending_event);
3186}
3187
3188/**
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303189 * hdd_ipa_uc_ol_deinit() - Disconnect IPA TX and RX pipes
3190 * @hdd_ctx: Global HDD context
3191 *
3192 * Return: 0 on success, negativer errno on error
3193 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003194int hdd_ipa_uc_ol_deinit(struct hdd_context *hdd_ctx)
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303195{
3196 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
3197 int ret = 0;
Yun Parkb4f591d2017-03-29 15:51:01 -07003198 QDF_STATUS status;
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303199
Yun Parke4239802018-01-09 11:01:40 -08003200 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003201
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303202 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
3203 return ret;
3204
Sravan Kumar Kairam374a8682017-05-15 13:19:44 +05303205 if (!hdd_ipa->ipa_pipes_down)
3206 hdd_ipa_uc_disable_pipes(hdd_ipa);
3207
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303208 if (true == hdd_ipa->uc_loaded) {
Yun Parkb4f591d2017-03-29 15:51:01 -07003209 status = cdp_ipa_cleanup(cds_get_context(QDF_MODULE_ID_SOC),
3210 hdd_ipa->tx_pipe_handle,
3211 hdd_ipa->rx_pipe_handle);
3212 if (status) {
3213 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3214 "Failure to cleanup IPA pipes (status=%d)",
3215 status);
3216 return -EFAULT;
3217 }
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303218 }
3219
Yun Parka4bb37c2017-12-08 16:14:22 -08003220 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Parkd8fb1a82017-10-13 16:48:20 -07003221 hdd_ipa_cleanup_pending_event(hdd_ipa);
Yun Parka4bb37c2017-12-08 16:14:22 -08003222 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Parkd8fb1a82017-10-13 16:48:20 -07003223
Yun Parke4239802018-01-09 11:01:40 -08003224 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: ret=%d", ret);
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303225 return ret;
3226}
3227
3228/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003229 * __hdd_ipa_uc_force_pipe_shutdown() - Force shutdown IPA pipe
Leo Change3e49442015-10-26 20:07:13 -07003230 * @hdd_ctx: hdd main context
3231 *
3232 * Force shutdown IPA pipe
3233 * Independent of FW pipe status, IPA pipe shutdonw progress
3234 * in case, any STA does not leave properly, IPA HW pipe should cleaned up
3235 * independent from FW pipe status
3236 *
3237 * Return: NONE
3238 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003239static void __hdd_ipa_uc_force_pipe_shutdown(struct hdd_context *hdd_ctx)
Leo Change3e49442015-10-26 20:07:13 -07003240{
3241 struct hdd_ipa_priv *hdd_ipa;
3242
Yun Parke4239802018-01-09 11:01:40 -08003243 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003244
Leo Change3e49442015-10-26 20:07:13 -07003245 if (!hdd_ipa_is_enabled(hdd_ctx) || !hdd_ctx->hdd_ipa)
3246 return;
3247
3248 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
3249 if (false == hdd_ipa->ipa_pipes_down) {
Yun Park46255682017-10-09 15:56:34 -07003250 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Parkb4f591d2017-03-29 15:51:01 -07003251 "IPA pipes are not down yet, force shutdown");
Leo Change3e49442015-10-26 20:07:13 -07003252 hdd_ipa_uc_disable_pipes(hdd_ipa);
3253 } else {
Srinivas Girigowda97852372017-03-06 16:52:59 -08003254 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb4f591d2017-03-29 15:51:01 -07003255 "IPA pipes are down, do nothing");
Leo Change3e49442015-10-26 20:07:13 -07003256 }
Yun Parkfec73dc2017-09-06 10:40:07 -07003257
Yun Parke4239802018-01-09 11:01:40 -08003258 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
Leo Change3e49442015-10-26 20:07:13 -07003259}
3260
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003262 * hdd_ipa_uc_force_pipe_shutdown() - SSR wrapper for
3263 * __hdd_ipa_uc_force_pipe_shutdown
3264 * @hdd_ctx: hdd main context
3265 *
3266 * Force shutdown IPA pipe
3267 * Independent of FW pipe status, IPA pipe shutdonw progress
3268 * in case, any STA does not leave properly, IPA HW pipe should cleaned up
3269 * independent from FW pipe status
3270 *
3271 * Return: NONE
3272 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003273void hdd_ipa_uc_force_pipe_shutdown(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003274{
3275 cds_ssr_protect(__func__);
3276 __hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3277 cds_ssr_unprotect(__func__);
3278}
3279
3280/**
Govind Singh9c58eba2016-09-02 16:23:06 +05303281 * hdd_ipa_msg_free_fn() - Free an IPA message
3282 * @buff: pointer to the IPA message
3283 * @len: length of the IPA message
3284 * @type: type of IPA message
3285 *
3286 * Return: None
3287 */
3288static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
3289{
Srinivas Girigowda97852372017-03-06 16:52:59 -08003290 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "msg type:%d, len:%d", type, len);
Govind Singh9c58eba2016-09-02 16:23:06 +05303291 ghdd_ipa->stats.num_free_msg++;
3292 qdf_mem_free(buff);
3293}
3294
Govind Singh9c58eba2016-09-02 16:23:06 +05303295/**
jge62037862016-12-09 10:44:33 +08003296 * hdd_ipa_uc_send_evt() - send event to ipa
3297 * @hdd_ctx: pointer to hdd context
3298 * @type: event type
3299 * @mac_addr: pointer to mac address
3300 *
3301 * Send event to IPA driver
Govind Singh9c58eba2016-09-02 16:23:06 +05303302 *
3303 * Return: 0 - Success
3304 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003305static int hdd_ipa_uc_send_evt(struct hdd_adapter *adapter,
Yun Park6c86a662017-10-05 16:09:15 -07003306 qdf_ipa_wlan_event_t type, uint8_t *mac_addr)
Govind Singh9c58eba2016-09-02 16:23:06 +05303307{
jge62037862016-12-09 10:44:33 +08003308 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07003309 qdf_ipa_msg_meta_t meta;
3310 qdf_ipa_wlan_msg_t *msg;
Govind Singh9c58eba2016-09-02 16:23:06 +05303311 int ret = 0;
jge62037862016-12-09 10:44:33 +08003312
Yun Park6c86a662017-10-05 16:09:15 -07003313 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3314 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
jge62037862016-12-09 10:44:33 +08003315 if (msg == NULL) {
3316 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3317 "msg allocation failed");
3318 return -ENOMEM;
3319 }
3320
Yun Park6c86a662017-10-05 16:09:15 -07003321 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
3322 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), adapter->dev->name,
jge62037862016-12-09 10:44:33 +08003323 IPA_RESOURCE_NAME_MAX);
Yun Park6c86a662017-10-05 16:09:15 -07003324 memcpy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, ETH_ALEN);
Yun Park199c2ed2017-10-02 11:24:22 -07003325 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "%s: Evt: %d",
Yun Park6c86a662017-10-05 16:09:15 -07003326 QDF_IPA_WLAN_MSG_NAME(msg), QDF_IPA_MSG_META_MSG_TYPE(&meta));
3327 ret = qdf_ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
jge62037862016-12-09 10:44:33 +08003328 if (ret) {
3329 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3330 "%s: Evt: %d fail:%d",
Yun Park6c86a662017-10-05 16:09:15 -07003331 QDF_IPA_WLAN_MSG_NAME(msg),
3332 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
jge62037862016-12-09 10:44:33 +08003333 qdf_mem_free(msg);
3334 return ret;
3335 }
3336
3337 hdd_ipa->stats.num_send_msg++;
3338
3339 return ret;
3340}
3341
3342/**
3343 * hdd_ipa_uc_disconnect_client() - send client disconnect event
3344 * @hdd_ctx: pointer to hdd adapter
3345 *
3346 * Send disconnect client event to IPA driver during SSR
3347 *
3348 * Return: 0 - Success
3349 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003350static int hdd_ipa_uc_disconnect_client(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003351{
3352 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3353 int ret = 0;
Govind Singh9c58eba2016-09-02 16:23:06 +05303354 int i;
3355
Yun Parke4239802018-01-09 11:01:40 -08003356 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Govind Singh9c58eba2016-09-02 16:23:06 +05303357 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003358 if (qdf_is_macaddr_broadcast(&adapter->sta_info[i].sta_mac))
Govind Singh9c58eba2016-09-02 16:23:06 +05303359 continue;
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003360 if ((adapter->sta_info[i].in_use) &&
3361 (!adapter->sta_info[i].is_deauth_in_progress) &&
jge62037862016-12-09 10:44:33 +08003362 hdd_ipa->sap_num_connected_sta) {
3363 hdd_ipa_uc_send_evt(adapter, WLAN_CLIENT_DISCONNECT,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003364 adapter->sta_info[i].sta_mac.bytes);
jge62037862016-12-09 10:44:33 +08003365 hdd_ipa->sap_num_connected_sta--;
Govind Singh9c58eba2016-09-02 16:23:06 +05303366 }
3367 }
Yun Parke4239802018-01-09 11:01:40 -08003368 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07003369 hdd_ipa->sap_num_connected_sta);
Govind Singh9c58eba2016-09-02 16:23:06 +05303370
3371 return ret;
3372}
3373
3374/**
jge62037862016-12-09 10:44:33 +08003375 * hdd_ipa_uc_disconnect_ap() - send ap disconnect event
3376 * @hdd_ctx: pointer to hdd adapter
3377 *
3378 * Send disconnect ap event to IPA driver during SSR
Govind Singh9c58eba2016-09-02 16:23:06 +05303379 *
3380 * Return: 0 - Success
3381 */
jge62037862016-12-09 10:44:33 +08003382
Jeff Johnson49d45e62017-08-29 14:30:42 -07003383static int hdd_ipa_uc_disconnect_ap(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003384{
3385 int ret = 0;
3386
Yun Parke4239802018-01-09 11:01:40 -08003387 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003388 if (adapter->ipa_context) {
jge62037862016-12-09 10:44:33 +08003389 hdd_ipa_uc_send_evt(adapter, WLAN_AP_DISCONNECT,
3390 adapter->dev->dev_addr);
Yun Parkfec73dc2017-09-06 10:40:07 -07003391 }
Yun Parke4239802018-01-09 11:01:40 -08003392 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
jge62037862016-12-09 10:44:33 +08003393
3394 return ret;
3395}
3396
jge62037862016-12-09 10:44:33 +08003397/**
3398 * hdd_ipa_uc_disconnect_sta() - send sta disconnect event
3399 * @hdd_ctx: pointer to hdd adapter
3400 *
3401 * Send disconnect sta event to IPA driver during SSR
3402 *
3403 * Return: 0 - Success
3404 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003405static int hdd_ipa_uc_disconnect_sta(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003406{
Jeff Johnsond377dce2017-10-04 10:32:42 -07003407 struct hdd_station_ctx *sta_ctx;
jge62037862016-12-09 10:44:33 +08003408 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3409 int ret = 0;
3410
Yun Parke4239802018-01-09 11:01:40 -08003411 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08003412 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
jge62037862016-12-09 10:44:33 +08003413 hdd_ipa->sta_connected) {
Jeff Johnsond377dce2017-10-04 10:32:42 -07003414 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
jge62037862016-12-09 10:44:33 +08003415 hdd_ipa_uc_send_evt(adapter, WLAN_STA_DISCONNECT,
Jeff Johnsond377dce2017-10-04 10:32:42 -07003416 sta_ctx->conn_info.bssId.bytes);
jge62037862016-12-09 10:44:33 +08003417 }
Yun Parke4239802018-01-09 11:01:40 -08003418 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
jge62037862016-12-09 10:44:33 +08003419
3420 return ret;
3421}
jge62037862016-12-09 10:44:33 +08003422
3423/**
3424 * hdd_ipa_uc_disconnect() - send disconnect ipa event
3425 * @hdd_ctx: pointer to hdd context
3426 *
3427 * Send disconnect event to IPA driver during SSR
3428 *
3429 * Return: 0 - Success
3430 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003431static int hdd_ipa_uc_disconnect(struct hdd_context *hdd_ctx)
Govind Singh9c58eba2016-09-02 16:23:06 +05303432{
Jeff Johnson49d45e62017-08-29 14:30:42 -07003433 struct hdd_adapter *adapter;
Govind Singh9c58eba2016-09-02 16:23:06 +05303434 int ret = 0;
3435
Dustin Brown920397d2017-12-13 16:27:50 -08003436 hdd_for_each_adapter(hdd_ctx, adapter) {
jge62037862016-12-09 10:44:33 +08003437 if (adapter->device_mode == QDF_SAP_MODE) {
3438 hdd_ipa_uc_disconnect_client(adapter);
3439 hdd_ipa_uc_disconnect_ap(adapter);
3440 } else if (adapter->device_mode == QDF_STA_MODE) {
3441 hdd_ipa_uc_disconnect_sta(adapter);
3442 }
Govind Singh9c58eba2016-09-02 16:23:06 +05303443 }
3444
3445 return ret;
3446}
3447
3448/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003449 * __hdd_ipa_uc_ssr_deinit() - handle ipa deinit for SSR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003450 *
3451 * Deinit basic IPA UC host side to be in sync reloaded FW during
3452 * SSR
3453 *
3454 * Return: 0 - Success
3455 */
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003456static int __hdd_ipa_uc_ssr_deinit(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457{
3458 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3459 int idx;
3460 struct hdd_ipa_iface_context *iface_context;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003461 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462
Yun Parke4239802018-01-09 11:01:40 -08003463 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003464
Arun Khandavallicc544b32017-01-30 19:52:16 +05303465 if (!hdd_ipa)
3466 return 0;
3467
3468 hdd_ctx = hdd_ipa->hdd_ctx;
3469 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 return 0;
3471
jge62037862016-12-09 10:44:33 +08003472 /* send disconnect to ipa driver */
Arun Khandavallicc544b32017-01-30 19:52:16 +05303473 hdd_ipa_uc_disconnect(hdd_ctx);
jge62037862016-12-09 10:44:33 +08003474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475 /* Clean up HDD IPA interfaces */
3476 for (idx = 0; (hdd_ipa->num_iface > 0) &&
3477 (idx < HDD_IPA_MAX_IFACE); idx++) {
3478 iface_context = &hdd_ipa->iface_context[idx];
Manikandan Mohaneab58242017-02-17 14:21:53 -08003479 if (iface_context->adapter && iface_context->adapter->magic ==
3480 WLAN_HDD_ADAPTER_MAGIC)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 hdd_ipa_cleanup_iface(iface_context);
3482 }
Manikandan Mohaneab58242017-02-17 14:21:53 -08003483 hdd_ipa->num_iface = 0;
Yun Parka4bb37c2017-12-08 16:14:22 -08003484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485 /* After SSR, wlan driver reloads FW again. But we need to protect
3486 * IPA submodule during SSR transient state. So deinit basic IPA
3487 * UC host side to be in sync with reloaded FW during SSR
3488 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003489
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303490 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
3492 hdd_ipa->assoc_stas_map[idx].is_reserved = false;
3493 hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF;
3494 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303495 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003496
Guolei Bianca144d82016-11-10 11:07:42 +08003497 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
3498 hdd_ipa_uc_sta_reset_sta_connected(hdd_ipa);
3499
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003500 for (idx = 0; idx < HDD_IPA_UC_OPCODE_MAX; idx++) {
3501 cancel_work_sync(&hdd_ipa->uc_op_work[idx].work);
3502 qdf_mem_free(hdd_ipa->uc_op_work[idx].msg);
3503 hdd_ipa->uc_op_work[idx].msg = NULL;
3504 }
Yun Parkfec73dc2017-09-06 10:40:07 -07003505
Yun Parke4239802018-01-09 11:01:40 -08003506 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003507 return 0;
3508}
3509
3510/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003511 * hdd_ipa_uc_ssr_deinit() - SSR wrapper for __hdd_ipa_uc_ssr_deinit
3512 *
3513 * Deinit basic IPA UC host side to be in sync reloaded FW during
3514 * SSR
3515 *
3516 * Return: 0 - Success
3517 */
3518int hdd_ipa_uc_ssr_deinit(void)
3519{
3520 int ret;
3521
3522 cds_ssr_protect(__func__);
3523 ret = __hdd_ipa_uc_ssr_deinit();
3524 cds_ssr_unprotect(__func__);
3525
3526 return ret;
3527}
3528
3529/**
3530 * __hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 *
3532 * Init basic IPA UC host side to be in sync with reloaded FW after
3533 * SSR to resume IPA UC operations
3534 *
3535 * Return: 0 - Success
3536 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003537static int __hdd_ipa_uc_ssr_reinit(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539
Arun Khandavallicc544b32017-01-30 19:52:16 +05303540 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3541 int i;
3542 struct hdd_ipa_iface_context *iface_context = NULL;
Arun Khandavallicc544b32017-01-30 19:52:16 +05303543
Yun Parke4239802018-01-09 11:01:40 -08003544 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003545
Arun Khandavallicc544b32017-01-30 19:52:16 +05303546 if (!hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx))
3547 return 0;
3548
Arun Khandavallicc544b32017-01-30 19:52:16 +05303549 /* Create the interface context */
3550 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
3551 iface_context = &hdd_ipa->iface_context[i];
3552 iface_context->hdd_ipa = hdd_ipa;
3553 iface_context->cons_client =
3554 hdd_ipa_adapter_2_client[i].cons_client;
3555 iface_context->prod_client =
3556 hdd_ipa_adapter_2_client[i].prod_client;
3557 iface_context->iface_id = i;
3558 iface_context->adapter = NULL;
3559 }
Arun Khandavallicc544b32017-01-30 19:52:16 +05303560
3561 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
3562 hdd_ipa->resource_loading = false;
3563 hdd_ipa->resource_unloading = false;
3564 hdd_ipa->sta_connected = 0;
3565 hdd_ipa->ipa_pipes_down = true;
3566 hdd_ipa->uc_loaded = true;
Arun Khandavallicc544b32017-01-30 19:52:16 +05303567 }
3568
Yun Parke4239802018-01-09 11:01:40 -08003569 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 return 0;
3571}
Leo Chang3bc8fed2015-11-13 10:59:47 -08003572
3573/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003574 * hdd_ipa_uc_ssr_reinit() - SSR wrapper for __hdd_ipa_uc_ssr_reinit
3575 *
3576 * Init basic IPA UC host side to be in sync with reloaded FW after
3577 * SSR to resume IPA UC operations
3578 *
3579 * Return: 0 - Success
3580 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003581int hdd_ipa_uc_ssr_reinit(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003582{
3583 int ret;
3584
3585 cds_ssr_protect(__func__);
Arun Khandavallicc544b32017-01-30 19:52:16 +05303586 ret = __hdd_ipa_uc_ssr_reinit(hdd_ctx);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003587 cds_ssr_unprotect(__func__);
3588
3589 return ret;
3590}
3591
3592/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003593 * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
3594 * @work: scheduled work
3595 *
3596 * When IPA resources are released in hdd_ipa_rm_try_release() we do
3597 * not want to immediately release the wake lock since the system
3598 * would then potentially try to suspend when there is a healthy data
3599 * rate. Deferred work is scheduled and this function handles the
3600 * work. When this function is called, if the IPA resource is still
3601 * released then we release the wake lock.
3602 *
3603 * Return: None
3604 */
3605static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
3606{
3607 struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
3608 struct hdd_ipa_priv,
3609 wake_lock_work);
3610
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303611 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612
3613 if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
3614 goto end;
3615
3616 hdd_ipa->wake_lock_released = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303617 qdf_wake_lock_release(&hdd_ipa->wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 WIFI_POWER_EVENT_WAKELOCK_IPA);
3619
3620end:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303621 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622}
3623
3624/**
3625 * hdd_ipa_rm_request() - Request resource from IPA
3626 * @hdd_ipa: Global HDD IPA context
3627 *
3628 * Return: 0 on success, negative errno on error
3629 */
3630static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa)
3631{
3632 int ret = 0;
3633
3634 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3635 return 0;
3636
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303637 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638
3639 switch (hdd_ipa->rm_state) {
3640 case HDD_IPA_RM_GRANTED:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303641 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 return 0;
3643 case HDD_IPA_RM_GRANT_PENDING:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303644 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 return -EINPROGRESS;
3646 case HDD_IPA_RM_RELEASED:
3647 hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
3648 break;
3649 }
3650
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303651 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652
Yun Park6c86a662017-10-05 16:09:15 -07003653 ret = qdf_ipa_rm_inactivity_timer_request_resource(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 IPA_RM_RESOURCE_WLAN_PROD);
3655
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303656 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657 if (ret == 0) {
3658 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
3659 hdd_ipa->stats.num_rm_grant_imm++;
3660 }
3661
3662 cancel_delayed_work(&hdd_ipa->wake_lock_work);
3663 if (hdd_ipa->wake_lock_released) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303664 qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 WIFI_POWER_EVENT_WAKELOCK_IPA);
3666 hdd_ipa->wake_lock_released = false;
3667 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303668 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669
3670 return ret;
3671}
3672
3673/**
3674 * hdd_ipa_rm_try_release() - Attempt to release IPA resource
3675 * @hdd_ipa: Global HDD IPA context
3676 *
3677 * Return: 0 if resources released, negative errno otherwise
3678 */
3679static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
3680{
3681 int ret = 0;
3682
3683 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3684 return 0;
3685
3686 if (atomic_read(&hdd_ipa->tx_ref_cnt))
3687 return -EAGAIN;
3688
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303689 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690
Nirav Shahcbc6d722016-03-01 16:24:53 +05303691 if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303692 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003693 return -EAGAIN;
3694 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303695 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303697 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 switch (hdd_ipa->rm_state) {
3699 case HDD_IPA_RM_GRANTED:
3700 break;
3701 case HDD_IPA_RM_GRANT_PENDING:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303702 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703 return -EINPROGRESS;
3704 case HDD_IPA_RM_RELEASED:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303705 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 return 0;
3707 }
3708
3709 /* IPA driver returns immediately so set the state here to avoid any
3710 * race condition.
3711 */
3712 hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
3713 hdd_ipa->stats.num_rm_release++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303714 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715
Yun Park6c86a662017-10-05 16:09:15 -07003716 ret = qdf_ipa_rm_inactivity_timer_release_resource(
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07003717 IPA_RM_RESOURCE_WLAN_PROD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003718
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303719 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003720 if (unlikely(ret != 0)) {
3721 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
3722 WARN_ON(1);
Yun Park199c2ed2017-10-02 11:24:22 -07003723 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
3724 "ipa_rm_inactivity_timer_release_resource returnied fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725 }
3726
3727 /*
3728 * If wake_lock is released immediately, kernel would try to suspend
3729 * immediately as well, Just avoid ping-pong between suspend-resume
3730 * while there is healthy amount of data transfer going on by
3731 * releasing the wake_lock after some delay.
3732 */
3733 schedule_delayed_work(&hdd_ipa->wake_lock_work,
3734 msecs_to_jiffies
3735 (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
3736
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303737 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003738
3739 return ret;
3740}
3741
3742/**
3743 * hdd_ipa_rm_notify() - IPA resource manager notifier callback
3744 * @user_data: user data registered with IPA
3745 * @event: the IPA resource manager event that occurred
3746 * @data: the data associated with the event
3747 *
3748 * Return: None
3749 */
Yun Park6c86a662017-10-05 16:09:15 -07003750static void hdd_ipa_rm_notify(void *user_data, qdf_ipa_rm_event_t event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751 unsigned long data)
3752{
3753 struct hdd_ipa_priv *hdd_ipa = user_data;
3754
3755 if (unlikely(!hdd_ipa))
3756 return;
3757
3758 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3759 return;
3760
Srinivas Girigowda97852372017-03-06 16:52:59 -08003761 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762
3763 switch (event) {
3764 case IPA_RM_RESOURCE_GRANTED:
3765 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
3766 /* RM Notification comes with ISR context
3767 * it should be serialized into work queue to avoid
3768 * ISR sleep problem
3769 */
3770 hdd_ipa->uc_rm_work.event = event;
3771 schedule_work(&hdd_ipa->uc_rm_work.work);
3772 break;
3773 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303774 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003775 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303776 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003777 hdd_ipa->stats.num_rm_grant++;
3778 break;
3779
3780 case IPA_RM_RESOURCE_RELEASED:
Srinivas Girigowda97852372017-03-06 16:52:59 -08003781 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 hdd_ipa->resource_unloading = false;
3783 break;
3784
3785 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303786 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 break;
3788 }
3789}
3790
3791/**
3792 * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
3793 *
3794 * Callback function registered with IPA that is called when IPA wants
3795 * to release the WLAN consumer resource
3796 *
3797 * Return: 0 if the request is granted, negative errno otherwise
3798 */
3799static int hdd_ipa_rm_cons_release(void)
3800{
3801 return 0;
3802}
3803
3804/**
3805 * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
3806 *
3807 * Callback function registered with IPA that is called when IPA wants
3808 * to access the WLAN consumer resource
3809 *
3810 * Return: 0 if the request is granted, negative errno otherwise
3811 */
3812static int hdd_ipa_rm_cons_request(void)
3813{
Yun Park4d8b60a2015-10-22 13:59:32 -07003814 int ret = 0;
3815
3816 if (ghdd_ipa->resource_loading) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303817 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
Yun Parkb4f591d2017-03-29 15:51:01 -07003818 "IPA resource loading in progress");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819 ghdd_ipa->pending_cons_req = true;
Yun Park4d8b60a2015-10-22 13:59:32 -07003820 ret = -EINPROGRESS;
3821 } else if (ghdd_ipa->resource_unloading) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303822 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
Yun Parkb4f591d2017-03-29 15:51:01 -07003823 "IPA resource unloading in progress");
Yun Park4d8b60a2015-10-22 13:59:32 -07003824 ghdd_ipa->pending_cons_req = true;
3825 ret = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 }
Yun Park4d8b60a2015-10-22 13:59:32 -07003827
3828 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829}
3830
3831/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003832 * __hdd_ipa_set_perf_level() - Set IPA performance level
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003833 * @hdd_ctx: Global HDD context
3834 * @tx_packets: Number of packets transmitted in the last sample period
3835 * @rx_packets: Number of packets received in the last sample period
3836 *
3837 * Return: 0 on success, negative errno on error
3838 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07003839static int __hdd_ipa_set_perf_level(struct hdd_context *hdd_ctx,
3840 uint64_t tx_packets,
3841 uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842{
3843 uint32_t next_cons_bw, next_prod_bw;
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003844 struct hdd_ipa_priv *hdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07003845 qdf_ipa_rm_perf_profile_t profile;
Yun Parkb4f591d2017-03-29 15:51:01 -07003846 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 int ret;
3848
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003849 if (wlan_hdd_validate_context(hdd_ctx))
3850 return 0;
3851
3852 hdd_ipa = hdd_ctx->hdd_ipa;
3853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 if ((!hdd_ipa_is_enabled(hdd_ctx)) ||
3855 (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)))
3856 return 0;
3857
3858 memset(&profile, 0, sizeof(profile));
3859
3860 if (tx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2))
3861 next_cons_bw = hdd_ctx->config->IpaHighBandwidthMbps;
3862 else if (tx_packets >
3863 (hdd_ctx->config->busBandwidthMediumThreshold / 2))
3864 next_cons_bw = hdd_ctx->config->IpaMediumBandwidthMbps;
3865 else
3866 next_cons_bw = hdd_ctx->config->IpaLowBandwidthMbps;
3867
3868 if (rx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2))
3869 next_prod_bw = hdd_ctx->config->IpaHighBandwidthMbps;
3870 else if (rx_packets >
3871 (hdd_ctx->config->busBandwidthMediumThreshold / 2))
3872 next_prod_bw = hdd_ctx->config->IpaMediumBandwidthMbps;
3873 else
3874 next_prod_bw = hdd_ctx->config->IpaLowBandwidthMbps;
3875
Yun Parkec845302016-12-15 09:22:57 -08003876 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 "CONS perf curr: %d, next: %d",
3878 hdd_ipa->curr_cons_bw, next_cons_bw);
Yun Parkec845302016-12-15 09:22:57 -08003879 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880 "PROD perf curr: %d, next: %d",
3881 hdd_ipa->curr_prod_bw, next_prod_bw);
3882
3883 if (hdd_ipa->curr_cons_bw != next_cons_bw) {
Yun Parkb187d542016-11-14 18:10:04 -08003884 hdd_debug("Requesting CONS perf curr: %d, next: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 hdd_ipa->curr_cons_bw, next_cons_bw);
Yun Parkb4f591d2017-03-29 15:51:01 -07003886 ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_CONS,
3887 next_cons_bw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003888 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08003889 hdd_err("RM CONS set perf profile failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003890
3891 return ret;
3892 }
3893 hdd_ipa->curr_cons_bw = next_cons_bw;
3894 hdd_ipa->stats.num_cons_perf_req++;
3895 }
3896
3897 if (hdd_ipa->curr_prod_bw != next_prod_bw) {
Yun Parkb187d542016-11-14 18:10:04 -08003898 hdd_debug("Requesting PROD perf curr: %d, next: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899 hdd_ipa->curr_prod_bw, next_prod_bw);
Yun Parkb4f591d2017-03-29 15:51:01 -07003900 ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_PROD,
3901 next_prod_bw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08003903 hdd_err("RM PROD set perf profile failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 return ret;
3905 }
3906 hdd_ipa->curr_prod_bw = next_prod_bw;
3907 hdd_ipa->stats.num_prod_perf_req++;
3908 }
3909
3910 return 0;
3911}
3912
3913/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003914 * hdd_ipa_set_perf_level() - SSR wrapper for __hdd_ipa_set_perf_level
3915 * @hdd_ctx: Global HDD context
3916 * @tx_packets: Number of packets transmitted in the last sample period
3917 * @rx_packets: Number of packets received in the last sample period
3918 *
3919 * Return: 0 on success, negative errno on error
3920 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003921int hdd_ipa_set_perf_level(struct hdd_context *hdd_ctx, uint64_t tx_packets,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003922 uint64_t rx_packets)
3923{
3924 int ret;
3925
3926 cds_ssr_protect(__func__);
3927 ret = __hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
3928 cds_ssr_unprotect(__func__);
3929
3930 return ret;
3931}
3932
3933/**
Rajeev Kumar217f2172016-01-06 18:11:55 -08003934 * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
3935 * @work: struct work_struct
3936 * @work_handler: work_handler
3937 *
3938 * Return: none
3939 */
Rajeev Kumar217f2172016-01-06 18:11:55 -08003940static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
3941 work_func_t work_handler)
3942{
3943 INIT_WORK(work, work_handler);
3944}
Rajeev Kumar217f2172016-01-06 18:11:55 -08003945
3946/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003947 * hdd_ipa_setup_rm() - Setup IPA resource management
3948 * @hdd_ipa: Global HDD IPA context
3949 *
3950 * Return: 0 on success, negative errno on error
3951 */
3952static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa)
3953{
Yun Park6c86a662017-10-05 16:09:15 -07003954 qdf_ipa_rm_create_params_t create_params = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003955 int ret;
3956
3957 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3958 return 0;
3959
Rajeev Kumar217f2172016-01-06 18:11:55 -08003960 hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
3961 hdd_ipa_uc_rm_notify_defer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003962 memset(&create_params, 0, sizeof(create_params));
Yun Park6c86a662017-10-05 16:09:15 -07003963 QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
3964 IPA_RM_RESOURCE_WLAN_PROD;
3965 QDF_IPA_RM_CREATE_PARAMS_USER_DATA(&create_params) =
3966 hdd_ipa;
3967 QDF_IPA_RM_CREATE_PARAMS_NOTIFY_CB(&create_params) =
3968 hdd_ipa_rm_notify;
3969 QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
3970 IPA_VOLTAGE_SVS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971
Yun Park6c86a662017-10-05 16:09:15 -07003972 ret = qdf_ipa_rm_create_resource(&create_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303974 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 "Create RM resource failed: %d", ret);
3976 goto setup_rm_fail;
3977 }
3978
3979 memset(&create_params, 0, sizeof(create_params));
Yun Park6c86a662017-10-05 16:09:15 -07003980 QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
3981 IPA_RM_RESOURCE_WLAN_CONS;
3982 QDF_IPA_RM_CREATE_PARAMS_REQUEST_RESOURCE(&create_params) =
3983 hdd_ipa_rm_cons_request;
3984 QDF_IPA_RM_CREATE_PARAMS_RELEASE_RESOURCE(&create_params) =
3985 hdd_ipa_rm_cons_release;
3986 QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
3987 IPA_VOLTAGE_SVS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988
Yun Park6c86a662017-10-05 16:09:15 -07003989 ret = qdf_ipa_rm_create_resource(&create_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303991 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 "Create RM CONS resource failed: %d", ret);
3993 goto delete_prod;
3994 }
3995
3996 ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
3997 IPA_RM_RESOURCE_APPS_CONS);
3998
Yun Park6c86a662017-10-05 16:09:15 -07003999 ret = qdf_ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
4000 HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304002 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003 ret);
4004 goto timer_init_failed;
4005 }
4006
4007 /* Set the lowest bandwidth to start with */
4008 ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
4009
4010 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304011 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004012 "Set perf level failed: %d", ret);
4013 goto set_perf_failed;
4014 }
4015
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304016 qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
4018 hdd_ipa_wake_lock_timer_func);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304019 qdf_spinlock_create(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
4021 hdd_ipa->wake_lock_released = true;
4022 atomic_set(&hdd_ipa->tx_ref_cnt, 0);
4023
4024 return ret;
4025
4026set_perf_failed:
4027 ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
4028
4029timer_init_failed:
4030 ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
4031
4032delete_prod:
4033 ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
4034
4035setup_rm_fail:
4036 return ret;
4037}
4038
4039/**
4040 * hdd_ipa_destroy_rm_resource() - Destroy IPA resources
4041 * @hdd_ipa: Global HDD IPA context
4042 *
4043 * Destroys all resources associated with the IPA resource manager
4044 *
4045 * Return: None
4046 */
4047static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa)
4048{
4049 int ret;
4050
4051 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4052 return;
4053
4054 cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304055 qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 cancel_work_sync(&hdd_ipa->uc_rm_work.work);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304058 qdf_spinlock_destroy(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004059
4060 ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
4061
Yun Park6c86a662017-10-05 16:09:15 -07004062 ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 if (ret)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304064 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004065 "RM PROD resource delete failed %d", ret);
4066
Yun Park6c86a662017-10-05 16:09:15 -07004067 ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 if (ret)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304069 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004070 "RM CONS resource delete failed %d", ret);
4071}
4072
tfyu0380a972017-07-13 18:19:37 +08004073#ifdef QCA_CONFIG_SMP
4074static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
4075{
4076 return netif_rx_ni(skb);
4077}
4078#else
4079static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
4080{
4081 struct iphdr *ip_h;
4082 static atomic_t softirq_mitigation_cntr =
4083 ATOMIC_INIT(IPA_WLAN_RX_SOFTIRQ_THRESH);
4084 int result;
4085
4086 ip_h = (struct iphdr *)(skb->data);
4087 if ((skb->protocol == htons(ETH_P_IP)) &&
4088 (ip_h->protocol == IPPROTO_ICMP)) {
4089 result = netif_rx_ni(skb);
4090 } else {
4091 /* Call netif_rx_ni for every IPA_WLAN_RX_SOFTIRQ_THRESH packets
4092 * to avoid excessive softirq's.
4093 */
4094 if (atomic_dec_and_test(&softirq_mitigation_cntr)) {
4095 result = netif_rx_ni(skb);
4096 atomic_set(&softirq_mitigation_cntr,
4097 IPA_WLAN_RX_SOFTIRQ_THRESH);
4098 } else {
4099 result = netif_rx(skb);
4100 }
4101 }
4102
4103 return result;
4104}
4105#endif
4106
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004107/**
4108 * hdd_ipa_send_skb_to_network() - Send skb to kernel
4109 * @skb: network buffer
4110 * @adapter: network adapter
4111 *
4112 * Called when a network buffer is received which should not be routed
4113 * to the IPA module.
4114 *
4115 * Return: None
4116 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304117static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004118 struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004119{
tfyu0380a972017-07-13 18:19:37 +08004120 int result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
4122 unsigned int cpu_index;
4123
4124 if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07004125 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Invalid adapter: 0x%pK",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 adapter);
Yun Park46255682017-10-09 15:56:34 -07004127 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004128 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 return;
4130 }
4131
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004132 if (cds_is_driver_unloading()) {
Yun Park46255682017-10-09 15:56:34 -07004133 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004134 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135 return;
4136 }
4137
4138 skb->destructor = hdd_ipa_uc_rt_debug_destructor;
4139 skb->dev = adapter->dev;
4140 skb->protocol = eth_type_trans(skb, skb->dev);
4141 skb->ip_summed = CHECKSUM_NONE;
4142
4143 cpu_index = wlan_hdd_get_cpu();
4144
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004145 ++adapter->hdd_stats.tx_rx_stats.rx_packets[cpu_index];
tfyu0380a972017-07-13 18:19:37 +08004146 result = hdd_ipa_aggregated_rx_ind(skb);
4147 if (result == NET_RX_SUCCESS)
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004148 ++adapter->hdd_stats.tx_rx_stats.rx_delivered[cpu_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004149 else
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004150 ++adapter->hdd_stats.tx_rx_stats.rx_refused[cpu_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151
Yun Park46255682017-10-09 15:56:34 -07004152 hdd_ipa->ipa_rx_net_send_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153}
4154
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155/**
Leo Chang69c39692016-10-12 20:11:12 -07004156 * hdd_ipa_forward() - handle packet forwarding to wlan tx
4157 * @hdd_ipa: pointer to hdd ipa context
4158 * @adapter: network adapter
4159 * @skb: data pointer
4160 *
4161 * if exception packet has set forward bit, copied new packet should be
4162 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
4163 * put into pm queue and tx procedure will be differed
4164 *
4165 * Return: None
4166 */
Jeff Johnson414f7ea2016-10-19 18:50:02 -07004167static void hdd_ipa_forward(struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004168 struct hdd_adapter *adapter, qdf_nbuf_t skb)
Leo Chang69c39692016-10-12 20:11:12 -07004169{
Leo Chang69c39692016-10-12 20:11:12 -07004170 struct hdd_ipa_pm_tx_cb *pm_tx_cb;
4171
Leo Chang69c39692016-10-12 20:11:12 -07004172 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Yun Park01deb2c2017-06-14 15:21:44 -07004173
4174 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
4175 qdf_nbuf_ipa_owned_set(skb);
4176
Yun Park46255682017-10-09 15:56:34 -07004177 /* WLAN subsystem is in suspend, put in queue */
Leo Chang69c39692016-10-12 20:11:12 -07004178 if (hdd_ipa->suspended) {
4179 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Yun Park46255682017-10-09 15:56:34 -07004180 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
4181 "Tx in suspend, put in queue");
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004182 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
4183 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Leo Chang69c39692016-10-12 20:11:12 -07004184 pm_tx_cb->exception = true;
4185 pm_tx_cb->adapter = adapter;
4186 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004187 qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb);
Leo Chang69c39692016-10-12 20:11:12 -07004188 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
4189 hdd_ipa->stats.num_tx_queued++;
4190 } else {
4191 /* Resume, put packet into WLAN TX */
4192 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004193 if (hdd_softap_hard_start_xmit(skb, adapter->dev)) {
Leo Chang69c39692016-10-12 20:11:12 -07004194 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07004195 "packet Tx fail");
Yun Parkb187d542016-11-14 18:10:04 -08004196 hdd_ipa->stats.num_tx_fwd_err++;
Leo Chang69c39692016-10-12 20:11:12 -07004197 } else {
Yun Parkb187d542016-11-14 18:10:04 -08004198 hdd_ipa->stats.num_tx_fwd_ok++;
Leo Chang69c39692016-10-12 20:11:12 -07004199 }
4200 }
4201}
4202
4203/**
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004204 * hdd_ipa_intrabss_forward() - Forward intra bss packets.
4205 * @hdd_ipa: pointer to HDD IPA struct
4206 * @adapter: hdd adapter pointer
4207 * @desc: Firmware descriptor
4208 * @skb: Data buffer
4209 *
4210 * Return:
4211 * HDD_IPA_FORWARD_PKT_NONE
4212 * HDD_IPA_FORWARD_PKT_DISCARD
4213 * HDD_IPA_FORWARD_PKT_LOCAL_STACK
4214 *
4215 */
4216
4217static enum hdd_ipa_forward_type hdd_ipa_intrabss_forward(
4218 struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004219 struct hdd_adapter *adapter,
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004220 uint8_t desc,
4221 qdf_nbuf_t skb)
4222{
4223 int ret = HDD_IPA_FORWARD_PKT_NONE;
Yun Park0dad1002017-07-14 14:57:01 -07004224 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4225 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004226
4227 if ((desc & FW_RX_DESC_FORWARD_M)) {
Poddar, Siddarth8e3ee2d2016-11-29 20:17:01 +05304228 if (!ol_txrx_fwd_desc_thresh_check(
Yun Park0dad1002017-07-14 14:57:01 -07004229 (struct ol_txrx_vdev_t *)cdp_get_vdev_from_vdev_id(soc,
4230 (struct cdp_pdev *)pdev,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004231 adapter->session_id))) {
Poddar, Siddarth8e3ee2d2016-11-29 20:17:01 +05304232 /* Drop the packet*/
4233 hdd_ipa->stats.num_tx_fwd_err++;
4234 kfree_skb(skb);
4235 ret = HDD_IPA_FORWARD_PKT_DISCARD;
4236 return ret;
4237 }
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004238 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
4239 "Forward packet to Tx (fw_desc=%d)", desc);
4240 hdd_ipa->ipa_tx_forward++;
4241
4242 if ((desc & FW_RX_DESC_DISCARD_M)) {
4243 hdd_ipa_forward(hdd_ipa, adapter, skb);
Yun Park46255682017-10-09 15:56:34 -07004244 hdd_ipa->ipa_rx_internal_drop_count++;
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004245 hdd_ipa->ipa_rx_discard++;
4246 ret = HDD_IPA_FORWARD_PKT_DISCARD;
4247 } else {
4248 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07004249
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004250 if (cloned_skb)
4251 hdd_ipa_forward(hdd_ipa, adapter, cloned_skb);
4252 else
4253 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07004254 "tx skb alloc failed");
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004255 ret = HDD_IPA_FORWARD_PKT_LOCAL_STACK;
4256 }
4257 }
4258
4259 return ret;
4260}
4261
4262/**
Yun Park637d6482016-10-05 10:51:33 -07004263 * __hdd_ipa_w2i_cb() - WLAN to IPA callback handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 * @priv: pointer to private data registered with IPA (we register a
4265 * pointer to the global IPA context)
4266 * @evt: the IPA event which triggered the callback
4267 * @data: data associated with the event
4268 *
4269 * Return: None
4270 */
Yun Park6c86a662017-10-05 16:09:15 -07004271static void __hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
4272 unsigned long data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273{
4274 struct hdd_ipa_priv *hdd_ipa = NULL;
Jeff Johnson49d45e62017-08-29 14:30:42 -07004275 struct hdd_adapter *adapter = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304276 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004277 uint8_t iface_id;
4278 uint8_t session_id;
4279 struct hdd_ipa_iface_context *iface_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280 uint8_t fw_desc;
Yun Parkf8d6a122016-10-11 15:49:43 -07004281 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282
4283 hdd_ipa = (struct hdd_ipa_priv *)priv;
4284
Prakash Dhavali63f8fd62016-11-14 14:40:42 -08004285 if (!hdd_ipa || wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
4286 return;
4287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004288 switch (evt) {
4289 case IPA_RECEIVE:
Nirav Shahcbc6d722016-03-01 16:24:53 +05304290 skb = (qdf_nbuf_t) data;
Yun Parkf8d6a122016-10-11 15:49:43 -07004291
4292 /*
4293 * When SSR is going on or driver is unloading,
4294 * just drop the packets.
4295 */
4296 status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
4297 if (0 != status) {
4298 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4299 "Invalid context: drop packet");
Yun Park46255682017-10-09 15:56:34 -07004300 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004301 kfree_skb(skb);
4302 return;
4303 }
4304
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
4306 session_id = (uint8_t)skb->cb[0];
Prakash Dhavali89d406d2016-11-23 11:11:00 -08004307 iface_id = hdd_ipa->vdev_to_iface[session_id];
Srinivas Girigowda97852372017-03-06 16:52:59 -08004308 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004309 "IPA_RECEIVE: session_id=%u, iface_id=%u",
4310 session_id, iface_id);
4311 } else {
4312 iface_id = HDD_IPA_GET_IFACE_ID(skb->data);
4313 }
4314
4315 if (iface_id >= HDD_IPA_MAX_IFACE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304316 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317 "IPA_RECEIVE: Invalid iface_id: %u",
4318 iface_id);
Srinivas Girigowda97852372017-03-06 16:52:59 -08004319 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb187d542016-11-14 18:10:04 -08004320 "w2i -- skb",
4321 skb->data, HDD_IPA_DBG_DUMP_RX_LEN);
Yun Park46255682017-10-09 15:56:34 -07004322 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004323 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 return;
4325 }
4326
4327 iface_context = &hdd_ipa->iface_context[iface_id];
4328 adapter = iface_context->adapter;
Yun Park16a78262017-02-01 12:15:03 -08004329 if (!adapter) {
4330 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4331 "IPA_RECEIVE: Adapter is NULL");
Yun Park46255682017-10-09 15:56:34 -07004332 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Park16a78262017-02-01 12:15:03 -08004333 kfree_skb(skb);
4334 return;
4335 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304337 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb187d542016-11-14 18:10:04 -08004338 "w2i -- skb",
4339 skb->data, HDD_IPA_DBG_DUMP_RX_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004340 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
4341 hdd_ipa->stats.num_rx_excep++;
4342 skb_pull(skb, HDD_IPA_UC_WLAN_CLD_HDR_LEN);
4343 } else {
4344 skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN);
4345 }
4346
4347 iface_context->stats.num_rx_ipa_excep++;
4348
4349 /* Disable to forward Intra-BSS Rx packets when
4350 * ap_isolate=1 in hostapd.conf
4351 */
Jeff Johnsonb9424862017-10-30 08:49:35 -07004352 if (!adapter->session.ap.disable_intrabss_fwd) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 /*
4354 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
4355 * all Rx packets to IPA uC, which need to be forwarded
4356 * to other interface.
4357 * And, IPA driver will send back to WLAN host driver
4358 * through exception pipe with fw_desc field set by FW.
4359 * Here we are checking fw_desc field for FORWARD bit
4360 * set, and forward to Tx. Then copy to kernel stack
4361 * only when DISCARD bit is not set.
4362 */
4363 fw_desc = (uint8_t)skb->cb[1];
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004364 if (HDD_IPA_FORWARD_PKT_DISCARD ==
4365 hdd_ipa_intrabss_forward(hdd_ipa, adapter,
4366 fw_desc, skb))
Mahesh Kumar Kalikot Veetil221dc672015-11-06 14:27:28 -08004367 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 } else {
Srinivas Girigowda97852372017-03-06 16:52:59 -08004369 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370 "Intra-BSS FWD is disabled-skip forward to Tx");
4371 }
4372
4373 hdd_ipa_send_skb_to_network(skb, adapter);
4374 break;
4375
4376 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304377 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 "w2i cb wrong event: 0x%x", evt);
4379 return;
4380 }
4381}
4382
4383/**
Yun Parkf8d6a122016-10-11 15:49:43 -07004384 * hdd_ipa_w2i_cb() - SSR wrapper for __hdd_ipa_w2i_cb
4385 * @priv: pointer to private data registered with IPA (we register a
4386 * pointer to the global IPA context)
4387 * @evt: the IPA event which triggered the callback
4388 * @data: data associated with the event
4389 *
4390 * Return: None
4391 */
Yun Park6c86a662017-10-05 16:09:15 -07004392static void hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Yun Parkf8d6a122016-10-11 15:49:43 -07004393 unsigned long data)
4394{
4395 cds_ssr_protect(__func__);
4396 __hdd_ipa_w2i_cb(priv, evt, data);
4397 cds_ssr_unprotect(__func__);
4398}
4399
4400/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 * hdd_ipa_nbuf_cb() - IPA TX complete callback
4402 * @skb: packet buffer which was transmitted
4403 *
4404 * Return: None
4405 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304406void hdd_ipa_nbuf_cb(qdf_nbuf_t skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004407{
4408 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07004409 qdf_ipa_rx_data_t *ipa_tx_desc;
Yun Park52b2b992016-09-22 15:49:51 -07004410 struct hdd_ipa_tx_desc *tx_desc;
4411 uint16_t id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412
Yun Park52b2b992016-09-22 15:49:51 -07004413 if (!qdf_nbuf_ipa_owned_get(skb)) {
4414 dev_kfree_skb_any(skb);
4415 return;
4416 }
4417
4418 /* Get Tx desc pointer from SKB CB */
4419 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
4420 tx_desc = hdd_ipa->tx_desc_list + id;
4421 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
4422
4423 /* Return Tx Desc to IPA */
4424 ipa_free_skb(ipa_tx_desc);
4425
4426 /* Return to free tx desc list */
4427 qdf_spin_lock_bh(&hdd_ipa->q_lock);
4428 tx_desc->ipa_tx_desc_ptr = NULL;
4429 list_add_tail(&tx_desc->link, &hdd_ipa->free_tx_desc_head);
4430 hdd_ipa->stats.num_tx_desc_q_cnt--;
4431 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004432
4433 hdd_ipa->stats.num_tx_comp_cnt++;
4434
4435 atomic_dec(&hdd_ipa->tx_ref_cnt);
4436
4437 hdd_ipa_rm_try_release(hdd_ipa);
4438}
4439
4440/**
4441 * hdd_ipa_send_pkt_to_tl() - Send an IPA packet to TL
4442 * @iface_context: interface-specific IPA context
4443 * @ipa_tx_desc: packet data descriptor
4444 *
4445 * Return: None
4446 */
4447static void hdd_ipa_send_pkt_to_tl(
4448 struct hdd_ipa_iface_context *iface_context,
Yun Park6c86a662017-10-05 16:09:15 -07004449 qdf_ipa_rx_data_t *ipa_tx_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004450{
4451 struct hdd_ipa_priv *hdd_ipa = iface_context->hdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07004452 struct hdd_adapter *adapter = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304453 qdf_nbuf_t skb;
Yun Park52b2b992016-09-22 15:49:51 -07004454 struct hdd_ipa_tx_desc *tx_desc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004455
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304456 qdf_spin_lock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004457 adapter = iface_context->adapter;
4458 if (!adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304459 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN, "Interface Down");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460 ipa_free_skb(ipa_tx_desc);
4461 iface_context->stats.num_tx_drop++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304462 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 hdd_ipa_rm_try_release(hdd_ipa);
4464 return;
4465 }
4466
4467 /*
4468 * During CAC period, data packets shouldn't be sent over the air so
4469 * drop all the packets here
4470 */
hqu70708ab2017-10-10 17:52:01 +08004471 if (QDF_SAP_MODE == adapter->device_mode ||
4472 QDF_P2P_GO_MODE == adapter->device_mode) {
4473 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->dfs_cac_block_tx) {
4474 ipa_free_skb(ipa_tx_desc);
4475 qdf_spin_unlock_bh(&iface_context->interface_lock);
4476 iface_context->stats.num_tx_cac_drop++;
4477 hdd_ipa_rm_try_release(hdd_ipa);
4478 return;
4479 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004480 }
4481
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 ++adapter->stats.tx_packets;
4483
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304484 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485
Yun Park6c86a662017-10-05 16:09:15 -07004486 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304488 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Yun Park52b2b992016-09-22 15:49:51 -07004489
4490 /* Store IPA Tx buffer ownership into SKB CB */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304491 qdf_nbuf_ipa_owned_set(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
Nirav Shahcbc6d722016-03-01 16:24:53 +05304493 qdf_nbuf_mapped_paddr_set(skb,
Yun Park6c86a662017-10-05 16:09:15 -07004494 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
Houston Hoffman43d47fa2016-02-24 16:34:30 -08004495 + HDD_IPA_WLAN_FRAG_HEADER
4496 + HDD_IPA_WLAN_IPA_HEADER);
Yun Park6c86a662017-10-05 16:09:15 -07004497 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER;
4499 } else
Nirav Shahcbc6d722016-03-01 16:24:53 +05304500 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501
Yun Park52b2b992016-09-22 15:49:51 -07004502 qdf_spin_lock_bh(&hdd_ipa->q_lock);
4503 /* get free Tx desc and assign ipa_tx_desc pointer */
4504 if (!list_empty(&hdd_ipa->free_tx_desc_head)) {
4505 tx_desc = list_first_entry(&hdd_ipa->free_tx_desc_head,
4506 struct hdd_ipa_tx_desc, link);
4507 list_del(&tx_desc->link);
4508 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
4509 hdd_ipa->stats.num_tx_desc_q_cnt++;
4510 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
4511 /* Store Tx Desc index into SKB CB */
4512 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
4513 } else {
4514 hdd_ipa->stats.num_tx_desc_error++;
4515 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
Yun Park52b2b992016-09-22 15:49:51 -07004516 ipa_free_skb(ipa_tx_desc);
4517 hdd_ipa_rm_try_release(hdd_ipa);
4518 return;
4519 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004520
Yun Park6c86a662017-10-05 16:09:15 -07004521 adapter->stats.tx_bytes += QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004522
Leo Changfdb45c32016-10-28 11:09:23 -07004523 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
Yun Park6c86a662017-10-05 16:09:15 -07004524 (struct cdp_vdev *)iface_context->tl_context,
4525 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 if (skb) {
jiad05c1e812017-08-01 16:48:52 +08004527 qdf_nbuf_free(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 iface_context->stats.num_tx_err++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return;
4530 }
4531
4532 atomic_inc(&hdd_ipa->tx_ref_cnt);
4533
4534 iface_context->stats.num_tx++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535}
4536
4537/**
Leo Chang11545d62016-10-17 14:53:50 -07004538 * hdd_ipa_is_present() - get IPA hw status
4539 * @hdd_ctx: pointer to hdd context
4540 *
4541 * ipa_uc_reg_rdyCB is not directly designed to check
4542 * ipa hw status. This is an undocumented function which
4543 * has confirmed with IPA team.
4544 *
4545 * Return: true - ipa hw present
4546 * false - ipa hw not present
4547 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004548bool hdd_ipa_is_present(struct hdd_context *hdd_ctx)
Leo Chang11545d62016-10-17 14:53:50 -07004549{
4550 /* Check if ipa hw is enabled */
Leo Chang63d73612016-10-18 18:09:43 -07004551 if (HDD_IPA_CHECK_HW() != -EPERM)
Leo Chang11545d62016-10-17 14:53:50 -07004552 return true;
4553 else
4554 return false;
4555}
4556
4557/**
Leo Chang69c39692016-10-12 20:11:12 -07004558 * hdd_ipa_pm_flush() - flush queued packets
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 * @work: pointer to the scheduled work
4560 *
4561 * Called during PM resume to send packets to TL which were queued
4562 * while host was in the process of suspending.
4563 *
4564 * Return: None
4565 */
Leo Chang69c39692016-10-12 20:11:12 -07004566static void hdd_ipa_pm_flush(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004567{
4568 struct hdd_ipa_priv *hdd_ipa = container_of(work,
4569 struct hdd_ipa_priv,
4570 pm_work);
4571 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304572 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573 uint32_t dequeued = 0;
4574
Leo Chang69c39692016-10-12 20:11:12 -07004575 qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
4576 WIFI_POWER_EVENT_WAKELOCK_IPA);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304577 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Nirav Shahcbc6d722016-03-01 16:24:53 +05304578 while (((skb = qdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head))
4579 != NULL)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304580 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
4582 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 dequeued++;
Leo Chang69c39692016-10-12 20:11:12 -07004584 if (pm_tx_cb->exception) {
Yun Park46255682017-10-09 15:56:34 -07004585 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
4586 "Flush Exception");
Govind Singh1dab23b2017-08-12 13:31:00 +05304587 if (pm_tx_cb->adapter->dev)
4588 hdd_softap_hard_start_xmit(skb,
4589 pm_tx_cb->adapter->dev);
Govind Singh02075942017-08-15 11:13:28 +05304590 else
4591 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
Leo Chang69c39692016-10-12 20:11:12 -07004592 } else {
4593 hdd_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004594 pm_tx_cb->ipa_tx_desc);
Leo Chang69c39692016-10-12 20:11:12 -07004595 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304596 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304598 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Leo Chang69c39692016-10-12 20:11:12 -07004599 qdf_wake_lock_release(&hdd_ipa->wake_lock,
4600 WIFI_POWER_EVENT_WAKELOCK_IPA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601
4602 hdd_ipa->stats.num_tx_dequeued += dequeued;
4603 if (dequeued > hdd_ipa->stats.num_max_pm_queue)
4604 hdd_ipa->stats.num_max_pm_queue = dequeued;
4605}
4606
4607/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004608 * __hdd_ipa_i2w_cb() - IPA to WLAN callback
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 * @priv: pointer to private data registered with IPA (we register a
4610 * pointer to the interface-specific IPA context)
4611 * @evt: the IPA event which triggered the callback
4612 * @data: data associated with the event
4613 *
4614 * Return: None
4615 */
Yun Park6c86a662017-10-05 16:09:15 -07004616static void __hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
4617 unsigned long data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004618{
4619 struct hdd_ipa_priv *hdd_ipa = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07004620 qdf_ipa_rx_data_t *ipa_tx_desc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621 struct hdd_ipa_iface_context *iface_context;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304622 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304624 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625
Mukul Sharma81661ae2015-10-30 20:26:02 +05304626 iface_context = (struct hdd_ipa_iface_context *)priv;
Yun Park6c86a662017-10-05 16:09:15 -07004627 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004628 hdd_ipa = iface_context->hdd_ipa;
4629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 if (evt != IPA_RECEIVE) {
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004631 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Event is not IPA_RECEIVE");
4632 ipa_free_skb(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004633 iface_context->stats.num_tx_drop++;
4634 return;
4635 }
4636
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 /*
4638 * When SSR is going on or driver is unloading, just drop the packets.
4639 * During SSR, there is no use in queueing the packets as STA has to
4640 * connect back any way
4641 */
4642 status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304643 if (status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 ipa_free_skb(ipa_tx_desc);
4645 iface_context->stats.num_tx_drop++;
4646 return;
4647 }
4648
Yun Park6c86a662017-10-05 16:09:15 -07004649 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650
Yun Parkb187d542016-11-14 18:10:04 -08004651 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
4652 "i2w", skb->data, HDD_IPA_DBG_DUMP_TX_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004653
4654 /*
4655 * If PROD resource is not requested here then there may be cases where
4656 * IPA hardware may be clocked down because of not having proper
4657 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
4658 * workaround to request PROD resource while data is going over CONS
4659 * pipe to prevent the IPA hardware clockdown.
4660 */
4661 hdd_ipa_rm_request(hdd_ipa);
4662
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304663 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 /*
4665 * If host is still suspended then queue the packets and these will be
4666 * drained later when resume completes. When packet is arrived here and
4667 * host is suspended, this means that there is already resume is in
4668 * progress.
4669 */
4670 if (hdd_ipa->suspended) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304671 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
4673 pm_tx_cb->iface_context = iface_context;
4674 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304675 qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676 hdd_ipa->stats.num_tx_queued++;
4677
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304678 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679 return;
4680 }
4681
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304682 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683
4684 /*
4685 * If we are here means, host is not suspended, wait for the work queue
4686 * to finish.
4687 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 flush_work(&hdd_ipa->pm_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
4690 return hdd_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
4691}
4692
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004693/*
4694 * hdd_ipa_i2w_cb() - SSR wrapper for __hdd_ipa_i2w_cb
4695 * @priv: pointer to private data registered with IPA (we register a
4696 * pointer to the interface-specific IPA context)
4697 * @evt: the IPA event which triggered the callback
4698 * @data: data associated with the event
4699 *
4700 * Return: None
4701 */
Yun Park6c86a662017-10-05 16:09:15 -07004702static void hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004703 unsigned long data)
4704{
4705 cds_ssr_protect(__func__);
4706 __hdd_ipa_i2w_cb(priv, evt, data);
4707 cds_ssr_unprotect(__func__);
4708}
4709
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004711 * __hdd_ipa_suspend() - Suspend IPA
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712 * @hdd_ctx: Global HDD context
4713 *
4714 * Return: 0 on success, negativer errno on error
4715 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004716static int __hdd_ipa_suspend(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004718 struct hdd_ipa_priv *hdd_ipa;
4719
4720 if (wlan_hdd_validate_context(hdd_ctx))
4721 return 0;
4722
4723 hdd_ipa = hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004724
4725 if (!hdd_ipa_is_enabled(hdd_ctx))
4726 return 0;
4727
4728 /*
4729 * Check if IPA is ready for suspend, If we are here means, there is
4730 * high chance that suspend would go through but just to avoid any race
4731 * condition after suspend started, these checks are conducted before
4732 * allowing to suspend.
4733 */
4734 if (atomic_read(&hdd_ipa->tx_ref_cnt))
4735 return -EAGAIN;
4736
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304737 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738
4739 if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304740 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741 return -EAGAIN;
4742 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304743 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004744
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304745 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 hdd_ipa->suspended = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304747 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004748
4749 return 0;
4750}
4751
4752/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004753 * hdd_ipa_suspend() - SSR wrapper for __hdd_ipa_suspend
4754 * @hdd_ctx: Global HDD context
4755 *
4756 * Return: 0 on success, negativer errno on error
4757 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004758int hdd_ipa_suspend(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004759{
4760 int ret;
4761
4762 cds_ssr_protect(__func__);
4763 ret = __hdd_ipa_suspend(hdd_ctx);
4764 cds_ssr_unprotect(__func__);
4765
4766 return ret;
4767}
4768
4769/**
4770 * __hdd_ipa_resume() - Resume IPA following suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004771 * hdd_ctx: Global HDD context
4772 *
4773 * Return: 0 on success, negative errno on error
4774 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004775static int __hdd_ipa_resume(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004777 struct hdd_ipa_priv *hdd_ipa;
4778
4779 if (wlan_hdd_validate_context(hdd_ctx))
4780 return 0;
4781
4782 hdd_ipa = hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004783
4784 if (!hdd_ipa_is_enabled(hdd_ctx))
4785 return 0;
4786
4787 schedule_work(&hdd_ipa->pm_work);
4788
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304789 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 hdd_ipa->suspended = false;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304791 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792
4793 return 0;
4794}
4795
4796/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004797 * hdd_ipa_resume() - SSR wrapper for __hdd_ipa_resume
4798 * hdd_ctx: Global HDD context
4799 *
4800 * Return: 0 on success, negative errno on error
4801 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004802int hdd_ipa_resume(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004803{
4804 int ret;
4805
4806 cds_ssr_protect(__func__);
4807 ret = __hdd_ipa_resume(hdd_ctx);
4808 cds_ssr_unprotect(__func__);
4809
4810 return ret;
4811}
4812
4813/**
Yun Park52b2b992016-09-22 15:49:51 -07004814 * hdd_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
4815 * @hdd_ipa: Global HDD IPA context
4816 *
4817 * Return: 0 on success, negative errno on error
4818 */
4819static int hdd_ipa_alloc_tx_desc_list(struct hdd_ipa_priv *hdd_ipa)
4820{
4821 int i;
4822 uint32_t max_desc_cnt;
4823 struct hdd_ipa_tx_desc *tmp_desc;
4824
Yun Parkd9c528e2017-08-30 16:34:57 -07004825 max_desc_cnt = hdd_ipa->hdd_ctx->config->IpaUcTxBufCount;
Yun Park52b2b992016-09-22 15:49:51 -07004826
4827 INIT_LIST_HEAD(&hdd_ipa->free_tx_desc_head);
4828
jiad14fe4fb2017-08-08 13:33:14 +08004829 tmp_desc = qdf_mem_malloc(sizeof(struct hdd_ipa_tx_desc) *
Yun Parkd9c528e2017-08-30 16:34:57 -07004830 max_desc_cnt);
Yun Park52b2b992016-09-22 15:49:51 -07004831
4832 if (!tmp_desc) {
4833 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkd9c528e2017-08-30 16:34:57 -07004834 "Free Tx descriptor allocation failed");
Yun Park52b2b992016-09-22 15:49:51 -07004835 return -ENOMEM;
4836 }
4837
4838 hdd_ipa->tx_desc_list = tmp_desc;
4839
4840 qdf_spin_lock_bh(&hdd_ipa->q_lock);
Yun Parkd9c528e2017-08-30 16:34:57 -07004841 for (i = 0; i < max_desc_cnt; i++) {
Yun Park52b2b992016-09-22 15:49:51 -07004842 tmp_desc->id = i;
4843 tmp_desc->ipa_tx_desc_ptr = NULL;
4844 list_add_tail(&tmp_desc->link,
4845 &hdd_ipa->free_tx_desc_head);
4846 tmp_desc++;
4847 }
4848
4849 hdd_ipa->stats.num_tx_desc_q_cnt = 0;
4850 hdd_ipa->stats.num_tx_desc_error = 0;
4851
4852 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
4853
4854 return 0;
4855}
4856
Yun Park9281cb72017-11-30 11:14:30 -08004857#ifndef QCA_LL_TX_FLOW_CONTROL_V2
Yun Park52b2b992016-09-22 15:49:51 -07004858/**
Yun Park9281cb72017-11-30 11:14:30 -08004859 * hdd_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004860 * @hdd_ipa: Global HDD IPA context
Yun Park9281cb72017-11-30 11:14:30 -08004861 * @desc_fifo_sz: Number of descriptors
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004862 *
4863 * Return: 0 on success, negative errno on error
4864 */
Yun Park9281cb72017-11-30 11:14:30 -08004865static int hdd_ipa_setup_tx_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
4866 int32_t desc_fifo_sz)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004867{
4868 int i, ret = 0;
Yun Park6c86a662017-10-05 16:09:15 -07004869 qdf_ipa_sys_connect_params_t *ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004870
4871 /*setup TX pipes */
4872 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
4873 ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params;
4874
4875 ipa->client = hdd_ipa_adapter_2_client[i].cons_client;
4876 ipa->desc_fifo_sz = desc_fifo_sz;
4877 ipa->priv = &hdd_ipa->iface_context[i];
4878 ipa->notify = hdd_ipa_i2w_cb;
4879
4880 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
4881 ipa->ipa_ep_cfg.hdr.hdr_len =
4882 HDD_IPA_UC_WLAN_TX_HDR_LEN;
4883 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
4884 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
4885 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
4886 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
4887 HDD_IPA_UC_WLAN_8023_HDR_SIZE;
4888 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
4889 } else {
4890 ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
4891 }
4892 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
4893
4894 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4895 ipa->keep_ipa_awake = 1;
4896
Yun Park6c86a662017-10-05 16:09:15 -07004897 ret = qdf_ipa_setup_sys_pipe(ipa,
4898 &hdd_ipa->sys_pipe[i].conn_hdl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004899 if (ret) {
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07004900 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4901 "Failed for pipe %d ret: %d", i, ret);
Yun Park9281cb72017-11-30 11:14:30 -08004902 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004903 }
4904 hdd_ipa->sys_pipe[i].conn_hdl_valid = 1;
4905 }
4906
Yun Park9281cb72017-11-30 11:14:30 -08004907 return ret;
4908}
4909#else
4910/**
4911 * hdd_ipa_setup_tx_sys_pipe() - Setup IPA Tx system pipes
4912 * @hdd_ipa: Global HDD IPA context
4913 * @desc_fifo_sz: Number of descriptors
4914 *
4915 * Return: 0 on success, negative errno on error
4916 */
4917static int hdd_ipa_setup_tx_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
4918 int32_t desc_fifo_sz)
4919{
4920 /*
4921 * The Tx system pipes are not needed for MCC when TX_FLOW_CONTROL_V2
4922 * is enabled, where per vdev descriptors are supported in firmware.
4923 */
4924 return 0;
4925}
4926#endif
4927
4928/**
4929 * hdd_ipa_setup_rx_sys_pipe() - Setup IPA Rx system pipes
4930 * @hdd_ipa: Global HDD IPA context
4931 * @desc_fifo_sz: Number of descriptors
4932 *
4933 * Return: 0 on success, negative errno on error
4934 */
4935static int hdd_ipa_setup_rx_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
4936 int32_t desc_fifo_sz)
4937{
4938 int ret = 0;
4939 qdf_ipa_sys_connect_params_t *ipa;
4940
4941 /*
4942 * Hard code it here, this can be extended if in case
4943 * PROD pipe is also per interface.
4944 * Right now there is no advantage of doing this.
4945 */
4946 ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params;
4947
4948 ipa->client = IPA_CLIENT_WLAN1_PROD;
4949
4950 ipa->desc_fifo_sz = desc_fifo_sz;
4951 ipa->priv = hdd_ipa;
4952 ipa->notify = hdd_ipa_w2i_cb;
4953
4954 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
4955 ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_RX_HDR_LEN;
4956 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
4957 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
4958
4959 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4960 ipa->keep_ipa_awake = 1;
4961
4962 ret = qdf_ipa_setup_sys_pipe(ipa,
4963 &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl);
4964 if (ret) {
4965 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4966 "Failed for RX pipe: %d", ret);
4967 return ret;
4968 }
4969 hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl_valid = 1;
4970
4971 return ret;
4972}
4973
4974/**
4975 * hdd_ipa_setup_sys_pipe() - Setup all IPA system pipes
4976 * @hdd_ipa: Global HDD IPA context
4977 *
4978 * Return: 0 on success, negative errno on error
4979 */
4980static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
4981{
4982 int i = HDD_IPA_MAX_IFACE, ret = 0;
4983 uint32_t desc_fifo_sz;
4984
4985 /* The maximum number of descriptors that can be provided to a BAM at
4986 * once is one less than the total number of descriptors that the buffer
4987 * can contain.
4988 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
4989 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
4990 * be provided at once.
4991 * Because of above requirement, one extra descriptor will be added to
4992 * make sure hardware always has one descriptor.
4993 */
4994 desc_fifo_sz = hdd_ipa->hdd_ctx->config->IpaDescSize
Yuanyuan Liu23a8eec2017-12-15 16:01:12 -08004995 + SPS_DESC_SIZE;
Yun Park9281cb72017-11-30 11:14:30 -08004996
4997 ret = hdd_ipa_setup_tx_sys_pipe(hdd_ipa, desc_fifo_sz);
4998 if (ret) {
4999 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
5000 "Failed for TX pipe: %d", ret);
5001 goto setup_sys_pipe_fail;
5002 }
5003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005004 if (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
Yun Park9281cb72017-11-30 11:14:30 -08005005 ret = hdd_ipa_setup_rx_sys_pipe(hdd_ipa, desc_fifo_sz);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305007 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park9281cb72017-11-30 11:14:30 -08005008 "Failed for RX pipe: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005009 goto setup_sys_pipe_fail;
5010 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 }
5012
Yun Parkd9c528e2017-08-30 16:34:57 -07005013 /* Allocate free Tx desc list */
Yun Park52b2b992016-09-22 15:49:51 -07005014 ret = hdd_ipa_alloc_tx_desc_list(hdd_ipa);
5015 if (ret)
5016 goto setup_sys_pipe_fail;
5017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 return ret;
5019
5020setup_sys_pipe_fail:
5021
Yun Park9281cb72017-11-30 11:14:30 -08005022 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
5023 if (hdd_ipa->sys_pipe[i].conn_hdl_valid)
5024 qdf_ipa_teardown_sys_pipe(
5025 hdd_ipa->sys_pipe[i].conn_hdl);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305026 qdf_mem_zero(&hdd_ipa->sys_pipe[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027 sizeof(struct hdd_ipa_sys_pipe));
5028 }
5029
5030 return ret;
5031}
5032
5033/**
5034 * hdd_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
5035 * @hdd_ipa: Global HDD IPA context
5036 *
5037 * Return: None
5038 */
5039static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
5040{
5041 int ret = 0, i;
Yun Parkd9c528e2017-08-30 16:34:57 -07005042 uint32_t max_desc_cnt;
Yun Park52b2b992016-09-22 15:49:51 -07005043 struct hdd_ipa_tx_desc *tmp_desc;
Yun Park6c86a662017-10-05 16:09:15 -07005044 qdf_ipa_rx_data_t *ipa_tx_desc;
Yun Park52b2b992016-09-22 15:49:51 -07005045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005046 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
5047 if (hdd_ipa->sys_pipe[i].conn_hdl_valid) {
Yun Park9281cb72017-11-30 11:14:30 -08005048 ret = qdf_ipa_teardown_sys_pipe(
5049 hdd_ipa->sys_pipe[i].conn_hdl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 if (ret)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305051 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Failed: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005052 ret);
5053
5054 hdd_ipa->sys_pipe[i].conn_hdl_valid = 0;
5055 }
5056 }
Yun Park52b2b992016-09-22 15:49:51 -07005057
5058 if (hdd_ipa->tx_desc_list) {
Yun Parkd9c528e2017-08-30 16:34:57 -07005059 max_desc_cnt = hdd_ipa->hdd_ctx->config->IpaUcTxBufCount;
5060
Yun Park52b2b992016-09-22 15:49:51 -07005061 qdf_spin_lock_bh(&hdd_ipa->q_lock);
Yun Parkd9c528e2017-08-30 16:34:57 -07005062 for (i = 0; i < max_desc_cnt; i++) {
Yun Park52b2b992016-09-22 15:49:51 -07005063 tmp_desc = hdd_ipa->tx_desc_list + i;
5064 ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
5065 if (ipa_tx_desc)
5066 ipa_free_skb(ipa_tx_desc);
5067 }
5068 tmp_desc = hdd_ipa->tx_desc_list;
5069 hdd_ipa->tx_desc_list = NULL;
5070 hdd_ipa->stats.num_tx_desc_q_cnt = 0;
5071 hdd_ipa->stats.num_tx_desc_error = 0;
5072 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
5073 qdf_mem_free(tmp_desc);
5074 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075}
5076
5077/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005078 * hdd_ipa_cleanup_iface() - Cleanup IPA on a given interface
5079 * @iface_context: interface-specific IPA context
5080 *
5081 * Return: None
5082 */
5083static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context)
5084{
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005085 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07005086
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 if (iface_context == NULL)
5088 return;
Orhan K AKYILDIZ3332be32017-05-31 15:36:31 -07005089 if (iface_context->adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
5090 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
5091 "%s: bad adapter(%pK).magic(%d)!",
5092 __func__, iface_context->adapter,
5093 iface_context->adapter->magic);
5094 return;
5095 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005096
Yun Parkb4f591d2017-03-29 15:51:01 -07005097 cdp_ipa_cleanup_iface(cds_get_context(QDF_MODULE_ID_SOC),
5098 iface_context->adapter->dev->name,
5099 hdd_ipa_is_ipv6_enabled(iface_context->hdd_ipa->hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005100
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305101 qdf_spin_lock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102 iface_context->adapter->ipa_context = NULL;
5103 iface_context->adapter = NULL;
5104 iface_context->tl_context = NULL;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305105 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005106 iface_context->ifa_address = 0;
5107 if (!iface_context->hdd_ipa->num_iface) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305108 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005109 "NUM INTF 0, Invalid");
Anurag Chouhandf2b2682016-02-29 14:15:27 +05305110 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005111 }
5112 iface_context->hdd_ipa->num_iface--;
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005113 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: num_iface=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005114 iface_context->hdd_ipa->num_iface);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005115}
5116
5117/**
5118 * hdd_ipa_setup_iface() - Setup IPA on a given interface
5119 * @hdd_ipa: HDD IPA global context
5120 * @adapter: Interface upon which IPA is being setup
5121 * @sta_id: Station ID of the API instance
5122 *
5123 * Return: 0 on success, negative errno value on error
5124 */
5125static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07005126 struct hdd_adapter *adapter, uint8_t sta_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005127{
5128 struct hdd_ipa_iface_context *iface_context = NULL;
Yun Park0dad1002017-07-14 14:57:01 -07005129 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
5130 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005131 void *tl_context = NULL;
5132 int i, ret = 0;
5133
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005134 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07005135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005136 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
5137 * channel change indication. Since these indications are sent by lower
5138 * layer as SAP updates and IPA doesn't have to do anything for these
5139 * updates so ignoring!
5140 */
Krunal Sonibe766b02016-03-10 13:00:44 -08005141 if (QDF_SAP_MODE == adapter->device_mode && adapter->ipa_context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 return 0;
5143
5144 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
5145 if (hdd_ipa->iface_context[i].adapter == NULL) {
5146 iface_context = &(hdd_ipa->iface_context[i]);
5147 break;
5148 }
5149 }
5150
5151 if (iface_context == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305152 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005153 "All the IPA interfaces are in use");
5154 ret = -ENOMEM;
5155 goto end;
5156 }
5157
5158 adapter->ipa_context = iface_context;
5159 iface_context->adapter = adapter;
5160 iface_context->sta_id = sta_id;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08005161 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(
Yun Park0dad1002017-07-14 14:57:01 -07005162 soc, (struct cdp_pdev *)pdev, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005163 if (tl_context == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305164 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005165 "Not able to get TL context sta_id: %d", sta_id);
5166 ret = -EINVAL;
5167 goto end;
5168 }
5169
5170 iface_context->tl_context = tl_context;
5171
Yun Parkb4f591d2017-03-29 15:51:01 -07005172 ret = cdp_ipa_setup_iface(cds_get_context(QDF_MODULE_ID_SOC),
5173 adapter->dev->name, adapter->dev->dev_addr,
5174 iface_context->prod_client,
5175 iface_context->cons_client,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005176 adapter->session_id,
Yun Parkb4f591d2017-03-29 15:51:01 -07005177 hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 if (ret)
5179 goto end;
5180
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005181 hdd_ipa->num_iface++;
Yun Parkfec73dc2017-09-06 10:40:07 -07005182
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005183 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: num_iface=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005184 hdd_ipa->num_iface);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185 return ret;
5186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187end:
5188 if (iface_context)
5189 hdd_ipa_cleanup_iface(iface_context);
5190 return ret;
5191}
5192
Yun Parka27049a2016-10-11 12:30:49 -07005193#ifndef QCA_LL_TX_FLOW_CONTROL_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005194/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005195 * __hdd_ipa_send_mcc_scc_msg() - send IPA WLAN_SWITCH_TO_MCC/SCC message
Jeff Johnson4929cd92017-10-06 19:21:57 -07005196 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005197 * @mcc_mode: 0=MCC/1=SCC
5198 *
5199 * Return: 0 on success, negative errno value on error
5200 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07005201static int __hdd_ipa_send_mcc_scc_msg(struct hdd_context *hdd_ctx,
5202 bool mcc_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005203{
Jeff Johnson089d0432017-10-02 13:27:21 -07005204 struct hdd_adapter *adapter;
Yun Park6c86a662017-10-05 16:09:15 -07005205 qdf_ipa_msg_meta_t meta;
5206 qdf_ipa_wlan_msg_t *msg;
5207
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005208 int ret;
5209
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005210 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005211 return -EINVAL;
5212
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005213 if (!hdd_ipa_uc_sta_is_enabled(hdd_ctx))
5214 return -EINVAL;
5215
5216 if (!hdd_ctx->mcc_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005217 /* Flush TxRx queue for each adapter before switch to SCC */
Dustin Brown920397d2017-12-13 16:27:50 -08005218 hdd_for_each_adapter(hdd_ctx, adapter) {
Jeff Johnson089d0432017-10-02 13:27:21 -07005219 if (adapter->device_mode == QDF_STA_MODE ||
5220 adapter->device_mode == QDF_SAP_MODE) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005221 hdd_debug("MCC->SCC: Flush TxRx queue(d_mode=%d)",
Jeff Johnson089d0432017-10-02 13:27:21 -07005222 adapter->device_mode);
5223 hdd_deinit_tx_rx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005225 }
5226 }
5227
5228 /* Send SCC/MCC Switching event to IPA */
Yun Park6c86a662017-10-05 16:09:15 -07005229 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
5230 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 if (msg == NULL) {
Jeff Johnsonab2cd402016-12-05 13:54:28 -08005232 hdd_err("msg allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 return -ENOMEM;
5234 }
5235
Yun Park6c86a662017-10-05 16:09:15 -07005236 QDF_IPA_MSG_META_MSG_TYPE(&meta) = mcc_mode ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237 WLAN_SWITCH_TO_MCC : WLAN_SWITCH_TO_SCC;
Yun Park6c86a662017-10-05 16:09:15 -07005238 hdd_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239
Yun Park6c86a662017-10-05 16:09:15 -07005240 ret = qdf_ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241
5242 if (ret) {
Jeff Johnsonab2cd402016-12-05 13:54:28 -08005243 hdd_err("ipa_send_msg(Evt:%d) - fail=%d",
Yun Park6c86a662017-10-05 16:09:15 -07005244 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305245 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005246 }
5247
5248 return ret;
5249}
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005250
5251/**
5252 * hdd_ipa_send_mcc_scc_msg() - SSR wrapper for __hdd_ipa_send_mcc_scc_msg
5253 * @mcc_mode: 0=MCC/1=SCC
5254 *
5255 * Return: 0 on success, negative errno value on error
5256 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07005257int hdd_ipa_send_mcc_scc_msg(struct hdd_context *hdd_ctx, bool mcc_mode)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005258{
5259 int ret;
5260
5261 cds_ssr_protect(__func__);
5262 ret = __hdd_ipa_send_mcc_scc_msg(hdd_ctx, mcc_mode);
5263 cds_ssr_unprotect(__func__);
5264
5265 return ret;
5266}
Yun Parka27049a2016-10-11 12:30:49 -07005267#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268
5269/**
Mohit Khannafa99aea2016-05-12 21:43:13 -07005270 * hdd_to_ipa_wlan_event() - convert hdd_ipa_wlan_event to ipa_wlan_event
5271 * @hdd_ipa_event_type: HDD IPA WLAN event to be converted to an ipa_wlan_event
5272 *
Yun Park6c86a662017-10-05 16:09:15 -07005273 * Return: qdf_ipa_wlan_event representing the hdd_ipa_wlan_event
Mohit Khannafa99aea2016-05-12 21:43:13 -07005274 */
Yun Park6c86a662017-10-05 16:09:15 -07005275static qdf_ipa_wlan_event_t
Mohit Khannafa99aea2016-05-12 21:43:13 -07005276hdd_to_ipa_wlan_event(enum hdd_ipa_wlan_event hdd_ipa_event_type)
5277{
Yun Park6c86a662017-10-05 16:09:15 -07005278 qdf_ipa_wlan_event_t ipa_event;
Mohit Khannafa99aea2016-05-12 21:43:13 -07005279
5280 switch (hdd_ipa_event_type) {
5281 case HDD_IPA_CLIENT_CONNECT:
5282 ipa_event = WLAN_CLIENT_CONNECT;
5283 break;
5284 case HDD_IPA_CLIENT_DISCONNECT:
5285 ipa_event = WLAN_CLIENT_DISCONNECT;
5286 break;
5287 case HDD_IPA_AP_CONNECT:
5288 ipa_event = WLAN_AP_CONNECT;
5289 break;
5290 case HDD_IPA_AP_DISCONNECT:
5291 ipa_event = WLAN_AP_DISCONNECT;
5292 break;
5293 case HDD_IPA_STA_CONNECT:
5294 ipa_event = WLAN_STA_CONNECT;
5295 break;
5296 case HDD_IPA_STA_DISCONNECT:
5297 ipa_event = WLAN_STA_DISCONNECT;
5298 break;
5299 case HDD_IPA_CLIENT_CONNECT_EX:
5300 ipa_event = WLAN_CLIENT_CONNECT_EX;
5301 break;
5302 case HDD_IPA_WLAN_EVENT_MAX:
5303 default:
5304 ipa_event = IPA_WLAN_EVENT_MAX;
5305 break;
5306 }
5307 return ipa_event;
5308
5309}
5310
5311/**
5312 * __hdd_ipa_wlan_evt() - IPA event handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 * @adapter: adapter upon which the event was received
5314 * @sta_id: station id for the event
Mohit Khannafa99aea2016-05-12 21:43:13 -07005315 * @type: event enum of type ipa_wlan_event
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005316 * @mac_address: MAC address associated with the event
5317 *
Mohit Khannafa99aea2016-05-12 21:43:13 -07005318 * This function is meant to be called from within wlan_hdd_ipa.c
5319 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 * Return: 0 on success, negative errno value on error
5321 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07005322static int __hdd_ipa_wlan_evt(struct hdd_adapter *adapter, uint8_t sta_id,
Yun Park6c86a662017-10-05 16:09:15 -07005323 qdf_ipa_wlan_event_t type, uint8_t *mac_addr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005324{
5325 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07005326 qdf_ipa_msg_meta_t meta;
5327 qdf_ipa_wlan_msg_t *msg;
5328 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 int ret;
5330
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005331 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: EVT: %s, MAC: %pM, sta_id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 adapter->dev->name, hdd_ipa_wlan_event_to_str(type),
5333 mac_addr, sta_id);
5334
5335 if (type >= IPA_WLAN_EVENT_MAX)
5336 return -EINVAL;
5337
5338 if (WARN_ON(is_zero_ether_addr(mac_addr)))
5339 return -EINVAL;
5340
5341 if (!hdd_ipa || !hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305342 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "IPA OFFLOAD NOT ENABLED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005343 return -EINVAL;
5344 }
5345
5346 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) &&
5347 !hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
Krunal Sonibe766b02016-03-10 13:00:44 -08005348 (QDF_SAP_MODE != adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005349 return 0;
5350 }
5351
5352 /*
5353 * During IPA UC resource loading/unloading new events can be issued.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005354 */
Yun Park777d7242017-03-30 15:38:33 -07005355 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) &&
5356 (hdd_ipa->resource_loading || hdd_ipa->resource_unloading)) {
5357 unsigned int pending_event_count;
5358 struct ipa_uc_pending_event *pending_event = NULL;
Yun Parkf19e07d2015-11-20 11:34:27 -08005359
Yun Park46255682017-10-09 15:56:34 -07005360 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park777d7242017-03-30 15:38:33 -07005361 "%s:IPA resource %s inprogress",
5362 hdd_ipa_wlan_event_to_str(type),
5363 hdd_ipa->resource_loading ?
5364 "load" : "unload");
5365
5366 /* Wait until completion of the long/unloading */
5367 ret = wait_for_completion_timeout(&hdd_ipa->ipa_resource_comp,
5368 msecs_to_jiffies(IPA_RESOURCE_COMP_WAIT_TIME));
5369 if (!ret) {
5370 /*
5371 * If timed out, store the events separately and
5372 * handle them later.
5373 */
Yun Park46255682017-10-09 15:56:34 -07005374 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park777d7242017-03-30 15:38:33 -07005375 "IPA resource %s timed out",
5376 hdd_ipa->resource_loading ?
5377 "load" : "unload");
Yun Park7c4f31b2016-11-30 10:09:21 -08005378
Yun Parka4bb37c2017-12-08 16:14:22 -08005379 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Parkf19e07d2015-11-20 11:34:27 -08005380
Yun Parka4bb37c2017-12-08 16:14:22 -08005381 pending_event_count =
5382 qdf_list_size(&hdd_ipa->pending_event);
5383 if (pending_event_count >=
5384 HDD_IPA_MAX_PENDING_EVENT_COUNT) {
5385 hdd_debug("Reached max pending event count");
5386 qdf_list_remove_front(
5387 &hdd_ipa->pending_event,
5388 (qdf_list_node_t **)&pending_event);
5389 } else {
5390 pending_event =
5391 (struct ipa_uc_pending_event *)
5392 qdf_mem_malloc(sizeof(
Yun Park777d7242017-03-30 15:38:33 -07005393 struct ipa_uc_pending_event));
Prakash Dhavalibf6d5d22016-08-17 10:17:46 -07005394 }
Yun Parka4bb37c2017-12-08 16:14:22 -08005395
5396 if (!pending_event) {
5397 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
5398 "Pending event memory alloc fail");
5399 qdf_mutex_release(&hdd_ipa->ipa_lock);
5400 return -ENOMEM;
5401 }
5402
5403 pending_event->adapter = adapter;
5404 pending_event->sta_id = sta_id;
5405 pending_event->type = type;
5406 pending_event->is_loading =
5407 hdd_ipa->resource_loading;
5408 qdf_mem_copy(pending_event->mac_addr,
5409 mac_addr, QDF_MAC_ADDR_SIZE);
5410 qdf_list_insert_back(&hdd_ipa->pending_event,
5411 &pending_event->node);
5412
5413 qdf_mutex_release(&hdd_ipa->ipa_lock);
5414
Prakash Dhavalibf6d5d22016-08-17 10:17:46 -07005415 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416 }
Yun Park46255682017-10-09 15:56:34 -07005417 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Jeff Johnson4929cd92017-10-06 19:21:57 -07005418 "IPA resource %s completed",
5419 hdd_ipa->resource_loading ?
5420 "load" : "unload");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005421 }
5422
5423 hdd_ipa->stats.event[type]++;
5424
Yun Park6c86a662017-10-05 16:09:15 -07005425 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005426 switch (type) {
5427 case WLAN_STA_CONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005428 qdf_mutex_acquire(&hdd_ipa->event_lock);
5429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430 /* STA already connected and without disconnect, connect again
5431 * This is Roaming scenario
5432 */
5433 if (hdd_ipa->sta_connected)
5434 hdd_ipa_cleanup_iface(adapter->ipa_context);
5435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005436 ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id);
5437 if (ret) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305438 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 goto end;
Yun Parka37592b2016-06-11 17:10:28 -07005440 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005441
Yun Park8f289c82016-10-18 16:38:21 -07005442 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
5443 (hdd_ipa->sap_num_connected_sta > 0) &&
5444 !hdd_ipa->sta_connected) {
5445 qdf_mutex_release(&hdd_ipa->event_lock);
5446 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005447 SIR_STA_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005448 qdf_mutex_acquire(&hdd_ipa->event_lock);
5449 }
5450
Jeff Johnson1b780e42017-10-31 14:11:45 -07005451 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 ((struct hdd_ipa_iface_context *)
Yun Parka37592b2016-06-11 17:10:28 -07005453 (adapter->ipa_context))->iface_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 hdd_ipa->sta_connected = 1;
Yun Park8f289c82016-10-18 16:38:21 -07005456
5457 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkfec73dc2017-09-06 10:40:07 -07005458
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005459 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "sta_connected=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005460 hdd_ipa->sta_connected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005461 break;
5462
5463 case WLAN_AP_CONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005464 qdf_mutex_acquire(&hdd_ipa->event_lock);
5465
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466 /* For DFS channel we get two start_bss event (before and after
5467 * CAC). Also when ACS range includes both DFS and non DFS
5468 * channels, we could possibly change channel many times due to
5469 * RADAR detection and chosen channel may not be a DFS channels.
5470 * So dont return error here. Just discard the event.
5471 */
Yun Park8f289c82016-10-18 16:38:21 -07005472 if (adapter->ipa_context) {
5473 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005474 return 0;
Yun Park8f289c82016-10-18 16:38:21 -07005475 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id);
5478 if (ret) {
Yun Park64c405e2017-01-10 22:35:51 -08005479 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005480 hdd_err("%s: Evt: %d, Interface setup failed",
Yun Park6c86a662017-10-05 16:09:15 -07005481 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005482 goto end;
Yun Parka37592b2016-06-11 17:10:28 -07005483 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005484
Yun Park8f289c82016-10-18 16:38:21 -07005485 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5486 qdf_mutex_release(&hdd_ipa->event_lock);
5487 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005488 SIR_AP_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005489 qdf_mutex_acquire(&hdd_ipa->event_lock);
5490 }
5491
Jeff Johnson1b780e42017-10-31 14:11:45 -07005492 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005493 ((struct hdd_ipa_iface_context *)
Yun Parka37592b2016-06-11 17:10:28 -07005494 (adapter->ipa_context))->iface_id;
5495
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305496 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005497 break;
5498
5499 case WLAN_STA_DISCONNECT:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305500 qdf_mutex_acquire(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501
5502 if (!hdd_ipa->sta_connected) {
Yun Park64c405e2017-01-10 22:35:51 -08005503 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005504 hdd_err("%s: Evt: %d, STA already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005505 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005506 return -EINVAL;
5507 }
Yun Parka37592b2016-06-11 17:10:28 -07005508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005509 hdd_ipa->sta_connected = 0;
Yun Parka37592b2016-06-11 17:10:28 -07005510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005511 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005512 hdd_debug("%s: IPA UC OFFLOAD NOT ENABLED",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005513 msg_ex->name);
5514 } else {
5515 /* Disable IPA UC TX PIPE when STA disconnected */
Yun Park3b7152b2017-08-25 08:33:37 -07005516 if ((1 == hdd_ipa->num_iface) &&
Yun Parka37592b2016-06-11 17:10:28 -07005517 (HDD_IPA_UC_NUM_WDI_PIPE ==
Yun Park3b7152b2017-08-25 08:33:37 -07005518 hdd_ipa->activated_fw_pipe) &&
5519 !hdd_ipa->ipa_pipes_down)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005520 hdd_ipa_uc_handle_last_discon(hdd_ipa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 }
5522
Yun Park74127cf2016-09-18 11:22:41 -07005523 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
5524 (hdd_ipa->sap_num_connected_sta > 0)) {
Yun Park8f289c82016-10-18 16:38:21 -07005525 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005526 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005527 SIR_STA_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005528 qdf_mutex_acquire(&hdd_ipa->event_lock);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005529 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005530 CSR_ROAM_SESSION_MAX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531 }
5532
Yun Park8f289c82016-10-18 16:38:21 -07005533 hdd_ipa_cleanup_iface(adapter->ipa_context);
5534
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305535 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkfec73dc2017-09-06 10:40:07 -07005536
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005537 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "sta_connected=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005538 hdd_ipa->sta_connected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005539 break;
5540
5541 case WLAN_AP_DISCONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005542 qdf_mutex_acquire(&hdd_ipa->event_lock);
5543
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 if (!adapter->ipa_context) {
Yun Park64c405e2017-01-10 22:35:51 -08005545 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005546 hdd_err("%s: Evt: %d, SAP already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005547 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 return -EINVAL;
5549 }
5550
Yun Park3b7152b2017-08-25 08:33:37 -07005551 if ((1 == hdd_ipa->num_iface) &&
5552 (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
5553 !hdd_ipa->ipa_pipes_down) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005554 if (cds_is_driver_unloading()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005555 /*
5556 * We disable WDI pipes directly here since
5557 * IPA_OPCODE_TX/RX_SUSPEND message will not be
5558 * processed when unloading WLAN driver is in
5559 * progress
5560 */
5561 hdd_ipa_uc_disable_pipes(hdd_ipa);
5562 } else {
Yun Park199c2ed2017-10-02 11:24:22 -07005563 /*
5564 * This shouldn't happen :
5565 * No interface left but WDI pipes are still
5566 * active - force close WDI pipes
5567 */
5568 WARN_ON(1);
5569 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
5570 "No interface left but WDI pipes are still active - force close WDI pipes");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005571 hdd_ipa_uc_handle_last_discon(hdd_ipa);
5572 }
5573 }
5574
5575 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Yun Park8f289c82016-10-18 16:38:21 -07005576 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005577 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005578 SIR_AP_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005579 qdf_mutex_acquire(&hdd_ipa->event_lock);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005580 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005581 CSR_ROAM_SESSION_MAX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 }
Yun Parka37592b2016-06-11 17:10:28 -07005583
Yun Park8f289c82016-10-18 16:38:21 -07005584 hdd_ipa_cleanup_iface(adapter->ipa_context);
5585
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305586 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005587 break;
5588
5589 case WLAN_CLIENT_CONNECT_EX:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005591 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 "%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
Manjeet Singhfd51d8f2016-11-09 15:58:26 +05305593 adapter->dev->name, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005594 return 0;
5595 }
5596
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305597 qdf_mutex_acquire(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598 if (hdd_ipa_uc_find_add_assoc_sta(hdd_ipa,
5599 true, sta_id)) {
Yun Park8f289c82016-10-18 16:38:21 -07005600 qdf_mutex_release(&hdd_ipa->event_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305601 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005602 "%s: STA ID %d found, not valid",
5603 adapter->dev->name, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005604 return 0;
5605 }
Yun Park312f71a2015-12-08 10:22:42 -08005606
5607 /* Enable IPA UC Data PIPEs when first STA connected */
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005608 if (hdd_ipa->sap_num_connected_sta == 0 &&
5609 hdd_ipa->uc_loaded == true) {
Yun Parka37592b2016-06-11 17:10:28 -07005610 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
Yun Park8f289c82016-10-18 16:38:21 -07005611 hdd_ipa->sta_connected) {
5612 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parka37592b2016-06-11 17:10:28 -07005613 hdd_ipa_uc_offload_enable_disable(
5614 hdd_get_adapter(hdd_ipa->hdd_ctx,
5615 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005616 SIR_STA_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005617 qdf_mutex_acquire(&hdd_ipa->event_lock);
5618 }
Yun Parka37592b2016-06-11 17:10:28 -07005619
Yun Park312f71a2015-12-08 10:22:42 -08005620 ret = hdd_ipa_uc_handle_first_con(hdd_ipa);
5621 if (ret) {
Yun Park46255682017-10-09 15:56:34 -07005622 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park312f71a2015-12-08 10:22:42 -08005623 "%s: handle 1st con ret %d",
5624 adapter->dev->name, ret);
Yun Parka37592b2016-06-11 17:10:28 -07005625
5626 if (hdd_ipa_uc_sta_is_enabled(
5627 hdd_ipa->hdd_ctx) &&
Yun Park8f289c82016-10-18 16:38:21 -07005628 hdd_ipa->sta_connected) {
5629 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parka37592b2016-06-11 17:10:28 -07005630 hdd_ipa_uc_offload_enable_disable(
5631 hdd_get_adapter(
5632 hdd_ipa->hdd_ctx,
5633 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005634 SIR_STA_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005635 } else {
5636 qdf_mutex_release(&hdd_ipa->event_lock);
5637 }
Yun Parka37592b2016-06-11 17:10:28 -07005638
Yun Park312f71a2015-12-08 10:22:42 -08005639 return ret;
5640 }
5641 }
5642
5643 hdd_ipa->sap_num_connected_sta++;
Yun Park312f71a2015-12-08 10:22:42 -08005644
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305645 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005646
Yun Park6c86a662017-10-05 16:09:15 -07005647 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
5648 QDF_IPA_MSG_META_MSG_LEN(&meta) =
5649 (sizeof(qdf_ipa_wlan_msg_ex_t) +
5650 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
5651 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652
5653 if (msg_ex == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305654 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005655 "msg_ex allocation failed");
5656 return -ENOMEM;
5657 }
5658 strlcpy(msg_ex->name, adapter->dev->name,
5659 IPA_RESOURCE_NAME_MAX);
5660 msg_ex->num_of_attribs = 1;
5661 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
5662 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5663 msg_ex->attribs[0].offset =
5664 HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
5665 } else {
5666 msg_ex->attribs[0].offset =
5667 HDD_IPA_WLAN_HDR_DES_MAC_OFFSET;
5668 }
5669 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
5670 IPA_MAC_ADDR_SIZE);
5671
5672 ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn);
5673
5674 if (ret) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005675 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Evt: %d : %d",
Manjeet Singhfd51d8f2016-11-09 15:58:26 +05305676 adapter->dev->name, type, ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305677 qdf_mem_free(msg_ex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005678 return ret;
5679 }
5680 hdd_ipa->stats.num_send_msg++;
Yun Parkfec73dc2017-09-06 10:40:07 -07005681
Yun Park199c2ed2017-10-02 11:24:22 -07005682 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005683 hdd_ipa->sap_num_connected_sta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005684 return ret;
5685
5686 case WLAN_CLIENT_DISCONNECT:
5687 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005688 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 "%s: IPA UC OFFLOAD NOT ENABLED",
5690 msg_ex->name);
5691 return 0;
5692 }
5693
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305694 qdf_mutex_acquire(&hdd_ipa->event_lock);
Yun Park73ea8bb2017-08-25 07:27:39 -07005695 if (!hdd_ipa->sap_num_connected_sta) {
5696 qdf_mutex_release(&hdd_ipa->event_lock);
5697 hdd_err("%s: Evt: %d, Client already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005698 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Yun Park73ea8bb2017-08-25 07:27:39 -07005699 return 0;
5700 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005701 if (!hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, false, sta_id)) {
Yun Park64c405e2017-01-10 22:35:51 -08005702 qdf_mutex_release(&hdd_ipa->event_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305703 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005704 "%s: STA ID %d NOT found, not valid",
5705 msg_ex->name, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005706 return 0;
5707 }
5708 hdd_ipa->sap_num_connected_sta--;
Yun Parka37592b2016-06-11 17:10:28 -07005709
Yun Park9b5030f2016-11-08 12:02:37 -08005710 /* Disable IPA UC TX PIPE when last STA disconnected */
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005711 if (!hdd_ipa->sap_num_connected_sta &&
5712 hdd_ipa->uc_loaded == true) {
Yun Park9b5030f2016-11-08 12:02:37 -08005713 if ((false == hdd_ipa->resource_unloading)
5714 && (HDD_IPA_UC_NUM_WDI_PIPE ==
Govind Singhb78a75c2017-02-21 17:37:11 +05305715 hdd_ipa->activated_fw_pipe) &&
5716 !hdd_ipa->ipa_pipes_down) {
Yun Park9b5030f2016-11-08 12:02:37 -08005717 hdd_ipa_uc_handle_last_discon(hdd_ipa);
5718 }
5719
Yun Park9b5030f2016-11-08 12:02:37 -08005720 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
jiad9d472c92017-07-28 14:05:31 +08005721 hdd_ipa->sta_connected) {
5722 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Park9b5030f2016-11-08 12:02:37 -08005723 hdd_ipa_uc_offload_enable_disable(
5724 hdd_get_adapter(hdd_ipa->hdd_ctx,
5725 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005726 SIR_STA_RX_DATA_OFFLOAD, false);
jiad9d472c92017-07-28 14:05:31 +08005727 } else {
5728 qdf_mutex_release(&hdd_ipa->event_lock);
5729 }
Yun Park8f289c82016-10-18 16:38:21 -07005730 } else {
5731 qdf_mutex_release(&hdd_ipa->event_lock);
5732 }
Yun Parkfec73dc2017-09-06 10:40:07 -07005733
Yun Park199c2ed2017-10-02 11:24:22 -07005734 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005735 hdd_ipa->sap_num_connected_sta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005736 break;
5737
5738 default:
5739 return 0;
5740 }
5741
Yun Park6c86a662017-10-05 16:09:15 -07005742 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
5743 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005744 if (msg == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305745 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "msg allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005746 return -ENOMEM;
5747 }
5748
Yun Park6c86a662017-10-05 16:09:15 -07005749 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
5750 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), adapter->dev->name,
5751 IPA_RESOURCE_NAME_MAX);
5752 memcpy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, ETH_ALEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005753
Srinivas Girigowda97852372017-03-06 16:52:59 -08005754 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Evt: %d",
Yun Park6c86a662017-10-05 16:09:15 -07005755 QDF_IPA_WLAN_MSG_NAME(msg),
5756 QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757
5758 ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
5759
5760 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08005761 hdd_err("%s: Evt: %d fail:%d",
Yun Park6c86a662017-10-05 16:09:15 -07005762 QDF_IPA_WLAN_MSG_NAME(msg),
5763 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305764 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005765 return ret;
5766 }
5767
5768 hdd_ipa->stats.num_send_msg++;
5769
5770end:
5771 return ret;
5772}
5773
5774/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005775 * hdd_ipa_wlan_evt() - SSR wrapper for __hdd_ipa_wlan_evt
Mohit Khannafa99aea2016-05-12 21:43:13 -07005776 * @adapter: adapter upon which the event was received
5777 * @sta_id: station id for the event
5778 * @hdd_event_type: event enum of type hdd_ipa_wlan_event
5779 * @mac_address: MAC address associated with the event
5780 *
5781 * This function is meant to be called from outside of wlan_hdd_ipa.c.
5782 *
5783 * Return: 0 on success, negative errno value on error
5784 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07005785int hdd_ipa_wlan_evt(struct hdd_adapter *adapter, uint8_t sta_id,
Mohit Khannafa99aea2016-05-12 21:43:13 -07005786 enum hdd_ipa_wlan_event hdd_event_type, uint8_t *mac_addr)
5787{
Yun Park6c86a662017-10-05 16:09:15 -07005788 qdf_ipa_wlan_event_t type = hdd_to_ipa_wlan_event(hdd_event_type);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005789 int ret = 0;
5790
5791 cds_ssr_protect(__func__);
Mohit Khannafa99aea2016-05-12 21:43:13 -07005792
Leo Changa202b522016-10-14 16:13:50 -07005793 /* Data path offload only support for STA and SAP mode */
5794 if ((QDF_STA_MODE == adapter->device_mode) ||
5795 (QDF_SAP_MODE == adapter->device_mode))
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005796 ret = __hdd_ipa_wlan_evt(adapter, sta_id, type, mac_addr);
Leo Changa202b522016-10-14 16:13:50 -07005797
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005798 cds_ssr_unprotect(__func__);
5799
5800 return ret;
Mohit Khannafa99aea2016-05-12 21:43:13 -07005801}
5802
5803/**
5804 * hdd_ipa_uc_proc_pending_event() - Process IPA uC pending events
5805 * @hdd_ipa: Global HDD IPA context
Yun Parka4bb37c2017-12-08 16:14:22 -08005806 * @is_loading: Indicate if invoked during loading
Mohit Khannafa99aea2016-05-12 21:43:13 -07005807 *
5808 * Return: None
5809 */
5810static void
Yun Parka4bb37c2017-12-08 16:14:22 -08005811hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa, bool is_loading)
Mohit Khannafa99aea2016-05-12 21:43:13 -07005812{
5813 unsigned int pending_event_count;
5814 struct ipa_uc_pending_event *pending_event = NULL;
5815
5816 pending_event_count = qdf_list_size(&hdd_ipa->pending_event);
Srinivas Girigowda97852372017-03-06 16:52:59 -08005817 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07005818 "Pending Event Count %d", pending_event_count);
Mohit Khannafa99aea2016-05-12 21:43:13 -07005819 if (!pending_event_count) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005820 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07005821 "No Pending Event");
Mohit Khannafa99aea2016-05-12 21:43:13 -07005822 return;
5823 }
5824
5825 qdf_list_remove_front(&hdd_ipa->pending_event,
5826 (qdf_list_node_t **)&pending_event);
5827 while (pending_event != NULL) {
Yun Parka4bb37c2017-12-08 16:14:22 -08005828 if (pending_event->is_loading == is_loading)
5829 __hdd_ipa_wlan_evt(pending_event->adapter,
5830 pending_event->sta_id,
5831 pending_event->type,
5832 pending_event->mac_addr);
Mohit Khannafa99aea2016-05-12 21:43:13 -07005833 qdf_mem_free(pending_event);
5834 pending_event = NULL;
5835 qdf_list_remove_front(&hdd_ipa->pending_event,
5836 (qdf_list_node_t **)&pending_event);
5837 }
5838}
5839
5840/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841 * hdd_ipa_rm_state_to_str() - Convert IPA RM state to string
5842 * @state: IPA RM state value
5843 *
5844 * Return: ASCII string representing the IPA RM state
5845 */
5846static inline char *hdd_ipa_rm_state_to_str(enum hdd_ipa_rm_state state)
5847{
5848 switch (state) {
5849 case HDD_IPA_RM_RELEASED:
5850 return "RELEASED";
5851 case HDD_IPA_RM_GRANT_PENDING:
5852 return "GRANT_PENDING";
5853 case HDD_IPA_RM_GRANTED:
5854 return "GRANTED";
5855 }
5856
5857 return "UNKNOWN";
5858}
5859
5860/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005861 * __hdd_ipa_init() - IPA initialization function
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005862 * @hdd_ctx: HDD global context
5863 *
5864 * Allocate hdd_ipa resources, ipa pipe resource and register
5865 * wlan interface with IPA module.
5866 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305867 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005868 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07005869static QDF_STATUS __hdd_ipa_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870{
5871 struct hdd_ipa_priv *hdd_ipa = NULL;
5872 int ret, i;
5873 struct hdd_ipa_iface_context *iface_context = NULL;
Yun Parkbaa62862017-01-18 13:43:34 -08005874 struct ol_txrx_pdev_t *pdev = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07005875 qdf_ipa_rm_perf_profile_t profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005876
5877 if (!hdd_ipa_is_enabled(hdd_ctx))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305878 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005879
Rajeev Kumar3887f9b2018-01-10 11:24:01 -08005880 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Park199c2ed2017-10-02 11:24:22 -07005881
Yun Parkbaa62862017-01-18 13:43:34 -08005882 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Park7f171ab2016-07-29 15:44:22 -07005883 if (!pdev) {
5884 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "pdev is NULL");
5885 goto fail_return;
5886 }
5887
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305888 hdd_ipa = qdf_mem_malloc(sizeof(*hdd_ipa));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005889 if (!hdd_ipa) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305890 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed");
Leo Chang3bc8fed2015-11-13 10:59:47 -08005891 goto fail_return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005892 }
5893
5894 hdd_ctx->hdd_ipa = hdd_ipa;
5895 ghdd_ipa = hdd_ipa;
5896 hdd_ipa->hdd_ctx = hdd_ctx;
5897 hdd_ipa->num_iface = 0;
5898
5899 /* Create the interface context */
5900 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
5901 iface_context = &hdd_ipa->iface_context[i];
5902 iface_context->hdd_ipa = hdd_ipa;
5903 iface_context->cons_client =
5904 hdd_ipa_adapter_2_client[i].cons_client;
5905 iface_context->prod_client =
5906 hdd_ipa_adapter_2_client[i].prod_client;
5907 iface_context->iface_id = i;
5908 iface_context->adapter = NULL;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305909 qdf_spinlock_create(&iface_context->interface_lock);
Yun Park9b5030f2016-11-08 12:02:37 -08005910 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005911
Leo Chang69c39692016-10-12 20:11:12 -07005912 INIT_WORK(&hdd_ipa->pm_work, hdd_ipa_pm_flush);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305913 qdf_spinlock_create(&hdd_ipa->pm_lock);
Yun Park52b2b992016-09-22 15:49:51 -07005914 qdf_spinlock_create(&hdd_ipa->q_lock);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305915 qdf_nbuf_queue_init(&hdd_ipa->pm_queue_head);
Manikandan Mohan2e803a02017-02-14 14:57:53 -08005916 qdf_list_create(&hdd_ipa->pending_event, 1000);
5917 qdf_mutex_create(&hdd_ipa->event_lock);
5918 qdf_mutex_create(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919
5920 ret = hdd_ipa_setup_rm(hdd_ipa);
5921 if (ret)
5922 goto fail_setup_rm;
5923
Yun Park9281cb72017-11-30 11:14:30 -08005924 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++)
5925 qdf_mem_zero(&hdd_ipa->sys_pipe[i],
5926 sizeof(struct hdd_ipa_sys_pipe));
5927
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005928 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5929 hdd_ipa_uc_rt_debug_init(hdd_ctx);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305930 qdf_mem_zero(&hdd_ipa->stats, sizeof(hdd_ipa->stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 hdd_ipa->sap_num_connected_sta = 0;
5932 hdd_ipa->ipa_tx_packets_diff = 0;
5933 hdd_ipa->ipa_rx_packets_diff = 0;
5934 hdd_ipa->ipa_p_tx_packets = 0;
5935 hdd_ipa->ipa_p_rx_packets = 0;
5936 hdd_ipa->resource_loading = false;
5937 hdd_ipa->resource_unloading = false;
5938 hdd_ipa->sta_connected = 0;
Leo Change3e49442015-10-26 20:07:13 -07005939 hdd_ipa->ipa_pipes_down = true;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08005940 hdd_ipa->wdi_enabled = false;
Yun Park9281cb72017-11-30 11:14:30 -08005941 /* Setup IPA system pipes */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005942 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
5943 ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
5944 if (ret)
5945 goto fail_create_sys_pipe;
5946 }
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005947 if (hdd_ipa_uc_register_uc_ready(hdd_ipa))
5948 goto fail_create_sys_pipe;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005949 } else {
5950 ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
5951 if (ret)
5952 goto fail_create_sys_pipe;
5953 }
5954
Yun Park66f24c42017-03-20 10:39:47 -07005955 /* When IPA clock scaling is disabled, initialze maximum clock */
5956 if (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)) {
5957 profile.max_supported_bandwidth_mbps = 800;
5958 hdd_debug("IPA clock scaling is disabled.");
5959 hdd_debug("Set initial CONS/PROD perf: %d",
5960 profile.max_supported_bandwidth_mbps);
5961 ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS,
5962 &profile);
5963 if (ret) {
5964 hdd_err("RM CONS set perf profile failed: %d", ret);
5965 goto fail_create_sys_pipe;
5966 }
5967
5968 ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD,
5969 &profile);
5970 if (ret) {
5971 hdd_err("RM PROD set perf profile failed: %d", ret);
5972 goto fail_create_sys_pipe;
5973 }
5974 }
5975
Yun Park777d7242017-03-30 15:38:33 -07005976 init_completion(&hdd_ipa->ipa_resource_comp);
5977
Yun Parke4239802018-01-09 11:01:40 -08005978 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: success");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305979 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980
5981fail_create_sys_pipe:
5982 hdd_ipa_destroy_rm_resource(hdd_ipa);
5983fail_setup_rm:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305984 qdf_spinlock_destroy(&hdd_ipa->pm_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305985 qdf_mem_free(hdd_ipa);
Leo Chang3bc8fed2015-11-13 10:59:47 -08005986 hdd_ctx->hdd_ipa = NULL;
5987 ghdd_ipa = NULL;
5988fail_return:
Rajeev Kumar3887f9b2018-01-10 11:24:01 -08005989 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: fail");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305990 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991}
5992
5993/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005994 * hdd_ipa_init() - SSR wrapper for __hdd_ipa_init
5995 * @hdd_ctx: HDD global context
5996 *
5997 * Allocate hdd_ipa resources, ipa pipe resource and register
5998 * wlan interface with IPA module.
5999 *
6000 * Return: QDF_STATUS enumeration
6001 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07006002QDF_STATUS hdd_ipa_init(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006003{
6004 QDF_STATUS ret;
6005
6006 cds_ssr_protect(__func__);
6007 ret = __hdd_ipa_init(hdd_ctx);
6008 cds_ssr_unprotect(__func__);
6009
6010 return ret;
6011}
6012
Arun Khandavallicc544b32017-01-30 19:52:16 +05306013
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006014/**
Govind Singh1dab23b2017-08-12 13:31:00 +05306015 * __hdd_ipa_flush - flush IPA exception path SKB's
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006016 * @hdd_ctx: HDD global context
6017 *
Govind Singh1dab23b2017-08-12 13:31:00 +05306018 * Return: none
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006019 */
Govind Singh1dab23b2017-08-12 13:31:00 +05306020static void __hdd_ipa_flush(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006021{
6022 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
Nirav Shahcbc6d722016-03-01 16:24:53 +05306023 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006024 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
6025
6026 if (!hdd_ipa_is_enabled(hdd_ctx))
Govind Singh1dab23b2017-08-12 13:31:00 +05306027 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006029 cancel_work_sync(&hdd_ipa->pm_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006030
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306031 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006032
Nirav Shahcbc6d722016-03-01 16:24:53 +05306033 while (((skb = qdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head))
6034 != NULL)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306035 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006036
6037 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Yun Parked827b42017-05-12 23:59:27 -07006038 if (pm_tx_cb->ipa_tx_desc)
6039 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006040
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306041 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306043 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Govind Singh1dab23b2017-08-12 13:31:00 +05306044}
6045
6046/**
6047 * __hdd_ipa_cleanup - IPA cleanup function
6048 * @hdd_ctx: HDD global context
6049 *
6050 * Return: QDF_STATUS enumeration
6051 */
6052static QDF_STATUS __hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
6053{
6054 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
6055 int i;
6056 struct hdd_ipa_iface_context *iface_context = NULL;
6057
6058 if (!hdd_ipa_is_enabled(hdd_ctx))
6059 return QDF_STATUS_SUCCESS;
6060
6061 if (!hdd_ipa_uc_is_enabled(hdd_ctx)) {
6062 unregister_inetaddr_notifier(&hdd_ipa->ipv4_notifier);
6063 hdd_ipa_teardown_sys_pipe(hdd_ipa);
6064 }
6065
6066 /* Teardown IPA sys_pipe for MCC */
6067 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
6068 hdd_ipa_teardown_sys_pipe(hdd_ipa);
6069
6070 hdd_ipa_destroy_rm_resource(hdd_ipa);
6071
6072 __hdd_ipa_flush(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306074 qdf_spinlock_destroy(&hdd_ipa->pm_lock);
Yun Park52b2b992016-09-22 15:49:51 -07006075 qdf_spinlock_destroy(&hdd_ipa->q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006076
6077 /* destory the interface lock */
6078 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
6079 iface_context = &hdd_ipa->iface_context[i];
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306080 qdf_spinlock_destroy(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006081 }
6082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006083 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Park7e1f7c02017-01-05 08:19:49 -08006084 if (ipa_uc_dereg_rdyCB())
6085 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
6086 "UC Ready CB deregister fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006087 hdd_ipa_uc_rt_debug_deinit(hdd_ctx);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306088 qdf_mutex_destroy(&hdd_ipa->event_lock);
6089 qdf_mutex_destroy(&hdd_ipa->ipa_lock);
Yun Parkd8fb1a82017-10-13 16:48:20 -07006090 qdf_list_destroy(&hdd_ipa->pending_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006092 for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
6093 cancel_work_sync(&hdd_ipa->uc_op_work[i].work);
6094 hdd_ipa->uc_op_work[i].msg = NULL;
6095 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006096 }
6097
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306098 qdf_mem_free(hdd_ipa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006099 hdd_ctx->hdd_ipa = NULL;
6100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306101 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006102}
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006103
6104/**
Govind Singh1dab23b2017-08-12 13:31:00 +05306105 * hdd_ipa_cleanup - SSR wrapper for __hdd_ipa_flush
6106 * @hdd_ctx: HDD global context
6107 *
6108 * Return: None
6109 */
6110void hdd_ipa_flush(struct hdd_context *hdd_ctx)
6111{
6112 cds_ssr_protect(__func__);
6113 __hdd_ipa_flush(hdd_ctx);
6114 cds_ssr_unprotect(__func__);
6115}
6116
6117/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006118 * hdd_ipa_cleanup - SSR wrapper for __hdd_ipa_cleanup
6119 * @hdd_ctx: HDD global context
6120 *
6121 * Return: QDF_STATUS enumeration
6122 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07006123QDF_STATUS hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006124{
6125 QDF_STATUS ret;
6126
6127 cds_ssr_protect(__func__);
6128 ret = __hdd_ipa_cleanup(hdd_ctx);
6129 cds_ssr_unprotect(__func__);
6130
6131 return ret;
6132}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006133#endif /* IPA_OFFLOAD */