1 /* 2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 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_samp_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 #define WLAN_DCS_MAX_STA_NUM 1 148 #define WLAN_DCS_MAX_SAP_NUM 2 149 #define WLAN_DCS_AFC_PREFER_BW CH_WIDTH_80MHZ 150 151 /** 152 * struct connection_chan_info - define connection channel information 153 * @freq: channel frequency 154 * @bw: channel bandwidth 155 * @vdev_id: connection vdev id 156 */ 157 struct connection_chan_info { 158 qdf_freq_t freq; 159 enum phy_ch_width bw; 160 uint8_t vdev_id; 161 }; 162 163 /** 164 * struct wlan_dcs_conn_info - define arguments list for DCS when AFC updated 165 * @sta_cnt: station count 166 * @sap_5ghz_cnt: 5 GHz sap count 167 * @sap_6ghz_cnt: 6 GHz sap count 168 * @sta: connection info of station 169 * @sap_5ghz: connection info of 5 GHz sap 170 * @sap_6ghz: connection info of 6 GHz sap 171 * @exit_condition: flag to exit iteration immediately 172 */ 173 struct wlan_dcs_conn_info { 174 uint8_t sta_cnt; 175 uint8_t sap_5ghz_cnt; 176 uint8_t sap_6ghz_cnt; 177 struct connection_chan_info sta[WLAN_DCS_MAX_STA_NUM]; 178 struct connection_chan_info sap_5ghz[WLAN_DCS_MAX_SAP_NUM]; 179 struct connection_chan_info sap_6ghz[WLAN_DCS_MAX_SAP_NUM]; 180 bool exit_condition; 181 }; 182 183 /** 184 * struct dcs_afc_select_chan_cbk - define sap afc select channel callback 185 * @cbk: callback 186 * @arg: argument supply by register 187 */ 188 struct dcs_afc_select_chan_cbk { 189 dcs_afc_select_chan_cb cbk; 190 void *arg; 191 }; 192 193 /** 194 * struct dcs_pdev_priv_obj - define dcs pdev priv 195 * @dcs_host_params: dcs host configuration parameter 196 * @dcs_im_stats: dcs im statistics 197 * @dcs_freq_ctrl_params: dcs frequency control parameter 198 * @dcs_disable_timer: dcs disable timer 199 * @dcs_timer_args: dcs disable timer args 200 * @lock: lock to protect dcs pdev priv 201 * @requestor_vdev_id: user request vdev id 202 * @user_cb: user request callback 203 */ 204 struct dcs_pdev_priv_obj { 205 struct pdev_dcs_params dcs_host_params; 206 struct pdev_dcs_im_stats dcs_im_stats; 207 struct pdev_dcs_freq_ctrl_params dcs_freq_ctrl_params; 208 qdf_timer_t dcs_disable_timer; 209 struct pdev_dcs_timer_args dcs_timer_args; 210 qdf_spinlock_t lock; 211 uint8_t requestor_vdev_id; 212 void (*user_cb)(uint8_t vdev_id, 213 struct wlan_host_dcs_im_user_stats *stats, 214 int status); 215 }; 216 217 /** 218 * enum wlan_dcs_chan_seg - Different segments in the channel band. 219 * @WLAN_DCS_SEG_INVALID: invalid segment 220 * @WLAN_DCS_SEG_PRI20: primary 20MHz 221 * @WLAN_DCS_SEG_SEC20: secondary 20MHz 222 * @WLAN_DCS_SEG_SEC40: secondary 40MHz 223 * @WLAN_DCS_SEG_SEC80: secondary 80MHz 224 * @WLAN_DCS_SEG_SEC160: secondary 160MHz 225 */ 226 enum wlan_dcs_chan_seg { 227 WLAN_DCS_SEG_INVALID, 228 WLAN_DCS_SEG_PRI20, 229 WLAN_DCS_SEG_SEC20, 230 WLAN_DCS_SEG_SEC40, 231 WLAN_DCS_SEG_SEC80, 232 WLAN_DCS_SEG_SEC160, 233 }; 234 235 /* masks for segments */ 236 #define WLAN_DCS_SEG_PRI20_MASK BIT(0) 237 #define WLAN_DCS_SEG_SEC20_MASK BIT(1) 238 #define WLAN_DCS_SEG_SEC40_MASK (BIT(2) | BIT(3)) 239 #define WLAN_DCS_SEG_SEC80_MASK (BIT(4) | BIT(5) | BIT(6) | BIT(7)) 240 #define WLAN_DCS_SEG_SEC160_MASK (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ 241 BIT(12) | BIT(13) | BIT(14) | BIT(15)) 242 243 #define WLAN_DCS_CHAN_FREQ_OFFSET 5 244 #define WLAN_DCS_IS_FREQ_IN_WIDTH(__cfreq, __cfreq0, __cfreq1, __width, __freq)\ 245 ((((__width) == CH_WIDTH_20MHZ) && \ 246 ((__cfreq) == (__freq))) || \ 247 (((__width) == CH_WIDTH_40MHZ) && \ 248 (((__freq) >= ((__cfreq0) - (2 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 249 ((__freq) <= ((__cfreq0) + (2 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 250 (((__width) == CH_WIDTH_80MHZ) && \ 251 (((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 252 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 253 (((__width) == CH_WIDTH_160MHZ) && \ 254 (((__freq) >= ((__cfreq1) - (14 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 255 ((__freq) <= ((__cfreq1) + (14 * WLAN_DCS_CHAN_FREQ_OFFSET))))) || \ 256 (((__width) == CH_WIDTH_80P80MHZ) && \ 257 ((((__freq) >= ((__cfreq0) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 258 ((__freq) <= ((__cfreq0) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET)))) || \ 259 (((__freq) >= ((__cfreq1) - (6 * WLAN_DCS_CHAN_FREQ_OFFSET))) && \ 260 ((__freq) <= ((__cfreq1) + (6 * WLAN_DCS_CHAN_FREQ_OFFSET))))))) 261 262 /** 263 * struct dcs_psoc_priv_obj - define dcs psoc priv 264 * @dcs_pdev_priv: dcs pdev priv 265 * @dcs_cbk: dcs callback 266 * @switch_chan_cb: callback for switching channel 267 * @afc_sel_chan_cbk: callback for afc channel selection 268 */ 269 struct dcs_psoc_priv_obj { 270 struct dcs_pdev_priv_obj dcs_pdev_priv[WLAN_DCS_MAX_PDEVS]; 271 struct psoc_dcs_cbk dcs_cbk; 272 dcs_switch_chan_cb switch_chan_cb; 273 struct dcs_afc_select_chan_cbk afc_sel_chan_cbk; 274 }; 275 276 /** 277 * wlan_dcs_get_pdev_private_obj() - get dcs pdev private object 278 * @psoc: psoc pointer 279 * @pdev_id: pdev_id 280 * 281 * API to retrieve the pdev private object from the psoc context 282 * 283 * Return: pdev private object pointer on success, NULL on error 284 */ 285 struct dcs_pdev_priv_obj * 286 wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 287 288 /** 289 * wlan_dcs_attach() - Attach dcs handler 290 * @psoc: psoc pointer 291 * 292 * This function gets called to register dcs FW events handler 293 * 294 * Return: QDF_STATUS 295 */ 296 QDF_STATUS wlan_dcs_attach(struct wlan_objmgr_psoc *psoc); 297 298 /** 299 * wlan_dcs_detach() - Detach dcs handler 300 * @psoc: psoc pointer 301 * 302 * This function gets called to unregister dcs FW events handler 303 * 304 * Return: QDF_STATUS 305 */ 306 QDF_STATUS wlan_dcs_detach(struct wlan_objmgr_psoc *psoc); 307 308 /** 309 * wlan_dcs_cmd_send() - Send dcs command to target_if layer 310 * @psoc: psoc pointer 311 * @pdev_id: pdev_id 312 * @is_host_pdev_id: pdev_id is host id or not 313 * 314 * The function gets called to send dcs command to FW 315 * 316 * return: QDF_STATUS_SUCCESS for success or error code 317 */ 318 QDF_STATUS wlan_dcs_cmd_send(struct wlan_objmgr_psoc *psoc, 319 uint32_t pdev_id, 320 bool is_host_pdev_id); 321 322 /** 323 * wlan_dcs_process() - dcs process main entry 324 * @psoc: psoc pointer 325 * @event: dcs event pointer 326 * 327 * This function is the main entry to do dcs related operation 328 * such as algorithm handling and dcs frequency control. 329 * 330 * Return: QDF_STATUS 331 */ 332 QDF_STATUS wlan_dcs_process(struct wlan_objmgr_psoc *psoc, 333 struct wlan_host_dcs_event *event); 334 335 /** 336 * wlan_dcs_disable_timer_fn() - dcs disable timer callback 337 * @dcs_timer_args: dcs timer argument pointer 338 * 339 * This function gets called when dcs disable timer timeout 340 * 341 * Return: None 342 */ 343 void wlan_dcs_disable_timer_fn(void *dcs_timer_args); 344 345 /** 346 * wlan_dcs_clear() - clear dcs information 347 * @psoc: psoc pointer 348 * @pdev_id: pdev_id 349 * 350 * The function gets called to clear dcs information such as dcs 351 * frequency control parameters and stop dcs disable timer 352 * 353 * Return: None 354 */ 355 void wlan_dcs_clear(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id); 356 357 /** 358 * wlan_dcs_set_algorithm_process() - config dcs event data to do algorithm 359 * process or not 360 * @psoc: psoc pointer 361 * @pdev_id: pdev_id 362 * @dcs_algorithm_process: dcs algorithm process 363 * 364 * The function gets called to config dcs event data to do algorithm 365 * process or not 366 * 367 * Return: None 368 */ 369 void wlan_dcs_set_algorithm_process(struct wlan_objmgr_psoc *psoc, 370 uint32_t pdev_id, 371 bool dcs_algorithm_process); 372 373 /** 374 * wlan_dcs_pdev_obj_lock() - private API to acquire spinlock at pdev 375 * @dcs_pdev: pointer to dcs pdev object 376 * 377 * Return: void 378 */ 379 static inline void wlan_dcs_pdev_obj_lock(struct dcs_pdev_priv_obj *dcs_pdev) 380 { 381 qdf_spin_lock_bh(&dcs_pdev->lock); 382 } 383 384 /** 385 * wlan_dcs_pdev_obj_unlock() - private api to release spinlock at pdev 386 * @dcs_pdev: pointer to dcs pdev object 387 * 388 * Return: void 389 */ 390 static inline void wlan_dcs_pdev_obj_unlock(struct dcs_pdev_priv_obj *dcs_pdev) 391 { 392 qdf_spin_unlock_bh(&dcs_pdev->lock); 393 } 394 395 /** 396 * wlan_dcs_switch_chan() - switch channel for vdev 397 * @vdev: vdev ptr 398 * @tgt_freq: target frequency 399 * @tgt_width: target channel width 400 * 401 * Return: QDF_STATUS 402 */ 403 QDF_STATUS 404 wlan_dcs_switch_chan(struct wlan_objmgr_vdev *vdev, qdf_freq_t tgt_freq, 405 enum phy_ch_width tgt_width); 406 #endif /* _WLAN_DCS_H_ */ 407