1 /*
2 * Copyright (c) 2016-2017,2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2002-2010, Atheros Communications Inc.
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 really does contain miscellaneous functions that didn't fit
20 * in anywhere else.
21 */
22
23 #include "../dfs.h"
24 #include "wlan_dfs_lmac_api.h"
25 #include "wlan_dfs_mlme_api.h"
26 #include "../dfs_internal.h"
27
28 /**
29 * dfs_adjust_pri_per_chan_busy() - Calculates adjust_pri.
30 * @ext_chan_busy: Extension channel PRI.
31 * @pri_margin: Primary margin.
32 *
33 * Calculates the adjust_pri using ext_chan_busy, DFS_EXT_CHAN_LOADING_THRESH
34 * and pri_margin.
35 *
36 * Return: adjust_pri.
37 */
dfs_adjust_pri_per_chan_busy(int ext_chan_busy,int pri_margin)38 static int dfs_adjust_pri_per_chan_busy(int ext_chan_busy, int pri_margin)
39 {
40 int adjust_pri = 0;
41
42 if (ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) {
43 adjust_pri = ((ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) *
44 (pri_margin));
45 adjust_pri /= 100;
46 }
47
48 return adjust_pri;
49 }
50
51 /**
52 * dfs_adjust_thresh_per_chan_busy() - Calculates adjust_thresh.
53 * @ext_chan_busy: Extension channel PRI.
54 * @thresh: Threshold value.
55 *
56 * Calculates the adjust_thresh using ext_chan_busy, DFS_EXT_CHAN_LOADING_THRESH
57 * and thresh.
58 *
59 * Return: adjust_thresh.
60 */
dfs_adjust_thresh_per_chan_busy(int ext_chan_busy,int thresh)61 static int dfs_adjust_thresh_per_chan_busy(int ext_chan_busy, int thresh)
62 {
63 int adjust_thresh = 0;
64
65 if (ext_chan_busy > DFS_EXT_CHAN_LOADING_THRESH) {
66 adjust_thresh = ((ext_chan_busy - DFS_EXT_CHAN_LOADING_THRESH) *
67 thresh);
68 adjust_thresh /= 100;
69 }
70
71 return adjust_thresh;
72 }
73
74 /**
75 * dfs_get_cached_ext_chan_busy() - Get cached ext chan busy.
76 * @dfs: Pointer to wlan_dfs structure.
77 * @ext_chan_busy: Extension channel PRI.
78 */
dfs_get_cached_ext_chan_busy(struct wlan_dfs * dfs,int * ext_chan_busy)79 static inline void dfs_get_cached_ext_chan_busy(
80 struct wlan_dfs *dfs,
81 int *ext_chan_busy)
82 {
83 *ext_chan_busy = 0;
84 /* Check to see if the cached value of ext_chan_busy can be used. */
85
86 if (dfs->dfs_rinfo.dfs_ext_chan_busy &&
87 (dfs->dfs_rinfo.rn_lastfull_ts <
88 dfs->dfs_rinfo.ext_chan_busy_ts)) {
89 *ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy;
90 dfs_debug(dfs, WLAN_DEBUG_DFS2,
91 "Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu",
92 *ext_chan_busy,
93 (uint64_t)dfs->dfs_rinfo.rn_lastfull_ts,
94 (uint64_t)dfs->dfs_rinfo.ext_chan_busy_ts);
95 }
96 }
97
98 #if defined(WLAN_DFS_PARTIAL_OFFLOAD)
dfs_get_pri_margin(struct wlan_dfs * dfs,int is_extchan_detect,int is_fixed_pattern)99 int dfs_get_pri_margin(struct wlan_dfs *dfs,
100 int is_extchan_detect,
101 int is_fixed_pattern)
102 {
103 int adjust_pri = 0, ext_chan_busy = 0;
104 int pri_margin;
105
106 if (is_fixed_pattern)
107 pri_margin = DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN;
108 else
109 pri_margin = DFS_DEFAULT_PRI_MARGIN;
110
111 if (WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan)) {
112 ext_chan_busy = lmac_get_ext_busy(dfs->dfs_pdev_obj);
113 if (ext_chan_busy >= 0) {
114 dfs->dfs_rinfo.ext_chan_busy_ts =
115 lmac_get_tsf64(dfs->dfs_pdev_obj);
116 dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy;
117 } else {
118 dfs_get_cached_ext_chan_busy(dfs, &ext_chan_busy);
119 }
120 adjust_pri = dfs_adjust_pri_per_chan_busy(ext_chan_busy,
121 pri_margin);
122 pri_margin -= adjust_pri;
123 }
124
125 return pri_margin;
126 }
127 #endif
128
dfs_get_filter_threshold(struct wlan_dfs * dfs,struct dfs_filter * rf,int is_extchan_detect)129 int dfs_get_filter_threshold(struct wlan_dfs *dfs,
130 struct dfs_filter *rf,
131 int is_extchan_detect)
132 {
133 int ext_chan_busy = 0;
134 int thresh, adjust_thresh = 0;
135
136 thresh = rf->rf_threshold;
137
138 if (WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan)) {
139 ext_chan_busy = lmac_get_ext_busy(dfs->dfs_pdev_obj);
140 if (ext_chan_busy >= 0) {
141 dfs->dfs_rinfo.ext_chan_busy_ts =
142 lmac_get_tsf64(dfs->dfs_pdev_obj);
143 dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy;
144 } else {
145 dfs_get_cached_ext_chan_busy(dfs, &ext_chan_busy);
146 }
147
148 adjust_thresh =
149 dfs_adjust_thresh_per_chan_busy(ext_chan_busy, thresh);
150 dfs_debug(dfs, WLAN_DEBUG_DFS2,
151 " filterID=%d extchanbusy=%d adjust_thresh=%d",
152 rf->rf_pulseid, ext_chan_busy, adjust_thresh);
153
154 thresh += adjust_thresh;
155 }
156
157 return thresh;
158 }
159
dfs_round(int32_t val)160 uint32_t dfs_round(int32_t val)
161 {
162 uint32_t ival, rem;
163
164 if (val < 0)
165 return 0;
166 ival = val/100;
167 rem = val - (ival * 100);
168 if (rem < 50)
169 return ival;
170 else
171 return ival + 1;
172 }
173