diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 329 |
1 files changed, 252 insertions, 77 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 3abbe7513ab5..5f04cf38a5bc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -59,8 +59,8 @@ | |||
59 | #include "base.h" | 59 | #include "base.h" |
60 | #include "reg.h" | 60 | #include "reg.h" |
61 | #include "debug.h" | 61 | #include "debug.h" |
62 | #include "ani.h" | ||
62 | 63 | ||
63 | static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | ||
64 | static int modparam_nohwcrypt; | 64 | static int modparam_nohwcrypt; |
65 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 65 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
66 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 66 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -199,7 +199,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | |||
199 | static int ath5k_pci_suspend(struct device *dev); | 199 | static int ath5k_pci_suspend(struct device *dev); |
200 | static int ath5k_pci_resume(struct device *dev); | 200 | static int ath5k_pci_resume(struct device *dev); |
201 | 201 | ||
202 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | 202 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); |
203 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | 203 | #define ATH5K_PM_OPS (&ath5k_pm_ops) |
204 | #else | 204 | #else |
205 | #define ATH5K_PM_OPS NULL | 205 | #define ATH5K_PM_OPS NULL |
@@ -231,7 +231,7 @@ static void ath5k_remove_interface(struct ieee80211_hw *hw, | |||
231 | struct ieee80211_vif *vif); | 231 | struct ieee80211_vif *vif); |
232 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 232 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
233 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 233 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
234 | int mc_count, struct dev_addr_list *mc_list); | 234 | struct netdev_hw_addr_list *mc_list); |
235 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 235 | static void ath5k_configure_filter(struct ieee80211_hw *hw, |
236 | unsigned int changed_flags, | 236 | unsigned int changed_flags, |
237 | unsigned int *new_flags, | 237 | unsigned int *new_flags, |
@@ -242,6 +242,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw, | |||
242 | struct ieee80211_key_conf *key); | 242 | struct ieee80211_key_conf *key); |
243 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 243 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
244 | struct ieee80211_low_level_stats *stats); | 244 | struct ieee80211_low_level_stats *stats); |
245 | static int ath5k_get_survey(struct ieee80211_hw *hw, | ||
246 | int idx, struct survey_info *survey); | ||
245 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 247 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
246 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | 248 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); |
247 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 249 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
@@ -267,6 +269,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
267 | .configure_filter = ath5k_configure_filter, | 269 | .configure_filter = ath5k_configure_filter, |
268 | .set_key = ath5k_set_key, | 270 | .set_key = ath5k_set_key, |
269 | .get_stats = ath5k_get_stats, | 271 | .get_stats = ath5k_get_stats, |
272 | .get_survey = ath5k_get_survey, | ||
270 | .conf_tx = NULL, | 273 | .conf_tx = NULL, |
271 | .get_tsf = ath5k_get_tsf, | 274 | .get_tsf = ath5k_get_tsf, |
272 | .set_tsf = ath5k_set_tsf, | 275 | .set_tsf = ath5k_set_tsf, |
@@ -308,7 +311,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
308 | struct ath5k_buf *bf); | 311 | struct ath5k_buf *bf); |
309 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 312 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
310 | struct ath5k_buf *bf, | 313 | struct ath5k_buf *bf, |
311 | struct ath5k_txq *txq); | 314 | struct ath5k_txq *txq, int padsize); |
312 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 315 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, |
313 | struct ath5k_buf *bf) | 316 | struct ath5k_buf *bf) |
314 | { | 317 | { |
@@ -365,6 +368,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc); | |||
365 | static void ath5k_beacon_config(struct ath5k_softc *sc); | 368 | static void ath5k_beacon_config(struct ath5k_softc *sc); |
366 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 369 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
367 | static void ath5k_tasklet_beacon(unsigned long data); | 370 | static void ath5k_tasklet_beacon(unsigned long data); |
371 | static void ath5k_tasklet_ani(unsigned long data); | ||
368 | 372 | ||
369 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 373 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
370 | { | 374 | { |
@@ -544,8 +548,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
544 | SET_IEEE80211_DEV(hw, &pdev->dev); | 548 | SET_IEEE80211_DEV(hw, &pdev->dev); |
545 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 549 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
546 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 550 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
547 | IEEE80211_HW_SIGNAL_DBM | | 551 | IEEE80211_HW_SIGNAL_DBM; |
548 | IEEE80211_HW_NOISE_DBM; | ||
549 | 552 | ||
550 | hw->wiphy->interface_modes = | 553 | hw->wiphy->interface_modes = |
551 | BIT(NL80211_IFTYPE_AP) | | 554 | BIT(NL80211_IFTYPE_AP) | |
@@ -830,6 +833,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
830 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 833 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
831 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | 834 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
832 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 835 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
836 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
833 | 837 | ||
834 | ret = ath5k_eeprom_read_mac(ah, mac); | 838 | ret = ath5k_eeprom_read_mac(ah, mac); |
835 | if (ret) { | 839 | if (ret) { |
@@ -1138,8 +1142,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1138 | struct ath5k_hw *ah = sc->ah; | 1142 | struct ath5k_hw *ah = sc->ah; |
1139 | u32 rfilt; | 1143 | u32 rfilt; |
1140 | 1144 | ||
1141 | ah->ah_op_mode = sc->opmode; | ||
1142 | |||
1143 | /* configure rx filter */ | 1145 | /* configure rx filter */ |
1144 | rfilt = sc->filter_flags; | 1146 | rfilt = sc->filter_flags; |
1145 | ath5k_hw_set_rx_filter(ah, rfilt); | 1147 | ath5k_hw_set_rx_filter(ah, rfilt); |
@@ -1148,8 +1150,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1148 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 1150 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); |
1149 | 1151 | ||
1150 | /* configure operational mode */ | 1152 | /* configure operational mode */ |
1151 | ath5k_hw_set_opmode(ah); | 1153 | ath5k_hw_set_opmode(ah, sc->opmode); |
1152 | 1154 | ||
1155 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); | ||
1153 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 1156 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1154 | } | 1157 | } |
1155 | 1158 | ||
@@ -1272,7 +1275,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1272 | 1275 | ||
1273 | static int | 1276 | static int |
1274 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1277 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1275 | struct ath5k_txq *txq) | 1278 | struct ath5k_txq *txq, int padsize) |
1276 | { | 1279 | { |
1277 | struct ath5k_hw *ah = sc->ah; | 1280 | struct ath5k_hw *ah = sc->ah; |
1278 | struct ath5k_desc *ds = bf->desc; | 1281 | struct ath5k_desc *ds = bf->desc; |
@@ -1324,7 +1327,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1324 | sc->vif, pktlen, info)); | 1327 | sc->vif, pktlen, info)); |
1325 | } | 1328 | } |
1326 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1329 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1327 | ieee80211_get_hdrlen_from_skb(skb), | 1330 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
1328 | get_hw_packet_type(skb), | 1331 | get_hw_packet_type(skb), |
1329 | (sc->power_level * 2), | 1332 | (sc->power_level * 2), |
1330 | hw_rate, | 1333 | hw_rate, |
@@ -1636,7 +1639,6 @@ ath5k_txq_cleanup(struct ath5k_softc *sc) | |||
1636 | sc->txqs[i].link); | 1639 | sc->txqs[i].link); |
1637 | } | 1640 | } |
1638 | } | 1641 | } |
1639 | ieee80211_wake_queues(sc->hw); /* XXX move to callers */ | ||
1640 | 1642 | ||
1641 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | 1643 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) |
1642 | if (sc->txqs[i].setup) | 1644 | if (sc->txqs[i].setup) |
@@ -1807,6 +1809,86 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1807 | } | 1809 | } |
1808 | 1810 | ||
1809 | static void | 1811 | static void |
1812 | ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | ||
1813 | { | ||
1814 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1815 | struct ath5k_hw *ah = sc->ah; | ||
1816 | struct ath_common *common = ath5k_hw_common(ah); | ||
1817 | |||
1818 | /* only beacons from our BSSID */ | ||
1819 | if (!ieee80211_is_beacon(mgmt->frame_control) || | ||
1820 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | ||
1821 | return; | ||
1822 | |||
1823 | ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, | ||
1824 | rssi); | ||
1825 | |||
1826 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | ||
1827 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | ||
1828 | } | ||
1829 | |||
1830 | /* | ||
1831 | * Compute padding position. skb must contains an IEEE 802.11 frame | ||
1832 | */ | ||
1833 | static int ath5k_common_padpos(struct sk_buff *skb) | ||
1834 | { | ||
1835 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | ||
1836 | __le16 frame_control = hdr->frame_control; | ||
1837 | int padpos = 24; | ||
1838 | |||
1839 | if (ieee80211_has_a4(frame_control)) { | ||
1840 | padpos += ETH_ALEN; | ||
1841 | } | ||
1842 | if (ieee80211_is_data_qos(frame_control)) { | ||
1843 | padpos += IEEE80211_QOS_CTL_LEN; | ||
1844 | } | ||
1845 | |||
1846 | return padpos; | ||
1847 | } | ||
1848 | |||
1849 | /* | ||
1850 | * This function expects a 802.11 frame and returns the number of | ||
1851 | * bytes added, or -1 if we don't have enought header room. | ||
1852 | */ | ||
1853 | |||
1854 | static int ath5k_add_padding(struct sk_buff *skb) | ||
1855 | { | ||
1856 | int padpos = ath5k_common_padpos(skb); | ||
1857 | int padsize = padpos & 3; | ||
1858 | |||
1859 | if (padsize && skb->len>padpos) { | ||
1860 | |||
1861 | if (skb_headroom(skb) < padsize) | ||
1862 | return -1; | ||
1863 | |||
1864 | skb_push(skb, padsize); | ||
1865 | memmove(skb->data, skb->data+padsize, padpos); | ||
1866 | return padsize; | ||
1867 | } | ||
1868 | |||
1869 | return 0; | ||
1870 | } | ||
1871 | |||
1872 | /* | ||
1873 | * This function expects a 802.11 frame and returns the number of | ||
1874 | * bytes removed | ||
1875 | */ | ||
1876 | |||
1877 | static int ath5k_remove_padding(struct sk_buff *skb) | ||
1878 | { | ||
1879 | int padpos = ath5k_common_padpos(skb); | ||
1880 | int padsize = padpos & 3; | ||
1881 | |||
1882 | if (padsize && skb->len>=padpos+padsize) { | ||
1883 | memmove(skb->data + padsize, skb->data, padpos); | ||
1884 | skb_pull(skb, padsize); | ||
1885 | return padsize; | ||
1886 | } | ||
1887 | |||
1888 | return 0; | ||
1889 | } | ||
1890 | |||
1891 | static void | ||
1810 | ath5k_tasklet_rx(unsigned long data) | 1892 | ath5k_tasklet_rx(unsigned long data) |
1811 | { | 1893 | { |
1812 | struct ieee80211_rx_status *rxs; | 1894 | struct ieee80211_rx_status *rxs; |
@@ -1819,8 +1901,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1819 | struct ath5k_buf *bf; | 1901 | struct ath5k_buf *bf; |
1820 | struct ath5k_desc *ds; | 1902 | struct ath5k_desc *ds; |
1821 | int ret; | 1903 | int ret; |
1822 | int hdrlen; | ||
1823 | int padsize; | ||
1824 | int rx_flag; | 1904 | int rx_flag; |
1825 | 1905 | ||
1826 | spin_lock(&sc->rxbuflock); | 1906 | spin_lock(&sc->rxbuflock); |
@@ -1845,18 +1925,24 @@ ath5k_tasklet_rx(unsigned long data) | |||
1845 | break; | 1925 | break; |
1846 | else if (unlikely(ret)) { | 1926 | else if (unlikely(ret)) { |
1847 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 1927 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1928 | sc->stats.rxerr_proc++; | ||
1848 | spin_unlock(&sc->rxbuflock); | 1929 | spin_unlock(&sc->rxbuflock); |
1849 | return; | 1930 | return; |
1850 | } | 1931 | } |
1851 | 1932 | ||
1852 | if (unlikely(rs.rs_more)) { | 1933 | sc->stats.rx_all_count++; |
1853 | ATH5K_WARN(sc, "unsupported jumbo\n"); | ||
1854 | goto next; | ||
1855 | } | ||
1856 | 1934 | ||
1857 | if (unlikely(rs.rs_status)) { | 1935 | if (unlikely(rs.rs_status)) { |
1858 | if (rs.rs_status & AR5K_RXERR_PHY) | 1936 | if (rs.rs_status & AR5K_RXERR_CRC) |
1937 | sc->stats.rxerr_crc++; | ||
1938 | if (rs.rs_status & AR5K_RXERR_FIFO) | ||
1939 | sc->stats.rxerr_fifo++; | ||
1940 | if (rs.rs_status & AR5K_RXERR_PHY) { | ||
1941 | sc->stats.rxerr_phy++; | ||
1942 | if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) | ||
1943 | sc->stats.rxerr_phy_code[rs.rs_phyerr]++; | ||
1859 | goto next; | 1944 | goto next; |
1945 | } | ||
1860 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | 1946 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
1861 | /* | 1947 | /* |
1862 | * Decrypt error. If the error occurred | 1948 | * Decrypt error. If the error occurred |
@@ -1868,12 +1954,14 @@ ath5k_tasklet_rx(unsigned long data) | |||
1868 | * | 1954 | * |
1869 | * XXX do key cache faulting | 1955 | * XXX do key cache faulting |
1870 | */ | 1956 | */ |
1957 | sc->stats.rxerr_decrypt++; | ||
1871 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | 1958 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && |
1872 | !(rs.rs_status & AR5K_RXERR_CRC)) | 1959 | !(rs.rs_status & AR5K_RXERR_CRC)) |
1873 | goto accept; | 1960 | goto accept; |
1874 | } | 1961 | } |
1875 | if (rs.rs_status & AR5K_RXERR_MIC) { | 1962 | if (rs.rs_status & AR5K_RXERR_MIC) { |
1876 | rx_flag |= RX_FLAG_MMIC_ERROR; | 1963 | rx_flag |= RX_FLAG_MMIC_ERROR; |
1964 | sc->stats.rxerr_mic++; | ||
1877 | goto accept; | 1965 | goto accept; |
1878 | } | 1966 | } |
1879 | 1967 | ||
@@ -1883,6 +1971,12 @@ ath5k_tasklet_rx(unsigned long data) | |||
1883 | sc->opmode != NL80211_IFTYPE_MONITOR) | 1971 | sc->opmode != NL80211_IFTYPE_MONITOR) |
1884 | goto next; | 1972 | goto next; |
1885 | } | 1973 | } |
1974 | |||
1975 | if (unlikely(rs.rs_more)) { | ||
1976 | sc->stats.rxerr_jumbo++; | ||
1977 | goto next; | ||
1978 | |||
1979 | } | ||
1886 | accept: | 1980 | accept: |
1887 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | 1981 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); |
1888 | 1982 | ||
@@ -1905,12 +1999,8 @@ accept: | |||
1905 | * bytes and we can optimize this a bit. In addition, we must | 1999 | * bytes and we can optimize this a bit. In addition, we must |
1906 | * not try to remove padding from short control frames that do | 2000 | * not try to remove padding from short control frames that do |
1907 | * not have payload. */ | 2001 | * not have payload. */ |
1908 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2002 | ath5k_remove_padding(skb); |
1909 | padsize = ath5k_pad_size(hdrlen); | 2003 | |
1910 | if (padsize) { | ||
1911 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1912 | skb_pull(skb, padsize); | ||
1913 | } | ||
1914 | rxs = IEEE80211_SKB_RXCB(skb); | 2004 | rxs = IEEE80211_SKB_RXCB(skb); |
1915 | 2005 | ||
1916 | /* | 2006 | /* |
@@ -1939,10 +2029,15 @@ accept: | |||
1939 | rxs->freq = sc->curchan->center_freq; | 2029 | rxs->freq = sc->curchan->center_freq; |
1940 | rxs->band = sc->curband->band; | 2030 | rxs->band = sc->curband->band; |
1941 | 2031 | ||
1942 | rxs->noise = sc->ah->ah_noise_floor; | 2032 | rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi; |
1943 | rxs->signal = rxs->noise + rs.rs_rssi; | ||
1944 | 2033 | ||
1945 | rxs->antenna = rs.rs_antenna; | 2034 | rxs->antenna = rs.rs_antenna; |
2035 | |||
2036 | if (rs.rs_antenna > 0 && rs.rs_antenna < 5) | ||
2037 | sc->stats.antenna_rx[rs.rs_antenna]++; | ||
2038 | else | ||
2039 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
2040 | |||
1946 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 2041 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1947 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 2042 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
1948 | 2043 | ||
@@ -1952,6 +2047,8 @@ accept: | |||
1952 | 2047 | ||
1953 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 2048 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
1954 | 2049 | ||
2050 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | ||
2051 | |||
1955 | /* check beacons in IBSS mode */ | 2052 | /* check beacons in IBSS mode */ |
1956 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | 2053 | if (sc->opmode == NL80211_IFTYPE_ADHOC) |
1957 | ath5k_check_ibss_tsf(sc, skb, rxs); | 2054 | ath5k_check_ibss_tsf(sc, skb, rxs); |
@@ -1988,6 +2085,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1988 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 2085 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
1989 | ds = bf->desc; | 2086 | ds = bf->desc; |
1990 | 2087 | ||
2088 | /* | ||
2089 | * It's possible that the hardware can say the buffer is | ||
2090 | * completed when it hasn't yet loaded the ds_link from | ||
2091 | * host memory and moved on. If there are more TX | ||
2092 | * descriptors in the queue, wait for TXDP to change | ||
2093 | * before processing this one. | ||
2094 | */ | ||
2095 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr && | ||
2096 | !list_is_last(&bf->list, &txq->q)) | ||
2097 | break; | ||
2098 | |||
1991 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); | 2099 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); |
1992 | if (unlikely(ret == -EINPROGRESS)) | 2100 | if (unlikely(ret == -EINPROGRESS)) |
1993 | break; | 2101 | break; |
@@ -1997,6 +2105,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1997 | break; | 2105 | break; |
1998 | } | 2106 | } |
1999 | 2107 | ||
2108 | sc->stats.tx_all_count++; | ||
2000 | skb = bf->skb; | 2109 | skb = bf->skb; |
2001 | info = IEEE80211_SKB_CB(skb); | 2110 | info = IEEE80211_SKB_CB(skb); |
2002 | bf->skb = NULL; | 2111 | bf->skb = NULL; |
@@ -2022,14 +2131,31 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2022 | info->status.rates[ts.ts_final_idx].count++; | 2131 | info->status.rates[ts.ts_final_idx].count++; |
2023 | 2132 | ||
2024 | if (unlikely(ts.ts_status)) { | 2133 | if (unlikely(ts.ts_status)) { |
2025 | sc->ll_stats.dot11ACKFailureCount++; | 2134 | sc->stats.ack_fail++; |
2026 | if (ts.ts_status & AR5K_TXERR_FILT) | 2135 | if (ts.ts_status & AR5K_TXERR_FILT) { |
2027 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2136 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2137 | sc->stats.txerr_filt++; | ||
2138 | } | ||
2139 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2140 | sc->stats.txerr_retry++; | ||
2141 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2142 | sc->stats.txerr_fifo++; | ||
2028 | } else { | 2143 | } else { |
2029 | info->flags |= IEEE80211_TX_STAT_ACK; | 2144 | info->flags |= IEEE80211_TX_STAT_ACK; |
2030 | info->status.ack_signal = ts.ts_rssi; | 2145 | info->status.ack_signal = ts.ts_rssi; |
2031 | } | 2146 | } |
2032 | 2147 | ||
2148 | /* | ||
2149 | * Remove MAC header padding before giving the frame | ||
2150 | * back to mac80211. | ||
2151 | */ | ||
2152 | ath5k_remove_padding(skb); | ||
2153 | |||
2154 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | ||
2155 | sc->stats.antenna_tx[ts.ts_antenna]++; | ||
2156 | else | ||
2157 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
2158 | |||
2033 | ieee80211_tx_status(sc->hw, skb); | 2159 | ieee80211_tx_status(sc->hw, skb); |
2034 | 2160 | ||
2035 | spin_lock(&sc->txbuflock); | 2161 | spin_lock(&sc->txbuflock); |
@@ -2073,6 +2199,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2073 | int ret = 0; | 2199 | int ret = 0; |
2074 | u8 antenna; | 2200 | u8 antenna; |
2075 | u32 flags; | 2201 | u32 flags; |
2202 | const int padsize = 0; | ||
2076 | 2203 | ||
2077 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 2204 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
2078 | PCI_DMA_TODEVICE); | 2205 | PCI_DMA_TODEVICE); |
@@ -2120,7 +2247,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2120 | * from tx power (value is in dB units already) */ | 2247 | * from tx power (value is in dB units already) */ |
2121 | ds->ds_data = bf->skbaddr; | 2248 | ds->ds_data = bf->skbaddr; |
2122 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, | 2249 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, |
2123 | ieee80211_get_hdrlen_from_skb(skb), | 2250 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
2124 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), | 2251 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), |
2125 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 2252 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, |
2126 | 1, AR5K_TXKEYIX_INVALID, | 2253 | 1, AR5K_TXKEYIX_INVALID, |
@@ -2407,9 +2534,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2407 | */ | 2534 | */ |
2408 | ath5k_stop_locked(sc); | 2535 | ath5k_stop_locked(sc); |
2409 | 2536 | ||
2410 | /* Set PHY calibration interval */ | ||
2411 | ah->ah_cal_intval = ath5k_calinterval; | ||
2412 | |||
2413 | /* | 2537 | /* |
2414 | * The basic interface to setting the hardware in a good | 2538 | * The basic interface to setting the hardware in a good |
2415 | * state is ``reset''. On return the hardware is known to | 2539 | * state is ``reset''. On return the hardware is known to |
@@ -2421,7 +2545,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2421 | sc->curband = &sc->sbands[sc->curchan->band]; | 2545 | sc->curband = &sc->sbands[sc->curchan->band]; |
2422 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2546 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2423 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2547 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2424 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; | 2548 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2549 | |||
2425 | ret = ath5k_reset(sc, NULL); | 2550 | ret = ath5k_reset(sc, NULL); |
2426 | if (ret) | 2551 | if (ret) |
2427 | goto done; | 2552 | goto done; |
@@ -2435,8 +2560,7 @@ ath5k_init(struct ath5k_softc *sc) | |||
2435 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | 2560 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) |
2436 | ath5k_hw_reset_key(ah, i); | 2561 | ath5k_hw_reset_key(ah, i); |
2437 | 2562 | ||
2438 | /* Set ack to be sent at low bit-rates */ | 2563 | ath5k_hw_set_ack_bitrate_high(ah, true); |
2439 | ath5k_hw_set_ack_bitrate_high(ah, false); | ||
2440 | ret = 0; | 2564 | ret = 0; |
2441 | done: | 2565 | done: |
2442 | mmiowb(); | 2566 | mmiowb(); |
@@ -2533,12 +2657,33 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2533 | tasklet_kill(&sc->restq); | 2657 | tasklet_kill(&sc->restq); |
2534 | tasklet_kill(&sc->calib); | 2658 | tasklet_kill(&sc->calib); |
2535 | tasklet_kill(&sc->beacontq); | 2659 | tasklet_kill(&sc->beacontq); |
2660 | tasklet_kill(&sc->ani_tasklet); | ||
2536 | 2661 | ||
2537 | ath5k_rfkill_hw_stop(sc->ah); | 2662 | ath5k_rfkill_hw_stop(sc->ah); |
2538 | 2663 | ||
2539 | return ret; | 2664 | return ret; |
2540 | } | 2665 | } |
2541 | 2666 | ||
2667 | static void | ||
2668 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | ||
2669 | { | ||
2670 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && | ||
2671 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { | ||
2672 | /* run ANI only when full calibration is not active */ | ||
2673 | ah->ah_cal_next_ani = jiffies + | ||
2674 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | ||
2675 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
2676 | |||
2677 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | ||
2678 | ah->ah_cal_next_full = jiffies + | ||
2679 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2680 | tasklet_schedule(&ah->ah_sc->calib); | ||
2681 | } | ||
2682 | /* we could use SWI to generate enough interrupts to meet our | ||
2683 | * calibration interval requirements, if necessary: | ||
2684 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | ||
2685 | } | ||
2686 | |||
2542 | static irqreturn_t | 2687 | static irqreturn_t |
2543 | ath5k_intr(int irq, void *dev_id) | 2688 | ath5k_intr(int irq, void *dev_id) |
2544 | { | 2689 | { |
@@ -2562,7 +2707,20 @@ ath5k_intr(int irq, void *dev_id) | |||
2562 | */ | 2707 | */ |
2563 | tasklet_schedule(&sc->restq); | 2708 | tasklet_schedule(&sc->restq); |
2564 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2709 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2565 | tasklet_schedule(&sc->restq); | 2710 | /* |
2711 | * Receive buffers are full. Either the bus is busy or | ||
2712 | * the CPU is not fast enough to process all received | ||
2713 | * frames. | ||
2714 | * Older chipsets need a reset to come out of this | ||
2715 | * condition, but we treat it as RX for newer chips. | ||
2716 | * We don't know exactly which versions need a reset - | ||
2717 | * this guess is copied from the HAL. | ||
2718 | */ | ||
2719 | sc->stats.rxorn_intr++; | ||
2720 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) | ||
2721 | tasklet_schedule(&sc->restq); | ||
2722 | else | ||
2723 | tasklet_schedule(&sc->rxtq); | ||
2566 | } else { | 2724 | } else { |
2567 | if (status & AR5K_INT_SWBA) { | 2725 | if (status & AR5K_INT_SWBA) { |
2568 | tasklet_hi_schedule(&sc->beacontq); | 2726 | tasklet_hi_schedule(&sc->beacontq); |
@@ -2587,15 +2745,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2587 | if (status & AR5K_INT_BMISS) { | 2745 | if (status & AR5K_INT_BMISS) { |
2588 | /* TODO */ | 2746 | /* TODO */ |
2589 | } | 2747 | } |
2590 | if (status & AR5K_INT_SWI) { | ||
2591 | tasklet_schedule(&sc->calib); | ||
2592 | } | ||
2593 | if (status & AR5K_INT_MIB) { | 2748 | if (status & AR5K_INT_MIB) { |
2594 | /* | 2749 | sc->stats.mib_intr++; |
2595 | * These stats are also used for ANI i think | 2750 | ath5k_hw_update_mib_counters(ah); |
2596 | * so how about updating them more often ? | 2751 | ath5k_ani_mib_intr(ah); |
2597 | */ | ||
2598 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
2599 | } | 2752 | } |
2600 | if (status & AR5K_INT_GPIO) | 2753 | if (status & AR5K_INT_GPIO) |
2601 | tasklet_schedule(&sc->rf_kill.toggleq); | 2754 | tasklet_schedule(&sc->rf_kill.toggleq); |
@@ -2606,7 +2759,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2606 | if (unlikely(!counter)) | 2759 | if (unlikely(!counter)) |
2607 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2760 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2608 | 2761 | ||
2609 | ath5k_hw_calibration_poll(ah); | 2762 | ath5k_intr_calibration_poll(ah); |
2610 | 2763 | ||
2611 | return IRQ_HANDLED; | 2764 | return IRQ_HANDLED; |
2612 | } | 2765 | } |
@@ -2630,8 +2783,7 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2630 | struct ath5k_hw *ah = sc->ah; | 2783 | struct ath5k_hw *ah = sc->ah; |
2631 | 2784 | ||
2632 | /* Only full calibration for now */ | 2785 | /* Only full calibration for now */ |
2633 | if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) | 2786 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; |
2634 | return; | ||
2635 | 2787 | ||
2636 | /* Stop queues so that calibration | 2788 | /* Stop queues so that calibration |
2637 | * doesn't interfere with tx */ | 2789 | * doesn't interfere with tx */ |
@@ -2647,18 +2799,29 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2647 | * to load new gain values. | 2799 | * to load new gain values. |
2648 | */ | 2800 | */ |
2649 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); | 2801 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); |
2650 | ath5k_reset_wake(sc); | 2802 | ath5k_reset(sc, sc->curchan); |
2651 | } | 2803 | } |
2652 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) | 2804 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) |
2653 | ATH5K_ERR(sc, "calibration of channel %u failed\n", | 2805 | ATH5K_ERR(sc, "calibration of channel %u failed\n", |
2654 | ieee80211_frequency_to_channel( | 2806 | ieee80211_frequency_to_channel( |
2655 | sc->curchan->center_freq)); | 2807 | sc->curchan->center_freq)); |
2656 | 2808 | ||
2657 | ah->ah_swi_mask = 0; | ||
2658 | |||
2659 | /* Wake queues */ | 2809 | /* Wake queues */ |
2660 | ieee80211_wake_queues(sc->hw); | 2810 | ieee80211_wake_queues(sc->hw); |
2661 | 2811 | ||
2812 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | ||
2813 | } | ||
2814 | |||
2815 | |||
2816 | static void | ||
2817 | ath5k_tasklet_ani(unsigned long data) | ||
2818 | { | ||
2819 | struct ath5k_softc *sc = (void *)data; | ||
2820 | struct ath5k_hw *ah = sc->ah; | ||
2821 | |||
2822 | ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; | ||
2823 | ath5k_ani_calibration(ah); | ||
2824 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI; | ||
2662 | } | 2825 | } |
2663 | 2826 | ||
2664 | 2827 | ||
@@ -2680,7 +2843,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2680 | struct ath5k_softc *sc = hw->priv; | 2843 | struct ath5k_softc *sc = hw->priv; |
2681 | struct ath5k_buf *bf; | 2844 | struct ath5k_buf *bf; |
2682 | unsigned long flags; | 2845 | unsigned long flags; |
2683 | int hdrlen; | ||
2684 | int padsize; | 2846 | int padsize; |
2685 | 2847 | ||
2686 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2848 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
@@ -2692,17 +2854,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2692 | * the hardware expects the header padded to 4 byte boundaries | 2854 | * the hardware expects the header padded to 4 byte boundaries |
2693 | * if this is not the case we add the padding after the header | 2855 | * if this is not the case we add the padding after the header |
2694 | */ | 2856 | */ |
2695 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2857 | padsize = ath5k_add_padding(skb); |
2696 | padsize = ath5k_pad_size(hdrlen); | 2858 | if (padsize < 0) { |
2697 | if (padsize) { | 2859 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" |
2698 | 2860 | " headroom to pad"); | |
2699 | if (skb_headroom(skb) < padsize) { | 2861 | goto drop_packet; |
2700 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | ||
2701 | " headroom to pad %d\n", hdrlen, padsize); | ||
2702 | goto drop_packet; | ||
2703 | } | ||
2704 | skb_push(skb, padsize); | ||
2705 | memmove(skb->data, skb->data+padsize, hdrlen); | ||
2706 | } | 2862 | } |
2707 | 2863 | ||
2708 | spin_lock_irqsave(&sc->txbuflock, flags); | 2864 | spin_lock_irqsave(&sc->txbuflock, flags); |
@@ -2721,7 +2877,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2721 | 2877 | ||
2722 | bf->skb = skb; | 2878 | bf->skb = skb; |
2723 | 2879 | ||
2724 | if (ath5k_txbuf_setup(sc, bf, txq)) { | 2880 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { |
2725 | bf->skb = NULL; | 2881 | bf->skb = NULL; |
2726 | spin_lock_irqsave(&sc->txbuflock, flags); | 2882 | spin_lock_irqsave(&sc->txbuflock, flags); |
2727 | list_add_tail(&bf->list, &sc->txbuf); | 2883 | list_add_tail(&bf->list, &sc->txbuf); |
@@ -2768,6 +2924,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
2768 | goto err; | 2924 | goto err; |
2769 | } | 2925 | } |
2770 | 2926 | ||
2927 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | ||
2928 | |||
2771 | /* | 2929 | /* |
2772 | * Change channels and update the h/w rate map if we're switching; | 2930 | * Change channels and update the h/w rate map if we're switching; |
2773 | * e.g. 11a to 11b/g. | 2931 | * e.g. 11a to 11b/g. |
@@ -2836,6 +2994,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2836 | goto end; | 2994 | goto end; |
2837 | } | 2995 | } |
2838 | 2996 | ||
2997 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | ||
2998 | |||
2839 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2999 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2840 | ath5k_mode_setup(sc); | 3000 | ath5k_mode_setup(sc); |
2841 | 3001 | ||
@@ -2906,7 +3066,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2906 | * then we must allow the user to set how many tx antennas we | 3066 | * then we must allow the user to set how many tx antennas we |
2907 | * have available | 3067 | * have available |
2908 | */ | 3068 | */ |
2909 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | 3069 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
2910 | 3070 | ||
2911 | unlock: | 3071 | unlock: |
2912 | mutex_unlock(&sc->lock); | 3072 | mutex_unlock(&sc->lock); |
@@ -2914,22 +3074,20 @@ unlock: | |||
2914 | } | 3074 | } |
2915 | 3075 | ||
2916 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 3076 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
2917 | int mc_count, struct dev_addr_list *mclist) | 3077 | struct netdev_hw_addr_list *mc_list) |
2918 | { | 3078 | { |
2919 | u32 mfilt[2], val; | 3079 | u32 mfilt[2], val; |
2920 | int i; | ||
2921 | u8 pos; | 3080 | u8 pos; |
3081 | struct netdev_hw_addr *ha; | ||
2922 | 3082 | ||
2923 | mfilt[0] = 0; | 3083 | mfilt[0] = 0; |
2924 | mfilt[1] = 1; | 3084 | mfilt[1] = 1; |
2925 | 3085 | ||
2926 | for (i = 0; i < mc_count; i++) { | 3086 | netdev_hw_addr_list_for_each(ha, mc_list) { |
2927 | if (!mclist) | ||
2928 | break; | ||
2929 | /* calculate XOR of eight 6-bit values */ | 3087 | /* calculate XOR of eight 6-bit values */ |
2930 | val = get_unaligned_le32(mclist->dmi_addr + 0); | 3088 | val = get_unaligned_le32(ha->addr + 0); |
2931 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | 3089 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; |
2932 | val = get_unaligned_le32(mclist->dmi_addr + 3); | 3090 | val = get_unaligned_le32(ha->addr + 3); |
2933 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | 3091 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; |
2934 | pos &= 0x3f; | 3092 | pos &= 0x3f; |
2935 | mfilt[pos / 32] |= (1 << (pos % 32)); | 3093 | mfilt[pos / 32] |= (1 << (pos % 32)); |
@@ -2937,8 +3095,7 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | |||
2937 | * but not sure, needs testing, if we do use this we'd | 3095 | * but not sure, needs testing, if we do use this we'd |
2938 | * neet to inform below to not reset the mcast */ | 3096 | * neet to inform below to not reset the mcast */ |
2939 | /* ath5k_hw_set_mcast_filterindex(ah, | 3097 | /* ath5k_hw_set_mcast_filterindex(ah, |
2940 | * mclist->dmi_addr[5]); */ | 3098 | * ha->addr[5]); */ |
2941 | mclist = mclist->next; | ||
2942 | } | 3099 | } |
2943 | 3100 | ||
2944 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | 3101 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; |
@@ -3124,12 +3281,30 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3124 | struct ieee80211_low_level_stats *stats) | 3281 | struct ieee80211_low_level_stats *stats) |
3125 | { | 3282 | { |
3126 | struct ath5k_softc *sc = hw->priv; | 3283 | struct ath5k_softc *sc = hw->priv; |
3127 | struct ath5k_hw *ah = sc->ah; | ||
3128 | 3284 | ||
3129 | /* Force update */ | 3285 | /* Force update */ |
3130 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | 3286 | ath5k_hw_update_mib_counters(sc->ah); |
3287 | |||
3288 | stats->dot11ACKFailureCount = sc->stats.ack_fail; | ||
3289 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | ||
3290 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | ||
3291 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | ||
3292 | |||
3293 | return 0; | ||
3294 | } | ||
3295 | |||
3296 | static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, | ||
3297 | struct survey_info *survey) | ||
3298 | { | ||
3299 | struct ath5k_softc *sc = hw->priv; | ||
3300 | struct ieee80211_conf *conf = &hw->conf; | ||
3301 | |||
3302 | if (idx != 0) | ||
3303 | return -ENOENT; | ||
3131 | 3304 | ||
3132 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | 3305 | survey->channel = conf->channel; |
3306 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
3307 | survey->noise = sc->ah->ah_noise_floor; | ||
3133 | 3308 | ||
3134 | return 0; | 3309 | return 0; |
3135 | } | 3310 | } |