svn commit: r249580 - in head/sys/dev/ath/ath_hal: ar5416 ar9002

Adrian Chadd adrian at FreeBSD.org
Wed Apr 17 07:31:55 UTC 2013


Author: adrian
Date: Wed Apr 17 07:31:53 2013
New Revision: 249580
URL: http://svnweb.freebsd.org/changeset/base/249580

Log:
  Setup needed tables for TPC on AR5416->AR9287 chips.
  
  * Add ah_ratesArray[] to the ar5416 HAL state - this stores the maximum
    values permissable per rate.
  * Since different chip EEPROM formats store this value in a different place,
    store the HT40 power detector increment value in the ar5416 HAL state.
  * Modify the target power setup code to store the maximum values in the
    ar5416 HAL state rather than using a local variable.
  * Add ar5416RateToRateTable() - to convert a hardware rate code to the
    ratesArray enum / index.
  * Add ar5416GetTxRatePower() - which goes through the gymnastics required
    to correctly calculate the target TX power:
    + Add the power detector increment for ht40;
    + Take the power offset into account for AR9280 and later;
    + Offset the TX power correctly when doing open-loop TX power control;
    + Enforce the per-rate maximum value allowable.
  
  Note - setting a TPC value of 0x0 in the TX descriptor on (at least)
  the AR9160 resulted in the TX power being very high indeed.  This didn't
  happen on the AR9220.  I'm guessing it's a chip bug that was fixed at
  some point.  So for now, just assume the AR5416/AR5418 and AR9130 are
  also suspect and clamp the minimum value here at 1.
  
  Tested:
  
  * AR5416, AR9160, AR9220 hostap, verified using (2GHz) spectrum analyser
  * Looked at target TX power in TX descriptor (using athalq) as well as TX
    power on the spectrum analyser.
  
  TODO:
  
  * The TX descriptor code sets the target TX power to 0 for AR9285 chips.
    I'm not yet sure why.  Disable this for TPC and ensure that the TPC
    TX power is set.
  * AR9280, AR9285, AR9227, AR9287 testing!
  * 5GHz testing!
  
  Quirks:
  
  * The per-packet TPC code is only exercised when the tpc sysctl is set
    to 1. (dev.ath.X.tpc=1.) This needs to be done before you bring the
    interface up.
  * When TPC is enabled, setting the TX power doesn't end up with a call
    through to the HAL to update the maximum TX power.  So ensure that
    you set the TPC sysctl before you bring the interface up and configure
    a lower TX power or the hardware will be clamped by the lower TX
    power (at least until the next channel change.)
  
  Thanks to Qualcomm Atheros for all the hardware, and Sam Leffler for use
  of his spectrum analyser to verify the TX channel power.

Modified:
  head/sys/dev/ath/ath_hal/ar5416/ar5416.h
  head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
  head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
  head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c
  head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c

Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416.h
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5416/ar5416.h	Wed Apr 17 07:22:23 2013	(r249579)
+++ head/sys/dev/ath/ath_hal/ar5416/ar5416.h	Wed Apr 17 07:31:53 2013	(r249580)
@@ -132,7 +132,12 @@ struct ath_hal_5416 {
 	struct ar5416NfLimits nf_2g;
 	struct ar5416NfLimits nf_5g;
 
+	/*
+	 * TX power configuration related structures
+	 */
 	int		initPDADC;
+	int		ah_ht40PowerIncForPdadc;
+	int16_t		ah_ratesArray[Ar5416RateSize];
 
 	int		ah_need_an_top2_fixup;	/* merlin or later chips that may need this workaround */
 

Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c	Wed Apr 17 07:22:23 2013	(r249579)
+++ head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c	Wed Apr 17 07:31:53 2013	(r249580)
@@ -1005,6 +1005,14 @@ ar5416WriteTxPowerRateRegisters(struct a
               | POW_SM(ratesArray[rateDupCck], 0)
         );
     }
+
+    /*
+     * Set max power to 30 dBm and, optionally,
+     * enable TPC in tx descriptors.
+     */
+    OS_REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER |
+      (AH5212(ah)->ah_tpcEnabled ? AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE : 0));
+#undef POW_SM
 }
 
 
@@ -1019,12 +1027,11 @@ ar5416SetTransmitPower(struct ath_hal *a
 	const struct ieee80211_channel *chan, uint16_t *rfXpdGain)
 {
 #define N(a)            (sizeof (a) / sizeof (a[0]))
+#define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
 
     MODAL_EEP_HEADER	*pModal;
     struct ath_hal_5212 *ahp = AH5212(ah);
-    int16_t		ratesArray[Ar5416RateSize];
     int16_t		txPowerIndexOffset = 0;
-    uint8_t		ht40PowerIncForPdadc = 2;	
     int			i;
     
     uint16_t		cfgCtl;
@@ -1037,8 +1044,13 @@ ar5416SetTransmitPower(struct ath_hal *a
 
     HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
 
+    /*
+     * Default to 2, is overridden based on the EEPROM version / value.
+     */
+    AH5416(ah)->ah_ht40PowerIncForPdadc = 2;
+
     /* Setup info for the actual eeprom */
-    OS_MEMZERO(ratesArray, sizeof(ratesArray));
+    OS_MEMZERO(AH5416(ah)->ah_ratesArray, sizeof(AH5416(ah)->ah_ratesArray));
     cfgCtl = ath_hal_getctl(ah, chan);
     powerLimit = chan->ic_maxregpower * 2;
     twiceAntennaReduction = chan->ic_maxantgain;
@@ -1048,11 +1060,12 @@ ar5416SetTransmitPower(struct ath_hal *a
 	__func__,chan->ic_freq, cfgCtl );      
   
     if (IS_EEP_MINOR_V2(ah)) {
-        ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
     }
  
     if (!ar5416SetPowerPerRateTable(ah, pEepData,  chan,
-                                    &ratesArray[0],cfgCtl,
+                                    &AH5416(ah)->ah_ratesArray[0],
+				    cfgCtl,
                                     twiceAntennaReduction,
 				    twiceMaxRegulatoryPower, powerLimit)) {
         HALDEBUG(ah, HAL_DEBUG_ANY,
@@ -1066,14 +1079,15 @@ ar5416SetTransmitPower(struct ath_hal *a
         return AH_FALSE;
     }
   
-    maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
+    maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb],
+      AH5416(ah)->ah_ratesArray[rateHt20_0]);
 
     if (IEEE80211_IS_CHAN_2GHZ(chan)) {
-        maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+        maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rate1l]);
     }
 
     if (IEEE80211_IS_CHAN_HT40(chan)) {
-        maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+        maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rateHt40_0]);
     }
 
     ahp->ah_tx6PowerInHalfDbm = maxPower;   
@@ -1084,10 +1098,11 @@ ar5416SetTransmitPower(struct ath_hal *a
      * txPowerIndexOffset is set by the SetPowerTable() call -
      *  adjust the rate table (0 offset if rates EEPROM not loaded)
      */
-    for (i = 0; i < N(ratesArray); i++) {
-        ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
-        if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-            ratesArray[i] = AR5416_MAX_RATE_POWER;
+    for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) {
+        AH5416(ah)->ah_ratesArray[i] =
+          (int16_t)(txPowerIndexOffset + AH5416(ah)->ah_ratesArray[i]);
+        if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER)
+            AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER;
     }
 
 #ifdef AH_EEPROM_DUMP
@@ -1098,7 +1113,7 @@ ar5416SetTransmitPower(struct ath_hal *a
      * this debugging; the values won't necessarily be what's being
      * programmed into the hardware.
      */
-    ar5416PrintPowerPerRate(ah, ratesArray);
+    ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray);
 #endif
 
     /*
@@ -1114,16 +1129,16 @@ ar5416SetTransmitPower(struct ath_hal *a
 	    &pwr_table_offset);
 	/* Underflow power gets clamped at raw value 0 */
 	/* Overflow power gets camped at AR5416_MAX_RATE_POWER */
-	for (i = 0; i < N(ratesArray); i++) {
+	for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) {
 		/*
 		 * + pwr_table_offset is in dBm
 		 * + ratesArray is in 1/2 dBm
 		 */
-		ratesArray[i] -= (pwr_table_offset * 2);
-		if (ratesArray[i] < 0)
-			ratesArray[i] = 0;
-		else if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-		    ratesArray[i] = AR5416_MAX_RATE_POWER;
+		AH5416(ah)->ah_ratesArray[i] -= (pwr_table_offset * 2);
+		if (AH5416(ah)->ah_ratesArray[i] < 0)
+			AH5416(ah)->ah_ratesArray[i] = 0;
+		else if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER)
+		    AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER;
 	}
     }
 
@@ -1150,9 +1165,9 @@ ar5416SetTransmitPower(struct ath_hal *a
         int cck_ofdm_delta = 2;
 	int i;
 	for (i = 0; i < N(adj); i++) {
-            ratesArray[adj[i]] -= cck_ofdm_delta;
-	    if (ratesArray[adj[i]] < 0)
-	        ratesArray[adj[i]] = 0;
+            AH5416(ah)->ah_ratesArray[adj[i]] -= cck_ofdm_delta;
+	    if (AH5416(ah)->ah_ratesArray[adj[i]] < 0)
+	        AH5416(ah)->ah_ratesArray[adj[i]] = 0;
         }
     }
 
@@ -1164,18 +1179,20 @@ ar5416SetTransmitPower(struct ath_hal *a
      * XXX handle overflow/too high power level?
      */
     if (IEEE80211_IS_CHAN_HT40(chan)) {
-	ratesArray[rateHt40_0] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_1] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_2] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_3] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_4] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_5] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_6] += ht40PowerIncForPdadc;
-	ratesArray[rateHt40_7] += ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_0] +=
+	  AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_1] +=
+	  AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_2] += AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_3] += AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_4] += AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_5] += AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_6] += AH5416(ah)->ah_ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ratesArray[rateHt40_7] += AH5416(ah)->ah_ht40PowerIncForPdadc;
     }
 
     /* Write the TX power rate registers */
-    ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray);
+    ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray);
 
     /* Write the Power subtraction for dynamic chain changing, for per-packet powertx */
     OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,

Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c	Wed Apr 17 07:22:23 2013	(r249579)
+++ head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c	Wed Apr 17 07:31:53 2013	(r249580)
@@ -155,6 +155,169 @@ ar5416StopTxDma(struct ath_hal *ah, u_in
 /* NB: accept HT rates */
 #define	isValidTxRate(_r)	((1<<((_r) & 0x7f)) & VALID_TX_RATES)
 
+static inline int
+ar5416RateToRateTable(struct ath_hal *ah, uint8_t rate, HAL_BOOL is_ht40)
+{
+
+	/*
+	 * Handle the non-MCS rates
+	 */
+	switch (rate) {
+	case /*   1 Mb */ 0x1b:
+	case /*   1 MbS*/ 0x1b | 0x4:
+		return (AH5416(ah)->ah_ratesArray[rate1l]);
+	case /*   2 Mb */ 0x1a:
+		return (AH5416(ah)->ah_ratesArray[rate2l]);
+	case /*   2 MbS*/ 0x1a | 0x4:
+		return (AH5416(ah)->ah_ratesArray[rate2s]);
+	case /* 5.5 Mb */ 0x19:
+		return (AH5416(ah)->ah_ratesArray[rate5_5l]);
+	case /* 5.5 MbS*/ 0x19 | 0x4:
+		return (AH5416(ah)->ah_ratesArray[rate5_5s]);
+	case /*  11 Mb */ 0x18:
+		return (AH5416(ah)->ah_ratesArray[rate11l]);
+	case /*  11 MbS*/ 0x18 | 0x4:
+		return (AH5416(ah)->ah_ratesArray[rate11s]);
+	}
+
+	/* OFDM rates */
+	switch (rate) {
+	case /*   6 Mb */ 0x0b:
+		return (AH5416(ah)->ah_ratesArray[rate6mb]);
+	case /*   9 Mb */ 0x0f:
+		return (AH5416(ah)->ah_ratesArray[rate9mb]);
+	case /*  12 Mb */ 0x0a:
+		return (AH5416(ah)->ah_ratesArray[rate12mb]);
+	case /*  18 Mb */ 0x0e:
+		return (AH5416(ah)->ah_ratesArray[rate18mb]);
+	case /*  24 Mb */ 0x09:
+		return (AH5416(ah)->ah_ratesArray[rate24mb]);
+	case /*  36 Mb */ 0x0d:
+		return (AH5416(ah)->ah_ratesArray[rate36mb]);
+	case /*  48 Mb */ 0x08:
+		return (AH5416(ah)->ah_ratesArray[rate48mb]);
+	case /*  54 Mb */ 0x0c:
+		return (AH5416(ah)->ah_ratesArray[rate54mb]);
+	}
+
+	/*
+	 * Handle HT20/HT40 - we only have to do MCS0-7;
+	 * there's no stream differences.
+	 */
+	if ((rate & 0x80) && is_ht40) {
+		return (AH5416(ah)->ah_ratesArray[rateHt40_0 + (rate & 0x7)]);
+	} else if (rate & 0x80) {
+		return (AH5416(ah)->ah_ratesArray[rateHt20_0 + (rate & 0x7)]);
+	}
+
+	/* XXX default (eg XR, bad bad person!) */
+	return (AH5416(ah)->ah_ratesArray[rate6mb]);
+}
+
+/*
+ * Return the TX power to be used for the given rate/chains/TX power.
+ *
+ * There are a bunch of tweaks to make to a given TX power based on
+ * the current configuration, so...
+ */
+static uint16_t
+ar5416GetTxRatePower(struct ath_hal *ah, uint8_t rate, uint8_t tx_chainmask,
+    uint16_t txPower, HAL_BOOL is_ht40)
+{
+	int n_txpower, max_txpower;
+	const int cck_ofdm_delta = 2;
+#define	EEP_MINOR(_ah) \
+	(AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
+#define	IS_EEP_MINOR_V2(_ah)	(EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2)
+
+	/* Take a copy ; we may underflow and thus need to clamp things */
+	n_txpower = txPower;
+
+	/* HT40? Need to adjust the TX power by this */
+	if (is_ht40)
+		n_txpower += AH5416(ah)->ah_ht40PowerIncForPdadc;
+
+	/*
+	 * Merlin? Offset the target TX power offset - it defaults to
+	 * starting at -5.0dBm, but that can change!
+	 *
+	 * Kiwi/Kite? Always -5.0dBm offset.
+	 */
+	if (AR_SREV_KIWI_10_OR_LATER(ah)) {
+		n_txpower -= (AR5416_PWR_TABLE_OFFSET_DB * 2);
+	} else if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+		int8_t pwr_table_offset = 0;
+		/* This is in dBm, convert to 1/2 dBm */
+		(void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET,
+		    &pwr_table_offset);
+		n_txpower -= (pwr_table_offset * 2);
+	}
+
+	/*
+	 * If Open-loop TX power control is used, the CCK rates need
+	 * to be offset by that.
+	 *
+	 * Rates: 2S, 2L, 1S, 1L, 5.5S, 5.5L
+	 *
+	 * XXX Odd, we don't have a PHY table entry for long preamble
+	 * 1mbit CCK?
+	 */
+	if (AR_SREV_MERLIN_20_OR_LATER(ah) &&
+	    ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
+
+		if (rate == 0x19 || rate == 0x1a || rate == 0x1b ||
+		    rate == (0x19 | 0x04) || rate == (0x1a | 0x04) ||
+		    rate == (0x1b | 0x04)) {
+			n_txpower -= cck_ofdm_delta;
+		}
+	}
+
+	/*
+	 * We're now offset by the same amount that the static maximum
+	 * PHY power tables are.  So, clamp the value based on that rate.
+	 */
+	max_txpower = ar5416RateToRateTable(ah, rate, is_ht40);
+#if 0
+	ath_hal_printf(ah, "%s: n_txpower = %d, max_txpower = %d, "
+	    "rate = 0x%x , is_ht40 = %d\n",
+	    __func__,
+	    n_txpower,
+	    max_txpower,
+	    rate,
+	    is_ht40);
+#endif
+	n_txpower = MIN(max_txpower, n_txpower);
+
+	/*
+	 * We don't have to offset the TX power for two or three
+	 * chain operation here - it's done by the AR_PHY_POWER_TX_SUB
+	 * register setting via the EEPROM.
+	 *
+	 * So for vendors that programmed the maximum target power assuming
+	 * that 2/3 chains are always on, things will just plain work.
+	 * (They won't reach that target power if only one chain is on, but
+	 * that's a different problem.)
+	 */
+
+	/* Over/underflow? Adjust */
+	if (n_txpower < 0)
+		n_txpower = 0;
+	else if (n_txpower > 63)
+		n_txpower = 63;
+
+	/*
+	 * For some odd reason the AR9160 with txpower=0 results in a
+	 * much higher (max?) TX power.  So, if it's a chipset before
+	 * AR9220/AR9280, just clamp the minimum value at 1.
+	 */
+	if ((! AR_SREV_MERLIN_10_OR_LATER(ah)) && (n_txpower == 0))
+		n_txpower = 1;
+
+	return (n_txpower);
+#undef	EEP_MINOR
+#undef	IS_EEP_MINOR_V2
+}
+
 HAL_BOOL
 ar5416SetupTxDesc(struct ath_hal *ah, struct ath_desc *ds,
 	u_int pktLen,
@@ -187,6 +350,16 @@ ar5416SetupTxDesc(struct ath_hal *ah, st
         if (txPower > 63)
 		txPower = 63;
 
+	/*
+	 * XXX For now, just assume that this isn't a HT40 frame.
+	 */
+	if (AH5212(ah)->ah_tpcEnabled) {
+		txPower = ar5416GetTxRatePower(ah, txRate0,
+		    ahp->ah_tx_chainmask,
+		    txPower,
+		    AH_FALSE);
+	}
+
 	ads->ds_ctl0 = (pktLen & AR_FrameLen)
 		     | (txPower << AR_XmitPower_S)
 		     | (flags & HAL_TXDESC_VEOL ? AR_VEOL : 0)
@@ -238,6 +411,8 @@ ar5416SetupTxDesc(struct ath_hal *ah, st
 	 * Set the TX antenna to 0 for Kite
 	 * To preserve existing behaviour, also set the TPC bits to 0;
 	 * when TPC is enabled these should be filled in appropriately.
+	 *
+	 * XXX TODO: when doing TPC, set the TX power up appropriately?
 	 */
 	if (AR_SREV_KITE(ah)) {
 		ads->ds_ctl8 = SM(0, AR_AntCtl0);
@@ -744,6 +919,48 @@ ar5416Set11nRateScenario(struct ath_hal 
 		     | set11nRateFlags(series, 2)
 		     | set11nRateFlags(series, 3)
 		     | SM(rtsctsRate, AR_RTSCTSRate);
+
+	/*
+	 * Doing per-packet TPC - update the TX power for the first
+	 * field; program in the other series.
+	 */
+	if (AH5212(ah)->ah_tpcEnabled) {
+		uint32_t ds_ctl0;
+		uint16_t txPower;
+
+		/* Modify the tx power field for rate 0 */
+		txPower = ar5416GetTxRatePower(ah, series[0].Rate,
+		    series[0].ChSel,
+		    series[0].tx_power_cap,
+		    !! (series[0].RateFlags & HAL_RATESERIES_2040));
+		ds_ctl0 = ads->ds_ctl0 & ~AR_XmitPower;
+		ds_ctl0 |= (txPower << AR_XmitPower_S);
+		ads->ds_ctl0 = ds_ctl0;
+
+		/*
+		 * Override the whole descriptor field for each TX power.
+		 *
+		 * This will need changing if we ever support antenna control
+		 * programming.
+		 */
+		txPower = ar5416GetTxRatePower(ah, series[1].Rate,
+		    series[1].ChSel,
+		    series[1].tx_power_cap,
+		    !! (series[1].RateFlags & HAL_RATESERIES_2040));
+		ads->ds_ctl9 = SM(0, AR_AntCtl1) | SM(txPower, AR_XmitPower1);
+
+		txPower = ar5416GetTxRatePower(ah, series[2].Rate,
+		    series[2].ChSel,
+		    series[2].tx_power_cap,
+		    !! (series[2].RateFlags & HAL_RATESERIES_2040));
+		ads->ds_ctl10 = SM(0, AR_AntCtl2) | SM(txPower, AR_XmitPower2);
+
+		txPower = ar5416GetTxRatePower(ah, series[3].Rate,
+		    series[3].ChSel,
+		    series[3].tx_power_cap,
+		    !! (series[3].RateFlags & HAL_RATESERIES_2040));
+		ads->ds_ctl11 = SM(0, AR_AntCtl3) | SM(txPower, AR_XmitPower3);
+	}
 }
 
 /*

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c	Wed Apr 17 07:22:23 2013	(r249579)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c	Wed Apr 17 07:31:53 2013	(r249580)
@@ -76,9 +76,7 @@ ar9285SetTransmitPower(struct ath_hal *a
 
     MODAL_EEP4K_HEADER	*pModal;
     struct ath_hal_5212 *ahp = AH5212(ah);
-    int16_t		ratesArray[Ar5416RateSize];
     int16_t		txPowerIndexOffset = 0;
-    uint8_t		ht40PowerIncForPdadc = 2;	
     int			i;
     
     uint16_t		cfgCtl;
@@ -91,8 +89,10 @@ ar9285SetTransmitPower(struct ath_hal *a
 
     HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1);
 
+    AH5416(ah)->ah_ht40PowerIncForPdadc = 2;
+
     /* Setup info for the actual eeprom */
-    OS_MEMZERO(ratesArray, sizeof(ratesArray));
+    OS_MEMZERO(AH5416(ah)->ah_ratesArray, sizeof(AH5416(ah)->ah_ratesArray));
     cfgCtl = ath_hal_getctl(ah, chan);
     powerLimit = chan->ic_maxregpower * 2;
     twiceAntennaReduction = chan->ic_maxantgain;
@@ -102,11 +102,11 @@ ar9285SetTransmitPower(struct ath_hal *a
 	__func__,chan->ic_freq, cfgCtl );      
   
     if (IS_EEP_MINOR_V2(ah)) {
-        ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
     }
  
     if (!ar9285SetPowerPerRateTable(ah, pEepData,  chan,
-                                    &ratesArray[0],cfgCtl,
+                                    &AH5416(ah)->ah_ratesArray[0],cfgCtl,
                                     twiceAntennaReduction,
 				    twiceMaxRegulatoryPower, powerLimit)) {
         HALDEBUG(ah, HAL_DEBUG_ANY,
@@ -120,11 +120,12 @@ ar9285SetTransmitPower(struct ath_hal *a
         return AH_FALSE;
     }
   
-    maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
-    maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+    maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb],
+      AH5416(ah)->ah_ratesArray[rateHt20_0]);
+    maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rate1l]);
 
     if (IEEE80211_IS_CHAN_HT40(chan)) {
-        maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+        maxPower = AH_MAX(maxPower, AH5416(ah)->ah_ratesArray[rateHt40_0]);
     }
 
     ahp->ah_tx6PowerInHalfDbm = maxPower;   
@@ -135,18 +136,18 @@ ar9285SetTransmitPower(struct ath_hal *a
      * txPowerIndexOffset is set by the SetPowerTable() call -
      *  adjust the rate table (0 offset if rates EEPROM not loaded)
      */
-    for (i = 0; i < N(ratesArray); i++) {
-        ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+    for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) {
+        AH5416(ah)->ah_ratesArray[i] = (int16_t)(txPowerIndexOffset + AH5416(ah)->ah_ratesArray[i]);
 	/* -5 dBm offset for Merlin and later; this includes Kite */
-	ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
-        if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-            ratesArray[i] = AR5416_MAX_RATE_POWER;
-	if (ratesArray[i] < 0)
-		ratesArray[i] = 0;
+	AH5416(ah)->ah_ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+        if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER)
+            AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER;
+	if (AH5416(ah)->ah_ratesArray[i] < 0)
+		AH5416(ah)->ah_ratesArray[i] = 0;
     }
 
 #ifdef AH_EEPROM_DUMP
-    ar5416PrintPowerPerRate(ah, ratesArray);
+    ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray);
 #endif
 
     /*
@@ -157,18 +158,26 @@ ar9285SetTransmitPower(struct ath_hal *a
      * XXX handle overflow/too high power level?
      */
     if (IEEE80211_IS_CHAN_HT40(chan)) {
-        ratesArray[rateHt40_0] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_1] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_2] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_3] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_4] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_5] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_6] += ht40PowerIncForPdadc;
-        ratesArray[rateHt40_7] += ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_0] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_1] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_2] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_3] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_4] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_5] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_6] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
+        AH5416(ah)->ah_ratesArray[rateHt40_7] +=
+          AH5416(ah)->ah_ht40PowerIncForPdadc;
     }
 
     /* Write the TX power rate registers */
-    ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray);
+    ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray);
 
     return AH_TRUE;
 #undef POW_SM

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Wed Apr 17 07:22:23 2013	(r249579)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Wed Apr 17 07:31:53 2013	(r249580)
@@ -333,9 +333,7 @@ ar9287SetTransmitPower(struct ath_hal *a
 
 	const struct modal_eep_ar9287_header *pModal;
 	struct ath_hal_5212 *ahp = AH5212(ah);
-	int16_t	     ratesArray[Ar5416RateSize];
 	int16_t	     txPowerIndexOffset = 0;
-	uint8_t	     ht40PowerIncForPdadc = 2;
 	int		 i;
 
 	uint16_t	    cfgCtl;
@@ -346,8 +344,11 @@ ar9287SetTransmitPower(struct ath_hal *a
 	HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom;
 	struct ar9287_eeprom *pEepData = &ee->ee_base;
 
+	AH5416(ah)->ah_ht40PowerIncForPdadc = 2;
+
 	/* Setup info for the actual eeprom */
-	OS_MEMZERO(ratesArray, sizeof(ratesArray));
+	OS_MEMZERO(AH5416(ah)->ah_ratesArray,
+	  sizeof(AH5416(ah)->ah_ratesArray));
 	cfgCtl = ath_hal_getctl(ah, chan);
 	powerLimit = chan->ic_maxregpower * 2;
 	twiceAntennaReduction = chan->ic_maxantgain;
@@ -358,11 +359,12 @@ ar9287SetTransmitPower(struct ath_hal *a
 	    __func__,chan->ic_freq, cfgCtl );
 
 	/* XXX Assume Minor is v2 or later */
-	ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+	AH5416(ah)->ah_ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
 
 	/* Fetch per-rate power table for the given channel */
 	if (! ar9287SetPowerPerRateTable(ah, pEepData,  chan,
-	    &ratesArray[0],cfgCtl,
+	    &AH5416(ah)->ah_ratesArray[0],
+	    cfgCtl,
 	    twiceAntennaReduction,
 	    twiceMaxRegulatoryPower, powerLimit)) {
 		HALDEBUG(ah, HAL_DEBUG_ANY,
@@ -374,11 +376,14 @@ ar9287SetTransmitPower(struct ath_hal *a
 	ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset);
 
 	/* Calculate maximum power level */
-	maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]);
-	maxPower = AH_MAX(maxPower, ratesArray[rate1l]);
+	maxPower = AH_MAX(AH5416(ah)->ah_ratesArray[rate6mb],
+	    AH5416(ah)->ah_ratesArray[rateHt20_0]);
+	maxPower = AH_MAX(maxPower,
+	    AH5416(ah)->ah_ratesArray[rate1l]);
 
 	if (IEEE80211_IS_CHAN_HT40(chan))
-		maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]);
+		maxPower = AH_MAX(maxPower,
+		    AH5416(ah)->ah_ratesArray[rateHt40_0]);
 
 	ahp->ah_tx6PowerInHalfDbm = maxPower;
 	AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower;
@@ -389,18 +394,20 @@ ar9287SetTransmitPower(struct ath_hal *a
 	 *  adjust the rate table (0 offset if rates EEPROM not loaded)
 	 */
 	/* XXX what about the pwrTableOffset? */
-	for (i = 0; i < N(ratesArray); i++) {
-		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+	for (i = 0; i < N(AH5416(ah)->ah_ratesArray); i++) {
+		AH5416(ah)->ah_ratesArray[i] =
+		    (int16_t)(txPowerIndexOffset +
+		      AH5416(ah)->ah_ratesArray[i]);
 		/* -5 dBm offset for Merlin and later; this includes Kiwi */
-		ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
-		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
-			ratesArray[i] = AR5416_MAX_RATE_POWER;
-		if (ratesArray[i] < 0)
-			ratesArray[i] = 0;
+		AH5416(ah)->ah_ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+		if (AH5416(ah)->ah_ratesArray[i] > AR5416_MAX_RATE_POWER)
+			AH5416(ah)->ah_ratesArray[i] = AR5416_MAX_RATE_POWER;
+		if (AH5416(ah)->ah_ratesArray[i] < 0)
+			AH5416(ah)->ah_ratesArray[i] = 0;
 	}
 
 #ifdef AH_EEPROM_DUMP
-	ar5416PrintPowerPerRate(ah, ratesArray);
+	ar5416PrintPowerPerRate(ah, AH5416(ah)->ah_ratesArray);
 #endif
 
 	/*
@@ -411,18 +418,26 @@ ar9287SetTransmitPower(struct ath_hal *a
 	 * XXX handle overflow/too high power level?
 	 */
 	if (IEEE80211_IS_CHAN_HT40(chan)) {
-		ratesArray[rateHt40_0] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_1] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_2] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_3] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_4] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_5] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_6] += ht40PowerIncForPdadc;
-		ratesArray[rateHt40_7] += ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_0] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_1] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_2] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_3] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_4] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_5] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_6] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
+		AH5416(ah)->ah_ratesArray[rateHt40_7] +=
+		  AH5416(ah)->ah_ht40PowerIncForPdadc;
 	}
 
 	/* Write the TX power rate registers */
-	ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray);
+	ar5416WriteTxPowerRateRegisters(ah, chan, AH5416(ah)->ah_ratesArray);
 
 	return AH_TRUE;
 #undef POW_SM


More information about the svn-src-all mailing list