The calculation of TX power has recently been improved in b43. This patch implements those improvements in b43legacy, and may help with association/authentication with distant APs.
With this patch, the estimated power out calculation becomes quite stable. After the initial settling, the estimate varies by 0.25 dBm, or less. Signed-off-by: Larry Finger <[EMAIL PROTECTED]> --- Index: wireless-testing/drivers/net/wireless/b43legacy/phy.c =================================================================== --- wireless-testing.orig/drivers/net/wireless/b43legacy/phy.c +++ wireless-testing/drivers/net/wireless/b43legacy/phy.c @@ -1766,6 +1766,58 @@ static s8 b43legacy_phy_estimate_power_o return dbm; } +void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt) +{ + int rfatt = *_rfatt; + int bbatt = *_bbatt; + + /* Get baseband and radio attenuation values into their permitted + * ranges. Radio attenuation affects power level 4 times as much as + * baseband. */ + + /* Range constants */ + const int rf_min = 0; + const int rf_max = 9; + const int bb_min = 0; + const int bb_max = 8; + + while (1) { + if (rfatt > rf_max && bbatt > bb_max - 4) + break; /* Can not get it into ranges */ + if (rfatt < rf_min && bbatt < bb_min + 4) + break; /* Can not get it into ranges */ + if (bbatt > bb_max && rfatt > rf_max - 1) + break; /* Can not get it into ranges */ + if (bbatt < bb_min && rfatt < rf_min + 1) + break; /* Can not get it into ranges */ + + if (bbatt > bb_max) { + bbatt -= 4; + rfatt += 1; + continue; + } + if (bbatt < bb_min) { + bbatt += 4; + rfatt -= 1; + continue; + } + if (rfatt > rf_max) { + rfatt -= 1; + bbatt += 4; + continue; + } + if (rfatt < rf_min) { + rfatt += 1; + bbatt -= 4; + continue; + } + break; + } + + *_rfatt = limit_value(rfatt, rf_min, rf_max); + *_bbatt = limit_value(bbatt, bb_min, bb_max); +} + /* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev) { @@ -1783,8 +1835,8 @@ void b43legacy_phy_xmitpower(struct b43l s16 pwr_adjust; s16 radio_att_delta; s16 baseband_att_delta; - s16 radio_attenuation; - s16 baseband_attenuation; + int radio_attenuation; + int baseband_attenuation; if (phy->savedpctlreg == 0xFFFF) return; @@ -1833,7 +1885,8 @@ void b43legacy_phy_xmitpower(struct b43l estimated_pwr = b43legacy_phy_estimate_power_out(dev, average); - max_pwr = dev->dev->bus->sprom.maxpwr_bg; + max_pwr = dev->dev->bus->sprom.maxpwr_bg + - dev->dev->bus->sprom.antenna_gain.ghz24.a0; if ((dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) && @@ -1846,28 +1899,23 @@ void b43legacy_phy_xmitpower(struct b43l dev->dev->bus->sprom.maxpwr_bg = max_pwr; } - /* Use regulatory information to get the maximum power. - * In the absence of such data from mac80211, we will use 20 dBm, which - * is the value for the EU, US, Canada, and most of the world. - * The regulatory maximum is reduced by the antenna gain (from sprom) - * and 1.5 dBm (a safety factor??). The result is in Q5.2 format - * which accounts for the factor of 4 */ -#define REG_MAX_PWR 20 - max_pwr = min(REG_MAX_PWR * 4 - - dev->dev->bus->sprom.antenna_gain.ghz24.a0 - - 0x6, max_pwr); - - /* find the desired power in Q5.2 - power_level is in dBm - * and limit it - max_pwr is already in Q5.2 */ - desired_pwr = limit_value(phy->power_level << 2, 0, max_pwr); + /* Get desired power (in Q5.2) */ + desired_pwr = phy->power_level << 2; + if (unlikely(desired_pwr <= 0)) { + b43legacywarn(dev->wl, "Invalid power_level\n"); + phy->power_level = 15; + desired_pwr = phy->power_level << 2; + } + /* And limit it. max_pwr already is Q5.2 */ + desired_pwr = limit_value(desired_pwr, 0, max_pwr); + if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER)) b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT " dBm, Desired TX power output: " Q52_FMT " dBm\n", Q52_ARG(estimated_pwr), Q52_ARG(desired_pwr)); - /* Check if we need to adjust the current power. The factor of 2 is - * for damping */ - pwr_adjust = (desired_pwr - estimated_pwr) / 2; + /* Check if we need to adjust the current power */ + pwr_adjust = desired_pwr - estimated_pwr; /* RF attenuation delta * The minus sign is because lower attenuation => more power */ radio_att_delta = -(pwr_adjust + 7) >> 3; @@ -1876,7 +1924,6 @@ void b43legacy_phy_xmitpower(struct b43l /* Do we need to adjust anything? */ if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { b43legacy_phy_lo_mark_current_used(dev); - return; } /* Calculate the new attenuation values. */ @@ -1885,28 +1932,9 @@ void b43legacy_phy_xmitpower(struct b43l radio_attenuation = phy->rfatt; radio_attenuation += radio_att_delta; - /* Get baseband and radio attenuation values into permitted ranges. - * baseband 0-11, radio 0-9. - * Radio attenuation affects power level 4 times as much as baseband. - */ - if (radio_attenuation < 0) { - baseband_attenuation -= (4 * -radio_attenuation); - radio_attenuation = 0; - } else if (radio_attenuation > 9) { - baseband_attenuation += (4 * (radio_attenuation - 9)); - radio_attenuation = 9; - } else { - while (baseband_attenuation < 0 && radio_attenuation > 0) { - baseband_attenuation += 4; - radio_attenuation--; - } - while (baseband_attenuation > 11 && radio_attenuation < 9) { - baseband_attenuation -= 4; - radio_attenuation++; - } - } - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - + /* Get baseband and radio attenuation values into permitted ranges. */ + b43legacy_put_attenuation_into_ranges(&baseband_attenuation, + &radio_attenuation); txpower = phy->txctl1; if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { if (radio_attenuation <= 1) { @@ -1933,8 +1961,8 @@ void b43legacy_phy_xmitpower(struct b43l } /* Save the control values */ phy->txctl1 = txpower; - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - radio_attenuation = limit_value(radio_attenuation, 0, 9); + b43legacy_put_attenuation_into_ranges(&baseband_attenuation, + &radio_attenuation); phy->rfatt = radio_attenuation; phy->bbatt = baseband_attenuation; Index: wireless-testing/drivers/net/wireless/b43legacy/phy.h =================================================================== --- wireless-testing.orig/drivers/net/wireless/b43legacy/phy.h +++ wireless-testing/drivers/net/wireless/b43legacy/phy.h @@ -160,8 +160,6 @@ void b43legacy_put_attenuation_into_rang #define B43legacy_PHY_DC_LTBASE B43legacy_PHY_OFDM(0x3A0) /* DC lookup table base */ #define B43legacy_PHY_GAIN_LTBASE B43legacy_PHY_OFDM(0x3C0) /* Gain lookup table base */ -void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt); - /* Masks for the different PHY versioning registers. */ #define B43legacy_PHYVER_ANALOG 0xF000 #define B43legacy_PHYVER_ANALOG_SHIFT 12 Index: wireless-testing/drivers/net/wireless/b43legacy/main.c =================================================================== --- wireless-testing.orig/drivers/net/wireless/b43legacy/main.c +++ wireless-testing/drivers/net/wireless/b43legacy/main.c @@ -127,6 +127,7 @@ static struct ieee80211_rate __b43legacy { \ .center_freq = (_freq), \ .hw_value = (_chanid), \ + .max_power = 30, \ } static struct ieee80211_channel b43legacy_bg_chantable[] = { CHANTAB_ENT(1, 2412), _______________________________________________ Bcm43xx-dev mailing list Bcm43xx-dev@lists.berlios.de https://lists.berlios.de/mailman/listinfo/bcm43xx-dev