diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw-ops.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 281 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 290 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/reg.h | 2 |
7 files changed, 310 insertions, 286 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index b229597e54cd..15f1b0f0d070 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -30,6 +30,11 @@ static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) | |||
30 | *ds_link = &((struct ar9003_txc *) ds)->link; | 30 | *ds_link = &((struct ar9003_txc *) ds)->link; |
31 | } | 31 | } |
32 | 32 | ||
33 | static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | ||
34 | { | ||
35 | return true; | ||
36 | } | ||
37 | |||
33 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 38 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
34 | { | 39 | { |
35 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 40 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
@@ -37,6 +42,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
37 | ops->rx_enable = ar9003_hw_rx_enable; | 42 | ops->rx_enable = ar9003_hw_rx_enable; |
38 | ops->set_desc_link = ar9003_hw_set_desc_link; | 43 | ops->set_desc_link = ar9003_hw_set_desc_link; |
39 | ops->get_desc_link = ar9003_hw_get_desc_link; | 44 | ops->get_desc_link = ar9003_hw_get_desc_link; |
45 | ops->get_isr = ar9003_hw_get_isr; | ||
40 | } | 46 | } |
41 | 47 | ||
42 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 48 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 3848c0d3f99e..b777fd1894f0 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -52,6 +52,11 @@ static inline bool ath9k_hw_calibrate(struct ath_hw *ah, | |||
52 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); | 52 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); |
53 | } | 53 | } |
54 | 54 | ||
55 | static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | ||
56 | { | ||
57 | return ath9k_hw_ops(ah)->get_isr(ah, masked); | ||
58 | } | ||
59 | |||
55 | /* Private hardware call ops */ | 60 | /* Private hardware call ops */ |
56 | 61 | ||
57 | /* PHY ops */ | 62 | /* PHY ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 127546c42223..ac57a975d014 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1780,287 +1780,6 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
1780 | } | 1780 | } |
1781 | EXPORT_SYMBOL(ath9k_hw_setpower); | 1781 | EXPORT_SYMBOL(ath9k_hw_setpower); |
1782 | 1782 | ||
1783 | /**********************/ | ||
1784 | /* Interrupt Handling */ | ||
1785 | /**********************/ | ||
1786 | |||
1787 | bool ath9k_hw_intrpend(struct ath_hw *ah) | ||
1788 | { | ||
1789 | u32 host_isr; | ||
1790 | |||
1791 | if (AR_SREV_9100(ah)) | ||
1792 | return true; | ||
1793 | |||
1794 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | ||
1795 | if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) | ||
1796 | return true; | ||
1797 | |||
1798 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); | ||
1799 | if ((host_isr & AR_INTR_SYNC_DEFAULT) | ||
1800 | && (host_isr != AR_INTR_SPURIOUS)) | ||
1801 | return true; | ||
1802 | |||
1803 | return false; | ||
1804 | } | ||
1805 | EXPORT_SYMBOL(ath9k_hw_intrpend); | ||
1806 | |||
1807 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | ||
1808 | { | ||
1809 | u32 isr = 0; | ||
1810 | u32 mask2 = 0; | ||
1811 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1812 | u32 sync_cause = 0; | ||
1813 | bool fatal_int = false; | ||
1814 | struct ath_common *common = ath9k_hw_common(ah); | ||
1815 | |||
1816 | if (!AR_SREV_9100(ah)) { | ||
1817 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | ||
1818 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | ||
1819 | == AR_RTC_STATUS_ON) { | ||
1820 | isr = REG_READ(ah, AR_ISR); | ||
1821 | } | ||
1822 | } | ||
1823 | |||
1824 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & | ||
1825 | AR_INTR_SYNC_DEFAULT; | ||
1826 | |||
1827 | *masked = 0; | ||
1828 | |||
1829 | if (!isr && !sync_cause) | ||
1830 | return false; | ||
1831 | } else { | ||
1832 | *masked = 0; | ||
1833 | isr = REG_READ(ah, AR_ISR); | ||
1834 | } | ||
1835 | |||
1836 | if (isr) { | ||
1837 | if (isr & AR_ISR_BCNMISC) { | ||
1838 | u32 isr2; | ||
1839 | isr2 = REG_READ(ah, AR_ISR_S2); | ||
1840 | if (isr2 & AR_ISR_S2_TIM) | ||
1841 | mask2 |= ATH9K_INT_TIM; | ||
1842 | if (isr2 & AR_ISR_S2_DTIM) | ||
1843 | mask2 |= ATH9K_INT_DTIM; | ||
1844 | if (isr2 & AR_ISR_S2_DTIMSYNC) | ||
1845 | mask2 |= ATH9K_INT_DTIMSYNC; | ||
1846 | if (isr2 & (AR_ISR_S2_CABEND)) | ||
1847 | mask2 |= ATH9K_INT_CABEND; | ||
1848 | if (isr2 & AR_ISR_S2_GTT) | ||
1849 | mask2 |= ATH9K_INT_GTT; | ||
1850 | if (isr2 & AR_ISR_S2_CST) | ||
1851 | mask2 |= ATH9K_INT_CST; | ||
1852 | if (isr2 & AR_ISR_S2_TSFOOR) | ||
1853 | mask2 |= ATH9K_INT_TSFOOR; | ||
1854 | } | ||
1855 | |||
1856 | isr = REG_READ(ah, AR_ISR_RAC); | ||
1857 | if (isr == 0xffffffff) { | ||
1858 | *masked = 0; | ||
1859 | return false; | ||
1860 | } | ||
1861 | |||
1862 | *masked = isr & ATH9K_INT_COMMON; | ||
1863 | |||
1864 | if (ah->config.rx_intr_mitigation) { | ||
1865 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | ||
1866 | *masked |= ATH9K_INT_RX; | ||
1867 | } | ||
1868 | |||
1869 | if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) | ||
1870 | *masked |= ATH9K_INT_RX; | ||
1871 | if (isr & | ||
1872 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | | ||
1873 | AR_ISR_TXEOL)) { | ||
1874 | u32 s0_s, s1_s; | ||
1875 | |||
1876 | *masked |= ATH9K_INT_TX; | ||
1877 | |||
1878 | s0_s = REG_READ(ah, AR_ISR_S0_S); | ||
1879 | ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); | ||
1880 | ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); | ||
1881 | |||
1882 | s1_s = REG_READ(ah, AR_ISR_S1_S); | ||
1883 | ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); | ||
1884 | ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); | ||
1885 | } | ||
1886 | |||
1887 | if (isr & AR_ISR_RXORN) { | ||
1888 | ath_print(common, ATH_DBG_INTERRUPT, | ||
1889 | "receive FIFO overrun interrupt\n"); | ||
1890 | } | ||
1891 | |||
1892 | if (!AR_SREV_9100(ah)) { | ||
1893 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1894 | u32 isr5 = REG_READ(ah, AR_ISR_S5_S); | ||
1895 | if (isr5 & AR_ISR_S5_TIM_TIMER) | ||
1896 | *masked |= ATH9K_INT_TIM_TIMER; | ||
1897 | } | ||
1898 | } | ||
1899 | |||
1900 | *masked |= mask2; | ||
1901 | } | ||
1902 | |||
1903 | if (AR_SREV_9100(ah)) | ||
1904 | return true; | ||
1905 | |||
1906 | if (isr & AR_ISR_GENTMR) { | ||
1907 | u32 s5_s; | ||
1908 | |||
1909 | s5_s = REG_READ(ah, AR_ISR_S5_S); | ||
1910 | if (isr & AR_ISR_GENTMR) { | ||
1911 | ah->intr_gen_timer_trigger = | ||
1912 | MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); | ||
1913 | |||
1914 | ah->intr_gen_timer_thresh = | ||
1915 | MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); | ||
1916 | |||
1917 | if (ah->intr_gen_timer_trigger) | ||
1918 | *masked |= ATH9K_INT_GENTIMER; | ||
1919 | |||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | if (sync_cause) { | ||
1924 | fatal_int = | ||
1925 | (sync_cause & | ||
1926 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | ||
1927 | ? true : false; | ||
1928 | |||
1929 | if (fatal_int) { | ||
1930 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | ||
1931 | ath_print(common, ATH_DBG_ANY, | ||
1932 | "received PCI FATAL interrupt\n"); | ||
1933 | } | ||
1934 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | ||
1935 | ath_print(common, ATH_DBG_ANY, | ||
1936 | "received PCI PERR interrupt\n"); | ||
1937 | } | ||
1938 | *masked |= ATH9K_INT_FATAL; | ||
1939 | } | ||
1940 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | ||
1941 | ath_print(common, ATH_DBG_INTERRUPT, | ||
1942 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); | ||
1943 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | ||
1944 | REG_WRITE(ah, AR_RC, 0); | ||
1945 | *masked |= ATH9K_INT_FATAL; | ||
1946 | } | ||
1947 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | ||
1948 | ath_print(common, ATH_DBG_INTERRUPT, | ||
1949 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | ||
1950 | } | ||
1951 | |||
1952 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | ||
1953 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | ||
1954 | } | ||
1955 | |||
1956 | return true; | ||
1957 | } | ||
1958 | EXPORT_SYMBOL(ath9k_hw_getisr); | ||
1959 | |||
1960 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | ||
1961 | { | ||
1962 | enum ath9k_int omask = ah->imask; | ||
1963 | u32 mask, mask2; | ||
1964 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1965 | struct ath_common *common = ath9k_hw_common(ah); | ||
1966 | |||
1967 | ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); | ||
1968 | |||
1969 | if (omask & ATH9K_INT_GLOBAL) { | ||
1970 | ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); | ||
1971 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
1972 | (void) REG_READ(ah, AR_IER); | ||
1973 | if (!AR_SREV_9100(ah)) { | ||
1974 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
1975 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
1976 | |||
1977 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
1978 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
1979 | } | ||
1980 | } | ||
1981 | |||
1982 | mask = ints & ATH9K_INT_COMMON; | ||
1983 | mask2 = 0; | ||
1984 | |||
1985 | if (ints & ATH9K_INT_TX) { | ||
1986 | if (ah->txok_interrupt_mask) | ||
1987 | mask |= AR_IMR_TXOK; | ||
1988 | if (ah->txdesc_interrupt_mask) | ||
1989 | mask |= AR_IMR_TXDESC; | ||
1990 | if (ah->txerr_interrupt_mask) | ||
1991 | mask |= AR_IMR_TXERR; | ||
1992 | if (ah->txeol_interrupt_mask) | ||
1993 | mask |= AR_IMR_TXEOL; | ||
1994 | } | ||
1995 | if (ints & ATH9K_INT_RX) { | ||
1996 | mask |= AR_IMR_RXERR; | ||
1997 | if (ah->config.rx_intr_mitigation) | ||
1998 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | ||
1999 | else | ||
2000 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | ||
2001 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | ||
2002 | mask |= AR_IMR_GENTMR; | ||
2003 | } | ||
2004 | |||
2005 | if (ints & (ATH9K_INT_BMISC)) { | ||
2006 | mask |= AR_IMR_BCNMISC; | ||
2007 | if (ints & ATH9K_INT_TIM) | ||
2008 | mask2 |= AR_IMR_S2_TIM; | ||
2009 | if (ints & ATH9K_INT_DTIM) | ||
2010 | mask2 |= AR_IMR_S2_DTIM; | ||
2011 | if (ints & ATH9K_INT_DTIMSYNC) | ||
2012 | mask2 |= AR_IMR_S2_DTIMSYNC; | ||
2013 | if (ints & ATH9K_INT_CABEND) | ||
2014 | mask2 |= AR_IMR_S2_CABEND; | ||
2015 | if (ints & ATH9K_INT_TSFOOR) | ||
2016 | mask2 |= AR_IMR_S2_TSFOOR; | ||
2017 | } | ||
2018 | |||
2019 | if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { | ||
2020 | mask |= AR_IMR_BCNMISC; | ||
2021 | if (ints & ATH9K_INT_GTT) | ||
2022 | mask2 |= AR_IMR_S2_GTT; | ||
2023 | if (ints & ATH9K_INT_CST) | ||
2024 | mask2 |= AR_IMR_S2_CST; | ||
2025 | } | ||
2026 | |||
2027 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); | ||
2028 | REG_WRITE(ah, AR_IMR, mask); | ||
2029 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | | ||
2030 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | | ||
2031 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); | ||
2032 | ah->imrs2_reg |= mask2; | ||
2033 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
2034 | |||
2035 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
2036 | if (ints & ATH9K_INT_TIM_TIMER) | ||
2037 | REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
2038 | else | ||
2039 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
2040 | } | ||
2041 | |||
2042 | if (ints & ATH9K_INT_GLOBAL) { | ||
2043 | ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); | ||
2044 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
2045 | if (!AR_SREV_9100(ah)) { | ||
2046 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
2047 | AR_INTR_MAC_IRQ); | ||
2048 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
2049 | |||
2050 | |||
2051 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, | ||
2052 | AR_INTR_SYNC_DEFAULT); | ||
2053 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | ||
2054 | AR_INTR_SYNC_DEFAULT); | ||
2055 | } | ||
2056 | ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
2057 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
2058 | } | ||
2059 | |||
2060 | return omask; | ||
2061 | } | ||
2062 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); | ||
2063 | |||
2064 | /*******************/ | 1783 | /*******************/ |
2065 | /* Beacon Handling */ | 1784 | /* Beacon Handling */ |
2066 | /*******************/ | 1785 | /*******************/ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b27e76b82dcf..7a32733108a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -227,6 +227,7 @@ struct ath9k_ops_config { | |||
227 | u32 enable_ani; | 227 | u32 enable_ani; |
228 | int serialize_regmode; | 228 | int serialize_regmode; |
229 | bool rx_intr_mitigation; | 229 | bool rx_intr_mitigation; |
230 | bool tx_intr_mitigation; | ||
230 | #define SPUR_DISABLE 0 | 231 | #define SPUR_DISABLE 0 |
231 | #define SPUR_ENABLE_IOCTL 1 | 232 | #define SPUR_ENABLE_IOCTL 1 |
232 | #define SPUR_ENABLE_EEPROM 2 | 233 | #define SPUR_ENABLE_EEPROM 2 |
@@ -549,6 +550,7 @@ struct ath_hw_ops { | |||
549 | struct ath9k_channel *chan, | 550 | struct ath9k_channel *chan, |
550 | u8 rxchainmask, | 551 | u8 rxchainmask, |
551 | bool longcal); | 552 | bool longcal); |
553 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); | ||
552 | }; | 554 | }; |
553 | 555 | ||
554 | struct ath_hw { | 556 | struct ath_hw { |
@@ -810,11 +812,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
810 | 812 | ||
811 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); | 813 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
812 | 814 | ||
813 | /* Interrupt Handling */ | ||
814 | bool ath9k_hw_intrpend(struct ath_hw *ah); | ||
815 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); | ||
816 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); | ||
817 | |||
818 | /* Generic hw timer primitives */ | 815 | /* Generic hw timer primitives */ |
819 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | 816 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, |
820 | void (*trigger)(void *), | 817 | void (*trigger)(void *), |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index a8dab23622f1..4a36ec53f732 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -31,6 +31,158 @@ static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) | |||
31 | *ds_link = &((struct ath_desc *)ds)->ds_link; | 31 | *ds_link = &((struct ath_desc *)ds)->ds_link; |
32 | } | 32 | } |
33 | 33 | ||
34 | static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | ||
35 | { | ||
36 | u32 isr = 0; | ||
37 | u32 mask2 = 0; | ||
38 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
39 | u32 sync_cause = 0; | ||
40 | bool fatal_int = false; | ||
41 | struct ath_common *common = ath9k_hw_common(ah); | ||
42 | |||
43 | if (!AR_SREV_9100(ah)) { | ||
44 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | ||
45 | if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) | ||
46 | == AR_RTC_STATUS_ON) { | ||
47 | isr = REG_READ(ah, AR_ISR); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & | ||
52 | AR_INTR_SYNC_DEFAULT; | ||
53 | |||
54 | *masked = 0; | ||
55 | |||
56 | if (!isr && !sync_cause) | ||
57 | return false; | ||
58 | } else { | ||
59 | *masked = 0; | ||
60 | isr = REG_READ(ah, AR_ISR); | ||
61 | } | ||
62 | |||
63 | if (isr) { | ||
64 | if (isr & AR_ISR_BCNMISC) { | ||
65 | u32 isr2; | ||
66 | isr2 = REG_READ(ah, AR_ISR_S2); | ||
67 | if (isr2 & AR_ISR_S2_TIM) | ||
68 | mask2 |= ATH9K_INT_TIM; | ||
69 | if (isr2 & AR_ISR_S2_DTIM) | ||
70 | mask2 |= ATH9K_INT_DTIM; | ||
71 | if (isr2 & AR_ISR_S2_DTIMSYNC) | ||
72 | mask2 |= ATH9K_INT_DTIMSYNC; | ||
73 | if (isr2 & (AR_ISR_S2_CABEND)) | ||
74 | mask2 |= ATH9K_INT_CABEND; | ||
75 | if (isr2 & AR_ISR_S2_GTT) | ||
76 | mask2 |= ATH9K_INT_GTT; | ||
77 | if (isr2 & AR_ISR_S2_CST) | ||
78 | mask2 |= ATH9K_INT_CST; | ||
79 | if (isr2 & AR_ISR_S2_TSFOOR) | ||
80 | mask2 |= ATH9K_INT_TSFOOR; | ||
81 | } | ||
82 | |||
83 | isr = REG_READ(ah, AR_ISR_RAC); | ||
84 | if (isr == 0xffffffff) { | ||
85 | *masked = 0; | ||
86 | return false; | ||
87 | } | ||
88 | |||
89 | *masked = isr & ATH9K_INT_COMMON; | ||
90 | |||
91 | if (ah->config.rx_intr_mitigation) { | ||
92 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | ||
93 | *masked |= ATH9K_INT_RX; | ||
94 | } | ||
95 | |||
96 | if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) | ||
97 | *masked |= ATH9K_INT_RX; | ||
98 | if (isr & | ||
99 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | | ||
100 | AR_ISR_TXEOL)) { | ||
101 | u32 s0_s, s1_s; | ||
102 | |||
103 | *masked |= ATH9K_INT_TX; | ||
104 | |||
105 | s0_s = REG_READ(ah, AR_ISR_S0_S); | ||
106 | ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); | ||
107 | ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); | ||
108 | |||
109 | s1_s = REG_READ(ah, AR_ISR_S1_S); | ||
110 | ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); | ||
111 | ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); | ||
112 | } | ||
113 | |||
114 | if (isr & AR_ISR_RXORN) { | ||
115 | ath_print(common, ATH_DBG_INTERRUPT, | ||
116 | "receive FIFO overrun interrupt\n"); | ||
117 | } | ||
118 | |||
119 | if (!AR_SREV_9100(ah)) { | ||
120 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
121 | u32 isr5 = REG_READ(ah, AR_ISR_S5_S); | ||
122 | if (isr5 & AR_ISR_S5_TIM_TIMER) | ||
123 | *masked |= ATH9K_INT_TIM_TIMER; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | *masked |= mask2; | ||
128 | } | ||
129 | |||
130 | if (AR_SREV_9100(ah)) | ||
131 | return true; | ||
132 | |||
133 | if (isr & AR_ISR_GENTMR) { | ||
134 | u32 s5_s; | ||
135 | |||
136 | s5_s = REG_READ(ah, AR_ISR_S5_S); | ||
137 | if (isr & AR_ISR_GENTMR) { | ||
138 | ah->intr_gen_timer_trigger = | ||
139 | MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); | ||
140 | |||
141 | ah->intr_gen_timer_thresh = | ||
142 | MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); | ||
143 | |||
144 | if (ah->intr_gen_timer_trigger) | ||
145 | *masked |= ATH9K_INT_GENTIMER; | ||
146 | |||
147 | } | ||
148 | } | ||
149 | |||
150 | if (sync_cause) { | ||
151 | fatal_int = | ||
152 | (sync_cause & | ||
153 | (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) | ||
154 | ? true : false; | ||
155 | |||
156 | if (fatal_int) { | ||
157 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | ||
158 | ath_print(common, ATH_DBG_ANY, | ||
159 | "received PCI FATAL interrupt\n"); | ||
160 | } | ||
161 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | ||
162 | ath_print(common, ATH_DBG_ANY, | ||
163 | "received PCI PERR interrupt\n"); | ||
164 | } | ||
165 | *masked |= ATH9K_INT_FATAL; | ||
166 | } | ||
167 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | ||
168 | ath_print(common, ATH_DBG_INTERRUPT, | ||
169 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); | ||
170 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | ||
171 | REG_WRITE(ah, AR_RC, 0); | ||
172 | *masked |= ATH9K_INT_FATAL; | ||
173 | } | ||
174 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | ||
175 | ath_print(common, ATH_DBG_INTERRUPT, | ||
176 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | ||
177 | } | ||
178 | |||
179 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | ||
180 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | ||
181 | } | ||
182 | |||
183 | return true; | ||
184 | } | ||
185 | |||
34 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | 186 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah) |
35 | { | 187 | { |
36 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | 188 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
@@ -38,6 +190,7 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | |||
38 | ops->rx_enable = ar9002_hw_rx_enable; | 190 | ops->rx_enable = ar9002_hw_rx_enable; |
39 | ops->set_desc_link = ar9002_hw_set_desc_link; | 191 | ops->set_desc_link = ar9002_hw_set_desc_link; |
40 | ops->get_desc_link = ar9002_hw_get_desc_link; | 192 | ops->get_desc_link = ar9002_hw_get_desc_link; |
193 | ops->get_isr = ar9002_hw_get_isr; | ||
41 | } | 194 | } |
42 | 195 | ||
43 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 196 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
@@ -1089,3 +1242,140 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah) | |||
1089 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | 1242 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); |
1090 | } | 1243 | } |
1091 | EXPORT_SYMBOL(ath9k_hw_beaconq_setup); | 1244 | EXPORT_SYMBOL(ath9k_hw_beaconq_setup); |
1245 | |||
1246 | bool ath9k_hw_intrpend(struct ath_hw *ah) | ||
1247 | { | ||
1248 | u32 host_isr; | ||
1249 | |||
1250 | if (AR_SREV_9100(ah)) | ||
1251 | return true; | ||
1252 | |||
1253 | host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); | ||
1254 | if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) | ||
1255 | return true; | ||
1256 | |||
1257 | host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); | ||
1258 | if ((host_isr & AR_INTR_SYNC_DEFAULT) | ||
1259 | && (host_isr != AR_INTR_SPURIOUS)) | ||
1260 | return true; | ||
1261 | |||
1262 | return false; | ||
1263 | } | ||
1264 | EXPORT_SYMBOL(ath9k_hw_intrpend); | ||
1265 | |||
1266 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | ||
1267 | enum ath9k_int ints) | ||
1268 | { | ||
1269 | enum ath9k_int omask = ah->imask; | ||
1270 | u32 mask, mask2; | ||
1271 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1272 | struct ath_common *common = ath9k_hw_common(ah); | ||
1273 | |||
1274 | ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); | ||
1275 | |||
1276 | if (omask & ATH9K_INT_GLOBAL) { | ||
1277 | ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); | ||
1278 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
1279 | (void) REG_READ(ah, AR_IER); | ||
1280 | if (!AR_SREV_9100(ah)) { | ||
1281 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
1282 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
1283 | |||
1284 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
1285 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | /* TODO: global int Ref count */ | ||
1290 | mask = ints & ATH9K_INT_COMMON; | ||
1291 | mask2 = 0; | ||
1292 | |||
1293 | if (ints & ATH9K_INT_TX) { | ||
1294 | if (ah->config.tx_intr_mitigation) | ||
1295 | mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; | ||
1296 | if (ah->txok_interrupt_mask) | ||
1297 | mask |= AR_IMR_TXOK; | ||
1298 | if (ah->txdesc_interrupt_mask) | ||
1299 | mask |= AR_IMR_TXDESC; | ||
1300 | if (ah->txerr_interrupt_mask) | ||
1301 | mask |= AR_IMR_TXERR; | ||
1302 | if (ah->txeol_interrupt_mask) | ||
1303 | mask |= AR_IMR_TXEOL; | ||
1304 | } | ||
1305 | if (ints & ATH9K_INT_RX) { | ||
1306 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1307 | mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP; | ||
1308 | if (ah->config.rx_intr_mitigation) { | ||
1309 | mask &= ~AR_IMR_RXOK_LP; | ||
1310 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | ||
1311 | } else { | ||
1312 | mask |= AR_IMR_RXOK_LP; | ||
1313 | } | ||
1314 | } else { | ||
1315 | if (ah->config.rx_intr_mitigation) | ||
1316 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | ||
1317 | else | ||
1318 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | ||
1319 | } | ||
1320 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | ||
1321 | mask |= AR_IMR_GENTMR; | ||
1322 | } | ||
1323 | |||
1324 | if (ints & (ATH9K_INT_BMISC)) { | ||
1325 | mask |= AR_IMR_BCNMISC; | ||
1326 | if (ints & ATH9K_INT_TIM) | ||
1327 | mask2 |= AR_IMR_S2_TIM; | ||
1328 | if (ints & ATH9K_INT_DTIM) | ||
1329 | mask2 |= AR_IMR_S2_DTIM; | ||
1330 | if (ints & ATH9K_INT_DTIMSYNC) | ||
1331 | mask2 |= AR_IMR_S2_DTIMSYNC; | ||
1332 | if (ints & ATH9K_INT_CABEND) | ||
1333 | mask2 |= AR_IMR_S2_CABEND; | ||
1334 | if (ints & ATH9K_INT_TSFOOR) | ||
1335 | mask2 |= AR_IMR_S2_TSFOOR; | ||
1336 | } | ||
1337 | |||
1338 | if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { | ||
1339 | mask |= AR_IMR_BCNMISC; | ||
1340 | if (ints & ATH9K_INT_GTT) | ||
1341 | mask2 |= AR_IMR_S2_GTT; | ||
1342 | if (ints & ATH9K_INT_CST) | ||
1343 | mask2 |= AR_IMR_S2_CST; | ||
1344 | } | ||
1345 | |||
1346 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); | ||
1347 | REG_WRITE(ah, AR_IMR, mask); | ||
1348 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | | ||
1349 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | | ||
1350 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); | ||
1351 | ah->imrs2_reg |= mask2; | ||
1352 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | ||
1353 | |||
1354 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1355 | if (ints & ATH9K_INT_TIM_TIMER) | ||
1356 | REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
1357 | else | ||
1358 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | ||
1359 | } | ||
1360 | |||
1361 | if (ints & ATH9K_INT_GLOBAL) { | ||
1362 | ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); | ||
1363 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
1364 | if (!AR_SREV_9100(ah)) { | ||
1365 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
1366 | AR_INTR_MAC_IRQ); | ||
1367 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
1368 | |||
1369 | |||
1370 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, | ||
1371 | AR_INTR_SYNC_DEFAULT); | ||
1372 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | ||
1373 | AR_INTR_SYNC_DEFAULT); | ||
1374 | } | ||
1375 | ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
1376 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
1377 | } | ||
1378 | |||
1379 | return omask; | ||
1380 | } | ||
1381 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 99f81ebb35bf..7c0d75490211 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -736,6 +736,11 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah); | |||
736 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); | 736 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); |
737 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); | 737 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); |
738 | 738 | ||
739 | /* Interrupt Handling */ | ||
740 | bool ath9k_hw_intrpend(struct ath_hw *ah); | ||
741 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | ||
742 | enum ath9k_int ints); | ||
743 | |||
739 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah); | 744 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah); |
740 | 745 | ||
741 | #endif /* MAC_H */ | 746 | #endif /* MAC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 96b2cfee8e33..7f856334a28a 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -253,6 +253,8 @@ | |||
253 | #define AR_IMR 0x00a0 | 253 | #define AR_IMR 0x00a0 |
254 | #define AR_IMR_RXOK 0x00000001 | 254 | #define AR_IMR_RXOK 0x00000001 |
255 | #define AR_IMR_RXDESC 0x00000002 | 255 | #define AR_IMR_RXDESC 0x00000002 |
256 | #define AR_IMR_RXOK_HP 0x00000001 | ||
257 | #define AR_IMR_RXOK_LP 0x00000002 | ||
256 | #define AR_IMR_RXERR 0x00000004 | 258 | #define AR_IMR_RXERR 0x00000004 |
257 | #define AR_IMR_RXNOPKT 0x00000008 | 259 | #define AR_IMR_RXNOPKT 0x00000008 |
258 | #define AR_IMR_RXEOL 0x00000010 | 260 | #define AR_IMR_RXEOL 0x00000010 |