mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 14:34:27 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- 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,8 @@ 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_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
 | 
						|
@@ -908,6 +908,21 @@ ieee80211_ioctl_giwessid(struct net_devi
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static u16
 | 
						|
+ieee80211_get_maxtxpow(struct ieee80211com *ic)
 | 
						|
+{
 | 
						|
+	u_int16_t txp = IEEE80211_TXPOWER_MAX;
 | 
						|
+
 | 
						|
+	if (ic->ic_bsschan && (ic->ic_bsschan != IEEE80211_CHAN_ANYC))
 | 
						|
+		txp = min(txp, (u16) ic->ic_bsschan->ic_maxpower);
 | 
						|
+
 | 
						|
+	if (ic->ic_max_txpower > 0)
 | 
						|
+		txp = min(txp, ic->ic_max_txpower);
 | 
						|
+
 | 
						|
+	return txp;
 | 
						|
+}
 | 
						|
+
 | 
						|
+
 | 
						|
 static int
 | 
						|
 ieee80211_ioctl_giwrange(struct net_device *dev, struct iw_request_info *info,
 | 
						|
 	struct iw_point *data, char *extra)
 | 
						|
@@ -920,17 +935,21 @@ 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 = ieee80211_get_maxtxpow(ic);
 | 
						|
+
 | 
						|
 	/* 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 +1398,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 +1413,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 +1587,18 @@ 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;
 | 
						|
+
 | 
						|
+	txp = ieee80211_get_maxtxpow(ic);
 | 
						|
+	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);
 | 
						|
@@ -3168,7 +3167,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;
 | 
						|
 
 | 
						|
@@ -8394,7 +8393,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 */
 | 
						|
@@ -10387,59 +10386,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_max_txpower = ath_get_clamped_maxtxpower(sc);
 | 
						|
 }
 | 
						|
 
 | 
						|
 #ifdef ATH_SUPERG_XR
 |