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 */
wlan_dcs_pdev_obj_lock(struct dcs_pdev_priv_obj * dcs_pdev)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 */
wlan_dcs_pdev_obj_unlock(struct dcs_pdev_priv_obj * dcs_pdev)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