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