From: Felix Fietkau Date: Wed, 14 Apr 2010 02:35:56 +0000 (+0000) Subject: ath9k: fix a crash in ath9k_hw_reset on older hw X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fsvn-archive%2Farchive.git;a=commitdiff_plain;hb=e3bfd57e8a853afeb54d4476cda09c35026a2779 ath9k: fix a crash in ath9k_hw_reset on older hw SVN-Revision: 20852 --- diff --git a/package/mac80211/patches/300-ar9300_support.patch b/package/mac80211/patches/300-ar9300_support.patch index 5a4a9033c9..9e494647a9 100644 --- a/package/mac80211/patches/300-ar9300_support.patch +++ b/package/mac80211/patches/300-ar9300_support.patch @@ -978,7 +978,7 @@ +#endif /* INITVALS_AR5008_H */ --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c -@@ -0,0 +1,1278 @@ +@@ -0,0 +1,1345 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * @@ -2226,6 +2226,72 @@ + nfarray[5] = nf; +} + ++static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) ++{ ++ struct ath9k_nfcal_hist *h; ++ int i, j; ++ int32_t val; ++ const u32 ar5416_cca_regs[6] = { ++ AR_PHY_CCA, ++ AR_PHY_CH1_CCA, ++ AR_PHY_CH2_CCA, ++ AR_PHY_EXT_CCA, ++ AR_PHY_CH1_EXT_CCA, ++ AR_PHY_CH2_EXT_CCA ++ }; ++ u8 chainmask, rx_chain_status; ++ ++ rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); ++ if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) ++ chainmask = 0x9; ++ else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { ++ if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) ++ chainmask = 0x1B; ++ else ++ chainmask = 0x09; ++ } else { ++ if (rx_chain_status & 0x4) ++ chainmask = 0x3F; ++ else if (rx_chain_status & 0x2) ++ chainmask = 0x1B; ++ else ++ chainmask = 0x09; ++ } ++ ++ h = ah->nfCalHist; ++ ++ for (i = 0; i < NUM_NF_READINGS; i++) { ++ if (chainmask & (1 << i)) { ++ val = REG_READ(ah, ar5416_cca_regs[i]); ++ val &= 0xFFFFFE00; ++ val |= (((u32) (h[i].privNF) << 1) & 0x1ff); ++ REG_WRITE(ah, ar5416_cca_regs[i], val); ++ } ++ } ++ ++ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, ++ AR_PHY_AGC_CONTROL_ENABLE_NF); ++ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, ++ AR_PHY_AGC_CONTROL_NO_UPDATE_NF); ++ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); ++ ++ for (j = 0; j < 5; j++) { ++ if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & ++ AR_PHY_AGC_CONTROL_NF) == 0) ++ break; ++ udelay(50); ++ } ++ ++ for (i = 0; i < NUM_NF_READINGS; i++) { ++ if (chainmask & (1 << i)) { ++ val = REG_READ(ah, ar5416_cca_regs[i]); ++ val &= 0xFFFFFE00; ++ val |= (((u32) (-50) << 1) & 0x1ff); ++ REG_WRITE(ah, ar5416_cca_regs[i], val); ++ } ++ } ++} ++ +void ar5008_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -2249,6 +2315,7 @@ + priv_ops->set_diversity = ar5008_set_diversity; + priv_ops->ani_control = ar5008_hw_ani_control; + priv_ops->do_getnf = ar5008_hw_do_getnf; ++ priv_ops->loadnf = ar5008_hw_loadnf; + + if (AR_SREV_9100(ah)) + priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; @@ -10791,7 +10858,7 @@ +} --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c -@@ -0,0 +1,601 @@ +@@ -0,0 +1,534 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * @@ -11313,72 +11380,6 @@ + } +} + -+static void ar9002_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) -+{ -+ struct ath9k_nfcal_hist *h; -+ int i, j; -+ int32_t val; -+ const u32 ar5416_cca_regs[6] = { -+ AR_PHY_CCA, -+ AR_PHY_CH1_CCA, -+ AR_PHY_CH2_CCA, -+ AR_PHY_EXT_CCA, -+ AR_PHY_CH1_EXT_CCA, -+ AR_PHY_CH2_EXT_CCA -+ }; -+ u8 chainmask, rx_chain_status; -+ -+ rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); -+ if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) -+ chainmask = 0x9; -+ else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { -+ if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) -+ chainmask = 0x1B; -+ else -+ chainmask = 0x09; -+ } else { -+ if (rx_chain_status & 0x4) -+ chainmask = 0x3F; -+ else if (rx_chain_status & 0x2) -+ chainmask = 0x1B; -+ else -+ chainmask = 0x09; -+ } -+ -+ h = ah->nfCalHist; -+ -+ for (i = 0; i < NUM_NF_READINGS; i++) { -+ if (chainmask & (1 << i)) { -+ val = REG_READ(ah, ar5416_cca_regs[i]); -+ val &= 0xFFFFFE00; -+ val |= (((u32) (h[i].privNF) << 1) & 0x1ff); -+ REG_WRITE(ah, ar5416_cca_regs[i], val); -+ } -+ } -+ -+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -+ AR_PHY_AGC_CONTROL_ENABLE_NF); -+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF); -+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); -+ -+ for (j = 0; j < 5; j++) { -+ if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & -+ AR_PHY_AGC_CONTROL_NF) == 0) -+ break; -+ udelay(50); -+ } -+ -+ for (i = 0; i < NUM_NF_READINGS; i++) { -+ if (chainmask & (1 << i)) { -+ val = REG_READ(ah, ar5416_cca_regs[i]); -+ val &= 0xFFFFFE00; -+ val |= (((u32) (-50) << 1) & 0x1ff); -+ REG_WRITE(ah, ar5416_cca_regs[i], val); -+ } -+ } -+} -+ +void ar9002_hw_attach_phy_ops(struct ath_hw *ah) +{ + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); @@ -11391,7 +11392,6 @@ + priv_ops->olc_init = ar9002_olc_init; + priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; + priv_ops->do_getnf = ar9002_hw_do_getnf; -+ priv_ops->loadnf = ar9002_hw_loadnf; +} --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h