diff options
author | Helmut Schaa <helmut.schaa@googlemail.com> | 2011-03-28 07:33:40 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-04 16:20:03 -0400 |
commit | 9e33a3553821418b2c4f53d09311476c55176b13 (patch) | |
tree | fa0538ca1775be5b598949b2418721268e0ece53 /drivers/net/wireless/rt2x00 | |
parent | 2f2bb7e8bdc977c94cdaaf84328526555eba89b1 (diff) |
rt2x00: Implement tx power temperature compensation
rt2800 devices should adjust their tx power in accordance with the
eeproms temperature calibration values. Add a new driver callback
gain_calibration that is called every 4 seconds.
The rt2800 gain calibration routine simply runs the tx power
configuration that takes care of calculating the temperature
compensation delta.
We don't need to synchronize the calls to rt2800_config_txpower
as they should all happen from mac80211's single threaded workqueue.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800.h | 106 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 133 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00link.c | 38 |
9 files changed, 296 insertions, 5 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 70b9abbdeb9e..3b3d851fe266 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -2104,6 +2104,59 @@ struct mac_iveiv_entry { | |||
2104 | #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) | 2104 | #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) |
2105 | 2105 | ||
2106 | /* | 2106 | /* |
2107 | * EEPROM temperature compensation boundaries 802.11BG | ||
2108 | * MINUS4: If the actual TSSI is below this boundary, tx power needs to be | ||
2109 | * reduced by (agc_step * -4) | ||
2110 | * MINUS3: If the actual TSSI is below this boundary, tx power needs to be | ||
2111 | * reduced by (agc_step * -3) | ||
2112 | */ | ||
2113 | #define EEPROM_TSSI_BOUND_BG1 0x0037 | ||
2114 | #define EEPROM_TSSI_BOUND_BG1_MINUS4 FIELD16(0x00ff) | ||
2115 | #define EEPROM_TSSI_BOUND_BG1_MINUS3 FIELD16(0xff00) | ||
2116 | |||
2117 | /* | ||
2118 | * EEPROM temperature compensation boundaries 802.11BG | ||
2119 | * MINUS2: If the actual TSSI is below this boundary, tx power needs to be | ||
2120 | * reduced by (agc_step * -2) | ||
2121 | * MINUS1: If the actual TSSI is below this boundary, tx power needs to be | ||
2122 | * reduced by (agc_step * -1) | ||
2123 | */ | ||
2124 | #define EEPROM_TSSI_BOUND_BG2 0x0038 | ||
2125 | #define EEPROM_TSSI_BOUND_BG2_MINUS2 FIELD16(0x00ff) | ||
2126 | #define EEPROM_TSSI_BOUND_BG2_MINUS1 FIELD16(0xff00) | ||
2127 | |||
2128 | /* | ||
2129 | * EEPROM temperature compensation boundaries 802.11BG | ||
2130 | * REF: Reference TSSI value, no tx power changes needed | ||
2131 | * PLUS1: If the actual TSSI is above this boundary, tx power needs to be | ||
2132 | * increased by (agc_step * 1) | ||
2133 | */ | ||
2134 | #define EEPROM_TSSI_BOUND_BG3 0x0039 | ||
2135 | #define EEPROM_TSSI_BOUND_BG3_REF FIELD16(0x00ff) | ||
2136 | #define EEPROM_TSSI_BOUND_BG3_PLUS1 FIELD16(0xff00) | ||
2137 | |||
2138 | /* | ||
2139 | * EEPROM temperature compensation boundaries 802.11BG | ||
2140 | * PLUS2: If the actual TSSI is above this boundary, tx power needs to be | ||
2141 | * increased by (agc_step * 2) | ||
2142 | * PLUS3: If the actual TSSI is above this boundary, tx power needs to be | ||
2143 | * increased by (agc_step * 3) | ||
2144 | */ | ||
2145 | #define EEPROM_TSSI_BOUND_BG4 0x003a | ||
2146 | #define EEPROM_TSSI_BOUND_BG4_PLUS2 FIELD16(0x00ff) | ||
2147 | #define EEPROM_TSSI_BOUND_BG4_PLUS3 FIELD16(0xff00) | ||
2148 | |||
2149 | /* | ||
2150 | * EEPROM temperature compensation boundaries 802.11BG | ||
2151 | * PLUS4: If the actual TSSI is above this boundary, tx power needs to be | ||
2152 | * increased by (agc_step * 4) | ||
2153 | * AGC_STEP: Temperature compensation step. | ||
2154 | */ | ||
2155 | #define EEPROM_TSSI_BOUND_BG5 0x003b | ||
2156 | #define EEPROM_TSSI_BOUND_BG5_PLUS4 FIELD16(0x00ff) | ||
2157 | #define EEPROM_TSSI_BOUND_BG5_AGC_STEP FIELD16(0xff00) | ||
2158 | |||
2159 | /* | ||
2107 | * EEPROM TXPOWER 802.11A | 2160 | * EEPROM TXPOWER 802.11A |
2108 | */ | 2161 | */ |
2109 | #define EEPROM_TXPOWER_A1 0x003c | 2162 | #define EEPROM_TXPOWER_A1 0x003c |
@@ -2113,6 +2166,59 @@ struct mac_iveiv_entry { | |||
2113 | #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) | 2166 | #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) |
2114 | 2167 | ||
2115 | /* | 2168 | /* |
2169 | * EEPROM temperature compensation boundaries 802.11A | ||
2170 | * MINUS4: If the actual TSSI is below this boundary, tx power needs to be | ||
2171 | * reduced by (agc_step * -4) | ||
2172 | * MINUS3: If the actual TSSI is below this boundary, tx power needs to be | ||
2173 | * reduced by (agc_step * -3) | ||
2174 | */ | ||
2175 | #define EEPROM_TSSI_BOUND_A1 0x006a | ||
2176 | #define EEPROM_TSSI_BOUND_A1_MINUS4 FIELD16(0x00ff) | ||
2177 | #define EEPROM_TSSI_BOUND_A1_MINUS3 FIELD16(0xff00) | ||
2178 | |||
2179 | /* | ||
2180 | * EEPROM temperature compensation boundaries 802.11A | ||
2181 | * MINUS2: If the actual TSSI is below this boundary, tx power needs to be | ||
2182 | * reduced by (agc_step * -2) | ||
2183 | * MINUS1: If the actual TSSI is below this boundary, tx power needs to be | ||
2184 | * reduced by (agc_step * -1) | ||
2185 | */ | ||
2186 | #define EEPROM_TSSI_BOUND_A2 0x006b | ||
2187 | #define EEPROM_TSSI_BOUND_A2_MINUS2 FIELD16(0x00ff) | ||
2188 | #define EEPROM_TSSI_BOUND_A2_MINUS1 FIELD16(0xff00) | ||
2189 | |||
2190 | /* | ||
2191 | * EEPROM temperature compensation boundaries 802.11A | ||
2192 | * REF: Reference TSSI value, no tx power changes needed | ||
2193 | * PLUS1: If the actual TSSI is above this boundary, tx power needs to be | ||
2194 | * increased by (agc_step * 1) | ||
2195 | */ | ||
2196 | #define EEPROM_TSSI_BOUND_A3 0x006c | ||
2197 | #define EEPROM_TSSI_BOUND_A3_REF FIELD16(0x00ff) | ||
2198 | #define EEPROM_TSSI_BOUND_A3_PLUS1 FIELD16(0xff00) | ||
2199 | |||
2200 | /* | ||
2201 | * EEPROM temperature compensation boundaries 802.11A | ||
2202 | * PLUS2: If the actual TSSI is above this boundary, tx power needs to be | ||
2203 | * increased by (agc_step * 2) | ||
2204 | * PLUS3: If the actual TSSI is above this boundary, tx power needs to be | ||
2205 | * increased by (agc_step * 3) | ||
2206 | */ | ||
2207 | #define EEPROM_TSSI_BOUND_A4 0x006d | ||
2208 | #define EEPROM_TSSI_BOUND_A4_PLUS2 FIELD16(0x00ff) | ||
2209 | #define EEPROM_TSSI_BOUND_A4_PLUS3 FIELD16(0xff00) | ||
2210 | |||
2211 | /* | ||
2212 | * EEPROM temperature compensation boundaries 802.11A | ||
2213 | * PLUS4: If the actual TSSI is above this boundary, tx power needs to be | ||
2214 | * increased by (agc_step * 4) | ||
2215 | * AGC_STEP: Temperature compensation step. | ||
2216 | */ | ||
2217 | #define EEPROM_TSSI_BOUND_A5 0x006e | ||
2218 | #define EEPROM_TSSI_BOUND_A5_PLUS4 FIELD16(0x00ff) | ||
2219 | #define EEPROM_TSSI_BOUND_A5_AGC_STEP FIELD16(0xff00) | ||
2220 | |||
2221 | /* | ||
2116 | * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode | 2222 | * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode |
2117 | */ | 2223 | */ |
2118 | #define EEPROM_TXPOWER_BYRATE 0x006f | 2224 | #define EEPROM_TXPOWER_BYRATE 0x006f |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 026513349370..59302faec395 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1813,6 +1813,116 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
1813 | rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); | 1813 | rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); |
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) | ||
1817 | { | ||
1818 | u8 tssi_bounds[9]; | ||
1819 | u8 current_tssi; | ||
1820 | u16 eeprom; | ||
1821 | u8 step; | ||
1822 | int i; | ||
1823 | |||
1824 | /* | ||
1825 | * Read TSSI boundaries for temperature compensation from | ||
1826 | * the EEPROM. | ||
1827 | * | ||
1828 | * Array idx 0 1 2 3 4 5 6 7 8 | ||
1829 | * Matching Delta value -4 -3 -2 -1 0 +1 +2 +3 +4 | ||
1830 | * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 | ||
1831 | */ | ||
1832 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | ||
1833 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); | ||
1834 | tssi_bounds[0] = rt2x00_get_field16(eeprom, | ||
1835 | EEPROM_TSSI_BOUND_BG1_MINUS4); | ||
1836 | tssi_bounds[1] = rt2x00_get_field16(eeprom, | ||
1837 | EEPROM_TSSI_BOUND_BG1_MINUS3); | ||
1838 | |||
1839 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); | ||
1840 | tssi_bounds[2] = rt2x00_get_field16(eeprom, | ||
1841 | EEPROM_TSSI_BOUND_BG2_MINUS2); | ||
1842 | tssi_bounds[3] = rt2x00_get_field16(eeprom, | ||
1843 | EEPROM_TSSI_BOUND_BG2_MINUS1); | ||
1844 | |||
1845 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); | ||
1846 | tssi_bounds[4] = rt2x00_get_field16(eeprom, | ||
1847 | EEPROM_TSSI_BOUND_BG3_REF); | ||
1848 | tssi_bounds[5] = rt2x00_get_field16(eeprom, | ||
1849 | EEPROM_TSSI_BOUND_BG3_PLUS1); | ||
1850 | |||
1851 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); | ||
1852 | tssi_bounds[6] = rt2x00_get_field16(eeprom, | ||
1853 | EEPROM_TSSI_BOUND_BG4_PLUS2); | ||
1854 | tssi_bounds[7] = rt2x00_get_field16(eeprom, | ||
1855 | EEPROM_TSSI_BOUND_BG4_PLUS3); | ||
1856 | |||
1857 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); | ||
1858 | tssi_bounds[8] = rt2x00_get_field16(eeprom, | ||
1859 | EEPROM_TSSI_BOUND_BG5_PLUS4); | ||
1860 | |||
1861 | step = rt2x00_get_field16(eeprom, | ||
1862 | EEPROM_TSSI_BOUND_BG5_AGC_STEP); | ||
1863 | } else { | ||
1864 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); | ||
1865 | tssi_bounds[0] = rt2x00_get_field16(eeprom, | ||
1866 | EEPROM_TSSI_BOUND_A1_MINUS4); | ||
1867 | tssi_bounds[1] = rt2x00_get_field16(eeprom, | ||
1868 | EEPROM_TSSI_BOUND_A1_MINUS3); | ||
1869 | |||
1870 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); | ||
1871 | tssi_bounds[2] = rt2x00_get_field16(eeprom, | ||
1872 | EEPROM_TSSI_BOUND_A2_MINUS2); | ||
1873 | tssi_bounds[3] = rt2x00_get_field16(eeprom, | ||
1874 | EEPROM_TSSI_BOUND_A2_MINUS1); | ||
1875 | |||
1876 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); | ||
1877 | tssi_bounds[4] = rt2x00_get_field16(eeprom, | ||
1878 | EEPROM_TSSI_BOUND_A3_REF); | ||
1879 | tssi_bounds[5] = rt2x00_get_field16(eeprom, | ||
1880 | EEPROM_TSSI_BOUND_A3_PLUS1); | ||
1881 | |||
1882 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); | ||
1883 | tssi_bounds[6] = rt2x00_get_field16(eeprom, | ||
1884 | EEPROM_TSSI_BOUND_A4_PLUS2); | ||
1885 | tssi_bounds[7] = rt2x00_get_field16(eeprom, | ||
1886 | EEPROM_TSSI_BOUND_A4_PLUS3); | ||
1887 | |||
1888 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); | ||
1889 | tssi_bounds[8] = rt2x00_get_field16(eeprom, | ||
1890 | EEPROM_TSSI_BOUND_A5_PLUS4); | ||
1891 | |||
1892 | step = rt2x00_get_field16(eeprom, | ||
1893 | EEPROM_TSSI_BOUND_A5_AGC_STEP); | ||
1894 | } | ||
1895 | |||
1896 | /* | ||
1897 | * Check if temperature compensation is supported. | ||
1898 | */ | ||
1899 | if (tssi_bounds[4] == 0xff) | ||
1900 | return 0; | ||
1901 | |||
1902 | /* | ||
1903 | * Read current TSSI (BBP 49). | ||
1904 | */ | ||
1905 | rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); | ||
1906 | |||
1907 | /* | ||
1908 | * Compare TSSI value (BBP49) with the compensation boundaries | ||
1909 | * from the EEPROM and increase or decrease tx power. | ||
1910 | */ | ||
1911 | for (i = 0; i <= 3; i++) { | ||
1912 | if (current_tssi > tssi_bounds[i]) | ||
1913 | break; | ||
1914 | } | ||
1915 | |||
1916 | if (i == 4) { | ||
1917 | for (i = 8; i >= 5; i--) { | ||
1918 | if (current_tssi < tssi_bounds[i]) | ||
1919 | break; | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | return (i - 4) * step; | ||
1924 | } | ||
1925 | |||
1816 | static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, | 1926 | static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, |
1817 | enum ieee80211_band band) | 1927 | enum ieee80211_band band) |
1818 | { | 1928 | { |
@@ -1904,7 +2014,8 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | |||
1904 | } | 2014 | } |
1905 | 2015 | ||
1906 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | 2016 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, |
1907 | struct ieee80211_conf *conf) | 2017 | enum ieee80211_band band, |
2018 | int power_level) | ||
1908 | { | 2019 | { |
1909 | u8 txpower; | 2020 | u8 txpower; |
1910 | u16 eeprom; | 2021 | u16 eeprom; |
@@ -1912,8 +2023,6 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
1912 | u32 reg; | 2023 | u32 reg; |
1913 | u8 r1; | 2024 | u8 r1; |
1914 | u32 offset; | 2025 | u32 offset; |
1915 | enum ieee80211_band band = conf->channel->band; | ||
1916 | int power_level = conf->power_level; | ||
1917 | int delta; | 2026 | int delta; |
1918 | 2027 | ||
1919 | /* | 2028 | /* |
@@ -1922,6 +2031,11 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
1922 | delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); | 2031 | delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); |
1923 | 2032 | ||
1924 | /* | 2033 | /* |
2034 | * calculate temperature compensation delta | ||
2035 | */ | ||
2036 | delta += rt2800_get_gain_calibration_delta(rt2x00dev); | ||
2037 | |||
2038 | /* | ||
1925 | * set to normal bbp tx power control mode: +/- 0dBm | 2039 | * set to normal bbp tx power control mode: +/- 0dBm |
1926 | */ | 2040 | */ |
1927 | rt2800_bbp_read(rt2x00dev, 1, &r1); | 2041 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
@@ -2041,6 +2155,13 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
2041 | } | 2155 | } |
2042 | } | 2156 | } |
2043 | 2157 | ||
2158 | void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) | ||
2159 | { | ||
2160 | rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, | ||
2161 | rt2x00dev->tx_power); | ||
2162 | } | ||
2163 | EXPORT_SYMBOL_GPL(rt2800_gain_calibration); | ||
2164 | |||
2044 | static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, | 2165 | static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, |
2045 | struct rt2x00lib_conf *libconf) | 2166 | struct rt2x00lib_conf *libconf) |
2046 | { | 2167 | { |
@@ -2094,10 +2215,12 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, | |||
2094 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { | 2215 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
2095 | rt2800_config_channel(rt2x00dev, libconf->conf, | 2216 | rt2800_config_channel(rt2x00dev, libconf->conf, |
2096 | &libconf->rf, &libconf->channel); | 2217 | &libconf->rf, &libconf->channel); |
2097 | rt2800_config_txpower(rt2x00dev, libconf->conf); | 2218 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, |
2219 | libconf->conf->power_level); | ||
2098 | } | 2220 | } |
2099 | if (flags & IEEE80211_CONF_CHANGE_POWER) | 2221 | if (flags & IEEE80211_CONF_CHANGE_POWER) |
2100 | rt2800_config_txpower(rt2x00dev, libconf->conf); | 2222 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, |
2223 | libconf->conf->power_level); | ||
2101 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 2224 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
2102 | rt2800_config_retry_limit(rt2x00dev, libconf); | 2225 | rt2800_config_retry_limit(rt2x00dev, libconf); |
2103 | if (flags & IEEE80211_CONF_CHANGE_PS) | 2226 | if (flags & IEEE80211_CONF_CHANGE_PS) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 0c92d86a36f4..f2d15941c71a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -181,6 +181,7 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); | |||
181 | void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); | 181 | void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual); |
182 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 182 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
183 | const u32 count); | 183 | const u32 count); |
184 | void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); | ||
184 | 185 | ||
185 | int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); | 186 | int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); |
186 | void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); | 187 | void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index d3055147ddfb..adc3534254df 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1053,6 +1053,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1053 | .link_stats = rt2800_link_stats, | 1053 | .link_stats = rt2800_link_stats, |
1054 | .reset_tuner = rt2800_reset_tuner, | 1054 | .reset_tuner = rt2800_reset_tuner, |
1055 | .link_tuner = rt2800_link_tuner, | 1055 | .link_tuner = rt2800_link_tuner, |
1056 | .gain_calibration = rt2800_gain_calibration, | ||
1056 | .start_queue = rt2800pci_start_queue, | 1057 | .start_queue = rt2800pci_start_queue, |
1057 | .kick_queue = rt2800pci_kick_queue, | 1058 | .kick_queue = rt2800pci_kick_queue, |
1058 | .stop_queue = rt2800pci_stop_queue, | 1059 | .stop_queue = rt2800pci_stop_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 1c99a4f449f5..8b3ab3f17eb3 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -629,6 +629,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
629 | .link_stats = rt2800_link_stats, | 629 | .link_stats = rt2800_link_stats, |
630 | .reset_tuner = rt2800_reset_tuner, | 630 | .reset_tuner = rt2800_reset_tuner, |
631 | .link_tuner = rt2800_link_tuner, | 631 | .link_tuner = rt2800_link_tuner, |
632 | .gain_calibration = rt2800_gain_calibration, | ||
632 | .watchdog = rt2800usb_watchdog, | 633 | .watchdog = rt2800usb_watchdog, |
633 | .start_queue = rt2800usb_start_queue, | 634 | .start_queue = rt2800usb_start_queue, |
634 | .kick_queue = rt2x00usb_kick_queue, | 635 | .kick_queue = rt2x00usb_kick_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 60b1cb05a70d..dd0f66ade6e8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -348,6 +348,11 @@ struct link { | |||
348 | * to bring the device/driver back into the desired state. | 348 | * to bring the device/driver back into the desired state. |
349 | */ | 349 | */ |
350 | struct delayed_work watchdog_work; | 350 | struct delayed_work watchdog_work; |
351 | |||
352 | /* | ||
353 | * Work structure for scheduling periodic AGC adjustments. | ||
354 | */ | ||
355 | struct delayed_work agc_work; | ||
351 | }; | 356 | }; |
352 | 357 | ||
353 | enum rt2x00_delayed_flags { | 358 | enum rt2x00_delayed_flags { |
@@ -556,6 +561,7 @@ struct rt2x00lib_ops { | |||
556 | struct link_qual *qual); | 561 | struct link_qual *qual); |
557 | void (*link_tuner) (struct rt2x00_dev *rt2x00dev, | 562 | void (*link_tuner) (struct rt2x00_dev *rt2x00dev, |
558 | struct link_qual *qual, const u32 count); | 563 | struct link_qual *qual, const u32 count); |
564 | void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); | ||
559 | 565 | ||
560 | /* | 566 | /* |
561 | * Data queue handlers. | 567 | * Data queue handlers. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 55c1d0332b2a..a98c43485239 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -71,6 +71,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
71 | */ | 71 | */ |
72 | rt2x00queue_start_queues(rt2x00dev); | 72 | rt2x00queue_start_queues(rt2x00dev); |
73 | rt2x00link_start_tuner(rt2x00dev); | 73 | rt2x00link_start_tuner(rt2x00dev); |
74 | rt2x00link_start_agc(rt2x00dev); | ||
74 | 75 | ||
75 | /* | 76 | /* |
76 | * Start watchdog monitoring. | 77 | * Start watchdog monitoring. |
@@ -93,6 +94,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
93 | /* | 94 | /* |
94 | * Stop all queues | 95 | * Stop all queues |
95 | */ | 96 | */ |
97 | rt2x00link_stop_agc(rt2x00dev); | ||
96 | rt2x00link_stop_tuner(rt2x00dev); | 98 | rt2x00link_stop_tuner(rt2x00dev); |
97 | rt2x00queue_stop_queues(rt2x00dev); | 99 | rt2x00queue_stop_queues(rt2x00dev); |
98 | rt2x00queue_flush_queues(rt2x00dev, true); | 100 | rt2x00queue_flush_queues(rt2x00dev, true); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 63c40d457244..88f2f9275528 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -32,6 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) | 33 | #define WATCHDOG_INTERVAL round_jiffies_relative(HZ) |
34 | #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) | 34 | #define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) |
35 | #define AGC_INTERVAL round_jiffies_relative(4 * HZ) | ||
35 | 36 | ||
36 | /* | 37 | /* |
37 | * rt2x00_rate: Per rate device information | 38 | * rt2x00_rate: Per rate device information |
@@ -271,6 +272,18 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev); | |||
271 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); | 272 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev); |
272 | 273 | ||
273 | /** | 274 | /** |
275 | * rt2x00link_start_agc - Start periodic gain calibration | ||
276 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
277 | */ | ||
278 | void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); | ||
279 | |||
280 | /** | ||
281 | * rt2x00link_stop_agc - Stop periodic gain calibration | ||
282 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
283 | */ | ||
284 | void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); | ||
285 | |||
286 | /** | ||
274 | * rt2x00link_register - Initialize link tuning & watchdog functionality | 287 | * rt2x00link_register - Initialize link tuning & watchdog functionality |
275 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 288 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
276 | * | 289 | * |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index fc8cee91b54e..128b3615c08c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -446,8 +446,46 @@ static void rt2x00link_watchdog(struct work_struct *work) | |||
446 | WATCHDOG_INTERVAL); | 446 | WATCHDOG_INTERVAL); |
447 | } | 447 | } |
448 | 448 | ||
449 | void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) | ||
450 | { | ||
451 | struct link *link = &rt2x00dev->link; | ||
452 | |||
453 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && | ||
454 | rt2x00dev->ops->lib->gain_calibration) | ||
455 | ieee80211_queue_delayed_work(rt2x00dev->hw, | ||
456 | &link->agc_work, | ||
457 | AGC_INTERVAL); | ||
458 | } | ||
459 | |||
460 | void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) | ||
461 | { | ||
462 | cancel_delayed_work_sync(&rt2x00dev->link.agc_work); | ||
463 | } | ||
464 | |||
465 | static void rt2x00link_agc(struct work_struct *work) | ||
466 | { | ||
467 | struct rt2x00_dev *rt2x00dev = | ||
468 | container_of(work, struct rt2x00_dev, link.agc_work.work); | ||
469 | struct link *link = &rt2x00dev->link; | ||
470 | |||
471 | /* | ||
472 | * When the radio is shutting down we should | ||
473 | * immediately cease the watchdog monitoring. | ||
474 | */ | ||
475 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
476 | return; | ||
477 | |||
478 | rt2x00dev->ops->lib->gain_calibration(rt2x00dev); | ||
479 | |||
480 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
481 | ieee80211_queue_delayed_work(rt2x00dev->hw, | ||
482 | &link->agc_work, | ||
483 | AGC_INTERVAL); | ||
484 | } | ||
485 | |||
449 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 486 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
450 | { | 487 | { |
488 | INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); | ||
451 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); | 489 | INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); |
452 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); | 490 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); |
453 | } | 491 | } |