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  
27  #ifndef IRQ_DISABLED_MAX_DURATION_NS
28  #define IRQ_DISABLED_MAX_DURATION_NS 100000000
29  #endif
30  
31  struct hif_exec_context;
32  
33  struct hif_execution_ops {
34  	char *context_type;
35  	void (*schedule)(struct hif_exec_context *);
36  	void (*reschedule)(struct hif_exec_context *);
37  	void (*kill)(struct hif_exec_context *);
38  };
39  
40  /**
41   * struct hif_exec_context - only ever allocated as a subtype eg.
42   *					hif_tasklet_exec_context
43   *
44   * @sched_ops: HIF executon ops
45   * @hif: HIF context
46   * @numirq: number of IRQs
47   * @irq: irq handle corresponding to hw block
48   * @os_irq: irq handle for irq_affinity
49   * @cpumask:
50   * @grp_id:
51   * @scale_bin_shift:
52   * @context_name: a pointer to a const string for debugging.
53   *		this should help whenever there could be ambiguity
54   *		in what type of context the void* context points to
55   * @context: context for the handler function to use.
56   * @handler: interrupt handler
57   * @work_complete: Function call called when leaving the execution context to
58   *	determine if this context should reschedule or wait for an interrupt.
59   *	This function may be used as a hook for post processing.
60   * @irq_enable: called when the context leaves polling mode
61   * @irq_disable: called before scheduling the context.
62   * @irq_name: pointer to function to return irq name/string mapped to irq number
63   * @sched_latency_stats: schedule latency stats for different latency buckets
64   * @tstamp: timestamp when napi poll happens
65   * @cpu: the cpu this context should be affined to
66   * @stats:
67   * @inited:
68   * @configured:
69   * @irq_requested:
70   * @irq_enabled:
71   * @irq_lock: spinlock used while enabling/disabling IRQs
72   * @type: type of execution context
73   * @poll_start_time: hif napi poll start time in nanoseconds
74   * @force_break: flag to indicate if HIF execution context was forced to return
75   *		 to HIF. This means there is more work to be done. Hence do not
76   *		 call napi_complete.
77   * @new_cpu_mask: Stores the affinity hint mask for each WLAN IRQ
78   * @force_napi_complete: do a force napi_complete when this flag is set to -1
79   * @irq_disabled_start_time: irq disabled start time for single MSI
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  	qdf_cpu_mask new_cpu_mask[HIF_MAX_GRP_IRQ];
114  #endif
115  #ifdef FEATURE_IRQ_AFFINITY
116  	qdf_atomic_t force_napi_complete;
117  #endif
118  	unsigned long long irq_disabled_start_time;
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*
hif_exec_get_napi(struct hif_exec_context * ctx)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*
hif_exec_get_tasklet(struct hif_exec_context * ctx)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
hif_pci_irq_set_affinity_hint(struct hif_exec_context * hif_ext_group,bool perf)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   * @scn: 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   */
hif_ce_irq_remove_affinity_hint(int irq)208  static inline void hif_ce_irq_remove_affinity_hint(int irq)
209  {
210  	hif_irq_affinity_remove(irq);
211  }
212  #else
213  
hif_pci_ce_irq_set_affinity_hint(struct hif_softc * scn)214  static inline void hif_pci_ce_irq_set_affinity_hint(
215  	struct hif_softc *scn)
216  {
217  }
218  
hif_ce_irq_remove_affinity_hint(int irq)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_cpu_affinity() - Remove cpu affinity of IRQ
227   * @scn: HIF handle
228   * @intr_ctxt_id: 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
hif_pci_config_irq_clear_cpu_affinity(struct hif_softc * scn,int intr_ctxt_id,int cpu)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