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