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 * @im_intfr_cnt: number of times the interference is 59 * detected within detection window 60 * @im_sample_cnt: sample counter 61 */ 62 struct pdev_dcs_im_stats { 63 struct wlan_host_dcs_im_tgt_stats prev_dcs_im_stats; 64 struct wlan_host_dcs_im_user_stats user_dcs_im_stats; 65 uint8_t im_intfr_cnt; 66 uint8_t im_samp_cnt; 67 }; 68 69 /** 70 * struct pdev_dcs_params - define dcs configuration parameter in pdev object 71 * @dcs_enable_cfg: dcs enable from ini config 72 * @dcs_enable: dcs enable from ucfg config 73 * @dcs_algorithm_process: do dcs algorithm process or not 74 * @dcs_debug: dcs debug trace level 75 * @phy_err_penalty: phy error penalty 76 * @phy_err_threshold: phy error threshold 77 * @radar_err_threshold: radar error threshold 78 * @coch_intfr_threshold: co-channel interference threshold 79 * @user_max_cu: tx channel utilization due to AP's tx and rx 80 * @intfr_detection_threshold: interference detection threshold 81 * @intfr_detection_window: interference sampling window 82 * @tx_err_threshold: transmission failure rate threshold 83 * @user_request_count: counter of stats requested from userspace 84 * @notify_user: whether to notify userspace 85 */ 86 struct pdev_dcs_params { 87 uint8_t dcs_enable_cfg; 88 uint8_t dcs_enable; 89 bool dcs_algorithm_process; 90 enum wlan_dcs_debug_level dcs_debug; 91 uint32_t phy_err_penalty; 92 uint32_t phy_err_threshold; 93 uint32_t radar_err_threshold; 94 uint32_t coch_intfr_threshold; 95 uint32_t user_max_cu; 96 uint32_t intfr_detection_threshold; 97 uint32_t intfr_detection_window; 98 uint32_t tx_err_threshold; 99 uint32_t user_request_count; 100 uint8_t notify_user; 101 }; 102 103 /** 104 * struct pdev_dcs_freq_ctrl_params - define dcs frequency control parameter 105 * in pdebv object 106 * @disable_threshold_per_5mins: in five minutes, if dcs happen more than 107 * threshold, then disable dcs for some time 108 * @restart_delay: when dcs happen more than threshold in five minutes, 109 * then start to disable dcs for restart_delay minutes 110 * @timestamp: record dcs happened timestamp 111 * @dcs_happened_count: dcs happened count 112 * @disable_delay_process: in dcs disable delay process or not 113 */ 114 struct pdev_dcs_freq_ctrl_params { 115 uint8_t disable_threshold_per_5mins; 116 uint32_t restart_delay; 117 unsigned long timestamp[MAX_DCS_TIME_RECORD]; 118 unsigned long dcs_happened_count; 119 bool disable_delay_process; 120 }; 121 122 /** 123 * struct pdev_dcs_timer_args - define pdev dcs timer args 124 * @psoc: psoc pointer 125 * @pdev_id: pdev id 126 */ 127 struct pdev_dcs_timer_args { 128 struct wlan_objmgr_psoc *psoc; 129 uint32_t pdev_id; 130 }; 131 132 /** 133 * struct psoc_dcs_cbk - define dcs callback in psoc oject 134 * @cbk: callback 135 * @arg: arguments 136 */ 137 struct psoc_dcs_cbk { 138 dcs_callback cbk; 139 void *arg; 140 }; 141 142 /** 143 * struct dcs_pdev_priv_obj - define dcs pdev priv 144 * @dcs_host_params: dcs host configuration parameter 145 * @dcs_im_stats: dcs im statistics 146 * @dcs_freq_ctrl_params: dcs frequency control parameter 147 * @dcs_disable_timer: dcs disable timer 148 * @dcs_timer_args: dcs disable timer args 149 * @lock: lock to protect dcs pdev priv 150 * @requestor_vdev_id: user request vdev id 151 * @user_cb: user request callback 152 */ 153 struct dcs_pdev_priv_obj { 154 struct pdev_dcs_params dcs_host_params; 155 struct pdev_dcs_im_stats dcs_im_stats; 156 struct pdev_dcs_freq_ctrl_params dcs_freq_ctrl_params; 157 qdf_timer_t dcs_disable_timer; 158 struct pdev_dcs_timer_args dcs_timer_args; 159 qdf_spinlock_t lock; 160 uint8_t requestor_vdev_id; 161 void (*user_cb)(uint8_t vdev_id, 162 struct wlan_host_dcs_im_user_stats *stats, 163 int status); 164 }; 165 166 /** 167 * wlan_dcs_chan_seg - Different segments in the channel band. 168 * @WLAN_DCS_SEG_INVALID: invalid segment 169 * @WLAN_DCS_SEG_PRI20: primary 20MHz 170 * @WLAN_DCS_SEG_SEC20: secondary 20MHz 171 * @WLAN_DCS_SEG_SEC40: secondary 40MHz 172 * @WLAN_DCS_SEG_SEC80: secondary 80MHz 173 * @WLAN_DCS_SEG_SEC160: secondary 160MHz 174 */ 175 enum wlan_dcs_chan_seg { 176 WLAN_DCS_SEG_INVALID, 177 WLAN_DCS_SEG_PRI20, 178 WLAN_DCS_SEG_SEC20, 179 WLAN_DCS_SEG_SEC40, 180 WLAN_DCS_SEG_SEC80, 181 WLAN_DCS_SEG_SEC160, 182 }; 183 184 /* masks for segments */ 185 #define WLAN_DCS_SEG_PRI20_MASK BIT(0) 186 #define WLAN_DCS_SEG_SEC20_MASK BIT(1) 187 #define WLAN_DCS_SEG_SEC40_MASK (BIT(2) | BIT(3)) 188 #define WLAN_DCS_SEG_SEC80_MASK (BIT(4) | BIT(5) | BIT(6) | BIT(7)) 189 #define WLAN_DCS_SEG_SEC160_MASK (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ 190 BIT(12) | BIT(13) | BIT(14) | BIT(15)) 191 192 #define WLAN_DCS_CHAN_FREQ_OFFSET 5 193 #define WLAN_DCS_IS_FREQ_IN_WIDTH(__cfreq, __cfreq0, __cfreq1, __width, __freq)\ 194 ((((__width) == CH_WIDTH_20MHZ) && \ 195 ((__cfreq) == (__freq))) || \ 196 (((__width) == CH_WIDTH_40MHZ) && \ 197 (((__freq) >= ((__cfreq0) - (2 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 198 ((__freq) <= ((__cfreq0) + (2 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 199 (((__width) == CH_WIDTH_80MHZ) && \ 200 (((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 201 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 202 (((__width) == CH_WIDTH_160MHZ) && \ 203 (((__freq) >= ((__cfreq1) - (14 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 204 ((__freq) <= ((__cfreq1) + (14 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 205 (((__width) == CH_WIDTH_80P80MHZ) && \ 206 ((((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 207 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET)))) || \ 208 (((__freq) >= ((__cfreq1) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 209 ((__freq) <= ((__cfreq1) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))))) 210 211 /** 212 * struct dcs_psoc_priv_obj - define dcs psoc priv 213 * @dcs_pdev_priv: dcs pdev priv 214 * @dcs_cbk: dcs callback 215 * @switch_chan_cb: callback for switching channel 216 */ 217 struct dcs_psoc_priv_obj { 218 struct dcs_pdev_priv_obj dcs_pdev_priv[WLAN_DCS_MAX_PDEVS]; 219 struct psoc_dcs_cbk dcs_cbk; 220 dcs_switch_chan_cb switch_chan_cb; 221 }; 222 223 /** 224 * wlan_dcs_get_pdev_private_obj() - get dcs pdev private object 225 * @psoc: psoc pointer 226 * @pdev_id: pdev_id 227 * 228 * API to retrieve the pdev private object from the psoc context 229 * 230 * Return: pdev private object pointer on success, NULL on error 231 */ 232 struct dcs_pdev_priv_obj * 233 wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 234 235 /** 236 * wlan_dcs_attach() - Attach dcs handler 237 * @psoc: psoc pointer 238 * 239 * This function gets called to register dcs FW events handler 240 * 241 * Return: QDF_STATUS 242 */ 243 QDF_STATUS wlan_dcs_attach(struct wlan_objmgr_psoc *psoc); 244 245 /** 246 * wlan_dcs_detach() - Detach dcs handler 247 * @psoc: psoc pointer 248 * 249 * This function gets called to unregister dcs FW events handler 250 * 251 * Return: QDF_STATUS 252 */ 253 QDF_STATUS wlan_dcs_detach(struct wlan_objmgr_psoc *psoc); 254 255 /** 256 * wlan_dcs_cmd_send() - Send dcs command to target_if layer 257 * @psoc: psoc pointer 258 * @pdev_id: pdev_id 259 * @is_host_pdev_id: pdev_id is host id or not 260 * 261 * The function gets called to send dcs command to FW 262 * 263 * return: QDF_STATUS_SUCCESS for success or error code 264 */ 265 QDF_STATUS wlan_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, 266 uint32_t pdev_id, 267 bool is_host_pdev_id); 268 269 /** 270 * wlan_dcs_process() - dcs process main entry 271 * @psoc: psoc pointer 272 * @event: dcs event pointer 273 * 274 * This function is the main entry to do dcs related operation 275 * such as algorithm handling and dcs frequency control. 276 * 277 * Return: QDF_STATUS 278 */ 279 QDF_STATUS wlan_dcs_process(struct wlan_objmgr_psoc *psoc, 280 struct wlan_host_dcs_event *event); 281 282 /** 283 * wlan_dcs_disable_timer_fn() - dcs disable timer callback 284 * @dcs_timer_args: dcs timer argument pointer 285 * 286 * This function gets called when dcs disable timer timeout 287 * 288 * Return: None 289 */ 290 void wlan_dcs_disable_timer_fn(void *dcs_timer_args); 291 292 /** 293 * wlan_dcs_clear() - clear dcs information 294 * @psoc: psoc pointer 295 * @pdev_id: pdev_id 296 * 297 * The function gets called to clear dcs information such as dcs 298 * frequency control parameters and stop dcs disable timer 299 * 300 * Return: None 301 */ 302 void wlan_dcs_clear(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 303 304 /** 305 * wlan_dcs_set_algorithm_process() - config dcs event data to do algorithm 306 * process or not 307 * @psoc: psoc pointer 308 * @pdev_id: pdev_id 309 * @dcs_algorithm_process: dcs algorithm process 310 * 311 * The function gets called to config dcs event data to do algorithm 312 * process or not 313 * 314 * Return: None 315 */ 316 void wlan_dcs_set_algorithm_process(struct wlan_objmgr_psoc *psoc, 317 uint32_t pdev_id, 318 bool dcs_algorithm_process); 319 320 /* 321 * wlan_dcs_pdev_obj_lock() - private API to acquire spinlock at pdev 322 * @dcs_pdev: pointer to dcs pdev object 323 * 324 * Return: void 325 */ 326 static inline void wlan_dcs_pdev_obj_lock(struct dcs_pdev_priv_obj *dcs_pdev) 327 { 328 qdf_spin_lock_bh(&dcs_pdev->lock); 329 } 330 331 /** 332 * wlan_dcs_pdev_obj_unlock() - private api to release spinlock at pdev 333 * @dcs_pdev: pointer to dcs pdev object 334 * 335 * Return: void 336 */ 337 static inline void wlan_dcs_pdev_obj_unlock(struct dcs_pdev_priv_obj *dcs_pdev) 338 { 339 qdf_spin_unlock_bh(&dcs_pdev->lock); 340 } 341 #endif /* _WLAN_DCS_H_ */ 342