svn commit: r278741 - head/sys/contrib/dev/ath/ath_hal/ar9300

Adrian Chadd adrian at FreeBSD.org
Sat Feb 14 04:28:56 UTC 2015


Author: adrian
Date: Sat Feb 14 04:28:51 2015
New Revision: 278741
URL: https://svnweb.freebsd.org/changeset/base/278741

Log:
  Update the AR9300 HAL to the latest public available HAL from QCA.
  
  I've been sitting on this for a year or so now; I've finally
  tested it on enough devices to be reasonably sure it won't
  cause too much drama.  But, if you see issues, please email me.
  
  Tested (all STA mode):
  
  PCIe:
  
  * AR9380
  * AR9390
  * AR9580
  * AR9462
  * AR9485
  
  SoC:
  
  * QCA9550
  * AR9331
  * AR9342

Modified:
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini
  head/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h	Sat Feb 14 04:28:51 2015	(r278741)
@@ -576,6 +576,9 @@ struct ath_hal_9300 {
     u_int8_t    ah_tx_chainmask; /* tx chain mask */
     u_int8_t    ah_rx_chainmask; /* rx chain mask */
 
+    /* optional tx chainmask */
+    u_int8_t    ah_tx_chainmaskopt;
+
     u_int8_t    ah_tx_cal_chainmask; /* tx cal chain mask */
     u_int8_t    ah_rx_cal_chainmask; /* rx cal chain mask */
 
@@ -845,6 +848,7 @@ struct ath_hal_9300 {
     HAL_BOOL                ah_aic_enabled;
     u_int32_t           ah_aic_sram[ATH_AIC_MAX_BT_CHANNEL];
 #endif
+
 #endif /* ATH_SUPPORT_MCI */
     u_int8_t            ah_cac_quiet_enabled;
 #if ATH_WOW_OFFLOAD
@@ -852,6 +856,14 @@ struct ath_hal_9300 {
     u_int32_t           ah_mcast_filter_u32_set;
 #endif
     HAL_BOOL            ah_reduced_self_gen_mask;
+    HAL_BOOL                ah_chip_reset_done;
+    HAL_BOOL                ah_abort_txdma_norx;
+    /* store previous passive RX Cal info */
+    HAL_BOOL                ah_skip_rx_iq_cal;
+    HAL_BOOL                ah_rx_cal_complete; /* previous rx cal completed or not */
+    u_int32_t           ah_rx_cal_chan;     /* chan on which rx cal is done */
+    u_int32_t           ah_rx_cal_chan_flag;
+    u_int32_t           ah_rx_cal_corr[AR9300_MAX_CHAINS];
 
     /* Local additions for FreeBSD */
     /*
@@ -877,7 +889,6 @@ struct ath_hal_9300 {
     struct ar9300NfLimits nf_2GHz;
     struct ar9300NfLimits nf_5GHz;
     struct ar9300NfLimits *nfp;
-
 };
 
 #define AH9300(_ah) ((struct ath_hal_9300 *)(_ah))
@@ -1194,7 +1205,8 @@ extern  HAL_BOOL ar9300_get_channel_edge
 extern  HAL_BOOL ar9300_fill_capability_info(struct ath_hal *ah);
 
 extern  void ar9300_beacon_init(struct ath_hal *ah,
-                              u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode);
+                              u_int32_t next_beacon, u_int32_t beacon_period, 
+                              u_int32_t beacon_period_fraction, HAL_OPMODE opmode);
 extern  void ar9300_set_sta_beacon_timers(struct ath_hal *ah,
         const HAL_BEACON_STATE *);
 
@@ -1217,12 +1229,19 @@ extern  HAL_BOOL ar9300_set_key_cache_en
 extern  HAL_BOOL ar9300_set_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
                        const HAL_KEYVAL *k, const u_int8_t *mac, int xor_key);
 extern  HAL_BOOL ar9300_print_keycache(struct ath_hal *ah);
+#if ATH_SUPPORT_KEYPLUMB_WAR
+extern  HAL_BOOL ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
+                        const HAL_KEYVAL *k, int xorKey);
+#endif
 
 extern  void ar9300_get_mac_address(struct ath_hal *ah, u_int8_t *mac);
 extern  HAL_BOOL ar9300_set_mac_address(struct ath_hal *ah, const u_int8_t *);
 extern  void ar9300_get_bss_id_mask(struct ath_hal *ah, u_int8_t *mac);
 extern  HAL_BOOL ar9300_set_bss_id_mask(struct ath_hal *, const u_int8_t *);
 extern  HAL_STATUS ar9300_select_ant_config(struct ath_hal *ah, u_int32_t cfg);
+extern  u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz);
+extern HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
+                                u_int32_t *common_tbl1, u_int32_t *common_tbl2);
 extern  HAL_BOOL ar9300_set_regulatory_domain(struct ath_hal *ah,
                                     u_int16_t reg_domain, HAL_STATUS *stats);
 extern  u_int ar9300_get_wireless_modes(struct ath_hal *ah);
@@ -1397,6 +1416,8 @@ extern HAL_BOOL ar9300_set_tx_power_limi
                                        u_int16_t extra_txpow, u_int16_t tpc_in_db);
 extern void ar9300_chain_noise_floor(struct ath_hal *ah, int16_t *nf_buf,
                                     struct ieee80211_channel *chan, int is_scan);
+extern int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time);
+extern int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal);
 extern HAL_BOOL ar9300_load_nf(struct ath_hal *ah, int16_t nf[]);
 
 extern HAL_RFGAIN ar9300_get_rfgain(struct ath_hal *ah);
@@ -1681,6 +1702,8 @@ extern void ar9300_tx99_start(struct ath
 extern void ar9300_tx99_stop(struct ath_hal *ah);
 #endif /* ATH_SUPPORT_HTC */
 #endif /* ATH_TX99_DIAG */
+extern HAL_BOOL ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array);
+extern void ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask);
 
 enum {
 	AR9300_COEFF_TX_TYPE = 0,

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -302,6 +302,7 @@ static const struct ath_hal_private ar93
         ar9300_get_desc_info,              /* ah_get_desc_info */
         ar9300_select_ant_config,          /* ah_select_ant_config */
         ar9300_ant_ctrl_common_get,        /* ah_ant_ctrl_common_get */
+        ar9300_ant_swcom_sel,              /* ah_ant_swcom_sel */
         ar9300_enable_tpc,                 /* ah_enable_tpc */
         AH_NULL,                           /* ah_olpc_temp_compensation */
 #if ATH_SUPPORT_CRDC
@@ -319,7 +320,9 @@ static const struct ath_hal_private ar93
         ar9300_set_key_cache_entry,        /* ah_set_key_cache_entry */
         ar9300_set_key_cache_entry_mac,    /* ah_set_key_cache_entry_mac */
         ar9300_print_keycache,             /* ah_print_key_cache */
-
+#if ATH_SUPPORT_KEYPLUMB_WAR
+        ar9300_check_key_cache_entry,      /* ah_check_key_cache_entry */
+#endif
         /* Power Management Functions */
         ar9300_set_power_mode,             /* ah_set_power_mode */
         ar9300_set_sm_power_mode,          /* ah_set_sm_ps_mode */
@@ -342,6 +345,8 @@ static const struct ath_hal_private ar93
         /* Get Channel Noise */
         ath_hal_get_chan_noise,            /* ah_get_chan_noise */
         ar9300_chain_noise_floor,          /* ah_get_chain_noise_floor */
+        ar9300_get_nf_from_reg,            /* ah_get_nf_from_reg */
+        ar9300_get_rx_nf_offset,           /* ah_get_rx_nf_offset */
 
         /* Beacon Functions */
         ar9300_beacon_init,                /* ah_beacon_init */
@@ -499,11 +504,11 @@ static const struct ath_hal_private ar93
 #else
         AH_NULL,
         AH_NULL,
-        ar9300TX99TgtChannelPwrUpdate,		/* ah_tx99channelpwrupdate */
-        ar9300TX99TgtStart,					/* ah_tx99start */
-        ar9300TX99TgtStop,					/* ah_tx99stop */
-        ar9300TX99TgtChainmskSetup,			/* ah_tx99_chainmsk_setup */
-        ar9300TX99SetSingleCarrier,			/* ah_tx99_set_single_carrier */
+        ar9300_tx99_channel_pwr_update,		/* ah_tx99channelpwrupdate */
+        ar9300_tx99_start,					/* ah_tx99start */
+        ar9300_tx99_stop,					/* ah_tx99stop */
+        ar9300_tx99_chainmsk_setup,			/* ah_tx99_chainmsk_setup */
+        ar9300_tx99_set_single_carrier,		/* ah_tx99_set_single_carrier */
 #endif
 #endif
         ar9300_chk_rssi_update_tx_pwr,
@@ -525,6 +530,8 @@ static const struct ath_hal_private ar93
         ar9300_dump_keycache,              /* ah_dump_keycache */
         ar9300_is_ani_noise_spur,         /* ah_is_ani_noise_spur */
         ar9300_set_hw_beacon_proc,         /* ah_set_hw_beacon_proc */
+        ar9300_set_ctl_pwr,                 /* ah_set_ctl_pwr */
+        ar9300_set_txchainmaskopt,          /* ah_set_txchainmaskopt */
     },
 
     ar9300_get_channel_edges,              /* ah_get_channel_edges */
@@ -838,6 +845,18 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC
     /* Enable RIFS */
     ahp->ah_rifs_enabled = AH_TRUE;
 
+    /* by default, stop RX also in abort txdma, due to
+       "Unable to stop TxDMA" msg observed */
+    ahp->ah_abort_txdma_norx = AH_TRUE;
+
+    /* do not use optional tx chainmask by default */
+    ahp->ah_tx_chainmaskopt = 0;
+
+    ahp->ah_skip_rx_iq_cal = AH_FALSE;
+    ahp->ah_rx_cal_complete = AH_FALSE;
+    ahp->ah_rx_cal_chan = 0;
+    ahp->ah_rx_cal_chan_flag = 0;
+
     HALDEBUG(ah, HAL_DEBUG_RESET,
         "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
         ahpriv->ah_macVersion,

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -34,7 +34,8 @@ extern u_int32_t ar9300_num_tx_pending(s
  */
 void
 ar9300_beacon_init(struct ath_hal *ah,
-    u_int32_t next_beacon, u_int32_t beacon_period, HAL_OPMODE opmode)
+    u_int32_t next_beacon, u_int32_t beacon_period, 
+    u_int32_t beacon_period_fraction, HAL_OPMODE opmode)
 {
     u_int32_t               beacon_period_usec;
 
@@ -52,6 +53,11 @@ ar9300_beacon_init(struct ath_hal *ah,
 
     beacon_period_usec =
         ONE_EIGHTH_TU_TO_USEC(beacon_period & HAL_BEACON_PERIOD_TU8);
+
+    /* Add the fraction adjustment lost due to unit conversions. */
+    beacon_period_usec += beacon_period_fraction;
+
+
     OS_REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period_usec);
     OS_REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period_usec);
     OS_REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period_usec);

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -1200,6 +1200,44 @@ ar9300_noise_floor_cal_or_power_get(stru
     return nf_use;
 }
 
+/*
+ * Return the Rx NF offset for specific channel.
+ * The values saved in EEPROM/OTP/Flash is converted through the following way:
+ *     ((_p) - NOISE_PWR_DATA_OFFSET) << 2
+ * So we need to convert back to the original values.
+ */
+int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) {
+    HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
+    int8_t rx_nf_pwr, rx_nf_cal;
+    int i; 
+    //HALASSERT(ichan);
+
+    /* Fill 0 if valid internal channel is not found */
+    if (ichan == AH_NULL) {
+        OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS);
+        OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS);
+        return -1;
+    }
+
+    for (i = 0; i < OSPREY_MAX_CHAINS; i++) {
+	    if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) {
+	        nf_pwr[i] = 0;
+	    } else {
+	        //printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr);
+            nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr);
+	    }
+
+	    if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) {
+	        nf_cal[i] = 0;
+	    } else {
+	        //printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal);
+            nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal);
+	    }
+    }
+
+    return 0;
+}
+
 int32_t ar9300_rx_gain_index_get(struct ath_hal *ah)
 {
     ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
@@ -1530,6 +1568,61 @@ u_int16_t ar9300_ant_ctrl_chain_get(stru
     return 0;
 }
 
+/*
+ * Select the usage of antenna via the RF switch.
+ * Default values are loaded from eeprom.
+ */
+HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
+                        u_int32_t *common_tbl1, u_int32_t *common_tbl2)
+{
+    ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
+    struct ath_hal_private  *ap  = AH_PRIVATE(ah);
+    const struct ieee80211_channel *curchan = ap->ah_curchan;
+    enum {
+        ANT_SELECT_OPS_GET,
+        ANT_SELECT_OPS_SET,
+    };
+
+    if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah))
+        return AH_FALSE;
+
+    if (!curchan)
+        return AH_FALSE;
+
+#define AR_SWITCH_TABLE_COM_ALL (0xffff)
+#define AR_SWITCH_TABLE_COM_ALL_S (0)
+#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
+#define AR_SWITCH_TABLE_COM2_ALL_S (0)
+    switch (ops) {
+    case ANT_SELECT_OPS_GET:
+        *common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM,
+                            AR_SWITCH_TABLE_COM_ALL);
+        *common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2,
+                            AR_SWITCH_TABLE_COM2_ALL);
+        break;
+    case ANT_SELECT_OPS_SET:
+        OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
+            AR_SWITCH_TABLE_COM_ALL, *common_tbl1);
+        OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
+            AR_SWITCH_TABLE_COM2_ALL, *common_tbl2);
+
+        /* write back to eeprom */
+        if (IEEE80211_IS_CHAN_2GHZ(curchan)) {
+            eep->modal_header_2g.ant_ctrl_common = *common_tbl1;
+            eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2;
+        } else {
+            eep->modal_header_5g.ant_ctrl_common = *common_tbl1;
+            eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2;
+        }
+
+        break;
+    default:
+        break;
+    }
+
+    return AH_TRUE;
+}
+
 HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
 {
     u_int32_t value;
@@ -2412,16 +2505,31 @@ ar9300_eeprom_set_power_per_rate_table(
     HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
 #endif
 
-    tx_chainmask = chainmask ? chainmask : ahp->ah_tx_chainmask;
+    if (chainmask)
+        tx_chainmask = chainmask;
+    else
+        tx_chainmask = ahp->ah_tx_chainmaskopt ?
+                            ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask;
 
     ar9300_get_channel_centers(ah, chan, &centers);
 
+#if 1
     if (IEEE80211_IS_CHAN_2GHZ(chan)) {
         ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain;
     } else {
         ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain;
     }
 
+#else
+    if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+        ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain,
+                                         AH_PRIVATE(ah)->ah_antenna_gain_2g);
+    } else {
+        ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain,
+                                         AH_PRIVATE(ah)->ah_antenna_gain_5g);
+    }
+#endif
+
     /* Save max allowed antenna gain to ease future lookups */
     ahp->twice_antenna_reduction = twice_antenna_reduction; 
 
@@ -2958,7 +3066,8 @@ ar9300_eeprom_set_transmit_power(struct 
     }
     max_power_level = target_power_val_t2[i];
     /* Adjusting the ah_max_power_level based on chains and antennaGain*/
-    switch (ar9300_get_ntxchains(ahp->ah_tx_chainmask))
+    switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ?
+                                    ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask)))
     {
         case 1:
             break;

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -606,7 +606,7 @@ ar9300_freebsd_beacon_init(struct ath_ha
     uint32_t beacon_period)
 {
 
-	ar9300_beacon_init(ah, next_beacon, beacon_period,
+	ar9300_beacon_init(ah, next_beacon, beacon_period, 0,
 	    AH_PRIVATE(ah)->ah_opmode);
 }
 

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h	Sat Feb 14 04:28:51 2015	(r278741)
@@ -35,6 +35,7 @@
 #define ATH_SUPPORT_PAPRD       1
 #define ATH_SUPPORT_TxBF        0
 #define AH_PRIVATE_DIAG         1
+#define ATH_SUPPORT_KEYPLUMB_WAR 0
 
 /* XXX need to reverify these; they came in with qcamain */
 #define ATH_SUPPORT_FAST_CC 0

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -436,3 +436,156 @@ void ar9300_dump_keycache(struct ath_hal
     }
 #undef AH_KEY_REG_SIZE
 }
+
+#if ATH_SUPPORT_KEYPLUMB_WAR
+/*
+ * Check the contents of the specified key cache entry
+ * and any associated MIC entry.
+ */
+    HAL_BOOL
+ar9300_check_key_cache_entry(struct ath_hal *ah, u_int16_t entry,
+        const HAL_KEYVAL *k, int xorKey)
+{
+    const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+    u_int32_t key0, key1, key2, key3, key4;
+    u_int32_t keyType;
+    u_int32_t xorMask = xorKey ?
+        (KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
+    struct ath_hal_9300 *ahp = AH9300(ah);
+
+
+    if (entry >= pCap->hal_key_cache_size) {
+        HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
+                "%s: entry %u out of range\n", __func__, entry);
+        return AH_FALSE;
+    }
+    switch (k->kv_type) {
+        case HAL_CIPHER_AES_OCB:
+            keyType = AR_KEYTABLE_TYPE_AES;
+            break;
+        case HAL_CIPHER_AES_CCM:
+            if (!pCap->hal_cipher_aes_ccm_support) {
+                HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: AES-CCM not supported by "
+                        "mac rev 0x%x\n",
+                        __func__, AH_PRIVATE(ah)->ah_macRev);
+                return AH_FALSE;
+            }
+            keyType = AR_KEYTABLE_TYPE_CCM;
+            break;
+        case HAL_CIPHER_TKIP:
+            keyType = AR_KEYTABLE_TYPE_TKIP;
+            if (IS_MIC_ENABLED(ah) && entry + 64 >= pCap->hal_key_cache_size) {
+                HALDEBUG(ah, HAL_DEBUG_KEYCACHE,
+                        "%s: entry %u inappropriate for TKIP\n",
+                        __func__, entry);
+                return AH_FALSE;
+            }
+            break;
+        case HAL_CIPHER_WEP:
+            if (k->kv_len < 40 / NBBY) {
+                HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: WEP key length %u too small\n",
+                        __func__, k->kv_len);
+                return AH_FALSE;
+            }
+            if (k->kv_len <= 40 / NBBY) {
+                keyType = AR_KEYTABLE_TYPE_40;
+            } else if (k->kv_len <= 104 / NBBY) {
+                keyType = AR_KEYTABLE_TYPE_104;
+            } else {
+                keyType = AR_KEYTABLE_TYPE_128;
+            }
+            break;
+        case HAL_CIPHER_CLR:
+            keyType = AR_KEYTABLE_TYPE_CLR;
+            return AH_TRUE;
+        default:
+            HALDEBUG(ah, HAL_DEBUG_KEYCACHE, "%s: cipher %u not supported\n",
+                    __func__, k->kv_type);
+            return AH_TRUE;
+    }
+
+    key0 =  LE_READ_4(k->kv_val +  0) ^ xorMask;
+    key1 = (LE_READ_2(k->kv_val +  4) ^ xorMask) & 0xffff;
+    key2 =  LE_READ_4(k->kv_val +  6) ^ xorMask;
+    key3 = (LE_READ_2(k->kv_val + 10) ^ xorMask) & 0xffff;
+    key4 =  LE_READ_4(k->kv_val + 12) ^ xorMask;
+    if (k->kv_len <= 104 / NBBY) {
+        key4 &= 0xff;
+    }
+
+    /*
+     * Note: key cache hardware requires that each double-word
+     * pair be written in even/odd order (since the destination is
+     * a 64-bit register).  Don't reorder these writes w/o
+     * considering this!
+     */
+    if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
+        u_int16_t micentry = entry + 64;  /* MIC goes at slot+64 */
+
+
+        /*
+         * Invalidate the encrypt/decrypt key until the MIC
+         * key is installed so pending rx frames will fail
+         * with decrypt errors rather than a MIC error.
+         */
+        if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) && 
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
+                ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) 
+        {
+
+            /*
+             * since the AR_MISC_MODE register was written with the contents of
+             * ah_miscMode (if any) in ar9300Attach, just check ah_miscMode and
+             * save a pci read per key set.
+             */
+            if (ahp->ah_misc_mode & AR_PCU_MIC_NEW_LOC_ENA) {
+                u_int32_t mic0,mic1,mic2,mic3,mic4;
+                /*
+                 * both RX and TX mic values can be combined into
+                 * one cache slot entry.
+                 * 8*N + 800         31:0    RX Michael key 0
+                 * 8*N + 804         15:0    TX Michael key 0 [31:16]
+                 * 8*N + 808         31:0    RX Michael key 1
+                 * 8*N + 80C         15:0    TX Michael key 0 [15:0]
+                 * 8*N + 810         31:0    TX Michael key 1
+                 * 8*N + 814         15:0    reserved
+                 * 8*N + 818         31:0    reserved
+                 * 8*N + 81C         14:0    reserved
+                 *                   15      key valid == 0
+                 */
+                /* RX mic */
+                mic0 = LE_READ_4(k->kv_mic + 0);
+                mic2 = LE_READ_4(k->kv_mic + 4);
+                /* TX mic */
+                mic1 = LE_READ_2(k->kv_txmic + 2) & 0xffff;
+                mic3 = LE_READ_2(k->kv_txmic + 0) & 0xffff;
+                mic4 = LE_READ_4(k->kv_txmic + 4);
+                if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(micentry)) == mic0) &&
+                        (OS_REG_READ(ah, AR_KEYTABLE_KEY1(micentry)) == mic1) &&
+                        (OS_REG_READ(ah, AR_KEYTABLE_KEY2(micentry)) == mic2) &&
+                        (OS_REG_READ(ah, AR_KEYTABLE_KEY3(micentry)) == mic3) &&
+                        (OS_REG_READ(ah, AR_KEYTABLE_KEY4(micentry)) == mic4) &&
+                        ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(micentry)) & AR_KEY_TYPE) == (AR_KEYTABLE_TYPE_CLR & AR_KEY_TYPE))) {
+                    return AH_TRUE;
+                }
+
+            } else {
+                return AH_TRUE;
+            }
+        }
+    } else {
+        if ((OS_REG_READ(ah, AR_KEYTABLE_KEY0(entry)) == key0) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY1(entry)) == key1) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY2(entry)) == key2) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY3(entry)) == key3) &&
+                (OS_REG_READ(ah, AR_KEYTABLE_KEY4(entry)) == key4) &&
+                ((OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry)) & AR_KEY_TYPE) == (keyType & AR_KEY_TYPE))) {
+            return AH_TRUE;
+        }
+    }
+    return AH_FALSE;
+}
+#endif

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -1697,10 +1697,10 @@ ar9300_get_bb_panic_info(struct ath_hal 
 
     /* Suppress BB Status mesg following signature */
     switch (bb_panic->status) {
-		case 0x04000539:
-		case 0x04008009:	
-		case 0x04000b09:
-		case 0x1300000a:
+        case 0x04000539:
+        case 0x04008009:    
+        case 0x04000b09:
+        case 0x1300000a:
         return -1;
     }
 
@@ -3718,8 +3718,6 @@ ar9300_tx99_start(struct ath_hal *ah, u_
 
     /* Disable AGC to A2 */
     OS_REG_WRITE(ah, AR_PHY_TEST, (OS_REG_READ(ah, AR_PHY_TEST) | PHY_AGC_CLR));
-    OS_REG_WRITE(ah, 0x9864, OS_REG_READ(ah, 0x9864) | 0x7f000);
-    OS_REG_WRITE(ah, 0x9924, OS_REG_READ(ah, 0x9924) | 0x7f00fe);
     OS_REG_WRITE(ah, AR_DIAG_SW, OS_REG_READ(ah, AR_DIAG_SW) &~ AR_DIAG_RX_DIS);
 
     OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);     /* set receive disable */
@@ -3763,3 +3761,47 @@ ar9300SetDfs3StreamFix(struct ath_hal *a
 {
    return AH_FALSE;
 }
+
+HAL_BOOL
+ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array)
+{
+    struct ath_hal_9300 *ahp = AH9300(ah);
+    ar9300_eeprom_t *p_eep_data = &ahp->ah_eeprom;
+    u_int8_t *ctl_index;
+    u_int32_t offset = 0;
+
+    if (!ctl_array)
+        return AH_FALSE;
+
+    /* copy 2G ctl freqbin and power data */
+    ctl_index = p_eep_data->ctl_index_2g;
+    OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_2G, ctl_array,
+                OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G +     /* ctl_freqbin_2G */
+                OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G));  /* ctl_power_data_2g */
+    offset = (OSPREY_NUM_CTLS_2G * OSPREY_NUM_BAND_EDGES_2G) +
+            ( OSPREY_NUM_CTLS_2G * sizeof(OSP_CAL_CTL_DATA_2G));
+
+
+    /* copy 2G ctl freqbin and power data */
+    ctl_index = p_eep_data->ctl_index_5g;
+    OS_MEMCPY(ctl_index + OSPREY_NUM_CTLS_5G, ctl_array + offset,
+                OSPREY_NUM_CTLS_5G * OSPREY_NUM_BAND_EDGES_5G +     /* ctl_freqbin_5G */
+                OSPREY_NUM_CTLS_5G * sizeof(OSP_CAL_CTL_DATA_5G));  /* ctl_power_data_5g */
+
+    return AH_FALSE;
+}
+
+void
+ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask)
+{
+    struct ath_hal_9300 *ahp = AH9300(ah);
+
+    /* optional txchainmask should be subset of primary txchainmask */
+    if ((mask & ahp->ah_tx_chainmask) != mask) {
+        ahp->ah_tx_chainmaskopt = 0;
+        ath_hal_printf(ah, "Error: ah_tx_chainmask=%d, mask=%d\n", ahp->ah_tx_chainmask, mask);
+        return;
+    }
+    
+    ahp->ah_tx_chainmaskopt = mask;
+}

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini	Sat Feb 14 04:28:51 2015	(r278741)
@@ -881,7 +881,7 @@ static const u_int32_t ar9300_osprey_2p2
   { 0x00008258 ,  0x00000000   },
   { 0x0000825c ,  0x40000000   },
   { 0x00008260 ,  0x00080922   },
-  { 0x00008264 ,  0x9bc00010   },
+  { 0x00008264 ,  0x9d400010   },
   { 0x00008268 ,  0xffffffff   },
   { 0x0000826c ,  0x0000ffff   },
   { 0x00008270 ,  0x00000000   },
@@ -1171,7 +1171,7 @@ static const u_int32_t ar9300_osprey_2p2
   { 0x000010b0 ,  0x00000e60   ,  0x00001cc0   ,  0x00007c70   ,  0x00003e38   },
   { 0x00008014 ,  0x03e803e8   ,  0x07d007d0   ,  0x10801600   ,  0x08400b00   },
   { 0x0000801c ,  0x128d8027   ,  0x128d804f   ,  0x12e00057   ,  0x12e0002b   },
-  { 0x00008120 ,  0x08f04800   ,  0x08f04800   ,  0x08f04810   ,  0x08f04810   },
+  { 0x00008120 ,  0x18f04800   ,  0x18f04800   ,  0x18f04810   ,  0x18f04810   },
   { 0x000081d0 ,  0x00003210   ,  0x00003210   ,  0x0000320a   ,  0x0000320a   },
   { 0x00008318 ,  0x00003e80   ,  0x00007d00   ,  0x00006880   ,  0x00003440   },
 };

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -469,7 +469,7 @@ u_int32_t ar9300_wow_offload_handshake(s
     OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_REQ);
     OS_REG_SET_BIT(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_INT_EMB_CPU);
 
-    if (!ath_hal_wait(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
+    if (!ath_hal_waitfor(ah, AR_MBOX_CTRL_STATUS, AR_MBOX_WOW_CONF, AR_MBOX_WOW_CONF, bt_handshake_timeout_us)) {
         HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: WoW offload handshake failed", __func__);
         return 0;
     }
@@ -678,6 +678,7 @@ ar9300_set_power_mode(struct ath_hal *ah
             OS_REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2);
         }
 #endif
+        ahp->ah_chip_full_sleep = AH_FALSE;
         break;
     case HAL_PM_FULL_SLEEP:
 #if ATH_SUPPORT_MCI
@@ -987,7 +988,7 @@ ar9300_set_power_mode_wow_sleep(struct a
     OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
 
     OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);    /* Set receive disable bit */
-    if (!ath_hal_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
+    if (!ath_hal_waitfor(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
         HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: dma failed to stop in 10ms\n"
                  "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", __func__,
                  OS_REG_READ(ah, AR_CR), OS_REG_READ(ah, AR_DIAG_SW));

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -68,6 +68,7 @@ ar9300_proc_rx_desc_fast(struct ath_hal 
 
     rxs->rs_status = 0;
     rxs->rs_flags =  0;
+    rxs->rs_phyerr = 0;
 
     rxs->rs_datalen = rxsp->status2 & AR_data_len;
     rxs->rs_tstamp =  rxsp->status3;
@@ -129,17 +130,16 @@ ar9300_proc_rx_desc_fast(struct ath_hal 
          * Consequently we filter them out here so we don't
          * confuse and/or complicate drivers.
          */
+
         if (rxsp->status11 & AR_crc_err) {
             rxs->rs_status |= HAL_RXERR_CRC;
             /* 
-			 * ignore CRC flag for spectral phy reports
+			 * ignore CRC flag for phy reports
 			 */
             if (rxsp->status11 & AR_phyerr) {
                 u_int phyerr = MS(rxsp->status11, AR_phy_err_code);
-                if (phyerr == HAL_PHYERR_SPECTRAL) {
-                    rxs->rs_status |= HAL_RXERR_PHY;
-                    rxs->rs_phyerr = phyerr;
-                }
+                rxs->rs_status |= HAL_RXERR_PHY;
+                rxs->rs_phyerr = phyerr;
             }
         } else if (rxsp->status11 & AR_phyerr) {
             u_int phyerr;
@@ -165,7 +165,9 @@ ar9300_proc_rx_desc_fast(struct ath_hal 
             rxs->rs_status |= HAL_RXERR_MIC;
         }
     }
-
+#if 0
+    rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel;
+#endif
     return HAL_OK;
 }
 

Modified: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c
==============================================================================
--- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c	Sat Feb 14 01:33:11 2015	(r278740)
+++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c	Sat Feb 14 04:28:51 2015	(r278741)
@@ -31,7 +31,6 @@
 #define FIX_NOISE_FLOOR     1
 
 
-
 /* Additional Time delay to wait after activiting the Base band */
 #define BASE_ACTIVATE_DELAY         100     /* usec */
 #define RTC_PLL_SETTLE_DELAY        100     /* usec */
@@ -325,6 +324,7 @@ int16_t ar9300_get_min_cca_pwr(struct at
     int16_t nf;
 //    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
 
+
     if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
         nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR9280_PHY_MINCCA_PWR);
         if (nf & 0x100) {
@@ -402,6 +402,33 @@ void ar9300_chain_noise_floor(struct ath
     }
 }
 
+/*
+ * Return the current NF value in register.
+ * If the current NF cal is not completed, return 0.
+ */
+int16_t ar9300_get_nf_from_reg(struct ath_hal *ah, struct ieee80211_channel *chan, int wait_time)
+{
+    int16_t nfarray[HAL_NUM_NF_READINGS] = {0};
+    int is_2g = 0;
+    HAL_CHANNEL_INTERNAL *ichan = NULL;
+
+    ichan = ath_hal_checkchannel(ah, chan);
+    if (ichan == NULL)
+        return (0);
+
+    if (wait_time <= 0) {
+        return 0;
+    }
+
+    if (!ath_hal_waitfor(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF, 0, wait_time)) {
+        ath_hal_printf(ah, "%s: NF cal is not complete in %dus", __func__, wait_time);
+        return 0;
+    }
+    is_2g = !! (IS_CHAN_2GHZ(ichan));
+    ar9300_upload_noise_floor(ah, is_2g, nfarray);
+
+    return nfarray[0];
+}
 
 /*
  * Pick up the medium one in the noise floor buffer and update the
@@ -415,6 +442,7 @@ ar9300_get_nf_hist_mid(struct ath_hal *a
     int16_t sort[HAL_NF_CAL_HIST_LEN_FULL]; /* upper bound for hist_len */
     int i, j;
 
+
     for (i = 0; i < hist_len; i++) {
         sort[i] = h->nf_cal_buffer[i][reading];
         HALDEBUG(ah, HAL_DEBUG_NFCAL,
@@ -451,7 +479,7 @@ ar9300_reset_nf_hist_buff(struct ath_hal
     HAL_CHAN_NFCAL_HIST *h = &ichan->nf_cal_hist;
     HAL_NFCAL_HIST_FULL *home = &AH_PRIVATE(ah)->nf_cal_hist;
     int i;
-
+    
     /* 
      * Copy the value for the channel in question into the home-channel
      * NF history buffer.  The channel NF is probably a value filled in by
@@ -538,6 +566,7 @@ get_noise_floor_thresh(struct ath_hal *a
 {
     struct ath_hal_9300 *ahp = AH9300(ah);
 
+
     switch (chan->channel_flags & CHANNEL_ALL_NOTURBO) {
     case CHANNEL_A:
     case CHANNEL_A_HT20:
@@ -1609,6 +1638,7 @@ ar9300_set_reset(struct ath_hal *ah, int
 {
     u_int32_t rst_flags;
     u_int32_t tmp_reg;
+    struct ath_hal_9300 *ahp = AH9300(ah);
 
     HALASSERT(type == HAL_RESET_WARM || type == HAL_RESET_COLD);
 
@@ -1802,6 +1832,7 @@ ar9300_set_reset(struct ath_hal *ah, int
 
     ar9300_attach_hw_platform(ah);
 
+    ahp->ah_chip_reset_done = 1;
     return AH_TRUE;
 }
 
@@ -2312,10 +2343,22 @@ ar9300_per_calibration(struct ath_hal *a
 static void
 ar9300_start_nf_cal(struct ath_hal *ah)
 {
+    struct ath_hal_9300 *ahp = AH9300(ah);
     OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
     OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
     OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
     AH9300(ah)->nf_tsf32 = ar9300_get_tsf32(ah);
+
+/*  
+ *  We are reading the NF values before we start the NF operation, because
+ *  of that we are getting very high values like -45.
+ *  This triggers the CW_INT detected and EACS module triggers the channel change
+ *  chip_reset_done value is used to fix this issue.
+ *  chip_reset_flag is set during the RTC reset.
+ *  chip_reset_flag is cleared during the starting NF operation.
+ *  if flag is set we will clear the flag and will not read the NF values.
+ */
+    ahp->ah_chip_reset_done = 0;    
 }
 
 /* ar9300_calibration
@@ -2409,7 +2452,7 @@ ar9300_calibration(struct ath_hal *ah, s
             ar9300_load_nf(ah, nf_buf);
     
             /* start NF calibration, without updating BB NF register*/
-            ar9300_start_nf_cal(ah);
+            ar9300_start_nf_cal(ah);	
         }
     }
     return AH_TRUE;
@@ -2459,12 +2502,15 @@ ar9300_iq_calibration(struct ath_hal *ah
     u_int32_t q_coff_denom, i_coff_denom;
     int32_t q_coff, i_coff;
     int iq_corr_neg, i;
+    HAL_CHANNEL_INTERNAL *ichan;
     static const u_int32_t offset_array[3] = {
         AR_PHY_RX_IQCAL_CORR_B0,
         AR_PHY_RX_IQCAL_CORR_B1,
         AR_PHY_RX_IQCAL_CORR_B2,
     };
 
+    ichan = ath_hal_checkchannel(ah, AH_PRIVATE(ah)->ah_curchan);
+
     for (i = 0; i < num_chains; i++) {
         power_meas_i = ahp->ah_total_power_meas_i[i];
         power_meas_q = ahp->ah_total_power_meas_q[i];
@@ -2537,6 +2583,19 @@ ar9300_iq_calibration(struct ath_hal *ah
             OS_REG_RMW_FIELD(ah, offset_array[i],
                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
 
+            /* store the RX cal results */
+	    if (ichan != NULL) {
+            ahp->ah_rx_cal_corr[i] = OS_REG_READ(ah, offset_array[i]) & 0x7fff;
+            ahp->ah_rx_cal_complete = AH_TRUE;
+            ahp->ah_rx_cal_chan = ichan->channel;
+//            ahp->ah_rx_cal_chan_flag = ichan->channel_flags &~ CHANNEL_PASSIVE; 
+            ahp->ah_rx_cal_chan_flag = 0; /* XXX */
+	    } else {
+	        /* XXX? Is this what I should do? */
+            	ahp->ah_rx_cal_complete = AH_FALSE;
+
+	    }
+
             HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
                 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) "
                 "after update = 0x%x\n",
@@ -2563,6 +2622,55 @@ ar9300_iq_calibration(struct ath_hal *ah
 }
 
 /*
+ * When coming back from offchan, we do not perform RX IQ Cal.
+ * But the chip reset will clear all previous results
+ * We store the previous results and restore here.
+ */
+static void
+ar9300_rx_iq_cal_restore(struct ath_hal *ah)
+{
+    struct ath_hal_9300 *ahp = AH9300(ah);
+    u_int32_t   i_coff, q_coff;
+    HAL_BOOL is_restore = AH_FALSE;
+    int i;
+    static const u_int32_t offset_array[3] = {
+        AR_PHY_RX_IQCAL_CORR_B0,
+        AR_PHY_RX_IQCAL_CORR_B1,
+        AR_PHY_RX_IQCAL_CORR_B2,
+    };
+
+    for (i=0; i<AR9300_MAX_CHAINS; i++) {
+        if (ahp->ah_rx_cal_corr[i]) {
+            i_coff = (ahp->ah_rx_cal_corr[i] &
+                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF) >>
+                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S;
+            q_coff = (ahp->ah_rx_cal_corr[i] &
+                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF) >>
+                        AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S;
+
+            OS_REG_RMW_FIELD(ah, offset_array[i],
+                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, i_coff);
+            OS_REG_RMW_FIELD(ah, offset_array[i],
+                AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, q_coff);
+
+            is_restore = AH_TRUE;
+        }
+    }
+
+    if (is_restore)
+        OS_REG_SET_BIT(ah,
+            AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
+
+    HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+        "%s: IQ Cal and Correction (offset 0x%04x) enabled "
+        "(bit position 0x%08x). New Value 0x%08x\n",
+        __func__,
+        (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
+        AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
+        OS_REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
+}
+
+/*
  * Set a limit on the overall output power.  Used for dynamic
  * transmit power control and the like.
  *
@@ -3739,6 +3847,13 @@ ar9300_init_cal_internal(struct ath_hal 
 #endif
     /* end - Init time calibrations */
 
+    /* Do not do RX cal in case of offchan, or cal data already exists on same channel*/
+    if (ahp->ah_skip_rx_iq_cal) {
+        HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
+                "Skip RX IQ Cal\n");
+        return AH_TRUE;
+    }
+
     /* If Cals are supported, add them to list via INIT/INSERT_CAL */
     if (AH_TRUE == ar9300_is_cal_supp(ah, chan, IQ_MISMATCH_CAL)) {
         INIT_CAL(&ahp->ah_iq_cal_data);
@@ -3839,6 +3954,8 @@ ar9300_set_dma(struct ath_hal *ah)
 {
     u_int32_t   regval;
     struct ath_hal_9300 *ahp = AH9300(ah);
+    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
+    HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
 
 #if 0
     /*
@@ -3898,9 +4015,14 @@ ar9300_set_dma(struct ath_hal *ah)
     /*
      * Enable HPQ for UAPSD
      */
-    if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
-        OS_REG_WRITE(ah, AR_HP_Q_CONTROL,
-            AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN);
+    if (pCap->halHwUapsdTrig == AH_TRUE) {
+    /* Only enable this if HAL capabilities says it is OK */
+        if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
+            OS_REG_WRITE(ah, AR_HP_Q_CONTROL,
+                    AR_HPQ_ENABLE | AR_HPQ_UAPSD | AR_HPQ_UAPSD_TRIGGER_EN);
+        }
+    } else {
+        /* use default value from ini file - which disable HPQ queue usage */
     }
 
     /*
@@ -4319,6 +4441,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPM
     HAL_BOOL                    stopped, cal_ret;
     HAL_BOOL                    apply_last_iqcorr = AH_FALSE;
 
+
     if (OS_REG_READ(ah, AR_IER) == AR_IER_ENABLE) {
         HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "** Reset called with WLAN "
                 "interrupt enabled %08x **\n", ar9300_get_interrupts(ah));
@@ -4347,6 +4470,11 @@ ar9300_reset(struct ath_hal *ah, HAL_OPM
     ahp->ah_rx_chainmask = rxchainmask & ap->ah_caps.halRxChainMask;
     ahp->ah_tx_cal_chainmask = ap->ah_caps.halTxChainMask;
     ahp->ah_rx_cal_chainmask = ap->ah_caps.halRxChainMask;
+
+    /* 
+     * Keep the previous optinal txchainmask value
+     */
+
     HALASSERT(ar9300_check_op_mode(opmode));
 
     OS_MARK(ah, AH_MARK_RESET, b_channel_change);
@@ -4453,7 +4581,21 @@ ar9300_reset(struct ath_hal *ah, HAL_OPM
 #if 0
     /* Get the value from the previous NF cal and update history buffer */
     if (curchan && (ahp->ah_chip_full_sleep != AH_TRUE)) {
-        ar9300_store_new_nf(ah, curchan, is_scan);
+
+        if(ahp->ah_chip_reset_done){
+            ahp->ah_chip_reset_done = 0;
+        } else {
+        	/*
+         	 * is_scan controls updating NF for home channel or off channel.
+         	 * Home -> Off, update home channel
+         	 * Off -> Home, update off channel
+         	 * Home -> Home, uppdate home channel
+         	 */
+        	if (ap->ah_curchan->channel != chan->channel)
+            	ar9300_store_new_nf(ah, curchan, !is_scan);
+        	else
+            	ar9300_store_new_nf(ah, curchan, is_scan);
+        }
     }
 #endif
 
@@ -4464,7 +4606,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPM
     AH9300(ah)->nfp = IS_CHAN_2GHZ(ichan) ? &ahp->nf_2GHz : &ahp->nf_5GHz;
 
     /*
-     * XXX For now, don't apply the last IQ correction.
+     * XXX FreeBSD For now, don't apply the last IQ correction.
      *
      * This should be done when scorpion is enabled on FreeBSD; just be
      * sure to fix this channel match code so it uses net80211 flags
@@ -4501,6 +4643,31 @@ ar9300_reset(struct ath_hal *ah, HAL_OPM
     }
 #endif

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list