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