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