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