diff options
| -rw-r--r-- | package/madwifi/patches/414-txpower.patch | 243 | 
1 files changed, 243 insertions, 0 deletions
diff --git a/package/madwifi/patches/414-txpower.patch b/package/madwifi/patches/414-txpower.patch new file mode 100644 index 000000000..3e7e315d1 --- /dev/null +++ b/package/madwifi/patches/414-txpower.patch @@ -0,0 +1,243 @@ +--- 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, 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; +@@ -1382,10 +1388,8 @@ ieee80211_ioctl_siwtxpow(struct net_devi + 	disabled = (fixed && vap->iv_bss->ni_txpower == 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, 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  | 
