aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorNick Kossifidis <mick@madwifi-project.org>2009-04-30 15:55:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:14:55 -0400
commita082381044ce026e83dbd17f8837722b028fc07d (patch)
tree181ef0bcdf8b69fa5aaf20da4b1e811feb57abd6 /drivers/net
parent15e469284d5e89c9113379b68566b0e059a97704 (diff)
ath5k: Allow user/driver to set txpower
* Now that we have regulatory control enable the driver to set txpower on hw * Also use txpower table offset so that we can match power range set by user/driver with indices on power table. Tested 2 different cards (a CM9 and an RF5112-based ubnt) and got the same output using a remote machine to measure per-packet rssi (conected the cards using attenuators). I also switched between various tx power levels and i saw an equal power change on the remote machine (so txpower changes as expected) and verified that we have the same output on each rate. Signed-off-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h7
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c11
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c45
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c2
4 files changed, 52 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 60c6d2edc4b9..04b73453f6a5 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1100,11 +1100,12 @@ struct ath5k_hw {
1100 /* Values in 0.25dB units */ 1100 /* Values in 0.25dB units */
1101 s16 txp_min_pwr; 1101 s16 txp_min_pwr;
1102 s16 txp_max_pwr; 1102 s16 txp_max_pwr;
1103 /* Values in 0.5dB units */
1103 s16 txp_offset; 1104 s16 txp_offset;
1104 s16 txp_ofdm; 1105 s16 txp_ofdm;
1105 /* Values in dB units */
1106 s16 txp_cck_ofdm_pwr_delta;
1107 s16 txp_cck_ofdm_gainf_delta; 1106 s16 txp_cck_ofdm_gainf_delta;
1107 /* Value in dB units */
1108 s16 txp_cck_ofdm_pwr_delta;
1108 } ah_txpower; 1109 } ah_txpower;
1109 1110
1110 struct { 1111 struct {
@@ -1271,7 +1272,7 @@ extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
1271extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); 1272extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
1272/* TX power setup */ 1273/* TX power setup */
1273extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); 1274extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower);
1274extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); 1275extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
1275 1276
1276/* 1277/*
1277 * Functions used internaly 1278 * Functions used internaly
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 7b80cebffd41..d70856a9520e 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2747,12 +2747,21 @@ static int
2747ath5k_config(struct ieee80211_hw *hw, u32 changed) 2747ath5k_config(struct ieee80211_hw *hw, u32 changed)
2748{ 2748{
2749 struct ath5k_softc *sc = hw->priv; 2749 struct ath5k_softc *sc = hw->priv;
2750 struct ath5k_hw *ah = sc->ah;
2750 struct ieee80211_conf *conf = &hw->conf; 2751 struct ieee80211_conf *conf = &hw->conf;
2751 int ret; 2752 int ret;
2752 2753
2753 mutex_lock(&sc->lock); 2754 mutex_lock(&sc->lock);
2754 2755
2755 sc->power_level = conf->power_level; 2756 sc->bintval = conf->beacon_int;
2757
2758 if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
2759 (sc->power_level != conf->power_level)) {
2760 sc->power_level = conf->power_level;
2761
2762 /* Half dB steps */
2763 ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
2764 }
2756 2765
2757 ret = ath5k_chan_set(sc, conf->channel); 2766 ret = ath5k_chan_set(sc, conf->channel);
2758 2767
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index b48b29dca3d2..bb61b8e2dce9 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -168,9 +168,6 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
168 * tx power and a Peak to Average Power Detector (PAPD) will try 168 * tx power and a Peak to Average Power Detector (PAPD) will try
169 * to measure the gain. 169 * to measure the gain.
170 * 170 *
171 * TODO: Use propper tx power setting for the probe packet so
172 * that we don't observe a serious power drop on the receiver
173 *
174 * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) 171 * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc)
175 * just after we enable the probe so that we don't mess with 172 * just after we enable the probe so that we don't mess with
176 * standard traffic ? Maybe it's time to use sw interrupts and 173 * standard traffic ? Maybe it's time to use sw interrupts and
@@ -186,7 +183,7 @@ static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
186 183
187 /* Send the packet with 2dB below max power as 184 /* Send the packet with 2dB below max power as
188 * patent doc suggest */ 185 * patent doc suggest */
189 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4, 186 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4,
190 AR5K_PHY_PAPD_PROBE_TXPOWER) | 187 AR5K_PHY_PAPD_PROBE_TXPOWER) |
191 AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); 188 AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
192 189
@@ -2482,8 +2479,19 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
2482 for (i = 8; i <= 15; i++) 2479 for (i = 8; i <= 15; i++)
2483 rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; 2480 rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
2484 2481
2485 ah->ah_txpower.txp_min_pwr = rates[7]; 2482 /* Now that we have all rates setup use table offset to
2486 ah->ah_txpower.txp_max_pwr = rates[0]; 2483 * match the power range set by user with the power indices
2484 * on PCDAC/PDADC table */
2485 for (i = 0; i < 16; i++) {
2486 rates[i] += ah->ah_txpower.txp_offset;
2487 /* Don't get out of bounds */
2488 if (rates[i] > 63)
2489 rates[i] = 63;
2490 }
2491
2492 /* Min/max in 0.25dB units */
2493 ah->ah_txpower.txp_min_pwr = 2 * rates[7];
2494 ah->ah_txpower.txp_max_pwr = 2 * rates[0];
2487 ah->ah_txpower.txp_ofdm = rates[7]; 2495 ah->ah_txpower.txp_ofdm = rates[7];
2488} 2496}
2489 2497
@@ -2591,16 +2599,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
2591 return 0; 2599 return 0;
2592} 2600}
2593 2601
2594int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) 2602int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
2595{ 2603{
2596 /*Just a try M.F.*/ 2604 /*Just a try M.F.*/
2597 struct ieee80211_channel *channel = &ah->ah_current_channel; 2605 struct ieee80211_channel *channel = &ah->ah_current_channel;
2606 u8 ee_mode;
2598 2607
2599 ATH5K_TRACE(ah->ah_sc); 2608 ATH5K_TRACE(ah->ah_sc);
2609
2610 switch (channel->hw_value & CHANNEL_MODES) {
2611 case CHANNEL_A:
2612 case CHANNEL_T:
2613 case CHANNEL_XR:
2614 ee_mode = AR5K_EEPROM_MODE_11A;
2615 break;
2616 case CHANNEL_G:
2617 case CHANNEL_TG:
2618 ee_mode = AR5K_EEPROM_MODE_11G;
2619 break;
2620 case CHANNEL_B:
2621 ee_mode = AR5K_EEPROM_MODE_11B;
2622 break;
2623 default:
2624 ATH5K_ERR(ah->ah_sc,
2625 "invalid channel: %d\n", channel->center_freq);
2626 return -EINVAL;
2627 }
2628
2600 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, 2629 ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
2601 "changing txpower to %d\n", txpower); 2630 "changing txpower to %d\n", txpower);
2602 2631
2603 return ath5k_hw_txpower(ah, channel, mode, txpower); 2632 return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
2604} 2633}
2605 2634
2606#undef _ATH5K_PHY 2635#undef _ATH5K_PHY
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 775fdf78554b..cb8a9a1398c9 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1000,7 +1000,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1000 * Set TX power (FIXME) 1000 * Set TX power (FIXME)
1001 */ 1001 */
1002 ret = ath5k_hw_txpower(ah, channel, ee_mode, 1002 ret = ath5k_hw_txpower(ah, channel, ee_mode,
1003 AR5K_TUNE_DEFAULT_TXPOWER); 1003 ah->ah_txpower.txp_max_pwr / 2);
1004 if (ret) 1004 if (ret)
1005 return ret; 1005 return ret;
1006 1006