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 */ 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 */ 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 */ 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) 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 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 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