blob: b1ff7cb91ae25614e53386bf67af8f0c65cd4267 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
jge62037862016-12-09 10:44:33 +08002 * Copyright (c) 2013-2017 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];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312};
313
314/**
315 * struct uc_rm_work_struct
316 * @work: uC RM work
317 * @event: IPA RM event
318 */
319struct uc_rm_work_struct {
320 struct work_struct work;
Yun Park6c86a662017-10-05 16:09:15 -0700321 qdf_ipa_rm_event_t event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322};
323
324/**
325 * struct uc_op_work_struct
326 * @work: uC OP work
327 * @msg: OP message
328 */
329struct uc_op_work_struct {
330 struct work_struct work;
331 struct op_msg_type *msg;
332};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800333
334/**
335 * struct uc_rt_debug_info
336 * @time: system time
337 * @ipa_excep_count: IPA exception packet count
338 * @rx_drop_count: IPA Rx drop packet count
339 * @net_sent_count: IPA Rx packet sent to network stack count
340 * @rx_discard_count: IPA Rx discard packet count
Yun Parkb187d542016-11-14 18:10:04 -0800341 * @tx_fwd_ok_count: IPA Tx forward success packet count
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342 * @tx_fwd_count: IPA Tx forward packet count
343 * @rx_destructor_call: IPA Rx packet destructor count
344 */
345struct uc_rt_debug_info {
Deepthi Gowri6acee342016-10-28 15:00:38 +0530346 uint64_t time;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800347 uint64_t ipa_excep_count;
348 uint64_t rx_drop_count;
349 uint64_t net_sent_count;
350 uint64_t rx_discard_count;
Yun Parkb187d542016-11-14 18:10:04 -0800351 uint64_t tx_fwd_ok_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 uint64_t tx_fwd_count;
353 uint64_t rx_destructor_call;
354};
355
Yun Park637d6482016-10-05 10:51:33 -0700356#ifdef FEATURE_METERING
357struct ipa_uc_sharing_stats {
358 uint64_t ipv4_rx_packets;
359 uint64_t ipv4_rx_bytes;
360 uint64_t ipv6_rx_packets;
361 uint64_t ipv6_rx_bytes;
362 uint64_t ipv4_tx_packets;
363 uint64_t ipv4_tx_bytes;
364 uint64_t ipv6_tx_packets;
365 uint64_t ipv6_tx_bytes;
366};
367
368struct ipa_uc_quota_rsp {
369 uint8_t success;
370 uint8_t reserved[3];
371 uint32_t quota_lo; /* quota limit low bytes */
372 uint32_t quota_hi; /* quota limit high bytes */
373};
374
375struct ipa_uc_quota_ind {
376 uint64_t quota_bytes; /* quota limit in bytes */
377};
378#endif
379
Yun Park52b2b992016-09-22 15:49:51 -0700380/**
381 * struct hdd_ipa_tx_desc
382 * @link: link to list head
383 * @priv: pointer to priv list entry
384 * @id: Tx desc idex
385 * @ipa_tx_desc_ptr: pointer to IPA Tx descriptor
386 */
387struct hdd_ipa_tx_desc {
388 struct list_head link;
389 void *priv;
390 uint32_t id;
Yun Park6c86a662017-10-05 16:09:15 -0700391 qdf_ipa_rx_data_t *ipa_tx_desc_ptr;
Yun Park52b2b992016-09-22 15:49:51 -0700392};
393
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394struct hdd_ipa_priv {
395 struct hdd_ipa_sys_pipe sys_pipe[HDD_IPA_MAX_SYSBAM_PIPE];
396 struct hdd_ipa_iface_context iface_context[HDD_IPA_MAX_IFACE];
397 uint8_t num_iface;
398 enum hdd_ipa_rm_state rm_state;
399 /*
Nirav Shahcbc6d722016-03-01 16:24:53 +0530400 * IPA driver can send RM notifications with IRQ disabled so using qdf
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 * APIs as it is taken care gracefully. Without this, kernel would throw
402 * an warning if spin_lock_bh is used while IRQ is disabled
403 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530404 qdf_spinlock_t rm_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 struct uc_rm_work_struct uc_rm_work;
406 struct uc_op_work_struct uc_op_work[HDD_IPA_UC_OPCODE_MAX];
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530407 qdf_wake_lock_t wake_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 struct delayed_work wake_lock_work;
409 bool wake_lock_released;
410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 atomic_t tx_ref_cnt;
Nirav Shahcbc6d722016-03-01 16:24:53 +0530412 qdf_nbuf_queue_t pm_queue_head;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 struct work_struct pm_work;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530414 qdf_spinlock_t pm_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 bool suspended;
416
Yun Park52b2b992016-09-22 15:49:51 -0700417 qdf_spinlock_t q_lock;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419 struct list_head pend_desc_head;
Yun Park52b2b992016-09-22 15:49:51 -0700420 struct hdd_ipa_tx_desc *tx_desc_list;
421 struct list_head free_tx_desc_head;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700423 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 struct hdd_ipa_stats stats;
425
426 struct notifier_block ipv4_notifier;
427 uint32_t curr_prod_bw;
428 uint32_t curr_cons_bw;
429
430 uint8_t activated_fw_pipe;
431 uint8_t sap_num_connected_sta;
432 uint8_t sta_connected;
433 uint32_t tx_pipe_handle;
434 uint32_t rx_pipe_handle;
435 bool resource_loading;
436 bool resource_unloading;
437 bool pending_cons_req;
438 struct ipa_uc_stas_map assoc_stas_map[WLAN_MAX_STA_COUNT];
Anurag Chouhanffb21542016-02-17 14:33:03 +0530439 qdf_list_t pending_event;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530440 qdf_mutex_t event_lock;
Leo Change3e49442015-10-26 20:07:13 -0700441 bool ipa_pipes_down;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 uint32_t ipa_tx_packets_diff;
443 uint32_t ipa_rx_packets_diff;
444 uint32_t ipa_p_tx_packets;
445 uint32_t ipa_p_rx_packets;
446 uint32_t stat_req_reason;
447 uint64_t ipa_tx_forward;
448 uint64_t ipa_rx_discard;
449 uint64_t ipa_rx_net_send_count;
Yun Park46255682017-10-09 15:56:34 -0700450 uint64_t ipa_rx_internal_drop_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 uint64_t ipa_rx_destructor_count;
Anurag Chouhan210db072016-02-22 18:42:15 +0530452 qdf_mc_timer_t rt_debug_timer;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453 struct uc_rt_debug_info rt_bug_buffer[HDD_IPA_UC_RT_DEBUG_BUF_COUNT];
454 unsigned int rt_buf_fill_index;
Yun Park6c86a662017-10-05 16:09:15 -0700455 qdf_ipa_wdi_in_params_t cons_pipe_in;
456 qdf_ipa_wdi_in_params_t prod_pipe_in;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800457 bool uc_loaded;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800458 bool wdi_enabled;
Anurag Chouhan210db072016-02-22 18:42:15 +0530459 qdf_mc_timer_t rt_debug_fill_timer;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530460 qdf_mutex_t rt_debug_lock;
461 qdf_mutex_t ipa_lock;
Yun Parkb4f591d2017-03-29 15:51:01 -0700462
Prakash Dhavali89d406d2016-11-23 11:11:00 -0800463 uint8_t vdev_to_iface[CSR_ROAM_SESSION_MAX];
464 bool vdev_offload_enabled[CSR_ROAM_SESSION_MAX];
Yun Park637d6482016-10-05 10:51:33 -0700465#ifdef FEATURE_METERING
466 struct ipa_uc_sharing_stats ipa_sharing_stats;
467 struct ipa_uc_quota_rsp ipa_quota_rsp;
468 struct ipa_uc_quota_ind ipa_quota_ind;
469 struct completion ipa_uc_sharing_stats_comp;
470 struct completion ipa_uc_set_quota_comp;
471#endif
Yun Park777d7242017-03-30 15:38:33 -0700472 struct completion ipa_resource_comp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473};
474
Leo Changcc923e22016-06-16 15:29:03 -0700475#define HDD_IPA_WLAN_FRAG_HEADER sizeof(struct frag_header)
476#define HDD_IPA_WLAN_IPA_HEADER sizeof(struct ipa_header)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477#define HDD_IPA_WLAN_CLD_HDR_LEN sizeof(struct hdd_ipa_cld_hdr)
478#define HDD_IPA_UC_WLAN_CLD_HDR_LEN 0
479#define HDD_IPA_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_tx_hdr)
480#define HDD_IPA_UC_WLAN_TX_HDR_LEN sizeof(struct hdd_ipa_uc_tx_hdr)
481#define HDD_IPA_WLAN_RX_HDR_LEN sizeof(struct hdd_ipa_rx_hdr)
Leo Changcc923e22016-06-16 15:29:03 -0700482#define HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET \
483 (HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484
485#define HDD_IPA_GET_IFACE_ID(_data) \
486 (((struct hdd_ipa_cld_hdr *) (_data))->iface_id)
487
488#define HDD_IPA_LOG(LVL, fmt, args ...) \
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530489 QDF_TRACE(QDF_MODULE_ID_HDD, LVL, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800490 "%s:%d: "fmt, __func__, __LINE__, ## args)
491
Govind Singhb6a89772016-08-12 11:23:35 +0530492#define HDD_IPA_DP_LOG(LVL, fmt, args...) \
493 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, LVL, \
494 "%s:%d: "fmt, __func__, __LINE__, ## args)
495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800496#define HDD_IPA_DBG_DUMP(_lvl, _prefix, _buf, _len) \
497 do { \
Yun Parkec845302016-12-15 09:22:57 -0800498 QDF_TRACE(QDF_MODULE_ID_HDD_DATA, _lvl, "%s:", _prefix); \
499 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD_DATA, _lvl, _buf, _len); \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 } while (0)
501
502#define HDD_IPA_IS_CONFIG_ENABLED(_hdd_ctx, _mask) \
503 (((_hdd_ctx)->config->IpaConfig & (_mask)) == (_mask))
504
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505#define HDD_BW_GET_DIFF(_x, _y) (unsigned long)((ULONG_MAX - (_y)) + (_x) + 1)
506
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -0700507#if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
Leo Chang63d73612016-10-18 18:09:43 -0700508#define HDD_IPA_CHECK_HW() ipa_uc_reg_rdyCB(NULL)
Leo Chang3bc8fed2015-11-13 10:59:47 -0800509#else
510/* Do nothing */
Leo Chang63d73612016-10-18 18:09:43 -0700511#define HDD_IPA_CHECK_HW() 0
Leo Chang07b28f62016-05-11 12:29:22 -0700512#endif /* IPA3 */
Leo Chang3bc8fed2015-11-13 10:59:47 -0800513
Yun Park0dad1002017-07-14 14:57:01 -0700514#define HDD_IPA_DBG_DUMP_RX_LEN 84
Yun Parkb187d542016-11-14 18:10:04 -0800515#define HDD_IPA_DBG_DUMP_TX_LEN 48
516
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517static struct hdd_ipa_adapter_2_client {
Yun Park6c86a662017-10-05 16:09:15 -0700518 qdf_ipa_client_type_t cons_client;
519 qdf_ipa_client_type_t prod_client;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520} hdd_ipa_adapter_2_client[HDD_IPA_MAX_IFACE] = {
521 {
522 IPA_CLIENT_WLAN2_CONS, IPA_CLIENT_WLAN1_PROD
523 }, {
524 IPA_CLIENT_WLAN3_CONS, IPA_CLIENT_WLAN1_PROD
525 }, {
526 IPA_CLIENT_WLAN4_CONS, IPA_CLIENT_WLAN1_PROD
527 },
528};
529
Yun Park637d6482016-10-05 10:51:33 -0700530#ifdef FEATURE_METERING
531#define IPA_UC_SHARING_STATES_WAIT_TIME 500
532#define IPA_UC_SET_QUOTA_WAIT_TIME 500
533#endif
534
Yun Park777d7242017-03-30 15:38:33 -0700535#define IPA_RESOURCE_COMP_WAIT_TIME 100
536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537static struct hdd_ipa_priv *ghdd_ipa;
538
539/* Local Function Prototypes */
Yun Park6c86a662017-10-05 16:09:15 -0700540static void hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 unsigned long data);
Yun Park6c86a662017-10-05 16:09:15 -0700542static void hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800543 unsigned long data);
Yun Parkb4f591d2017-03-29 15:51:01 -0700544#ifdef FEATURE_METERING
Yun Park6c86a662017-10-05 16:09:15 -0700545static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Parkb4f591d2017-03-29 15:51:01 -0700546 void *data);
547#else
548static void hdd_ipa_wdi_meter_notifier_cb(void);
549#endif
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800550static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551
552static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context);
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -0700553static void hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800555#if ((defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)) || \
556 defined(IPA_CLIENT_IS_MHI_CONS))
557/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800558 * hdd_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
559 * @priv_ctxt: hdd ipa local context
560 *
561 * Will be called by IPA context.
562 * It's atomic context, then should be scheduled to kworker thread
563 *
564 * Return: None
565 */
566static void hdd_ipa_uc_loaded_uc_cb(void *priv_ctxt)
567{
568 struct hdd_ipa_priv *hdd_ipa;
569 struct op_msg_type *msg;
570 struct uc_op_work_struct *uc_op_work;
571
572 if (priv_ctxt == NULL) {
573 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Invalid IPA context");
574 return;
575 }
576
577 hdd_ipa = (struct hdd_ipa_priv *)priv_ctxt;
578 msg = (struct op_msg_type *)qdf_mem_malloc(sizeof(*msg));
579 if (!msg) {
580 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "op_msg allocation fails");
581 return;
582 }
583
584 msg->op_code = HDD_IPA_UC_OPCODE_UC_READY;
585
586 uc_op_work = &hdd_ipa->uc_op_work[msg->op_code];
587
588 /* When the same uC OPCODE is already pended, just return */
589 if (uc_op_work->msg)
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530590 goto done;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800591
592 uc_op_work->msg = msg;
593 schedule_work(&uc_op_work->work);
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530594
jiadd91a6842017-08-01 14:46:02 +0800595 /* work handler will free the msg buffer */
596 return;
597
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +0530598done:
599 qdf_mem_free(msg);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800600}
601
602/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800603 * hdd_ipa_uc_send_wdi_control_msg() - Set WDI control message
604 * @ctrl: WDI control value
605 *
606 * Send WLAN_WDI_ENABLE for ctrl = true and WLAN_WDI_DISABLE otherwise.
607 *
608 * Return: 0 on message send to ipa, -1 on failure
609 */
610static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
611{
Yun Park6c86a662017-10-05 16:09:15 -0700612 qdf_ipa_msg_meta_t meta;
613 qdf_ipa_wlan_msg_t *ipa_msg;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800614 int ret = 0;
615
616 /* WDI enable message to IPA */
Yun Park6c86a662017-10-05 16:09:15 -0700617 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*ipa_msg);
618 ipa_msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800619 if (ipa_msg == NULL) {
620 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
621 "msg allocation failed");
622 return -ENOMEM;
623 }
624
625 if (ctrl == true)
Yun Park6c86a662017-10-05 16:09:15 -0700626 QDF_IPA_MSG_META_MSG_TYPE(&meta) = WLAN_WDI_ENABLE;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800627 else
Yun Park6c86a662017-10-05 16:09:15 -0700628 QDF_IPA_MSG_META_MSG_TYPE(&meta) = WLAN_WDI_DISABLE;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800629
Srinivas Girigowda97852372017-03-06 16:52:59 -0800630 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park6c86a662017-10-05 16:09:15 -0700631 "ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
632 ret = qdf_ipa_send_msg(&meta, ipa_msg, hdd_ipa_msg_free_fn);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800633 if (ret) {
634 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
635 "ipa_send_msg(Evt:%d)-fail=%d",
Yun Park6c86a662017-10-05 16:09:15 -0700636 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800637 qdf_mem_free(ipa_msg);
638 }
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800639 return ret;
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800640}
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800641
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800642/**
643 * hdd_ipa_uc_register_uc_ready() - Register UC ready callback function to IPA
644 * @hdd_ipa: HDD IPA local context
645 *
646 * Register IPA UC ready callback function to IPA kernel driver
647 * Even IPA UC loaded later than WLAN kernel driver, WLAN kernel driver will
648 * open WDI pipe after WLAN driver loading finished
649 *
650 * Return: 0 Success
651 * -EPERM Registration fail
652 */
653static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
654{
Yun Park6c86a662017-10-05 16:09:15 -0700655 qdf_ipa_wdi_uc_ready_params_t uc_ready_param;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800656 int ret = 0;
657
658 hdd_ipa->uc_loaded = false;
Yun Park6c86a662017-10-05 16:09:15 -0700659 QDF_IPA_UC_READY_PARAMS_PRIV(&uc_ready_param) = (void *)hdd_ipa;
660 QDF_IPA_UC_READY_PARAMS_NOTIFY(&uc_ready_param) =
661 hdd_ipa_uc_loaded_uc_cb;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800662 if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
663 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
664 "UC Ready CB register fail");
665 return -EPERM;
666 }
Yun Park6c86a662017-10-05 16:09:15 -0700667 if (false != QDF_IPA_UC_READY_PARAMS_IS_UC_READY(&uc_ready_param)) {
Srinivas Girigowda2b5d47c2017-03-29 00:28:46 -0700668 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
Manikandan Mohancd64c0b2017-03-08 13:00:24 -0800669 hdd_ipa->uc_loaded = true;
670 } else {
671 ret = hdd_ipa_uc_send_wdi_control_msg(false);
672 }
673
674 return ret;
675}
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800676#else
Manikandan Mohan153a4c32017-02-16 15:04:30 -0800677static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
678{
679 hdd_ipa->uc_loaded = true;
680 return 0;
681}
682
683static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
684{
685 return 0;
686}
687#endif
688
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689/**
690 * hdd_ipa_is_enabled() - Is IPA enabled?
691 * @hdd_ctx: Global HDD context
692 *
693 * Return: true if IPA is enabled, false otherwise
694 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700695bool hdd_ipa_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696{
697 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_ENABLE_MASK);
698}
699
700/**
701 * hdd_ipa_uc_is_enabled() - Is IPA uC offload enabled?
702 * @hdd_ctx: Global HDD context
703 *
704 * Return: true if IPA uC offload is enabled, false otherwise
705 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700706bool hdd_ipa_uc_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707{
708 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_ENABLE_MASK);
709}
710
711/**
712 * hdd_ipa_uc_sta_is_enabled() - Is STA mode IPA uC offload enabled?
713 * @hdd_ctx: Global HDD context
714 *
715 * Return: true if STA mode IPA uC offload is enabled, false otherwise
716 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700717static inline bool hdd_ipa_uc_sta_is_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718{
719 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_UC_STA_ENABLE_MASK);
720}
721
722/**
Guolei Bianca144d82016-11-10 11:07:42 +0800723 * hdd_ipa_uc_sta_reset_sta_connected() - Reset sta_connected flag
724 * @hdd_ipa: Global HDD IPA context
725 *
726 * Return: None
727 */
Guolei Bianca144d82016-11-10 11:07:42 +0800728static inline void hdd_ipa_uc_sta_reset_sta_connected(
729 struct hdd_ipa_priv *hdd_ipa)
730{
Yun Park637d6482016-10-05 10:51:33 -0700731 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Guolei Bianca144d82016-11-10 11:07:42 +0800732 hdd_ipa->sta_connected = 0;
Yun Park637d6482016-10-05 10:51:33 -0700733 qdf_mutex_release(&hdd_ipa->ipa_lock);
Guolei Bianca144d82016-11-10 11:07:42 +0800734}
Guolei Bianca144d82016-11-10 11:07:42 +0800735
736/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800737 * hdd_ipa_is_pre_filter_enabled() - Is IPA pre-filter enabled?
738 * @hdd_ipa: Global HDD IPA context
739 *
740 * Return: true if pre-filter is enabled, otherwise false
741 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700742static inline bool hdd_ipa_is_pre_filter_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800743{
744 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx,
745 HDD_IPA_PRE_FILTER_ENABLE_MASK);
746}
747
748/**
749 * hdd_ipa_is_ipv6_enabled() - Is IPA IPv6 enabled?
750 * @hdd_ipa: Global HDD IPA context
751 *
752 * Return: true if IPv6 is enabled, otherwise false
753 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700754static inline bool hdd_ipa_is_ipv6_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755{
756 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_IPV6_ENABLE_MASK);
757}
758
759/**
760 * hdd_ipa_is_rm_enabled() - Is IPA resource manager enabled?
761 * @hdd_ipa: Global HDD IPA context
762 *
763 * Return: true if resource manager is enabled, otherwise false
764 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700765static inline bool hdd_ipa_is_rm_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800766{
767 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_RM_ENABLE_MASK);
768}
769
770/**
771 * hdd_ipa_is_rt_debugging_enabled() - Is IPA real-time debug enabled?
772 * @hdd_ipa: Global HDD IPA context
773 *
774 * Return: true if resource manager is enabled, otherwise false
775 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700776static inline bool hdd_ipa_is_rt_debugging_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777{
778 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx, HDD_IPA_REAL_TIME_DEBUGGING);
779}
780
781/**
782 * hdd_ipa_is_clk_scaling_enabled() - Is IPA clock scaling enabled?
783 * @hdd_ipa: Global HDD IPA context
784 *
785 * Return: true if clock scaling is enabled, otherwise false
786 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700787static inline bool hdd_ipa_is_clk_scaling_enabled(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788{
789 return HDD_IPA_IS_CONFIG_ENABLED(hdd_ctx,
790 HDD_IPA_CLK_SCALING_ENABLE_MASK |
791 HDD_IPA_RM_ENABLE_MASK);
792}
793
794/**
795 * hdd_ipa_uc_rt_debug_host_fill - fill rt debug buffer
796 * @ctext: pointer to hdd context.
797 *
798 * If rt debug enabled, periodically called, and fill debug buffer
799 *
800 * Return: none
801 */
802static void hdd_ipa_uc_rt_debug_host_fill(void *ctext)
803{
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700804 struct hdd_context *hdd_ctx = (struct hdd_context *)ctext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 struct hdd_ipa_priv *hdd_ipa;
806 struct uc_rt_debug_info *dump_info = NULL;
807
808 if (wlan_hdd_validate_context(hdd_ctx))
809 return;
810
811 if (!hdd_ctx->hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700812 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "IPA UC is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 return;
814 }
815
816 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
817
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530818 qdf_mutex_acquire(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 dump_info = &hdd_ipa->rt_bug_buffer[
820 hdd_ipa->rt_buf_fill_index % HDD_IPA_UC_RT_DEBUG_BUF_COUNT];
821
Deepthi Gowri6acee342016-10-28 15:00:38 +0530822 dump_info->time = (uint64_t)qdf_mc_timer_get_system_time();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 dump_info->ipa_excep_count = hdd_ipa->stats.num_rx_excep;
Yun Park46255682017-10-09 15:56:34 -0700824 dump_info->rx_drop_count = hdd_ipa->ipa_rx_internal_drop_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 dump_info->net_sent_count = hdd_ipa->ipa_rx_net_send_count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 dump_info->tx_fwd_count = hdd_ipa->ipa_tx_forward;
Yun Parkb187d542016-11-14 18:10:04 -0800827 dump_info->tx_fwd_ok_count = hdd_ipa->stats.num_tx_fwd_ok;
828 dump_info->rx_discard_count = hdd_ipa->ipa_rx_discard;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800829 dump_info->rx_destructor_call = hdd_ipa->ipa_rx_destructor_count;
830 hdd_ipa->rt_buf_fill_index++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530831 qdf_mutex_release(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800832
Anurag Chouhan210db072016-02-22 18:42:15 +0530833 qdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834 HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
835}
836
837/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700838 * __hdd_ipa_uc_rt_debug_host_dump - dump rt debug buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839 * @hdd_ctx: pointer to hdd context.
840 *
841 * If rt debug enabled, dump debug buffer contents based on requirement
842 *
843 * Return: none
844 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700845static void __hdd_ipa_uc_rt_debug_host_dump(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846{
847 struct hdd_ipa_priv *hdd_ipa;
848 unsigned int dump_count;
849 unsigned int dump_index;
850 struct uc_rt_debug_info *dump_info = NULL;
851
852 if (wlan_hdd_validate_context(hdd_ctx))
853 return;
854
855 hdd_ipa = hdd_ctx->hdd_ipa;
856 if (!hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700857 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "IPA UC is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 return;
859 }
860
Chris Guo1751acf2017-07-03 14:09:01 +0800861 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
862 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -0700863 "IPA RT debug is not enabled");
Chris Guo1751acf2017-07-03 14:09:01 +0800864 return;
865 }
866
Yun Park46255682017-10-09 15:56:34 -0700867 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868 "========= WLAN-IPA DEBUG BUF DUMP ==========\n");
Yun Park46255682017-10-09 15:56:34 -0700869 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Parkb187d542016-11-14 18:10:04 -0800870 " TM : EXEP : DROP : NETS : FWOK : TXFD : DSTR : DSCD\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530872 qdf_mutex_acquire(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800873 for (dump_count = 0;
874 dump_count < HDD_IPA_UC_RT_DEBUG_BUF_COUNT;
875 dump_count++) {
876 dump_index = (hdd_ipa->rt_buf_fill_index + dump_count) %
877 HDD_IPA_UC_RT_DEBUG_BUF_COUNT;
878 dump_info = &hdd_ipa->rt_bug_buffer[dump_index];
Yun Park46255682017-10-09 15:56:34 -0700879 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Deepthi Gowri6acee342016-10-28 15:00:38 +0530880 "%12llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800881 dump_info->time, dump_info->ipa_excep_count,
882 dump_info->rx_drop_count, dump_info->net_sent_count,
Yun Parkb187d542016-11-14 18:10:04 -0800883 dump_info->tx_fwd_ok_count, dump_info->tx_fwd_count,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 dump_info->rx_destructor_call,
885 dump_info->rx_discard_count);
886 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530887 qdf_mutex_release(&hdd_ipa->rt_debug_lock);
Yun Park46255682017-10-09 15:56:34 -0700888 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889 "======= WLAN-IPA DEBUG BUF DUMP END ========\n");
890}
891
892/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700893 * hdd_ipa_uc_rt_debug_host_dump - SSR wrapper for
894 * __hdd_ipa_uc_rt_debug_host_dump
895 * @hdd_ctx: pointer to hdd context.
896 *
897 * If rt debug enabled, dump debug buffer contents based on requirement
898 *
899 * Return: none
900 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700901void hdd_ipa_uc_rt_debug_host_dump(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700902{
903 cds_ssr_protect(__func__);
904 __hdd_ipa_uc_rt_debug_host_dump(hdd_ctx);
905 cds_ssr_unprotect(__func__);
906}
907
908/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909 * hdd_ipa_uc_rt_debug_handler - periodic memory health monitor handler
910 * @ctext: pointer to hdd context.
911 *
912 * periodically called by timer expire
913 * will try to alloc dummy memory and detect out of memory condition
914 * if out of memory detected, dump wlan-ipa stats
915 *
916 * Return: none
917 */
918static void hdd_ipa_uc_rt_debug_handler(void *ctext)
919{
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700920 struct hdd_context *hdd_ctx = (struct hdd_context *)ctext;
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700921 struct hdd_ipa_priv *hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 void *dummy_ptr = NULL;
923
924 if (wlan_hdd_validate_context(hdd_ctx))
925 return;
926
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700927 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
928
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700930 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
931 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800932 return;
933 }
934
935 /* Allocate dummy buffer periodically and free immediately. this will
936 * proactively detect OOM and if allocation fails dump ipa stats
937 */
938 dummy_ptr = kmalloc(HDD_IPA_UC_DEBUG_DUMMY_MEM_SIZE,
939 GFP_KERNEL | GFP_ATOMIC);
940 if (!dummy_ptr) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 hdd_ipa_uc_rt_debug_host_dump(hdd_ctx);
942 hdd_ipa_uc_stat_request(
Yun Park637d6482016-10-05 10:51:33 -0700943 hdd_get_adapter(hdd_ctx, QDF_SAP_MODE),
944 HDD_IPA_UC_STAT_REASON_DEBUG);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 } else {
946 kfree(dummy_ptr);
947 }
948
Anurag Chouhan210db072016-02-22 18:42:15 +0530949 qdf_mc_timer_start(&hdd_ipa->rt_debug_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 HDD_IPA_UC_RT_DEBUG_PERIOD);
951}
952
953/**
Yun Parkb187d542016-11-14 18:10:04 -0800954 * hdd_ipa_uc_rt_debug_destructor() - called by data packet free
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 * @skb: packet pinter
956 *
957 * when free data packet, will be invoked by wlan client and will increase
958 * free counter
959 *
960 * Return: none
961 */
Jeff Johnsond7720632016-10-05 16:04:32 -0700962static void hdd_ipa_uc_rt_debug_destructor(struct sk_buff *skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963{
964 if (!ghdd_ipa) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700965 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "invalid hdd context");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966 return;
967 }
968
969 ghdd_ipa->ipa_rx_destructor_count++;
970}
971
972/**
Yun Parkb187d542016-11-14 18:10:04 -0800973 * hdd_ipa_uc_rt_debug_deinit() - remove resources to handle rt debugging
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 * @hdd_ctx: hdd main context
975 *
976 * free all rt debugging resources
977 *
978 * Return: none
979 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -0700980static void hdd_ipa_uc_rt_debug_deinit(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981{
Prakash Dhavali412cdb02016-10-20 21:19:31 -0700982 struct hdd_ipa_priv *hdd_ipa;
983
984 if (wlan_hdd_validate_context(hdd_ctx))
985 return;
986
987 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530989 qdf_mutex_destroy(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800990
991 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -0700992 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
993 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994 return;
995 }
996
Anurag Chouhan210db072016-02-22 18:42:15 +0530997 if (QDF_TIMER_STATE_STOPPED !=
Prakash Dhavali169de302016-11-30 12:52:49 -0800998 qdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_fill_timer)) {
999 qdf_mc_timer_stop(&hdd_ipa->rt_debug_fill_timer);
1000 }
1001 qdf_mc_timer_destroy(&hdd_ipa->rt_debug_fill_timer);
1002
1003 if (QDF_TIMER_STATE_STOPPED !=
Anurag Chouhan210db072016-02-22 18:42:15 +05301004 qdf_mc_timer_get_current_state(&hdd_ipa->rt_debug_timer)) {
1005 qdf_mc_timer_stop(&hdd_ipa->rt_debug_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006 }
Anurag Chouhan210db072016-02-22 18:42:15 +05301007 qdf_mc_timer_destroy(&hdd_ipa->rt_debug_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008}
1009
1010/**
Yun Parkb187d542016-11-14 18:10:04 -08001011 * hdd_ipa_uc_rt_debug_init() - intialize resources to handle rt debugging
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 * @hdd_ctx: hdd main context
1013 *
1014 * alloc and initialize all rt debugging resources
1015 *
1016 * Return: none
1017 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001018static void hdd_ipa_uc_rt_debug_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001019{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001020 struct hdd_ipa_priv *hdd_ipa;
1021
Chris Guo1751acf2017-07-03 14:09:01 +08001022 if (wlan_hdd_validate_context_in_loading(hdd_ctx))
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001023 return;
1024
1025 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301027 qdf_mutex_create(&hdd_ipa->rt_debug_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001028 hdd_ipa->rt_buf_fill_index = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301029 qdf_mem_zero(hdd_ipa->rt_bug_buffer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001030 sizeof(struct uc_rt_debug_info) *
1031 HDD_IPA_UC_RT_DEBUG_BUF_COUNT);
1032 hdd_ipa->ipa_tx_forward = 0;
1033 hdd_ipa->ipa_rx_discard = 0;
1034 hdd_ipa->ipa_rx_net_send_count = 0;
Yun Park46255682017-10-09 15:56:34 -07001035 hdd_ipa->ipa_rx_internal_drop_count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036 hdd_ipa->ipa_rx_destructor_count = 0;
1037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 /* Reatime debug enable on feature enable */
1039 if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
Yun Parkb4f591d2017-03-29 15:51:01 -07001040 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
1041 "IPA RT debug is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042 return;
1043 }
Yun Parkdfc1da52016-11-15 14:50:11 -08001044
1045 qdf_mc_timer_init(&hdd_ipa->rt_debug_fill_timer, QDF_TIMER_TYPE_SW,
1046 hdd_ipa_uc_rt_debug_host_fill, (void *)hdd_ctx);
1047 qdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer,
1048 HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
1049
Anurag Chouhan210db072016-02-22 18:42:15 +05301050 qdf_mc_timer_init(&hdd_ipa->rt_debug_timer, QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 hdd_ipa_uc_rt_debug_handler, (void *)hdd_ctx);
Anurag Chouhan210db072016-02-22 18:42:15 +05301052 qdf_mc_timer_start(&hdd_ipa->rt_debug_timer,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001053 HDD_IPA_UC_RT_DEBUG_PERIOD);
1054
1055}
1056
1057/**
Yun Parkb187d542016-11-14 18:10:04 -08001058 * hdd_ipa_dump_hdd_ipa() - dump entries in HDD IPA struct
1059 * @hdd_ipa: HDD IPA struct
1060 *
1061 * Dump entries in struct hdd_ipa
1062 *
1063 * Return: none
1064 */
1065static void hdd_ipa_dump_hdd_ipa(struct hdd_ipa_priv *hdd_ipa)
1066{
1067 int i;
1068
1069 /* HDD IPA */
Yun Park46255682017-10-09 15:56:34 -07001070 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1071 "\n==== HDD IPA ====\n"
Yun Parkb187d542016-11-14 18:10:04 -08001072 "num_iface: %d\n"
1073 "rm_state: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001074 "rm_lock: %pK\n"
1075 "uc_rm_work: %pK\n"
1076 "uc_op_work: %pK\n"
1077 "wake_lock: %pK\n"
1078 "wake_lock_work: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001079 "wake_lock_released: %d\n"
Yun Parkb187d542016-11-14 18:10:04 -08001080 "tx_ref_cnt: %d\n"
1081 "pm_queue_head----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001082 "\thead: %pK\n"
1083 "\ttail: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001084 "\tqlen: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001085 "pm_work: %pK\n"
1086 "pm_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001087 "suspended: %d\n",
1088 hdd_ipa->num_iface,
1089 hdd_ipa->rm_state,
1090 &hdd_ipa->rm_lock,
1091 &hdd_ipa->uc_rm_work,
1092 &hdd_ipa->uc_op_work,
1093 &hdd_ipa->wake_lock,
1094 &hdd_ipa->wake_lock_work,
1095 hdd_ipa->wake_lock_released,
Yun Parkb187d542016-11-14 18:10:04 -08001096 hdd_ipa->tx_ref_cnt.counter,
1097 hdd_ipa->pm_queue_head.head,
1098 hdd_ipa->pm_queue_head.tail,
1099 hdd_ipa->pm_queue_head.qlen,
1100 &hdd_ipa->pm_work,
1101 &hdd_ipa->pm_lock,
1102 hdd_ipa->suspended);
Yun Park46255682017-10-09 15:56:34 -07001103
1104 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1105 "\nq_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001106 "pend_desc_head----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001107 "\tnext: %pK\n"
1108 "\tprev: %pK\n"
1109 "hdd_ctx: %pK\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001110 "stats: %pK\n"
1111 "ipv4_notifier: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001112 "curr_prod_bw: %d\n"
1113 "curr_cons_bw: %d\n"
1114 "activated_fw_pipe: %d\n"
1115 "sap_num_connected_sta: %d\n"
1116 "sta_connected: %d\n",
Yun Parkb187d542016-11-14 18:10:04 -08001117 &hdd_ipa->q_lock,
Yun Parkb187d542016-11-14 18:10:04 -08001118 hdd_ipa->pend_desc_head.next,
1119 hdd_ipa->pend_desc_head.prev,
1120 hdd_ipa->hdd_ctx,
Yun Parkb187d542016-11-14 18:10:04 -08001121 &hdd_ipa->stats,
1122 &hdd_ipa->ipv4_notifier,
1123 hdd_ipa->curr_prod_bw,
1124 hdd_ipa->curr_cons_bw,
1125 hdd_ipa->activated_fw_pipe,
1126 hdd_ipa->sap_num_connected_sta,
Yun Park46255682017-10-09 15:56:34 -07001127 (unsigned int)hdd_ipa->sta_connected);
1128
1129 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1130 "\ntx_pipe_handle: 0x%x\n"
Yun Parkb187d542016-11-14 18:10:04 -08001131 "rx_pipe_handle: 0x%x\n"
1132 "resource_loading: %d\n"
1133 "resource_unloading: %d\n"
1134 "pending_cons_req: %d\n"
1135 "pending_event----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001136 "\tanchor.next: %pK\n"
1137 "\tanchor.prev: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001138 "\tcount: %d\n"
1139 "\tmax_size: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001140 "event_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001141 "ipa_tx_packets_diff: %d\n"
1142 "ipa_rx_packets_diff: %d\n"
1143 "ipa_p_tx_packets: %d\n"
1144 "ipa_p_rx_packets: %d\n"
1145 "stat_req_reason: %d\n",
1146 hdd_ipa->tx_pipe_handle,
1147 hdd_ipa->rx_pipe_handle,
1148 hdd_ipa->resource_loading,
1149 hdd_ipa->resource_unloading,
1150 hdd_ipa->pending_cons_req,
1151 hdd_ipa->pending_event.anchor.next,
1152 hdd_ipa->pending_event.anchor.prev,
1153 hdd_ipa->pending_event.count,
1154 hdd_ipa->pending_event.max_size,
1155 &hdd_ipa->event_lock,
1156 hdd_ipa->ipa_tx_packets_diff,
1157 hdd_ipa->ipa_rx_packets_diff,
1158 hdd_ipa->ipa_p_tx_packets,
1159 hdd_ipa->ipa_p_rx_packets,
1160 hdd_ipa->stat_req_reason);
1161
Yun Park46255682017-10-09 15:56:34 -07001162 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1163 "\ncons_pipe_in----\n"
1164 "\tsys: %pK\n"
1165 "\tdl.comp_ring_base_pa: 0x%x\n"
1166 "\tdl.comp_ring_size: %d\n"
1167 "\tdl.ce_ring_base_pa: 0x%x\n"
1168 "\tdl.ce_door_bell_pa: 0x%x\n"
1169 "\tdl.ce_ring_size: %d\n"
1170 "\tdl.num_tx_buffers: %d\n"
1171 "prod_pipe_in----\n"
1172 "\tsys: %pK\n"
1173 "\tul.rdy_ring_base_pa: 0x%x\n"
1174 "\tul.rdy_ring_size: %d\n"
1175 "\tul.rdy_ring_rp_pa: 0x%x\n"
1176 "uc_loaded: %d\n"
1177 "wdi_enabled: %d\n"
1178 "rt_debug_fill_timer: %pK\n"
1179 "rt_debug_lock: %pK\n"
1180 "ipa_lock: %pK\n",
1181 &hdd_ipa->cons_pipe_in.sys,
1182 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.comp_ring_base_pa,
1183 hdd_ipa->cons_pipe_in.u.dl.comp_ring_size,
1184 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.ce_ring_base_pa,
1185 (unsigned int)hdd_ipa->cons_pipe_in.u.dl.ce_door_bell_pa,
1186 hdd_ipa->cons_pipe_in.u.dl.ce_ring_size,
1187 hdd_ipa->cons_pipe_in.u.dl.num_tx_buffers,
1188 &hdd_ipa->prod_pipe_in.sys,
1189 (unsigned int)hdd_ipa->prod_pipe_in.u.ul.rdy_ring_base_pa,
1190 hdd_ipa->prod_pipe_in.u.ul.rdy_ring_size,
1191 (unsigned int)hdd_ipa->prod_pipe_in.u.ul.rdy_ring_rp_pa,
1192 hdd_ipa->uc_loaded,
1193 hdd_ipa->wdi_enabled,
1194 &hdd_ipa->rt_debug_fill_timer,
1195 &hdd_ipa->rt_debug_lock,
1196 &hdd_ipa->ipa_lock);
1197
1198 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1199 "\nvdev_to_iface----");
1200 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
1201 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1202 "\n\t[%d]=%d", i, hdd_ipa->vdev_to_iface[i]);
1203 }
1204 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1205 "\nvdev_offload_enabled----");
1206 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
1207 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1208 "\n\t[%d]=%d", i, hdd_ipa->vdev_offload_enabled[i]);
1209 }
1210 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1211 "\nassoc_stas_map ----");
Yun Parkb187d542016-11-14 18:10:04 -08001212 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Yun Park46255682017-10-09 15:56:34 -07001213 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1214 "\n\t[%d]: is_reserved=%d, sta_id=%d", i,
Yun Parkb187d542016-11-14 18:10:04 -08001215 hdd_ipa->assoc_stas_map[i].is_reserved,
1216 hdd_ipa->assoc_stas_map[i].sta_id);
1217 }
1218}
1219
1220/**
1221 * hdd_ipa_dump_sys_pipe() - dump HDD IPA SYS Pipe struct
1222 * @hdd_ipa: HDD IPA struct
1223 *
1224 * Dump entire struct hdd_ipa_sys_pipe
1225 *
1226 * Return: none
1227 */
1228static void hdd_ipa_dump_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
1229{
1230 int i;
1231
1232 /* IPA SYS Pipes */
Yun Park46255682017-10-09 15:56:34 -07001233 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1234 "\n==== IPA SYS Pipes ====\n");
Yun Parkb187d542016-11-14 18:10:04 -08001235
1236 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
1237 struct hdd_ipa_sys_pipe *sys_pipe;
Yun Park6c86a662017-10-05 16:09:15 -07001238 qdf_ipa_sys_connect_params_t *ipa_sys_params;
Yun Parkb187d542016-11-14 18:10:04 -08001239
1240 sys_pipe = &hdd_ipa->sys_pipe[i];
1241 ipa_sys_params = &sys_pipe->ipa_sys_params;
1242
Yun Park46255682017-10-09 15:56:34 -07001243 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1244 "\nsys_pipe[%d]----\n"
Yun Parkb187d542016-11-14 18:10:04 -08001245 "\tconn_hdl: 0x%x\n"
1246 "\tconn_hdl_valid: %d\n"
1247 "\tnat_en: %d\n"
1248 "\thdr_len %d\n"
1249 "\thdr_additional_const_len: %d\n"
1250 "\thdr_ofst_pkt_size_valid: %d\n"
1251 "\thdr_ofst_pkt_size: %d\n"
1252 "\thdr_little_endian: %d\n"
1253 "\tmode: %d\n"
1254 "\tclient: %d\n"
1255 "\tdesc_fifo_sz: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001256 "\tpriv: %pK\n"
1257 "\tnotify: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001258 "\tskip_ep_cfg: %d\n"
1259 "\tkeep_ipa_awake: %d\n",
1260 i,
1261 sys_pipe->conn_hdl,
1262 sys_pipe->conn_hdl_valid,
Yun Park6c86a662017-10-05 16:09:15 -07001263 QDF_IPA_SYS_PARAMS_NAT_EN(ipa_sys_params),
1264 QDF_IPA_SYS_PARAMS_HDR_LEN(ipa_sys_params),
1265 QDF_IPA_SYS_PARAMS_HDR_ADDITIONAL_CONST_LEN(
1266 ipa_sys_params),
1267 QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE_VALID(
1268 ipa_sys_params),
1269 QDF_IPA_SYS_PARAMS_HDR_OFST_PKT_SIZE(ipa_sys_params),
1270 QDF_IPA_SYS_PARAMS_HDR_LITTLE_ENDIAN(ipa_sys_params),
1271 QDF_IPA_SYS_PARAMS_MODE(ipa_sys_params),
1272 QDF_IPA_SYS_PARAMS_CLIENT(ipa_sys_params),
1273 QDF_IPA_SYS_PARAMS_DESC_FIFO_SZ(ipa_sys_params),
1274 QDF_IPA_SYS_PARAMS_PRIV(ipa_sys_params),
1275 QDF_IPA_SYS_PARAMS_NOTIFY(ipa_sys_params),
1276 QDF_IPA_SYS_PARAMS_SKIP_EP_CFG(ipa_sys_params),
1277 QDF_IPA_SYS_PARAMS_KEEP_IPA_AWAKE(ipa_sys_params));
Yun Parkb187d542016-11-14 18:10:04 -08001278 }
1279}
1280
1281/**
1282 * hdd_ipa_dump_iface_context() - dump HDD IPA Interface Context struct
1283 * @hdd_ipa: HDD IPA struct
1284 *
1285 * Dump entire struct hdd_ipa_iface_context
1286 *
1287 * Return: none
1288 */
1289static void hdd_ipa_dump_iface_context(struct hdd_ipa_priv *hdd_ipa)
1290{
1291 int i;
1292
1293 /* IPA Interface Contexts */
Yun Park46255682017-10-09 15:56:34 -07001294 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1295 "\n==== IPA Interface Contexts ====\n");
Yun Parkb187d542016-11-14 18:10:04 -08001296
1297 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
1298 struct hdd_ipa_iface_context *iface_context;
1299
1300 iface_context = &hdd_ipa->iface_context[i];
1301
Yun Park46255682017-10-09 15:56:34 -07001302 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
1303 "\niface_context[%d]----\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001304 "\thdd_ipa: %pK\n"
1305 "\tadapter: %pK\n"
1306 "\ttl_context: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001307 "\tcons_client: %d\n"
1308 "\tprod_client: %d\n"
1309 "\tiface_id: %d\n"
1310 "\tsta_id: %d\n"
Jeff Johnson36e74c42017-09-18 08:15:42 -07001311 "\tinterface_lock: %pK\n"
Yun Parkb187d542016-11-14 18:10:04 -08001312 "\tifa_address: 0x%x\n",
1313 i,
1314 iface_context->hdd_ipa,
1315 iface_context->adapter,
1316 iface_context->tl_context,
1317 iface_context->cons_client,
1318 iface_context->prod_client,
1319 iface_context->iface_id,
1320 iface_context->sta_id,
1321 &iface_context->interface_lock,
1322 iface_context->ifa_address);
1323 }
1324}
1325
1326/**
1327 * hdd_ipa_dump_info() - dump HDD IPA struct
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001328 * @hdd_ctx: hdd main context
Yun Parkb187d542016-11-14 18:10:04 -08001329 *
1330 * Dump entire struct hdd_ipa
1331 *
1332 * Return: none
1333 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001334void hdd_ipa_dump_info(struct hdd_context *hdd_ctx)
Yun Parkb187d542016-11-14 18:10:04 -08001335{
1336 struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1337
1338 hdd_ipa_dump_hdd_ipa(hdd_ipa);
1339 hdd_ipa_dump_sys_pipe(hdd_ipa);
1340 hdd_ipa_dump_iface_context(hdd_ipa);
1341}
1342
1343/**
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001344 * hdd_ipa_set_tx_flow_info() - To set TX flow info if IPA is
1345 * enabled
1346 *
1347 * This routine is called to set TX flow info if IPA is enabled
1348 *
1349 * Return: None
1350 */
1351void hdd_ipa_set_tx_flow_info(void)
1352{
1353 hdd_adapter_list_node_t *adapterNode = NULL, *pNext = NULL;
1354 QDF_STATUS status;
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;
1391 status = hdd_get_front_adapter(hdd_ctx, &adapterNode);
1392 while (NULL != adapterNode && QDF_STATUS_SUCCESS == status) {
Jeff Johnson57eb2732017-10-02 11:40:20 -07001393 adapter = adapterNode->adapter;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001394 switch (adapter->device_mode) {
1395 case QDF_STA_MODE:
Jeff Johnsond377dce2017-10-04 10:32:42 -07001396 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001397 if (eConnectionState_Associated ==
Jeff Johnsond377dce2017-10-04 10:32:42 -07001398 sta_ctx->conn_info.connState) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001399 staChannel =
Jeff Johnsond377dce2017-10-04 10:32:42 -07001400 sta_ctx->conn_info.operationChannel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001401 qdf_copy_macaddr(&staBssid,
Jeff Johnsond377dce2017-10-04 10:32:42 -07001402 &sta_ctx->conn_info.bssId);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001403#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1404 targetChannel = staChannel;
1405#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1406 }
1407 break;
1408 case QDF_P2P_CLIENT_MODE:
Jeff Johnsond377dce2017-10-04 10:32:42 -07001409 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001410 if (eConnectionState_Associated ==
Jeff Johnsond377dce2017-10-04 10:32:42 -07001411 sta_ctx->conn_info.connState) {
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001412 p2pChannel =
Jeff Johnsond377dce2017-10-04 10:32:42 -07001413 sta_ctx->conn_info.operationChannel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001414 qdf_copy_macaddr(&p2pBssid,
Jeff Johnsond377dce2017-10-04 10:32:42 -07001415 &sta_ctx->conn_info.bssId);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001416 p2pMode = "CLI";
1417#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1418 targetChannel = p2pChannel;
1419#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1420 }
1421 break;
1422 case QDF_P2P_GO_MODE:
1423 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1424 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001425 if (hostapd_state->bss_state == BSS_START
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001426 && hostapd_state->qdf_status ==
1427 QDF_STATUS_SUCCESS) {
Jeff Johnson01206862017-10-27 20:55:59 -07001428 p2pChannel = hdd_ap_ctx->operating_channel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001429 qdf_copy_macaddr(&p2pBssid,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001430 &adapter->mac_addr);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001431#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1432 targetChannel = p2pChannel;
1433#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1434 }
1435 p2pMode = "GO";
1436 break;
1437 case QDF_SAP_MODE:
1438 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
1439 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Jeff Johnson0f9f87b2017-10-28 09:21:06 -07001440 if (hostapd_state->bss_state == BSS_START
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001441 && hostapd_state->qdf_status ==
1442 QDF_STATUS_SUCCESS) {
Jeff Johnson01206862017-10-27 20:55:59 -07001443 apChannel = hdd_ap_ctx->operating_channel;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001444 qdf_copy_macaddr(&apBssid,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001445 &adapter->mac_addr);
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001446#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1447 targetChannel = apChannel;
1448#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1449 }
1450 break;
1451 case QDF_IBSS_MODE:
1452 default:
1453 break;
1454 }
1455#ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
1456 if (targetChannel) {
1457 /*
1458 * This is first adapter detected as active
1459 * set as default for none concurrency case
1460 */
1461 if (!preAdapterChannel) {
1462 /* If IPA UC data path is enabled,
1463 * target should reserve extra tx descriptors
1464 * for IPA data path.
1465 * Then host data path should allow less TX
1466 * packet pumping in case IPA
1467 * data path enabled
1468 */
1469 if (hdd_ipa_uc_is_enabled(hdd_ctx) &&
1470 (QDF_SAP_MODE == adapter->device_mode)) {
1471 adapter->tx_flow_low_watermark =
1472 hdd_ctx->config->TxFlowLowWaterMark +
1473 WLAN_TFC_IPAUC_TX_DESC_RESERVE;
1474 } else {
1475 adapter->tx_flow_low_watermark =
1476 hdd_ctx->config->
1477 TxFlowLowWaterMark;
1478 }
1479 adapter->tx_flow_high_watermark_offset =
1480 hdd_ctx->config->TxFlowHighWaterMarkOffset;
1481 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001482 adapter->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001483 hdd_ctx->config->TxFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001484 hdd_info("MODE %d,CH %d,LWM %d,HWM %d,TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001485 adapter->device_mode,
1486 targetChannel,
1487 adapter->tx_flow_low_watermark,
1488 adapter->tx_flow_low_watermark +
1489 adapter->tx_flow_high_watermark_offset,
1490 hdd_ctx->config->TxFlowMaxQueueDepth);
1491 preAdapterChannel = targetChannel;
1492 preAdapterContext = adapter;
1493 } else {
1494 /*
1495 * SCC, disable TX flow control for both
1496 * SCC each adapter cannot reserve dedicated
1497 * channel resource, as a result, if any adapter
1498 * blocked OS Q by flow control,
1499 * blocked adapter will lost chance to recover
1500 */
1501 if (preAdapterChannel == targetChannel) {
1502 /* Current adapter */
1503 adapter->tx_flow_low_watermark = 0;
1504 adapter->
1505 tx_flow_high_watermark_offset = 0;
1506 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001507 adapter->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001508 hdd_ctx->config->
1509 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001510 hdd_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001511 hdd_device_mode_to_string(
1512 adapter->device_mode),
1513 adapter->device_mode,
1514 targetChannel,
1515 adapter->tx_flow_low_watermark,
1516 adapter->tx_flow_low_watermark +
1517 adapter->
1518 tx_flow_high_watermark_offset,
1519 hdd_ctx->config->
1520 TxHbwFlowMaxQueueDepth);
1521
1522 if (!preAdapterContext) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001523 hdd_err("SCC: Previous adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001524 continue;
1525 }
1526
1527 /* Previous adapter */
1528 preAdapterContext->
1529 tx_flow_low_watermark = 0;
1530 preAdapterContext->
1531 tx_flow_high_watermark_offset = 0;
1532 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001533 preAdapterContext->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001534 hdd_ctx->config->
1535 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001536 hdd_info("SCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001537 hdd_device_mode_to_string(
1538 preAdapterContext->device_mode
1539 ),
1540 preAdapterContext->device_mode,
1541 targetChannel,
1542 preAdapterContext->
1543 tx_flow_low_watermark,
1544 preAdapterContext->
1545 tx_flow_low_watermark +
1546 preAdapterContext->
1547 tx_flow_high_watermark_offset,
1548 hdd_ctx->config->
1549 TxHbwFlowMaxQueueDepth);
1550 }
1551 /*
1552 * MCC, each adapter will have dedicated
1553 * resource
1554 */
1555 else {
1556 /* current channel is 2.4 */
1557 if (targetChannel <=
1558 WLAN_HDD_TX_FLOW_CONTROL_MAX_24BAND_CH) {
1559 channel24 = targetChannel;
1560 channel5 = preAdapterChannel;
1561 adapter2_4 = adapter;
1562 adapter5 = preAdapterContext;
1563 } else {
1564 /* Current channel is 5 */
1565 channel24 = preAdapterChannel;
1566 channel5 = targetChannel;
1567 adapter2_4 = preAdapterContext;
1568 adapter5 = adapter;
1569 }
1570
1571 if (!adapter5) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001572 hdd_err("MCC: 5GHz adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001573 continue;
1574 }
1575 adapter5->tx_flow_low_watermark =
1576 hdd_ctx->config->
1577 TxHbwFlowLowWaterMark;
1578 adapter5->
1579 tx_flow_high_watermark_offset =
1580 hdd_ctx->config->
1581 TxHbwFlowHighWaterMarkOffset;
1582 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001583 adapter5->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001584 hdd_ctx->config->
1585 TxHbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001586 hdd_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001587 hdd_device_mode_to_string(
1588 adapter5->device_mode),
1589 adapter5->device_mode,
1590 channel5,
1591 adapter5->tx_flow_low_watermark,
1592 adapter5->
1593 tx_flow_low_watermark +
1594 adapter5->
1595 tx_flow_high_watermark_offset,
1596 hdd_ctx->config->
1597 TxHbwFlowMaxQueueDepth);
1598
1599 if (!adapter2_4) {
Jeff Johnson6867ec32017-09-29 20:30:20 -07001600 hdd_err("MCC: 2.4GHz adapter context NULL");
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001601 continue;
1602 }
1603 adapter2_4->tx_flow_low_watermark =
1604 hdd_ctx->config->
1605 TxLbwFlowLowWaterMark;
1606 adapter2_4->
1607 tx_flow_high_watermark_offset =
1608 hdd_ctx->config->
1609 TxLbwFlowHighWaterMarkOffset;
1610 cdp_fc_ll_set_tx_pause_q_depth(soc,
Jeff Johnson1b780e42017-10-31 14:11:45 -07001611 adapter2_4->session_id,
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001612 hdd_ctx->config->
1613 TxLbwFlowMaxQueueDepth);
Jeff Johnson6867ec32017-09-29 20:30:20 -07001614 hdd_info("MCC: MODE %s(%d), CH %d, LWM %d, HWM %d, TXQDEP %d",
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08001615 hdd_device_mode_to_string(
1616 adapter2_4->device_mode),
1617 adapter2_4->device_mode,
1618 channel24,
1619 adapter2_4->
1620 tx_flow_low_watermark,
1621 adapter2_4->
1622 tx_flow_low_watermark +
1623 adapter2_4->
1624 tx_flow_high_watermark_offset,
1625 hdd_ctx->config->
1626 TxLbwFlowMaxQueueDepth);
1627
1628 }
1629 }
1630 }
1631 targetChannel = 0;
1632#endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
1633 status = hdd_get_next_adapter(hdd_ctx, adapterNode, &pNext);
1634 adapterNode = pNext;
1635 }
1636 hdd_ctx->mcc_mode = policy_mgr_current_concurrency_is_mcc(psoc);
1637}
1638
1639/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001640 * __hdd_ipa_uc_stat_query() - Query the IPA stats
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001641 * @hdd_ctx: Global HDD context
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001642 * @ipa_tx_diff: tx packet count diff from previous tx packet count
1643 * @ipa_rx_diff: rx packet count diff from previous rx packet count
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644 *
1645 * Return: true if IPA is enabled, false otherwise
1646 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001647static void __hdd_ipa_uc_stat_query(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff)
1649{
1650 struct hdd_ipa_priv *hdd_ipa;
1651
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652 *ipa_tx_diff = 0;
1653 *ipa_rx_diff = 0;
1654
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001655 if (wlan_hdd_validate_context(hdd_ctx))
1656 return;
1657
1658 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1659
1660 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1661 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 return;
1663 }
1664
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301665 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
1667 (false == hdd_ipa->resource_loading)) {
1668 *ipa_tx_diff = hdd_ipa->ipa_tx_packets_diff;
1669 *ipa_rx_diff = hdd_ipa->ipa_rx_packets_diff;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301671 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001672}
1673
1674/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001675 * hdd_ipa_uc_stat_query() - SSR wrapper for __hdd_ipa_uc_stat_query
1676 * @hdd_ctx: Global HDD context
1677 * @ipa_tx_diff: tx packet count diff from previous tx packet count
1678 * @ipa_rx_diff: rx packet count diff from previous rx packet count
1679 *
1680 * Return: true if IPA is enabled, false otherwise
1681 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001682void hdd_ipa_uc_stat_query(struct hdd_context *hdd_ctx,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001683 uint32_t *ipa_tx_diff, uint32_t *ipa_rx_diff)
1684{
1685 cds_ssr_protect(__func__);
1686 __hdd_ipa_uc_stat_query(hdd_ctx, ipa_tx_diff, ipa_rx_diff);
1687 cds_ssr_unprotect(__func__);
1688}
1689
1690/**
1691 * __hdd_ipa_uc_stat_request() - Get IPA stats from IPA.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001692 * @adapter: network adapter
1693 * @reason: STAT REQ Reason
1694 *
1695 * Return: None
1696 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07001697static void __hdd_ipa_uc_stat_request(struct hdd_adapter *adapter,
1698 uint8_t reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001699{
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001700 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001701 struct hdd_ipa_priv *hdd_ipa;
1702
Yun Park637d6482016-10-05 10:51:33 -07001703 if (!adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705
Jeff Johnson399c6272017-08-30 10:51:00 -07001706 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001707
1708 if (wlan_hdd_validate_context(hdd_ctx))
1709 return;
1710
1711 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
1712 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1713 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 return;
1715 }
1716
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301717 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 if ((HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
1719 (false == hdd_ipa->resource_loading)) {
1720 hdd_ipa->stat_req_reason = reason;
Yun Park637d6482016-10-05 10:51:33 -07001721 qdf_mutex_release(&hdd_ipa->ipa_lock);
Sandeep Puligillaf587adf2017-04-27 19:53:21 -07001722 sme_ipa_uc_stat_request(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -07001723 adapter->session_id,
Sandeep Puligillaf587adf2017-04-27 19:53:21 -07001724 WMA_VDEV_TXRX_GET_IPA_UC_FW_STATS_CMDID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 0, VDEV_CMD);
Yun Park637d6482016-10-05 10:51:33 -07001726 } else {
1727 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001729}
1730
1731/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001732 * hdd_ipa_uc_stat_request() - SSR wrapper for __hdd_ipa_uc_stat_request
1733 * @adapter: network adapter
1734 * @reason: STAT REQ Reason
1735 *
1736 * Return: None
1737 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001738void hdd_ipa_uc_stat_request(struct hdd_adapter *adapter, uint8_t reason)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001739{
1740 cds_ssr_protect(__func__);
1741 __hdd_ipa_uc_stat_request(adapter, reason);
1742 cds_ssr_unprotect(__func__);
1743}
1744
Yun Park637d6482016-10-05 10:51:33 -07001745#ifdef FEATURE_METERING
1746/**
1747 * hdd_ipa_uc_sharing_stats_request() - Get IPA stats from IPA.
1748 * @adapter: network adapter
1749 * @reset_stats: reset stat countis after response
1750 *
1751 * Return: None
1752 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001753void hdd_ipa_uc_sharing_stats_request(struct hdd_adapter *adapter,
Yun Park637d6482016-10-05 10:51:33 -07001754 uint8_t reset_stats)
1755{
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001756 struct hdd_context *hdd_ctx;
Yun Park637d6482016-10-05 10:51:33 -07001757 struct hdd_ipa_priv *hdd_ipa;
1758
1759 if (!adapter)
1760 return;
1761
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001762 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1763 hdd_ipa = hdd_ctx->hdd_ipa;
1764 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1765 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Yun Park637d6482016-10-05 10:51:33 -07001766 return;
1767 }
1768
1769 HDD_IPA_LOG(LOG1, "SHARING_STATS: reset_stats=%d", reset_stats);
1770 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Park3374a4b2016-12-15 16:52:15 -08001771 if (false == hdd_ipa->resource_loading) {
Yun Park637d6482016-10-05 10:51:33 -07001772 qdf_mutex_release(&hdd_ipa->ipa_lock);
1773 wma_cli_set_command(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001774 (int)adapter->session_id,
Yun Park637d6482016-10-05 10:51:33 -07001775 (int)WMA_VDEV_TXRX_GET_IPA_UC_SHARING_STATS_CMDID,
1776 reset_stats, VDEV_CMD);
1777 } else {
1778 qdf_mutex_release(&hdd_ipa->ipa_lock);
1779 }
1780}
1781
1782/**
1783 * hdd_ipa_uc_set_quota() - Set quota limit bytes from IPA.
1784 * @adapter: network adapter
1785 * @set_quota: when 1, FW starts quota monitoring
1786 * @quota_bytes: quota limit in bytes
1787 *
1788 * Return: None
1789 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07001790void hdd_ipa_uc_set_quota(struct hdd_adapter *adapter, uint8_t set_quota,
Yun Park637d6482016-10-05 10:51:33 -07001791 uint64_t quota_bytes)
1792{
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001793 struct hdd_context *hdd_ctx;
Yun Park637d6482016-10-05 10:51:33 -07001794 struct hdd_ipa_priv *hdd_ipa;
1795
1796 if (!adapter)
1797 return;
1798
Jeff Johnson2c4a93f2017-09-03 08:51:14 -07001799 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1800 hdd_ipa = hdd_ctx->hdd_ipa;
1801 if (!hdd_ipa_is_enabled(hdd_ctx) ||
1802 !(hdd_ipa_uc_is_enabled(hdd_ctx))) {
Yun Park637d6482016-10-05 10:51:33 -07001803 return;
1804 }
1805
1806 HDD_IPA_LOG(LOG1, "SET_QUOTA: set_quota=%d, quota_bytes=%llu",
1807 set_quota, quota_bytes);
1808
1809 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Park3374a4b2016-12-15 16:52:15 -08001810 if (false == hdd_ipa->resource_loading) {
Yun Park637d6482016-10-05 10:51:33 -07001811 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park327e7812017-02-14 15:18:10 -08001812 wma_cli_set2_command(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001813 (int)adapter->session_id,
Yun Park637d6482016-10-05 10:51:33 -07001814 (int)WMA_VDEV_TXRX_SET_IPA_UC_QUOTA_CMDID,
Yun Park327e7812017-02-14 15:18:10 -08001815 (set_quota ? quota_bytes&0xffffffff : 0),
1816 (set_quota ? quota_bytes>>32 : 0),
1817 VDEV_CMD);
Yun Park637d6482016-10-05 10:51:33 -07001818 } else {
1819 qdf_mutex_release(&hdd_ipa->ipa_lock);
1820 }
1821}
1822#endif
1823
Prakash Dhavali412cdb02016-10-20 21:19:31 -07001824/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 * hdd_ipa_uc_find_add_assoc_sta() - Find associated station
1826 * @hdd_ipa: Global HDD IPA context
1827 * @sta_add: Should station be added
1828 * @sta_id: ID of the station being queried
1829 *
1830 * Return: true if the station was found
1831 */
1832static bool hdd_ipa_uc_find_add_assoc_sta(struct hdd_ipa_priv *hdd_ipa,
1833 bool sta_add, uint8_t sta_id)
1834{
1835 bool sta_found = false;
1836 uint8_t idx;
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07001837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001838 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1839 if ((hdd_ipa->assoc_stas_map[idx].is_reserved) &&
1840 (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) {
1841 sta_found = true;
1842 break;
1843 }
1844 }
1845 if (sta_add && sta_found) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301846 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001847 "STA ID %d already exist, cannot add", sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001848 return sta_found;
1849 }
1850 if (sta_add) {
1851 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1852 if (!hdd_ipa->assoc_stas_map[idx].is_reserved) {
1853 hdd_ipa->assoc_stas_map[idx].is_reserved = true;
1854 hdd_ipa->assoc_stas_map[idx].sta_id = sta_id;
1855 return sta_found;
1856 }
1857 }
1858 }
1859 if (!sta_add && !sta_found) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301860 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001861 "STA ID %d does not exist, cannot delete", sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 return sta_found;
1863 }
1864 if (!sta_add) {
1865 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
1866 if ((hdd_ipa->assoc_stas_map[idx].is_reserved) &&
1867 (hdd_ipa->assoc_stas_map[idx].sta_id == sta_id)) {
1868 hdd_ipa->assoc_stas_map[idx].is_reserved =
1869 false;
1870 hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF;
1871 return sta_found;
1872 }
1873 }
1874 }
1875 return sta_found;
1876}
1877
1878/**
1879 * hdd_ipa_uc_enable_pipes() - Enable IPA uC pipes
1880 * @hdd_ipa: Global HDD IPA context
1881 *
1882 * Return: 0 on success, negative errno if error
1883 */
1884static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa)
1885{
Yun Parkfec73dc2017-09-06 10:40:07 -07001886 int result = 0;
Leo Changfdb45c32016-10-28 11:09:23 -07001887 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkb4f591d2017-03-29 15:51:01 -07001888 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889
Yun Park199c2ed2017-10-02 11:24:22 -07001890 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
1891
1892 if (!hdd_ipa->ipa_pipes_down) {
1893 /*
1894 * This shouldn't happen :
1895 * IPA WDI Pipes are already activated
1896 */
1897 WARN_ON(1);
1898 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
1899 "IPA WDI Pipes are already activated");
1900 goto end;
1901 }
Yun Parkfec73dc2017-09-06 10:40:07 -07001902
Yun Parkb4f591d2017-03-29 15:51:01 -07001903 result = cdp_ipa_enable_pipes(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 if (result) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301905 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001906 "Enable PIPE fail, code %d", result);
Yun Parkfec73dc2017-09-06 10:40:07 -07001907 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909
Yun Park777d7242017-03-30 15:38:33 -07001910 INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
Leo Change3e49442015-10-26 20:07:13 -07001911 hdd_ipa->ipa_pipes_down = false;
Yun Parkb4f591d2017-03-29 15:51:01 -07001912
1913 cdp_ipa_enable_autonomy(soc, (struct cdp_pdev *)pdev);
1914
Yun Parkfec73dc2017-09-06 10:40:07 -07001915end:
Yun Park199c2ed2017-10-02 11:24:22 -07001916 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: ipa_pipes_down=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07001917 hdd_ipa->ipa_pipes_down);
Yun Park199c2ed2017-10-02 11:24:22 -07001918
Yun Parkfec73dc2017-09-06 10:40:07 -07001919 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920}
1921
1922/**
1923 * hdd_ipa_uc_disable_pipes() - Disable IPA uC pipes
1924 * @hdd_ipa: Global HDD IPA context
1925 *
1926 * Return: 0 on success, negative errno if error
1927 */
1928static int hdd_ipa_uc_disable_pipes(struct hdd_ipa_priv *hdd_ipa)
1929{
Yun Parkb4f591d2017-03-29 15:51:01 -07001930 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1931 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Parkfec73dc2017-09-06 10:40:07 -07001932 int result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
Yun Park199c2ed2017-10-02 11:24:22 -07001934 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
1935
1936 if (hdd_ipa->ipa_pipes_down) {
1937 /*
1938 * This shouldn't happen :
1939 * IPA WDI Pipes are already deactivated
1940 */
1941 WARN_ON(1);
1942 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
1943 "IPA WDI Pipes are already deactivated");
1944 goto end;
1945 }
Leo Change3e49442015-10-26 20:07:13 -07001946
Yun Parkb4f591d2017-03-29 15:51:01 -07001947 cdp_ipa_disable_autonomy(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001948
Yun Parkb4f591d2017-03-29 15:51:01 -07001949 result = cdp_ipa_disable_pipes(soc, (struct cdp_pdev *)pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950 if (result) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301951 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001952 "Disable WDI PIPE fail, code %d", result);
Yun Parkfec73dc2017-09-06 10:40:07 -07001953 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 }
1955
Yun Parkfec73dc2017-09-06 10:40:07 -07001956 hdd_ipa->ipa_pipes_down = true;
1957
1958end:
Yun Park199c2ed2017-10-02 11:24:22 -07001959 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: ipa_pipes_down=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07001960 hdd_ipa->ipa_pipes_down);
1961 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962}
1963
1964/**
1965 * hdd_ipa_uc_handle_first_con() - Handle first uC IPA connection
1966 * @hdd_ipa: Global HDD IPA context
1967 *
1968 * Return: 0 on success, negative errno if error
1969 */
1970static int hdd_ipa_uc_handle_first_con(struct hdd_ipa_priv *hdd_ipa)
1971{
Jeff Johnsondd595cb2017-08-28 11:58:09 -07001972 struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
Yun Parkb4f591d2017-03-29 15:51:01 -07001973
Yun Park199c2ed2017-10-02 11:24:22 -07001974 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07001975
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 hdd_ipa->activated_fw_pipe = 0;
1977 hdd_ipa->resource_loading = true;
Yun Park4cab6ee2015-10-27 11:43:40 -07001978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 /* If RM feature enabled
1980 * Request PROD Resource first
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001981 * PROD resource may return sync or async manners
1982 */
Yun Parkb4f591d2017-03-29 15:51:01 -07001983 if (hdd_ipa_is_rm_enabled(hdd_ctx)) {
Yun Park4cab6ee2015-10-27 11:43:40 -07001984 if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
1985 /* RM PROD request sync return
1986 * enable pipe immediately
1987 */
1988 if (hdd_ipa_uc_enable_pipes(hdd_ipa)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301989 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07001990 "IPA WDI Pipe activation failed");
Yun Park4cab6ee2015-10-27 11:43:40 -07001991 hdd_ipa->resource_loading = false;
1992 return -EBUSY;
1993 }
Sravan Kumar Kairamc76f28a2017-07-25 19:03:40 +05301994 } else {
1995 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park199c2ed2017-10-02 11:24:22 -07001996 "IPA WDI Pipe activation deferred");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 }
1998 } else {
1999 /* RM Disabled
Yun Park4cab6ee2015-10-27 11:43:40 -07002000 * Just enabled all the PIPEs
2001 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 if (hdd_ipa_uc_enable_pipes(hdd_ipa)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302003 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07002004 "IPA WDI Pipe activation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 hdd_ipa->resource_loading = false;
2006 return -EBUSY;
2007 }
2008 hdd_ipa->resource_loading = false;
2009 }
Yun Park4cab6ee2015-10-27 11:43:40 -07002010
Yun Park199c2ed2017-10-02 11:24:22 -07002011 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 return 0;
2013}
2014
2015/**
2016 * hdd_ipa_uc_handle_last_discon() - Handle last uC IPA disconnection
2017 * @hdd_ipa: Global HDD IPA context
2018 *
2019 * Return: None
2020 */
2021static void hdd_ipa_uc_handle_last_discon(struct hdd_ipa_priv *hdd_ipa)
2022{
Leo Changfdb45c32016-10-28 11:09:23 -07002023 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkb4f591d2017-03-29 15:51:01 -07002024 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025
Yun Park199c2ed2017-10-02 11:24:22 -07002026 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07002027
Yun Parkb4f591d2017-03-29 15:51:01 -07002028 if (!pdev) {
Yun Park7c4f31b2016-11-30 10:09:21 -08002029 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "txrx context is NULL");
2030 QDF_ASSERT(0);
2031 return;
2032 }
2033
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 hdd_ipa->resource_unloading = true;
Yun Park777d7242017-03-30 15:38:33 -07002035 INIT_COMPLETION(hdd_ipa->ipa_resource_comp);
Yun Parkb4f591d2017-03-29 15:51:01 -07002036 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable FW RX PIPE");
2037 cdp_ipa_set_active(soc, (struct cdp_pdev *)pdev, false, false);
2038 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Disable FW TX PIPE");
2039 cdp_ipa_set_active(soc, (struct cdp_pdev *)pdev, false, true);
Yun Parkfec73dc2017-09-06 10:40:07 -07002040
Yun Park199c2ed2017-10-02 11:24:22 -07002041 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: IPA WDI Pipes deactivated");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042}
2043
2044/**
2045 * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
2046 * @context: User context registered with TL (the IPA Global context is
2047 * registered
2048 * @rxpkt: Packet containing the notification
2049 * @staid: ID of the station associated with the packet
2050 *
2051 * Return: None
2052 */
2053static void
Yun Park6c86a662017-10-05 16:09:15 -07002054hdd_ipa_uc_rm_notify_handler(void *context, qdf_ipa_rm_event_t event)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055{
2056 struct hdd_ipa_priv *hdd_ipa = context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302057 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002058 struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002059
2060 /*
2061 * When SSR is going on or driver is unloading, just return.
2062 */
Yun Parkb4f591d2017-03-29 15:51:01 -07002063 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302064 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066
Yun Parkb4f591d2017-03-29 15:51:01 -07002067 if (!hdd_ipa_is_rm_enabled(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068 return;
2069
Yun Park46255682017-10-09 15:56:34 -07002070 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d",
2071 event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072
2073 switch (event) {
2074 case IPA_RM_RESOURCE_GRANTED:
2075 /* Differed RM Granted */
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302076 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 if ((false == hdd_ipa->resource_unloading) &&
2078 (!hdd_ipa->activated_fw_pipe)) {
2079 hdd_ipa_uc_enable_pipes(hdd_ipa);
2080 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302081 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 break;
2083
2084 case IPA_RM_RESOURCE_RELEASED:
2085 /* Differed RM Released */
2086 hdd_ipa->resource_unloading = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 break;
2088
2089 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302090 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002091 "invalid event code %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002092 break;
2093 }
2094}
2095
2096/**
2097 * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
2098 * @hdd_ipa: Global HDD IPA context
2099 * @event: IPA resource manager event to be deferred
2100 *
2101 * This function is called when a resource manager event is received
2102 * from firmware in interrupt context. This function will defer the
2103 * handling to the OL RX thread
2104 *
2105 * Return: None
2106 */
2107static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
2108{
Yun Park6c86a662017-10-05 16:09:15 -07002109 qdf_ipa_rm_event_t event;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002110 struct uc_rm_work_struct *uc_rm_work = container_of(work,
2111 struct uc_rm_work_struct, work);
2112 struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
2113 struct hdd_ipa_priv, uc_rm_work);
2114
2115 cds_ssr_protect(__func__);
2116 event = uc_rm_work->event;
Srinivas Girigowda97852372017-03-06 16:52:59 -08002117 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07002118 "posted event %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119
2120 hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
2121 cds_ssr_unprotect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122}
2123
2124/**
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002125 * hdd_ipa_uc_loaded_handler() - Process IPA uC loaded indication
Yun Parkb4f591d2017-03-29 15:51:01 -07002126 * @hdd_ipa: hdd ipa local context
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002127 *
2128 * Will handle IPA UC image loaded indication comes from IPA kernel
2129 *
2130 * Return: None
2131 */
Yun Parkb4f591d2017-03-29 15:51:01 -07002132static void hdd_ipa_uc_loaded_handler(struct hdd_ipa_priv *hdd_ipa)
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002133{
Yun Parkb4f591d2017-03-29 15:51:01 -07002134 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2135 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002136 struct hdd_context *hdd_ctx;
Yun Parkb4f591d2017-03-29 15:51:01 -07002137 QDF_STATUS status;
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002138
Yun Park46255682017-10-09 15:56:34 -07002139 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC READY");
Yun Parkb4f591d2017-03-29 15:51:01 -07002140 if (true == hdd_ipa->uc_loaded) {
Yun Park46255682017-10-09 15:56:34 -07002141 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "UC already loaded");
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002142 return;
2143 }
2144
Yun Parkb4f591d2017-03-29 15:51:01 -07002145 hdd_ctx = hdd_ipa->hdd_ctx;
2146 hdd_ipa->uc_loaded = true;
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002147
Yun Parkb4f591d2017-03-29 15:51:01 -07002148 /* Connect pipe */
2149 status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
2150 hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
2151 hdd_ipa_wdi_meter_notifier_cb,
2152 hdd_ctx->config->IpaDescSize,
2153 hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
2154 &hdd_ipa->tx_pipe_handle,
2155 &hdd_ipa->rx_pipe_handle);
2156 if (status) {
2157 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2158 "Failure to setup IPA pipes (status=%d)",
2159 status);
2160 return;
2161 }
2162
2163 cdp_ipa_set_doorbell_paddr(soc, (struct cdp_pdev *)pdev);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002164
2165 /* If already any STA connected, enable IPA/FW PIPEs */
Yun Parkb4f591d2017-03-29 15:51:01 -07002166 if (hdd_ipa->sap_num_connected_sta) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08002167 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002168 "Client already connected, enable IPA/FW PIPEs");
Yun Parkb4f591d2017-03-29 15:51:01 -07002169 hdd_ipa_uc_handle_first_con(hdd_ipa);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002170 }
2171}
2172
2173/**
Yun Park637d6482016-10-05 10:51:33 -07002174 * hdd_ipa_uc_op_metering() - IPA uC operation for stats and quota limit
2175 * @hdd_ctx: Global HDD context
2176 * @op_msg: operation message received from firmware
2177 *
2178 * Return: QDF_STATUS enumeration
2179 */
2180#ifdef FEATURE_METERING
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002181static QDF_STATUS hdd_ipa_uc_op_metering(struct hdd_context *hdd_ctx,
Yun Park637d6482016-10-05 10:51:33 -07002182 struct op_msg_type *op_msg)
2183{
2184 struct op_msg_type *msg = op_msg;
2185 struct ipa_uc_sharing_stats *uc_sharing_stats;
2186 struct ipa_uc_quota_rsp *uc_quota_rsp;
2187 struct ipa_uc_quota_ind *uc_quota_ind;
2188 struct hdd_ipa_priv *hdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07002189 struct hdd_adapter *adapter;
Yun Park637d6482016-10-05 10:51:33 -07002190
2191 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
2192
2193 if (HDD_IPA_UC_OPCODE_SHARING_STATS == msg->op_code) {
2194 /* fill-up ipa_uc_sharing_stats structure from FW */
2195 uc_sharing_stats = (struct ipa_uc_sharing_stats *)
2196 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2197
2198 memcpy(&(hdd_ipa->ipa_sharing_stats), uc_sharing_stats,
2199 sizeof(struct ipa_uc_sharing_stats));
2200
2201 complete(&hdd_ipa->ipa_uc_sharing_stats_comp);
2202
2203 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2204 "%s: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
2205 "HDD_IPA_UC_OPCODE_SHARING_STATS",
2206 hdd_ipa->ipa_sharing_stats.ipv4_rx_packets,
2207 hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes,
2208 hdd_ipa->ipa_sharing_stats.ipv6_rx_packets,
2209 hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes,
2210 hdd_ipa->ipa_sharing_stats.ipv4_tx_packets,
2211 hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes,
2212 hdd_ipa->ipa_sharing_stats.ipv6_tx_packets,
2213 hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes);
2214 } else if (HDD_IPA_UC_OPCODE_QUOTA_RSP == msg->op_code) {
2215 /* received set quota response */
2216 uc_quota_rsp = (struct ipa_uc_quota_rsp *)
2217 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2218
2219 memcpy(&(hdd_ipa->ipa_quota_rsp), uc_quota_rsp,
2220 sizeof(struct ipa_uc_quota_rsp));
2221
2222 complete(&hdd_ipa->ipa_uc_set_quota_comp);
2223 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2224 "%s: success=%d, quota_bytes=%llu",
2225 "HDD_IPA_UC_OPCODE_QUOTA_RSP",
2226 hdd_ipa->ipa_quota_rsp.success,
2227 ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)<<32)|
2228 hdd_ipa->ipa_quota_rsp.quota_lo);
2229 } else if (HDD_IPA_UC_OPCODE_QUOTA_IND == msg->op_code) {
2230 /* hit quota limit */
2231 uc_quota_ind = (struct ipa_uc_quota_ind *)
2232 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
2233
2234 hdd_ipa->ipa_quota_ind.quota_bytes =
2235 uc_quota_ind->quota_bytes;
2236
2237 /* send quota exceeded indication to IPA */
2238 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
2239 "OPCODE_QUOTA_IND: quota exceed! (quota_bytes=%llu)",
2240 hdd_ipa->ipa_quota_ind.quota_bytes);
2241
2242 adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
2243 if (adapter)
2244 ipa_broadcast_wdi_quota_reach_ind(
2245 adapter->dev->ifindex,
2246 uc_quota_ind->quota_bytes);
2247 else
2248 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2249 "Failed quota_reach_ind: NULL adapter");
2250 } else {
2251 return QDF_STATUS_E_INVAL;
2252 }
2253
2254 return QDF_STATUS_SUCCESS;
2255}
2256#else
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002257static QDF_STATUS hdd_ipa_uc_op_metering(struct hdd_context *hdd_ctx,
Yun Park637d6482016-10-05 10:51:33 -07002258 struct op_msg_type *op_msg)
2259{
2260 return QDF_STATUS_E_INVAL;
2261}
2262#endif
2263
Yun Park657c7d72017-06-07 15:44:59 -07002264#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
2265/* older versions had a typo */
2266#define num_bam_int_in_non_running_state num_bam_int_in_non_runnning_state
2267#endif
2268
Yun Park637d6482016-10-05 10:51:33 -07002269/**
Yun Park46255682017-10-09 15:56:34 -07002270 * hdd_ipa_wlan_event_to_str() - convert IPA WLAN event to string
2271 * @event: IPA WLAN event to be converted to a string
2272 *
2273 * Return: ASCII string representing the IPA WLAN event
2274 */
Yun Park6c86a662017-10-05 16:09:15 -07002275static inline char *hdd_ipa_wlan_event_to_str(qdf_ipa_wlan_event_t event)
Yun Park46255682017-10-09 15:56:34 -07002276{
2277 switch (event) {
2278 CASE_RETURN_STRING(WLAN_CLIENT_CONNECT);
2279 CASE_RETURN_STRING(WLAN_CLIENT_DISCONNECT);
2280 CASE_RETURN_STRING(WLAN_CLIENT_POWER_SAVE_MODE);
2281 CASE_RETURN_STRING(WLAN_CLIENT_NORMAL_MODE);
2282 CASE_RETURN_STRING(SW_ROUTING_ENABLE);
2283 CASE_RETURN_STRING(SW_ROUTING_DISABLE);
2284 CASE_RETURN_STRING(WLAN_AP_CONNECT);
2285 CASE_RETURN_STRING(WLAN_AP_DISCONNECT);
2286 CASE_RETURN_STRING(WLAN_STA_CONNECT);
2287 CASE_RETURN_STRING(WLAN_STA_DISCONNECT);
2288 CASE_RETURN_STRING(WLAN_CLIENT_CONNECT_EX);
2289 default:
2290 return "UNKNOWN";
2291 }
2292}
2293
2294/**
2295 * hdd_ipa_print_session_info - Print IPA session info
2296 * @hdd_ipa: HDD IPA local context
2297 *
2298 * Return: None
2299 */
2300static void hdd_ipa_print_session_info(struct hdd_ipa_priv *hdd_ipa)
2301{
2302 uint8_t session_id;
2303 int device_mode;
2304 struct ipa_uc_pending_event *event = NULL, *next = NULL;
2305 struct hdd_ipa_iface_context *iface_context = NULL;
2306 int i;
2307
2308 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2309 "\n==== IPA SESSION INFO ====\n"
2310 "NUM IFACE: %d\n"
2311 "RM STATE: %d\n"
2312 "ACTIVATED FW PIPE: %d\n"
2313 "SAP NUM STAs: %d\n"
2314 "STA CONNECTED: %d\n"
2315 "CONCURRENT MODE: %s\n"
2316 "RSC LOADING: %d\n"
2317 "RSC UNLOADING: %d\n"
2318 "PENDING CONS REQ: %d\n"
2319 "IPA PIPES DOWN: %d\n"
2320 "IPA UC LOADED: %d\n"
2321 "IPA WDI ENABLED: %d\n"
2322 "NUM SEND MSG: %d\n"
2323 "NUM FREE MSG: %d\n",
2324 hdd_ipa->num_iface,
2325 hdd_ipa->rm_state,
2326 hdd_ipa->activated_fw_pipe,
2327 hdd_ipa->sap_num_connected_sta,
2328 hdd_ipa->sta_connected,
2329 (hdd_ipa->hdd_ctx->mcc_mode ? "MCC" : "SCC"),
2330 hdd_ipa->resource_loading,
2331 hdd_ipa->resource_unloading,
2332 hdd_ipa->pending_cons_req,
2333 hdd_ipa->ipa_pipes_down,
2334 hdd_ipa->uc_loaded,
2335 hdd_ipa->wdi_enabled,
2336 (unsigned int)hdd_ipa->stats.num_send_msg,
2337 (unsigned int)hdd_ipa->stats.num_free_msg);
2338
2339 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
2340 iface_context = &hdd_ipa->iface_context[i];
2341 if (!iface_context || !iface_context->adapter)
2342 continue;
2343
Jeff Johnson1b780e42017-10-31 14:11:45 -07002344 session_id = iface_context->adapter->session_id;
Yun Park46255682017-10-09 15:56:34 -07002345 if (session_id >= CSR_ROAM_SESSION_MAX)
2346 continue;
2347
2348 device_mode = iface_context->adapter->device_mode;
2349 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2350 "\nIFACE[%d]: session:%d, sta_id:%d, mode:%s, offload:%d",
2351 i, session_id,
2352 iface_context->sta_id,
2353 hdd_device_mode_to_string(device_mode),
2354 hdd_ipa->vdev_offload_enabled[session_id]);
2355 }
2356
2357 for (i = 0; i < IPA_WLAN_EVENT_MAX; i++)
2358 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2359 "\nEVENT[%d]=%d",
2360 i, hdd_ipa->stats.event[i]);
2361
2362 i = 0;
2363 qdf_list_peek_front(&hdd_ipa->pending_event,
2364 (qdf_list_node_t **)&event);
2365 while (event != NULL) {
2366 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2367 "\nPENDING EVENT[%d]: DEV:%s, EVT:%s, sta_id:%d, MAC:%pM",
2368 i, event->adapter->dev->name,
2369 hdd_ipa_wlan_event_to_str(event->type),
2370 event->sta_id, event->mac_addr);
2371
2372 qdf_list_peek_next(&hdd_ipa->pending_event,
2373 (qdf_list_node_t *)event, (qdf_list_node_t **)&next);
2374 event = next;
2375 next = NULL;
2376 i++;
2377 }
2378}
2379
2380/**
2381 * hdd_ipa_print_txrx_stats - Print HDD IPA TX/RX stats
2382 * @hdd_ipa: HDD IPA local context
2383 *
2384 * Return: None
2385 */
2386static void hdd_ipa_print_txrx_stats(struct hdd_ipa_priv *hdd_ipa)
2387{
2388 int i;
2389 struct hdd_ipa_iface_context *iface_context = NULL;
2390
2391 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2392 "\n==== HDD IPA TX/RX STATS ====\n"
2393 "NUM RM GRANT: %llu\n"
2394 "NUM RM RELEASE: %llu\n"
2395 "NUM RM GRANT IMM: %llu\n"
2396 "NUM CONS PERF REQ: %llu\n"
2397 "NUM PROD PERF REQ: %llu\n"
2398 "NUM RX DROP: %llu\n"
2399 "NUM EXCP PKT: %llu\n"
2400 "NUM TX FWD OK: %llu\n"
2401 "NUM TX FWD ERR: %llu\n"
2402 "NUM TX DESC Q CNT: %llu\n"
2403 "NUM TX DESC ERROR: %llu\n"
2404 "NUM TX COMP CNT: %llu\n"
2405 "NUM TX QUEUED: %llu\n"
2406 "NUM TX DEQUEUED: %llu\n"
2407 "NUM MAX PM QUEUE: %llu\n"
2408 "TX REF CNT: %d\n"
2409 "SUSPENDED: %d\n"
2410 "PEND DESC HEAD: %pK\n"
2411 "TX DESC LIST: %pK\n"
2412 "FREE TX DESC HEAD: %pK\n",
2413 hdd_ipa->stats.num_rm_grant,
2414 hdd_ipa->stats.num_rm_release,
2415 hdd_ipa->stats.num_rm_grant_imm,
2416 hdd_ipa->stats.num_cons_perf_req,
2417 hdd_ipa->stats.num_prod_perf_req,
2418 hdd_ipa->stats.num_rx_drop,
2419 hdd_ipa->stats.num_rx_excep,
2420 hdd_ipa->stats.num_tx_fwd_ok,
2421 hdd_ipa->stats.num_tx_fwd_err,
2422 hdd_ipa->stats.num_tx_desc_q_cnt,
2423 hdd_ipa->stats.num_tx_desc_error,
2424 hdd_ipa->stats.num_tx_comp_cnt,
2425 hdd_ipa->stats.num_tx_queued,
2426 hdd_ipa->stats.num_tx_dequeued,
2427 hdd_ipa->stats.num_max_pm_queue,
2428 hdd_ipa->tx_ref_cnt.counter,
2429 hdd_ipa->suspended,
2430 &hdd_ipa->pend_desc_head,
2431 hdd_ipa->tx_desc_list,
2432 &hdd_ipa->free_tx_desc_head);
2433
2434 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
2435 iface_context = &hdd_ipa->iface_context[i];
2436 if (!iface_context || !iface_context->adapter)
2437 continue;
2438
2439 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2440 "IFACE[%d]: TX:%llu, TX DROP:%llu, TX ERR:%llu, TX CAC DROP:%llu, RX IPA EXCEP:%llu",
2441 i,
2442 iface_context->stats.num_tx,
2443 iface_context->stats.num_tx_drop,
2444 iface_context->stats.num_tx_err,
2445 iface_context->stats.num_tx_cac_drop,
2446 iface_context->stats.num_rx_ipa_excep);
2447 }
2448}
2449
2450/**
2451 * hdd_ipa_print_fw_wdi_stats - Print WLAN FW WDI stats
2452 * @hdd_ipa: HDD IPA local context
2453 *
2454 * Return: None
2455 */
2456static void hdd_ipa_print_fw_wdi_stats(struct hdd_ipa_priv *hdd_ipa,
2457 struct ipa_uc_fw_stats *uc_fw_stat)
2458{
2459 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2460 "\n==== WLAN FW WDI TX STATS ====\n"
2461 "COMP RING BASE: 0x%x\n"
2462 "COMP RING SIZE: %d\n"
2463 "COMP RING DBELL : 0x%x\n"
2464 "COMP RING DBELL IND VAL : %d\n"
2465 "COMP RING DBELL CACHED VAL : %d\n"
2466 "PKTS ENQ : %d\n"
2467 "PKTS COMP : %d\n"
2468 "IS SUSPEND : %d\n",
2469 uc_fw_stat->tx_comp_ring_base,
2470 uc_fw_stat->tx_comp_ring_size,
2471 uc_fw_stat->tx_comp_ring_dbell_addr,
2472 uc_fw_stat->tx_comp_ring_dbell_ind_val,
2473 uc_fw_stat->tx_comp_ring_dbell_cached_val,
2474 uc_fw_stat->tx_pkts_enqueued,
2475 uc_fw_stat->tx_pkts_completed,
2476 uc_fw_stat->tx_is_suspend);
2477
2478 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2479 "\n==== WLAN FW WDI RX STATS ====\n"
2480 "IND RING BASE: 0x%x\n"
2481 "IND RING SIZE: %d\n"
2482 "IND RING DBELL : 0x%x\n"
2483 "IND RING DBELL IND VAL : %d\n"
2484 "IND RING DBELL CACHED VAL : %d\n"
2485 "RDY IND ADDR : 0x%x\n"
2486 "RDY IND CACHE VAL : %d\n"
2487 "RFIL IND : %d\n"
2488 "NUM PKT INDICAT : %d\n"
2489 "BUF REFIL : %d\n"
2490 "NUM DROP NO SPC : %d\n"
2491 "NUM DROP NO BUF : %d\n"
2492 "IS SUSPND : %d\n",
2493 uc_fw_stat->rx_ind_ring_base,
2494 uc_fw_stat->rx_ind_ring_size,
2495 uc_fw_stat->rx_ind_ring_dbell_addr,
2496 uc_fw_stat->rx_ind_ring_dbell_ind_val,
2497 uc_fw_stat->rx_ind_ring_dbell_ind_cached_val,
2498 uc_fw_stat->rx_ind_ring_rdidx_addr,
2499 uc_fw_stat->rx_ind_ring_rd_idx_cached_val,
2500 uc_fw_stat->rx_refill_idx,
2501 uc_fw_stat->rx_num_pkts_indicated,
2502 uc_fw_stat->rx_buf_refilled,
2503 uc_fw_stat->rx_num_ind_drop_no_space,
2504 uc_fw_stat->rx_num_ind_drop_no_buf,
2505 uc_fw_stat->rx_is_suspend);
2506}
2507
2508/**
2509 * hdd_ipa_print_ipa_wdi_stats - Print IPA WDI stats
2510 * @hdd_ipa: HDD IPA local context
2511 *
2512 * Return: None
2513 */
2514static void hdd_ipa_print_ipa_wdi_stats(struct hdd_ipa_priv *hdd_ipa)
2515{
2516 struct IpaHwStatsWDIInfoData_t ipa_stat;
2517
2518 ipa_get_wdi_stats(&ipa_stat);
2519
2520 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2521 "\n==== IPA WDI TX STATS ====\n"
2522 "NUM PROCD : %d\n"
2523 "CE DBELL : 0x%x\n"
2524 "NUM DBELL FIRED : %d\n"
2525 "COMP RNG FULL : %d\n"
2526 "COMP RNG EMPT : %d\n"
2527 "COMP RNG USE HGH : %d\n"
2528 "COMP RNG USE LOW : %d\n"
2529 "BAM FIFO FULL : %d\n"
2530 "BAM FIFO EMPT : %d\n"
2531 "BAM FIFO USE HGH : %d\n"
2532 "BAM FIFO USE LOW : %d\n"
2533 "NUM DBELL : %d\n"
2534 "NUM UNEXP DBELL : %d\n"
2535 "NUM BAM INT HDL : 0x%x\n"
2536 "NUM BAM INT NON-RUN : 0x%x\n"
2537 "NUM QMB INT HDL : 0x%x\n",
2538 ipa_stat.tx_ch_stats.num_pkts_processed,
2539 ipa_stat.tx_ch_stats.copy_engine_doorbell_value,
2540 ipa_stat.tx_ch_stats.num_db_fired,
2541 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringFull,
2542 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringEmpty,
2543 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh,
2544 ipa_stat.tx_ch_stats.tx_comp_ring_stats.ringUsageLow,
2545 ipa_stat.tx_ch_stats.bam_stats.bamFifoFull,
2546 ipa_stat.tx_ch_stats.bam_stats.bamFifoEmpty,
2547 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageHigh,
2548 ipa_stat.tx_ch_stats.bam_stats.bamFifoUsageLow,
2549 ipa_stat.tx_ch_stats.num_db,
2550 ipa_stat.tx_ch_stats.num_unexpected_db,
2551 ipa_stat.tx_ch_stats.num_bam_int_handled,
2552 ipa_stat.tx_ch_stats.
2553#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2554 num_bam_int_in_non_running_state,
2555#else
2556 num_bam_int_in_non_runnning_state,
2557#endif
2558 ipa_stat.tx_ch_stats.num_qmb_int_handled);
2559
2560 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
2561 "\n==== IPA WDI RX STATS ====\n"
2562 "MAX OST PKT : %d\n"
2563 "NUM PKT PRCSD : %d\n"
2564 "RNG RP : 0x%x\n"
2565 "IND RNG FULL : %d\n"
2566 "IND RNG EMPT : %d\n"
2567 "IND RNG USE HGH : %d\n"
2568 "IND RNG USE LOW : %d\n"
2569 "BAM FIFO FULL : %d\n"
2570 "BAM FIFO EMPT : %d\n"
2571 "BAM FIFO USE HGH : %d\n"
2572 "BAM FIFO USE LOW : %d\n"
2573 "NUM DB : %d\n"
2574 "NUM UNEXP DB : %d\n"
2575 "NUM BAM INT HNDL : 0x%x\n",
2576 ipa_stat.rx_ch_stats.max_outstanding_pkts,
2577 ipa_stat.rx_ch_stats.num_pkts_processed,
2578 ipa_stat.rx_ch_stats.rx_ring_rp_value,
2579 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringFull,
2580 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringEmpty,
2581 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh,
2582 ipa_stat.rx_ch_stats.rx_ind_ring_stats.ringUsageLow,
2583 ipa_stat.rx_ch_stats.bam_stats.bamFifoFull,
2584 ipa_stat.rx_ch_stats.bam_stats.bamFifoEmpty,
2585 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageHigh,
2586 ipa_stat.rx_ch_stats.bam_stats.bamFifoUsageLow,
2587 ipa_stat.rx_ch_stats.num_db,
2588 ipa_stat.rx_ch_stats.num_unexpected_db,
2589 ipa_stat.rx_ch_stats.num_bam_int_handled);
2590}
2591
2592/**
2593 * hdd_ipa_uc_info() - Print IPA uC resource and session information
2594 * @adapter: network adapter
2595 *
2596 * Return: None
2597 */
2598void hdd_ipa_uc_info(struct hdd_context *hdd_ctx)
2599{
2600 struct hdd_ipa_priv *hdd_ipa;
2601
2602 hdd_ipa = hdd_ctx->hdd_ipa;
2603
2604 if (!hdd_ipa) {
2605 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2606 "HDD IPA context is NULL");
2607 return;
2608 }
2609
2610 /* IPA session info */
2611 hdd_ipa_print_session_info(hdd_ipa);
2612}
2613
2614/**
2615 * hdd_ipa_uc_stat() - Print IPA uC stats
2616 * @adapter: network adapter
2617 *
2618 * Return: None
2619 */
2620void hdd_ipa_uc_stat(struct hdd_adapter *adapter)
2621{
2622 struct hdd_context *hdd_ctx;
2623 struct hdd_ipa_priv *hdd_ipa;
2624
2625 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2626 hdd_ipa = hdd_ctx->hdd_ipa;
2627
2628 if (!hdd_ipa) {
2629 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2630 "HDD IPA context is NULL");
2631 return;
2632 }
2633
2634 /* HDD IPA TX/RX stats */
2635 hdd_ipa_print_txrx_stats(hdd_ipa);
2636 /* IPA WDI stats */
2637 hdd_ipa_print_ipa_wdi_stats(hdd_ipa);
2638 /* WLAN FW WDI stats */
2639 hdd_ipa_uc_stat_request(adapter, HDD_IPA_UC_STAT_REASON_DEBUG);
2640}
2641
2642/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002643 * hdd_ipa_uc_op_cb() - IPA uC operation callback
2644 * @op_msg: operation message received from firmware
2645 * @usr_ctxt: user context registered with TL (we register the HDD Global
2646 * context)
2647 *
2648 * Return: None
2649 */
2650static void hdd_ipa_uc_op_cb(struct op_msg_type *op_msg, void *usr_ctxt)
2651{
2652 struct op_msg_type *msg = op_msg;
2653 struct ipa_uc_fw_stats *uc_fw_stat;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002654 struct hdd_ipa_priv *hdd_ipa;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002655 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302656 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657
2658 if (!op_msg || !usr_ctxt) {
Yun Park46255682017-10-09 15:56:34 -07002659 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "INVALID ARG");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 return;
2661 }
2662
2663 if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302664 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002665 "INVALID OPCODE %d", msg->op_code);
jiadd91a6842017-08-01 14:46:02 +08002666 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002667 return;
2668 }
2669
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002670 hdd_ctx = (struct hdd_context *) usr_ctxt;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671
2672 /*
2673 * When SSR is going on or driver is unloading, just return.
2674 */
2675 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302676 if (status) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302677 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 return;
2679 }
2680
2681 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
2682
Govind Singhb6a89772016-08-12 11:23:35 +05302683 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park5f0fc232017-02-10 10:34:57 -08002684 "OPCODE=%d", msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685
2686 if ((HDD_IPA_UC_OPCODE_TX_RESUME == msg->op_code) ||
2687 (HDD_IPA_UC_OPCODE_RX_RESUME == msg->op_code)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302688 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 hdd_ipa->activated_fw_pipe++;
2690 if (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) {
2691 hdd_ipa->resource_loading = false;
Yun Park777d7242017-03-30 15:38:33 -07002692 complete(&hdd_ipa->ipa_resource_comp);
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08002693 if (hdd_ipa->wdi_enabled == false) {
2694 hdd_ipa->wdi_enabled = true;
2695 if (hdd_ipa_uc_send_wdi_control_msg(true) == 0)
2696 hdd_ipa_send_mcc_scc_msg(hdd_ctx,
2697 hdd_ctx->mcc_mode);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002698 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002699 hdd_ipa_uc_proc_pending_event(hdd_ipa);
Yun Parkccc6d7a2015-12-02 14:50:13 -08002700 if (hdd_ipa->pending_cons_req)
2701 ipa_rm_notify_completion(
2702 IPA_RM_RESOURCE_GRANTED,
2703 IPA_RM_RESOURCE_WLAN_CONS);
Yun Park5b635012015-12-02 15:05:01 -08002704 hdd_ipa->pending_cons_req = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302706 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park8292dcb2016-10-07 16:46:06 -07002707 } else if ((HDD_IPA_UC_OPCODE_TX_SUSPEND == msg->op_code) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 (HDD_IPA_UC_OPCODE_RX_SUSPEND == msg->op_code)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302709 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002710 hdd_ipa->activated_fw_pipe--;
2711 if (!hdd_ipa->activated_fw_pipe) {
Yun Park777d7242017-03-30 15:38:33 -07002712 /*
2713 * Async return success from FW
2714 * Disable/suspend all the PIPEs
2715 */
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 Park5b635012015-12-02 15:05:01 -08002720 hdd_ipa->resource_unloading = false;
Yun Park777d7242017-03-30 15:38:33 -07002721 complete(&hdd_ipa->ipa_resource_comp);
Yun Park5b635012015-12-02 15:05:01 -08002722 hdd_ipa_uc_proc_pending_event(hdd_ipa);
2723 hdd_ipa->pending_cons_req = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302725 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park8292dcb2016-10-07 16:46:06 -07002726 } else if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 (HDD_IPA_UC_STAT_REASON_DEBUG == hdd_ipa->stat_req_reason)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 uc_fw_stat = (struct ipa_uc_fw_stats *)
Yun Park46255682017-10-09 15:56:34 -07002729 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730
Yun Park46255682017-10-09 15:56:34 -07002731 /* WLAN FW WDI stats */
2732 hdd_ipa_print_fw_wdi_stats(hdd_ipa, uc_fw_stat);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 } else if ((HDD_IPA_UC_OPCODE_STATS == msg->op_code) &&
2734 (HDD_IPA_UC_STAT_REASON_BW_CAL == hdd_ipa->stat_req_reason)) {
2735 /* STATs from FW */
2736 uc_fw_stat = (struct ipa_uc_fw_stats *)
2737 ((uint8_t *)op_msg + sizeof(struct op_msg_type));
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302738 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739 hdd_ipa->ipa_tx_packets_diff = HDD_BW_GET_DIFF(
2740 uc_fw_stat->tx_pkts_completed,
2741 hdd_ipa->ipa_p_tx_packets);
2742 hdd_ipa->ipa_rx_packets_diff = HDD_BW_GET_DIFF(
2743 (uc_fw_stat->rx_num_ind_drop_no_space +
2744 uc_fw_stat->rx_num_ind_drop_no_buf +
2745 uc_fw_stat->rx_num_pkts_indicated),
2746 hdd_ipa->ipa_p_rx_packets);
2747
2748 hdd_ipa->ipa_p_tx_packets = uc_fw_stat->tx_pkts_completed;
2749 hdd_ipa->ipa_p_rx_packets =
2750 (uc_fw_stat->rx_num_ind_drop_no_space +
2751 uc_fw_stat->rx_num_ind_drop_no_buf +
2752 uc_fw_stat->rx_num_pkts_indicated);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05302753 qdf_mutex_release(&hdd_ipa->ipa_lock);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08002754 } else if (msg->op_code == HDD_IPA_UC_OPCODE_UC_READY) {
2755 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
2756 hdd_ipa_uc_loaded_handler(hdd_ipa);
2757 qdf_mutex_release(&hdd_ipa->ipa_lock);
Yun Park637d6482016-10-05 10:51:33 -07002758 } else if (hdd_ipa_uc_op_metering(hdd_ctx, op_msg)) {
2759 HDD_IPA_LOG(LOGE, "Invalid message: op_code=%d, reason=%d",
2760 msg->op_code, hdd_ipa->stat_req_reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 }
Yun Park8957d802017-01-25 12:27:29 -08002762
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302763 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002764}
2765
2766
2767/**
2768 * hdd_ipa_uc_offload_enable_disable() - wdi enable/disable notify to fw
2769 * @adapter: device adapter instance
2770 * @offload_type: MCC or SCC
2771 * @enable: TX offload enable or disable
2772 *
2773 * Return: none
2774 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07002775static void hdd_ipa_uc_offload_enable_disable(struct hdd_adapter *adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002776 uint32_t offload_type, bool enable)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777{
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002778 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 struct sir_ipa_offload_enable_disable ipa_offload_enable_disable;
Yun Park8292dcb2016-10-07 16:46:06 -07002780 struct hdd_ipa_iface_context *iface_context = NULL;
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002781 uint8_t session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002783 if (!adapter || !hdd_ipa)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 return;
2785
Yun Park8292dcb2016-10-07 16:46:06 -07002786 iface_context = adapter->ipa_context;
Jeff Johnson1b780e42017-10-31 14:11:45 -07002787 session_id = adapter->session_id;
Yun Park8292dcb2016-10-07 16:46:06 -07002788
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002789 if (!iface_context) {
2790 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2791 "Interface context is NULL");
2792 return;
2793 }
Zhu Jianminded9d2d2017-06-22 09:39:36 +08002794 if (session_id >= CSR_ROAM_SESSION_MAX) {
2795 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2796 "invalid session id: %d", session_id);
2797 return;
2798 }
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002799 if (enable == hdd_ipa->vdev_offload_enabled[session_id]) {
Yun Park199c2ed2017-10-02 11:24:22 -07002800 /*
2801 * This shouldn't happen :
2802 * IPA offload status is already set as desired
2803 */
2804 WARN_ON(1);
2805 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
Yun Parkb4f591d2017-03-29 15:51:01 -07002806 "%s (offload_type=%d, vdev_id=%d, enable=%d)",
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002807 "IPA offload status is already set",
2808 offload_type, session_id, enable);
Yun Park8292dcb2016-10-07 16:46:06 -07002809 return;
2810 }
2811
Jeff Johnson1b780e42017-10-31 14:11:45 -07002812 if (wlan_hdd_validate_session_id(adapter->session_id)) {
Yun Park4540e862016-11-10 16:30:06 -08002813 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2814 "invalid session id: %d, offload_type=%d, enable=%d",
Jeff Johnson1b780e42017-10-31 14:11:45 -07002815 adapter->session_id, offload_type, enable);
Yun Park4540e862016-11-10 16:30:06 -08002816 return;
2817 }
2818
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302819 qdf_mem_zero(&ipa_offload_enable_disable,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 sizeof(ipa_offload_enable_disable));
2821 ipa_offload_enable_disable.offload_type = offload_type;
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002822 ipa_offload_enable_disable.vdev_id = session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002823 ipa_offload_enable_disable.enable = enable;
2824
Yun Park199c2ed2017-10-02 11:24:22 -07002825 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park8292dcb2016-10-07 16:46:06 -07002826 "offload_type=%d, vdev_id=%d, enable=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 ipa_offload_enable_disable.offload_type,
2828 ipa_offload_enable_disable.vdev_id,
2829 ipa_offload_enable_disable.enable);
2830
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302831 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 sme_ipa_offload_enable_disable(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -07002833 adapter->session_id, &ipa_offload_enable_disable)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302834 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07002835 "Failure to enable IPA offload (offload_type=%d, vdev_id=%d, enable=%d)",
2836 ipa_offload_enable_disable.offload_type,
2837 ipa_offload_enable_disable.vdev_id,
2838 ipa_offload_enable_disable.enable);
Yun Park8292dcb2016-10-07 16:46:06 -07002839 } else {
2840 /* Update the IPA offload status */
Prakash Dhavali89d406d2016-11-23 11:11:00 -08002841 hdd_ipa->vdev_offload_enabled[session_id] =
Yun Park8292dcb2016-10-07 16:46:06 -07002842 ipa_offload_enable_disable.enable;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 }
2844}
2845
2846/**
2847 * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2848 * @work: uC OP work
2849 *
2850 * Return: None
2851 */
2852static void hdd_ipa_uc_fw_op_event_handler(struct work_struct *work)
2853{
2854 struct op_msg_type *msg;
2855 struct uc_op_work_struct *uc_op_work = container_of(work,
2856 struct uc_op_work_struct, work);
2857 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
2858
2859 cds_ssr_protect(__func__);
2860
2861 msg = uc_op_work->msg;
2862 uc_op_work->msg = NULL;
Srinivas Girigowda97852372017-03-06 16:52:59 -08002863 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07002864 "posted msg %d", msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865
2866 hdd_ipa_uc_op_cb(msg, hdd_ipa->hdd_ctx);
2867
2868 cds_ssr_unprotect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869}
2870
2871/**
2872 * hdd_ipa_uc_op_event_handler() - Adapter lookup
2873 * hdd_ipa_uc_fw_op_event_handler - IPA uC FW OPvent handler
2874 * @op_msg: operation message received from firmware
2875 * @hdd_ctx: Global HDD context
2876 *
2877 * Return: None
2878 */
2879static void hdd_ipa_uc_op_event_handler(uint8_t *op_msg, void *hdd_ctx)
2880{
2881 struct hdd_ipa_priv *hdd_ipa;
2882 struct op_msg_type *msg;
2883 struct uc_op_work_struct *uc_op_work;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302884 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002885
2886 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302887 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002888 goto end;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889
2890 msg = (struct op_msg_type *)op_msg;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07002891 hdd_ipa = ((struct hdd_context *)hdd_ctx)->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892
2893 if (unlikely(!hdd_ipa))
2894 goto end;
2895
2896 if (HDD_IPA_UC_OPCODE_MAX <= msg->op_code) {
Yun Parkb4f591d2017-03-29 15:51:01 -07002897 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Invalid OP Code (%d)",
2898 msg->op_code);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 goto end;
2900 }
2901
2902 uc_op_work = &hdd_ipa->uc_op_work[msg->op_code];
2903 if (uc_op_work->msg)
2904 /* When the same uC OPCODE is already pended, just return */
2905 goto end;
2906
2907 uc_op_work->msg = msg;
2908 schedule_work(&uc_op_work->work);
2909 return;
2910
2911end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302912 qdf_mem_free(op_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913}
2914
2915/**
Rajeev Kumar217f2172016-01-06 18:11:55 -08002916 * hdd_ipa_init_uc_op_work - init ipa uc op work
2917 * @work: struct work_struct
2918 * @work_handler: work_handler
2919 *
2920 * Return: none
2921 */
Rajeev Kumar217f2172016-01-06 18:11:55 -08002922static void hdd_ipa_init_uc_op_work(struct work_struct *work,
Yun Park637d6482016-10-05 10:51:33 -07002923 work_func_t work_handler)
Rajeev Kumar217f2172016-01-06 18:11:55 -08002924{
2925 INIT_WORK(work, work_handler);
2926}
Rajeev Kumar217f2172016-01-06 18:11:55 -08002927
Yun Park637d6482016-10-05 10:51:33 -07002928#ifdef FEATURE_METERING
2929/**
2930 * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
2931 * IPA calls to get WLAN stats or set quota limit.
2932 * @priv: pointer to private data registered with IPA (we register a
2933 *» pointer to the global IPA context)
2934 * @evt: the IPA event which triggered the callback
2935 * @data: data associated with the event
2936 *
2937 * Return: None
2938 */
Yun Park6c86a662017-10-05 16:09:15 -07002939static void __hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Park637d6482016-10-05 10:51:33 -07002940 void *data)
2941{
2942 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07002943 struct hdd_adapter *adapter = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07002944 qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats;
2945 qdf_ipa_set_wifi_quota_t *ipa_set_quota;
Yun Park637d6482016-10-05 10:51:33 -07002946 int ret = 0;
2947
2948 if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
2949 return;
2950
2951 adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
2952
2953 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "event=%d", evt);
2954
2955 switch (evt) {
2956 case IPA_GET_WDI_SAP_STATS:
2957 /* fill-up ipa_get_wdi_sap_stats structure after getting
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07002958 * ipa_uc_fw_stats from FW
2959 */
Yun Park637d6482016-10-05 10:51:33 -07002960 wdi_sap_stats = data;
2961
2962 if (!adapter) {
2963 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2964 "IPA uC share stats failed - no adapter");
Yun Park6c86a662017-10-05 16:09:15 -07002965 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) =
2966 0;
Yun Park637d6482016-10-05 10:51:33 -07002967 return;
2968 }
2969
2970 INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
Yun Park637d6482016-10-05 10:51:33 -07002971 hdd_ipa_uc_sharing_stats_request(adapter,
Yun Park6c86a662017-10-05 16:09:15 -07002972 QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats));
Yun Park637d6482016-10-05 10:51:33 -07002973 ret = wait_for_completion_timeout(
2974 &hdd_ipa->ipa_uc_sharing_stats_comp,
2975 msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
2976 if (!ret) {
2977 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
2978 "IPA uC share stats request timed out");
Yun Park6c86a662017-10-05 16:09:15 -07002979 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
2980 = 0;
Yun Park637d6482016-10-05 10:51:33 -07002981 } else {
Yun Park6c86a662017-10-05 16:09:15 -07002982 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
2983 = 1;
Yun Park637d6482016-10-05 10:51:33 -07002984
Yun Park6c86a662017-10-05 16:09:15 -07002985 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats)
2986 = hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
2987 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats)
2988 = hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
2989 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats)
2990 = hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
2991 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats)
2992 = hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
2993 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats)
2994 = hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
2995 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats)
2996 = hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
2997 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats)
2998 = hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
2999 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats)
3000 = hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
Yun Park637d6482016-10-05 10:51:33 -07003001 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
3002 "%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
3003 "IPA_GET_WDI_SAP_STATS",
Yun Park6c86a662017-10-05 16:09:15 -07003004 QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(
3005 wdi_sap_stats),
3006 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(
3007 wdi_sap_stats),
3008 QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(
3009 wdi_sap_stats),
3010 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(
3011 wdi_sap_stats),
3012 QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(
3013 wdi_sap_stats),
3014 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(
3015 wdi_sap_stats),
3016 QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(
3017 wdi_sap_stats),
3018 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(
3019 wdi_sap_stats),
3020 QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(
3021 wdi_sap_stats));
Yun Park637d6482016-10-05 10:51:33 -07003022 }
3023 break;
3024 case IPA_SET_WIFI_QUOTA:
3025 /* get ipa_set_wifi_quota structure from IPA and pass to FW
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07003026 * through quota_exceeded field in ipa_uc_fw_stats
3027 */
Yun Park637d6482016-10-05 10:51:33 -07003028 ipa_set_quota = data;
3029
3030 if (!adapter) {
3031 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3032 "IPA uC set quota failed - no adapter");
3033 ipa_set_quota->set_valid = 0;
3034 return;
3035 }
3036
Yun Park777d7242017-03-30 15:38:33 -07003037 INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
Yun Park637d6482016-10-05 10:51:33 -07003038 hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
3039 ipa_set_quota->quota_bytes);
3040
3041 ret = wait_for_completion_timeout(
3042 &hdd_ipa->ipa_uc_set_quota_comp,
3043 msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
3044 if (!ret) {
3045 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3046 "IPA uC set quota request timed out");
Yun Park6c86a662017-10-05 16:09:15 -07003047 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) = 0;
Yun Park637d6482016-10-05 10:51:33 -07003048 } else {
Yun Park6c86a662017-10-05 16:09:15 -07003049 QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) =
Yun Park637d6482016-10-05 10:51:33 -07003050 ((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
3051 <<32)|hdd_ipa->ipa_quota_rsp.quota_lo;
Yun Park6c86a662017-10-05 16:09:15 -07003052 QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota) =
Yun Park637d6482016-10-05 10:51:33 -07003053 hdd_ipa->ipa_quota_rsp.success;
3054 }
3055
3056 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
3057 ipa_set_quota->quota_bytes,
3058 ipa_set_quota->set_valid);
3059 break;
3060 }
3061}
3062
3063/**
3064 * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
3065 * IPA calls to get WLAN stats or set quota limit.
3066 * @priv: pointer to private data registered with IPA (we register a
Yun Parkb4f591d2017-03-29 15:51:01 -07003067 * pointer to the global IPA context)
Yun Park637d6482016-10-05 10:51:33 -07003068 * @evt: the IPA event which triggered the callback
3069 * @data: data associated with the event
3070 *
3071 * Return: None
3072 */
Yun Park6c86a662017-10-05 16:09:15 -07003073static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
Yun Park637d6482016-10-05 10:51:33 -07003074 void *data)
3075{
3076 cds_ssr_protect(__func__);
3077 __hdd_ipa_wdi_meter_notifier_cb(evt, data);
3078 cds_ssr_unprotect(__func__);
3079}
3080
Yun Parkb4f591d2017-03-29 15:51:01 -07003081static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
Yun Park637d6482016-10-05 10:51:33 -07003082{
Yun Park637d6482016-10-05 10:51:33 -07003083 init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
3084 init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
3085}
3086#else
Yun Parkb4f591d2017-03-29 15:51:01 -07003087static void hdd_ipa_wdi_meter_notifier_cb(void)
3088{
3089}
3090
3091static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
Yun Park637d6482016-10-05 10:51:33 -07003092{
3093}
3094#endif
3095
Rajeev Kumar217f2172016-01-06 18:11:55 -08003096/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 * hdd_ipa_uc_ol_init() - Initialize IPA uC offload
3098 * @hdd_ctx: Global HDD context
3099 *
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003100 * This function is called to update IPA pipe configuration with resources
3101 * allocated by wlan driver (cds_pre_enable) before enabling it in FW
3102 * (cds_enable)
3103 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303104 * Return: QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003106QDF_STATUS hdd_ipa_uc_ol_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107{
Yun Parkb4f591d2017-03-29 15:51:01 -07003108 struct hdd_ipa_priv *hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
Leo Changfdb45c32016-10-28 11:09:23 -07003109 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Yun Parkbaa62862017-01-18 13:43:34 -08003110 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Parkb4f591d2017-03-29 15:51:01 -07003111 uint8_t i;
3112 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003113
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003114 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
3115 return QDF_STATUS_SUCCESS;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003116
Yun Park199c2ed2017-10-02 11:24:22 -07003117 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003118
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003119 /* Do only IPA Pipe specific configuration here. All one time
3120 * initialization wrt IPA UC shall in hdd_ipa_init and those need
3121 * to be reinit at SSR shall in be SSR deinit / reinit functions.
3122 */
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003123 if (!pdev || !soc) {
3124 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "DP context is NULL");
Yun Parkb4f591d2017-03-29 15:51:01 -07003125 status = QDF_STATUS_E_FAILURE;
Yun Parkbaa62862017-01-18 13:43:34 -08003126 goto fail_return;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003127 }
Yun Parkb4f591d2017-03-29 15:51:01 -07003128 if (cdp_ipa_get_resource(soc, (struct cdp_pdev *)pdev)) {
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003129 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
3130 "IPA UC resource alloc fail");
Yun Park199c2ed2017-10-02 11:24:22 -07003131 status = QDF_STATUS_E_FAILURE;
3132 goto fail_return;
Manikandan Mohanbb8a7ee2017-02-09 11:26:53 -08003133 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134
Yun Parkb4f591d2017-03-29 15:51:01 -07003135 if (true == hdd_ipa->uc_loaded) {
3136 status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
3137 hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
3138 hdd_ipa_wdi_meter_notifier_cb,
3139 hdd_ctx->config->IpaDescSize,
3140 hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
3141 &hdd_ipa->tx_pipe_handle,
3142 &hdd_ipa->rx_pipe_handle);
3143 if (status) {
Yun Parkbaa62862017-01-18 13:43:34 -08003144 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkb4f591d2017-03-29 15:51:01 -07003145 "Failure to setup IPA pipes (status=%d)",
3146 status);
Yun Park199c2ed2017-10-02 11:24:22 -07003147 status = QDF_STATUS_E_FAILURE;
3148 goto fail_return;
Yun Parkbaa62862017-01-18 13:43:34 -08003149 }
Yun Park637d6482016-10-05 10:51:33 -07003150
Yun Parkb4f591d2017-03-29 15:51:01 -07003151 cdp_ipa_set_doorbell_paddr(soc, (struct cdp_pdev *)pdev);
3152 hdd_ipa_init_metering(hdd_ipa);
Manikandan Mohan153a4c32017-02-16 15:04:30 -08003153 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154
Yun Parkb4f591d2017-03-29 15:51:01 -07003155 cdp_ipa_register_op_cb(soc, (struct cdp_pdev *)pdev,
Yun Parkbaa62862017-01-18 13:43:34 -08003156 hdd_ipa_uc_op_event_handler, (void *)hdd_ctx);
3157
Yun Parkb4f591d2017-03-29 15:51:01 -07003158 for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
3159 hdd_ipa_init_uc_op_work(&hdd_ipa->uc_op_work[i].work,
3160 hdd_ipa_uc_fw_op_event_handler);
3161 hdd_ipa->uc_op_work[i].msg = NULL;
3162 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163
Yun Parkbaa62862017-01-18 13:43:34 -08003164fail_return:
Yun Park199c2ed2017-10-02 11:24:22 -07003165 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: status=%d", status);
Yun Parkb4f591d2017-03-29 15:51:01 -07003166 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167}
3168
Leo Change3e49442015-10-26 20:07:13 -07003169/**
Yun Parkd8fb1a82017-10-13 16:48:20 -07003170 * hdd_ipa_cleanup_pending_event() - Cleanup IPA pending event list
3171 * @hdd_ipa: pointer to HDD IPA struct
3172 *
3173 * Return: none
3174 */
3175static void hdd_ipa_cleanup_pending_event(struct hdd_ipa_priv *hdd_ipa)
3176{
3177 struct ipa_uc_pending_event *pending_event = NULL;
3178
3179 while (qdf_list_remove_front(&hdd_ipa->pending_event,
3180 (qdf_list_node_t **)&pending_event) == QDF_STATUS_SUCCESS)
3181 qdf_mem_free(pending_event);
3182}
3183
3184/**
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303185 * hdd_ipa_uc_ol_deinit() - Disconnect IPA TX and RX pipes
3186 * @hdd_ctx: Global HDD context
3187 *
3188 * Return: 0 on success, negativer errno on error
3189 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003190int hdd_ipa_uc_ol_deinit(struct hdd_context *hdd_ctx)
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303191{
3192 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
3193 int ret = 0;
Yun Parkb4f591d2017-03-29 15:51:01 -07003194 QDF_STATUS status;
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303195
Yun Park199c2ed2017-10-02 11:24:22 -07003196 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003197
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303198 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
3199 return ret;
3200
Sravan Kumar Kairam374a8682017-05-15 13:19:44 +05303201 if (!hdd_ipa->ipa_pipes_down)
3202 hdd_ipa_uc_disable_pipes(hdd_ipa);
3203
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303204 if (true == hdd_ipa->uc_loaded) {
Yun Parkb4f591d2017-03-29 15:51:01 -07003205 status = cdp_ipa_cleanup(cds_get_context(QDF_MODULE_ID_SOC),
3206 hdd_ipa->tx_pipe_handle,
3207 hdd_ipa->rx_pipe_handle);
3208 if (status) {
3209 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3210 "Failure to cleanup IPA pipes (status=%d)",
3211 status);
3212 return -EFAULT;
3213 }
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303214 }
3215
Yun Parkd8fb1a82017-10-13 16:48:20 -07003216 hdd_ipa_cleanup_pending_event(hdd_ipa);
3217
Yun Park199c2ed2017-10-02 11:24:22 -07003218 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: ret=%d", ret);
Sravan Kumar Kairam71121712017-04-15 00:34:42 +05303219 return ret;
3220}
3221
3222/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003223 * __hdd_ipa_uc_force_pipe_shutdown() - Force shutdown IPA pipe
Leo Change3e49442015-10-26 20:07:13 -07003224 * @hdd_ctx: hdd main context
3225 *
3226 * Force shutdown IPA pipe
3227 * Independent of FW pipe status, IPA pipe shutdonw progress
3228 * in case, any STA does not leave properly, IPA HW pipe should cleaned up
3229 * independent from FW pipe status
3230 *
3231 * Return: NONE
3232 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003233static void __hdd_ipa_uc_force_pipe_shutdown(struct hdd_context *hdd_ctx)
Leo Change3e49442015-10-26 20:07:13 -07003234{
3235 struct hdd_ipa_priv *hdd_ipa;
3236
Yun Park199c2ed2017-10-02 11:24:22 -07003237 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003238
Leo Change3e49442015-10-26 20:07:13 -07003239 if (!hdd_ipa_is_enabled(hdd_ctx) || !hdd_ctx->hdd_ipa)
3240 return;
3241
3242 hdd_ipa = (struct hdd_ipa_priv *)hdd_ctx->hdd_ipa;
3243 if (false == hdd_ipa->ipa_pipes_down) {
Yun Park46255682017-10-09 15:56:34 -07003244 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Parkb4f591d2017-03-29 15:51:01 -07003245 "IPA pipes are not down yet, force shutdown");
Leo Change3e49442015-10-26 20:07:13 -07003246 hdd_ipa_uc_disable_pipes(hdd_ipa);
3247 } else {
Srinivas Girigowda97852372017-03-06 16:52:59 -08003248 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb4f591d2017-03-29 15:51:01 -07003249 "IPA pipes are down, do nothing");
Leo Change3e49442015-10-26 20:07:13 -07003250 }
Yun Parkfec73dc2017-09-06 10:40:07 -07003251
Yun Park199c2ed2017-10-02 11:24:22 -07003252 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
Leo Change3e49442015-10-26 20:07:13 -07003253}
3254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003256 * hdd_ipa_uc_force_pipe_shutdown() - SSR wrapper for
3257 * __hdd_ipa_uc_force_pipe_shutdown
3258 * @hdd_ctx: hdd main context
3259 *
3260 * Force shutdown IPA pipe
3261 * Independent of FW pipe status, IPA pipe shutdonw progress
3262 * in case, any STA does not leave properly, IPA HW pipe should cleaned up
3263 * independent from FW pipe status
3264 *
3265 * Return: NONE
3266 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003267void hdd_ipa_uc_force_pipe_shutdown(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003268{
3269 cds_ssr_protect(__func__);
3270 __hdd_ipa_uc_force_pipe_shutdown(hdd_ctx);
3271 cds_ssr_unprotect(__func__);
3272}
3273
3274/**
Govind Singh9c58eba2016-09-02 16:23:06 +05303275 * hdd_ipa_msg_free_fn() - Free an IPA message
3276 * @buff: pointer to the IPA message
3277 * @len: length of the IPA message
3278 * @type: type of IPA message
3279 *
3280 * Return: None
3281 */
3282static void hdd_ipa_msg_free_fn(void *buff, uint32_t len, uint32_t type)
3283{
Srinivas Girigowda97852372017-03-06 16:52:59 -08003284 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "msg type:%d, len:%d", type, len);
Govind Singh9c58eba2016-09-02 16:23:06 +05303285 ghdd_ipa->stats.num_free_msg++;
3286 qdf_mem_free(buff);
3287}
3288
Govind Singh9c58eba2016-09-02 16:23:06 +05303289/**
jge62037862016-12-09 10:44:33 +08003290 * hdd_ipa_uc_send_evt() - send event to ipa
3291 * @hdd_ctx: pointer to hdd context
3292 * @type: event type
3293 * @mac_addr: pointer to mac address
3294 *
3295 * Send event to IPA driver
Govind Singh9c58eba2016-09-02 16:23:06 +05303296 *
3297 * Return: 0 - Success
3298 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003299static int hdd_ipa_uc_send_evt(struct hdd_adapter *adapter,
Yun Park6c86a662017-10-05 16:09:15 -07003300 qdf_ipa_wlan_event_t type, uint8_t *mac_addr)
Govind Singh9c58eba2016-09-02 16:23:06 +05303301{
jge62037862016-12-09 10:44:33 +08003302 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07003303 qdf_ipa_msg_meta_t meta;
3304 qdf_ipa_wlan_msg_t *msg;
Govind Singh9c58eba2016-09-02 16:23:06 +05303305 int ret = 0;
jge62037862016-12-09 10:44:33 +08003306
Yun Park6c86a662017-10-05 16:09:15 -07003307 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
3308 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
jge62037862016-12-09 10:44:33 +08003309 if (msg == NULL) {
3310 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3311 "msg allocation failed");
3312 return -ENOMEM;
3313 }
3314
Yun Park6c86a662017-10-05 16:09:15 -07003315 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
3316 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), adapter->dev->name,
jge62037862016-12-09 10:44:33 +08003317 IPA_RESOURCE_NAME_MAX);
Yun Park6c86a662017-10-05 16:09:15 -07003318 memcpy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, ETH_ALEN);
Yun Park199c2ed2017-10-02 11:24:22 -07003319 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "%s: Evt: %d",
Yun Park6c86a662017-10-05 16:09:15 -07003320 QDF_IPA_WLAN_MSG_NAME(msg), QDF_IPA_MSG_META_MSG_TYPE(&meta));
3321 ret = qdf_ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
jge62037862016-12-09 10:44:33 +08003322 if (ret) {
3323 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
3324 "%s: Evt: %d fail:%d",
Yun Park6c86a662017-10-05 16:09:15 -07003325 QDF_IPA_WLAN_MSG_NAME(msg),
3326 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
jge62037862016-12-09 10:44:33 +08003327 qdf_mem_free(msg);
3328 return ret;
3329 }
3330
3331 hdd_ipa->stats.num_send_msg++;
3332
3333 return ret;
3334}
3335
3336/**
3337 * hdd_ipa_uc_disconnect_client() - send client disconnect event
3338 * @hdd_ctx: pointer to hdd adapter
3339 *
3340 * Send disconnect client event to IPA driver during SSR
3341 *
3342 * Return: 0 - Success
3343 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003344static int hdd_ipa_uc_disconnect_client(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003345{
3346 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3347 int ret = 0;
Govind Singh9c58eba2016-09-02 16:23:06 +05303348 int i;
3349
Yun Park199c2ed2017-10-02 11:24:22 -07003350 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Govind Singh9c58eba2016-09-02 16:23:06 +05303351 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003352 if (qdf_is_macaddr_broadcast(&adapter->sta_info[i].sta_mac))
Govind Singh9c58eba2016-09-02 16:23:06 +05303353 continue;
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003354 if ((adapter->sta_info[i].in_use) &&
3355 (!adapter->sta_info[i].is_deauth_in_progress) &&
jge62037862016-12-09 10:44:33 +08003356 hdd_ipa->sap_num_connected_sta) {
3357 hdd_ipa_uc_send_evt(adapter, WLAN_CLIENT_DISCONNECT,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07003358 adapter->sta_info[i].sta_mac.bytes);
jge62037862016-12-09 10:44:33 +08003359 hdd_ipa->sap_num_connected_sta--;
Govind Singh9c58eba2016-09-02 16:23:06 +05303360 }
3361 }
Yun Park199c2ed2017-10-02 11:24:22 -07003362 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07003363 hdd_ipa->sap_num_connected_sta);
Govind Singh9c58eba2016-09-02 16:23:06 +05303364
3365 return ret;
3366}
3367
3368/**
jge62037862016-12-09 10:44:33 +08003369 * hdd_ipa_uc_disconnect_ap() - send ap disconnect event
3370 * @hdd_ctx: pointer to hdd adapter
3371 *
3372 * Send disconnect ap event to IPA driver during SSR
Govind Singh9c58eba2016-09-02 16:23:06 +05303373 *
3374 * Return: 0 - Success
3375 */
jge62037862016-12-09 10:44:33 +08003376
Jeff Johnson49d45e62017-08-29 14:30:42 -07003377static int hdd_ipa_uc_disconnect_ap(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003378{
3379 int ret = 0;
3380
Yun Park199c2ed2017-10-02 11:24:22 -07003381 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003382 if (adapter->ipa_context) {
jge62037862016-12-09 10:44:33 +08003383 hdd_ipa_uc_send_evt(adapter, WLAN_AP_DISCONNECT,
3384 adapter->dev->dev_addr);
Yun Parkfec73dc2017-09-06 10:40:07 -07003385 }
Yun Park199c2ed2017-10-02 11:24:22 -07003386 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
jge62037862016-12-09 10:44:33 +08003387
3388 return ret;
3389}
3390
jge62037862016-12-09 10:44:33 +08003391/**
3392 * hdd_ipa_uc_disconnect_sta() - send sta disconnect event
3393 * @hdd_ctx: pointer to hdd adapter
3394 *
3395 * Send disconnect sta event to IPA driver during SSR
3396 *
3397 * Return: 0 - Success
3398 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07003399static int hdd_ipa_uc_disconnect_sta(struct hdd_adapter *adapter)
jge62037862016-12-09 10:44:33 +08003400{
Jeff Johnsond377dce2017-10-04 10:32:42 -07003401 struct hdd_station_ctx *sta_ctx;
jge62037862016-12-09 10:44:33 +08003402 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3403 int ret = 0;
3404
Yun Park199c2ed2017-10-02 11:24:22 -07003405 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08003406 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
jge62037862016-12-09 10:44:33 +08003407 hdd_ipa->sta_connected) {
Jeff Johnsond377dce2017-10-04 10:32:42 -07003408 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
jge62037862016-12-09 10:44:33 +08003409 hdd_ipa_uc_send_evt(adapter, WLAN_STA_DISCONNECT,
Jeff Johnsond377dce2017-10-04 10:32:42 -07003410 sta_ctx->conn_info.bssId.bytes);
jge62037862016-12-09 10:44:33 +08003411 }
Yun Park199c2ed2017-10-02 11:24:22 -07003412 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
jge62037862016-12-09 10:44:33 +08003413
3414 return ret;
3415}
jge62037862016-12-09 10:44:33 +08003416
3417/**
3418 * hdd_ipa_uc_disconnect() - send disconnect ipa event
3419 * @hdd_ctx: pointer to hdd context
3420 *
3421 * Send disconnect event to IPA driver during SSR
3422 *
3423 * Return: 0 - Success
3424 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003425static int hdd_ipa_uc_disconnect(struct hdd_context *hdd_ctx)
Govind Singh9c58eba2016-09-02 16:23:06 +05303426{
3427 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3428 QDF_STATUS status;
Jeff Johnson49d45e62017-08-29 14:30:42 -07003429 struct hdd_adapter *adapter;
Govind Singh9c58eba2016-09-02 16:23:06 +05303430 int ret = 0;
3431
Govind Singh9c58eba2016-09-02 16:23:06 +05303432 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
3433 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Jeff Johnson57eb2732017-10-02 11:40:20 -07003434 adapter = adapter_node->adapter;
jge62037862016-12-09 10:44:33 +08003435 if (adapter->device_mode == QDF_SAP_MODE) {
3436 hdd_ipa_uc_disconnect_client(adapter);
3437 hdd_ipa_uc_disconnect_ap(adapter);
3438 } else if (adapter->device_mode == QDF_STA_MODE) {
3439 hdd_ipa_uc_disconnect_sta(adapter);
3440 }
3441
Govind Singh9c58eba2016-09-02 16:23:06 +05303442 status = hdd_get_next_adapter(
3443 hdd_ctx, adapter_node, &next);
3444 adapter_node = next;
3445 }
3446
3447 return ret;
3448}
3449
3450/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003451 * __hdd_ipa_uc_ssr_deinit() - handle ipa deinit for SSR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452 *
3453 * Deinit basic IPA UC host side to be in sync reloaded FW during
3454 * SSR
3455 *
3456 * Return: 0 - Success
3457 */
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003458static int __hdd_ipa_uc_ssr_deinit(void)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459{
3460 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3461 int idx;
3462 struct hdd_ipa_iface_context *iface_context;
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003463 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464
Yun Park199c2ed2017-10-02 11:24:22 -07003465 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003466
Arun Khandavallicc544b32017-01-30 19:52:16 +05303467 if (!hdd_ipa)
3468 return 0;
3469
3470 hdd_ctx = hdd_ipa->hdd_ctx;
3471 if (!hdd_ipa_uc_is_enabled(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 return 0;
3473
jge62037862016-12-09 10:44:33 +08003474 /* send disconnect to ipa driver */
Arun Khandavallicc544b32017-01-30 19:52:16 +05303475 hdd_ipa_uc_disconnect(hdd_ctx);
jge62037862016-12-09 10:44:33 +08003476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 /* Clean up HDD IPA interfaces */
3478 for (idx = 0; (hdd_ipa->num_iface > 0) &&
3479 (idx < HDD_IPA_MAX_IFACE); idx++) {
3480 iface_context = &hdd_ipa->iface_context[idx];
Manikandan Mohaneab58242017-02-17 14:21:53 -08003481 if (iface_context->adapter && iface_context->adapter->magic ==
3482 WLAN_HDD_ADAPTER_MAGIC)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 hdd_ipa_cleanup_iface(iface_context);
3484 }
Manikandan Mohaneab58242017-02-17 14:21:53 -08003485 hdd_ipa->num_iface = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 /* After SSR, wlan driver reloads FW again. But we need to protect
3487 * IPA submodule during SSR transient state. So deinit basic IPA
3488 * UC host side to be in sync with reloaded FW during SSR
3489 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303491 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 for (idx = 0; idx < WLAN_MAX_STA_COUNT; idx++) {
3493 hdd_ipa->assoc_stas_map[idx].is_reserved = false;
3494 hdd_ipa->assoc_stas_map[idx].sta_id = 0xFF;
3495 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303496 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003497
Guolei Bianca144d82016-11-10 11:07:42 +08003498 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
3499 hdd_ipa_uc_sta_reset_sta_connected(hdd_ipa);
3500
Manikandan Mohan2e803a02017-02-14 14:57:53 -08003501 for (idx = 0; idx < HDD_IPA_UC_OPCODE_MAX; idx++) {
3502 cancel_work_sync(&hdd_ipa->uc_op_work[idx].work);
3503 qdf_mem_free(hdd_ipa->uc_op_work[idx].msg);
3504 hdd_ipa->uc_op_work[idx].msg = NULL;
3505 }
Yun Parkfec73dc2017-09-06 10:40:07 -07003506
Yun Park199c2ed2017-10-02 11:24:22 -07003507 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 return 0;
3509}
3510
3511/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003512 * hdd_ipa_uc_ssr_deinit() - SSR wrapper for __hdd_ipa_uc_ssr_deinit
3513 *
3514 * Deinit basic IPA UC host side to be in sync reloaded FW during
3515 * SSR
3516 *
3517 * Return: 0 - Success
3518 */
3519int hdd_ipa_uc_ssr_deinit(void)
3520{
3521 int ret;
3522
3523 cds_ssr_protect(__func__);
3524 ret = __hdd_ipa_uc_ssr_deinit();
3525 cds_ssr_unprotect(__func__);
3526
3527 return ret;
3528}
3529
3530/**
3531 * __hdd_ipa_uc_ssr_reinit() - handle ipa reinit after SSR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 *
3533 * Init basic IPA UC host side to be in sync with reloaded FW after
3534 * SSR to resume IPA UC operations
3535 *
3536 * Return: 0 - Success
3537 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003538static int __hdd_ipa_uc_ssr_reinit(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540
Arun Khandavallicc544b32017-01-30 19:52:16 +05303541 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
3542 int i;
3543 struct hdd_ipa_iface_context *iface_context = NULL;
Arun Khandavallicc544b32017-01-30 19:52:16 +05303544
Yun Park199c2ed2017-10-02 11:24:22 -07003545 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07003546
Arun Khandavallicc544b32017-01-30 19:52:16 +05303547 if (!hdd_ipa || !hdd_ipa_uc_is_enabled(hdd_ctx))
3548 return 0;
3549
Arun Khandavallicc544b32017-01-30 19:52:16 +05303550 /* Create the interface context */
3551 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
3552 iface_context = &hdd_ipa->iface_context[i];
3553 iface_context->hdd_ipa = hdd_ipa;
3554 iface_context->cons_client =
3555 hdd_ipa_adapter_2_client[i].cons_client;
3556 iface_context->prod_client =
3557 hdd_ipa_adapter_2_client[i].prod_client;
3558 iface_context->iface_id = i;
3559 iface_context->adapter = NULL;
3560 }
3561 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
3562 hdd_ipa->vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
3563 hdd_ipa->vdev_offload_enabled[i] = false;
3564 }
3565
3566 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
3567 hdd_ipa->resource_loading = false;
3568 hdd_ipa->resource_unloading = false;
3569 hdd_ipa->sta_connected = 0;
3570 hdd_ipa->ipa_pipes_down = true;
3571 hdd_ipa->uc_loaded = true;
Arun Khandavallicc544b32017-01-30 19:52:16 +05303572 }
3573
Yun Park199c2ed2017-10-02 11:24:22 -07003574 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003575 return 0;
3576}
Leo Chang3bc8fed2015-11-13 10:59:47 -08003577
3578/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003579 * hdd_ipa_uc_ssr_reinit() - SSR wrapper for __hdd_ipa_uc_ssr_reinit
3580 *
3581 * Init basic IPA UC host side to be in sync with reloaded FW after
3582 * SSR to resume IPA UC operations
3583 *
3584 * Return: 0 - Success
3585 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003586int hdd_ipa_uc_ssr_reinit(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003587{
3588 int ret;
3589
3590 cds_ssr_protect(__func__);
Arun Khandavallicc544b32017-01-30 19:52:16 +05303591 ret = __hdd_ipa_uc_ssr_reinit(hdd_ctx);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003592 cds_ssr_unprotect(__func__);
3593
3594 return ret;
3595}
3596
3597/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
3599 * @work: scheduled work
3600 *
3601 * When IPA resources are released in hdd_ipa_rm_try_release() we do
3602 * not want to immediately release the wake lock since the system
3603 * would then potentially try to suspend when there is a healthy data
3604 * rate. Deferred work is scheduled and this function handles the
3605 * work. When this function is called, if the IPA resource is still
3606 * released then we release the wake lock.
3607 *
3608 * Return: None
3609 */
3610static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
3611{
3612 struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
3613 struct hdd_ipa_priv,
3614 wake_lock_work);
3615
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303616 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003617
3618 if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
3619 goto end;
3620
3621 hdd_ipa->wake_lock_released = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303622 qdf_wake_lock_release(&hdd_ipa->wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003623 WIFI_POWER_EVENT_WAKELOCK_IPA);
3624
3625end:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303626 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627}
3628
3629/**
3630 * hdd_ipa_rm_request() - Request resource from IPA
3631 * @hdd_ipa: Global HDD IPA context
3632 *
3633 * Return: 0 on success, negative errno on error
3634 */
3635static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa)
3636{
3637 int ret = 0;
3638
3639 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3640 return 0;
3641
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303642 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643
3644 switch (hdd_ipa->rm_state) {
3645 case HDD_IPA_RM_GRANTED:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303646 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003647 return 0;
3648 case HDD_IPA_RM_GRANT_PENDING:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303649 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 return -EINPROGRESS;
3651 case HDD_IPA_RM_RELEASED:
3652 hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
3653 break;
3654 }
3655
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303656 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003657
Yun Park6c86a662017-10-05 16:09:15 -07003658 ret = qdf_ipa_rm_inactivity_timer_request_resource(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 IPA_RM_RESOURCE_WLAN_PROD);
3660
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303661 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 if (ret == 0) {
3663 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
3664 hdd_ipa->stats.num_rm_grant_imm++;
3665 }
3666
3667 cancel_delayed_work(&hdd_ipa->wake_lock_work);
3668 if (hdd_ipa->wake_lock_released) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303669 qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670 WIFI_POWER_EVENT_WAKELOCK_IPA);
3671 hdd_ipa->wake_lock_released = false;
3672 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303673 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674
3675 return ret;
3676}
3677
3678/**
3679 * hdd_ipa_rm_try_release() - Attempt to release IPA resource
3680 * @hdd_ipa: Global HDD IPA context
3681 *
3682 * Return: 0 if resources released, negative errno otherwise
3683 */
3684static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
3685{
3686 int ret = 0;
3687
3688 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3689 return 0;
3690
3691 if (atomic_read(&hdd_ipa->tx_ref_cnt))
3692 return -EAGAIN;
3693
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303694 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003695
Nirav Shahcbc6d722016-03-01 16:24:53 +05303696 if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303697 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003698 return -EAGAIN;
3699 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303700 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303702 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003703 switch (hdd_ipa->rm_state) {
3704 case HDD_IPA_RM_GRANTED:
3705 break;
3706 case HDD_IPA_RM_GRANT_PENDING:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303707 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003708 return -EINPROGRESS;
3709 case HDD_IPA_RM_RELEASED:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303710 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711 return 0;
3712 }
3713
3714 /* IPA driver returns immediately so set the state here to avoid any
3715 * race condition.
3716 */
3717 hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
3718 hdd_ipa->stats.num_rm_release++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303719 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003720
Yun Park6c86a662017-10-05 16:09:15 -07003721 ret = qdf_ipa_rm_inactivity_timer_release_resource(
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07003722 IPA_RM_RESOURCE_WLAN_PROD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003723
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303724 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725 if (unlikely(ret != 0)) {
3726 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
3727 WARN_ON(1);
Yun Park199c2ed2017-10-02 11:24:22 -07003728 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
3729 "ipa_rm_inactivity_timer_release_resource returnied fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003730 }
3731
3732 /*
3733 * If wake_lock is released immediately, kernel would try to suspend
3734 * immediately as well, Just avoid ping-pong between suspend-resume
3735 * while there is healthy amount of data transfer going on by
3736 * releasing the wake_lock after some delay.
3737 */
3738 schedule_delayed_work(&hdd_ipa->wake_lock_work,
3739 msecs_to_jiffies
3740 (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
3741
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303742 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743
3744 return ret;
3745}
3746
3747/**
3748 * hdd_ipa_rm_notify() - IPA resource manager notifier callback
3749 * @user_data: user data registered with IPA
3750 * @event: the IPA resource manager event that occurred
3751 * @data: the data associated with the event
3752 *
3753 * Return: None
3754 */
Yun Park6c86a662017-10-05 16:09:15 -07003755static void hdd_ipa_rm_notify(void *user_data, qdf_ipa_rm_event_t event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003756 unsigned long data)
3757{
3758 struct hdd_ipa_priv *hdd_ipa = user_data;
3759
3760 if (unlikely(!hdd_ipa))
3761 return;
3762
3763 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3764 return;
3765
Srinivas Girigowda97852372017-03-06 16:52:59 -08003766 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767
3768 switch (event) {
3769 case IPA_RM_RESOURCE_GRANTED:
3770 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
3771 /* RM Notification comes with ISR context
3772 * it should be serialized into work queue to avoid
3773 * ISR sleep problem
3774 */
3775 hdd_ipa->uc_rm_work.event = event;
3776 schedule_work(&hdd_ipa->uc_rm_work.work);
3777 break;
3778 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303779 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780 hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05303781 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 hdd_ipa->stats.num_rm_grant++;
3783 break;
3784
3785 case IPA_RM_RESOURCE_RELEASED:
Srinivas Girigowda97852372017-03-06 16:52:59 -08003786 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787 hdd_ipa->resource_unloading = false;
3788 break;
3789
3790 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303791 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 break;
3793 }
3794}
3795
3796/**
3797 * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
3798 *
3799 * Callback function registered with IPA that is called when IPA wants
3800 * to release the WLAN consumer resource
3801 *
3802 * Return: 0 if the request is granted, negative errno otherwise
3803 */
3804static int hdd_ipa_rm_cons_release(void)
3805{
3806 return 0;
3807}
3808
3809/**
3810 * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
3811 *
3812 * Callback function registered with IPA that is called when IPA wants
3813 * to access the WLAN consumer resource
3814 *
3815 * Return: 0 if the request is granted, negative errno otherwise
3816 */
3817static int hdd_ipa_rm_cons_request(void)
3818{
Yun Park4d8b60a2015-10-22 13:59:32 -07003819 int ret = 0;
3820
3821 if (ghdd_ipa->resource_loading) {
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 loading in progress");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003824 ghdd_ipa->pending_cons_req = true;
Yun Park4d8b60a2015-10-22 13:59:32 -07003825 ret = -EINPROGRESS;
3826 } else if (ghdd_ipa->resource_unloading) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303827 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
Yun Parkb4f591d2017-03-29 15:51:01 -07003828 "IPA resource unloading in progress");
Yun Park4d8b60a2015-10-22 13:59:32 -07003829 ghdd_ipa->pending_cons_req = true;
3830 ret = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 }
Yun Park4d8b60a2015-10-22 13:59:32 -07003832
3833 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834}
3835
3836/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003837 * __hdd_ipa_set_perf_level() - Set IPA performance level
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838 * @hdd_ctx: Global HDD context
3839 * @tx_packets: Number of packets transmitted in the last sample period
3840 * @rx_packets: Number of packets received in the last sample period
3841 *
3842 * Return: 0 on success, negative errno on error
3843 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07003844static int __hdd_ipa_set_perf_level(struct hdd_context *hdd_ctx,
3845 uint64_t tx_packets,
3846 uint64_t rx_packets)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847{
3848 uint32_t next_cons_bw, next_prod_bw;
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003849 struct hdd_ipa_priv *hdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07003850 qdf_ipa_rm_perf_profile_t profile;
Yun Parkb4f591d2017-03-29 15:51:01 -07003851 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852 int ret;
3853
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003854 if (wlan_hdd_validate_context(hdd_ctx))
3855 return 0;
3856
3857 hdd_ipa = hdd_ctx->hdd_ipa;
3858
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 if ((!hdd_ipa_is_enabled(hdd_ctx)) ||
3860 (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)))
3861 return 0;
3862
3863 memset(&profile, 0, sizeof(profile));
3864
3865 if (tx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2))
3866 next_cons_bw = hdd_ctx->config->IpaHighBandwidthMbps;
3867 else if (tx_packets >
3868 (hdd_ctx->config->busBandwidthMediumThreshold / 2))
3869 next_cons_bw = hdd_ctx->config->IpaMediumBandwidthMbps;
3870 else
3871 next_cons_bw = hdd_ctx->config->IpaLowBandwidthMbps;
3872
3873 if (rx_packets > (hdd_ctx->config->busBandwidthHighThreshold / 2))
3874 next_prod_bw = hdd_ctx->config->IpaHighBandwidthMbps;
3875 else if (rx_packets >
3876 (hdd_ctx->config->busBandwidthMediumThreshold / 2))
3877 next_prod_bw = hdd_ctx->config->IpaMediumBandwidthMbps;
3878 else
3879 next_prod_bw = hdd_ctx->config->IpaLowBandwidthMbps;
3880
Yun Parkec845302016-12-15 09:22:57 -08003881 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 "CONS perf curr: %d, next: %d",
3883 hdd_ipa->curr_cons_bw, next_cons_bw);
Yun Parkec845302016-12-15 09:22:57 -08003884 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 "PROD perf curr: %d, next: %d",
3886 hdd_ipa->curr_prod_bw, next_prod_bw);
3887
3888 if (hdd_ipa->curr_cons_bw != next_cons_bw) {
Yun Parkb187d542016-11-14 18:10:04 -08003889 hdd_debug("Requesting CONS perf curr: %d, next: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003890 hdd_ipa->curr_cons_bw, next_cons_bw);
Yun Parkb4f591d2017-03-29 15:51:01 -07003891 ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_CONS,
3892 next_cons_bw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08003894 hdd_err("RM CONS set perf profile failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895
3896 return ret;
3897 }
3898 hdd_ipa->curr_cons_bw = next_cons_bw;
3899 hdd_ipa->stats.num_cons_perf_req++;
3900 }
3901
3902 if (hdd_ipa->curr_prod_bw != next_prod_bw) {
Yun Parkb187d542016-11-14 18:10:04 -08003903 hdd_debug("Requesting PROD perf curr: %d, next: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003904 hdd_ipa->curr_prod_bw, next_prod_bw);
Yun Parkb4f591d2017-03-29 15:51:01 -07003905 ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_PROD,
3906 next_prod_bw);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08003908 hdd_err("RM PROD set perf profile failed: %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003909 return ret;
3910 }
3911 hdd_ipa->curr_prod_bw = next_prod_bw;
3912 hdd_ipa->stats.num_prod_perf_req++;
3913 }
3914
3915 return 0;
3916}
3917
3918/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003919 * hdd_ipa_set_perf_level() - SSR wrapper for __hdd_ipa_set_perf_level
3920 * @hdd_ctx: Global HDD context
3921 * @tx_packets: Number of packets transmitted in the last sample period
3922 * @rx_packets: Number of packets received in the last sample period
3923 *
3924 * Return: 0 on success, negative errno on error
3925 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07003926int hdd_ipa_set_perf_level(struct hdd_context *hdd_ctx, uint64_t tx_packets,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07003927 uint64_t rx_packets)
3928{
3929 int ret;
3930
3931 cds_ssr_protect(__func__);
3932 ret = __hdd_ipa_set_perf_level(hdd_ctx, tx_packets, rx_packets);
3933 cds_ssr_unprotect(__func__);
3934
3935 return ret;
3936}
3937
3938/**
Rajeev Kumar217f2172016-01-06 18:11:55 -08003939 * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
3940 * @work: struct work_struct
3941 * @work_handler: work_handler
3942 *
3943 * Return: none
3944 */
Rajeev Kumar217f2172016-01-06 18:11:55 -08003945static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
3946 work_func_t work_handler)
3947{
3948 INIT_WORK(work, work_handler);
3949}
Rajeev Kumar217f2172016-01-06 18:11:55 -08003950
3951/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003952 * hdd_ipa_setup_rm() - Setup IPA resource management
3953 * @hdd_ipa: Global HDD IPA context
3954 *
3955 * Return: 0 on success, negative errno on error
3956 */
3957static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa)
3958{
Yun Park6c86a662017-10-05 16:09:15 -07003959 qdf_ipa_rm_create_params_t create_params = { 0 };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003960 int ret;
3961
3962 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
3963 return 0;
3964
Rajeev Kumar217f2172016-01-06 18:11:55 -08003965 hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
3966 hdd_ipa_uc_rm_notify_defer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003967 memset(&create_params, 0, sizeof(create_params));
Yun Park6c86a662017-10-05 16:09:15 -07003968 QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
3969 IPA_RM_RESOURCE_WLAN_PROD;
3970 QDF_IPA_RM_CREATE_PARAMS_USER_DATA(&create_params) =
3971 hdd_ipa;
3972 QDF_IPA_RM_CREATE_PARAMS_NOTIFY_CB(&create_params) =
3973 hdd_ipa_rm_notify;
3974 QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
3975 IPA_VOLTAGE_SVS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003976
Yun Park6c86a662017-10-05 16:09:15 -07003977 ret = qdf_ipa_rm_create_resource(&create_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303979 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980 "Create RM resource failed: %d", ret);
3981 goto setup_rm_fail;
3982 }
3983
3984 memset(&create_params, 0, sizeof(create_params));
Yun Park6c86a662017-10-05 16:09:15 -07003985 QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
3986 IPA_RM_RESOURCE_WLAN_CONS;
3987 QDF_IPA_RM_CREATE_PARAMS_REQUEST_RESOURCE(&create_params) =
3988 hdd_ipa_rm_cons_request;
3989 QDF_IPA_RM_CREATE_PARAMS_RELEASE_RESOURCE(&create_params) =
3990 hdd_ipa_rm_cons_release;
3991 QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
3992 IPA_VOLTAGE_SVS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003993
Yun Park6c86a662017-10-05 16:09:15 -07003994 ret = qdf_ipa_rm_create_resource(&create_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05303996 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003997 "Create RM CONS resource failed: %d", ret);
3998 goto delete_prod;
3999 }
4000
4001 ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
4002 IPA_RM_RESOURCE_APPS_CONS);
4003
Yun Park6c86a662017-10-05 16:09:15 -07004004 ret = qdf_ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
4005 HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004006 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304007 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 ret);
4009 goto timer_init_failed;
4010 }
4011
4012 /* Set the lowest bandwidth to start with */
4013 ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
4014
4015 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304016 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017 "Set perf level failed: %d", ret);
4018 goto set_perf_failed;
4019 }
4020
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304021 qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
4023 hdd_ipa_wake_lock_timer_func);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304024 qdf_spinlock_create(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004025 hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
4026 hdd_ipa->wake_lock_released = true;
4027 atomic_set(&hdd_ipa->tx_ref_cnt, 0);
4028
4029 return ret;
4030
4031set_perf_failed:
4032 ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
4033
4034timer_init_failed:
4035 ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
4036
4037delete_prod:
4038 ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
4039
4040setup_rm_fail:
4041 return ret;
4042}
4043
4044/**
4045 * hdd_ipa_destroy_rm_resource() - Destroy IPA resources
4046 * @hdd_ipa: Global HDD IPA context
4047 *
4048 * Destroys all resources associated with the IPA resource manager
4049 *
4050 * Return: None
4051 */
4052static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa)
4053{
4054 int ret;
4055
4056 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4057 return;
4058
4059 cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304060 qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062 cancel_work_sync(&hdd_ipa->uc_rm_work.work);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304063 qdf_spinlock_destroy(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064
4065 ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
4066
Yun Park6c86a662017-10-05 16:09:15 -07004067 ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
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 PROD resource delete failed %d", ret);
4071
Yun Park6c86a662017-10-05 16:09:15 -07004072 ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 if (ret)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304074 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 "RM CONS resource delete failed %d", ret);
4076}
4077
tfyu0380a972017-07-13 18:19:37 +08004078#ifdef QCA_CONFIG_SMP
4079static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
4080{
4081 return netif_rx_ni(skb);
4082}
4083#else
4084static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
4085{
4086 struct iphdr *ip_h;
4087 static atomic_t softirq_mitigation_cntr =
4088 ATOMIC_INIT(IPA_WLAN_RX_SOFTIRQ_THRESH);
4089 int result;
4090
4091 ip_h = (struct iphdr *)(skb->data);
4092 if ((skb->protocol == htons(ETH_P_IP)) &&
4093 (ip_h->protocol == IPPROTO_ICMP)) {
4094 result = netif_rx_ni(skb);
4095 } else {
4096 /* Call netif_rx_ni for every IPA_WLAN_RX_SOFTIRQ_THRESH packets
4097 * to avoid excessive softirq's.
4098 */
4099 if (atomic_dec_and_test(&softirq_mitigation_cntr)) {
4100 result = netif_rx_ni(skb);
4101 atomic_set(&softirq_mitigation_cntr,
4102 IPA_WLAN_RX_SOFTIRQ_THRESH);
4103 } else {
4104 result = netif_rx(skb);
4105 }
4106 }
4107
4108 return result;
4109}
4110#endif
4111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112/**
4113 * hdd_ipa_send_skb_to_network() - Send skb to kernel
4114 * @skb: network buffer
4115 * @adapter: network adapter
4116 *
4117 * Called when a network buffer is received which should not be routed
4118 * to the IPA module.
4119 *
4120 * Return: None
4121 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304122static void hdd_ipa_send_skb_to_network(qdf_nbuf_t skb,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004123 struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124{
tfyu0380a972017-07-13 18:19:37 +08004125 int result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
4127 unsigned int cpu_index;
4128
4129 if (!adapter || adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07004130 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Invalid adapter: 0x%pK",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004131 adapter);
Yun Park46255682017-10-09 15:56:34 -07004132 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004133 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 return;
4135 }
4136
Prashanth Bhatta9e143052015-12-04 11:56:47 -08004137 if (cds_is_driver_unloading()) {
Yun Park46255682017-10-09 15:56:34 -07004138 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004139 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 return;
4141 }
4142
4143 skb->destructor = hdd_ipa_uc_rt_debug_destructor;
4144 skb->dev = adapter->dev;
4145 skb->protocol = eth_type_trans(skb, skb->dev);
4146 skb->ip_summed = CHECKSUM_NONE;
4147
4148 cpu_index = wlan_hdd_get_cpu();
4149
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004150 ++adapter->hdd_stats.tx_rx_stats.rx_packets[cpu_index];
tfyu0380a972017-07-13 18:19:37 +08004151 result = hdd_ipa_aggregated_rx_ind(skb);
4152 if (result == NET_RX_SUCCESS)
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004153 ++adapter->hdd_stats.tx_rx_stats.rx_delivered[cpu_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004154 else
Jeff Johnson6ced42c2017-10-20 12:48:11 -07004155 ++adapter->hdd_stats.tx_rx_stats.rx_refused[cpu_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156
Yun Park46255682017-10-09 15:56:34 -07004157 hdd_ipa->ipa_rx_net_send_count++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158}
4159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004160/**
Leo Chang69c39692016-10-12 20:11:12 -07004161 * hdd_ipa_forward() - handle packet forwarding to wlan tx
4162 * @hdd_ipa: pointer to hdd ipa context
4163 * @adapter: network adapter
4164 * @skb: data pointer
4165 *
4166 * if exception packet has set forward bit, copied new packet should be
4167 * forwarded to wlan tx. if wlan subsystem is in suspend state, packet should
4168 * put into pm queue and tx procedure will be differed
4169 *
4170 * Return: None
4171 */
Jeff Johnson414f7ea2016-10-19 18:50:02 -07004172static void hdd_ipa_forward(struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004173 struct hdd_adapter *adapter, qdf_nbuf_t skb)
Leo Chang69c39692016-10-12 20:11:12 -07004174{
Leo Chang69c39692016-10-12 20:11:12 -07004175 struct hdd_ipa_pm_tx_cb *pm_tx_cb;
4176
Leo Chang69c39692016-10-12 20:11:12 -07004177 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Yun Park01deb2c2017-06-14 15:21:44 -07004178
4179 /* Set IPA ownership for intra-BSS Tx packets to avoid skb_orphan */
4180 qdf_nbuf_ipa_owned_set(skb);
4181
Yun Park46255682017-10-09 15:56:34 -07004182 /* WLAN subsystem is in suspend, put in queue */
Leo Chang69c39692016-10-12 20:11:12 -07004183 if (hdd_ipa->suspended) {
4184 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Yun Park46255682017-10-09 15:56:34 -07004185 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
4186 "Tx in suspend, put in queue");
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004187 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
4188 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Leo Chang69c39692016-10-12 20:11:12 -07004189 pm_tx_cb->exception = true;
4190 pm_tx_cb->adapter = adapter;
4191 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004192 qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb);
Leo Chang69c39692016-10-12 20:11:12 -07004193 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
4194 hdd_ipa->stats.num_tx_queued++;
4195 } else {
4196 /* Resume, put packet into WLAN TX */
4197 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004198 if (hdd_softap_hard_start_xmit(skb, adapter->dev)) {
Leo Chang69c39692016-10-12 20:11:12 -07004199 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07004200 "packet Tx fail");
Yun Parkb187d542016-11-14 18:10:04 -08004201 hdd_ipa->stats.num_tx_fwd_err++;
Leo Chang69c39692016-10-12 20:11:12 -07004202 } else {
Yun Parkb187d542016-11-14 18:10:04 -08004203 hdd_ipa->stats.num_tx_fwd_ok++;
Leo Chang69c39692016-10-12 20:11:12 -07004204 }
4205 }
4206}
4207
4208/**
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004209 * hdd_ipa_intrabss_forward() - Forward intra bss packets.
4210 * @hdd_ipa: pointer to HDD IPA struct
4211 * @adapter: hdd adapter pointer
4212 * @desc: Firmware descriptor
4213 * @skb: Data buffer
4214 *
4215 * Return:
4216 * HDD_IPA_FORWARD_PKT_NONE
4217 * HDD_IPA_FORWARD_PKT_DISCARD
4218 * HDD_IPA_FORWARD_PKT_LOCAL_STACK
4219 *
4220 */
4221
4222static enum hdd_ipa_forward_type hdd_ipa_intrabss_forward(
4223 struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07004224 struct hdd_adapter *adapter,
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004225 uint8_t desc,
4226 qdf_nbuf_t skb)
4227{
4228 int ret = HDD_IPA_FORWARD_PKT_NONE;
Yun Park0dad1002017-07-14 14:57:01 -07004229 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4230 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004231
4232 if ((desc & FW_RX_DESC_FORWARD_M)) {
Poddar, Siddarth8e3ee2d2016-11-29 20:17:01 +05304233 if (!ol_txrx_fwd_desc_thresh_check(
Yun Park0dad1002017-07-14 14:57:01 -07004234 (struct ol_txrx_vdev_t *)cdp_get_vdev_from_vdev_id(soc,
4235 (struct cdp_pdev *)pdev,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004236 adapter->session_id))) {
Poddar, Siddarth8e3ee2d2016-11-29 20:17:01 +05304237 /* Drop the packet*/
4238 hdd_ipa->stats.num_tx_fwd_err++;
4239 kfree_skb(skb);
4240 ret = HDD_IPA_FORWARD_PKT_DISCARD;
4241 return ret;
4242 }
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004243 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
4244 "Forward packet to Tx (fw_desc=%d)", desc);
4245 hdd_ipa->ipa_tx_forward++;
4246
4247 if ((desc & FW_RX_DESC_DISCARD_M)) {
4248 hdd_ipa_forward(hdd_ipa, adapter, skb);
Yun Park46255682017-10-09 15:56:34 -07004249 hdd_ipa->ipa_rx_internal_drop_count++;
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004250 hdd_ipa->ipa_rx_discard++;
4251 ret = HDD_IPA_FORWARD_PKT_DISCARD;
4252 } else {
4253 struct sk_buff *cloned_skb = skb_clone(skb, GFP_ATOMIC);
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07004254
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004255 if (cloned_skb)
4256 hdd_ipa_forward(hdd_ipa, adapter, cloned_skb);
4257 else
4258 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Park46255682017-10-09 15:56:34 -07004259 "tx skb alloc failed");
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004260 ret = HDD_IPA_FORWARD_PKT_LOCAL_STACK;
4261 }
4262 }
4263
4264 return ret;
4265}
4266
4267/**
Yun Park637d6482016-10-05 10:51:33 -07004268 * __hdd_ipa_w2i_cb() - WLAN to IPA callback handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 * @priv: pointer to private data registered with IPA (we register a
4270 * pointer to the global IPA context)
4271 * @evt: the IPA event which triggered the callback
4272 * @data: data associated with the event
4273 *
4274 * Return: None
4275 */
Yun Park6c86a662017-10-05 16:09:15 -07004276static void __hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
4277 unsigned long data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278{
4279 struct hdd_ipa_priv *hdd_ipa = NULL;
Jeff Johnson49d45e62017-08-29 14:30:42 -07004280 struct hdd_adapter *adapter = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304281 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282 uint8_t iface_id;
4283 uint8_t session_id;
4284 struct hdd_ipa_iface_context *iface_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 uint8_t fw_desc;
Yun Parkf8d6a122016-10-11 15:49:43 -07004286 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287
4288 hdd_ipa = (struct hdd_ipa_priv *)priv;
4289
Prakash Dhavali63f8fd62016-11-14 14:40:42 -08004290 if (!hdd_ipa || wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
4291 return;
4292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 switch (evt) {
4294 case IPA_RECEIVE:
Nirav Shahcbc6d722016-03-01 16:24:53 +05304295 skb = (qdf_nbuf_t) data;
Yun Parkf8d6a122016-10-11 15:49:43 -07004296
4297 /*
4298 * When SSR is going on or driver is unloading,
4299 * just drop the packets.
4300 */
4301 status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
4302 if (0 != status) {
4303 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4304 "Invalid context: drop packet");
Yun Park46255682017-10-09 15:56:34 -07004305 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004306 kfree_skb(skb);
4307 return;
4308 }
4309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
4311 session_id = (uint8_t)skb->cb[0];
Prakash Dhavali89d406d2016-11-23 11:11:00 -08004312 iface_id = hdd_ipa->vdev_to_iface[session_id];
Srinivas Girigowda97852372017-03-06 16:52:59 -08004313 HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004314 "IPA_RECEIVE: session_id=%u, iface_id=%u",
4315 session_id, iface_id);
4316 } else {
4317 iface_id = HDD_IPA_GET_IFACE_ID(skb->data);
4318 }
4319
4320 if (iface_id >= HDD_IPA_MAX_IFACE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304321 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004322 "IPA_RECEIVE: Invalid iface_id: %u",
4323 iface_id);
Srinivas Girigowda97852372017-03-06 16:52:59 -08004324 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb187d542016-11-14 18:10:04 -08004325 "w2i -- skb",
4326 skb->data, HDD_IPA_DBG_DUMP_RX_LEN);
Yun Park46255682017-10-09 15:56:34 -07004327 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Parkf8d6a122016-10-11 15:49:43 -07004328 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 return;
4330 }
4331
4332 iface_context = &hdd_ipa->iface_context[iface_id];
4333 adapter = iface_context->adapter;
Yun Park16a78262017-02-01 12:15:03 -08004334 if (!adapter) {
4335 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4336 "IPA_RECEIVE: Adapter is NULL");
Yun Park46255682017-10-09 15:56:34 -07004337 hdd_ipa->ipa_rx_internal_drop_count++;
Yun Park16a78262017-02-01 12:15:03 -08004338 kfree_skb(skb);
4339 return;
4340 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304342 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
Yun Parkb187d542016-11-14 18:10:04 -08004343 "w2i -- skb",
4344 skb->data, HDD_IPA_DBG_DUMP_RX_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
4346 hdd_ipa->stats.num_rx_excep++;
4347 skb_pull(skb, HDD_IPA_UC_WLAN_CLD_HDR_LEN);
4348 } else {
4349 skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN);
4350 }
4351
4352 iface_context->stats.num_rx_ipa_excep++;
4353
4354 /* Disable to forward Intra-BSS Rx packets when
4355 * ap_isolate=1 in hostapd.conf
4356 */
Jeff Johnsonb9424862017-10-30 08:49:35 -07004357 if (!adapter->session.ap.disable_intrabss_fwd) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004358 /*
4359 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send
4360 * all Rx packets to IPA uC, which need to be forwarded
4361 * to other interface.
4362 * And, IPA driver will send back to WLAN host driver
4363 * through exception pipe with fw_desc field set by FW.
4364 * Here we are checking fw_desc field for FORWARD bit
4365 * set, and forward to Tx. Then copy to kernel stack
4366 * only when DISCARD bit is not set.
4367 */
4368 fw_desc = (uint8_t)skb->cb[1];
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004369 if (HDD_IPA_FORWARD_PKT_DISCARD ==
4370 hdd_ipa_intrabss_forward(hdd_ipa, adapter,
4371 fw_desc, skb))
Mahesh Kumar Kalikot Veetil221dc672015-11-06 14:27:28 -08004372 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 } else {
Srinivas Girigowda97852372017-03-06 16:52:59 -08004374 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 "Intra-BSS FWD is disabled-skip forward to Tx");
4376 }
4377
4378 hdd_ipa_send_skb_to_network(skb, adapter);
4379 break;
4380
4381 default:
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304382 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 "w2i cb wrong event: 0x%x", evt);
4384 return;
4385 }
4386}
4387
4388/**
Yun Parkf8d6a122016-10-11 15:49:43 -07004389 * hdd_ipa_w2i_cb() - SSR wrapper for __hdd_ipa_w2i_cb
4390 * @priv: pointer to private data registered with IPA (we register a
4391 * pointer to the global IPA context)
4392 * @evt: the IPA event which triggered the callback
4393 * @data: data associated with the event
4394 *
4395 * Return: None
4396 */
Yun Park6c86a662017-10-05 16:09:15 -07004397static void hdd_ipa_w2i_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Yun Parkf8d6a122016-10-11 15:49:43 -07004398 unsigned long data)
4399{
4400 cds_ssr_protect(__func__);
4401 __hdd_ipa_w2i_cb(priv, evt, data);
4402 cds_ssr_unprotect(__func__);
4403}
4404
4405/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004406 * hdd_ipa_nbuf_cb() - IPA TX complete callback
4407 * @skb: packet buffer which was transmitted
4408 *
4409 * Return: None
4410 */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304411void hdd_ipa_nbuf_cb(qdf_nbuf_t skb)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412{
4413 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07004414 qdf_ipa_rx_data_t *ipa_tx_desc;
Yun Park52b2b992016-09-22 15:49:51 -07004415 struct hdd_ipa_tx_desc *tx_desc;
4416 uint16_t id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417
Yun Park52b2b992016-09-22 15:49:51 -07004418 if (!qdf_nbuf_ipa_owned_get(skb)) {
4419 dev_kfree_skb_any(skb);
4420 return;
4421 }
4422
4423 /* Get Tx desc pointer from SKB CB */
4424 id = QDF_NBUF_CB_TX_IPA_PRIV(skb);
4425 tx_desc = hdd_ipa->tx_desc_list + id;
4426 ipa_tx_desc = tx_desc->ipa_tx_desc_ptr;
4427
4428 /* Return Tx Desc to IPA */
4429 ipa_free_skb(ipa_tx_desc);
4430
4431 /* Return to free tx desc list */
4432 qdf_spin_lock_bh(&hdd_ipa->q_lock);
4433 tx_desc->ipa_tx_desc_ptr = NULL;
4434 list_add_tail(&tx_desc->link, &hdd_ipa->free_tx_desc_head);
4435 hdd_ipa->stats.num_tx_desc_q_cnt--;
4436 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437
4438 hdd_ipa->stats.num_tx_comp_cnt++;
4439
4440 atomic_dec(&hdd_ipa->tx_ref_cnt);
4441
4442 hdd_ipa_rm_try_release(hdd_ipa);
4443}
4444
4445/**
4446 * hdd_ipa_send_pkt_to_tl() - Send an IPA packet to TL
4447 * @iface_context: interface-specific IPA context
4448 * @ipa_tx_desc: packet data descriptor
4449 *
4450 * Return: None
4451 */
4452static void hdd_ipa_send_pkt_to_tl(
4453 struct hdd_ipa_iface_context *iface_context,
Yun Park6c86a662017-10-05 16:09:15 -07004454 qdf_ipa_rx_data_t *ipa_tx_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004455{
4456 struct hdd_ipa_priv *hdd_ipa = iface_context->hdd_ipa;
Jeff Johnson49d45e62017-08-29 14:30:42 -07004457 struct hdd_adapter *adapter = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304458 qdf_nbuf_t skb;
Yun Park52b2b992016-09-22 15:49:51 -07004459 struct hdd_ipa_tx_desc *tx_desc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304461 qdf_spin_lock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 adapter = iface_context->adapter;
4463 if (!adapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304464 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN, "Interface Down");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465 ipa_free_skb(ipa_tx_desc);
4466 iface_context->stats.num_tx_drop++;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304467 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004468 hdd_ipa_rm_try_release(hdd_ipa);
4469 return;
4470 }
4471
4472 /*
4473 * During CAC period, data packets shouldn't be sent over the air so
4474 * drop all the packets here
4475 */
hqu70708ab2017-10-10 17:52:01 +08004476 if (QDF_SAP_MODE == adapter->device_mode ||
4477 QDF_P2P_GO_MODE == adapter->device_mode) {
4478 if (WLAN_HDD_GET_AP_CTX_PTR(adapter)->dfs_cac_block_tx) {
4479 ipa_free_skb(ipa_tx_desc);
4480 qdf_spin_unlock_bh(&iface_context->interface_lock);
4481 iface_context->stats.num_tx_cac_drop++;
4482 hdd_ipa_rm_try_release(hdd_ipa);
4483 return;
4484 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 }
4486
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487 ++adapter->stats.tx_packets;
4488
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304489 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490
Yun Park6c86a662017-10-05 16:09:15 -07004491 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304493 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Yun Park52b2b992016-09-22 15:49:51 -07004494
4495 /* Store IPA Tx buffer ownership into SKB CB */
Nirav Shahcbc6d722016-03-01 16:24:53 +05304496 qdf_nbuf_ipa_owned_set(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
Nirav Shahcbc6d722016-03-01 16:24:53 +05304498 qdf_nbuf_mapped_paddr_set(skb,
Yun Park6c86a662017-10-05 16:09:15 -07004499 QDF_IPA_RX_DATA_DMA_ADDR(ipa_tx_desc)
Houston Hoffman43d47fa2016-02-24 16:34:30 -08004500 + HDD_IPA_WLAN_FRAG_HEADER
4501 + HDD_IPA_WLAN_IPA_HEADER);
Yun Park6c86a662017-10-05 16:09:15 -07004502 QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc) -=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 HDD_IPA_WLAN_FRAG_HEADER + HDD_IPA_WLAN_IPA_HEADER;
4504 } else
Nirav Shahcbc6d722016-03-01 16:24:53 +05304505 qdf_nbuf_mapped_paddr_set(skb, ipa_tx_desc->dma_addr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506
Yun Park52b2b992016-09-22 15:49:51 -07004507 qdf_spin_lock_bh(&hdd_ipa->q_lock);
4508 /* get free Tx desc and assign ipa_tx_desc pointer */
4509 if (!list_empty(&hdd_ipa->free_tx_desc_head)) {
4510 tx_desc = list_first_entry(&hdd_ipa->free_tx_desc_head,
4511 struct hdd_ipa_tx_desc, link);
4512 list_del(&tx_desc->link);
4513 tx_desc->ipa_tx_desc_ptr = ipa_tx_desc;
4514 hdd_ipa->stats.num_tx_desc_q_cnt++;
4515 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
4516 /* Store Tx Desc index into SKB CB */
4517 QDF_NBUF_CB_TX_IPA_PRIV(skb) = tx_desc->id;
4518 } else {
4519 hdd_ipa->stats.num_tx_desc_error++;
4520 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
Yun Park52b2b992016-09-22 15:49:51 -07004521 ipa_free_skb(ipa_tx_desc);
4522 hdd_ipa_rm_try_release(hdd_ipa);
4523 return;
4524 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525
Yun Park6c86a662017-10-05 16:09:15 -07004526 adapter->stats.tx_bytes += QDF_IPA_RX_DATA_SKB_LEN(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004527
Leo Changfdb45c32016-10-28 11:09:23 -07004528 skb = cdp_ipa_tx_send_data_frame(cds_get_context(QDF_MODULE_ID_SOC),
Yun Park6c86a662017-10-05 16:09:15 -07004529 (struct cdp_vdev *)iface_context->tl_context,
4530 QDF_IPA_RX_DATA_SKB(ipa_tx_desc));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 if (skb) {
jiad05c1e812017-08-01 16:48:52 +08004532 qdf_nbuf_free(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533 iface_context->stats.num_tx_err++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004534 return;
4535 }
4536
4537 atomic_inc(&hdd_ipa->tx_ref_cnt);
4538
4539 iface_context->stats.num_tx++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540}
4541
4542/**
Leo Chang11545d62016-10-17 14:53:50 -07004543 * hdd_ipa_is_present() - get IPA hw status
4544 * @hdd_ctx: pointer to hdd context
4545 *
4546 * ipa_uc_reg_rdyCB is not directly designed to check
4547 * ipa hw status. This is an undocumented function which
4548 * has confirmed with IPA team.
4549 *
4550 * Return: true - ipa hw present
4551 * false - ipa hw not present
4552 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004553bool hdd_ipa_is_present(struct hdd_context *hdd_ctx)
Leo Chang11545d62016-10-17 14:53:50 -07004554{
4555 /* Check if ipa hw is enabled */
Leo Chang63d73612016-10-18 18:09:43 -07004556 if (HDD_IPA_CHECK_HW() != -EPERM)
Leo Chang11545d62016-10-17 14:53:50 -07004557 return true;
4558 else
4559 return false;
4560}
4561
4562/**
Leo Chang69c39692016-10-12 20:11:12 -07004563 * hdd_ipa_pm_flush() - flush queued packets
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 * @work: pointer to the scheduled work
4565 *
4566 * Called during PM resume to send packets to TL which were queued
4567 * while host was in the process of suspending.
4568 *
4569 * Return: None
4570 */
Leo Chang69c39692016-10-12 20:11:12 -07004571static void hdd_ipa_pm_flush(struct work_struct *work)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004572{
4573 struct hdd_ipa_priv *hdd_ipa = container_of(work,
4574 struct hdd_ipa_priv,
4575 pm_work);
4576 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304577 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004578 uint32_t dequeued = 0;
4579
Leo Chang69c39692016-10-12 20:11:12 -07004580 qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
4581 WIFI_POWER_EVENT_WAKELOCK_IPA);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304582 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Nirav Shahcbc6d722016-03-01 16:24:53 +05304583 while (((skb = qdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head))
4584 != NULL)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304585 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586
4587 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 dequeued++;
Leo Chang69c39692016-10-12 20:11:12 -07004589 if (pm_tx_cb->exception) {
Yun Park46255682017-10-09 15:56:34 -07004590 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
4591 "Flush Exception");
Govind Singh1dab23b2017-08-12 13:31:00 +05304592 if (pm_tx_cb->adapter->dev)
4593 hdd_softap_hard_start_xmit(skb,
4594 pm_tx_cb->adapter->dev);
Govind Singh02075942017-08-15 11:13:28 +05304595 else
4596 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
Leo Chang69c39692016-10-12 20:11:12 -07004597 } else {
4598 hdd_ipa_send_pkt_to_tl(pm_tx_cb->iface_context,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599 pm_tx_cb->ipa_tx_desc);
Leo Chang69c39692016-10-12 20:11:12 -07004600 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304601 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304603 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Leo Chang69c39692016-10-12 20:11:12 -07004604 qdf_wake_lock_release(&hdd_ipa->wake_lock,
4605 WIFI_POWER_EVENT_WAKELOCK_IPA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004606
4607 hdd_ipa->stats.num_tx_dequeued += dequeued;
4608 if (dequeued > hdd_ipa->stats.num_max_pm_queue)
4609 hdd_ipa->stats.num_max_pm_queue = dequeued;
4610}
4611
4612/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004613 * __hdd_ipa_i2w_cb() - IPA to WLAN callback
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 * @priv: pointer to private data registered with IPA (we register a
4615 * pointer to the interface-specific IPA context)
4616 * @evt: the IPA event which triggered the callback
4617 * @data: data associated with the event
4618 *
4619 * Return: None
4620 */
Yun Park6c86a662017-10-05 16:09:15 -07004621static void __hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
4622 unsigned long data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623{
4624 struct hdd_ipa_priv *hdd_ipa = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07004625 qdf_ipa_rx_data_t *ipa_tx_desc;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 struct hdd_ipa_iface_context *iface_context;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304627 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304629 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630
Mukul Sharma81661ae2015-10-30 20:26:02 +05304631 iface_context = (struct hdd_ipa_iface_context *)priv;
Yun Park6c86a662017-10-05 16:09:15 -07004632 ipa_tx_desc = (qdf_ipa_rx_data_t *)data;
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004633 hdd_ipa = iface_context->hdd_ipa;
4634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004635 if (evt != IPA_RECEIVE) {
Prakash Dhavali87b38e32016-11-14 16:22:53 -08004636 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Event is not IPA_RECEIVE");
4637 ipa_free_skb(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004638 iface_context->stats.num_tx_drop++;
4639 return;
4640 }
4641
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 /*
4643 * When SSR is going on or driver is unloading, just drop the packets.
4644 * During SSR, there is no use in queueing the packets as STA has to
4645 * connect back any way
4646 */
4647 status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304648 if (status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004649 ipa_free_skb(ipa_tx_desc);
4650 iface_context->stats.num_tx_drop++;
4651 return;
4652 }
4653
Yun Park6c86a662017-10-05 16:09:15 -07004654 skb = QDF_IPA_RX_DATA_SKB(ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004655
Yun Parkb187d542016-11-14 18:10:04 -08004656 HDD_IPA_DBG_DUMP(QDF_TRACE_LEVEL_DEBUG,
4657 "i2w", skb->data, HDD_IPA_DBG_DUMP_TX_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004658
4659 /*
4660 * If PROD resource is not requested here then there may be cases where
4661 * IPA hardware may be clocked down because of not having proper
4662 * dependency graph between WLAN CONS and modem PROD pipes. Adding the
4663 * workaround to request PROD resource while data is going over CONS
4664 * pipe to prevent the IPA hardware clockdown.
4665 */
4666 hdd_ipa_rm_request(hdd_ipa);
4667
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304668 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 /*
4670 * If host is still suspended then queue the packets and these will be
4671 * drained later when resume completes. When packet is arrived here and
4672 * host is suspended, this means that there is already resume is in
4673 * progress.
4674 */
4675 if (hdd_ipa->suspended) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304676 qdf_mem_set(skb->cb, sizeof(skb->cb), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004677 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
4678 pm_tx_cb->iface_context = iface_context;
4679 pm_tx_cb->ipa_tx_desc = ipa_tx_desc;
Nirav Shahcbc6d722016-03-01 16:24:53 +05304680 qdf_nbuf_queue_add(&hdd_ipa->pm_queue_head, skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 hdd_ipa->stats.num_tx_queued++;
4682
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304683 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004684 return;
4685 }
4686
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304687 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688
4689 /*
4690 * If we are here means, host is not suspended, wait for the work queue
4691 * to finish.
4692 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 flush_work(&hdd_ipa->pm_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694
4695 return hdd_ipa_send_pkt_to_tl(iface_context, ipa_tx_desc);
4696}
4697
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004698/*
4699 * hdd_ipa_i2w_cb() - SSR wrapper for __hdd_ipa_i2w_cb
4700 * @priv: pointer to private data registered with IPA (we register a
4701 * pointer to the interface-specific IPA context)
4702 * @evt: the IPA event which triggered the callback
4703 * @data: data associated with the event
4704 *
4705 * Return: None
4706 */
Yun Park6c86a662017-10-05 16:09:15 -07004707static void hdd_ipa_i2w_cb(void *priv, qdf_ipa_dp_evt_type_t evt,
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004708 unsigned long data)
4709{
4710 cds_ssr_protect(__func__);
4711 __hdd_ipa_i2w_cb(priv, evt, data);
4712 cds_ssr_unprotect(__func__);
4713}
4714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004715/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004716 * __hdd_ipa_suspend() - Suspend IPA
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 * @hdd_ctx: Global HDD context
4718 *
4719 * Return: 0 on success, negativer errno on error
4720 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004721static int __hdd_ipa_suspend(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004723 struct hdd_ipa_priv *hdd_ipa;
4724
4725 if (wlan_hdd_validate_context(hdd_ctx))
4726 return 0;
4727
4728 hdd_ipa = hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004729
4730 if (!hdd_ipa_is_enabled(hdd_ctx))
4731 return 0;
4732
4733 /*
4734 * Check if IPA is ready for suspend, If we are here means, there is
4735 * high chance that suspend would go through but just to avoid any race
4736 * condition after suspend started, these checks are conducted before
4737 * allowing to suspend.
4738 */
4739 if (atomic_read(&hdd_ipa->tx_ref_cnt))
4740 return -EAGAIN;
4741
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304742 qdf_spin_lock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004743
4744 if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304745 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 return -EAGAIN;
4747 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304748 qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004749
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304750 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004751 hdd_ipa->suspended = true;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304752 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004753
4754 return 0;
4755}
4756
4757/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004758 * hdd_ipa_suspend() - SSR wrapper for __hdd_ipa_suspend
4759 * @hdd_ctx: Global HDD context
4760 *
4761 * Return: 0 on success, negativer errno on error
4762 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004763int hdd_ipa_suspend(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004764{
4765 int ret;
4766
4767 cds_ssr_protect(__func__);
4768 ret = __hdd_ipa_suspend(hdd_ctx);
4769 cds_ssr_unprotect(__func__);
4770
4771 return ret;
4772}
4773
4774/**
4775 * __hdd_ipa_resume() - Resume IPA following suspend
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 * hdd_ctx: Global HDD context
4777 *
4778 * Return: 0 on success, negative errno on error
4779 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004780static int __hdd_ipa_resume(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781{
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004782 struct hdd_ipa_priv *hdd_ipa;
4783
4784 if (wlan_hdd_validate_context(hdd_ctx))
4785 return 0;
4786
4787 hdd_ipa = hdd_ctx->hdd_ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004788
4789 if (!hdd_ipa_is_enabled(hdd_ctx))
4790 return 0;
4791
4792 schedule_work(&hdd_ipa->pm_work);
4793
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304794 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004795 hdd_ipa->suspended = false;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05304796 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004797
4798 return 0;
4799}
4800
4801/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004802 * hdd_ipa_resume() - SSR wrapper for __hdd_ipa_resume
4803 * hdd_ctx: Global HDD context
4804 *
4805 * Return: 0 on success, negative errno on error
4806 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07004807int hdd_ipa_resume(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07004808{
4809 int ret;
4810
4811 cds_ssr_protect(__func__);
4812 ret = __hdd_ipa_resume(hdd_ctx);
4813 cds_ssr_unprotect(__func__);
4814
4815 return ret;
4816}
4817
4818/**
Yun Park52b2b992016-09-22 15:49:51 -07004819 * hdd_ipa_alloc_tx_desc_list() - Allocate IPA Tx desc list
4820 * @hdd_ipa: Global HDD IPA context
4821 *
4822 * Return: 0 on success, negative errno on error
4823 */
4824static int hdd_ipa_alloc_tx_desc_list(struct hdd_ipa_priv *hdd_ipa)
4825{
4826 int i;
4827 uint32_t max_desc_cnt;
4828 struct hdd_ipa_tx_desc *tmp_desc;
4829
Yun Parkd9c528e2017-08-30 16:34:57 -07004830 max_desc_cnt = hdd_ipa->hdd_ctx->config->IpaUcTxBufCount;
Yun Park52b2b992016-09-22 15:49:51 -07004831
4832 INIT_LIST_HEAD(&hdd_ipa->free_tx_desc_head);
4833
jiad14fe4fb2017-08-08 13:33:14 +08004834 tmp_desc = qdf_mem_malloc(sizeof(struct hdd_ipa_tx_desc) *
Yun Parkd9c528e2017-08-30 16:34:57 -07004835 max_desc_cnt);
Yun Park52b2b992016-09-22 15:49:51 -07004836
4837 if (!tmp_desc) {
4838 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Yun Parkd9c528e2017-08-30 16:34:57 -07004839 "Free Tx descriptor allocation failed");
Yun Park52b2b992016-09-22 15:49:51 -07004840 return -ENOMEM;
4841 }
4842
4843 hdd_ipa->tx_desc_list = tmp_desc;
4844
4845 qdf_spin_lock_bh(&hdd_ipa->q_lock);
Yun Parkd9c528e2017-08-30 16:34:57 -07004846 for (i = 0; i < max_desc_cnt; i++) {
Yun Park52b2b992016-09-22 15:49:51 -07004847 tmp_desc->id = i;
4848 tmp_desc->ipa_tx_desc_ptr = NULL;
4849 list_add_tail(&tmp_desc->link,
4850 &hdd_ipa->free_tx_desc_head);
4851 tmp_desc++;
4852 }
4853
4854 hdd_ipa->stats.num_tx_desc_q_cnt = 0;
4855 hdd_ipa->stats.num_tx_desc_error = 0;
4856
4857 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
4858
4859 return 0;
4860}
4861
4862/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004863 * hdd_ipa_setup_sys_pipe() - Setup all IPA Sys pipes
4864 * @hdd_ipa: Global HDD IPA context
4865 *
4866 * Return: 0 on success, negative errno on error
4867 */
4868static int hdd_ipa_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
4869{
4870 int i, ret = 0;
Yun Park6c86a662017-10-05 16:09:15 -07004871 qdf_ipa_sys_connect_params_t *ipa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872 uint32_t desc_fifo_sz;
4873
4874 /* The maximum number of descriptors that can be provided to a BAM at
4875 * once is one less than the total number of descriptors that the buffer
4876 * can contain.
4877 * If max_num_of_descriptors = (BAM_PIPE_DESCRIPTOR_FIFO_SIZE / sizeof
4878 * (SPS_DESCRIPTOR)), then (max_num_of_descriptors - 1) descriptors can
4879 * be provided at once.
4880 * Because of above requirement, one extra descriptor will be added to
4881 * make sure hardware always has one descriptor.
4882 */
4883 desc_fifo_sz = hdd_ipa->hdd_ctx->config->IpaDescSize
4884 + sizeof(struct sps_iovec);
4885
4886 /*setup TX pipes */
4887 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
4888 ipa = &hdd_ipa->sys_pipe[i].ipa_sys_params;
4889
4890 ipa->client = hdd_ipa_adapter_2_client[i].cons_client;
4891 ipa->desc_fifo_sz = desc_fifo_sz;
4892 ipa->priv = &hdd_ipa->iface_context[i];
4893 ipa->notify = hdd_ipa_i2w_cb;
4894
4895 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
4896 ipa->ipa_ep_cfg.hdr.hdr_len =
4897 HDD_IPA_UC_WLAN_TX_HDR_LEN;
4898 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
4899 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
4900 ipa->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
4901 ipa->ipa_ep_cfg.hdr.hdr_additional_const_len =
4902 HDD_IPA_UC_WLAN_8023_HDR_SIZE;
4903 ipa->ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
4904 } else {
4905 ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_TX_HDR_LEN;
4906 }
4907 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
4908
4909 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4910 ipa->keep_ipa_awake = 1;
4911
Yun Park6c86a662017-10-05 16:09:15 -07004912 ret = qdf_ipa_setup_sys_pipe(ipa,
4913 &hdd_ipa->sys_pipe[i].conn_hdl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004914 if (ret) {
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07004915 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
4916 "Failed for pipe %d ret: %d", i, ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004917 goto setup_sys_pipe_fail;
4918 }
4919 hdd_ipa->sys_pipe[i].conn_hdl_valid = 1;
4920 }
4921
4922 if (!hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
4923 /*
4924 * Hard code it here, this can be extended if in case
4925 * PROD pipe is also per interface.
4926 * Right now there is no advantage of doing this.
4927 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004928 ipa = &hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].ipa_sys_params;
4929
Yun Parkb4f591d2017-03-29 15:51:01 -07004930 ipa->client = IPA_CLIENT_WLAN1_PROD;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931
4932 ipa->desc_fifo_sz = desc_fifo_sz;
4933 ipa->priv = hdd_ipa;
4934 ipa->notify = hdd_ipa_w2i_cb;
4935
4936 ipa->ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
4937 ipa->ipa_ep_cfg.hdr.hdr_len = HDD_IPA_WLAN_RX_HDR_LEN;
4938 ipa->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1;
4939 ipa->ipa_ep_cfg.mode.mode = IPA_BASIC;
4940
4941 if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
4942 ipa->keep_ipa_awake = 1;
4943
Yun Park6c86a662017-10-05 16:09:15 -07004944 ret = qdf_ipa_setup_sys_pipe(ipa,
4945 &hdd_ipa->sys_pipe[i].conn_hdl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004946 if (ret) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304947 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 "Failed for RX pipe: %d", ret);
4949 goto setup_sys_pipe_fail;
4950 }
4951 hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl_valid = 1;
4952 }
4953
Yun Parkd9c528e2017-08-30 16:34:57 -07004954 /* Allocate free Tx desc list */
Yun Park52b2b992016-09-22 15:49:51 -07004955 ret = hdd_ipa_alloc_tx_desc_list(hdd_ipa);
4956 if (ret)
4957 goto setup_sys_pipe_fail;
4958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 return ret;
4960
4961setup_sys_pipe_fail:
4962
4963 while (--i >= 0) {
4964 ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].conn_hdl);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304965 qdf_mem_zero(&hdd_ipa->sys_pipe[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004966 sizeof(struct hdd_ipa_sys_pipe));
4967 }
4968
4969 return ret;
4970}
4971
4972/**
4973 * hdd_ipa_teardown_sys_pipe() - Tear down all IPA Sys pipes
4974 * @hdd_ipa: Global HDD IPA context
4975 *
4976 * Return: None
4977 */
4978static void hdd_ipa_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa)
4979{
4980 int ret = 0, i;
Yun Parkd9c528e2017-08-30 16:34:57 -07004981 uint32_t max_desc_cnt;
Yun Park52b2b992016-09-22 15:49:51 -07004982 struct hdd_ipa_tx_desc *tmp_desc;
Yun Park6c86a662017-10-05 16:09:15 -07004983 qdf_ipa_rx_data_t *ipa_tx_desc;
Yun Park52b2b992016-09-22 15:49:51 -07004984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004985 for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
4986 if (hdd_ipa->sys_pipe[i].conn_hdl_valid) {
Yun Parkb4f591d2017-03-29 15:51:01 -07004987 ret = ipa_teardown_sys_pipe(hdd_ipa->sys_pipe[i].
4988 conn_hdl);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004989 if (ret)
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05304990 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Failed: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 ret);
4992
4993 hdd_ipa->sys_pipe[i].conn_hdl_valid = 0;
4994 }
4995 }
Yun Park52b2b992016-09-22 15:49:51 -07004996
4997 if (hdd_ipa->tx_desc_list) {
Yun Parkd9c528e2017-08-30 16:34:57 -07004998 max_desc_cnt = hdd_ipa->hdd_ctx->config->IpaUcTxBufCount;
4999
Yun Park52b2b992016-09-22 15:49:51 -07005000 qdf_spin_lock_bh(&hdd_ipa->q_lock);
Yun Parkd9c528e2017-08-30 16:34:57 -07005001 for (i = 0; i < max_desc_cnt; i++) {
Yun Park52b2b992016-09-22 15:49:51 -07005002 tmp_desc = hdd_ipa->tx_desc_list + i;
5003 ipa_tx_desc = tmp_desc->ipa_tx_desc_ptr;
5004 if (ipa_tx_desc)
5005 ipa_free_skb(ipa_tx_desc);
5006 }
5007 tmp_desc = hdd_ipa->tx_desc_list;
5008 hdd_ipa->tx_desc_list = NULL;
5009 hdd_ipa->stats.num_tx_desc_q_cnt = 0;
5010 hdd_ipa->stats.num_tx_desc_error = 0;
5011 qdf_spin_unlock_bh(&hdd_ipa->q_lock);
5012 qdf_mem_free(tmp_desc);
5013 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005014}
5015
5016/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005017 * hdd_ipa_cleanup_iface() - Cleanup IPA on a given interface
5018 * @iface_context: interface-specific IPA context
5019 *
5020 * Return: None
5021 */
5022static void hdd_ipa_cleanup_iface(struct hdd_ipa_iface_context *iface_context)
5023{
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005024 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07005025
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005026 if (iface_context == NULL)
5027 return;
Orhan K AKYILDIZ3332be32017-05-31 15:36:31 -07005028 if (iface_context->adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
5029 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
5030 "%s: bad adapter(%pK).magic(%d)!",
5031 __func__, iface_context->adapter,
5032 iface_context->adapter->magic);
5033 return;
5034 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005035
Yun Parkb4f591d2017-03-29 15:51:01 -07005036 cdp_ipa_cleanup_iface(cds_get_context(QDF_MODULE_ID_SOC),
5037 iface_context->adapter->dev->name,
5038 hdd_ipa_is_ipv6_enabled(iface_context->hdd_ipa->hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005039
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305040 qdf_spin_lock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 iface_context->adapter->ipa_context = NULL;
5042 iface_context->adapter = NULL;
5043 iface_context->tl_context = NULL;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305044 qdf_spin_unlock_bh(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 iface_context->ifa_address = 0;
5046 if (!iface_context->hdd_ipa->num_iface) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305047 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 "NUM INTF 0, Invalid");
Anurag Chouhandf2b2682016-02-29 14:15:27 +05305049 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005050 }
5051 iface_context->hdd_ipa->num_iface--;
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005052 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: num_iface=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005053 iface_context->hdd_ipa->num_iface);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005054}
5055
5056/**
5057 * hdd_ipa_setup_iface() - Setup IPA on a given interface
5058 * @hdd_ipa: HDD IPA global context
5059 * @adapter: Interface upon which IPA is being setup
5060 * @sta_id: Station ID of the API instance
5061 *
5062 * Return: 0 on success, negative errno value on error
5063 */
5064static int hdd_ipa_setup_iface(struct hdd_ipa_priv *hdd_ipa,
Jeff Johnson49d45e62017-08-29 14:30:42 -07005065 struct hdd_adapter *adapter, uint8_t sta_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066{
5067 struct hdd_ipa_iface_context *iface_context = NULL;
Yun Park0dad1002017-07-14 14:57:01 -07005068 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
5069 struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005070 void *tl_context = NULL;
5071 int i, ret = 0;
5072
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005073 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
Yun Parkfec73dc2017-09-06 10:40:07 -07005074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005075 /* Lower layer may send multiple START_BSS_EVENT in DFS mode or during
5076 * channel change indication. Since these indications are sent by lower
5077 * layer as SAP updates and IPA doesn't have to do anything for these
5078 * updates so ignoring!
5079 */
Krunal Sonibe766b02016-03-10 13:00:44 -08005080 if (QDF_SAP_MODE == adapter->device_mode && adapter->ipa_context)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005081 return 0;
5082
5083 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
5084 if (hdd_ipa->iface_context[i].adapter == NULL) {
5085 iface_context = &(hdd_ipa->iface_context[i]);
5086 break;
5087 }
5088 }
5089
5090 if (iface_context == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305091 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005092 "All the IPA interfaces are in use");
5093 ret = -ENOMEM;
5094 goto end;
5095 }
5096
5097 adapter->ipa_context = iface_context;
5098 iface_context->adapter = adapter;
5099 iface_context->sta_id = sta_id;
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08005100 tl_context = (void *)cdp_peer_get_vdev_by_sta_id(
Yun Park0dad1002017-07-14 14:57:01 -07005101 soc, (struct cdp_pdev *)pdev, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005102 if (tl_context == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305103 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005104 "Not able to get TL context sta_id: %d", sta_id);
5105 ret = -EINVAL;
5106 goto end;
5107 }
5108
5109 iface_context->tl_context = tl_context;
5110
Yun Parkb4f591d2017-03-29 15:51:01 -07005111 ret = cdp_ipa_setup_iface(cds_get_context(QDF_MODULE_ID_SOC),
5112 adapter->dev->name, adapter->dev->dev_addr,
5113 iface_context->prod_client,
5114 iface_context->cons_client,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005115 adapter->session_id,
Yun Parkb4f591d2017-03-29 15:51:01 -07005116 hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005117 if (ret)
5118 goto end;
5119
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005120 hdd_ipa->num_iface++;
Yun Parkfec73dc2017-09-06 10:40:07 -07005121
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005122 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "exit: num_iface=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005123 hdd_ipa->num_iface);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005124 return ret;
5125
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005126end:
5127 if (iface_context)
5128 hdd_ipa_cleanup_iface(iface_context);
5129 return ret;
5130}
5131
Yun Parka27049a2016-10-11 12:30:49 -07005132#ifndef QCA_LL_TX_FLOW_CONTROL_V2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005134 * __hdd_ipa_send_mcc_scc_msg() - send IPA WLAN_SWITCH_TO_MCC/SCC message
Jeff Johnson4929cd92017-10-06 19:21:57 -07005135 * @hdd_ctx: HDD context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005136 * @mcc_mode: 0=MCC/1=SCC
5137 *
5138 * Return: 0 on success, negative errno value on error
5139 */
Jeff Johnson4929cd92017-10-06 19:21:57 -07005140static int __hdd_ipa_send_mcc_scc_msg(struct hdd_context *hdd_ctx,
5141 bool mcc_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142{
5143 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305144 QDF_STATUS status;
Jeff Johnson089d0432017-10-02 13:27:21 -07005145 struct hdd_adapter *adapter;
Yun Park6c86a662017-10-05 16:09:15 -07005146 qdf_ipa_msg_meta_t meta;
5147 qdf_ipa_wlan_msg_t *msg;
5148
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 int ret;
5150
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005151 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005152 return -EINVAL;
5153
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005154 if (!hdd_ipa_uc_sta_is_enabled(hdd_ctx))
5155 return -EINVAL;
5156
5157 if (!hdd_ctx->mcc_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005158 /* Flush TxRx queue for each adapter before switch to SCC */
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005159 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305160 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
Jeff Johnson089d0432017-10-02 13:27:21 -07005161 adapter = adapter_node->adapter;
5162 if (adapter->device_mode == QDF_STA_MODE ||
5163 adapter->device_mode == QDF_SAP_MODE) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005164 hdd_debug("MCC->SCC: Flush TxRx queue(d_mode=%d)",
Jeff Johnson089d0432017-10-02 13:27:21 -07005165 adapter->device_mode);
5166 hdd_deinit_tx_rx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005167 }
5168 status = hdd_get_next_adapter(
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005169 hdd_ctx, adapter_node, &next);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005170 adapter_node = next;
5171 }
5172 }
5173
5174 /* Send SCC/MCC Switching event to IPA */
Yun Park6c86a662017-10-05 16:09:15 -07005175 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(*msg);
5176 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005177 if (msg == NULL) {
Jeff Johnsonab2cd402016-12-05 13:54:28 -08005178 hdd_err("msg allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005179 return -ENOMEM;
5180 }
5181
Yun Park6c86a662017-10-05 16:09:15 -07005182 QDF_IPA_MSG_META_MSG_TYPE(&meta) = mcc_mode ?
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005183 WLAN_SWITCH_TO_MCC : WLAN_SWITCH_TO_SCC;
Yun Park6c86a662017-10-05 16:09:15 -07005184 hdd_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005185
Yun Park6c86a662017-10-05 16:09:15 -07005186 ret = qdf_ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005187
5188 if (ret) {
Jeff Johnsonab2cd402016-12-05 13:54:28 -08005189 hdd_err("ipa_send_msg(Evt:%d) - fail=%d",
Yun Park6c86a662017-10-05 16:09:15 -07005190 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305191 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005192 }
5193
5194 return ret;
5195}
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005196
5197/**
5198 * hdd_ipa_send_mcc_scc_msg() - SSR wrapper for __hdd_ipa_send_mcc_scc_msg
5199 * @mcc_mode: 0=MCC/1=SCC
5200 *
5201 * Return: 0 on success, negative errno value on error
5202 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07005203int hdd_ipa_send_mcc_scc_msg(struct hdd_context *hdd_ctx, bool mcc_mode)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005204{
5205 int ret;
5206
5207 cds_ssr_protect(__func__);
5208 ret = __hdd_ipa_send_mcc_scc_msg(hdd_ctx, mcc_mode);
5209 cds_ssr_unprotect(__func__);
5210
5211 return ret;
5212}
Yun Parka27049a2016-10-11 12:30:49 -07005213#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005214
5215/**
Mohit Khannafa99aea2016-05-12 21:43:13 -07005216 * hdd_to_ipa_wlan_event() - convert hdd_ipa_wlan_event to ipa_wlan_event
5217 * @hdd_ipa_event_type: HDD IPA WLAN event to be converted to an ipa_wlan_event
5218 *
Yun Park6c86a662017-10-05 16:09:15 -07005219 * Return: qdf_ipa_wlan_event representing the hdd_ipa_wlan_event
Mohit Khannafa99aea2016-05-12 21:43:13 -07005220 */
Yun Park6c86a662017-10-05 16:09:15 -07005221static qdf_ipa_wlan_event_t
Mohit Khannafa99aea2016-05-12 21:43:13 -07005222hdd_to_ipa_wlan_event(enum hdd_ipa_wlan_event hdd_ipa_event_type)
5223{
Yun Park6c86a662017-10-05 16:09:15 -07005224 qdf_ipa_wlan_event_t ipa_event;
Mohit Khannafa99aea2016-05-12 21:43:13 -07005225
5226 switch (hdd_ipa_event_type) {
5227 case HDD_IPA_CLIENT_CONNECT:
5228 ipa_event = WLAN_CLIENT_CONNECT;
5229 break;
5230 case HDD_IPA_CLIENT_DISCONNECT:
5231 ipa_event = WLAN_CLIENT_DISCONNECT;
5232 break;
5233 case HDD_IPA_AP_CONNECT:
5234 ipa_event = WLAN_AP_CONNECT;
5235 break;
5236 case HDD_IPA_AP_DISCONNECT:
5237 ipa_event = WLAN_AP_DISCONNECT;
5238 break;
5239 case HDD_IPA_STA_CONNECT:
5240 ipa_event = WLAN_STA_CONNECT;
5241 break;
5242 case HDD_IPA_STA_DISCONNECT:
5243 ipa_event = WLAN_STA_DISCONNECT;
5244 break;
5245 case HDD_IPA_CLIENT_CONNECT_EX:
5246 ipa_event = WLAN_CLIENT_CONNECT_EX;
5247 break;
5248 case HDD_IPA_WLAN_EVENT_MAX:
5249 default:
5250 ipa_event = IPA_WLAN_EVENT_MAX;
5251 break;
5252 }
5253 return ipa_event;
5254
5255}
5256
5257/**
5258 * __hdd_ipa_wlan_evt() - IPA event handler
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 * @adapter: adapter upon which the event was received
5260 * @sta_id: station id for the event
Mohit Khannafa99aea2016-05-12 21:43:13 -07005261 * @type: event enum of type ipa_wlan_event
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262 * @mac_address: MAC address associated with the event
5263 *
Mohit Khannafa99aea2016-05-12 21:43:13 -07005264 * This function is meant to be called from within wlan_hdd_ipa.c
5265 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 * Return: 0 on success, negative errno value on error
5267 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07005268static int __hdd_ipa_wlan_evt(struct hdd_adapter *adapter, uint8_t sta_id,
Yun Park6c86a662017-10-05 16:09:15 -07005269 qdf_ipa_wlan_event_t type, uint8_t *mac_addr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270{
5271 struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
Yun Park6c86a662017-10-05 16:09:15 -07005272 qdf_ipa_msg_meta_t meta;
5273 qdf_ipa_wlan_msg_t *msg;
5274 qdf_ipa_wlan_msg_ex_t *msg_ex = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005275 int ret;
5276
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005277 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: EVT: %s, MAC: %pM, sta_id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005278 adapter->dev->name, hdd_ipa_wlan_event_to_str(type),
5279 mac_addr, sta_id);
5280
5281 if (type >= IPA_WLAN_EVENT_MAX)
5282 return -EINVAL;
5283
5284 if (WARN_ON(is_zero_ether_addr(mac_addr)))
5285 return -EINVAL;
5286
5287 if (!hdd_ipa || !hdd_ipa_is_enabled(hdd_ipa->hdd_ctx)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305288 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "IPA OFFLOAD NOT ENABLED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289 return -EINVAL;
5290 }
5291
5292 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) &&
5293 !hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
Krunal Sonibe766b02016-03-10 13:00:44 -08005294 (QDF_SAP_MODE != adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005295 return 0;
5296 }
5297
5298 /*
5299 * During IPA UC resource loading/unloading new events can be issued.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 */
Yun Park777d7242017-03-30 15:38:33 -07005301 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx) &&
5302 (hdd_ipa->resource_loading || hdd_ipa->resource_unloading)) {
5303 unsigned int pending_event_count;
5304 struct ipa_uc_pending_event *pending_event = NULL;
Yun Parkf19e07d2015-11-20 11:34:27 -08005305
Yun Park46255682017-10-09 15:56:34 -07005306 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park777d7242017-03-30 15:38:33 -07005307 "%s:IPA resource %s inprogress",
5308 hdd_ipa_wlan_event_to_str(type),
5309 hdd_ipa->resource_loading ?
5310 "load" : "unload");
5311
5312 /* Wait until completion of the long/unloading */
5313 ret = wait_for_completion_timeout(&hdd_ipa->ipa_resource_comp,
5314 msecs_to_jiffies(IPA_RESOURCE_COMP_WAIT_TIME));
5315 if (!ret) {
5316 /*
5317 * If timed out, store the events separately and
5318 * handle them later.
5319 */
Yun Park46255682017-10-09 15:56:34 -07005320 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park777d7242017-03-30 15:38:33 -07005321 "IPA resource %s timed out",
5322 hdd_ipa->resource_loading ?
5323 "load" : "unload");
Yun Park7c4f31b2016-11-30 10:09:21 -08005324
Yun Park777d7242017-03-30 15:38:33 -07005325 if (hdd_ipa->resource_loading) {
5326 qdf_mutex_acquire(&hdd_ipa->ipa_lock);
Yun Parkf19e07d2015-11-20 11:34:27 -08005327
Yun Park777d7242017-03-30 15:38:33 -07005328 pending_event_count =
Srinivas Girigowdac16ba6d2017-03-25 11:43:26 -07005329 qdf_list_size(&hdd_ipa->pending_event);
Yun Park777d7242017-03-30 15:38:33 -07005330 if (pending_event_count >=
5331 HDD_IPA_MAX_PENDING_EVENT_COUNT) {
5332 hdd_debug(
5333 "Reached max pending event count");
5334 qdf_list_remove_front(
5335 &hdd_ipa->pending_event,
5336 (qdf_list_node_t **)&pending_event);
5337 } else {
5338 pending_event =
5339 (struct ipa_uc_pending_event *)
5340 qdf_mem_malloc(sizeof(
5341 struct ipa_uc_pending_event));
5342 }
Prakash Dhavalibf6d5d22016-08-17 10:17:46 -07005343
Yun Park777d7242017-03-30 15:38:33 -07005344 if (!pending_event) {
5345 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
5346 "Pending event memory alloc fail");
5347 qdf_mutex_release(&hdd_ipa->ipa_lock);
5348 return -ENOMEM;
5349 }
5350
5351 pending_event->adapter = adapter;
5352 pending_event->sta_id = sta_id;
5353 pending_event->type = type;
5354 qdf_mem_copy(pending_event->mac_addr,
5355 mac_addr, QDF_MAC_ADDR_SIZE);
5356 qdf_list_insert_back(&hdd_ipa->pending_event,
5357 &pending_event->node);
5358
Yun Park64c405e2017-01-10 22:35:51 -08005359 qdf_mutex_release(&hdd_ipa->ipa_lock);
Prakash Dhavalibf6d5d22016-08-17 10:17:46 -07005360 }
Prakash Dhavalibf6d5d22016-08-17 10:17:46 -07005361 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005362 }
Yun Park46255682017-10-09 15:56:34 -07005363 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Jeff Johnson4929cd92017-10-06 19:21:57 -07005364 "IPA resource %s completed",
5365 hdd_ipa->resource_loading ?
5366 "load" : "unload");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005367 }
5368
5369 hdd_ipa->stats.event[type]++;
5370
Yun Park6c86a662017-10-05 16:09:15 -07005371 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372 switch (type) {
5373 case WLAN_STA_CONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005374 qdf_mutex_acquire(&hdd_ipa->event_lock);
5375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 /* STA already connected and without disconnect, connect again
5377 * This is Roaming scenario
5378 */
5379 if (hdd_ipa->sta_connected)
5380 hdd_ipa_cleanup_iface(adapter->ipa_context);
5381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382 ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id);
5383 if (ret) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305384 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 goto end;
Yun Parka37592b2016-06-11 17:10:28 -07005386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387
Yun Park8f289c82016-10-18 16:38:21 -07005388 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
5389 (hdd_ipa->sap_num_connected_sta > 0) &&
5390 !hdd_ipa->sta_connected) {
5391 qdf_mutex_release(&hdd_ipa->event_lock);
5392 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005393 SIR_STA_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005394 qdf_mutex_acquire(&hdd_ipa->event_lock);
5395 }
5396
Jeff Johnson1b780e42017-10-31 14:11:45 -07005397 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005398 ((struct hdd_ipa_iface_context *)
Yun Parka37592b2016-06-11 17:10:28 -07005399 (adapter->ipa_context))->iface_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401 hdd_ipa->sta_connected = 1;
Yun Park8f289c82016-10-18 16:38:21 -07005402
5403 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkfec73dc2017-09-06 10:40:07 -07005404
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005405 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "sta_connected=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005406 hdd_ipa->sta_connected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005407 break;
5408
5409 case WLAN_AP_CONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005410 qdf_mutex_acquire(&hdd_ipa->event_lock);
5411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 /* For DFS channel we get two start_bss event (before and after
5413 * CAC). Also when ACS range includes both DFS and non DFS
5414 * channels, we could possibly change channel many times due to
5415 * RADAR detection and chosen channel may not be a DFS channels.
5416 * So dont return error here. Just discard the event.
5417 */
Yun Park8f289c82016-10-18 16:38:21 -07005418 if (adapter->ipa_context) {
5419 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005420 return 0;
Yun Park8f289c82016-10-18 16:38:21 -07005421 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005422
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005423 ret = hdd_ipa_setup_iface(hdd_ipa, adapter, sta_id);
5424 if (ret) {
Yun Park64c405e2017-01-10 22:35:51 -08005425 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005426 hdd_err("%s: Evt: %d, Interface setup failed",
Yun Park6c86a662017-10-05 16:09:15 -07005427 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 goto end;
Yun Parka37592b2016-06-11 17:10:28 -07005429 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430
Yun Park8f289c82016-10-18 16:38:21 -07005431 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5432 qdf_mutex_release(&hdd_ipa->event_lock);
5433 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005434 SIR_AP_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005435 qdf_mutex_acquire(&hdd_ipa->event_lock);
5436 }
5437
Jeff Johnson1b780e42017-10-31 14:11:45 -07005438 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 ((struct hdd_ipa_iface_context *)
Yun Parka37592b2016-06-11 17:10:28 -07005440 (adapter->ipa_context))->iface_id;
5441
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305442 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005443 break;
5444
5445 case WLAN_STA_DISCONNECT:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305446 qdf_mutex_acquire(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005447
5448 if (!hdd_ipa->sta_connected) {
Yun Park64c405e2017-01-10 22:35:51 -08005449 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005450 hdd_err("%s: Evt: %d, STA already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005451 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 return -EINVAL;
5453 }
Yun Parka37592b2016-06-11 17:10:28 -07005454
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005455 hdd_ipa->sta_connected = 0;
Yun Parka37592b2016-06-11 17:10:28 -07005456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005457 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005458 hdd_debug("%s: IPA UC OFFLOAD NOT ENABLED",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459 msg_ex->name);
5460 } else {
5461 /* Disable IPA UC TX PIPE when STA disconnected */
Yun Park3b7152b2017-08-25 08:33:37 -07005462 if ((1 == hdd_ipa->num_iface) &&
Yun Parka37592b2016-06-11 17:10:28 -07005463 (HDD_IPA_UC_NUM_WDI_PIPE ==
Yun Park3b7152b2017-08-25 08:33:37 -07005464 hdd_ipa->activated_fw_pipe) &&
5465 !hdd_ipa->ipa_pipes_down)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005466 hdd_ipa_uc_handle_last_discon(hdd_ipa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005467 }
5468
Yun Park74127cf2016-09-18 11:22:41 -07005469 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
5470 (hdd_ipa->sap_num_connected_sta > 0)) {
Yun Park8f289c82016-10-18 16:38:21 -07005471 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005473 SIR_STA_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005474 qdf_mutex_acquire(&hdd_ipa->event_lock);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005475 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005476 CSR_ROAM_SESSION_MAX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005477 }
5478
Yun Park8f289c82016-10-18 16:38:21 -07005479 hdd_ipa_cleanup_iface(adapter->ipa_context);
5480
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305481 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkfec73dc2017-09-06 10:40:07 -07005482
Kiran Kumar Lokere1d411bb2017-11-29 15:24:05 -08005483 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "sta_connected=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005484 hdd_ipa->sta_connected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005485 break;
5486
5487 case WLAN_AP_DISCONNECT:
Yun Park8f289c82016-10-18 16:38:21 -07005488 qdf_mutex_acquire(&hdd_ipa->event_lock);
5489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005490 if (!adapter->ipa_context) {
Yun Park64c405e2017-01-10 22:35:51 -08005491 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parkb187d542016-11-14 18:10:04 -08005492 hdd_err("%s: Evt: %d, SAP already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005493 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005494 return -EINVAL;
5495 }
5496
Yun Park3b7152b2017-08-25 08:33:37 -07005497 if ((1 == hdd_ipa->num_iface) &&
5498 (HDD_IPA_UC_NUM_WDI_PIPE == hdd_ipa->activated_fw_pipe) &&
5499 !hdd_ipa->ipa_pipes_down) {
Prashanth Bhatta9e143052015-12-04 11:56:47 -08005500 if (cds_is_driver_unloading()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005501 /*
5502 * We disable WDI pipes directly here since
5503 * IPA_OPCODE_TX/RX_SUSPEND message will not be
5504 * processed when unloading WLAN driver is in
5505 * progress
5506 */
5507 hdd_ipa_uc_disable_pipes(hdd_ipa);
5508 } else {
Yun Park199c2ed2017-10-02 11:24:22 -07005509 /*
5510 * This shouldn't happen :
5511 * No interface left but WDI pipes are still
5512 * active - force close WDI pipes
5513 */
5514 WARN_ON(1);
5515 HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
5516 "No interface left but WDI pipes are still active - force close WDI pipes");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005517 hdd_ipa_uc_handle_last_discon(hdd_ipa);
5518 }
5519 }
5520
5521 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Yun Park8f289c82016-10-18 16:38:21 -07005522 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005523 hdd_ipa_uc_offload_enable_disable(adapter,
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005524 SIR_AP_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005525 qdf_mutex_acquire(&hdd_ipa->event_lock);
Jeff Johnson1b780e42017-10-31 14:11:45 -07005526 hdd_ipa->vdev_to_iface[adapter->session_id] =
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005527 CSR_ROAM_SESSION_MAX;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005528 }
Yun Parka37592b2016-06-11 17:10:28 -07005529
Yun Park8f289c82016-10-18 16:38:21 -07005530 hdd_ipa_cleanup_iface(adapter->ipa_context);
5531
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305532 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005533 break;
5534
5535 case WLAN_CLIENT_CONNECT_EX:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005536 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005537 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005538 "%s: Evt: %d, IPA UC OFFLOAD NOT ENABLED",
Manjeet Singhfd51d8f2016-11-09 15:58:26 +05305539 adapter->dev->name, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540 return 0;
5541 }
5542
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305543 qdf_mutex_acquire(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005544 if (hdd_ipa_uc_find_add_assoc_sta(hdd_ipa,
5545 true, sta_id)) {
Yun Park8f289c82016-10-18 16:38:21 -07005546 qdf_mutex_release(&hdd_ipa->event_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305547 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 "%s: STA ID %d found, not valid",
5549 adapter->dev->name, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005550 return 0;
5551 }
Yun Park312f71a2015-12-08 10:22:42 -08005552
5553 /* Enable IPA UC Data PIPEs when first STA connected */
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005554 if (hdd_ipa->sap_num_connected_sta == 0 &&
5555 hdd_ipa->uc_loaded == true) {
Yun Parka37592b2016-06-11 17:10:28 -07005556 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
Yun Park8f289c82016-10-18 16:38:21 -07005557 hdd_ipa->sta_connected) {
5558 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parka37592b2016-06-11 17:10:28 -07005559 hdd_ipa_uc_offload_enable_disable(
5560 hdd_get_adapter(hdd_ipa->hdd_ctx,
5561 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005562 SIR_STA_RX_DATA_OFFLOAD, true);
Yun Park8f289c82016-10-18 16:38:21 -07005563 qdf_mutex_acquire(&hdd_ipa->event_lock);
5564 }
Yun Parka37592b2016-06-11 17:10:28 -07005565
Yun Park312f71a2015-12-08 10:22:42 -08005566 ret = hdd_ipa_uc_handle_first_con(hdd_ipa);
5567 if (ret) {
Yun Park46255682017-10-09 15:56:34 -07005568 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
Yun Park312f71a2015-12-08 10:22:42 -08005569 "%s: handle 1st con ret %d",
5570 adapter->dev->name, ret);
Yun Parka37592b2016-06-11 17:10:28 -07005571
5572 if (hdd_ipa_uc_sta_is_enabled(
5573 hdd_ipa->hdd_ctx) &&
Yun Park8f289c82016-10-18 16:38:21 -07005574 hdd_ipa->sta_connected) {
5575 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Parka37592b2016-06-11 17:10:28 -07005576 hdd_ipa_uc_offload_enable_disable(
5577 hdd_get_adapter(
5578 hdd_ipa->hdd_ctx,
5579 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005580 SIR_STA_RX_DATA_OFFLOAD, false);
Yun Park8f289c82016-10-18 16:38:21 -07005581 } else {
5582 qdf_mutex_release(&hdd_ipa->event_lock);
5583 }
Yun Parka37592b2016-06-11 17:10:28 -07005584
Yun Park312f71a2015-12-08 10:22:42 -08005585 return ret;
5586 }
5587 }
5588
5589 hdd_ipa->sap_num_connected_sta++;
Yun Park312f71a2015-12-08 10:22:42 -08005590
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305591 qdf_mutex_release(&hdd_ipa->event_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592
Yun Park6c86a662017-10-05 16:09:15 -07005593 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
5594 QDF_IPA_MSG_META_MSG_LEN(&meta) =
5595 (sizeof(qdf_ipa_wlan_msg_ex_t) +
5596 sizeof(qdf_ipa_wlan_hdr_attrib_val_t));
5597 msg_ex = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005598
5599 if (msg_ex == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305600 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005601 "msg_ex allocation failed");
5602 return -ENOMEM;
5603 }
5604 strlcpy(msg_ex->name, adapter->dev->name,
5605 IPA_RESOURCE_NAME_MAX);
5606 msg_ex->num_of_attribs = 1;
5607 msg_ex->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
5608 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5609 msg_ex->attribs[0].offset =
5610 HDD_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
5611 } else {
5612 msg_ex->attribs[0].offset =
5613 HDD_IPA_WLAN_HDR_DES_MAC_OFFSET;
5614 }
5615 memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
5616 IPA_MAC_ADDR_SIZE);
5617
5618 ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn);
5619
5620 if (ret) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005621 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Evt: %d : %d",
Manjeet Singhfd51d8f2016-11-09 15:58:26 +05305622 adapter->dev->name, type, ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305623 qdf_mem_free(msg_ex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005624 return ret;
5625 }
5626 hdd_ipa->stats.num_send_msg++;
Yun Parkfec73dc2017-09-06 10:40:07 -07005627
Yun Park199c2ed2017-10-02 11:24:22 -07005628 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005629 hdd_ipa->sap_num_connected_sta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005630 return ret;
5631
5632 case WLAN_CLIENT_DISCONNECT:
5633 if (!hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005634 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005635 "%s: IPA UC OFFLOAD NOT ENABLED",
5636 msg_ex->name);
5637 return 0;
5638 }
5639
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305640 qdf_mutex_acquire(&hdd_ipa->event_lock);
Yun Park73ea8bb2017-08-25 07:27:39 -07005641 if (!hdd_ipa->sap_num_connected_sta) {
5642 qdf_mutex_release(&hdd_ipa->event_lock);
5643 hdd_err("%s: Evt: %d, Client already disconnected",
Yun Park6c86a662017-10-05 16:09:15 -07005644 msg_ex->name, QDF_IPA_MSG_META_MSG_TYPE(&meta));
Yun Park73ea8bb2017-08-25 07:27:39 -07005645 return 0;
5646 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 if (!hdd_ipa_uc_find_add_assoc_sta(hdd_ipa, false, sta_id)) {
Yun Park64c405e2017-01-10 22:35:51 -08005648 qdf_mutex_release(&hdd_ipa->event_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305649 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005650 "%s: STA ID %d NOT found, not valid",
5651 msg_ex->name, sta_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005652 return 0;
5653 }
5654 hdd_ipa->sap_num_connected_sta--;
Yun Parka37592b2016-06-11 17:10:28 -07005655
Yun Park9b5030f2016-11-08 12:02:37 -08005656 /* Disable IPA UC TX PIPE when last STA disconnected */
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005657 if (!hdd_ipa->sap_num_connected_sta &&
5658 hdd_ipa->uc_loaded == true) {
Yun Park9b5030f2016-11-08 12:02:37 -08005659 if ((false == hdd_ipa->resource_unloading)
5660 && (HDD_IPA_UC_NUM_WDI_PIPE ==
Govind Singhb78a75c2017-02-21 17:37:11 +05305661 hdd_ipa->activated_fw_pipe) &&
5662 !hdd_ipa->ipa_pipes_down) {
Yun Park9b5030f2016-11-08 12:02:37 -08005663 hdd_ipa_uc_handle_last_discon(hdd_ipa);
5664 }
5665
Yun Park9b5030f2016-11-08 12:02:37 -08005666 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx) &&
jiad9d472c92017-07-28 14:05:31 +08005667 hdd_ipa->sta_connected) {
5668 qdf_mutex_release(&hdd_ipa->event_lock);
Yun Park9b5030f2016-11-08 12:02:37 -08005669 hdd_ipa_uc_offload_enable_disable(
5670 hdd_get_adapter(hdd_ipa->hdd_ctx,
5671 QDF_STA_MODE),
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005672 SIR_STA_RX_DATA_OFFLOAD, false);
jiad9d472c92017-07-28 14:05:31 +08005673 } else {
5674 qdf_mutex_release(&hdd_ipa->event_lock);
5675 }
Yun Park8f289c82016-10-18 16:38:21 -07005676 } else {
5677 qdf_mutex_release(&hdd_ipa->event_lock);
5678 }
Yun Parkfec73dc2017-09-06 10:40:07 -07005679
Yun Park199c2ed2017-10-02 11:24:22 -07005680 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "sap_num_connected_sta=%d",
Yun Parkfec73dc2017-09-06 10:40:07 -07005681 hdd_ipa->sap_num_connected_sta);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005682 break;
5683
5684 default:
5685 return 0;
5686 }
5687
Yun Park6c86a662017-10-05 16:09:15 -07005688 QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
5689 msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005690 if (msg == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305691 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "msg allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692 return -ENOMEM;
5693 }
5694
Yun Park6c86a662017-10-05 16:09:15 -07005695 QDF_IPA_MSG_META_MSG_TYPE(&meta) = type;
5696 strlcpy(QDF_IPA_WLAN_MSG_NAME(msg), adapter->dev->name,
5697 IPA_RESOURCE_NAME_MAX);
5698 memcpy(QDF_IPA_WLAN_MSG_MAC_ADDR(msg), mac_addr, ETH_ALEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005699
Srinivas Girigowda97852372017-03-06 16:52:59 -08005700 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Evt: %d",
Yun Park6c86a662017-10-05 16:09:15 -07005701 QDF_IPA_WLAN_MSG_NAME(msg),
5702 QDF_IPA_MSG_META_MSG_TYPE(&meta));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703
5704 ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
5705
5706 if (ret) {
Yun Parkb187d542016-11-14 18:10:04 -08005707 hdd_err("%s: Evt: %d fail:%d",
Yun Park6c86a662017-10-05 16:09:15 -07005708 QDF_IPA_WLAN_MSG_NAME(msg),
5709 QDF_IPA_MSG_META_MSG_TYPE(&meta), ret);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305710 qdf_mem_free(msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005711 return ret;
5712 }
5713
5714 hdd_ipa->stats.num_send_msg++;
5715
5716end:
5717 return ret;
5718}
5719
5720/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005721 * hdd_ipa_wlan_evt() - SSR wrapper for __hdd_ipa_wlan_evt
Mohit Khannafa99aea2016-05-12 21:43:13 -07005722 * @adapter: adapter upon which the event was received
5723 * @sta_id: station id for the event
5724 * @hdd_event_type: event enum of type hdd_ipa_wlan_event
5725 * @mac_address: MAC address associated with the event
5726 *
5727 * This function is meant to be called from outside of wlan_hdd_ipa.c.
5728 *
5729 * Return: 0 on success, negative errno value on error
5730 */
Jeff Johnson49d45e62017-08-29 14:30:42 -07005731int hdd_ipa_wlan_evt(struct hdd_adapter *adapter, uint8_t sta_id,
Mohit Khannafa99aea2016-05-12 21:43:13 -07005732 enum hdd_ipa_wlan_event hdd_event_type, uint8_t *mac_addr)
5733{
Yun Park6c86a662017-10-05 16:09:15 -07005734 qdf_ipa_wlan_event_t type = hdd_to_ipa_wlan_event(hdd_event_type);
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005735 int ret = 0;
5736
5737 cds_ssr_protect(__func__);
Mohit Khannafa99aea2016-05-12 21:43:13 -07005738
Leo Changa202b522016-10-14 16:13:50 -07005739 /* Data path offload only support for STA and SAP mode */
5740 if ((QDF_STA_MODE == adapter->device_mode) ||
5741 (QDF_SAP_MODE == adapter->device_mode))
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005742 ret = __hdd_ipa_wlan_evt(adapter, sta_id, type, mac_addr);
Leo Changa202b522016-10-14 16:13:50 -07005743
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005744 cds_ssr_unprotect(__func__);
5745
5746 return ret;
Mohit Khannafa99aea2016-05-12 21:43:13 -07005747}
5748
5749/**
5750 * hdd_ipa_uc_proc_pending_event() - Process IPA uC pending events
5751 * @hdd_ipa: Global HDD IPA context
5752 *
5753 * Return: None
5754 */
5755static void
5756hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa)
5757{
5758 unsigned int pending_event_count;
5759 struct ipa_uc_pending_event *pending_event = NULL;
5760
5761 pending_event_count = qdf_list_size(&hdd_ipa->pending_event);
Srinivas Girigowda97852372017-03-06 16:52:59 -08005762 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07005763 "Pending Event Count %d", pending_event_count);
Mohit Khannafa99aea2016-05-12 21:43:13 -07005764 if (!pending_event_count) {
Srinivas Girigowda97852372017-03-06 16:52:59 -08005765 HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
Yun Park46255682017-10-09 15:56:34 -07005766 "No Pending Event");
Mohit Khannafa99aea2016-05-12 21:43:13 -07005767 return;
5768 }
5769
5770 qdf_list_remove_front(&hdd_ipa->pending_event,
5771 (qdf_list_node_t **)&pending_event);
5772 while (pending_event != NULL) {
5773 __hdd_ipa_wlan_evt(pending_event->adapter,
Mohit Khannafa99aea2016-05-12 21:43:13 -07005774 pending_event->sta_id,
Will Huang0ca39e22017-10-24 14:32:57 +08005775 pending_event->type,
Mohit Khannafa99aea2016-05-12 21:43:13 -07005776 pending_event->mac_addr);
5777 qdf_mem_free(pending_event);
5778 pending_event = NULL;
5779 qdf_list_remove_front(&hdd_ipa->pending_event,
5780 (qdf_list_node_t **)&pending_event);
5781 }
5782}
5783
5784/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005785 * hdd_ipa_rm_state_to_str() - Convert IPA RM state to string
5786 * @state: IPA RM state value
5787 *
5788 * Return: ASCII string representing the IPA RM state
5789 */
5790static inline char *hdd_ipa_rm_state_to_str(enum hdd_ipa_rm_state state)
5791{
5792 switch (state) {
5793 case HDD_IPA_RM_RELEASED:
5794 return "RELEASED";
5795 case HDD_IPA_RM_GRANT_PENDING:
5796 return "GRANT_PENDING";
5797 case HDD_IPA_RM_GRANTED:
5798 return "GRANTED";
5799 }
5800
5801 return "UNKNOWN";
5802}
5803
5804/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005805 * __hdd_ipa_init() - IPA initialization function
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 * @hdd_ctx: HDD global context
5807 *
5808 * Allocate hdd_ipa resources, ipa pipe resource and register
5809 * wlan interface with IPA module.
5810 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305811 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005812 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07005813static QDF_STATUS __hdd_ipa_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005814{
5815 struct hdd_ipa_priv *hdd_ipa = NULL;
5816 int ret, i;
5817 struct hdd_ipa_iface_context *iface_context = NULL;
Yun Parkbaa62862017-01-18 13:43:34 -08005818 struct ol_txrx_pdev_t *pdev = NULL;
Yun Park6c86a662017-10-05 16:09:15 -07005819 qdf_ipa_rm_perf_profile_t profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005820
5821 if (!hdd_ipa_is_enabled(hdd_ctx))
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305822 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005823
Yun Park199c2ed2017-10-02 11:24:22 -07005824 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "enter");
5825
Yun Parkbaa62862017-01-18 13:43:34 -08005826 pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Yun Park7f171ab2016-07-29 15:44:22 -07005827 if (!pdev) {
5828 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "pdev is NULL");
5829 goto fail_return;
5830 }
5831
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305832 hdd_ipa = qdf_mem_malloc(sizeof(*hdd_ipa));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 if (!hdd_ipa) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05305834 HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL, "hdd_ipa allocation failed");
Leo Chang3bc8fed2015-11-13 10:59:47 -08005835 goto fail_return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005836 }
5837
5838 hdd_ctx->hdd_ipa = hdd_ipa;
5839 ghdd_ipa = hdd_ipa;
5840 hdd_ipa->hdd_ctx = hdd_ctx;
5841 hdd_ipa->num_iface = 0;
5842
5843 /* Create the interface context */
5844 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
5845 iface_context = &hdd_ipa->iface_context[i];
5846 iface_context->hdd_ipa = hdd_ipa;
5847 iface_context->cons_client =
5848 hdd_ipa_adapter_2_client[i].cons_client;
5849 iface_context->prod_client =
5850 hdd_ipa_adapter_2_client[i].prod_client;
5851 iface_context->iface_id = i;
5852 iface_context->adapter = NULL;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305853 qdf_spinlock_create(&iface_context->interface_lock);
Yun Park9b5030f2016-11-08 12:02:37 -08005854 }
5855 for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
Prakash Dhavali89d406d2016-11-23 11:11:00 -08005856 hdd_ipa->vdev_to_iface[i] = CSR_ROAM_SESSION_MAX;
5857 hdd_ipa->vdev_offload_enabled[i] = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858 }
5859
Leo Chang69c39692016-10-12 20:11:12 -07005860 INIT_WORK(&hdd_ipa->pm_work, hdd_ipa_pm_flush);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305861 qdf_spinlock_create(&hdd_ipa->pm_lock);
Yun Park52b2b992016-09-22 15:49:51 -07005862 qdf_spinlock_create(&hdd_ipa->q_lock);
Nirav Shahcbc6d722016-03-01 16:24:53 +05305863 qdf_nbuf_queue_init(&hdd_ipa->pm_queue_head);
Manikandan Mohan2e803a02017-02-14 14:57:53 -08005864 qdf_list_create(&hdd_ipa->pending_event, 1000);
5865 qdf_mutex_create(&hdd_ipa->event_lock);
5866 qdf_mutex_create(&hdd_ipa->ipa_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005867
5868 ret = hdd_ipa_setup_rm(hdd_ipa);
5869 if (ret)
5870 goto fail_setup_rm;
5871
5872 if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
5873 hdd_ipa_uc_rt_debug_init(hdd_ctx);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305874 qdf_mem_zero(&hdd_ipa->stats, sizeof(hdd_ipa->stats));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005875 hdd_ipa->sap_num_connected_sta = 0;
5876 hdd_ipa->ipa_tx_packets_diff = 0;
5877 hdd_ipa->ipa_rx_packets_diff = 0;
5878 hdd_ipa->ipa_p_tx_packets = 0;
5879 hdd_ipa->ipa_p_rx_packets = 0;
5880 hdd_ipa->resource_loading = false;
5881 hdd_ipa->resource_unloading = false;
5882 hdd_ipa->sta_connected = 0;
Leo Change3e49442015-10-26 20:07:13 -07005883 hdd_ipa->ipa_pipes_down = true;
Manikandan Mohancd64c0b2017-03-08 13:00:24 -08005884 hdd_ipa->wdi_enabled = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005885 /* Setup IPA sys_pipe for MCC */
5886 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx)) {
5887 ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
5888 if (ret)
5889 goto fail_create_sys_pipe;
5890 }
Manikandan Mohan153a4c32017-02-16 15:04:30 -08005891 if (hdd_ipa_uc_register_uc_ready(hdd_ipa))
5892 goto fail_create_sys_pipe;
Manikandan Mohan2e803a02017-02-14 14:57:53 -08005893
5894 for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
5895 hdd_ipa_init_uc_op_work(&hdd_ipa->uc_op_work[i].work,
5896 hdd_ipa_uc_fw_op_event_handler);
5897 hdd_ipa->uc_op_work[i].msg = NULL;
5898 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005899 } else {
5900 ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
5901 if (ret)
5902 goto fail_create_sys_pipe;
5903 }
5904
Yun Park66f24c42017-03-20 10:39:47 -07005905 /* When IPA clock scaling is disabled, initialze maximum clock */
5906 if (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)) {
5907 profile.max_supported_bandwidth_mbps = 800;
5908 hdd_debug("IPA clock scaling is disabled.");
5909 hdd_debug("Set initial CONS/PROD perf: %d",
5910 profile.max_supported_bandwidth_mbps);
5911 ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS,
5912 &profile);
5913 if (ret) {
5914 hdd_err("RM CONS set perf profile failed: %d", ret);
5915 goto fail_create_sys_pipe;
5916 }
5917
5918 ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD,
5919 &profile);
5920 if (ret) {
5921 hdd_err("RM PROD set perf profile failed: %d", ret);
5922 goto fail_create_sys_pipe;
5923 }
5924 }
5925
Yun Park777d7242017-03-30 15:38:33 -07005926 init_completion(&hdd_ipa->ipa_resource_comp);
5927
Yun Park199c2ed2017-10-02 11:24:22 -07005928 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: success");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305929 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005930
5931fail_create_sys_pipe:
5932 hdd_ipa_destroy_rm_resource(hdd_ipa);
5933fail_setup_rm:
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305934 qdf_spinlock_destroy(&hdd_ipa->pm_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305935 qdf_mem_free(hdd_ipa);
Leo Chang3bc8fed2015-11-13 10:59:47 -08005936 hdd_ctx->hdd_ipa = NULL;
5937 ghdd_ipa = NULL;
5938fail_return:
Yun Park199c2ed2017-10-02 11:24:22 -07005939 HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "exit: fail");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305940 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005941}
5942
5943/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005944 * hdd_ipa_init() - SSR wrapper for __hdd_ipa_init
5945 * @hdd_ctx: HDD global context
5946 *
5947 * Allocate hdd_ipa resources, ipa pipe resource and register
5948 * wlan interface with IPA module.
5949 *
5950 * Return: QDF_STATUS enumeration
5951 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07005952QDF_STATUS hdd_ipa_init(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005953{
5954 QDF_STATUS ret;
5955
5956 cds_ssr_protect(__func__);
5957 ret = __hdd_ipa_init(hdd_ctx);
5958 cds_ssr_unprotect(__func__);
5959
5960 return ret;
5961}
5962
Arun Khandavallicc544b32017-01-30 19:52:16 +05305963
Prakash Dhavali412cdb02016-10-20 21:19:31 -07005964/**
Govind Singh1dab23b2017-08-12 13:31:00 +05305965 * __hdd_ipa_flush - flush IPA exception path SKB's
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005966 * @hdd_ctx: HDD global context
5967 *
Govind Singh1dab23b2017-08-12 13:31:00 +05305968 * Return: none
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005969 */
Govind Singh1dab23b2017-08-12 13:31:00 +05305970static void __hdd_ipa_flush(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971{
5972 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
Nirav Shahcbc6d722016-03-01 16:24:53 +05305973 qdf_nbuf_t skb;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005974 struct hdd_ipa_pm_tx_cb *pm_tx_cb = NULL;
5975
5976 if (!hdd_ipa_is_enabled(hdd_ctx))
Govind Singh1dab23b2017-08-12 13:31:00 +05305977 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005979 cancel_work_sync(&hdd_ipa->pm_work);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005980
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305981 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005982
Nirav Shahcbc6d722016-03-01 16:24:53 +05305983 while (((skb = qdf_nbuf_queue_remove(&hdd_ipa->pm_queue_head))
5984 != NULL)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305985 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005986
5987 pm_tx_cb = (struct hdd_ipa_pm_tx_cb *)skb->cb;
Yun Parked827b42017-05-12 23:59:27 -07005988 if (pm_tx_cb->ipa_tx_desc)
5989 ipa_free_skb(pm_tx_cb->ipa_tx_desc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005990
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305991 qdf_spin_lock_bh(&hdd_ipa->pm_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05305993 qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
Govind Singh1dab23b2017-08-12 13:31:00 +05305994}
5995
5996/**
5997 * __hdd_ipa_cleanup - IPA cleanup function
5998 * @hdd_ctx: HDD global context
5999 *
6000 * Return: QDF_STATUS enumeration
6001 */
6002static QDF_STATUS __hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
6003{
6004 struct hdd_ipa_priv *hdd_ipa = hdd_ctx->hdd_ipa;
6005 int i;
6006 struct hdd_ipa_iface_context *iface_context = NULL;
6007
6008 if (!hdd_ipa_is_enabled(hdd_ctx))
6009 return QDF_STATUS_SUCCESS;
6010
6011 if (!hdd_ipa_uc_is_enabled(hdd_ctx)) {
6012 unregister_inetaddr_notifier(&hdd_ipa->ipv4_notifier);
6013 hdd_ipa_teardown_sys_pipe(hdd_ipa);
6014 }
6015
6016 /* Teardown IPA sys_pipe for MCC */
6017 if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
6018 hdd_ipa_teardown_sys_pipe(hdd_ipa);
6019
6020 hdd_ipa_destroy_rm_resource(hdd_ipa);
6021
6022 __hdd_ipa_flush(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006023
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306024 qdf_spinlock_destroy(&hdd_ipa->pm_lock);
Yun Park52b2b992016-09-22 15:49:51 -07006025 qdf_spinlock_destroy(&hdd_ipa->q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006026
6027 /* destory the interface lock */
6028 for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
6029 iface_context = &hdd_ipa->iface_context[i];
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306030 qdf_spinlock_destroy(&iface_context->interface_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006031 }
6032
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006033 if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
Yun Park7e1f7c02017-01-05 08:19:49 -08006034 if (ipa_uc_dereg_rdyCB())
6035 HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
6036 "UC Ready CB deregister fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006037 hdd_ipa_uc_rt_debug_deinit(hdd_ctx);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05306038 qdf_mutex_destroy(&hdd_ipa->event_lock);
6039 qdf_mutex_destroy(&hdd_ipa->ipa_lock);
Yun Parkd8fb1a82017-10-13 16:48:20 -07006040 qdf_list_destroy(&hdd_ipa->pending_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006041
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006042 for (i = 0; i < HDD_IPA_UC_OPCODE_MAX; i++) {
6043 cancel_work_sync(&hdd_ipa->uc_op_work[i].work);
6044 hdd_ipa->uc_op_work[i].msg = NULL;
6045 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006046 }
6047
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306048 qdf_mem_free(hdd_ipa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049 hdd_ctx->hdd_ipa = NULL;
6050
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306051 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006052}
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006053
6054/**
Govind Singh1dab23b2017-08-12 13:31:00 +05306055 * hdd_ipa_cleanup - SSR wrapper for __hdd_ipa_flush
6056 * @hdd_ctx: HDD global context
6057 *
6058 * Return: None
6059 */
6060void hdd_ipa_flush(struct hdd_context *hdd_ctx)
6061{
6062 cds_ssr_protect(__func__);
6063 __hdd_ipa_flush(hdd_ctx);
6064 cds_ssr_unprotect(__func__);
6065}
6066
6067/**
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006068 * hdd_ipa_cleanup - SSR wrapper for __hdd_ipa_cleanup
6069 * @hdd_ctx: HDD global context
6070 *
6071 * Return: QDF_STATUS enumeration
6072 */
Jeff Johnsondd595cb2017-08-28 11:58:09 -07006073QDF_STATUS hdd_ipa_cleanup(struct hdd_context *hdd_ctx)
Prakash Dhavali412cdb02016-10-20 21:19:31 -07006074{
6075 QDF_STATUS ret;
6076
6077 cds_ssr_protect(__func__);
6078 ret = __hdd_ipa_cleanup(hdd_ctx);
6079 cds_ssr_unprotect(__func__);
6080
6081 return ret;
6082}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006083#endif /* IPA_OFFLOAD */