1 /*
2 * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #ifndef __CE_H__
21 #define __CE_H__
22
23 #include "qdf_atomic.h"
24 #include "qdf_lock.h"
25 #include "hif_main.h"
26 #include "qdf_util.h"
27 #include "hif_exec.h"
28
29 #ifndef DATA_CE_SW_INDEX_NO_INLINE_UPDATE
30 #define DATA_CE_UPDATE_SWINDEX(x, scn, addr) \
31 (x = CE_SRC_RING_READ_IDX_GET_FROM_DDR(scn, addr))
32 #else
33 #define DATA_CE_UPDATE_SWINDEX(x, scn, addr)
34 #endif
35
36 /*
37 * Number of times to check for any pending tx/rx completion on
38 * a copy engine, this count should be big enough. Once we hit
39 * this threshold we'll not check for any Tx/Rx completion in same
40 * interrupt handling. Note that this threshold is only used for
41 * Rx interrupt processing, this can be used tor Tx as well if we
42 * suspect any infinite loop in checking for pending Tx completion.
43 */
44 #define CE_TXRX_COMP_CHECK_THRESHOLD 20
45
46 #define CE_HTT_T2H_MSG 1
47 #define CE_HTT_H2T_MSG 4
48
49 #define CE_OFFSET 0x00000400
50 #define CE_USEFUL_SIZE 0x00000058
51 #define CE_ALL_BITMAP 0xFFFF
52
53 #define HIF_REQUESTED_EVENTS 20
54 /*
55 * enum ce_id_type - Copy engine ID
56 */
57 enum ce_id_type {
58 CE_ID_0,
59 CE_ID_1,
60 CE_ID_2,
61 CE_ID_3,
62 CE_ID_4,
63 CE_ID_5,
64 CE_ID_6,
65 CE_ID_7,
66 CE_ID_8,
67 CE_ID_9,
68 CE_ID_10,
69 CE_ID_11,
70 #ifdef QCA_WIFI_QCN9224
71 CE_ID_12,
72 CE_ID_13,
73 CE_ID_14,
74 CE_ID_15,
75 #endif
76 CE_ID_MAX
77 };
78
79 #ifdef CE_TASKLET_DEBUG_ENABLE
80 /**
81 * enum ce_buckets - CE tasklet time buckets
82 * @CE_BUCKET_500_US: tasklet bucket to store 0-0.5ms
83 * @CE_BUCKET_1_MS: tasklet bucket to store 0.5-1ms
84 * @CE_BUCKET_2_MS: tasklet bucket to store 1-2ms
85 * @CE_BUCKET_5_MS: tasklet bucket to store 2-5ms
86 * @CE_BUCKET_10_MS: tasklet bucket to store 5-10ms
87 * @CE_BUCKET_BEYOND: tasklet bucket to store > 10ms
88 * @CE_BUCKET_MAX: enum max value
89 */
90 enum ce_buckets {
91 CE_BUCKET_500_US,
92 CE_BUCKET_1_MS,
93 CE_BUCKET_2_MS,
94 CE_BUCKET_5_MS,
95 CE_BUCKET_10_MS,
96 CE_BUCKET_BEYOND,
97 CE_BUCKET_MAX,
98 };
99 #endif
100
101 enum ce_target_type {
102 CE_SVC_LEGACY,
103 CE_SVC_SRNG,
104 CE_MAX_TARGET_TYPE
105 };
106
107 enum ol_ath_hif_pkt_ecodes {
108 HIF_PIPE_NO_RESOURCE = 0
109 };
110
111 struct HIF_CE_state;
112
113 /* Per-pipe state. */
114 struct HIF_CE_pipe_info {
115 /* Handle of underlying Copy Engine */
116 struct CE_handle *ce_hdl;
117
118 /* Our pipe number; facilitates use of pipe_info ptrs. */
119 uint8_t pipe_num;
120
121 /* Convenience back pointer to HIF_CE_state. */
122 struct HIF_CE_state *HIF_CE_state;
123
124 /* Instantaneous number of receive buffers that should be posted */
125 atomic_t recv_bufs_needed;
126 qdf_size_t buf_sz;
127 qdf_spinlock_t recv_bufs_needed_lock;
128
129 qdf_spinlock_t completion_freeq_lock;
130 /* Limit the number of outstanding send requests. */
131 int num_sends_allowed;
132
133 /* adding three counts for debugging ring buffer errors */
134 uint32_t nbuf_alloc_err_count;
135 uint32_t nbuf_dma_err_count;
136 uint32_t nbuf_ce_enqueue_err_count;
137 struct hif_msg_callbacks pipe_callbacks;
138 };
139
140 /**
141 * struct ce_tasklet_entry
142 *
143 * @intr_tq: intr_tq
144 * @ce_id: ce_id
145 * @inited: inited
146 * @hi_tasklet_ce:
147 * @hif_ce_state: hif_ce_state
148 */
149 struct ce_tasklet_entry {
150 struct tasklet_struct intr_tq;
151 enum ce_id_type ce_id;
152 bool inited;
153 bool hi_tasklet_ce;
154 void *hif_ce_state;
155 };
156
hif_dummy_grp_done(struct hif_exec_context * grp_entry,int work_done)157 static inline bool hif_dummy_grp_done(struct hif_exec_context *grp_entry, int
158 work_done)
159 {
160 return true;
161 }
162
163 extern struct hif_execution_ops tasklet_sched_ops;
164 extern struct hif_execution_ops napi_sched_ops;
165
166 /**
167 * struct ce_stats
168 *
169 * @ce_per_cpu: Stats of the CEs running per CPU
170 * @record_index: Current index to store in time record
171 * @tasklet_sched_entry_ts: Timestamp when tasklet is scheduled
172 * @tasklet_exec_entry_ts: Timestamp when tasklet is started execuiton
173 * @tasklet_exec_time_record: Last N number of tasklets execution time
174 * @tasklet_sched_time_record: Last N number of tasklets scheduled time
175 * @ce_tasklet_exec_bucket: Tasklet execution time buckets
176 * @ce_tasklet_sched_bucket: Tasklet time in queue buckets
177 * @ce_tasklet_exec_last_update: Latest timestamp when bucket is updated
178 * @ce_tasklet_sched_last_update: Latest timestamp when bucket is updated
179 * @ce_ring_full_count:
180 * @ce_manual_tasklet_schedule_count:
181 * @ce_last_manual_tasklet_schedule_ts:
182 */
183 struct ce_stats {
184 uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU];
185 #ifdef CE_TASKLET_DEBUG_ENABLE
186 uint32_t record_index[CE_COUNT_MAX];
187 uint64_t tasklet_sched_entry_ts[CE_COUNT_MAX];
188 uint64_t tasklet_exec_entry_ts[CE_COUNT_MAX];
189 uint64_t tasklet_exec_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
190 uint64_t tasklet_sched_time_record[CE_COUNT_MAX][HIF_REQUESTED_EVENTS];
191 uint64_t ce_tasklet_exec_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
192 uint64_t ce_tasklet_sched_bucket[CE_COUNT_MAX][CE_BUCKET_MAX];
193 uint64_t ce_tasklet_exec_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
194 uint64_t ce_tasklet_sched_last_update[CE_COUNT_MAX][CE_BUCKET_MAX];
195 #ifdef CE_TASKLET_SCHEDULE_ON_FULL
196 uint32_t ce_ring_full_count[CE_COUNT_MAX];
197 uint32_t ce_manual_tasklet_schedule_count[CE_COUNT_MAX];
198 uint64_t ce_last_manual_tasklet_schedule_ts[CE_COUNT_MAX];
199 #endif
200 #endif
201 };
202
203 struct HIF_CE_state {
204 struct hif_softc ol_sc;
205 bool started;
206 struct ce_tasklet_entry tasklets[CE_COUNT_MAX];
207 struct hif_exec_context *hif_ext_group[HIF_MAX_GROUP];
208 uint32_t hif_num_extgroup;
209 qdf_spinlock_t keep_awake_lock;
210 qdf_spinlock_t irq_reg_lock;
211 unsigned int keep_awake_count;
212 bool verified_awake;
213 bool fake_sleep;
214 qdf_timer_t sleep_timer;
215 bool sleep_timer_init;
216 qdf_time_t sleep_ticks;
217 uint32_t ce_register_irq_done;
218
219 struct CE_pipe_config *target_ce_config;
220 struct CE_attr *host_ce_config;
221 uint32_t target_ce_config_sz;
222 /* Per-pipe state. */
223 struct HIF_CE_pipe_info pipe_info[CE_COUNT_MAX];
224 /* to be activated after BMI_DONE */
225 struct hif_msg_callbacks msg_callbacks_pending;
226 /* current msg callbacks in use */
227 struct hif_msg_callbacks msg_callbacks_current;
228
229 /* Target address used to signal a pending firmware event */
230 uint32_t fw_indicator_address;
231
232 /* Copy Engine used for Diagnostic Accesses */
233 struct CE_handle *ce_diag;
234 struct ce_stats stats;
235 struct ce_ops *ce_services;
236 struct service_to_pipe *tgt_svc_map;
237 int sz_tgt_svc_map;
238 };
239
240 /*
241 * HIA Map Definition
242 */
243 struct host_interest_area_t {
244 uint32_t hi_interconnect_state;
245 uint32_t hi_early_alloc;
246 uint32_t hi_option_flag2;
247 uint32_t hi_board_data;
248 uint32_t hi_board_data_initialized;
249 uint32_t hi_failure_state;
250 uint32_t hi_rddi_msi_num;
251 uint32_t hi_pcie_perst_couple_en;
252 uint32_t hi_sw_protocol_version;
253 };
254
255 struct shadow_reg_cfg {
256 uint16_t ce_id;
257 uint16_t reg_offset;
258 };
259
260 struct shadow_reg_v2_cfg {
261 uint32_t reg_value;
262 };
263
264 #ifdef CONFIG_BYPASS_QMI
265
266 #define FW_SHARED_MEM (2 * 1024 * 1024)
267
268 #ifdef QCN7605_SUPPORT
269 struct msi_cfg {
270 u16 ce_id;
271 u16 msi_vector;
272 } qdf_packed;
273
274 struct ce_info {
275 u32 rri_over_ddr_low_paddr;
276 u32 rri_over_ddr_high_paddr;
277 struct msi_cfg cfg[CE_COUNT_MAX];
278 } qdf_packed;
279 #endif
280 #endif
281
282 /**
283 * struct ce_index
284 *
285 * @id: CE id
286 * @u: union of legacy_info and srng_info
287 * @sw_index: sw index
288 * @write_index: write index
289 * @hp: ring head pointer
290 * @tp: ring tail pointer
291 * @status_hp: status ring head pointer
292 * @status_tp: status ring tail pointer
293 */
294 struct ce_index {
295 uint8_t id;
296 union {
297 struct {
298 uint16_t sw_index;
299 uint16_t write_index;
300 } legacy_info;
301 struct {
302 uint16_t hp;
303 uint16_t tp;
304 uint16_t status_hp;
305 uint16_t status_tp;
306 } srng_info;
307 } u;
308 } qdf_packed;
309
310 /**
311 * struct hang_event_info
312 *
313 * @tlv_header: tlv header
314 * @active_tasklet_count: active tasklet count
315 * @active_grp_tasklet_cnt: active grp tasklet count
316 * @ce_count:
317 * @ce_info: CE info
318 */
319 struct hang_event_info {
320 uint16_t tlv_header;
321 uint8_t active_tasklet_count;
322 uint8_t active_grp_tasklet_cnt;
323 uint8_t ce_count;
324 struct ce_index ce_info[CE_COUNT_MAX];
325 } qdf_packed;
326
327 void hif_ce_stop(struct hif_softc *scn);
328 int hif_dump_ce_registers(struct hif_softc *scn);
329 void
330 hif_ce_dump_target_memory(struct hif_softc *scn, void *ramdump_base,
331 uint32_t address, uint32_t size);
332
333 #ifdef IPA_OFFLOAD
334 void hif_ce_ipa_get_ce_resource(struct hif_softc *scn,
335 qdf_shared_mem_t **ce_sr,
336 uint32_t *ce_sr_ring_size,
337 qdf_dma_addr_t *ce_reg_paddr);
338 #else
339 static inline
hif_ce_ipa_get_ce_resource(struct hif_softc * scn,qdf_shared_mem_t ** ce_sr,uint32_t * ce_sr_ring_size,qdf_dma_addr_t * ce_reg_paddr)340 void hif_ce_ipa_get_ce_resource(struct hif_softc *scn,
341 qdf_shared_mem_t **ce_sr,
342 uint32_t *ce_sr_ring_size,
343 qdf_dma_addr_t *ce_reg_paddr)
344 {
345 }
346
347 #endif
348 int hif_wlan_enable(struct hif_softc *scn);
349 void ce_enable_polling(void *cestate);
350 void ce_disable_polling(void *cestate);
351 void hif_wlan_disable(struct hif_softc *scn);
352 void hif_get_target_ce_config(struct hif_softc *scn,
353 struct CE_pipe_config **target_ce_config_ret,
354 uint32_t *target_ce_config_sz_ret,
355 struct service_to_pipe **target_service_to_ce_map_ret,
356 uint32_t *target_service_to_ce_map_sz_ret,
357 struct shadow_reg_cfg **target_shadow_reg_cfg_v1_ret,
358 uint32_t *shadow_cfg_v1_sz_ret);
359
360 #ifdef WLAN_FEATURE_EPPING
361 void hif_ce_prepare_epping_config(struct hif_softc *scn,
362 struct HIF_CE_state *hif_state);
363 void hif_select_epping_service_to_pipe_map(struct service_to_pipe
364 **tgt_svc_map_to_use,
365 uint32_t *sz_tgt_svc_map_to_use);
366
367 #else
368 static inline
hif_ce_prepare_epping_config(struct hif_softc * scn,struct HIF_CE_state * hif_state)369 void hif_ce_prepare_epping_config(struct hif_softc *scn,
370 struct HIF_CE_state *hif_state)
371 { }
372 static inline
hif_select_epping_service_to_pipe_map(struct service_to_pipe ** tgt_svc_map_to_use,uint32_t * sz_tgt_svc_map_to_use)373 void hif_select_epping_service_to_pipe_map(struct service_to_pipe
374 **tgt_svc_map_to_use,
375 uint32_t *sz_tgt_svc_map_to_use)
376 { }
377 #endif
378
379 void ce_service_register_module(enum ce_target_type target_type,
380 struct ce_ops* (*ce_attach)(void));
381
382 #ifdef CONFIG_SHADOW_V3
383 void hif_get_shadow_reg_config_v3(struct hif_softc *scn,
384 struct pld_shadow_reg_v3_cfg **shadow_config,
385 int *num_shadow_registers_configured);
386 void hif_preare_shadow_register_cfg_v3(struct hif_softc *scn);
387 #endif
388 #endif /* __CE_H__ */
389