diff options
author | Adrian Chadd <adrian@FreeBSD.org> | 2015-02-14 04:28:51 +0000 |
---|---|---|
committer | Adrian Chadd <adrian@FreeBSD.org> | 2015-02-14 04:28:51 +0000 |
commit | 899d1cacacfe2372aa56de9471c05638d8be3b42 (patch) | |
tree | a21d911a487d20cb979c73f628b7023168f93b39 /sys/contrib/dev | |
parent | a89629abd92175c722ec03d526ef22190cdf7628 (diff) | |
download | src-899d1cacacfe2372aa56de9471c05638d8be3b42.tar.gz src-899d1cacacfe2372aa56de9471c05638d8be3b42.zip |
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
Notes
Notes:
svn path=/head/; revision=278741
Diffstat (limited to 'sys/contrib/dev')
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h | 27 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c | 31 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c | 8 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c | 113 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c | 2 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h | 1 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c | 153 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c | 54 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini | 4 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c | 5 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c | 14 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c | 217 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c | 92 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini | 8 | ||||
-rw-r--r-- | sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini | 8 |
15 files changed, 682 insertions, 55 deletions
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h index f16ef6b12fcb..eaabbe289f7d 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h @@ -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_edges(struct ath_hal *ah, 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_entry_mac(struct ath_hal *, 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_limit(struct ath_hal *ah, u_int32_t limit, 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_hal *ah, u_int8_t *data); 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, diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c index 80dc2a3b3068..a446f96e8918 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c @@ -302,6 +302,7 @@ static const struct ath_hal_private ar9300hal = { 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 ar9300hal = { 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 ar9300hal = { /* 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 ar9300hal = { #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 ar9300hal = { 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 sc, HAL_BUS_TAG st, /* 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, diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c index 17943a9123d0..a3cca95aea4c 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c @@ -34,7 +34,8 @@ extern u_int32_t ar9300_num_tx_pending(struct ath_hal *ah, u_int q); */ 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); diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c index 669104a00c55..9028ab7fa2ab 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c @@ -1200,6 +1200,44 @@ ar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency, 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(struct ath_hal *ah, int chain, 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, ¢ers); +#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 ath_hal *ah, } 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; diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c index 315086c2d42e..7a5919eb8495 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c @@ -606,7 +606,7 @@ ar9300_freebsd_beacon_init(struct ath_hal *ah, uint32_t next_beacon, 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); } diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h index f7ddf15fdf3d..1af621ba30f1 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd_inc.h @@ -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 diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c index 8b9a1438e2ce..0f4fab93abbc 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c @@ -436,3 +436,156 @@ void ar9300_dump_keycache(struct ath_hal *ah, int n, u_int32_t *entry) } #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 diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c index a0722b72f8b7..dbf58f628e95 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c @@ -1697,10 +1697,10 @@ ar9300_get_bb_panic_info(struct ath_hal *ah, struct hal_bb_panic_info *bb_panic) /* 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_int8_t *data) /* 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 *ah, u_int32_t val) { 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; +} diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini index 9814dab95b4e..fffaf7af7841 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_osprey22.ini @@ -881,7 +881,7 @@ static const u_int32_t ar9300_osprey_2p2_mac_core[][2] = { { 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_mac_postamble[][5] = { { 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 }, }; diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c index 5a4623f77bb4..2a8f7f86315b 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_power.c @@ -469,7 +469,7 @@ u_int32_t ar9300_wow_offload_handshake(struct ath_hal *ah, u_int32_t pattern_ena 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, HAL_POWER_MODE mode, int set_chip) 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 ath_hal *ah) 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)); diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c index a83099e87d4e..d4065d8211a7 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c @@ -68,6 +68,7 @@ ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds, 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 *ah, struct ath_desc *ds, * 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 *ah, struct ath_desc *ds, rxs->rs_status |= HAL_RXERR_MIC; } } - +#if 0 + rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel; +#endif return HAL_OK; } diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c index 51ce195ff56c..9ed224c46ede 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c @@ -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 ath_hal *ah) 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_hal *ah, int16_t *nf_buf, } } +/* + * 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 *ah, HAL_NFCAL_HIST_FULL *h, int reading, 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 *ah, HAL_CHANNEL_INTERNAL *ichan) 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 *ah, const HAL_CHANNEL_INTERNAL *chan, { 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 type) { 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 type) ar9300_attach_hw_platform(ah); + ahp->ah_chip_reset_done = 1; return AH_TRUE; } @@ -2312,10 +2343,22 @@ ar9300_per_calibration(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *ichan, 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, struct ieee80211_channel *chan, u_int8_t 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_int8_t num_chains) 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, u_int8_t num_chains) 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, u_int8_t num_chains) } /* + * 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 *ah, struct ieee80211_channel *chan, #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_OPMODE opmode, struct ieee80211_channel *ch 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_OPMODE opmode, struct ieee80211_channel *ch 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_OPMODE opmode, struct ieee80211_channel *ch #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_OPMODE opmode, struct ieee80211_channel *ch 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_OPMODE opmode, struct ieee80211_channel *ch } #endif /* + * In case of + * - offchan scan, or + * - same channel and RX IQ Cal already available + * disable RX IQ Cal. + */ + if (is_scan) { + ahp->ah_skip_rx_iq_cal = AH_TRUE; + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "Skip RX IQ Cal due to scanning\n"); + } else { +#if 0 + /* XXX FreeBSD: always just do the RX IQ cal */ + /* XXX I think it's just going to speed things up; I don't think it's to avoid chan bugs */ + if (ahp->ah_rx_cal_complete && + ahp->ah_rx_cal_chan == ichan->channel && + ahp->ah_rx_cal_chan_flag == chan->channel_flags) { + ahp->ah_skip_rx_iq_cal = AH_TRUE; + HALDEBUG(ah, HAL_DEBUG_CALIBRATE, + "Skip RX IQ Cal due to same channel with completed RX IQ Cal\n"); + } else +#endif + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } + + /* * Fast channel change (Change synthesizer based on channel freq * without resetting chip) * Don't do it when @@ -4866,6 +5033,23 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch ar9300_init_bb(ah, chan); /* BB Step 7: Calibration */ + /* + * Only kick off calibration not on offchan. + * If coming back from offchan, restore prevous Cal results + * since chip reset will clear existings. + */ + if (!ahp->ah_skip_rx_iq_cal) { + int i; + /* clear existing RX cal data */ + for (i=0; i<AR9300_MAX_CHAINS; i++) + ahp->ah_rx_cal_corr[i] = 0; + + ahp->ah_rx_cal_complete = AH_FALSE; +// ahp->ah_rx_cal_chan = chan->channel; +// ahp->ah_rx_cal_chan_flag = ichan->channel_flags; + ahp->ah_rx_cal_chan = 0; + ahp->ah_rx_cal_chan_flag = 0; /* XXX FreeBSD */ + } ar9300_invalidate_saved_cals(ah, ichan); cal_ret = ar9300_init_cal(ah, chan, AH_FALSE, apply_last_iqcorr); @@ -5021,6 +5205,11 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch nf_hist_buff_reset = 0; #ifndef ATH_NF_PER_CHAN if (First_NFCal(ah, ichan, is_scan, chan)){ + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } } #endif /* ATH_NF_PER_CHAN */ } @@ -5094,12 +5283,24 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch ar9300_set_smart_antenna(ah, ahp->ah_smartantenna_enable); + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } + return AH_TRUE; bad: OS_MARK(ah, AH_MARK_RESET_DONE, ecode); *status = ecode; + if (ahp->ah_skip_rx_iq_cal && !is_scan) { + /* restore RX Cal result if existing */ + ar9300_rx_iq_cal_restore(ah); + ahp->ah_skip_rx_iq_cal = AH_FALSE; + } + return AH_FALSE; #undef FAIL } diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c index ab392843c612..530b29a237fb 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c @@ -583,6 +583,14 @@ ar9300_num_tx_pending(struct ath_hal *ah, u_int q) HAL_BOOL ar9300_stop_tx_dma(struct ath_hal *ah, u_int q, u_int timeout) { + struct ath_hal_9300 *ahp = AH9300(ah); + + /* + * If we call abort txdma instead, no need to stop RX. + * Otherwise, the RX logic might not be restarted properly. + */ + ahp->ah_abort_txdma_norx = AH_FALSE; + /* * Directly call abort. It is better, hardware-wise, to stop all * queues at once than individual ones. @@ -798,10 +806,40 @@ ar9300_stop_tx_dma_indv_que(struct ath_hal *ah, u_int q, u_int timeout) */ #define AR9300_ABORT_LOOPS 1000 #define AR9300_ABORT_WAIT 5 +#define NEXT_TBTT_NOW 10 HAL_BOOL ar9300_abort_tx_dma(struct ath_hal *ah) { + struct ath_hal_9300 *ahp = AH9300(ah); int i, q; + u_int32_t nexttbtt, nextdba, tsf_tbtt, tbtt, dba; + HAL_BOOL stopped; + HAL_BOOL status = AH_TRUE; + + if (ahp->ah_abort_txdma_norx) { + /* + * First of all, make sure RX has been stopped + */ + if (ar9300_get_power_mode(ah) != HAL_PM_FULL_SLEEP) { + /* Need to stop RX DMA before reset otherwise chip might hang */ + stopped = ar9300_set_rx_abort(ah, AH_TRUE); /* abort and disable PCU */ + ar9300_set_rx_filter(ah, 0); + stopped &= ar9300_stop_dma_receive(ah, 0); /* stop and disable RX DMA */ + if (!stopped) { + /* + * During the transition from full sleep to reset, + * recv DMA regs are not available to be read + */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s[%d]: ar9300_stop_dma_receive failed\n", __func__, __LINE__); + //We still continue to stop TX dma + //return AH_FALSE; + } + } else { + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s[%d]: Chip is already in full sleep\n", __func__, __LINE__); + } + } /* * set txd on all queues @@ -812,13 +850,27 @@ ar9300_abort_tx_dma(struct ath_hal *ah) * set tx abort bits (also disable rx) */ OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); - OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR)); + /* Add a new receipe from K31 code */ + OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | + AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + /* beacon Q flush */ + nexttbtt = OS_REG_READ(ah, AR_NEXT_TBTT_TIMER); + nextdba = OS_REG_READ(ah, AR_NEXT_DMA_BEACON_ALERT); + //printk("%s[%d]:dba: %d, nt: %d \n", __func__, __LINE__, nextdba, nexttbtt); + tsf_tbtt = OS_REG_READ(ah, AR_TSF_L32); + tbtt = tsf_tbtt + NEXT_TBTT_NOW; + dba = tsf_tbtt; + OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, dba); + OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, tbtt); OS_REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); - /* Let TXE (all queues) clear before waiting on any pending frames */ - for (i = 0; i < AR9300_ABORT_LOOPS; i++) { - if (OS_REG_READ(ah, AR_Q_TXE) == 0) { + /* + * Let TXE (all queues) clear before waiting for any pending frames + * This is needed before starting the RF_BUS GRANT sequence other wise causes kernel + * panic + */ + for(i = 0; i < AR9300_ABORT_LOOPS; i++) { + if(OS_REG_READ(ah, AR_Q_TXE) == 0) { break; } OS_DELAY(AR9300_ABORT_WAIT); @@ -830,28 +882,38 @@ ar9300_abort_tx_dma(struct ath_hal *ah) /* * wait on all tx queues + * This need to be checked in the last to gain extra 50 usec. on avg. + * Currently checked first since we dont have a previous channel information currently. + * Which is needed to revert the rf changes. */ - for (q = 0; q < AR_NUM_QCU; q++) { + for (q = AR_NUM_QCU - 1; q >= 0; q--) { for (i = 0; i < AR9300_ABORT_LOOPS; i++) { - if (!ar9300_num_tx_pending(ah, q)) { + if (!(ar9300_num_tx_pending(ah, q))) { break; } OS_DELAY(AR9300_ABORT_WAIT); } if (i == AR9300_ABORT_LOOPS) { - HALDEBUG(ah, HAL_DEBUG_TX, - "%s[%d] reached max wait on pending tx, q %d\n", - __func__, __LINE__, q); - return AH_FALSE; + status = AH_FALSE; + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "ABORT LOOP finsihsed for Q: %d, num_pending: %d \n", + q, ar9300_num_tx_pending(ah, q)); + goto exit; } } + /* Updating the beacon alert register with correct value */ + OS_REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, nextdba); + OS_REG_WRITE(ah, AR_NEXT_TBTT_TIMER, nexttbtt); + +exit: /* * clear tx abort bits */ OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); - OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR)); + /* Added a new receipe from K31 code */ + OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH | AR_DIAG_RX_DIS | + AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); OS_REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); /* @@ -859,7 +921,9 @@ ar9300_abort_tx_dma(struct ath_hal *ah) */ OS_REG_WRITE(ah, AR_Q_TXD, 0); - return AH_TRUE; + ahp->ah_abort_txdma_norx = AH_TRUE; + + return status; } /* diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini index 81894de89d21..ef7dbcab602f 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9340.ini @@ -1078,7 +1078,7 @@ static const u_int32_t ar9340_wasp_1p0_mac_postamble[][5] = { { 0x0000801c , 0x128d8027 , 0x128d804f , 0x12e00057 , 0x12e0002b }, - { 0x00008120 , 0x08f04800 , 0x08f04800 , 0x08f04810 , 0x08f04810 }, + { 0x00008120 , 0x18f04800 , 0x18f04800 , 0x18f04810 , 0x18f04810 }, { 0x000081d0 , 0x00003210 , 0x00003210 , 0x0000320a , 0x0000320a }, @@ -1212,7 +1212,7 @@ static const u_int32_t ar9340_wasp_1p0_baseband_postamble[][5] = { { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, - { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c }, + { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c }, { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce }, @@ -1586,10 +1586,14 @@ static const u_int32_t ar9340_wasp_1p0_baseband_postamble_dfs_channel[][3] = { { 0x00009824 , 0x5ac668d0 , 0x5ac668d0 }, + { 0x00009828 , 0x06903080 , 0x06903080 }, + { 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 }, { 0x00009e14 , 0x37b9625e , 0x37b9625e }, + { 0x00009814 , 0x3400c00f , 0x3400c00f }, + }; diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini b/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini index 32124dbdfbc2..52b92ff1f7c9 100644 --- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini +++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9580.ini @@ -34,8 +34,10 @@ static const u_int32_t ar9300_ar9580_1p0_baseband_postamble_dfs_channel[][3] = { /* Addr 5G_HT20 5G_HT40 */ { 0x00009824 , 0x5ac668d0 , 0x5ac668d0 }, + { 0x00009828 , 0x06903080 , 0x06903080 }, { 0x00009e0c , 0x6d4000e2 , 0x6d4000e2 }, { 0x00009e14 , 0x37b9625e , 0x37b9625e }, + { 0x00009814 , 0x3400c00f , 0x3400c00f }, }; static const u_int32_t ar9300Modes_fast_clock_ar9580_1p0[][3] = { @@ -257,7 +259,7 @@ static const u_int32_t ar9300_ar9580_1p0_mac_postamble[][5] = { { 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 }, }; @@ -1091,7 +1093,7 @@ static const u_int32_t ar9300_ar9580_1p0_mac_core[][2] = { { 0x00008258 , 0x00000000 }, { 0x0000825c , 0x40000000 }, { 0x00008260 , 0x00080922 }, - { 0x00008264 , 0x9bc00010 }, + { 0x00008264 , 0x9d400010 }, { 0x00008268 , 0xffffffff }, { 0x0000826c , 0x0000ffff }, { 0x00008270 , 0x00000000 }, @@ -2155,7 +2157,7 @@ static const u_int32_t ar9300_ar9580_1p0_baseband_postamble[][5] = { { 0x00009e10 , 0x7ec88d2e , 0x7ec88d2e , 0x7ec84d2e , 0x7ec84d2e }, { 0x00009e14 , 0x37b95d5e , 0x37b9605e , 0x3379605e , 0x33795d5e }, { 0x00009e18 , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 }, - { 0x00009e1c , 0x0001cf9c , 0x0001cf9c , 0x00021f9c , 0x00021f9c }, + { 0x00009e1c , 0x0001c59c , 0x0001c59c , 0x0002159c , 0x0002159c }, { 0x00009e20 , 0x000003b5 , 0x000003b5 , 0x000003ce , 0x000003ce }, { 0x00009e2c , 0x0000001c , 0x0000001c , 0x00000021 , 0x00000021 }, { 0x00009e3c , 0xcf946220 , 0xcf946220 , 0xcf946222 , 0xcf946222 }, |