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