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