| 1 | --- a/net80211/ieee80211.c |
| 2 | +++ b/net80211/ieee80211.c |
| 3 | @@ -270,6 +270,7 @@ ieee80211_ifattach(struct ieee80211com * |
| 4 | ("invalid number of channels specified: %u", ic->ic_nchans)); |
| 5 | memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); |
| 6 | ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; |
| 7 | + ic->ic_max_txpower = IEEE80211_TXPOWER_MIN; |
| 8 | |
| 9 | for (i = 0; i < ic->ic_nchans; i++) { |
| 10 | c = &ic->ic_channels[i]; |
| 11 | @@ -277,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com * |
| 12 | KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX, |
| 13 | ("channel with bogus ieee number %u", c->ic_ieee)); |
| 14 | setbit(ic->ic_chan_avail, c->ic_ieee); |
| 15 | + ic->ic_max_txpower = max(ic->ic_max_txpower, (u16) (c->ic_maxpower * 2)); |
| 16 | |
| 17 | if (c->ic_scanflags & IEEE80211_NOSCAN_DEFAULT) |
| 18 | c->ic_scanflags |= IEEE80211_NOSCAN_SET; |
| 19 | @@ -346,8 +348,6 @@ ieee80211_ifattach(struct ieee80211com * |
| 20 | TAILQ_INIT(&ic->ic_vaps); |
| 21 | |
| 22 | ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; |
| 23 | - ic->ic_txpowlimit = IEEE80211_TXPOWER_MIN; |
| 24 | - ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX; |
| 25 | |
| 26 | init_timer(&ic->ic_dfs_excl_timer); |
| 27 | ic->ic_dfs_excl_timer.function = |
| 28 | --- a/net80211/ieee80211_node.c |
| 29 | +++ b/net80211/ieee80211_node.c |
| 30 | @@ -1125,7 +1125,7 @@ ieee80211_alloc_node(struct ieee80211vap |
| 31 | |
| 32 | ni->ni_chan = IEEE80211_CHAN_ANYC; |
| 33 | ni->ni_authmode = IEEE80211_AUTH_OPEN; |
| 34 | - ni->ni_txpower = ic->ic_txpowlimit; |
| 35 | + ni->ni_txpower = IEEE80211_TXPOWER_MAX; |
| 36 | |
| 37 | ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, |
| 38 | IEEE80211_KEYIX_NONE); |
| 39 | --- a/net80211/ieee80211_var.h |
| 40 | +++ b/net80211/ieee80211_var.h |
| 41 | @@ -343,8 +343,8 @@ struct ieee80211com { |
| 42 | u_int16_t ic_holdover; /* PM hold over duration */ |
| 43 | u_int16_t ic_bmissthreshold; /* beacon miss threshold (# beacons) */ |
| 44 | unsigned long ic_bmiss_guard; /* when to cease ignoring bmiss (jiffies) */ |
| 45 | - u_int16_t ic_txpowlimit; /* global tx power limit (in 0.5 dBm) */ |
| 46 | - u_int16_t ic_newtxpowlimit; /* tx power limit to change to (in 0.5 dBm) */ |
| 47 | + u_int16_t ic_txpowlimit; /* configured global tx power limit (in 0.5 dBm) */ |
| 48 | + u_int16_t ic_max_txpower; /* global hardware tx power limit */ |
| 49 | u_int16_t ic_uapsdmaxtriggers; /* max triggers that could arrive */ |
| 50 | u_int8_t ic_coverageclass; /* coverage class */ |
| 51 | u_int8_t ic_protmode_rssi; /* rssi threshold for protection mode */ |
| 52 | --- a/net80211/ieee80211_wireless.c |
| 53 | +++ b/net80211/ieee80211_wireless.c |
| 54 | @@ -908,6 +908,21 @@ ieee80211_ioctl_giwessid(struct net_devi |
| 55 | return 0; |
| 56 | } |
| 57 | |
| 58 | +static u16 |
| 59 | +ieee80211_get_maxtxpow(struct ieee80211com *ic) |
| 60 | +{ |
| 61 | + u_int16_t txp = IEEE80211_TXPOWER_MAX; |
| 62 | + |
| 63 | + if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC)) |
| 64 | + txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower); |
| 65 | + |
| 66 | + if (ic->ic_max_txpower > 0) |
| 67 | + txp = min(txp, ic->ic_max_txpower); |
| 68 | + |
| 69 | + return txp; |
| 70 | +} |
| 71 | + |
| 72 | + |
| 73 | static int |
| 74 | ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info, |
| 75 | struct iw_point *data, char *extra) |
| 76 | @@ -920,17 +935,21 @@ ieee80211_ioctl_giwrange(struct net_devi |
| 77 | u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */ |
| 78 | int i, r; |
| 79 | int step = 0; |
| 80 | + u_int16_t power; |
| 81 | |
| 82 | data->length = sizeof(struct iw_range); |
| 83 | memset(range, 0, sizeof(struct iw_range)); |
| 84 | |
| 85 | + power = ieee80211_get_maxtxpow(ic); |
| 86 | + |
| 87 | /* txpower (128 values, but will print out only IW_MAX_TXPOWER) */ |
| 88 | - range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit; |
| 89 | - step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1)); |
| 90 | + power /= 2; /* Unit: 0.5 dBm */ |
| 91 | + range->num_txpower = (power >= 8) ? IW_MAX_TXPOWER : power; |
| 92 | + step = power / (IW_MAX_TXPOWER - 1); |
| 93 | |
| 94 | range->txpower[0] = 0; |
| 95 | for (i = 1; i < IW_MAX_TXPOWER; i++) |
| 96 | - range->txpower[i] = (ic->ic_txpowlimit/2) |
| 97 | + range->txpower[i] = power |
| 98 | - (IW_MAX_TXPOWER - i - 1) * step; |
| 99 | |
| 100 | range->txpower_capa = IW_TXPOW_DBM; |
| 101 | @@ -1379,13 +1398,11 @@ ieee80211_ioctl_siwtxpow(struct net_devi |
| 102 | int fixed, disabled; |
| 103 | |
| 104 | fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED); |
| 105 | - disabled = (fixed && vap->iv_bss->ni_txpower == 0); |
| 106 | + disabled = (fixed && ic->ic_txpowlimit == 0); |
| 107 | if (rrq->disabled) { |
| 108 | if (!disabled) { |
| 109 | - if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) |
| 110 | - return -EOPNOTSUPP; |
| 111 | ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; |
| 112 | - vap->iv_bss->ni_txpower = 0; |
| 113 | + ic->ic_txpowlimit = 0; |
| 114 | goto done; |
| 115 | } |
| 116 | return 0; |
| 117 | @@ -1396,30 +1413,12 @@ ieee80211_ioctl_siwtxpow(struct net_devi |
| 118 | return -EOPNOTSUPP; |
| 119 | if (rrq->flags != IW_TXPOW_DBM) |
| 120 | return -EINVAL; |
| 121 | - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) { |
| 122 | - if ((ic->ic_bsschan->ic_maxregpower >= rrq->value) && |
| 123 | - (ic->ic_txpowlimit/2 >= rrq->value)) { |
| 124 | - vap->iv_bss->ni_txpower = 2 * rrq->value; |
| 125 | - ic->ic_newtxpowlimit = 2 * rrq->value; |
| 126 | - ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; |
| 127 | - } else |
| 128 | - return -EINVAL; |
| 129 | - } else { |
| 130 | - /* |
| 131 | - * No channel set yet |
| 132 | - */ |
| 133 | - if (ic->ic_txpowlimit/2 >= rrq->value) { |
| 134 | - vap->iv_bss->ni_txpower = 2 * rrq->value; |
| 135 | - ic->ic_newtxpowlimit = 2 * rrq->value; |
| 136 | - ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; |
| 137 | - } |
| 138 | - else |
| 139 | - return -EINVAL; |
| 140 | - } |
| 141 | + ic->ic_txpowlimit = 2 * rrq->value; |
| 142 | + ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; |
| 143 | } else { |
| 144 | if (!fixed) /* no change */ |
| 145 | return 0; |
| 146 | - ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX; |
| 147 | + ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; |
| 148 | ic->ic_flags &= ~IEEE80211_F_TXPOW_FIXED; |
| 149 | } |
| 150 | done: |
| 151 | @@ -1588,9 +1587,18 @@ ieee80211_ioctl_giwtxpow(struct net_devi |
| 152 | { |
| 153 | struct ieee80211vap *vap = dev->priv; |
| 154 | struct ieee80211com *ic = vap->iv_ic; |
| 155 | - |
| 156 | - rrq->value = vap->iv_bss->ni_txpower / 2; |
| 157 | - rrq->fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) != 0; |
| 158 | + unsigned int power = ic->ic_txpowlimit; |
| 159 | + struct ieee80211_channel *c; |
| 160 | + u_int16_t txp; |
| 161 | + |
| 162 | + txp = ieee80211_get_maxtxpow(ic); |
| 163 | + if (ic->ic_flags & IEEE80211_F_TXPOW_FIXED) { |
| 164 | + txp = min(txp, ic->ic_txpowlimit); |
| 165 | + rrq->fixed = 1; |
| 166 | + } else { |
| 167 | + rrq->fixed = 0; |
| 168 | + } |
| 169 | + rrq->value = txp / 2; |
| 170 | rrq->disabled = (rrq->fixed && rrq->value == 0); |
| 171 | rrq->flags = IW_TXPOW_DBM; |
| 172 | return 0; |
| 173 | --- a/ath/if_ath.c |
| 174 | +++ b/ath/if_ath.c |
| 175 | @@ -380,7 +380,6 @@ static unsigned int ath_dump_hal_map(str |
| 176 | static u_int32_t ath_get_clamped_maxtxpower(struct ath_softc *sc); |
| 177 | static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, |
| 178 | u_int32_t new_clamped_maxtxpower); |
| 179 | -static u_int32_t ath_get_real_maxtxpower(struct ath_softc *sc); |
| 180 | |
| 181 | static void ath_poll_disable(struct net_device *dev); |
| 182 | static void ath_poll_enable(struct net_device *dev); |
| 183 | @@ -3168,7 +3167,7 @@ ath_tx_startraw(struct net_device *dev, |
| 184 | try0 = ph->try0; |
| 185 | rt = sc->sc_currates; |
| 186 | txrate = dot11_to_ratecode(sc, rt, ph->rate0); |
| 187 | - power = ph->power > 60 ? 60 : ph->power; |
| 188 | + power = ph->power > 63 ? 63 : ph->power; |
| 189 | hdrlen = ieee80211_anyhdrsize(wh); |
| 190 | pktlen = skb->len + IEEE80211_CRC_LEN; |
| 191 | |
| 192 | @@ -8394,7 +8393,7 @@ ath_tx_start(struct net_device *dev, str |
| 193 | pktlen, /* packet length */ |
| 194 | hdrlen, /* header length */ |
| 195 | atype, /* Atheros packet type */ |
| 196 | - MIN(ni->ni_txpower, 60), /* txpower */ |
| 197 | + MIN(ni->ni_txpower, 63), /* txpower */ |
| 198 | txrate, try0, /* series 0 rate/tries */ |
| 199 | keyix, /* key cache index */ |
| 200 | antenna, /* antenna mode */ |
| 201 | @@ -10387,59 +10386,16 @@ ath_get_clamped_maxtxpower(struct ath_so |
| 202 | |
| 203 | /* XXX: this function needs some locking to avoid being called |
| 204 | * twice/interrupted */ |
| 205 | -/* 1. Save the currently specified maximum txpower (as clamped by madwifi) |
| 206 | - * 2. Determine the real maximum txpower the card can support by |
| 207 | - * setting a value that exceeds the maximum range (by one) and |
| 208 | - * finding out what it limits us to. |
| 209 | - * 3. Restore the saved maxtxpower value we had previously specified */ |
| 210 | -static u_int32_t |
| 211 | -ath_get_real_maxtxpower(struct ath_softc *sc) |
| 212 | -{ |
| 213 | - u_int32_t saved_clamped_maxtxpower; |
| 214 | - u_int32_t real_maxtxpower; |
| 215 | - |
| 216 | - saved_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc); |
| 217 | - real_maxtxpower = |
| 218 | - ath_set_clamped_maxtxpower(sc, IEEE80211_TXPOWER_MAX + 1); |
| 219 | - ath_set_clamped_maxtxpower(sc, saved_clamped_maxtxpower); |
| 220 | - return real_maxtxpower; |
| 221 | -} |
| 222 | - |
| 223 | - |
| 224 | -/* XXX: this function needs some locking to avoid being called |
| 225 | - * twice/interrupted */ |
| 226 | static void |
| 227 | ath_update_txpow(struct ath_softc *sc) |
| 228 | { |
| 229 | struct ieee80211com *ic = &sc->sc_ic; |
| 230 | struct ieee80211vap *vap = NULL; |
| 231 | struct ath_hal *ah = sc->sc_ah; |
| 232 | - u_int32_t prev_clamped_maxtxpower = 0; |
| 233 | - u_int32_t new_clamped_maxtxpower = 0; |
| 234 | |
| 235 | /* Determine the previous value of maxtxpower */ |
| 236 | - prev_clamped_maxtxpower = ath_get_clamped_maxtxpower(sc); |
| 237 | - /* Determine the real maximum txpower the card can support */ |
| 238 | - ic->ic_txpowlimit = ath_get_real_maxtxpower(sc); |
| 239 | - /* Grab the new maxtxpower setting (which may have changed) */ |
| 240 | - new_clamped_maxtxpower = ic->ic_newtxpowlimit; |
| 241 | - /* Make sure the change is within limits, clamp it otherwise */ |
| 242 | - if (ic->ic_newtxpowlimit > ic->ic_txpowlimit) |
| 243 | - new_clamped_maxtxpower = ic->ic_txpowlimit; |
| 244 | - /* Search for the VAP that needs a txpow change, if any */ |
| 245 | - TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { |
| 246 | - if (!tpc || ic->ic_newtxpowlimit != vap->iv_bss->ni_txpower) { |
| 247 | - vap->iv_bss->ni_txpower = new_clamped_maxtxpower; |
| 248 | - ieee80211_iterate_nodes(&vap->iv_ic->ic_sta, |
| 249 | - set_node_txpower, |
| 250 | - &new_clamped_maxtxpower); |
| 251 | - } |
| 252 | - } |
| 253 | - |
| 254 | - /* Store the assigned (clamped) maximum txpower and update the HAL */ |
| 255 | - sc->sc_curtxpow = new_clamped_maxtxpower; |
| 256 | - if (new_clamped_maxtxpower != prev_clamped_maxtxpower) |
| 257 | - ath_hal_settxpowlimit(ah, new_clamped_maxtxpower); |
| 258 | + ath_set_clamped_maxtxpower(sc, ic->ic_txpowlimit); |
| 259 | + ic->ic_max_txpower = ath_get_clamped_maxtxpower(sc); |
| 260 | } |
| 261 | |
| 262 | #ifdef ATH_SUPERG_XR |
| 263 | |