xref: /wlan-dirver/qca-wifi-host-cmn/umac/dcs/core/src/wlan_dcs.h (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
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