1 /* 2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: This file has main dcs structures definition. 20 */ 21 22 #ifndef _WLAN_DCS_H_ 23 #define _WLAN_DCS_H_ 24 25 #include <wmi_unified_param.h> 26 #include "wlan_dcs_tgt_api.h" 27 #include "wlan_dcs_ucfg_api.h" 28 29 #define dcs_debug(args ...) \ 30 QDF_TRACE_DEBUG(QDF_MODULE_ID_DCS, ## args) 31 #define dcs_info(args ...) \ 32 QDF_TRACE_INFO(QDF_MODULE_ID_DCS, ## args) 33 #define dcs_err(args ...) \ 34 QDF_TRACE_ERROR(QDF_MODULE_ID_DCS, ## args) 35 36 #define WLAN_DCS_MAX_PDEVS 3 37 38 #define DCS_TX_MAX_CU 30 39 #define MAX_DCS_TIME_RECORD 10 40 #define DCS_FREQ_CONTROL_TIME (5 * 60 * 1000) 41 42 /** 43 * enum wlan_dcs_debug_level - dcs debug trace level 44 * @DCS_DEBUG_DISABLE: disable debug trace 45 * @DCS_DEBUG_CRITICAL: critical debug trace level 46 * @DCS_DEBUG_VERBOSE: verbose debug trace level 47 */ 48 enum wlan_dcs_debug_level { 49 DCS_DEBUG_DISABLE = 0, 50 DCS_DEBUG_CRITICAL = 1, 51 DCS_DEBUG_VERBOSE = 2 52 }; 53 54 /** 55 * struct pdev_dcs_im_stats - define dcs interference mitigation 56 * stats in pdev object 57 * @prev_dcs_im_stats: previous statistics at last time 58 * @user_dcs_im_stats: statistics requested from userspace 59 * @dcs_ch_util_im_stats: chan utilization statistics 60 * @im_intfr_cnt: number of times the interference is 61 * detected within detection window 62 * @im_sample_cnt: sample counter 63 */ 64 struct pdev_dcs_im_stats { 65 struct wlan_host_dcs_im_tgt_stats prev_dcs_im_stats; 66 struct wlan_host_dcs_im_user_stats user_dcs_im_stats; 67 struct wlan_host_dcs_ch_util_stats dcs_ch_util_im_stats; 68 uint8_t im_intfr_cnt; 69 uint8_t im_samp_cnt; 70 }; 71 72 /** 73 * struct pdev_dcs_params - define dcs configuration parameter in pdev object 74 * @dcs_enable_cfg: dcs enable from ini config 75 * @dcs_enable: dcs enable from ucfg config 76 * @dcs_algorithm_process: do dcs algorithm process or not 77 * @force_disable_algorithm: disable dcs algorithm forcely 78 * @dcs_debug: dcs debug trace level 79 * @phy_err_penalty: phy error penalty 80 * @phy_err_threshold: phy error threshold 81 * @radar_err_threshold: radar error threshold 82 * @coch_intfr_threshold: co-channel interference threshold 83 * @user_max_cu: tx channel utilization due to AP's tx and rx 84 * @intfr_detection_threshold: interference detection threshold 85 * @intfr_detection_window: interference sampling window 86 * @tx_err_threshold: transmission failure rate threshold 87 * @user_request_count: counter of stats requested from userspace 88 * @notify_user: whether to notify userspace 89 */ 90 struct pdev_dcs_params { 91 uint8_t dcs_enable_cfg; 92 uint8_t dcs_enable; 93 bool dcs_algorithm_process; 94 bool force_disable_algorithm; 95 enum wlan_dcs_debug_level dcs_debug; 96 uint32_t phy_err_penalty; 97 uint32_t phy_err_threshold; 98 uint32_t radar_err_threshold; 99 uint32_t coch_intfr_threshold; 100 uint32_t user_max_cu; 101 uint32_t intfr_detection_threshold; 102 uint32_t intfr_detection_window; 103 uint32_t tx_err_threshold; 104 uint32_t user_request_count; 105 uint8_t notify_user; 106 }; 107 108 /** 109 * struct pdev_dcs_freq_ctrl_params - define dcs frequency control parameter 110 * in pdebv object 111 * @disable_threshold_per_5mins: in five minutes, if dcs happen more than 112 * threshold, then disable dcs for some time 113 * @restart_delay: when dcs happen more than threshold in five minutes, 114 * then start to disable dcs for restart_delay minutes 115 * @timestamp: record dcs happened timestamp 116 * @dcs_happened_count: dcs happened count 117 * @disable_delay_process: in dcs disable delay process or not 118 */ 119 struct pdev_dcs_freq_ctrl_params { 120 uint8_t disable_threshold_per_5mins; 121 uint32_t restart_delay; 122 unsigned long timestamp[MAX_DCS_TIME_RECORD]; 123 unsigned long dcs_happened_count; 124 bool disable_delay_process; 125 }; 126 127 /** 128 * struct pdev_dcs_timer_args - define pdev dcs timer args 129 * @psoc: psoc pointer 130 * @pdev_id: pdev id 131 */ 132 struct pdev_dcs_timer_args { 133 struct wlan_objmgr_psoc *psoc; 134 uint32_t pdev_id; 135 }; 136 137 /** 138 * struct psoc_dcs_cbk - define dcs callback in psoc object 139 * @cbk: callback 140 * @arg: arguments 141 */ 142 struct psoc_dcs_cbk { 143 dcs_callback cbk; 144 void *arg; 145 }; 146 147 /** 148 * struct dcs_pdev_priv_obj - define dcs pdev priv 149 * @dcs_host_params: dcs host configuration parameter 150 * @dcs_im_stats: dcs im statistics 151 * @dcs_freq_ctrl_params: dcs frequency control parameter 152 * @dcs_disable_timer: dcs disable timer 153 * @dcs_timer_args: dcs disable timer args 154 * @lock: lock to protect dcs pdev priv 155 * @requestor_vdev_id: user request vdev id 156 * @user_cb: user request callback 157 */ 158 struct dcs_pdev_priv_obj { 159 struct pdev_dcs_params dcs_host_params; 160 struct pdev_dcs_im_stats dcs_im_stats; 161 struct pdev_dcs_freq_ctrl_params dcs_freq_ctrl_params; 162 qdf_timer_t dcs_disable_timer; 163 struct pdev_dcs_timer_args dcs_timer_args; 164 qdf_spinlock_t lock; 165 uint8_t requestor_vdev_id; 166 void (*user_cb)(uint8_t vdev_id, 167 struct wlan_host_dcs_im_user_stats *stats, 168 int status); 169 }; 170 171 /** 172 * wlan_dcs_chan_seg - Different segments in the channel band. 173 * @WLAN_DCS_SEG_INVALID: invalid segment 174 * @WLAN_DCS_SEG_PRI20: primary 20MHz 175 * @WLAN_DCS_SEG_SEC20: secondary 20MHz 176 * @WLAN_DCS_SEG_SEC40: secondary 40MHz 177 * @WLAN_DCS_SEG_SEC80: secondary 80MHz 178 * @WLAN_DCS_SEG_SEC160: secondary 160MHz 179 */ 180 enum wlan_dcs_chan_seg { 181 WLAN_DCS_SEG_INVALID, 182 WLAN_DCS_SEG_PRI20, 183 WLAN_DCS_SEG_SEC20, 184 WLAN_DCS_SEG_SEC40, 185 WLAN_DCS_SEG_SEC80, 186 WLAN_DCS_SEG_SEC160, 187 }; 188 189 /* masks for segments */ 190 #define WLAN_DCS_SEG_PRI20_MASK BIT(0) 191 #define WLAN_DCS_SEG_SEC20_MASK BIT(1) 192 #define WLAN_DCS_SEG_SEC40_MASK (BIT(2) | BIT(3)) 193 #define WLAN_DCS_SEG_SEC80_MASK (BIT(4) | BIT(5) | BIT(6) | BIT(7)) 194 #define WLAN_DCS_SEG_SEC160_MASK (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ 195 BIT(12) | BIT(13) | BIT(14) | BIT(15)) 196 197 #define WLAN_DCS_CHAN_FREQ_OFFSET 5 198 #define WLAN_DCS_IS_FREQ_IN_WIDTH(__cfreq, __cfreq0, __cfreq1, __width, __freq)\ 199 ((((__width) == CH_WIDTH_20MHZ) && \ 200 ((__cfreq) == (__freq))) || \ 201 (((__width) == CH_WIDTH_40MHZ) && \ 202 (((__freq) >= ((__cfreq0) - (2 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 203 ((__freq) <= ((__cfreq0) + (2 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 204 (((__width) == CH_WIDTH_80MHZ) && \ 205 (((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 206 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 207 (((__width) == CH_WIDTH_160MHZ) && \ 208 (((__freq) >= ((__cfreq1) - (14 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 209 ((__freq) <= ((__cfreq1) + (14 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 210 (((__width) == CH_WIDTH_80P80MHZ) && \ 211 ((((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 212 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET)))) || \ 213 (((__freq) >= ((__cfreq1) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 214 ((__freq) <= ((__cfreq1) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))))) 215 216 /** 217 * struct dcs_psoc_priv_obj - define dcs psoc priv 218 * @dcs_pdev_priv: dcs pdev priv 219 * @dcs_cbk: dcs callback 220 * @switch_chan_cb: callback for switching channel 221 */ 222 struct dcs_psoc_priv_obj { 223 struct dcs_pdev_priv_obj dcs_pdev_priv[WLAN_DCS_MAX_PDEVS]; 224 struct psoc_dcs_cbk dcs_cbk; 225 dcs_switch_chan_cb switch_chan_cb; 226 }; 227 228 /** 229 * wlan_dcs_get_pdev_private_obj() - get dcs pdev private object 230 * @psoc: psoc pointer 231 * @pdev_id: pdev_id 232 * 233 * API to retrieve the pdev private object from the psoc context 234 * 235 * Return: pdev private object pointer on success, NULL on error 236 */ 237 struct dcs_pdev_priv_obj * 238 wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 239 240 /** 241 * wlan_dcs_attach() - Attach dcs handler 242 * @psoc: psoc pointer 243 * 244 * This function gets called to register dcs FW events handler 245 * 246 * Return: QDF_STATUS 247 */ 248 QDF_STATUS wlan_dcs_attach(struct wlan_objmgr_psoc *psoc); 249 250 /** 251 * wlan_dcs_detach() - Detach dcs handler 252 * @psoc: psoc pointer 253 * 254 * This function gets called to unregister dcs FW events handler 255 * 256 * Return: QDF_STATUS 257 */ 258 QDF_STATUS wlan_dcs_detach(struct wlan_objmgr_psoc *psoc); 259 260 /** 261 * wlan_dcs_cmd_send() - Send dcs command to target_if layer 262 * @psoc: psoc pointer 263 * @pdev_id: pdev_id 264 * @is_host_pdev_id: pdev_id is host id or not 265 * 266 * The function gets called to send dcs command to FW 267 * 268 * return: QDF_STATUS_SUCCESS for success or error code 269 */ 270 QDF_STATUS wlan_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, 271 uint32_t pdev_id, 272 bool is_host_pdev_id); 273 274 /** 275 * wlan_dcs_process() - dcs process main entry 276 * @psoc: psoc pointer 277 * @event: dcs event pointer 278 * 279 * This function is the main entry to do dcs related operation 280 * such as algorithm handling and dcs frequency control. 281 * 282 * Return: QDF_STATUS 283 */ 284 QDF_STATUS wlan_dcs_process(struct wlan_objmgr_psoc *psoc, 285 struct wlan_host_dcs_event *event); 286 287 /** 288 * wlan_dcs_disable_timer_fn() - dcs disable timer callback 289 * @dcs_timer_args: dcs timer argument pointer 290 * 291 * This function gets called when dcs disable timer timeout 292 * 293 * Return: None 294 */ 295 void wlan_dcs_disable_timer_fn(void *dcs_timer_args); 296 297 /** 298 * wlan_dcs_clear() - clear dcs information 299 * @psoc: psoc pointer 300 * @pdev_id: pdev_id 301 * 302 * The function gets called to clear dcs information such as dcs 303 * frequency control parameters and stop dcs disable timer 304 * 305 * Return: None 306 */ 307 void wlan_dcs_clear(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 308 309 /** 310 * wlan_dcs_set_algorithm_process() - config dcs event data to do algorithm 311 * process or not 312 * @psoc: psoc pointer 313 * @pdev_id: pdev_id 314 * @dcs_algorithm_process: dcs algorithm process 315 * 316 * The function gets called to config dcs event data to do algorithm 317 * process or not 318 * 319 * Return: None 320 */ 321 void wlan_dcs_set_algorithm_process(struct wlan_objmgr_psoc *psoc, 322 uint32_t pdev_id, 323 bool dcs_algorithm_process); 324 325 /* 326 * wlan_dcs_pdev_obj_lock() - private API to acquire spinlock at pdev 327 * @dcs_pdev: pointer to dcs pdev object 328 * 329 * Return: void 330 */ 331 static inline void wlan_dcs_pdev_obj_lock(struct dcs_pdev_priv_obj *dcs_pdev) 332 { 333 qdf_spin_lock_bh(&dcs_pdev->lock); 334 } 335 336 /** 337 * wlan_dcs_pdev_obj_unlock() - private api to release spinlock at pdev 338 * @dcs_pdev: pointer to dcs pdev object 339 * 340 * Return: void 341 */ 342 static inline void wlan_dcs_pdev_obj_unlock(struct dcs_pdev_priv_obj *dcs_pdev) 343 { 344 qdf_spin_unlock_bh(&dcs_pdev->lock); 345 } 346 #endif /* _WLAN_DCS_H_ */ 347