xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/hif_exec.h (revision 70a19e16789e308182f63b15c75decec7bf0b342)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-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 __HIF_EXEC_H__
21 #define __HIF_EXEC_H__
22 
23 #include <hif.h>
24 #include <hif_irq_affinity.h>
25 #include <linux/cpumask.h>
26 /*Number of buckets for latency*/
27 #define HIF_SCHED_LATENCY_BUCKETS 8
28 
29 /*Buckets for latency between 0 to 2 ms*/
30 #define HIF_SCHED_LATENCY_BUCKET_0_2 2
31 /*Buckets for latency between 3 to 10 ms*/
32 #define HIF_SCHED_LATENCY_BUCKET_3_10 10
33 /*Buckets for latency between 11 to 20 ms*/
34 #define HIF_SCHED_LATENCY_BUCKET_11_20 20
35 /*Buckets for latency between 21 to 50 ms*/
36 #define HIF_SCHED_LATENCY_BUCKET_21_50 50
37 /*Buckets for latency between 50 to 100 ms*/
38 #define HIF_SCHED_LATENCY_BUCKET_51_100 100
39 /*Buckets for latency between 100 to 250 ms*/
40 #define HIF_SCHED_LATENCY_BUCKET_101_250 250
41 /*Buckets for latency between 250 to 500 ms*/
42 #define HIF_SCHED_LATENCY_BUCKET_251_500 500
43 
44 #ifndef IRQ_DISABLED_MAX_DURATION_NS
45 #define IRQ_DISABLED_MAX_DURATION_NS 100000000
46 #endif
47 
48 struct hif_exec_context;
49 
50 struct hif_execution_ops {
51 	char *context_type;
52 	void (*schedule)(struct hif_exec_context *);
53 	void (*reschedule)(struct hif_exec_context *);
54 	void (*kill)(struct hif_exec_context *);
55 };
56 
57 /**
58  * struct hif_exec_context - only ever allocated as a subtype eg.
59  *					hif_tasklet_exec_context
60  *
61  * @sched_ops: HIF executon ops
62  * @hif: HIF context
63  * @numirq: number of IRQs
64  * @irq: irq handle corresponding to hw block
65  * @os_irq: irq handle for irq_affinity
66  * @cpumask:
67  * @grp_id:
68  * @scale_bin_shift:
69  * @context_name: a pointer to a const string for debugging.
70  *		this should help whenever there could be ambiguity
71  *		in what type of context the void* context points to
72  * @context: context for the handler function to use.
73  * @handler: interrupt handler
74  * @work_complete: Function call called when leaving the execution context to
75  *	determine if this context should reschedule or wait for an interrupt.
76  *	This function may be used as a hook for post processing.
77  * @irq_enable: called when the context leaves polling mode
78  * @irq_disable: called before scheduling the context.
79  * @irq_name: pointer to function to return irq name/string mapped to irq number
80  * @sched_latency_stats: schedule latency stats for different latency buckets
81  * @tstamp: timestamp when napi poll happens
82  * @cpu: the cpu this context should be affined to
83  * @stats:
84  * @inited:
85  * @configured:
86  * @irq_requested:
87  * @irq_enabled:
88  * @irq_lock: spinlock used while enabling/disabling IRQs
89  * @type: type of execution context
90  * @poll_start_time: hif napi poll start time in nanoseconds
91  * @force_break: flag to indicate if HIF execution context was forced to return
92  *		 to HIF. This means there is more work to be done. Hence do not
93  *		 call napi_complete.
94  * @new_cpu_mask: Stores the affinity hint mask for each WLAN IRQ
95  * @force_napi_complete: do a force napi_complete when this flag is set to -1
96  * @irq_disabled_start_time: irq disabled start time for single MSI
97  */
98 struct hif_exec_context {
99 	struct hif_execution_ops *sched_ops;
100 	struct hif_opaque_softc *hif;
101 	uint32_t numirq;
102 	uint32_t irq[HIF_MAX_GRP_IRQ];
103 	uint32_t os_irq[HIF_MAX_GRP_IRQ];
104 	cpumask_t cpumask;
105 	uint32_t grp_id;
106 	uint32_t scale_bin_shift;
107 	const char *context_name;
108 	void *context;
109 	ext_intr_handler handler;
110 
111 	bool (*work_complete)(struct hif_exec_context *, int work_done);
112 	void (*irq_enable)(struct hif_exec_context *);
113 	void (*irq_disable)(struct hif_exec_context *);
114 	const char* (*irq_name)(int irq_no);
115 	uint64_t sched_latency_stats[HIF_SCHED_LATENCY_BUCKETS];
116 	uint64_t tstamp;
117 
118 	uint8_t cpu;
119 	struct qca_napi_stat stats[NR_CPUS];
120 	bool inited;
121 	bool configured;
122 	bool irq_requested;
123 	bool irq_enabled;
124 	qdf_spinlock_t irq_lock;
125 	enum hif_exec_type type;
126 	unsigned long long poll_start_time;
127 	bool force_break;
128 #if defined(FEATURE_IRQ_AFFINITY) || defined(HIF_CPU_PERF_AFFINE_MASK) || \
129 	defined(HIF_CPU_CLEAR_AFFINITY)
130 	qdf_cpu_mask new_cpu_mask[HIF_MAX_GRP_IRQ];
131 #endif
132 #ifdef FEATURE_IRQ_AFFINITY
133 	qdf_atomic_t force_napi_complete;
134 #endif
135 	unsigned long long irq_disabled_start_time;
136 };
137 
138 /**
139  * struct hif_tasklet_exec_context - exec_context for tasklets
140  * @exec_ctx: inherited data type
141  * @tasklet: tasklet structure for scheduling
142  */
143 struct hif_tasklet_exec_context {
144 	struct hif_exec_context exec_ctx;
145 	struct tasklet_struct tasklet;
146 };
147 
148 /**
149  * struct hif_napi_exec_context - exec_context for NAPI
150  * @exec_ctx: inherited data type
151  * @netdev: dummy net device associated with the napi context
152  * @napi: napi structure used in scheduling
153  */
154 struct hif_napi_exec_context {
155 	struct hif_exec_context exec_ctx;
156 	struct net_device    netdev; /* dummy net_dev */
157 	struct napi_struct   napi;
158 };
159 
160 static inline struct hif_napi_exec_context*
161 	hif_exec_get_napi(struct hif_exec_context *ctx)
162 {
163 	return (struct hif_napi_exec_context *) ctx;
164 }
165 
166 static inline struct hif_tasklet_exec_context*
167 	hif_exec_get_tasklet(struct hif_exec_context *ctx)
168 {
169 	return (struct hif_tasklet_exec_context *) ctx;
170 }
171 
172 struct hif_exec_context *hif_exec_create(enum hif_exec_type type,
173 						uint32_t scale);
174 
175 void hif_exec_destroy(struct hif_exec_context *ctx);
176 
177 int hif_grp_irq_configure(struct hif_softc *scn,
178 			  struct hif_exec_context *hif_exec);
179 void hif_grp_irq_deconfigure(struct hif_softc *scn);
180 irqreturn_t hif_ext_group_interrupt_handler(int irq, void *context);
181 
182 struct hif_exec_context *hif_exec_get_ctx(struct hif_opaque_softc *hif,
183 					  uint8_t id);
184 void hif_exec_kill(struct hif_opaque_softc *scn);
185 
186 #if defined(HIF_CPU_PERF_AFFINE_MASK) || defined(FEATURE_IRQ_AFFINITY)
187 /**
188  * hif_pci_irq_set_affinity_hint() - API to set IRQ affinity
189  * @hif_ext_group: hif_ext_group to extract the irq info
190  * @perf: affine to perf cluster or non-perf cluster
191  *
192  * This function will set the IRQ affinity to gold cores
193  * or silver cores based on perf flag
194  *
195  * Return: none
196  */
197 void hif_pci_irq_set_affinity_hint(struct hif_exec_context *hif_ext_group,
198 				   bool perf);
199 #else
200 static inline
201 void hif_pci_irq_set_affinity_hint(struct hif_exec_context *hif_ext_group,
202 				   bool perf)
203 {
204 }
205 #endif
206 
207 #ifdef HIF_CPU_PERF_AFFINE_MASK
208 
209 /**
210  * hif_pci_ce_irq_set_affinity_hint() - API to set IRQ affinity
211  * @scn: hif_softc to extract the CE irq info
212  *
213  * This function will set the CE IRQ affinity to the gold cores
214  * only for defconfig builds
215  *
216  * Return: none
217  */
218 void hif_pci_ce_irq_set_affinity_hint(
219 	struct hif_softc *scn);
220 
221 /**
222  * hif_ce_irq_remove_affinity_hint() - remove affinity for the irq
223  * @irq: irq number to remove affinity from
224  */
225 static inline void hif_ce_irq_remove_affinity_hint(int irq)
226 {
227 	hif_irq_affinity_remove(irq);
228 }
229 #else
230 
231 static inline void hif_pci_ce_irq_set_affinity_hint(
232 	struct hif_softc *scn)
233 {
234 }
235 
236 static inline void hif_ce_irq_remove_affinity_hint(int irq)
237 {
238 }
239 #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */
240 
241 #ifdef HIF_CPU_CLEAR_AFFINITY
242 /**
243  * hif_pci_config_irq_clear_cpu_affinity() - Remove cpu affinity of IRQ
244  * @scn: HIF handle
245  * @intr_ctxt_id: interrupt group index
246  * @cpu: CPU core to clear
247  *
248  * Return: None
249  */
250 void hif_pci_config_irq_clear_cpu_affinity(struct hif_softc *scn,
251 					   int intr_ctxt_id, int cpu);
252 #else
253 static inline
254 void hif_pci_config_irq_clear_cpu_affinity(struct hif_softc *scn,
255 					   int intr_ctxt_id, int cpu)
256 {
257 }
258 #endif /* HIF_CPU_CLEAR_AFFINITY */
259 
260 #endif
261 
262