diff options
author | Nick Kossifidis <mick@madwifi-project.org> | 2009-04-30 15:55:44 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-05-06 15:14:55 -0400 |
commit | a082381044ce026e83dbd17f8837722b028fc07d (patch) | |
tree | 181ef0bcdf8b69fa5aaf20da4b1e811feb57abd6 /drivers/net | |
parent | 15e469284d5e89c9113379b68566b0e059a97704 (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.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 2 |
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); | |||
1271 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); | 1272 | extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1272 | /* TX power setup */ | 1273 | /* TX power setup */ |
1273 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); | 1274 | extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); |
1274 | extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 ee_mode, u8 txpower); | 1275 | extern 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 | |||
2747 | ath5k_config(struct ieee80211_hw *hw, u32 changed) | 2747 | ath5k_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 | ||
2594 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 mode, u8 txpower) | 2602 | int 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 | ||