diff options
106 files changed, 4945 insertions, 2435 deletions
diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200 index 80c728522c4c..e4d3267071e4 100644 --- a/Documentation/networking/README.ipw2200 +++ b/Documentation/networking/README.ipw2200 | |||
@@ -171,7 +171,7 @@ Where the supported parameter are: | |||
171 | 171 | ||
172 | led | 172 | led |
173 | Can be used to turn on experimental LED code. | 173 | Can be used to turn on experimental LED code. |
174 | 0 = Off, 1 = On. Default is 0. | 174 | 0 = Off, 1 = On. Default is 1. |
175 | 175 | ||
176 | mode | 176 | mode |
177 | Can be used to set the default mode of the adapter. | 177 | Can be used to set the default mode of the adapter. |
diff --git a/MAINTAINERS b/MAINTAINERS index 0924a76da873..2ebb56710f4d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2978,20 +2978,14 @@ F: drivers/net/ixgb/ | |||
2978 | F: drivers/net/ixgbe/ | 2978 | F: drivers/net/ixgbe/ |
2979 | 2979 | ||
2980 | INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT | 2980 | INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT |
2981 | M: Reinette Chatre <reinette.chatre@intel.com> | ||
2982 | M: Intel Linux Wireless <ilw@linux.intel.com> | ||
2983 | L: linux-wireless@vger.kernel.org | 2981 | L: linux-wireless@vger.kernel.org |
2984 | W: http://ipw2100.sourceforge.net | 2982 | S: Orphan |
2985 | S: Odd Fixes | ||
2986 | F: Documentation/networking/README.ipw2100 | 2983 | F: Documentation/networking/README.ipw2100 |
2987 | F: drivers/net/wireless/ipw2x00/ipw2100.* | 2984 | F: drivers/net/wireless/ipw2x00/ipw2100.* |
2988 | 2985 | ||
2989 | INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT | 2986 | INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT |
2990 | M: Reinette Chatre <reinette.chatre@intel.com> | ||
2991 | M: Intel Linux Wireless <ilw@linux.intel.com> | ||
2992 | L: linux-wireless@vger.kernel.org | 2987 | L: linux-wireless@vger.kernel.org |
2993 | W: http://ipw2200.sourceforge.net | 2988 | S: Orphan |
2994 | S: Odd Fixes | ||
2995 | F: Documentation/networking/README.ipw2200 | 2989 | F: Documentation/networking/README.ipw2200 |
2996 | F: drivers/net/wireless/ipw2x00/ipw2200.* | 2990 | F: drivers/net/wireless/ipw2x00/ipw2200.* |
2997 | 2991 | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index cf16318a0a17..ea6362a8988d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -566,7 +566,7 @@ enum ath5k_pkt_type { | |||
566 | ) | 566 | ) |
567 | 567 | ||
568 | /* | 568 | /* |
569 | * DMA size definitions (2^n+2) | 569 | * DMA size definitions (2^(n+2)) |
570 | */ | 570 | */ |
571 | enum ath5k_dmasize { | 571 | enum ath5k_dmasize { |
572 | AR5K_DMASIZE_4B = 0, | 572 | AR5K_DMASIZE_4B = 0, |
@@ -1127,15 +1127,10 @@ struct ath5k_hw { | |||
1127 | /* | 1127 | /* |
1128 | * Function pointers | 1128 | * Function pointers |
1129 | */ | 1129 | */ |
1130 | int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1131 | u32 size, unsigned int flags); | ||
1132 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1130 | int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1133 | unsigned int, unsigned int, int, enum ath5k_pkt_type, | 1131 | unsigned int, unsigned int, int, enum ath5k_pkt_type, |
1134 | unsigned int, unsigned int, unsigned int, unsigned int, | 1132 | unsigned int, unsigned int, unsigned int, unsigned int, |
1135 | unsigned int, unsigned int, unsigned int, unsigned int); | 1133 | unsigned int, unsigned int, unsigned int, unsigned int); |
1136 | int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | ||
1137 | unsigned int, unsigned int, unsigned int, unsigned int, | ||
1138 | unsigned int, unsigned int); | ||
1139 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1134 | int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
1140 | struct ath5k_tx_status *); | 1135 | struct ath5k_tx_status *); |
1141 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, | 1136 | int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, |
@@ -1236,6 +1231,11 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | |||
1236 | 1231 | ||
1237 | /* Hardware Descriptor Functions */ | 1232 | /* Hardware Descriptor Functions */ |
1238 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
1234 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1235 | u32 size, unsigned int flags); | ||
1236 | int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
1237 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
1238 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); | ||
1239 | 1239 | ||
1240 | /* GPIO Functions */ | 1240 | /* GPIO Functions */ |
1241 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1241 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 9d37c1a43a9d..20328bdd138b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -311,7 +311,8 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
311 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 311 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
312 | struct ath5k_buf *bf, | 312 | struct ath5k_buf *bf, |
313 | struct ath5k_txq *txq, int padsize); | 313 | struct ath5k_txq *txq, int padsize); |
314 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 314 | |
315 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, | ||
315 | struct ath5k_buf *bf) | 316 | struct ath5k_buf *bf) |
316 | { | 317 | { |
317 | BUG_ON(!bf); | 318 | BUG_ON(!bf); |
@@ -321,9 +322,11 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | |||
321 | PCI_DMA_TODEVICE); | 322 | PCI_DMA_TODEVICE); |
322 | dev_kfree_skb_any(bf->skb); | 323 | dev_kfree_skb_any(bf->skb); |
323 | bf->skb = NULL; | 324 | bf->skb = NULL; |
325 | bf->skbaddr = 0; | ||
326 | bf->desc->ds_data = 0; | ||
324 | } | 327 | } |
325 | 328 | ||
326 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | 329 | static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, |
327 | struct ath5k_buf *bf) | 330 | struct ath5k_buf *bf) |
328 | { | 331 | { |
329 | struct ath5k_hw *ah = sc->ah; | 332 | struct ath5k_hw *ah = sc->ah; |
@@ -336,6 +339,8 @@ static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | |||
336 | PCI_DMA_FROMDEVICE); | 339 | PCI_DMA_FROMDEVICE); |
337 | dev_kfree_skb_any(bf->skb); | 340 | dev_kfree_skb_any(bf->skb); |
338 | bf->skb = NULL; | 341 | bf->skb = NULL; |
342 | bf->skbaddr = 0; | ||
343 | bf->desc->ds_data = 0; | ||
339 | } | 344 | } |
340 | 345 | ||
341 | 346 | ||
@@ -352,7 +357,6 @@ static void ath5k_txq_release(struct ath5k_softc *sc); | |||
352 | static int ath5k_rx_start(struct ath5k_softc *sc); | 357 | static int ath5k_rx_start(struct ath5k_softc *sc); |
353 | static void ath5k_rx_stop(struct ath5k_softc *sc); | 358 | static void ath5k_rx_stop(struct ath5k_softc *sc); |
354 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | 359 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, |
355 | struct ath5k_desc *ds, | ||
356 | struct sk_buff *skb, | 360 | struct sk_buff *skb, |
357 | struct ath5k_rx_status *rs); | 361 | struct ath5k_rx_status *rs); |
358 | static void ath5k_tasklet_rx(unsigned long data); | 362 | static void ath5k_tasklet_rx(unsigned long data); |
@@ -765,7 +769,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
765 | * return false w/o doing anything. MAC's that do | 769 | * return false w/o doing anything. MAC's that do |
766 | * support it will return true w/o doing anything. | 770 | * support it will return true w/o doing anything. |
767 | */ | 771 | */ |
768 | ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | 772 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); |
773 | |||
769 | if (ret < 0) | 774 | if (ret < 0) |
770 | goto err; | 775 | goto err; |
771 | if (ret > 0) | 776 | if (ret > 0) |
@@ -1111,8 +1116,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1111 | static int | 1116 | static int |
1112 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | 1117 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) |
1113 | { | 1118 | { |
1114 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", | 1119 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
1115 | sc->curchan->center_freq, chan->center_freq); | 1120 | "channel set, resetting (%u -> %u MHz)\n", |
1121 | sc->curchan->center_freq, chan->center_freq); | ||
1116 | 1122 | ||
1117 | /* | 1123 | /* |
1118 | * To switch channels clear any pending DMA operations; | 1124 | * To switch channels clear any pending DMA operations; |
@@ -1228,21 +1234,23 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1228 | * not get overrun under high load (as can happen with a | 1234 | * not get overrun under high load (as can happen with a |
1229 | * 5212 when ANI processing enables PHY error frames). | 1235 | * 5212 when ANI processing enables PHY error frames). |
1230 | * | 1236 | * |
1231 | * To insure the last descriptor is self-linked we create | 1237 | * To ensure the last descriptor is self-linked we create |
1232 | * each descriptor as self-linked and add it to the end. As | 1238 | * each descriptor as self-linked and add it to the end. As |
1233 | * each additional descriptor is added the previous self-linked | 1239 | * each additional descriptor is added the previous self-linked |
1234 | * entry is ``fixed'' naturally. This should be safe even | 1240 | * entry is "fixed" naturally. This should be safe even |
1235 | * if DMA is happening. When processing RX interrupts we | 1241 | * if DMA is happening. When processing RX interrupts we |
1236 | * never remove/process the last, self-linked, entry on the | 1242 | * never remove/process the last, self-linked, entry on the |
1237 | * descriptor list. This insures the hardware always has | 1243 | * descriptor list. This ensures the hardware always has |
1238 | * someplace to write a new frame. | 1244 | * someplace to write a new frame. |
1239 | */ | 1245 | */ |
1240 | ds = bf->desc; | 1246 | ds = bf->desc; |
1241 | ds->ds_link = bf->daddr; /* link to self */ | 1247 | ds->ds_link = bf->daddr; /* link to self */ |
1242 | ds->ds_data = bf->skbaddr; | 1248 | ds->ds_data = bf->skbaddr; |
1243 | ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); | 1249 | ret = ath5k_hw_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); |
1244 | if (ret) | 1250 | if (ret) { |
1251 | ATH5K_ERR(sc, "%s: could not setup RX desc\n", __func__); | ||
1245 | return ret; | 1252 | return ret; |
1253 | } | ||
1246 | 1254 | ||
1247 | if (sc->rxlink != NULL) | 1255 | if (sc->rxlink != NULL) |
1248 | *sc->rxlink = bf->daddr; | 1256 | *sc->rxlink = bf->daddr; |
@@ -1347,7 +1355,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1347 | mrr_tries[i] = info->control.rates[i + 1].count; | 1355 | mrr_tries[i] = info->control.rates[i + 1].count; |
1348 | } | 1356 | } |
1349 | 1357 | ||
1350 | ah->ah_setup_mrr_tx_desc(ah, ds, | 1358 | ath5k_hw_setup_mrr_tx_desc(ah, ds, |
1351 | mrr_rate[0], mrr_tries[0], | 1359 | mrr_rate[0], mrr_tries[0], |
1352 | mrr_rate[1], mrr_tries[1], | 1360 | mrr_rate[1], mrr_tries[1], |
1353 | mrr_rate[2], mrr_tries[2]); | 1361 | mrr_rate[2], mrr_tries[2]); |
@@ -1443,17 +1451,20 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
1443 | { | 1451 | { |
1444 | struct ath5k_buf *bf; | 1452 | struct ath5k_buf *bf; |
1445 | 1453 | ||
1446 | ath5k_txbuf_free(sc, sc->bbuf); | 1454 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
1447 | list_for_each_entry(bf, &sc->txbuf, list) | 1455 | list_for_each_entry(bf, &sc->txbuf, list) |
1448 | ath5k_txbuf_free(sc, bf); | 1456 | ath5k_txbuf_free_skb(sc, bf); |
1449 | list_for_each_entry(bf, &sc->rxbuf, list) | 1457 | list_for_each_entry(bf, &sc->rxbuf, list) |
1450 | ath5k_rxbuf_free(sc, bf); | 1458 | ath5k_rxbuf_free_skb(sc, bf); |
1451 | 1459 | ||
1452 | /* Free memory associated with all descriptors */ | 1460 | /* Free memory associated with all descriptors */ |
1453 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | 1461 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); |
1462 | sc->desc = NULL; | ||
1463 | sc->desc_daddr = 0; | ||
1454 | 1464 | ||
1455 | kfree(sc->bufptr); | 1465 | kfree(sc->bufptr); |
1456 | sc->bufptr = NULL; | 1466 | sc->bufptr = NULL; |
1467 | sc->bbuf = NULL; | ||
1457 | } | 1468 | } |
1458 | 1469 | ||
1459 | 1470 | ||
@@ -1602,7 +1613,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1602 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1613 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
1603 | ath5k_debug_printtxbuf(sc, bf); | 1614 | ath5k_debug_printtxbuf(sc, bf); |
1604 | 1615 | ||
1605 | ath5k_txbuf_free(sc, bf); | 1616 | ath5k_txbuf_free_skb(sc, bf); |
1606 | 1617 | ||
1607 | spin_lock_bh(&sc->txbuflock); | 1618 | spin_lock_bh(&sc->txbuflock); |
1608 | list_move_tail(&bf->list, &sc->txbuf); | 1619 | list_move_tail(&bf->list, &sc->txbuf); |
@@ -1721,8 +1732,8 @@ ath5k_rx_stop(struct ath5k_softc *sc) | |||
1721 | } | 1732 | } |
1722 | 1733 | ||
1723 | static unsigned int | 1734 | static unsigned int |
1724 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | 1735 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct sk_buff *skb, |
1725 | struct sk_buff *skb, struct ath5k_rx_status *rs) | 1736 | struct ath5k_rx_status *rs) |
1726 | { | 1737 | { |
1727 | struct ath5k_hw *ah = sc->ah; | 1738 | struct ath5k_hw *ah = sc->ah; |
1728 | struct ath_common *common = ath5k_hw_common(ah); | 1739 | struct ath_common *common = ath5k_hw_common(ah); |
@@ -1889,9 +1900,138 @@ static int ath5k_remove_padding(struct sk_buff *skb) | |||
1889 | } | 1900 | } |
1890 | 1901 | ||
1891 | static void | 1902 | static void |
1892 | ath5k_tasklet_rx(unsigned long data) | 1903 | ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, |
1904 | struct ath5k_rx_status *rs) | ||
1893 | { | 1905 | { |
1894 | struct ieee80211_rx_status *rxs; | 1906 | struct ieee80211_rx_status *rxs; |
1907 | |||
1908 | /* The MAC header is padded to have 32-bit boundary if the | ||
1909 | * packet payload is non-zero. The general calculation for | ||
1910 | * padsize would take into account odd header lengths: | ||
1911 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1912 | * even-length headers are used, padding can only be 0 or 2 | ||
1913 | * bytes and we can optimize this a bit. In addition, we must | ||
1914 | * not try to remove padding from short control frames that do | ||
1915 | * not have payload. */ | ||
1916 | ath5k_remove_padding(skb); | ||
1917 | |||
1918 | rxs = IEEE80211_SKB_RXCB(skb); | ||
1919 | |||
1920 | rxs->flag = 0; | ||
1921 | if (unlikely(rs->rs_status & AR5K_RXERR_MIC)) | ||
1922 | rxs->flag |= RX_FLAG_MMIC_ERROR; | ||
1923 | |||
1924 | /* | ||
1925 | * always extend the mac timestamp, since this information is | ||
1926 | * also needed for proper IBSS merging. | ||
1927 | * | ||
1928 | * XXX: it might be too late to do it here, since rs_tstamp is | ||
1929 | * 15bit only. that means TSF extension has to be done within | ||
1930 | * 32768usec (about 32ms). it might be necessary to move this to | ||
1931 | * the interrupt handler, like it is done in madwifi. | ||
1932 | * | ||
1933 | * Unfortunately we don't know when the hardware takes the rx | ||
1934 | * timestamp (beginning of phy frame, data frame, end of rx?). | ||
1935 | * The only thing we know is that it is hardware specific... | ||
1936 | * On AR5213 it seems the rx timestamp is at the end of the | ||
1937 | * frame, but i'm not sure. | ||
1938 | * | ||
1939 | * NOTE: mac80211 defines mactime at the beginning of the first | ||
1940 | * data symbol. Since we don't have any time references it's | ||
1941 | * impossible to comply to that. This affects IBSS merge only | ||
1942 | * right now, so it's not too bad... | ||
1943 | */ | ||
1944 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); | ||
1945 | rxs->flag |= RX_FLAG_TSFT; | ||
1946 | |||
1947 | rxs->freq = sc->curchan->center_freq; | ||
1948 | rxs->band = sc->curband->band; | ||
1949 | |||
1950 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; | ||
1951 | |||
1952 | rxs->antenna = rs->rs_antenna; | ||
1953 | |||
1954 | if (rs->rs_antenna > 0 && rs->rs_antenna < 5) | ||
1955 | sc->stats.antenna_rx[rs->rs_antenna]++; | ||
1956 | else | ||
1957 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
1958 | |||
1959 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs->rs_rate); | ||
1960 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); | ||
1961 | |||
1962 | if (rxs->rate_idx >= 0 && rs->rs_rate == | ||
1963 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | ||
1964 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
1965 | |||
1966 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | ||
1967 | |||
1968 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); | ||
1969 | |||
1970 | /* check beacons in IBSS mode */ | ||
1971 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | ||
1972 | ath5k_check_ibss_tsf(sc, skb, rxs); | ||
1973 | |||
1974 | ieee80211_rx(sc->hw, skb); | ||
1975 | } | ||
1976 | |||
1977 | /** ath5k_frame_receive_ok() - Do we want to receive this frame or not? | ||
1978 | * | ||
1979 | * Check if we want to further process this frame or not. Also update | ||
1980 | * statistics. Return true if we want this frame, false if not. | ||
1981 | */ | ||
1982 | static bool | ||
1983 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | ||
1984 | { | ||
1985 | sc->stats.rx_all_count++; | ||
1986 | |||
1987 | if (unlikely(rs->rs_status)) { | ||
1988 | if (rs->rs_status & AR5K_RXERR_CRC) | ||
1989 | sc->stats.rxerr_crc++; | ||
1990 | if (rs->rs_status & AR5K_RXERR_FIFO) | ||
1991 | sc->stats.rxerr_fifo++; | ||
1992 | if (rs->rs_status & AR5K_RXERR_PHY) { | ||
1993 | sc->stats.rxerr_phy++; | ||
1994 | if (rs->rs_phyerr > 0 && rs->rs_phyerr < 32) | ||
1995 | sc->stats.rxerr_phy_code[rs->rs_phyerr]++; | ||
1996 | return false; | ||
1997 | } | ||
1998 | if (rs->rs_status & AR5K_RXERR_DECRYPT) { | ||
1999 | /* | ||
2000 | * Decrypt error. If the error occurred | ||
2001 | * because there was no hardware key, then | ||
2002 | * let the frame through so the upper layers | ||
2003 | * can process it. This is necessary for 5210 | ||
2004 | * parts which have no way to setup a ``clear'' | ||
2005 | * key cache entry. | ||
2006 | * | ||
2007 | * XXX do key cache faulting | ||
2008 | */ | ||
2009 | sc->stats.rxerr_decrypt++; | ||
2010 | if (rs->rs_keyix == AR5K_RXKEYIX_INVALID && | ||
2011 | !(rs->rs_status & AR5K_RXERR_CRC)) | ||
2012 | return true; | ||
2013 | } | ||
2014 | if (rs->rs_status & AR5K_RXERR_MIC) { | ||
2015 | sc->stats.rxerr_mic++; | ||
2016 | return true; | ||
2017 | } | ||
2018 | |||
2019 | /* let crypto-error packets fall through in MNTR */ | ||
2020 | if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | ||
2021 | sc->opmode != NL80211_IFTYPE_MONITOR) | ||
2022 | return false; | ||
2023 | } | ||
2024 | |||
2025 | if (unlikely(rs->rs_more)) { | ||
2026 | sc->stats.rxerr_jumbo++; | ||
2027 | return false; | ||
2028 | } | ||
2029 | return true; | ||
2030 | } | ||
2031 | |||
2032 | static void | ||
2033 | ath5k_tasklet_rx(unsigned long data) | ||
2034 | { | ||
1895 | struct ath5k_rx_status rs = {}; | 2035 | struct ath5k_rx_status rs = {}; |
1896 | struct sk_buff *skb, *next_skb; | 2036 | struct sk_buff *skb, *next_skb; |
1897 | dma_addr_t next_skb_addr; | 2037 | dma_addr_t next_skb_addr; |
@@ -1901,7 +2041,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1901 | struct ath5k_buf *bf; | 2041 | struct ath5k_buf *bf; |
1902 | struct ath5k_desc *ds; | 2042 | struct ath5k_desc *ds; |
1903 | int ret; | 2043 | int ret; |
1904 | int rx_flag; | ||
1905 | 2044 | ||
1906 | spin_lock(&sc->rxbuflock); | 2045 | spin_lock(&sc->rxbuflock); |
1907 | if (list_empty(&sc->rxbuf)) { | 2046 | if (list_empty(&sc->rxbuf)) { |
@@ -1909,8 +2048,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1909 | goto unlock; | 2048 | goto unlock; |
1910 | } | 2049 | } |
1911 | do { | 2050 | do { |
1912 | rx_flag = 0; | ||
1913 | |||
1914 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | 2051 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); |
1915 | BUG_ON(bf->skb == NULL); | 2052 | BUG_ON(bf->skb == NULL); |
1916 | skb = bf->skb; | 2053 | skb = bf->skb; |
@@ -1926,137 +2063,30 @@ ath5k_tasklet_rx(unsigned long data) | |||
1926 | else if (unlikely(ret)) { | 2063 | else if (unlikely(ret)) { |
1927 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 2064 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1928 | sc->stats.rxerr_proc++; | 2065 | sc->stats.rxerr_proc++; |
1929 | spin_unlock(&sc->rxbuflock); | 2066 | break; |
1930 | return; | ||
1931 | } | 2067 | } |
1932 | 2068 | ||
1933 | sc->stats.rx_all_count++; | 2069 | if (ath5k_receive_frame_ok(sc, &rs)) { |
1934 | 2070 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | |
1935 | if (unlikely(rs.rs_status)) { | ||
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]++; | ||
1944 | goto next; | ||
1945 | } | ||
1946 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | ||
1947 | /* | ||
1948 | * Decrypt error. If the error occurred | ||
1949 | * because there was no hardware key, then | ||
1950 | * let the frame through so the upper layers | ||
1951 | * can process it. This is necessary for 5210 | ||
1952 | * parts which have no way to setup a ``clear'' | ||
1953 | * key cache entry. | ||
1954 | * | ||
1955 | * XXX do key cache faulting | ||
1956 | */ | ||
1957 | sc->stats.rxerr_decrypt++; | ||
1958 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | ||
1959 | !(rs.rs_status & AR5K_RXERR_CRC)) | ||
1960 | goto accept; | ||
1961 | } | ||
1962 | if (rs.rs_status & AR5K_RXERR_MIC) { | ||
1963 | rx_flag |= RX_FLAG_MMIC_ERROR; | ||
1964 | sc->stats.rxerr_mic++; | ||
1965 | goto accept; | ||
1966 | } | ||
1967 | 2071 | ||
1968 | /* let crypto-error packets fall through in MNTR */ | 2072 | /* |
1969 | if ((rs.rs_status & | 2073 | * If we can't replace bf->skb with a new skb under |
1970 | ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 2074 | * memory pressure, just skip this packet |
1971 | sc->opmode != NL80211_IFTYPE_MONITOR) | 2075 | */ |
2076 | if (!next_skb) | ||
1972 | goto next; | 2077 | goto next; |
1973 | } | ||
1974 | |||
1975 | if (unlikely(rs.rs_more)) { | ||
1976 | sc->stats.rxerr_jumbo++; | ||
1977 | goto next; | ||
1978 | 2078 | ||
1979 | } | 2079 | pci_unmap_single(sc->pdev, bf->skbaddr, |
1980 | accept: | 2080 | common->rx_bufsize, |
1981 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | 2081 | PCI_DMA_FROMDEVICE); |
1982 | 2082 | ||
1983 | /* | 2083 | skb_put(skb, rs.rs_datalen); |
1984 | * If we can't replace bf->skb with a new skb under memory | ||
1985 | * pressure, just skip this packet | ||
1986 | */ | ||
1987 | if (!next_skb) | ||
1988 | goto next; | ||
1989 | |||
1990 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, | ||
1991 | PCI_DMA_FROMDEVICE); | ||
1992 | skb_put(skb, rs.rs_datalen); | ||
1993 | |||
1994 | /* The MAC header is padded to have 32-bit boundary if the | ||
1995 | * packet payload is non-zero. The general calculation for | ||
1996 | * padsize would take into account odd header lengths: | ||
1997 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1998 | * even-length headers are used, padding can only be 0 or 2 | ||
1999 | * bytes and we can optimize this a bit. In addition, we must | ||
2000 | * not try to remove padding from short control frames that do | ||
2001 | * not have payload. */ | ||
2002 | ath5k_remove_padding(skb); | ||
2003 | 2084 | ||
2004 | rxs = IEEE80211_SKB_RXCB(skb); | 2085 | ath5k_receive_frame(sc, skb, &rs); |
2005 | 2086 | ||
2006 | /* | 2087 | bf->skb = next_skb; |
2007 | * always extend the mac timestamp, since this information is | 2088 | bf->skbaddr = next_skb_addr; |
2008 | * also needed for proper IBSS merging. | 2089 | } |
2009 | * | ||
2010 | * XXX: it might be too late to do it here, since rs_tstamp is | ||
2011 | * 15bit only. that means TSF extension has to be done within | ||
2012 | * 32768usec (about 32ms). it might be necessary to move this to | ||
2013 | * the interrupt handler, like it is done in madwifi. | ||
2014 | * | ||
2015 | * Unfortunately we don't know when the hardware takes the rx | ||
2016 | * timestamp (beginning of phy frame, data frame, end of rx?). | ||
2017 | * The only thing we know is that it is hardware specific... | ||
2018 | * On AR5213 it seems the rx timestamp is at the end of the | ||
2019 | * frame, but i'm not sure. | ||
2020 | * | ||
2021 | * NOTE: mac80211 defines mactime at the beginning of the first | ||
2022 | * data symbol. Since we don't have any time references it's | ||
2023 | * impossible to comply to that. This affects IBSS merge only | ||
2024 | * right now, so it's not too bad... | ||
2025 | */ | ||
2026 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); | ||
2027 | rxs->flag = rx_flag | RX_FLAG_TSFT; | ||
2028 | |||
2029 | rxs->freq = sc->curchan->center_freq; | ||
2030 | rxs->band = sc->curband->band; | ||
2031 | |||
2032 | rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi; | ||
2033 | |||
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 | |||
2041 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | ||
2042 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | ||
2043 | |||
2044 | if (rxs->rate_idx >= 0 && rs.rs_rate == | ||
2045 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | ||
2046 | rxs->flag |= RX_FLAG_SHORTPRE; | ||
2047 | |||
2048 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | ||
2049 | |||
2050 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | ||
2051 | |||
2052 | /* check beacons in IBSS mode */ | ||
2053 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | ||
2054 | ath5k_check_ibss_tsf(sc, skb, rxs); | ||
2055 | |||
2056 | ieee80211_rx(sc->hw, skb); | ||
2057 | |||
2058 | bf->skb = next_skb; | ||
2059 | bf->skbaddr = next_skb_addr; | ||
2060 | next: | 2090 | next: |
2061 | list_move_tail(&bf->list, &sc->rxbuf); | 2091 | list_move_tail(&bf->list, &sc->rxbuf); |
2062 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 2092 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
@@ -2065,8 +2095,6 @@ unlock: | |||
2065 | } | 2095 | } |
2066 | 2096 | ||
2067 | 2097 | ||
2068 | |||
2069 | |||
2070 | /*************\ | 2098 | /*************\ |
2071 | * TX Handling * | 2099 | * TX Handling * |
2072 | \*************/ | 2100 | \*************/ |
@@ -2298,6 +2326,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2298 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 2326 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
2299 | "stuck beacon time (%u missed)\n", | 2327 | "stuck beacon time (%u missed)\n", |
2300 | sc->bmisscount); | 2328 | sc->bmisscount); |
2329 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2330 | "stuck beacon, resetting\n"); | ||
2301 | tasklet_schedule(&sc->restq); | 2331 | tasklet_schedule(&sc->restq); |
2302 | } | 2332 | } |
2303 | return; | 2333 | return; |
@@ -2647,7 +2677,7 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2647 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 2677 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2648 | "putting device to sleep\n"); | 2678 | "putting device to sleep\n"); |
2649 | } | 2679 | } |
2650 | ath5k_txbuf_free(sc, sc->bbuf); | 2680 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
2651 | 2681 | ||
2652 | mmiowb(); | 2682 | mmiowb(); |
2653 | mutex_unlock(&sc->lock); | 2683 | mutex_unlock(&sc->lock); |
@@ -2705,6 +2735,8 @@ ath5k_intr(int irq, void *dev_id) | |||
2705 | * Fatal errors are unrecoverable. | 2735 | * Fatal errors are unrecoverable. |
2706 | * Typically these are caused by DMA errors. | 2736 | * Typically these are caused by DMA errors. |
2707 | */ | 2737 | */ |
2738 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2739 | "fatal int, resetting\n"); | ||
2708 | tasklet_schedule(&sc->restq); | 2740 | tasklet_schedule(&sc->restq); |
2709 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2741 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2710 | /* | 2742 | /* |
@@ -2717,8 +2749,11 @@ ath5k_intr(int irq, void *dev_id) | |||
2717 | * this guess is copied from the HAL. | 2749 | * this guess is copied from the HAL. |
2718 | */ | 2750 | */ |
2719 | sc->stats.rxorn_intr++; | 2751 | sc->stats.rxorn_intr++; |
2720 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) | 2752 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) { |
2753 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2754 | "rx overrun, resetting\n"); | ||
2721 | tasklet_schedule(&sc->restq); | 2755 | tasklet_schedule(&sc->restq); |
2756 | } | ||
2722 | else | 2757 | else |
2723 | tasklet_schedule(&sc->rxtq); | 2758 | tasklet_schedule(&sc->rxtq); |
2724 | } else { | 2759 | } else { |
@@ -3368,7 +3403,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
3368 | 3403 | ||
3369 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | 3404 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); |
3370 | 3405 | ||
3371 | ath5k_txbuf_free(sc, sc->bbuf); | 3406 | ath5k_txbuf_free_skb(sc, sc->bbuf); |
3372 | sc->bbuf->skb = skb; | 3407 | sc->bbuf->skb = skb; |
3373 | ret = ath5k_beacon_setup(sc, sc->bbuf); | 3408 | ret = ath5k_beacon_setup(sc, sc->bbuf); |
3374 | if (ret) | 3409 | if (ret) |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0f2e37d85cbd..8c638865c712 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -278,6 +278,7 @@ static ssize_t write_file_reset(struct file *file, | |||
278 | size_t count, loff_t *ppos) | 278 | size_t count, loff_t *ppos) |
279 | { | 279 | { |
280 | struct ath5k_softc *sc = file->private_data; | 280 | struct ath5k_softc *sc = file->private_data; |
281 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "debug file triggered reset\n"); | ||
281 | tasklet_schedule(&sc->restq); | 282 | tasklet_schedule(&sc->restq); |
282 | return count; | 283 | return count; |
283 | } | 284 | } |
@@ -924,7 +925,7 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, | |||
924 | ds, (unsigned long long)bf->daddr, | 925 | ds, (unsigned long long)bf->daddr, |
925 | ds->ds_link, ds->ds_data, | 926 | ds->ds_link, ds->ds_data, |
926 | rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, | 927 | rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, |
927 | rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, | 928 | rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1, |
928 | !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); | 929 | !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); |
929 | } | 930 | } |
930 | 931 | ||
@@ -939,7 +940,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
939 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 940 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) |
940 | return; | 941 | return; |
941 | 942 | ||
942 | printk(KERN_DEBUG "rx queue %x, link %p\n", | 943 | printk(KERN_DEBUG "rxdp %x, rxlink %p\n", |
943 | ath5k_hw_get_rxdp(ah), sc->rxlink); | 944 | ath5k_hw_get_rxdp(ah), sc->rxlink); |
944 | 945 | ||
945 | spin_lock_bh(&sc->rxbuflock); | 946 | spin_lock_bh(&sc->rxbuflock); |
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index da5dbb63047f..43244382f213 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -91,14 +91,13 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
91 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; | 91 | tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; |
92 | 92 | ||
93 | /* | 93 | /* |
94 | * Verify and set header length | 94 | * Verify and set header length (only 5210) |
95 | * XXX: I only found that on 5210 code, does it work on 5211 ? | ||
96 | */ | 95 | */ |
97 | if (ah->ah_version == AR5K_AR5210) { | 96 | if (ah->ah_version == AR5K_AR5210) { |
98 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) | 97 | if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210) |
99 | return -EINVAL; | 98 | return -EINVAL; |
100 | tx_ctl->tx_control_0 |= | 99 | tx_ctl->tx_control_0 |= |
101 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); | 100 | AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210); |
102 | } | 101 | } |
103 | 102 | ||
104 | /*Differences between 5210-5211*/ | 103 | /*Differences between 5210-5211*/ |
@@ -110,11 +109,11 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
110 | case AR5K_PKT_TYPE_PIFS: | 109 | case AR5K_PKT_TYPE_PIFS: |
111 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | 110 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; |
112 | default: | 111 | default: |
113 | frame_type = type /*<< 2 ?*/; | 112 | frame_type = type; |
114 | } | 113 | } |
115 | 114 | ||
116 | tx_ctl->tx_control_0 |= | 115 | tx_ctl->tx_control_0 |= |
117 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | | 116 | AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210) | |
118 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | 117 | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); |
119 | 118 | ||
120 | } else { | 119 | } else { |
@@ -123,21 +122,30 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
123 | AR5K_REG_SM(antenna_mode, | 122 | AR5K_REG_SM(antenna_mode, |
124 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); | 123 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); |
125 | tx_ctl->tx_control_1 |= | 124 | tx_ctl->tx_control_1 |= |
126 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); | 125 | AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211); |
127 | } | 126 | } |
127 | |||
128 | #define _TX_FLAGS(_c, _flag) \ | 128 | #define _TX_FLAGS(_c, _flag) \ |
129 | if (flags & AR5K_TXDESC_##_flag) { \ | 129 | if (flags & AR5K_TXDESC_##_flag) { \ |
130 | tx_ctl->tx_control_##_c |= \ | 130 | tx_ctl->tx_control_##_c |= \ |
131 | AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ | 131 | AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ |
132 | } | 132 | } |
133 | 133 | #define _TX_FLAGS_5211(_c, _flag) \ | |
134 | if (flags & AR5K_TXDESC_##_flag) { \ | ||
135 | tx_ctl->tx_control_##_c |= \ | ||
136 | AR5K_2W_TX_DESC_CTL##_c##_##_flag##_5211; \ | ||
137 | } | ||
134 | _TX_FLAGS(0, CLRDMASK); | 138 | _TX_FLAGS(0, CLRDMASK); |
135 | _TX_FLAGS(0, VEOL); | ||
136 | _TX_FLAGS(0, INTREQ); | 139 | _TX_FLAGS(0, INTREQ); |
137 | _TX_FLAGS(0, RTSENA); | 140 | _TX_FLAGS(0, RTSENA); |
138 | _TX_FLAGS(1, NOACK); | 141 | |
142 | if (ah->ah_version == AR5K_AR5211) { | ||
143 | _TX_FLAGS_5211(0, VEOL); | ||
144 | _TX_FLAGS_5211(1, NOACK); | ||
145 | } | ||
139 | 146 | ||
140 | #undef _TX_FLAGS | 147 | #undef _TX_FLAGS |
148 | #undef _TX_FLAGS_5211 | ||
141 | 149 | ||
142 | /* | 150 | /* |
143 | * WEP crap | 151 | * WEP crap |
@@ -147,7 +155,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
147 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 155 | AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
148 | tx_ctl->tx_control_1 |= | 156 | tx_ctl->tx_control_1 |= |
149 | AR5K_REG_SM(key_index, | 157 | AR5K_REG_SM(key_index, |
150 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 158 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX); |
151 | } | 159 | } |
152 | 160 | ||
153 | /* | 161 | /* |
@@ -156,7 +164,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
156 | if ((ah->ah_version == AR5K_AR5210) && | 164 | if ((ah->ah_version == AR5K_AR5210) && |
157 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) | 165 | (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) |
158 | tx_ctl->tx_control_1 |= rtscts_duration & | 166 | tx_ctl->tx_control_1 |= rtscts_duration & |
159 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION; | 167 | AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210; |
160 | 168 | ||
161 | return 0; | 169 | return 0; |
162 | } | 170 | } |
@@ -255,7 +263,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
255 | if (key_index != AR5K_TXKEYIX_INVALID) { | 263 | if (key_index != AR5K_TXKEYIX_INVALID) { |
256 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 264 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
257 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | 265 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, |
258 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); | 266 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); |
259 | } | 267 | } |
260 | 268 | ||
261 | /* | 269 | /* |
@@ -277,13 +285,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
277 | /* | 285 | /* |
278 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 | 286 | * Initialize a 4-word multi rate retry tx control descriptor on 5212 |
279 | */ | 287 | */ |
280 | static int | 288 | int |
281 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 289 | ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
282 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | 290 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, |
283 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | 291 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) |
284 | { | 292 | { |
285 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 293 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
286 | 294 | ||
295 | /* no mrr support for cards older than 5212 */ | ||
296 | if (ah->ah_version < AR5K_AR5212) | ||
297 | return 0; | ||
298 | |||
287 | /* | 299 | /* |
288 | * Rates can be 0 as long as the retry count is 0 too. | 300 | * Rates can be 0 as long as the retry count is 0 too. |
289 | * A zero rate and nonzero retry count will put the HW into a mode where | 301 | * A zero rate and nonzero retry count will put the HW into a mode where |
@@ -323,15 +335,6 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
323 | return 0; | 335 | return 0; |
324 | } | 336 | } |
325 | 337 | ||
326 | /* no mrr support for cards older than 5212 */ | ||
327 | static int | ||
328 | ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
329 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
330 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | ||
331 | { | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | /* | 338 | /* |
336 | * Proccess the tx status descriptor on 5210/5211 | 339 | * Proccess the tx status descriptor on 5210/5211 |
337 | */ | 340 | */ |
@@ -414,11 +417,11 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
414 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 417 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, |
415 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 418 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
416 | ts->ts_antenna = (tx_status->tx_status_1 & | 419 | ts->ts_antenna = (tx_status->tx_status_1 & |
417 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | 420 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; |
418 | ts->ts_status = 0; | 421 | ts->ts_status = 0; |
419 | 422 | ||
420 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, | 423 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, |
421 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); | 424 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
422 | 425 | ||
423 | /* The longretry counter has the number of un-acked retries | 426 | /* The longretry counter has the number of un-acked retries |
424 | * for the final rate. To get the total number of retries | 427 | * for the final rate. To get the total number of retries |
@@ -480,8 +483,8 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
480 | /* | 483 | /* |
481 | * Initialize an rx control descriptor | 484 | * Initialize an rx control descriptor |
482 | */ | 485 | */ |
483 | static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | 486 | int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, |
484 | u32 size, unsigned int flags) | 487 | u32 size, unsigned int flags) |
485 | { | 488 | { |
486 | struct ath5k_hw_rx_ctl *rx_ctl; | 489 | struct ath5k_hw_rx_ctl *rx_ctl; |
487 | 490 | ||
@@ -496,10 +499,11 @@ static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
496 | */ | 499 | */ |
497 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); | 500 | memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); |
498 | 501 | ||
502 | if (unlikely(size & ~AR5K_DESC_RX_CTL1_BUF_LEN)) | ||
503 | return -EINVAL; | ||
504 | |||
499 | /* Setup descriptor */ | 505 | /* Setup descriptor */ |
500 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; | 506 | rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; |
501 | if (unlikely(rx_ctl->rx_control_1 != size)) | ||
502 | return -EINVAL; | ||
503 | 507 | ||
504 | if (flags & AR5K_RXDESC_INTREQ) | 508 | if (flags & AR5K_RXDESC_INTREQ) |
505 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; | 509 | rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; |
@@ -515,13 +519,15 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
515 | { | 519 | { |
516 | struct ath5k_hw_rx_status *rx_status; | 520 | struct ath5k_hw_rx_status *rx_status; |
517 | 521 | ||
518 | rx_status = &desc->ud.ds_rx.u.rx_stat; | 522 | rx_status = &desc->ud.ds_rx.rx_stat; |
519 | 523 | ||
520 | /* No frame received / not ready */ | 524 | /* No frame received / not ready */ |
521 | if (unlikely(!(rx_status->rx_status_1 & | 525 | if (unlikely(!(rx_status->rx_status_1 & |
522 | AR5K_5210_RX_DESC_STATUS1_DONE))) | 526 | AR5K_5210_RX_DESC_STATUS1_DONE))) |
523 | return -EINPROGRESS; | 527 | return -EINPROGRESS; |
524 | 528 | ||
529 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | ||
530 | |||
525 | /* | 531 | /* |
526 | * Frame receive status | 532 | * Frame receive status |
527 | */ | 533 | */ |
@@ -531,15 +537,23 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
531 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 537 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
532 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 538 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, |
533 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); | 539 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); |
534 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | ||
535 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); | ||
536 | rs->rs_more = !!(rx_status->rx_status_0 & | 540 | rs->rs_more = !!(rx_status->rx_status_0 & |
537 | AR5K_5210_RX_DESC_STATUS0_MORE); | 541 | AR5K_5210_RX_DESC_STATUS0_MORE); |
538 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ | 542 | /* TODO: this timestamp is 13 bit, later on we assume 15 bit! |
543 | * also the HAL code for 5210 says the timestamp is bits [10..22] of the | ||
544 | * TSF, and extends the timestamp here to 15 bit. | ||
545 | * we need to check on 5210... | ||
546 | */ | ||
539 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 547 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
540 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 548 | AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
541 | rs->rs_status = 0; | 549 | |
542 | rs->rs_phyerr = 0; | 550 | if (ah->ah_version == AR5K_AR5211) |
551 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | ||
552 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211); | ||
553 | else | ||
554 | rs->rs_antenna = (rx_status->rx_status_0 & | ||
555 | AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210) | ||
556 | ? 2 : 1; | ||
543 | 557 | ||
544 | /* | 558 | /* |
545 | * Key table status | 559 | * Key table status |
@@ -554,19 +568,21 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
554 | * Receive/descriptor errors | 568 | * Receive/descriptor errors |
555 | */ | 569 | */ |
556 | if (!(rx_status->rx_status_1 & | 570 | if (!(rx_status->rx_status_1 & |
557 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 571 | AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
558 | if (rx_status->rx_status_1 & | 572 | if (rx_status->rx_status_1 & |
559 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) | 573 | AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) |
560 | rs->rs_status |= AR5K_RXERR_CRC; | 574 | rs->rs_status |= AR5K_RXERR_CRC; |
561 | 575 | ||
562 | if (rx_status->rx_status_1 & | 576 | /* only on 5210 */ |
563 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) | 577 | if ((ah->ah_version == AR5K_AR5210) && |
578 | (rx_status->rx_status_1 & | ||
579 | AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210)) | ||
564 | rs->rs_status |= AR5K_RXERR_FIFO; | 580 | rs->rs_status |= AR5K_RXERR_FIFO; |
565 | 581 | ||
566 | if (rx_status->rx_status_1 & | 582 | if (rx_status->rx_status_1 & |
567 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { | 583 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { |
568 | rs->rs_status |= AR5K_RXERR_PHY; | 584 | rs->rs_status |= AR5K_RXERR_PHY; |
569 | rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, | 585 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
570 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); | 586 | AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); |
571 | } | 587 | } |
572 | 588 | ||
@@ -582,21 +598,20 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
582 | * Proccess the rx status descriptor on 5212 | 598 | * Proccess the rx status descriptor on 5212 |
583 | */ | 599 | */ |
584 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | 600 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, |
585 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | 601 | struct ath5k_desc *desc, |
602 | struct ath5k_rx_status *rs) | ||
586 | { | 603 | { |
587 | struct ath5k_hw_rx_status *rx_status; | 604 | struct ath5k_hw_rx_status *rx_status; |
588 | struct ath5k_hw_rx_error *rx_err; | ||
589 | |||
590 | rx_status = &desc->ud.ds_rx.u.rx_stat; | ||
591 | 605 | ||
592 | /* Overlay on error */ | 606 | rx_status = &desc->ud.ds_rx.rx_stat; |
593 | rx_err = &desc->ud.ds_rx.u.rx_err; | ||
594 | 607 | ||
595 | /* No frame received / not ready */ | 608 | /* No frame received / not ready */ |
596 | if (unlikely(!(rx_status->rx_status_1 & | 609 | if (unlikely(!(rx_status->rx_status_1 & |
597 | AR5K_5212_RX_DESC_STATUS1_DONE))) | 610 | AR5K_5212_RX_DESC_STATUS1_DONE))) |
598 | return -EINPROGRESS; | 611 | return -EINPROGRESS; |
599 | 612 | ||
613 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | ||
614 | |||
600 | /* | 615 | /* |
601 | * Frame receive status | 616 | * Frame receive status |
602 | */ | 617 | */ |
@@ -612,15 +627,13 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
612 | AR5K_5212_RX_DESC_STATUS0_MORE); | 627 | AR5K_5212_RX_DESC_STATUS0_MORE); |
613 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | 628 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
614 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 629 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
615 | rs->rs_status = 0; | ||
616 | rs->rs_phyerr = 0; | ||
617 | 630 | ||
618 | /* | 631 | /* |
619 | * Key table status | 632 | * Key table status |
620 | */ | 633 | */ |
621 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | 634 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
622 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 635 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, |
623 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | 636 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
624 | else | 637 | else |
625 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | 638 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
626 | 639 | ||
@@ -628,7 +641,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
628 | * Receive/descriptor errors | 641 | * Receive/descriptor errors |
629 | */ | 642 | */ |
630 | if (!(rx_status->rx_status_1 & | 643 | if (!(rx_status->rx_status_1 & |
631 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 644 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
632 | if (rx_status->rx_status_1 & | 645 | if (rx_status->rx_status_1 & |
633 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | 646 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
634 | rs->rs_status |= AR5K_RXERR_CRC; | 647 | rs->rs_status |= AR5K_RXERR_CRC; |
@@ -636,9 +649,10 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
636 | if (rx_status->rx_status_1 & | 649 | if (rx_status->rx_status_1 & |
637 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | 650 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
638 | rs->rs_status |= AR5K_RXERR_PHY; | 651 | rs->rs_status |= AR5K_RXERR_PHY; |
639 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | 652 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
640 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | 653 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); |
641 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | 654 | if (!ah->ah_capabilities.cap_has_phyerr_counters) |
655 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | ||
642 | } | 656 | } |
643 | 657 | ||
644 | if (rx_status->rx_status_1 & | 658 | if (rx_status->rx_status_1 & |
@@ -649,7 +663,6 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
649 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | 663 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
650 | rs->rs_status |= AR5K_RXERR_MIC; | 664 | rs->rs_status |= AR5K_RXERR_MIC; |
651 | } | 665 | } |
652 | |||
653 | return 0; | 666 | return 0; |
654 | } | 667 | } |
655 | 668 | ||
@@ -658,29 +671,15 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
658 | */ | 671 | */ |
659 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | 672 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) |
660 | { | 673 | { |
661 | |||
662 | if (ah->ah_version != AR5K_AR5210 && | ||
663 | ah->ah_version != AR5K_AR5211 && | ||
664 | ah->ah_version != AR5K_AR5212) | ||
665 | return -ENOTSUPP; | ||
666 | |||
667 | if (ah->ah_version == AR5K_AR5212) { | 674 | if (ah->ah_version == AR5K_AR5212) { |
668 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | ||
669 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; | 675 | ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; |
670 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; | ||
671 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; | 676 | ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; |
672 | } else { | 677 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; |
673 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | 678 | } else if (ah->ah_version <= AR5K_AR5211) { |
674 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | 679 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; |
675 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; | ||
676 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | 680 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; |
677 | } | ||
678 | |||
679 | if (ah->ah_version == AR5K_AR5212) | ||
680 | ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; | ||
681 | else if (ah->ah_version <= AR5K_AR5211) | ||
682 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; | 681 | ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; |
683 | 682 | } else | |
683 | return -ENOTSUPP; | ||
684 | return 0; | 684 | return 0; |
685 | } | 685 | } |
686 | |||
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 64538fbe4167..b2adb2a281c2 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -17,28 +17,24 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * Internal RX/TX descriptor structures | 20 | * RX/TX descriptor structures |
21 | * (rX: reserved fields possibily used by future versions of the ar5k chipset) | ||
22 | */ | 21 | */ |
23 | 22 | ||
24 | /* | 23 | /* |
25 | * common hardware RX control descriptor | 24 | * Common hardware RX control descriptor |
26 | */ | 25 | */ |
27 | struct ath5k_hw_rx_ctl { | 26 | struct ath5k_hw_rx_ctl { |
28 | u32 rx_control_0; /* RX control word 0 */ | 27 | u32 rx_control_0; /* RX control word 0 */ |
29 | u32 rx_control_1; /* RX control word 1 */ | 28 | u32 rx_control_1; /* RX control word 1 */ |
30 | } __packed; | 29 | } __packed; |
31 | 30 | ||
32 | /* RX control word 0 field/sflags */ | ||
33 | #define AR5K_DESC_RX_CTL0 0x00000000 | ||
34 | |||
35 | /* RX control word 1 fields/flags */ | 31 | /* RX control word 1 fields/flags */ |
36 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff | 32 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
37 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 | 33 | #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ |
38 | 34 | ||
39 | /* | 35 | /* |
40 | * common hardware RX status descriptor | 36 | * Common hardware RX status descriptor |
41 | * 5210/11 and 5212 differ only in the flags defined below | 37 | * 5210, 5211 and 5212 differ only in the fields and flags defined below |
42 | */ | 38 | */ |
43 | struct ath5k_hw_rx_status { | 39 | struct ath5k_hw_rx_status { |
44 | u32 rx_status_0; /* RX status word 0 */ | 40 | u32 rx_status_0; /* RX status word 0 */ |
@@ -47,81 +43,69 @@ struct ath5k_hw_rx_status { | |||
47 | 43 | ||
48 | /* 5210/5211 */ | 44 | /* 5210/5211 */ |
49 | /* RX status word 0 fields/flags */ | 45 | /* RX status word 0 fields/flags */ |
50 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 46 | #define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ |
51 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 | 47 | #define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ |
52 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 | 48 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210 0x00004000 /* [5210] receive on ant 1 */ |
49 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 /* reception rate */ | ||
53 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | 50 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 |
54 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 | 51 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 /* rssi */ |
55 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 | 52 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 |
56 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 | 53 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211 0x38000000 /* [5211] receive antenna */ |
57 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 | 54 | #define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211_S 27 |
58 | 55 | ||
59 | /* RX status word 1 fields/flags */ | 56 | /* RX status word 1 fields/flags */ |
60 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 | 57 | #define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ |
61 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 58 | #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* reception success */ |
62 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 59 | #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ |
63 | #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 | 60 | #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 0x00000008 /* [5210] FIFO overrun */ |
64 | #define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 | 61 | #define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 /* decyption CRC failure */ |
65 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 | 62 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 /* PHY error */ |
66 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 | 63 | #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 |
67 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | 64 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ |
68 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 | 65 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 /* decyption key index */ |
69 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 | 66 | #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 |
70 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 | 67 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 /* 13 bit of TSF */ |
71 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 | 68 | #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 |
72 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 | 69 | #define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 /* key cache miss */ |
73 | 70 | ||
74 | /* 5212 */ | 71 | /* 5212 */ |
75 | /* RX status word 0 fields/flags */ | 72 | /* RX status word 0 fields/flags */ |
76 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff | 73 | #define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff /* RX data length */ |
77 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 | 74 | #define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 /* more desc for this frame */ |
78 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 | 75 | #define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 /* decompression CRC error */ |
79 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 | 76 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 /* reception rate */ |
80 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 | 77 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 |
81 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 | 78 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 /* rssi */ |
82 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 | 79 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 |
83 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 | 80 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 /* receive antenna */ |
84 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 | 81 | #define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 |
85 | 82 | ||
86 | /* RX status word 1 fields/flags */ | 83 | /* RX status word 1 fields/flags */ |
87 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 | 84 | #define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 /* descriptor complete */ |
88 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 | 85 | #define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 /* frame reception success */ |
89 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 | 86 | #define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 /* CRC error */ |
90 | #define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 | 87 | #define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 /* decryption CRC failure */ |
91 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 | 88 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 /* PHY error */ |
92 | #define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 | 89 | #define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 /* MIC decrypt error */ |
93 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 | 90 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 /* key index valid */ |
94 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 | 91 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 /* decryption key index */ |
95 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 | 92 | #define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 |
96 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 | 93 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 /* first 15bit of the TSF */ |
97 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 | 94 | #define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 |
98 | #define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 | 95 | #define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 /* key cache miss */ |
99 | 96 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE 0x0000ff00 /* phy error code overlays key index and valid fields */ | |
100 | /* | 97 | #define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE_S 8 |
101 | * common hardware RX error descriptor | ||
102 | */ | ||
103 | struct ath5k_hw_rx_error { | ||
104 | u32 rx_error_0; /* RX status word 0 */ | ||
105 | u32 rx_error_1; /* RX status word 1 */ | ||
106 | } __packed; | ||
107 | |||
108 | /* RX error word 0 fields/flags */ | ||
109 | #define AR5K_RX_DESC_ERROR0 0x00000000 | ||
110 | |||
111 | /* RX error word 1 fields/flags */ | ||
112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | ||
113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | ||
114 | 98 | ||
115 | /** | 99 | /** |
116 | * enum ath5k_phy_error_code - PHY Error codes | 100 | * enum ath5k_phy_error_code - PHY Error codes |
117 | */ | 101 | */ |
118 | enum ath5k_phy_error_code { | 102 | enum ath5k_phy_error_code { |
119 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ | 103 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ |
120 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ | 104 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ |
121 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ | 105 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ |
122 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ | 106 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ |
123 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ | 107 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ |
124 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ | 108 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ |
125 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | 109 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ |
126 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | 110 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ |
127 | /* these are specific to the 5212 */ | 111 | /* these are specific to the 5212 */ |
@@ -148,112 +132,111 @@ struct ath5k_hw_2w_tx_ctl { | |||
148 | } __packed; | 132 | } __packed; |
149 | 133 | ||
150 | /* TX control word 0 fields/flags */ | 134 | /* TX control word 0 fields/flags */ |
151 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 135 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
152 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ | 136 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210 0x0003f000 /* [5210] header length */ |
153 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 | 137 | #define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210_S 12 |
154 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 | 138 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 /* tx rate */ |
155 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 | 139 | #define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 |
156 | #define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 | 140 | #define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ |
157 | #define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 | 141 | #define AR5K_2W_TX_DESC_CTL0_LONG_PACKET_5210 0x00800000 /* [5210] long packet */ |
158 | #define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ | 142 | #define AR5K_2W_TX_DESC_CTL0_VEOL_5211 0x00800000 /* [5211] virtual end-of-list */ |
159 | #define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ | 143 | #define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ |
160 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ | 144 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 /* [5210] antenna selection */ |
161 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 | 145 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 /* [5211] antenna selection */ |
162 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 | ||
163 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 | ||
164 | |||
165 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ | 146 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ |
166 | (ah->ah_version == AR5K_AR5210 ? \ | 147 | (ah->ah_version == AR5K_AR5210 ? \ |
167 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ | 148 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ |
168 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) | 149 | AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) |
169 | |||
170 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | 150 | #define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 |
171 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 | 151 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210 0x1c000000 /* [5210] frame type */ |
172 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | 152 | #define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210_S 26 |
153 | #define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ | ||
154 | #define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* key is valid */ | ||
173 | 155 | ||
174 | /* TX control word 1 fields/flags */ | 156 | /* TX control word 1 fields/flags */ |
175 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff | 157 | #define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
176 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 | 158 | #define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ |
177 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 | 159 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 0x0007e000 /* [5210] key table index */ |
178 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 | 160 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211 0x000fe000 /* [5211] key table index */ |
179 | 161 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX \ | |
180 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ | ||
181 | (ah->ah_version == AR5K_AR5210 ? \ | 162 | (ah->ah_version == AR5K_AR5210 ? \ |
182 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ | 163 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5210 : \ |
183 | AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) | 164 | AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_5211) |
184 | 165 | #define AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX_S 13 | |
185 | #define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | 166 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211 0x00700000 /* [5211] frame type */ |
186 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ | 167 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211_S 20 |
187 | #define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 | 168 | #define AR5K_2W_TX_DESC_CTL1_NOACK_5211 0x00800000 /* [5211] no ACK */ |
188 | #define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ | 169 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210 0xfff80000 /* [5210] lower 13 bit of duration */ |
189 | #define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ | ||
190 | 170 | ||
191 | /* Frame types */ | 171 | /* Frame types */ |
192 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 | 172 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0 |
193 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 | 173 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 1 |
194 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 | 174 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 2 |
195 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c | 175 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 3 |
196 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 | 176 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_BEACON 3 |
177 | #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 | ||
178 | #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 | ||
197 | 179 | ||
198 | /* | 180 | /* |
199 | * 5212 hardware 4-word TX control descriptor | 181 | * 5212 hardware 4-word TX control descriptor |
200 | */ | 182 | */ |
201 | struct ath5k_hw_4w_tx_ctl { | 183 | struct ath5k_hw_4w_tx_ctl { |
202 | u32 tx_control_0; /* TX control word 0 */ | 184 | u32 tx_control_0; /* TX control word 0 */ |
185 | u32 tx_control_1; /* TX control word 1 */ | ||
186 | u32 tx_control_2; /* TX control word 2 */ | ||
187 | u32 tx_control_3; /* TX control word 3 */ | ||
188 | } __packed; | ||
203 | 189 | ||
204 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff | 190 | /* TX control word 0 fields/flags */ |
205 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 | 191 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
192 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 /* transmit power */ | ||
206 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 | 193 | #define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 |
207 | #define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 | 194 | #define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 /* RTS/CTS enable */ |
208 | #define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 | 195 | #define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 /* virtual end-of-list */ |
209 | #define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 | 196 | #define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 /* clear destination mask */ |
210 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 | 197 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 /* TX antenna selection */ |
211 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 | 198 | #define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 |
212 | #define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 | 199 | #define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 /* TX interrupt request */ |
213 | #define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 | 200 | #define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 /* destination index valid */ |
214 | #define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 | 201 | #define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 /* precede frame with CTS */ |
215 | |||
216 | u32 tx_control_1; /* TX control word 1 */ | ||
217 | 202 | ||
218 | #define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff | 203 | /* TX control word 1 fields/flags */ |
219 | #define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 | 204 | #define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
220 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 | 205 | #define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 /* more desc for this frame */ |
221 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 | 206 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX 0x000fe000 /* destination table index */ |
222 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 | 207 | #define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX_S 13 |
208 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 /* frame type */ | ||
223 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 | 209 | #define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 |
224 | #define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 | 210 | #define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 /* no ACK */ |
225 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 | 211 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 /* compression processing */ |
226 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 | 212 | #define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 |
227 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 | 213 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 /* length of frame IV */ |
228 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 | 214 | #define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 |
229 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 | 215 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 /* length of frame ICV */ |
230 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 | 216 | #define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 |
231 | 217 | ||
232 | u32 tx_control_2; /* TX control word 2 */ | 218 | /* TX control word 2 fields/flags */ |
233 | 219 | #define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff /* RTS/CTS duration */ | |
234 | #define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff | 220 | #define AR5K_4W_TX_DESC_CTL2_DURATION_UPD_EN 0x00008000 /* frame duration update */ |
235 | #define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 | 221 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 /* series 0 max attempts */ |
236 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 | 222 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 |
237 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 | 223 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 /* series 1 max attempts */ |
238 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 | 224 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 |
239 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 | 225 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 /* series 2 max attempts */ |
240 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 | 226 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 |
241 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 | 227 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 /* series 3 max attempts */ |
242 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 | 228 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 |
243 | #define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 | 229 | |
244 | 230 | /* TX control word 3 fields/flags */ | |
245 | u32 tx_control_3; /* TX control word 3 */ | 231 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f /* series 0 tx rate */ |
246 | 232 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 /* series 1 tx rate */ | |
247 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f | ||
248 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 | ||
249 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 | 233 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 |
250 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 | 234 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 /* series 2 tx rate */ |
251 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 | 235 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 |
252 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 | 236 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 /* series 3 tx rate */ |
253 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 | 237 | #define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 |
254 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 | 238 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ |
255 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 | 239 | #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 |
256 | } __packed; | ||
257 | 240 | ||
258 | /* | 241 | /* |
259 | * Common TX status descriptor | 242 | * Common TX status descriptor |
@@ -264,37 +247,34 @@ struct ath5k_hw_tx_status { | |||
264 | } __packed; | 247 | } __packed; |
265 | 248 | ||
266 | /* TX status word 0 fields/flags */ | 249 | /* TX status word 0 fields/flags */ |
267 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 | 250 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ |
268 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 | 251 | #define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 /* excessive retries */ |
269 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 | 252 | #define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 /* FIFO underrun */ |
270 | #define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 | 253 | #define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 /* TX filter indication */ |
271 | /*??? | 254 | /* according to the HAL sources the spec has short/long retry counts reversed. |
272 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 | 255 | * we have it reversed to the HAL sources as well, for 5210 and 5211. |
273 | #define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 | 256 | * For 5212 these fields are defined as RTS_FAIL_COUNT and DATA_FAIL_COUNT, |
274 | */ | 257 | * but used respectively as SHORT and LONG retry count in the code later. This |
275 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 | 258 | * is consistent with the definitions here... TODO: check */ |
259 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 /* short retry count */ | ||
276 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 | 260 | #define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 |
277 | /*??? | 261 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 /* long retry count */ |
278 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 | ||
279 | #define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 | ||
280 | */ | ||
281 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 | ||
282 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 | 262 | #define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 |
283 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 | 263 | #define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5211 0x0000f000 /* [5211+] virtual collision count */ |
284 | #define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 | 264 | #define AR5K_DESC_TX_STATUS0_VIRTCOLL_CT_5212_S 12 |
285 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 | 265 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 /* TX timestamp */ |
286 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 | 266 | #define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 |
287 | 267 | ||
288 | /* TX status word 1 fields/flags */ | 268 | /* TX status word 1 fields/flags */ |
289 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 | 269 | #define AR5K_DESC_TX_STATUS1_DONE 0x00000001 /* descriptor complete */ |
290 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe | 270 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe /* TX sequence number */ |
291 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 | 271 | #define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 |
292 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 | 272 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 /* signal strength of ACK */ |
293 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 | 273 | #define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 |
294 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 | 274 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212 0x00600000 /* [5212] final TX attempt series ix */ |
295 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 | 275 | #define AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212_S 21 |
296 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 | 276 | #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ |
297 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 | 277 | #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ |
298 | 278 | ||
299 | /* | 279 | /* |
300 | * 5210/5211 hardware TX descriptor | 280 | * 5210/5211 hardware TX descriptor |
@@ -313,18 +293,15 @@ struct ath5k_hw_5212_tx_desc { | |||
313 | } __packed; | 293 | } __packed; |
314 | 294 | ||
315 | /* | 295 | /* |
316 | * common hardware RX descriptor | 296 | * Common hardware RX descriptor |
317 | */ | 297 | */ |
318 | struct ath5k_hw_all_rx_desc { | 298 | struct ath5k_hw_all_rx_desc { |
319 | struct ath5k_hw_rx_ctl rx_ctl; | 299 | struct ath5k_hw_rx_ctl rx_ctl; |
320 | union { | 300 | struct ath5k_hw_rx_status rx_stat; |
321 | struct ath5k_hw_rx_status rx_stat; | ||
322 | struct ath5k_hw_rx_error rx_err; | ||
323 | } u; | ||
324 | } __packed; | 301 | } __packed; |
325 | 302 | ||
326 | /* | 303 | /* |
327 | * Atheros hardware descriptor | 304 | * Atheros hardware DMA descriptor |
328 | * This is read and written to by the hardware | 305 | * This is read and written to by the hardware |
329 | */ | 306 | */ |
330 | struct ath5k_desc { | 307 | struct ath5k_desc { |
@@ -346,4 +323,3 @@ struct ath5k_desc { | |||
346 | #define AR5K_TXDESC_CTSENA 0x0008 | 323 | #define AR5K_TXDESC_CTSENA 0x0008 |
347 | #define AR5K_TXDESC_INTREQ 0x0010 | 324 | #define AR5K_TXDESC_INTREQ 0x0010 |
348 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ | 325 | #define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ |
349 | |||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index dd112be218ab..973ae4f49f35 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -32,7 +32,8 @@ ath9k_hw-y:= \ | |||
32 | mac.o \ | 32 | mac.o \ |
33 | ar9002_mac.o \ | 33 | ar9002_mac.o \ |
34 | ar9003_mac.o \ | 34 | ar9003_mac.o \ |
35 | ar9003_eeprom.o | 35 | ar9003_eeprom.o \ |
36 | ar9003_paprd.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 38 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
38 | 39 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 3da820ffc65e..cc648b6ae31c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2010 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,8 +17,99 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | 19 | ||
20 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 20 | struct ani_ofdm_level_entry { |
21 | struct ath9k_channel *chan) | 21 | int spur_immunity_level; |
22 | int fir_step_level; | ||
23 | int ofdm_weak_signal_on; | ||
24 | }; | ||
25 | |||
26 | /* values here are relative to the INI */ | ||
27 | |||
28 | /* | ||
29 | * Legend: | ||
30 | * | ||
31 | * SI: Spur immunity | ||
32 | * FS: FIR Step | ||
33 | * WS: OFDM / CCK Weak Signal detection | ||
34 | * MRC-CCK: Maximal Ratio Combining for CCK | ||
35 | */ | ||
36 | |||
37 | static const struct ani_ofdm_level_entry ofdm_level_table[] = { | ||
38 | /* SI FS WS */ | ||
39 | { 0, 0, 1 }, /* lvl 0 */ | ||
40 | { 1, 1, 1 }, /* lvl 1 */ | ||
41 | { 2, 2, 1 }, /* lvl 2 */ | ||
42 | { 3, 2, 1 }, /* lvl 3 (default) */ | ||
43 | { 4, 3, 1 }, /* lvl 4 */ | ||
44 | { 5, 4, 1 }, /* lvl 5 */ | ||
45 | { 6, 5, 1 }, /* lvl 6 */ | ||
46 | { 7, 6, 1 }, /* lvl 7 */ | ||
47 | { 7, 7, 1 }, /* lvl 8 */ | ||
48 | { 7, 8, 0 } /* lvl 9 */ | ||
49 | }; | ||
50 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | ||
51 | (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) | ||
52 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ | ||
53 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) | ||
54 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ | ||
55 | 3 /* default level - matches the INI settings */ | ||
56 | |||
57 | /* | ||
58 | * MRC (Maximal Ratio Combining) has always been used with multi-antenna ofdm. | ||
59 | * With OFDM for single stream you just add up all antenna inputs, you're | ||
60 | * only interested in what you get after FFT. Signal aligment is also not | ||
61 | * required for OFDM because any phase difference adds up in the frequency | ||
62 | * domain. | ||
63 | * | ||
64 | * MRC requires extra work for use with CCK. You need to align the antenna | ||
65 | * signals from the different antenna before you can add the signals together. | ||
66 | * You need aligment of signals as CCK is in time domain, so addition can cancel | ||
67 | * your signal completely if phase is 180 degrees (think of adding sine waves). | ||
68 | * You also need to remove noise before the addition and this is where ANI | ||
69 | * MRC CCK comes into play. One of the antenna inputs may be stronger but | ||
70 | * lower SNR, so just adding after alignment can be dangerous. | ||
71 | * | ||
72 | * Regardless of alignment in time, the antenna signals add constructively after | ||
73 | * FFT and improve your reception. For more information: | ||
74 | * | ||
75 | * http://en.wikipedia.org/wiki/Maximal-ratio_combining | ||
76 | */ | ||
77 | |||
78 | struct ani_cck_level_entry { | ||
79 | int fir_step_level; | ||
80 | int mrc_cck_on; | ||
81 | }; | ||
82 | |||
83 | static const struct ani_cck_level_entry cck_level_table[] = { | ||
84 | /* FS MRC-CCK */ | ||
85 | { 0, 1 }, /* lvl 0 */ | ||
86 | { 1, 1 }, /* lvl 1 */ | ||
87 | { 2, 1 }, /* lvl 2 (default) */ | ||
88 | { 3, 1 }, /* lvl 3 */ | ||
89 | { 4, 0 }, /* lvl 4 */ | ||
90 | { 5, 0 }, /* lvl 5 */ | ||
91 | { 6, 0 }, /* lvl 6 */ | ||
92 | { 7, 0 }, /* lvl 7 (only for high rssi) */ | ||
93 | { 8, 0 } /* lvl 8 (only for high rssi) */ | ||
94 | }; | ||
95 | |||
96 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | ||
97 | (sizeof(cck_level_table)/sizeof(cck_level_table[0])) | ||
98 | #define ATH9K_ANI_CCK_MAX_LEVEL \ | ||
99 | (ATH9K_ANI_CCK_NUM_LEVEL-1) | ||
100 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ | ||
101 | (ATH9K_ANI_CCK_NUM_LEVEL-3) | ||
102 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | ||
103 | 2 /* default level - matches the INI settings */ | ||
104 | |||
105 | /* Private to ani.c */ | ||
106 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | ||
107 | { | ||
108 | ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); | ||
109 | } | ||
110 | |||
111 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
112 | struct ath9k_channel *chan) | ||
22 | { | 113 | { |
23 | int i; | 114 | int i; |
24 | 115 | ||
@@ -48,7 +139,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
48 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 139 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); |
49 | } | 140 | } |
50 | 141 | ||
51 | static void ath9k_ani_restart(struct ath_hw *ah) | 142 | static void ath9k_ani_restart_old(struct ath_hw *ah) |
52 | { | 143 | { |
53 | struct ar5416AniState *aniState; | 144 | struct ar5416AniState *aniState; |
54 | struct ath_common *common = ath9k_hw_common(ah); | 145 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -96,7 +187,42 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
96 | aniState->cckPhyErrCount = 0; | 187 | aniState->cckPhyErrCount = 0; |
97 | } | 188 | } |
98 | 189 | ||
99 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | 190 | static void ath9k_ani_restart_new(struct ath_hw *ah) |
191 | { | ||
192 | struct ar5416AniState *aniState; | ||
193 | struct ath_common *common = ath9k_hw_common(ah); | ||
194 | |||
195 | if (!DO_ANI(ah)) | ||
196 | return; | ||
197 | |||
198 | aniState = ah->curani; | ||
199 | aniState->listenTime = 0; | ||
200 | |||
201 | aniState->ofdmPhyErrBase = 0; | ||
202 | aniState->cckPhyErrBase = 0; | ||
203 | |||
204 | ath_print(common, ATH_DBG_ANI, | ||
205 | "Writing ofdmbase=%08x cckbase=%08x\n", | ||
206 | aniState->ofdmPhyErrBase, | ||
207 | aniState->cckPhyErrBase); | ||
208 | |||
209 | ENABLE_REGWRITE_BUFFER(ah); | ||
210 | |||
211 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
212 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
213 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
214 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
215 | |||
216 | REGWRITE_BUFFER_FLUSH(ah); | ||
217 | DISABLE_REGWRITE_BUFFER(ah); | ||
218 | |||
219 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
220 | |||
221 | aniState->ofdmPhyErrCount = 0; | ||
222 | aniState->cckPhyErrCount = 0; | ||
223 | } | ||
224 | |||
225 | static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | ||
100 | { | 226 | { |
101 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 227 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
102 | struct ar5416AniState *aniState; | 228 | struct ar5416AniState *aniState; |
@@ -168,7 +294,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | |||
168 | } | 294 | } |
169 | } | 295 | } |
170 | 296 | ||
171 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | 297 | static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) |
172 | { | 298 | { |
173 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 299 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
174 | struct ar5416AniState *aniState; | 300 | struct ar5416AniState *aniState; |
@@ -206,7 +332,125 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | |||
206 | } | 332 | } |
207 | } | 333 | } |
208 | 334 | ||
209 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | 335 | /* Adjust the OFDM Noise Immunity Level */ |
336 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | ||
337 | { | ||
338 | struct ar5416AniState *aniState = ah->curani; | ||
339 | struct ath_common *common = ath9k_hw_common(ah); | ||
340 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
341 | const struct ani_cck_level_entry *entry_cck; | ||
342 | |||
343 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
344 | |||
345 | ath_print(common, ATH_DBG_ANI, | ||
346 | "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | ||
347 | aniState->ofdmNoiseImmunityLevel, | ||
348 | immunityLevel, aniState->noiseFloor, | ||
349 | aniState->rssiThrLow, aniState->rssiThrHigh); | ||
350 | |||
351 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | ||
352 | |||
353 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | ||
354 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | ||
355 | |||
356 | if (aniState->spurImmunityLevel != entry_ofdm->spur_immunity_level) | ||
357 | ath9k_hw_ani_control(ah, | ||
358 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL, | ||
359 | entry_ofdm->spur_immunity_level); | ||
360 | |||
361 | if (aniState->firstepLevel != entry_ofdm->fir_step_level && | ||
362 | entry_ofdm->fir_step_level >= entry_cck->fir_step_level) | ||
363 | ath9k_hw_ani_control(ah, | ||
364 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
365 | entry_ofdm->fir_step_level); | ||
366 | |||
367 | if ((ah->opmode != NL80211_IFTYPE_STATION && | ||
368 | ah->opmode != NL80211_IFTYPE_ADHOC) || | ||
369 | aniState->noiseFloor <= aniState->rssiThrHigh) { | ||
370 | if (aniState->ofdmWeakSigDetectOff) | ||
371 | /* force on ofdm weak sig detect */ | ||
372 | ath9k_hw_ani_control(ah, | ||
373 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
374 | true); | ||
375 | else if (aniState->ofdmWeakSigDetectOff == | ||
376 | entry_ofdm->ofdm_weak_signal_on) | ||
377 | ath9k_hw_ani_control(ah, | ||
378 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
379 | entry_ofdm->ofdm_weak_signal_on); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | ||
384 | { | ||
385 | struct ar5416AniState *aniState; | ||
386 | |||
387 | if (!DO_ANI(ah)) | ||
388 | return; | ||
389 | |||
390 | aniState = ah->curani; | ||
391 | |||
392 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | ||
393 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * Set the ANI settings to match an CCK level. | ||
398 | */ | ||
399 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | ||
400 | { | ||
401 | struct ar5416AniState *aniState = ah->curani; | ||
402 | struct ath_common *common = ath9k_hw_common(ah); | ||
403 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
404 | const struct ani_cck_level_entry *entry_cck; | ||
405 | |||
406 | aniState->noiseFloor = BEACON_RSSI(ah); | ||
407 | ath_print(common, ATH_DBG_ANI, | ||
408 | "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | ||
409 | aniState->cckNoiseImmunityLevel, immunityLevel, | ||
410 | aniState->noiseFloor, aniState->rssiThrLow, | ||
411 | aniState->rssiThrHigh); | ||
412 | |||
413 | if ((ah->opmode == NL80211_IFTYPE_STATION || | ||
414 | ah->opmode == NL80211_IFTYPE_ADHOC) && | ||
415 | aniState->noiseFloor <= aniState->rssiThrLow && | ||
416 | immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) | ||
417 | immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; | ||
418 | |||
419 | aniState->cckNoiseImmunityLevel = immunityLevel; | ||
420 | |||
421 | entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; | ||
422 | entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; | ||
423 | |||
424 | if (aniState->firstepLevel != entry_cck->fir_step_level && | ||
425 | entry_cck->fir_step_level >= entry_ofdm->fir_step_level) | ||
426 | ath9k_hw_ani_control(ah, | ||
427 | ATH9K_ANI_FIRSTEP_LEVEL, | ||
428 | entry_cck->fir_step_level); | ||
429 | |||
430 | /* Skip MRC CCK for pre AR9003 families */ | ||
431 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
432 | return; | ||
433 | |||
434 | if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) | ||
435 | ath9k_hw_ani_control(ah, | ||
436 | ATH9K_ANI_MRC_CCK, | ||
437 | entry_cck->mrc_cck_on); | ||
438 | } | ||
439 | |||
440 | static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) | ||
441 | { | ||
442 | struct ar5416AniState *aniState; | ||
443 | |||
444 | if (!DO_ANI(ah)) | ||
445 | return; | ||
446 | |||
447 | aniState = ah->curani; | ||
448 | |||
449 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | ||
450 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | ||
451 | } | ||
452 | |||
453 | static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | ||
210 | { | 454 | { |
211 | struct ar5416AniState *aniState; | 455 | struct ar5416AniState *aniState; |
212 | int32_t rssi; | 456 | int32_t rssi; |
@@ -259,9 +503,53 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | |||
259 | } | 503 | } |
260 | } | 504 | } |
261 | 505 | ||
506 | /* | ||
507 | * only lower either OFDM or CCK errors per turn | ||
508 | * we lower the other one next time | ||
509 | */ | ||
510 | static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | ||
511 | { | ||
512 | struct ar5416AniState *aniState; | ||
513 | |||
514 | aniState = ah->curani; | ||
515 | |||
516 | /* lower OFDM noise immunity */ | ||
517 | if (aniState->ofdmNoiseImmunityLevel > 0 && | ||
518 | (aniState->ofdmsTurn || aniState->cckNoiseImmunityLevel == 0)) { | ||
519 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel - 1); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* lower CCK noise immunity */ | ||
524 | if (aniState->cckNoiseImmunityLevel > 0) | ||
525 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); | ||
526 | } | ||
527 | |||
528 | static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | ||
529 | { | ||
530 | struct ath9k_channel *chan = ah->curchan; | ||
531 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
532 | u8 clockrate; /* in MHz */ | ||
533 | |||
534 | if (!ah->curchan) /* should really check for CCK instead */ | ||
535 | clockrate = ATH9K_CLOCK_RATE_CCK; | ||
536 | else if (conf->channel->band == IEEE80211_BAND_2GHZ) | ||
537 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; | ||
538 | else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | ||
539 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | ||
540 | else | ||
541 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; | ||
542 | |||
543 | if (conf_is_ht40(conf)) | ||
544 | return clockrate * 2; | ||
545 | |||
546 | return clockrate * 2; | ||
547 | } | ||
548 | |||
262 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | 549 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) |
263 | { | 550 | { |
264 | struct ar5416AniState *aniState; | 551 | struct ar5416AniState *aniState; |
552 | struct ath_common *common = ath9k_hw_common(ah); | ||
265 | u32 txFrameCount, rxFrameCount, cycleCount; | 553 | u32 txFrameCount, rxFrameCount, cycleCount; |
266 | int32_t listenTime; | 554 | int32_t listenTime; |
267 | 555 | ||
@@ -271,15 +559,31 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | |||
271 | 559 | ||
272 | aniState = ah->curani; | 560 | aniState = ah->curani; |
273 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | 561 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { |
274 | |||
275 | listenTime = 0; | 562 | listenTime = 0; |
276 | ah->stats.ast_ani_lzero++; | 563 | ah->stats.ast_ani_lzero++; |
564 | ath_print(common, ATH_DBG_ANI, | ||
565 | "1st call: aniState->cycleCount=%d\n", | ||
566 | aniState->cycleCount); | ||
277 | } else { | 567 | } else { |
278 | int32_t ccdelta = cycleCount - aniState->cycleCount; | 568 | int32_t ccdelta = cycleCount - aniState->cycleCount; |
279 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | 569 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; |
280 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | 570 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; |
281 | listenTime = (ccdelta - rfdelta - tfdelta) / 44000; | 571 | int32_t clock_rate; |
572 | |||
573 | /* | ||
574 | * convert HW counter values to ms using mode | ||
575 | * specifix clock rate | ||
576 | */ | ||
577 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; | ||
578 | |||
579 | listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; | ||
580 | |||
581 | ath_print(common, ATH_DBG_ANI, | ||
582 | "cyclecount=%d, rfcount=%d, " | ||
583 | "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", | ||
584 | ccdelta, rfdelta, tfdelta, listenTime, clock_rate); | ||
282 | } | 585 | } |
586 | |||
283 | aniState->cycleCount = cycleCount; | 587 | aniState->cycleCount = cycleCount; |
284 | aniState->txFrameCount = txFrameCount; | 588 | aniState->txFrameCount = txFrameCount; |
285 | aniState->rxFrameCount = rxFrameCount; | 589 | aniState->rxFrameCount = rxFrameCount; |
@@ -287,7 +591,7 @@ static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | |||
287 | return listenTime; | 591 | return listenTime; |
288 | } | 592 | } |
289 | 593 | ||
290 | void ath9k_ani_reset(struct ath_hw *ah) | 594 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) |
291 | { | 595 | { |
292 | struct ar5416AniState *aniState; | 596 | struct ar5416AniState *aniState; |
293 | struct ath9k_channel *chan = ah->curchan; | 597 | struct ath9k_channel *chan = ah->curchan; |
@@ -340,7 +644,7 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
340 | ah->curani->cckTrigLow = | 644 | ah->curani->cckTrigLow = |
341 | ah->config.cck_trig_low; | 645 | ah->config.cck_trig_low; |
342 | } | 646 | } |
343 | ath9k_ani_restart(ah); | 647 | ath9k_ani_restart_old(ah); |
344 | return; | 648 | return; |
345 | } | 649 | } |
346 | 650 | ||
@@ -362,7 +666,7 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
362 | 666 | ||
363 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | 667 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
364 | ~ATH9K_RX_FILTER_PHYERR); | 668 | ~ATH9K_RX_FILTER_PHYERR); |
365 | ath9k_ani_restart(ah); | 669 | ath9k_ani_restart_old(ah); |
366 | 670 | ||
367 | ENABLE_REGWRITE_BUFFER(ah); | 671 | ENABLE_REGWRITE_BUFFER(ah); |
368 | 672 | ||
@@ -373,8 +677,102 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
373 | DISABLE_REGWRITE_BUFFER(ah); | 677 | DISABLE_REGWRITE_BUFFER(ah); |
374 | } | 678 | } |
375 | 679 | ||
376 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 680 | /* |
377 | struct ath9k_channel *chan) | 681 | * Restore the ANI parameters in the HAL and reset the statistics. |
682 | * This routine should be called for every hardware reset and for | ||
683 | * every channel change. | ||
684 | */ | ||
685 | static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | ||
686 | { | ||
687 | struct ar5416AniState *aniState = ah->curani; | ||
688 | struct ath9k_channel *chan = ah->curchan; | ||
689 | struct ath_common *common = ath9k_hw_common(ah); | ||
690 | |||
691 | if (!DO_ANI(ah)) | ||
692 | return; | ||
693 | |||
694 | BUG_ON(aniState == NULL); | ||
695 | ah->stats.ast_ani_reset++; | ||
696 | |||
697 | /* only allow a subset of functions in AP mode */ | ||
698 | if (ah->opmode == NL80211_IFTYPE_AP) { | ||
699 | if (IS_CHAN_2GHZ(chan)) { | ||
700 | ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | | ||
701 | ATH9K_ANI_FIRSTEP_LEVEL); | ||
702 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
703 | ah->ani_function |= ATH9K_ANI_MRC_CCK; | ||
704 | } else | ||
705 | ah->ani_function = 0; | ||
706 | } | ||
707 | |||
708 | /* always allow mode (on/off) to be controlled */ | ||
709 | ah->ani_function |= ATH9K_ANI_MODE; | ||
710 | |||
711 | if (is_scanning || | ||
712 | (ah->opmode != NL80211_IFTYPE_STATION && | ||
713 | ah->opmode != NL80211_IFTYPE_ADHOC)) { | ||
714 | /* | ||
715 | * If we're scanning or in AP mode, the defaults (ini) | ||
716 | * should be in place. For an AP we assume the historical | ||
717 | * levels for this channel are probably outdated so start | ||
718 | * from defaults instead. | ||
719 | */ | ||
720 | if (aniState->ofdmNoiseImmunityLevel != | ||
721 | ATH9K_ANI_OFDM_DEF_LEVEL || | ||
722 | aniState->cckNoiseImmunityLevel != | ||
723 | ATH9K_ANI_CCK_DEF_LEVEL) { | ||
724 | ath_print(common, ATH_DBG_ANI, | ||
725 | "Restore defaults: opmode %u " | ||
726 | "chan %d Mhz/0x%x is_scanning=%d " | ||
727 | "ofdm:%d cck:%d\n", | ||
728 | ah->opmode, | ||
729 | chan->channel, | ||
730 | chan->channelFlags, | ||
731 | is_scanning, | ||
732 | aniState->ofdmNoiseImmunityLevel, | ||
733 | aniState->cckNoiseImmunityLevel); | ||
734 | |||
735 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); | ||
736 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); | ||
737 | } | ||
738 | } else { | ||
739 | /* | ||
740 | * restore historical levels for this channel | ||
741 | */ | ||
742 | ath_print(common, ATH_DBG_ANI, | ||
743 | "Restore history: opmode %u " | ||
744 | "chan %d Mhz/0x%x is_scanning=%d " | ||
745 | "ofdm:%d cck:%d\n", | ||
746 | ah->opmode, | ||
747 | chan->channel, | ||
748 | chan->channelFlags, | ||
749 | is_scanning, | ||
750 | aniState->ofdmNoiseImmunityLevel, | ||
751 | aniState->cckNoiseImmunityLevel); | ||
752 | |||
753 | ath9k_hw_set_ofdm_nil(ah, | ||
754 | aniState->ofdmNoiseImmunityLevel); | ||
755 | ath9k_hw_set_cck_nil(ah, | ||
756 | aniState->cckNoiseImmunityLevel); | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * enable phy counters if hw supports or if not, enable phy | ||
761 | * interrupts (so we can count each one) | ||
762 | */ | ||
763 | ath9k_ani_restart_new(ah); | ||
764 | |||
765 | ENABLE_REGWRITE_BUFFER(ah); | ||
766 | |||
767 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
768 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
769 | |||
770 | REGWRITE_BUFFER_FLUSH(ah); | ||
771 | DISABLE_REGWRITE_BUFFER(ah); | ||
772 | } | ||
773 | |||
774 | static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | ||
775 | struct ath9k_channel *chan) | ||
378 | { | 776 | { |
379 | struct ar5416AniState *aniState; | 777 | struct ar5416AniState *aniState; |
380 | struct ath_common *common = ath9k_hw_common(ah); | 778 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -390,7 +788,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
390 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 788 | listenTime = ath9k_hw_ani_get_listen_time(ah); |
391 | if (listenTime < 0) { | 789 | if (listenTime < 0) { |
392 | ah->stats.ast_ani_lneg++; | 790 | ah->stats.ast_ani_lneg++; |
393 | ath9k_ani_restart(ah); | 791 | ath9k_ani_restart_old(ah); |
394 | return; | 792 | return; |
395 | } | 793 | } |
396 | 794 | ||
@@ -444,21 +842,166 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
444 | aniState->cckPhyErrCount <= aniState->listenTime * | 842 | aniState->cckPhyErrCount <= aniState->listenTime * |
445 | aniState->cckTrigLow / 1000) | 843 | aniState->cckTrigLow / 1000) |
446 | ath9k_hw_ani_lower_immunity(ah); | 844 | ath9k_hw_ani_lower_immunity(ah); |
447 | ath9k_ani_restart(ah); | 845 | ath9k_ani_restart_old(ah); |
448 | } else if (aniState->listenTime > ah->aniperiod) { | 846 | } else if (aniState->listenTime > ah->aniperiod) { |
449 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | 847 | if (aniState->ofdmPhyErrCount > aniState->listenTime * |
450 | aniState->ofdmTrigHigh / 1000) { | 848 | aniState->ofdmTrigHigh / 1000) { |
451 | ath9k_hw_ani_ofdm_err_trigger(ah); | 849 | ath9k_hw_ani_ofdm_err_trigger_old(ah); |
452 | ath9k_ani_restart(ah); | 850 | ath9k_ani_restart_old(ah); |
453 | } else if (aniState->cckPhyErrCount > | 851 | } else if (aniState->cckPhyErrCount > |
454 | aniState->listenTime * aniState->cckTrigHigh / | 852 | aniState->listenTime * aniState->cckTrigHigh / |
455 | 1000) { | 853 | 1000) { |
456 | ath9k_hw_ani_cck_err_trigger(ah); | 854 | ath9k_hw_ani_cck_err_trigger_old(ah); |
457 | ath9k_ani_restart(ah); | 855 | ath9k_ani_restart_old(ah); |
856 | } | ||
857 | } | ||
858 | } | ||
859 | |||
860 | static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | ||
861 | struct ath9k_channel *chan) | ||
862 | { | ||
863 | struct ar5416AniState *aniState; | ||
864 | struct ath_common *common = ath9k_hw_common(ah); | ||
865 | int32_t listenTime; | ||
866 | u32 phyCnt1, phyCnt2; | ||
867 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
868 | u32 ofdmPhyErrRate, cckPhyErrRate; | ||
869 | |||
870 | if (!DO_ANI(ah)) | ||
871 | return; | ||
872 | |||
873 | aniState = ah->curani; | ||
874 | if (WARN_ON(!aniState)) | ||
875 | return; | ||
876 | |||
877 | listenTime = ath9k_hw_ani_get_listen_time(ah); | ||
878 | if (listenTime <= 0) { | ||
879 | ah->stats.ast_ani_lneg++; | ||
880 | /* restart ANI period if listenTime is invalid */ | ||
881 | ath_print(common, ATH_DBG_ANI, | ||
882 | "listenTime=%d - on new ani monitor\n", | ||
883 | listenTime); | ||
884 | ath9k_ani_restart_new(ah); | ||
885 | return; | ||
886 | } | ||
887 | |||
888 | aniState->listenTime += listenTime; | ||
889 | |||
890 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
891 | |||
892 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
893 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
894 | |||
895 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
896 | phyCnt2 < aniState->cckPhyErrBase) { | ||
897 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
898 | ath_print(common, ATH_DBG_ANI, | ||
899 | "phyCnt1 0x%x, resetting " | ||
900 | "counter value to 0x%x\n", | ||
901 | phyCnt1, | ||
902 | aniState->ofdmPhyErrBase); | ||
903 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
904 | aniState->ofdmPhyErrBase); | ||
905 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
906 | AR_PHY_ERR_OFDM_TIMING); | ||
907 | } | ||
908 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
909 | ath_print(common, ATH_DBG_ANI, | ||
910 | "phyCnt2 0x%x, resetting " | ||
911 | "counter value to 0x%x\n", | ||
912 | phyCnt2, | ||
913 | aniState->cckPhyErrBase); | ||
914 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
915 | aniState->cckPhyErrBase); | ||
916 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
917 | AR_PHY_ERR_CCK_TIMING); | ||
918 | } | ||
919 | return; | ||
920 | } | ||
921 | |||
922 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
923 | ah->stats.ast_ani_ofdmerrs += | ||
924 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
925 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
926 | |||
927 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
928 | ah->stats.ast_ani_cckerrs += | ||
929 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
930 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
931 | |||
932 | ath_print(common, ATH_DBG_ANI, | ||
933 | "Errors: OFDM=0x%08x-0x%08x=%d " | ||
934 | "CCK=0x%08x-0x%08x=%d\n", | ||
935 | phyCnt1, | ||
936 | aniState->ofdmPhyErrBase, | ||
937 | ofdmPhyErrCnt, | ||
938 | phyCnt2, | ||
939 | aniState->cckPhyErrBase, | ||
940 | cckPhyErrCnt); | ||
941 | |||
942 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / | ||
943 | aniState->listenTime; | ||
944 | cckPhyErrRate = aniState->cckPhyErrCount * 1000 / | ||
945 | aniState->listenTime; | ||
946 | |||
947 | ath_print(common, ATH_DBG_ANI, | ||
948 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " | ||
949 | "errs=%d/s ofdm_turn=%d\n", | ||
950 | listenTime, aniState->ofdmNoiseImmunityLevel, | ||
951 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | ||
952 | cckPhyErrRate, aniState->ofdmsTurn); | ||
953 | |||
954 | if (aniState->listenTime > 5 * ah->aniperiod) { | ||
955 | if (ofdmPhyErrRate <= aniState->ofdmTrigLow && | ||
956 | cckPhyErrRate <= aniState->cckTrigLow) { | ||
957 | ath_print(common, ATH_DBG_ANI, | ||
958 | "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " | ||
959 | "CCK:%d errs=%d/s(<%d) -> " | ||
960 | "ath9k_hw_ani_lower_immunity()\n", | ||
961 | aniState->listenTime, | ||
962 | aniState->ofdmNoiseImmunityLevel, | ||
963 | ofdmPhyErrRate, | ||
964 | aniState->ofdmTrigLow, | ||
965 | aniState->cckNoiseImmunityLevel, | ||
966 | cckPhyErrRate, | ||
967 | aniState->cckTrigLow); | ||
968 | ath9k_hw_ani_lower_immunity(ah); | ||
969 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | ||
970 | } | ||
971 | ath_print(common, ATH_DBG_ANI, | ||
972 | "1 listenTime=%d ofdm=%d/s cck=%d/s - " | ||
973 | "calling ath9k_ani_restart_new()\n", | ||
974 | aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); | ||
975 | ath9k_ani_restart_new(ah); | ||
976 | } else if (aniState->listenTime > ah->aniperiod) { | ||
977 | /* check to see if need to raise immunity */ | ||
978 | if (ofdmPhyErrRate > aniState->ofdmTrigHigh && | ||
979 | (cckPhyErrRate <= aniState->cckTrigHigh || | ||
980 | aniState->ofdmsTurn)) { | ||
981 | ath_print(common, ATH_DBG_ANI, | ||
982 | "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " | ||
983 | "ath9k_hw_ani_ofdm_err_trigger_new()\n", | ||
984 | aniState->listenTime, | ||
985 | aniState->ofdmNoiseImmunityLevel, | ||
986 | ofdmPhyErrRate, | ||
987 | aniState->ofdmTrigHigh); | ||
988 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
989 | ath9k_ani_restart_new(ah); | ||
990 | aniState->ofdmsTurn = false; | ||
991 | } else if (cckPhyErrRate > aniState->cckTrigHigh) { | ||
992 | ath_print(common, ATH_DBG_ANI, | ||
993 | "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " | ||
994 | "ath9k_hw_ani_cck_err_trigger_new()\n", | ||
995 | aniState->listenTime, | ||
996 | aniState->cckNoiseImmunityLevel, | ||
997 | cckPhyErrRate, | ||
998 | aniState->cckTrigHigh); | ||
999 | ath9k_hw_ani_cck_err_trigger_new(ah); | ||
1000 | ath9k_ani_restart_new(ah); | ||
1001 | aniState->ofdmsTurn = true; | ||
458 | } | 1002 | } |
459 | } | 1003 | } |
460 | } | 1004 | } |
461 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
462 | 1005 | ||
463 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 1006 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
464 | { | 1007 | { |
@@ -543,7 +1086,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | |||
543 | * any of the MIB counters overflow/trigger so don't assume we're | 1086 | * any of the MIB counters overflow/trigger so don't assume we're |
544 | * here because a PHY error counter triggered. | 1087 | * here because a PHY error counter triggered. |
545 | */ | 1088 | */ |
546 | void ath9k_hw_procmibevent(struct ath_hw *ah) | 1089 | static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) |
547 | { | 1090 | { |
548 | u32 phyCnt1, phyCnt2; | 1091 | u32 phyCnt1, phyCnt2; |
549 | 1092 | ||
@@ -556,8 +1099,15 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) | |||
556 | /* Clear the mib counters and save them in the stats */ | 1099 | /* Clear the mib counters and save them in the stats */ |
557 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 1100 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
558 | 1101 | ||
559 | if (!DO_ANI(ah)) | 1102 | if (!DO_ANI(ah)) { |
1103 | /* | ||
1104 | * We must always clear the interrupt cause by | ||
1105 | * resetting the phy error regs. | ||
1106 | */ | ||
1107 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
1108 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
560 | return; | 1109 | return; |
1110 | } | ||
561 | 1111 | ||
562 | /* NB: these are not reset-on-read */ | 1112 | /* NB: these are not reset-on-read */ |
563 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 1113 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
@@ -585,14 +1135,51 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) | |||
585 | * check will never be true. | 1135 | * check will never be true. |
586 | */ | 1136 | */ |
587 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | 1137 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) |
588 | ath9k_hw_ani_ofdm_err_trigger(ah); | 1138 | ath9k_hw_ani_ofdm_err_trigger_new(ah); |
589 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | 1139 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) |
590 | ath9k_hw_ani_cck_err_trigger(ah); | 1140 | ath9k_hw_ani_cck_err_trigger_old(ah); |
591 | /* NB: always restart to insure the h/w counters are reset */ | 1141 | /* NB: always restart to insure the h/w counters are reset */ |
592 | ath9k_ani_restart(ah); | 1142 | ath9k_ani_restart_old(ah); |
593 | } | 1143 | } |
594 | } | 1144 | } |
595 | EXPORT_SYMBOL(ath9k_hw_procmibevent); | 1145 | |
1146 | /* | ||
1147 | * Process a MIB interrupt. We may potentially be invoked because | ||
1148 | * any of the MIB counters overflow/trigger so don't assume we're | ||
1149 | * here because a PHY error counter triggered. | ||
1150 | */ | ||
1151 | static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | ||
1152 | { | ||
1153 | u32 phyCnt1, phyCnt2; | ||
1154 | |||
1155 | /* Reset these counters regardless */ | ||
1156 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
1157 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
1158 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | ||
1159 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | ||
1160 | |||
1161 | /* Clear the mib counters and save them in the stats */ | ||
1162 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
1163 | |||
1164 | if (!DO_ANI(ah)) { | ||
1165 | /* | ||
1166 | * We must always clear the interrupt cause by | ||
1167 | * resetting the phy error regs. | ||
1168 | */ | ||
1169 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
1170 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
1171 | return; | ||
1172 | } | ||
1173 | |||
1174 | /* NB: these are not reset-on-read */ | ||
1175 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
1176 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
1177 | |||
1178 | /* NB: always restart to insure the h/w counters are reset */ | ||
1179 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
1180 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) | ||
1181 | ath9k_ani_restart_new(ah); | ||
1182 | } | ||
596 | 1183 | ||
597 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 1184 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
598 | { | 1185 | { |
@@ -620,22 +1207,70 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
620 | 1207 | ||
621 | memset(ah->ani, 0, sizeof(ah->ani)); | 1208 | memset(ah->ani, 0, sizeof(ah->ani)); |
622 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 1209 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { |
623 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; | 1210 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { |
624 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; | 1211 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; |
625 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; | 1212 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; |
626 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; | 1213 | |
1214 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | ||
1215 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; | ||
1216 | |||
1217 | ah->ani[i].spurImmunityLevel = | ||
1218 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1219 | |||
1220 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1221 | |||
1222 | ah->ani[i].ofdmPhyErrBase = 0; | ||
1223 | ah->ani[i].cckPhyErrBase = 0; | ||
1224 | |||
1225 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1226 | ah->ani[i].mrcCCKOff = | ||
1227 | !ATH9K_ANI_ENABLE_MRC_CCK; | ||
1228 | else | ||
1229 | ah->ani[i].mrcCCKOff = true; | ||
1230 | |||
1231 | ah->ani[i].ofdmsTurn = true; | ||
1232 | } else { | ||
1233 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1234 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1235 | |||
1236 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1237 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
1238 | |||
1239 | ah->ani[i].spurImmunityLevel = | ||
1240 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | ||
1241 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | ||
1242 | |||
1243 | ah->ani[i].ofdmPhyErrBase = | ||
1244 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1245 | ah->ani[i].cckPhyErrBase = | ||
1246 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1247 | ah->ani[i].cckWeakSigThreshold = | ||
1248 | ATH9K_ANI_CCK_WEAK_SIG_THR; | ||
1249 | } | ||
1250 | |||
627 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 1251 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
628 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 1252 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
629 | ah->ani[i].ofdmWeakSigDetectOff = | 1253 | ah->ani[i].ofdmWeakSigDetectOff = |
630 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1254 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
631 | ah->ani[i].cckWeakSigThreshold = | 1255 | ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
632 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 1256 | } |
633 | ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; | 1257 | |
634 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; | 1258 | /* |
635 | ah->ani[i].ofdmPhyErrBase = | 1259 | * since we expect some ongoing maintenance on the tables, let's sanity |
636 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; | 1260 | * check here default level should not modify INI setting. |
637 | ah->ani[i].cckPhyErrBase = | 1261 | */ |
638 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; | 1262 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { |
1263 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
1264 | const struct ani_cck_level_entry *entry_cck; | ||
1265 | |||
1266 | entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; | ||
1267 | entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; | ||
1268 | |||
1269 | ah->aniperiod = ATH9K_ANI_PERIOD_NEW; | ||
1270 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; | ||
1271 | } else { | ||
1272 | ah->aniperiod = ATH9K_ANI_PERIOD_OLD; | ||
1273 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | ||
639 | } | 1274 | } |
640 | 1275 | ||
641 | ath_print(common, ATH_DBG_ANI, | 1276 | ath_print(common, ATH_DBG_ANI, |
@@ -654,7 +1289,34 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
654 | 1289 | ||
655 | ath9k_enable_mib_counters(ah); | 1290 | ath9k_enable_mib_counters(ah); |
656 | 1291 | ||
657 | ah->aniperiod = ATH9K_ANI_PERIOD; | ||
658 | if (ah->config.enable_ani) | 1292 | if (ah->config.enable_ani) |
659 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 1293 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
660 | } | 1294 | } |
1295 | |||
1296 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) | ||
1297 | { | ||
1298 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1299 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1300 | |||
1301 | priv_ops->ani_reset = ath9k_ani_reset_old; | ||
1302 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; | ||
1303 | |||
1304 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; | ||
1305 | ops->ani_monitor = ath9k_hw_ani_monitor_old; | ||
1306 | |||
1307 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); | ||
1308 | } | ||
1309 | |||
1310 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) | ||
1311 | { | ||
1312 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1313 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1314 | |||
1315 | priv_ops->ani_reset = ath9k_ani_reset_new; | ||
1316 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; | ||
1317 | |||
1318 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; | ||
1319 | ops->ani_monitor = ath9k_hw_ani_monitor_new; | ||
1320 | |||
1321 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); | ||
1322 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 3356762ea384..f4d0a4d48b37 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -23,23 +23,55 @@ | |||
23 | 23 | ||
24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
25 | 25 | ||
26 | #define ATH9K_ANI_OFDM_TRIG_HIGH 500 | 26 | /* units are errors per second */ |
27 | #define ATH9K_ANI_OFDM_TRIG_LOW 200 | 27 | #define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 |
28 | #define ATH9K_ANI_CCK_TRIG_HIGH 200 | 28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000 |
29 | #define ATH9K_ANI_CCK_TRIG_LOW 100 | 29 | |
30 | /* units are errors per second */ | ||
31 | #define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 | ||
32 | #define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 | ||
33 | |||
34 | /* units are errors per second */ | ||
35 | #define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 | ||
36 | #define ATH9K_ANI_CCK_TRIG_HIGH_NEW 600 | ||
37 | |||
38 | /* units are errors per second */ | ||
39 | #define ATH9K_ANI_CCK_TRIG_LOW_OLD 100 | ||
40 | #define ATH9K_ANI_CCK_TRIG_LOW_NEW 300 | ||
41 | |||
30 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 | 42 | #define ATH9K_ANI_NOISE_IMMUNE_LVL 4 |
31 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true | 43 | #define ATH9K_ANI_USE_OFDM_WEAK_SIG true |
32 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false | 44 | #define ATH9K_ANI_CCK_WEAK_SIG_THR false |
33 | #define ATH9K_ANI_SPUR_IMMUNE_LVL 7 | 45 | |
34 | #define ATH9K_ANI_FIRSTEP_LVL 0 | 46 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_OLD 7 |
47 | #define ATH9K_ANI_SPUR_IMMUNE_LVL_NEW 3 | ||
48 | |||
49 | #define ATH9K_ANI_FIRSTEP_LVL_OLD 0 | ||
50 | #define ATH9K_ANI_FIRSTEP_LVL_NEW 2 | ||
51 | |||
35 | #define ATH9K_ANI_RSSI_THR_HIGH 40 | 52 | #define ATH9K_ANI_RSSI_THR_HIGH 40 |
36 | #define ATH9K_ANI_RSSI_THR_LOW 7 | 53 | #define ATH9K_ANI_RSSI_THR_LOW 7 |
37 | #define ATH9K_ANI_PERIOD 100 | 54 | |
55 | #define ATH9K_ANI_PERIOD_OLD 100 | ||
56 | #define ATH9K_ANI_PERIOD_NEW 1000 | ||
57 | |||
58 | /* in ms */ | ||
59 | #define ATH9K_ANI_POLLINTERVAL_OLD 100 | ||
60 | #define ATH9K_ANI_POLLINTERVAL_NEW 1000 | ||
38 | 61 | ||
39 | #define HAL_NOISE_IMMUNE_MAX 4 | 62 | #define HAL_NOISE_IMMUNE_MAX 4 |
40 | #define HAL_SPUR_IMMUNE_MAX 7 | 63 | #define HAL_SPUR_IMMUNE_MAX 7 |
41 | #define HAL_FIRST_STEP_MAX 2 | 64 | #define HAL_FIRST_STEP_MAX 2 |
42 | 65 | ||
66 | #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 | ||
67 | #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 | ||
68 | #define ATH9K_SIG_SPUR_IMM_SETTING_MIN 0 | ||
69 | #define ATH9K_SIG_SPUR_IMM_SETTING_MAX 22 | ||
70 | |||
71 | #define ATH9K_ANI_ENABLE_MRC_CCK true | ||
72 | |||
73 | /* values here are relative to the INI */ | ||
74 | |||
43 | enum ath9k_ani_cmd { | 75 | enum ath9k_ani_cmd { |
44 | ATH9K_ANI_PRESENT = 0x1, | 76 | ATH9K_ANI_PRESENT = 0x1, |
45 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, | 77 | ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, |
@@ -49,7 +81,8 @@ enum ath9k_ani_cmd { | |||
49 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, | 81 | ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, |
50 | ATH9K_ANI_MODE = 0x40, | 82 | ATH9K_ANI_MODE = 0x40, |
51 | ATH9K_ANI_PHYERR_RESET = 0x80, | 83 | ATH9K_ANI_PHYERR_RESET = 0x80, |
52 | ATH9K_ANI_ALL = 0xff | 84 | ATH9K_ANI_MRC_CCK = 0x100, |
85 | ATH9K_ANI_ALL = 0xfff | ||
53 | }; | 86 | }; |
54 | 87 | ||
55 | struct ath9k_mib_stats { | 88 | struct ath9k_mib_stats { |
@@ -60,9 +93,31 @@ struct ath9k_mib_stats { | |||
60 | u32 beacons; | 93 | u32 beacons; |
61 | }; | 94 | }; |
62 | 95 | ||
96 | /* INI default values for ANI registers */ | ||
97 | struct ath9k_ani_default { | ||
98 | u16 m1ThreshLow; | ||
99 | u16 m2ThreshLow; | ||
100 | u16 m1Thresh; | ||
101 | u16 m2Thresh; | ||
102 | u16 m2CountThr; | ||
103 | u16 m2CountThrLow; | ||
104 | u16 m1ThreshLowExt; | ||
105 | u16 m2ThreshLowExt; | ||
106 | u16 m1ThreshExt; | ||
107 | u16 m2ThreshExt; | ||
108 | u16 firstep; | ||
109 | u16 firstepLow; | ||
110 | u16 cycpwrThr1; | ||
111 | u16 cycpwrThr1Ext; | ||
112 | }; | ||
113 | |||
63 | struct ar5416AniState { | 114 | struct ar5416AniState { |
64 | struct ath9k_channel *c; | 115 | struct ath9k_channel *c; |
65 | u8 noiseImmunityLevel; | 116 | u8 noiseImmunityLevel; |
117 | u8 ofdmNoiseImmunityLevel; | ||
118 | u8 cckNoiseImmunityLevel; | ||
119 | bool ofdmsTurn; | ||
120 | u8 mrcCCKOff; | ||
66 | u8 spurImmunityLevel; | 121 | u8 spurImmunityLevel; |
67 | u8 firstepLevel; | 122 | u8 firstepLevel; |
68 | u8 ofdmWeakSigDetectOff; | 123 | u8 ofdmWeakSigDetectOff; |
@@ -85,6 +140,7 @@ struct ar5416AniState { | |||
85 | int16_t pktRssi[2]; | 140 | int16_t pktRssi[2]; |
86 | int16_t ofdmErrRssi[2]; | 141 | int16_t ofdmErrRssi[2]; |
87 | int16_t cckErrRssi[2]; | 142 | int16_t cckErrRssi[2]; |
143 | struct ath9k_ani_default iniDef; | ||
88 | }; | 144 | }; |
89 | 145 | ||
90 | struct ar5416Stats { | 146 | struct ar5416Stats { |
@@ -108,15 +164,13 @@ struct ar5416Stats { | |||
108 | }; | 164 | }; |
109 | #define ah_mibStats stats.ast_mibstats | 165 | #define ah_mibStats stats.ast_mibstats |
110 | 166 | ||
111 | void ath9k_ani_reset(struct ath_hw *ah); | ||
112 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
113 | struct ath9k_channel *chan); | ||
114 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 167 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
115 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 168 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
116 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | 169 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, |
117 | u32 *rxf_pcnt, u32 *txf_pcnt); | 170 | u32 *rxf_pcnt, u32 *txf_pcnt); |
118 | void ath9k_hw_procmibevent(struct ath_hw *ah); | ||
119 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 171 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
120 | void ath9k_hw_ani_init(struct ath_hw *ah); | 172 | void ath9k_hw_ani_init(struct ath_hw *ah); |
173 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
174 | struct ath9k_channel *chan); | ||
121 | 175 | ||
122 | #endif /* ANI_H */ | 176 | #endif /* ANI_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 96018d53f48e..ee34a495b0be 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -19,7 +19,30 @@ | |||
19 | #include "../regd.h" | 19 | #include "../regd.h" |
20 | #include "ar9002_phy.h" | 20 | #include "ar9002_phy.h" |
21 | 21 | ||
22 | /* All code below is for non single-chip solutions */ | 22 | /* All code below is for AR5008, AR9001, AR9002 */ |
23 | |||
24 | static const int firstep_table[] = | ||
25 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
26 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | ||
27 | |||
28 | static const int cycpwrThr1_table[] = | ||
29 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
30 | { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ | ||
31 | |||
32 | /* | ||
33 | * register values to turn OFDM weak signal detection OFF | ||
34 | */ | ||
35 | static const int m1ThreshLow_off = 127; | ||
36 | static const int m2ThreshLow_off = 127; | ||
37 | static const int m1Thresh_off = 127; | ||
38 | static const int m2Thresh_off = 127; | ||
39 | static const int m2CountThr_off = 31; | ||
40 | static const int m2CountThrLow_off = 63; | ||
41 | static const int m1ThreshLowExt_off = 127; | ||
42 | static const int m2ThreshLowExt_off = 127; | ||
43 | static const int m1ThreshExt_off = 127; | ||
44 | static const int m2ThreshExt_off = 127; | ||
45 | |||
23 | 46 | ||
24 | /** | 47 | /** |
25 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters | 48 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters |
@@ -1026,8 +1049,9 @@ static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, | |||
1026 | return pll; | 1049 | return pll; |
1027 | } | 1050 | } |
1028 | 1051 | ||
1029 | static bool ar5008_hw_ani_control(struct ath_hw *ah, | 1052 | static bool ar5008_hw_ani_control_old(struct ath_hw *ah, |
1030 | enum ath9k_ani_cmd cmd, int param) | 1053 | enum ath9k_ani_cmd cmd, |
1054 | int param) | ||
1031 | { | 1055 | { |
1032 | struct ar5416AniState *aniState = ah->curani; | 1056 | struct ar5416AniState *aniState = ah->curani; |
1033 | struct ath_common *common = ath9k_hw_common(ah); | 1057 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1209,6 +1233,265 @@ static bool ar5008_hw_ani_control(struct ath_hw *ah, | |||
1209 | return true; | 1233 | return true; |
1210 | } | 1234 | } |
1211 | 1235 | ||
1236 | static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | ||
1237 | enum ath9k_ani_cmd cmd, | ||
1238 | int param) | ||
1239 | { | ||
1240 | struct ar5416AniState *aniState = ah->curani; | ||
1241 | struct ath_common *common = ath9k_hw_common(ah); | ||
1242 | struct ath9k_channel *chan = ah->curchan; | ||
1243 | s32 value, value2; | ||
1244 | |||
1245 | switch (cmd & ah->ani_function) { | ||
1246 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | ||
1247 | /* | ||
1248 | * on == 1 means ofdm weak signal detection is ON | ||
1249 | * on == 1 is the default, for less noise immunity | ||
1250 | * | ||
1251 | * on == 0 means ofdm weak signal detection is OFF | ||
1252 | * on == 0 means more noise imm | ||
1253 | */ | ||
1254 | u32 on = param ? 1 : 0; | ||
1255 | /* | ||
1256 | * make register setting for default | ||
1257 | * (weak sig detect ON) come from INI file | ||
1258 | */ | ||
1259 | int m1ThreshLow = on ? | ||
1260 | aniState->iniDef.m1ThreshLow : m1ThreshLow_off; | ||
1261 | int m2ThreshLow = on ? | ||
1262 | aniState->iniDef.m2ThreshLow : m2ThreshLow_off; | ||
1263 | int m1Thresh = on ? | ||
1264 | aniState->iniDef.m1Thresh : m1Thresh_off; | ||
1265 | int m2Thresh = on ? | ||
1266 | aniState->iniDef.m2Thresh : m2Thresh_off; | ||
1267 | int m2CountThr = on ? | ||
1268 | aniState->iniDef.m2CountThr : m2CountThr_off; | ||
1269 | int m2CountThrLow = on ? | ||
1270 | aniState->iniDef.m2CountThrLow : m2CountThrLow_off; | ||
1271 | int m1ThreshLowExt = on ? | ||
1272 | aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; | ||
1273 | int m2ThreshLowExt = on ? | ||
1274 | aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; | ||
1275 | int m1ThreshExt = on ? | ||
1276 | aniState->iniDef.m1ThreshExt : m1ThreshExt_off; | ||
1277 | int m2ThreshExt = on ? | ||
1278 | aniState->iniDef.m2ThreshExt : m2ThreshExt_off; | ||
1279 | |||
1280 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1281 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
1282 | m1ThreshLow); | ||
1283 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1284 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
1285 | m2ThreshLow); | ||
1286 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1287 | AR_PHY_SFCORR_M1_THRESH, m1Thresh); | ||
1288 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1289 | AR_PHY_SFCORR_M2_THRESH, m2Thresh); | ||
1290 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1291 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); | ||
1292 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1293 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
1294 | m2CountThrLow); | ||
1295 | |||
1296 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1297 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); | ||
1298 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1299 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); | ||
1300 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1301 | AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); | ||
1302 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1303 | AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); | ||
1304 | |||
1305 | if (on) | ||
1306 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1307 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1308 | else | ||
1309 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | ||
1310 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
1311 | |||
1312 | if (!on != aniState->ofdmWeakSigDetectOff) { | ||
1313 | ath_print(common, ATH_DBG_ANI, | ||
1314 | "** ch %d: ofdm weak signal: %s=>%s\n", | ||
1315 | chan->channel, | ||
1316 | !aniState->ofdmWeakSigDetectOff ? | ||
1317 | "on" : "off", | ||
1318 | on ? "on" : "off"); | ||
1319 | if (on) | ||
1320 | ah->stats.ast_ani_ofdmon++; | ||
1321 | else | ||
1322 | ah->stats.ast_ani_ofdmoff++; | ||
1323 | aniState->ofdmWeakSigDetectOff = !on; | ||
1324 | } | ||
1325 | break; | ||
1326 | } | ||
1327 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | ||
1328 | u32 level = param; | ||
1329 | |||
1330 | if (level >= ARRAY_SIZE(firstep_table)) { | ||
1331 | ath_print(common, ATH_DBG_ANI, | ||
1332 | "ATH9K_ANI_FIRSTEP_LEVEL: level " | ||
1333 | "out of range (%u > %u)\n", | ||
1334 | level, | ||
1335 | (unsigned) ARRAY_SIZE(firstep_table)); | ||
1336 | return false; | ||
1337 | } | ||
1338 | |||
1339 | /* | ||
1340 | * make register setting relative to default | ||
1341 | * from INI file & cap value | ||
1342 | */ | ||
1343 | value = firstep_table[level] - | ||
1344 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
1345 | aniState->iniDef.firstep; | ||
1346 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1347 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1348 | if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1349 | value = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1350 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
1351 | AR_PHY_FIND_SIG_FIRSTEP, | ||
1352 | value); | ||
1353 | /* | ||
1354 | * we need to set first step low register too | ||
1355 | * make register setting relative to default | ||
1356 | * from INI file & cap value | ||
1357 | */ | ||
1358 | value2 = firstep_table[level] - | ||
1359 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
1360 | aniState->iniDef.firstepLow; | ||
1361 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
1362 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
1363 | if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
1364 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
1365 | |||
1366 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, | ||
1367 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); | ||
1368 | |||
1369 | if (level != aniState->firstepLevel) { | ||
1370 | ath_print(common, ATH_DBG_ANI, | ||
1371 | "** ch %d: level %d=>%d[def:%d] " | ||
1372 | "firstep[level]=%d ini=%d\n", | ||
1373 | chan->channel, | ||
1374 | aniState->firstepLevel, | ||
1375 | level, | ||
1376 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
1377 | value, | ||
1378 | aniState->iniDef.firstep); | ||
1379 | ath_print(common, ATH_DBG_ANI, | ||
1380 | "** ch %d: level %d=>%d[def:%d] " | ||
1381 | "firstep_low[level]=%d ini=%d\n", | ||
1382 | chan->channel, | ||
1383 | aniState->firstepLevel, | ||
1384 | level, | ||
1385 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
1386 | value2, | ||
1387 | aniState->iniDef.firstepLow); | ||
1388 | if (level > aniState->firstepLevel) | ||
1389 | ah->stats.ast_ani_stepup++; | ||
1390 | else if (level < aniState->firstepLevel) | ||
1391 | ah->stats.ast_ani_stepdown++; | ||
1392 | aniState->firstepLevel = level; | ||
1393 | } | ||
1394 | break; | ||
1395 | } | ||
1396 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | ||
1397 | u32 level = param; | ||
1398 | |||
1399 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { | ||
1400 | ath_print(common, ATH_DBG_ANI, | ||
1401 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " | ||
1402 | "out of range (%u > %u)\n", | ||
1403 | level, | ||
1404 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); | ||
1405 | return false; | ||
1406 | } | ||
1407 | /* | ||
1408 | * make register setting relative to default | ||
1409 | * from INI file & cap value | ||
1410 | */ | ||
1411 | value = cycpwrThr1_table[level] - | ||
1412 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
1413 | aniState->iniDef.cycpwrThr1; | ||
1414 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1415 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1416 | if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1417 | value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1418 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | ||
1419 | AR_PHY_TIMING5_CYCPWR_THR1, | ||
1420 | value); | ||
1421 | |||
1422 | /* | ||
1423 | * set AR_PHY_EXT_CCA for extension channel | ||
1424 | * make register setting relative to default | ||
1425 | * from INI file & cap value | ||
1426 | */ | ||
1427 | value2 = cycpwrThr1_table[level] - | ||
1428 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
1429 | aniState->iniDef.cycpwrThr1Ext; | ||
1430 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
1431 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
1432 | if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
1433 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
1434 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
1435 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); | ||
1436 | |||
1437 | if (level != aniState->spurImmunityLevel) { | ||
1438 | ath_print(common, ATH_DBG_ANI, | ||
1439 | "** ch %d: level %d=>%d[def:%d] " | ||
1440 | "cycpwrThr1[level]=%d ini=%d\n", | ||
1441 | chan->channel, | ||
1442 | aniState->spurImmunityLevel, | ||
1443 | level, | ||
1444 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
1445 | value, | ||
1446 | aniState->iniDef.cycpwrThr1); | ||
1447 | ath_print(common, ATH_DBG_ANI, | ||
1448 | "** ch %d: level %d=>%d[def:%d] " | ||
1449 | "cycpwrThr1Ext[level]=%d ini=%d\n", | ||
1450 | chan->channel, | ||
1451 | aniState->spurImmunityLevel, | ||
1452 | level, | ||
1453 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
1454 | value2, | ||
1455 | aniState->iniDef.cycpwrThr1Ext); | ||
1456 | if (level > aniState->spurImmunityLevel) | ||
1457 | ah->stats.ast_ani_spurup++; | ||
1458 | else if (level < aniState->spurImmunityLevel) | ||
1459 | ah->stats.ast_ani_spurdown++; | ||
1460 | aniState->spurImmunityLevel = level; | ||
1461 | } | ||
1462 | break; | ||
1463 | } | ||
1464 | case ATH9K_ANI_MRC_CCK: | ||
1465 | /* | ||
1466 | * You should not see this as AR5008, AR9001, AR9002 | ||
1467 | * does not have hardware support for MRC CCK. | ||
1468 | */ | ||
1469 | WARN_ON(1); | ||
1470 | break; | ||
1471 | case ATH9K_ANI_PRESENT: | ||
1472 | break; | ||
1473 | default: | ||
1474 | ath_print(common, ATH_DBG_ANI, | ||
1475 | "invalid cmd %u\n", cmd); | ||
1476 | return false; | ||
1477 | } | ||
1478 | |||
1479 | ath_print(common, ATH_DBG_ANI, | ||
1480 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | ||
1481 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | ||
1482 | "ofdmErrs=%d cckErrs=%d\n", | ||
1483 | aniState->spurImmunityLevel, | ||
1484 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | ||
1485 | aniState->firstepLevel, | ||
1486 | !aniState->mrcCCKOff ? "on" : "off", | ||
1487 | aniState->listenTime, | ||
1488 | aniState->cycleCount, | ||
1489 | aniState->listenTime, | ||
1490 | aniState->ofdmPhyErrCount, | ||
1491 | aniState->cckPhyErrCount); | ||
1492 | return true; | ||
1493 | } | ||
1494 | |||
1212 | static void ar5008_hw_do_getnf(struct ath_hw *ah, | 1495 | static void ar5008_hw_do_getnf(struct ath_hw *ah, |
1213 | int16_t nfarray[NUM_NF_READINGS]) | 1496 | int16_t nfarray[NUM_NF_READINGS]) |
1214 | { | 1497 | { |
@@ -1329,6 +1612,71 @@ static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1329 | DISABLE_REGWRITE_BUFFER(ah); | 1612 | DISABLE_REGWRITE_BUFFER(ah); |
1330 | } | 1613 | } |
1331 | 1614 | ||
1615 | /* | ||
1616 | * Initialize the ANI register values with default (ini) values. | ||
1617 | * This routine is called during a (full) hardware reset after | ||
1618 | * all the registers are initialised from the INI. | ||
1619 | */ | ||
1620 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
1621 | { | ||
1622 | struct ar5416AniState *aniState; | ||
1623 | struct ath_common *common = ath9k_hw_common(ah); | ||
1624 | struct ath9k_channel *chan = ah->curchan; | ||
1625 | struct ath9k_ani_default *iniDef; | ||
1626 | int index; | ||
1627 | u32 val; | ||
1628 | |||
1629 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1630 | aniState = &ah->ani[index]; | ||
1631 | ah->curani = aniState; | ||
1632 | iniDef = &aniState->iniDef; | ||
1633 | |||
1634 | ath_print(common, ATH_DBG_ANI, | ||
1635 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | ||
1636 | ah->hw_version.macVersion, | ||
1637 | ah->hw_version.macRev, | ||
1638 | ah->opmode, | ||
1639 | chan->channel, | ||
1640 | chan->channelFlags); | ||
1641 | |||
1642 | val = REG_READ(ah, AR_PHY_SFCORR); | ||
1643 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | ||
1644 | iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); | ||
1645 | iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); | ||
1646 | |||
1647 | val = REG_READ(ah, AR_PHY_SFCORR_LOW); | ||
1648 | iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); | ||
1649 | iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); | ||
1650 | iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); | ||
1651 | |||
1652 | val = REG_READ(ah, AR_PHY_SFCORR_EXT); | ||
1653 | iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); | ||
1654 | iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); | ||
1655 | iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); | ||
1656 | iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); | ||
1657 | iniDef->firstep = REG_READ_FIELD(ah, | ||
1658 | AR_PHY_FIND_SIG, | ||
1659 | AR_PHY_FIND_SIG_FIRSTEP); | ||
1660 | iniDef->firstepLow = REG_READ_FIELD(ah, | ||
1661 | AR_PHY_FIND_SIG_LOW, | ||
1662 | AR_PHY_FIND_SIG_FIRSTEP_LOW); | ||
1663 | iniDef->cycpwrThr1 = REG_READ_FIELD(ah, | ||
1664 | AR_PHY_TIMING5, | ||
1665 | AR_PHY_TIMING5_CYCPWR_THR1); | ||
1666 | iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, | ||
1667 | AR_PHY_EXT_CCA, | ||
1668 | AR_PHY_EXT_TIMING5_CYCPWR_THR1); | ||
1669 | |||
1670 | /* these levels just got reset to defaults by the INI */ | ||
1671 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1672 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1673 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
1674 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ | ||
1675 | |||
1676 | aniState->cycleCount = 0; | ||
1677 | } | ||
1678 | |||
1679 | |||
1332 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1680 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) |
1333 | { | 1681 | { |
1334 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1682 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -1350,10 +1698,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1350 | priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; | 1698 | priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; |
1351 | priv_ops->restore_chainmask = ar5008_restore_chainmask; | 1699 | priv_ops->restore_chainmask = ar5008_restore_chainmask; |
1352 | priv_ops->set_diversity = ar5008_set_diversity; | 1700 | priv_ops->set_diversity = ar5008_set_diversity; |
1353 | priv_ops->ani_control = ar5008_hw_ani_control; | ||
1354 | priv_ops->do_getnf = ar5008_hw_do_getnf; | 1701 | priv_ops->do_getnf = ar5008_hw_do_getnf; |
1355 | priv_ops->loadnf = ar5008_hw_loadnf; | 1702 | priv_ops->loadnf = ar5008_hw_loadnf; |
1356 | 1703 | ||
1704 | if (modparam_force_new_ani) { | ||
1705 | priv_ops->ani_control = ar5008_hw_ani_control_new; | ||
1706 | priv_ops->ani_cache_ini_regs = ar5008_hw_ani_cache_ini_regs; | ||
1707 | } else | ||
1708 | priv_ops->ani_control = ar5008_hw_ani_control_old; | ||
1709 | |||
1357 | if (AR_SREV_9100(ah)) | 1710 | if (AR_SREV_9100(ah)) |
1358 | priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; | 1711 | priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; |
1359 | else if (AR_SREV_9160_10_OR_LATER(ah)) | 1712 | else if (AR_SREV_9160_10_OR_LATER(ah)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 7ba9dd68cc05..0317ac9fc1b7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -20,6 +20,10 @@ | |||
20 | #include "ar9002_initvals.h" | 20 | #include "ar9002_initvals.h" |
21 | #include "ar9002_phy.h" | 21 | #include "ar9002_phy.h" |
22 | 22 | ||
23 | int modparam_force_new_ani; | ||
24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | ||
25 | MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002"); | ||
26 | |||
23 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | 27 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
24 | 28 | ||
25 | static bool ar9002_hw_macversion_supported(u32 macversion) | 29 | static bool ar9002_hw_macversion_supported(u32 macversion) |
@@ -636,4 +640,9 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
636 | 640 | ||
637 | ar9002_hw_attach_calib_ops(ah); | 641 | ar9002_hw_attach_calib_ops(ah); |
638 | ar9002_hw_attach_mac_ops(ah); | 642 | ar9002_hw_attach_mac_ops(ah); |
643 | |||
644 | if (modparam_force_new_ani) | ||
645 | ath9k_hw_attach_ani_ops_new(ah); | ||
646 | else | ||
647 | ath9k_hw_attach_ani_ops_old(ah); | ||
639 | } | 648 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 81bf6e5840e1..ce8bb001c6d1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -114,6 +114,10 @@ | |||
114 | #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 | 114 | #define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 |
115 | #define AR_PHY_FIND_SIG_FIRPWR_S 18 | 115 | #define AR_PHY_FIND_SIG_FIRPWR_S 18 |
116 | 116 | ||
117 | #define AR_PHY_FIND_SIG_LOW 0x9840 | ||
118 | #define AR_PHY_FIND_SIG_FIRSTEP_LOW 0x00000FC0L | ||
119 | #define AR_PHY_FIND_SIG_FIRSTEP_LOW_S 6 | ||
120 | |||
117 | #define AR_PHY_AGC_CTL1 0x985C | 121 | #define AR_PHY_AGC_CTL1 0x985C |
118 | #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 | 122 | #define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 |
119 | #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 | 123 | #define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 |
@@ -325,6 +329,9 @@ | |||
325 | #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 | 329 | #define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 |
326 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 | 330 | #define AR_PHY_EXT_CCA_THRESH62 0x007F0000 |
327 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | 331 | #define AR_PHY_EXT_CCA_THRESH62_S 16 |
332 | #define AR_PHY_EXT_TIMING5_CYCPWR_THR1 0x0000FE00L | ||
333 | #define AR_PHY_EXT_TIMING5_CYCPWR_THR1_S 9 | ||
334 | |||
328 | #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 | 335 | #define AR_PHY_EXT_MINCCA_PWR 0xFF800000 |
329 | #define AR_PHY_EXT_MINCCA_PWR_S 23 | 336 | #define AR_PHY_EXT_MINCCA_PWR_S 23 |
330 | #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 | 337 | #define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h index f82a00da82b8..d3375fc4ce8b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h | |||
@@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = { | |||
835 | 835 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | 836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
840 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
841 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 841 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
842 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 842 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
843 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 843 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
844 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 844 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
845 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 845 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
846 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 846 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
847 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 847 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
848 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 848 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
849 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 849 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
850 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 850 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
851 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 851 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
852 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 852 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
853 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 853 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
854 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 854 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
855 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 855 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
856 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 856 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
857 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 857 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
859 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 859 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
860 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 860 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
861 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 861 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
862 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 862 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
863 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 863 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
864 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 864 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
865 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 865 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
866 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 866 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
867 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 867 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
868 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 868 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
869 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 869 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
870 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 870 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
872 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 872 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
873 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 873 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
874 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 874 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
875 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 875 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
876 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 876 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
877 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 877 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
878 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 878 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
879 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 879 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
880 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 880 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
881 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 881 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
882 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 882 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
883 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 883 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
884 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 884 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
885 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 885 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
886 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 886 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
887 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 887 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
888 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 888 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
889 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 889 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
890 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 890 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
891 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 891 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
892 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 892 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
893 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 893 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
894 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 894 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
895 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 895 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
896 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 896 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
897 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 897 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
898 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 898 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
899 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 899 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
900 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
901 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
902 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, |
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, |
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, |
@@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | |||
913 | 913 | ||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { | 914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { |
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
916 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
918 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
919 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 919 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
920 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 920 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
921 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 921 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
922 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 922 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
923 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 923 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
924 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 924 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
925 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 925 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
926 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 926 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
927 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 927 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
928 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 928 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
929 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 929 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
930 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 930 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
931 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 931 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
932 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 932 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
933 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 933 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
934 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 934 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
935 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 935 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
937 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 937 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
938 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 938 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
939 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 939 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
940 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 940 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
941 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 941 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
942 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 942 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
943 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 943 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
944 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 944 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
945 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 945 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
946 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 946 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
947 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 947 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
948 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 948 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
950 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 950 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
951 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 951 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
952 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 952 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
953 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 953 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
954 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 954 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
955 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 955 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
956 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 956 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
957 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 957 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
958 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 958 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
959 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 959 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
960 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 960 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
961 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 961 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
962 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 962 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
963 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 963 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
964 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 964 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
965 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 965 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
966 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 966 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
967 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 967 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
968 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 968 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
969 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 969 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
970 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 970 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
971 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 971 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
972 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 972 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
973 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 973 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
974 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 974 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
975 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 975 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
976 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 976 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
977 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 977 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
978 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
979 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
980 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, |
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, |
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 745150573793..ec98ab50748a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -835,71 +835,71 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
835 | 835 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | 836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
840 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
841 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 841 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
842 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 842 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
843 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 843 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
844 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 844 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
845 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 845 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
846 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 846 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
847 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 847 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
848 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 848 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
849 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 849 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
850 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 850 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
851 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 851 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
852 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 852 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
853 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 853 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
854 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 854 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
855 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 855 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
856 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 856 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
857 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 857 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
859 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 859 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
860 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 860 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
861 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 861 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
862 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 862 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
863 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 863 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
864 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 864 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
865 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 865 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
866 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 866 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
867 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 867 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
868 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 868 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
869 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 869 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
870 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 870 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 871 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
872 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 872 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
873 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 873 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
874 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 874 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
875 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 875 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
876 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 876 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
877 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 877 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
878 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 878 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
879 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 879 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
880 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 880 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
881 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 881 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
882 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 882 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
883 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 883 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
884 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 884 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
885 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 885 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
886 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 886 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
887 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 887 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
888 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 888 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
889 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 889 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
890 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 890 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
891 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 891 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
892 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 892 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
893 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 893 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
894 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 894 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
895 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 895 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
896 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 896 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
897 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 897 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
898 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 898 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
899 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 899 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
900 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
901 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
902 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, |
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, |
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, |
@@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
913 | 913 | ||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | 914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { |
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
916 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
918 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
919 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 919 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, |
920 | {0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, | 920 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, |
921 | {0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, | 921 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, |
922 | {0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, | 922 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, |
923 | {0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, | 923 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, |
924 | {0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, | 924 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, |
925 | {0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, | 925 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, |
926 | {0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, | 926 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, |
927 | {0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, | 927 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, |
928 | {0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, | 928 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, |
929 | {0x0000a530, 0x34025643, 0x34025643, 0x2a000e20, 0x2a000e20}, | 929 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, |
930 | {0x0000a534, 0x38025a44, 0x38025a44, 0x2e000e22, 0x2e000e22}, | 930 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, |
931 | {0x0000a538, 0x3b025e45, 0x3b025e45, 0x31000e24, 0x31000e24}, | 931 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, |
932 | {0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640}, | 932 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, |
933 | {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660}, | 933 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
934 | {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861}, | 934 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
935 | {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81}, | 935 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, |
937 | {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84}, | 937 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
938 | {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3}, | 938 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
939 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 939 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
940 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 940 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, |
941 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 941 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, |
942 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 942 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
943 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 943 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
944 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 944 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
945 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 945 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
946 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 946 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
947 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 947 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
948 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 948 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, |
949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | 949 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, |
950 | {0x0000a584, 0x06802223, 0x06802223, 0x04800002, 0x04800002}, | 950 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, |
951 | {0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, | 951 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, |
952 | {0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, | 952 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, |
953 | {0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, | 953 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, |
954 | {0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, | 954 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, |
955 | {0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, | 955 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, |
956 | {0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, | 956 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, |
957 | {0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, | 957 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, |
958 | {0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, | 958 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, |
959 | {0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, | 959 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, |
960 | {0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, | 960 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, |
961 | {0x0000a5b0, 0x34825643, 0x34825643, 0x2a800e20, 0x2a800e20}, | 961 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, |
962 | {0x0000a5b4, 0x38825a44, 0x38825a44, 0x2e800e22, 0x2e800e22}, | 962 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, |
963 | {0x0000a5b8, 0x3b825e45, 0x3b825e45, 0x31800e24, 0x31800e24}, | 963 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, |
964 | {0x0000a5bc, 0x41825e4a, 0x41825e4a, 0x34801640, 0x34801640}, | 964 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, |
965 | {0x0000a5c0, 0x48825e6c, 0x48825e6c, 0x38801660, 0x38801660}, | 965 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, |
966 | {0x0000a5c4, 0x4e825e8e, 0x4e825e8e, 0x3b801861, 0x3b801861}, | 966 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, |
967 | {0x0000a5c8, 0x53825eb2, 0x53825eb2, 0x3e801a81, 0x3e801a81}, | 967 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, |
968 | {0x0000a5cc, 0x59825eb5, 0x59825eb5, 0x42801a83, 0x42801a83}, | 968 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, |
969 | {0x0000a5d0, 0x5f825ef6, 0x5f825ef6, 0x44801c84, 0x44801c84}, | 969 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, |
970 | {0x0000a5d4, 0x62825f56, 0x62825f56, 0x48801ce3, 0x48801ce3}, | 970 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, |
971 | {0x0000a5d8, 0x66827f56, 0x66827f56, 0x4c801ce5, 0x4c801ce5}, | 971 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, |
972 | {0x0000a5dc, 0x6a829f56, 0x6a829f56, 0x50801ce9, 0x50801ce9}, | 972 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, |
973 | {0x0000a5e0, 0x70849f56, 0x70849f56, 0x54801ceb, 0x54801ceb}, | 973 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, |
974 | {0x0000a5e4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 974 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
975 | {0x0000a5e8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 975 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
976 | {0x0000a5ec, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 976 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
977 | {0x0000a5f0, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 977 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
978 | {0x0000a5f4, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
979 | {0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
980 | {0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec}, | 980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, |
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, |
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 23eb60ea5455..343c9a427acb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -67,6 +67,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
67 | * bit2 - enable fastClock - enabled | 67 | * bit2 - enable fastClock - enabled |
68 | * bit3 - enable doubling - enabled | 68 | * bit3 - enable doubling - enabled |
69 | * bit4 - enable internal regulator - disabled | 69 | * bit4 - enable internal regulator - disabled |
70 | * bit5 - enable pa predistortion - disabled | ||
70 | */ | 71 | */ |
71 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | 72 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ |
72 | .eepromWriteEnableGpio = 3, | 73 | .eepromWriteEnableGpio = 3, |
@@ -129,9 +130,11 @@ static const struct ar9300_eeprom ar9300_default = { | |||
129 | .txEndToRxOn = 0x2, | 130 | .txEndToRxOn = 0x2, |
130 | .txFrameToXpaOn = 0xe, | 131 | .txFrameToXpaOn = 0xe, |
131 | .thresh62 = 28, | 132 | .thresh62 = 28, |
132 | .futureModal = { /* [32] */ | 133 | .papdRateMaskHt20 = LE32(0x80c080), |
134 | .papdRateMaskHt40 = LE32(0x80c080), | ||
135 | .futureModal = { | ||
133 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 136 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
134 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 137 | 0, 0, 0, 0, 0, 0, 0, 0 |
135 | }, | 138 | }, |
136 | }, | 139 | }, |
137 | .calFreqPier2G = { | 140 | .calFreqPier2G = { |
@@ -326,9 +329,11 @@ static const struct ar9300_eeprom ar9300_default = { | |||
326 | .txEndToRxOn = 0x2, | 329 | .txEndToRxOn = 0x2, |
327 | .txFrameToXpaOn = 0xe, | 330 | .txFrameToXpaOn = 0xe, |
328 | .thresh62 = 28, | 331 | .thresh62 = 28, |
332 | .papdRateMaskHt20 = LE32(0xf0e0e0), | ||
333 | .papdRateMaskHt40 = LE32(0xf0e0e0), | ||
329 | .futureModal = { | 334 | .futureModal = { |
330 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 335 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
331 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 336 | 0, 0, 0, 0, 0, 0, 0, 0 |
332 | }, | 337 | }, |
333 | }, | 338 | }, |
334 | .calFreqPier5G = { | 339 | .calFreqPier5G = { |
@@ -644,6 +649,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
644 | return (pBase->featureEnable & 0x10) >> 4; | 649 | return (pBase->featureEnable & 0x10) >> 4; |
645 | case EEP_SWREG: | 650 | case EEP_SWREG: |
646 | return le32_to_cpu(pBase->swreg); | 651 | return le32_to_cpu(pBase->swreg); |
652 | case EEP_PAPRD: | ||
653 | return !!(pBase->featureEnable & BIT(5)); | ||
647 | default: | 654 | default: |
648 | return 0; | 655 | return 0; |
649 | } | 656 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 23fb353c3bba..3c533bb983c7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -234,7 +234,9 @@ struct ar9300_modal_eep_header { | |||
234 | u8 txEndToRxOn; | 234 | u8 txEndToRxOn; |
235 | u8 txFrameToXpaOn; | 235 | u8 txFrameToXpaOn; |
236 | u8 thresh62; | 236 | u8 thresh62; |
237 | u8 futureModal[32]; | 237 | __le32 papdRateMaskHt20; |
238 | __le32 papdRateMaskHt40; | ||
239 | u8 futureModal[24]; | ||
238 | } __packed; | 240 | } __packed; |
239 | 241 | ||
240 | struct ar9300_cal_data_per_freq_op_loop { | 242 | struct ar9300_cal_data_per_freq_op_loop { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 863f61e3a16f..82c3ab756cd0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -313,4 +313,6 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
313 | ar9003_hw_attach_phy_ops(ah); | 313 | ar9003_hw_attach_phy_ops(ah); |
314 | ar9003_hw_attach_calib_ops(ah); | 314 | ar9003_hw_attach_calib_ops(ah); |
315 | ar9003_hw_attach_mac_ops(ah); | 315 | ar9003_hw_attach_mac_ops(ah); |
316 | |||
317 | ath9k_hw_attach_ani_ops_new(ah); | ||
316 | } | 318 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 40731077cbb4..06ef71019c12 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -470,6 +470,14 @@ static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
470 | ads->ctl11 &= ~AR_VirtMoreFrag; | 470 | ads->ctl11 &= ~AR_VirtMoreFrag; |
471 | } | 471 | } |
472 | 472 | ||
473 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | ||
474 | { | ||
475 | struct ar9003_txc *ads = ds; | ||
476 | |||
477 | ads->ctl12 |= SM(chains, AR_PAPRDChainMask); | ||
478 | } | ||
479 | EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc); | ||
480 | |||
473 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 481 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
474 | { | 482 | { |
475 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 483 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 5a7a286e2773..f76f27d16f77 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h | |||
@@ -40,6 +40,10 @@ | |||
40 | 40 | ||
41 | #define AR_Not_Sounding 0x20000000 | 41 | #define AR_Not_Sounding 0x20000000 |
42 | 42 | ||
43 | /* ctl 12 */ | ||
44 | #define AR_PAPRDChainMask 0x00000e00 | ||
45 | #define AR_PAPRDChainMask_S 9 | ||
46 | |||
43 | #define MAP_ISR_S2_CST 6 | 47 | #define MAP_ISR_S2_CST 6 |
44 | #define MAP_ISR_S2_GTT 6 | 48 | #define MAP_ISR_S2_GTT 6 |
45 | #define MAP_ISR_S2_TIM 3 | 49 | #define MAP_ISR_S2_TIM 3 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c new file mode 100644 index 000000000000..49e0c865ce5c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -0,0 +1,714 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "hw.h" | ||
18 | #include "ar9003_phy.h" | ||
19 | |||
20 | void ar9003_paprd_enable(struct ath_hw *ah, bool val) | ||
21 | { | ||
22 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, | ||
23 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
24 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, | ||
25 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
26 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | ||
27 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
28 | } | ||
29 | EXPORT_SYMBOL(ar9003_paprd_enable); | ||
30 | |||
31 | static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | ||
32 | { | ||
33 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
34 | struct ar9300_modal_eep_header *hdr; | ||
35 | const u32 ctrl0[3] = { | ||
36 | AR_PHY_PAPRD_CTRL0_B0, | ||
37 | AR_PHY_PAPRD_CTRL0_B1, | ||
38 | AR_PHY_PAPRD_CTRL0_B2 | ||
39 | }; | ||
40 | const u32 ctrl1[3] = { | ||
41 | AR_PHY_PAPRD_CTRL1_B0, | ||
42 | AR_PHY_PAPRD_CTRL1_B1, | ||
43 | AR_PHY_PAPRD_CTRL1_B2 | ||
44 | }; | ||
45 | u32 am_mask, ht40_mask; | ||
46 | int i; | ||
47 | |||
48 | if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) | ||
49 | hdr = &eep->modalHeader5G; | ||
50 | else | ||
51 | hdr = &eep->modalHeader2G; | ||
52 | |||
53 | am_mask = le32_to_cpu(hdr->papdRateMaskHt20); | ||
54 | ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); | ||
55 | |||
56 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); | ||
57 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); | ||
58 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); | ||
59 | |||
60 | for (i = 0; i < 3; i++) { | ||
61 | REG_RMW_FIELD(ah, ctrl0[i], | ||
62 | AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); | ||
63 | REG_RMW_FIELD(ah, ctrl1[i], | ||
64 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE, 1); | ||
65 | REG_RMW_FIELD(ah, ctrl1[i], | ||
66 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE, 1); | ||
67 | REG_RMW_FIELD(ah, ctrl1[i], | ||
68 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
69 | REG_RMW_FIELD(ah, ctrl1[i], | ||
70 | AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK, 181); | ||
71 | REG_RMW_FIELD(ah, ctrl1[i], | ||
72 | AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT, 361); | ||
73 | REG_RMW_FIELD(ah, ctrl1[i], | ||
74 | AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA, 0); | ||
75 | REG_RMW_FIELD(ah, ctrl0[i], | ||
76 | AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH, 3); | ||
77 | } | ||
78 | |||
79 | ar9003_paprd_enable(ah, false); | ||
80 | |||
81 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
82 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP, 0x30); | ||
83 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
84 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE, 1); | ||
85 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
86 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE, 1); | ||
87 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
88 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE, 0); | ||
89 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
90 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE, 0); | ||
91 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
92 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING, 28); | ||
93 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL1, | ||
94 | AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE, 1); | ||
95 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL2, | ||
96 | AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN, 147); | ||
97 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
98 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN, 4); | ||
99 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
100 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN, 4); | ||
101 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
102 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); | ||
103 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
104 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); | ||
105 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
106 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); | ||
107 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
108 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, | ||
109 | -15); | ||
110 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
111 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE, 1); | ||
112 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
113 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA, 0); | ||
114 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
115 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR, 400); | ||
116 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL4, | ||
117 | AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES, | ||
118 | 100); | ||
119 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_0_B0, | ||
120 | AR_PHY_PAPRD_PRE_POST_SCALING, 261376); | ||
121 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_1_B0, | ||
122 | AR_PHY_PAPRD_PRE_POST_SCALING, 248079); | ||
123 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_2_B0, | ||
124 | AR_PHY_PAPRD_PRE_POST_SCALING, 233759); | ||
125 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_3_B0, | ||
126 | AR_PHY_PAPRD_PRE_POST_SCALING, 220464); | ||
127 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_4_B0, | ||
128 | AR_PHY_PAPRD_PRE_POST_SCALING, 208194); | ||
129 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_5_B0, | ||
130 | AR_PHY_PAPRD_PRE_POST_SCALING, 196949); | ||
131 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_6_B0, | ||
132 | AR_PHY_PAPRD_PRE_POST_SCALING, 185706); | ||
133 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, | ||
134 | AR_PHY_PAPRD_PRE_POST_SCALING, 175487); | ||
135 | } | ||
136 | |||
137 | static void ar9003_paprd_get_gain_table(struct ath_hw *ah) | ||
138 | { | ||
139 | u32 *entry = ah->paprd_gain_table_entries; | ||
140 | u8 *index = ah->paprd_gain_table_index; | ||
141 | u32 reg = AR_PHY_TXGAIN_TABLE; | ||
142 | int i; | ||
143 | |||
144 | memset(entry, 0, sizeof(ah->paprd_gain_table_entries)); | ||
145 | memset(index, 0, sizeof(ah->paprd_gain_table_index)); | ||
146 | |||
147 | for (i = 0; i < 32; i++) { | ||
148 | entry[i] = REG_READ(ah, reg); | ||
149 | index[i] = (entry[i] >> 24) & 0xff; | ||
150 | reg += 4; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain, | ||
155 | int target_power) | ||
156 | { | ||
157 | int olpc_gain_delta = 0; | ||
158 | int alpha_therm, alpha_volt; | ||
159 | int therm_cal_value, volt_cal_value; | ||
160 | int therm_value, volt_value; | ||
161 | int thermal_gain_corr, voltage_gain_corr; | ||
162 | int desired_scale, desired_gain = 0; | ||
163 | u32 reg; | ||
164 | |||
165 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
166 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
167 | desired_scale = REG_READ_FIELD(ah, AR_PHY_TPC_12, | ||
168 | AR_PHY_TPC_12_DESIRED_SCALE_HT40_5); | ||
169 | alpha_therm = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
170 | AR_PHY_TPC_19_ALPHA_THERM); | ||
171 | alpha_volt = REG_READ_FIELD(ah, AR_PHY_TPC_19, | ||
172 | AR_PHY_TPC_19_ALPHA_VOLT); | ||
173 | therm_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
174 | AR_PHY_TPC_18_THERM_CAL_VALUE); | ||
175 | volt_cal_value = REG_READ_FIELD(ah, AR_PHY_TPC_18, | ||
176 | AR_PHY_TPC_18_VOLT_CAL_VALUE); | ||
177 | therm_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
178 | AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE); | ||
179 | volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, | ||
180 | AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE); | ||
181 | |||
182 | if (chain == 0) | ||
183 | reg = AR_PHY_TPC_11_B0; | ||
184 | else if (chain == 1) | ||
185 | reg = AR_PHY_TPC_11_B1; | ||
186 | else | ||
187 | reg = AR_PHY_TPC_11_B2; | ||
188 | |||
189 | olpc_gain_delta = REG_READ_FIELD(ah, reg, | ||
190 | AR_PHY_TPC_11_OLPC_GAIN_DELTA); | ||
191 | |||
192 | if (olpc_gain_delta >= 128) | ||
193 | olpc_gain_delta = olpc_gain_delta - 256; | ||
194 | |||
195 | thermal_gain_corr = (alpha_therm * (therm_value - therm_cal_value) + | ||
196 | (256 / 2)) / 256; | ||
197 | voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) + | ||
198 | (128 / 2)) / 128; | ||
199 | desired_gain = target_power - olpc_gain_delta - thermal_gain_corr - | ||
200 | voltage_gain_corr + desired_scale; | ||
201 | |||
202 | return desired_gain; | ||
203 | } | ||
204 | |||
205 | static void ar9003_tx_force_gain(struct ath_hw *ah, unsigned int gain_index) | ||
206 | { | ||
207 | int selected_gain_entry, txbb1dbgain, txbb6dbgain, txmxrgain; | ||
208 | int padrvgnA, padrvgnB, padrvgnC, padrvgnD; | ||
209 | u32 *gain_table_entries = ah->paprd_gain_table_entries; | ||
210 | |||
211 | selected_gain_entry = gain_table_entries[gain_index]; | ||
212 | txbb1dbgain = selected_gain_entry & 0x7; | ||
213 | txbb6dbgain = (selected_gain_entry >> 3) & 0x3; | ||
214 | txmxrgain = (selected_gain_entry >> 5) & 0xf; | ||
215 | padrvgnA = (selected_gain_entry >> 9) & 0xf; | ||
216 | padrvgnB = (selected_gain_entry >> 13) & 0xf; | ||
217 | padrvgnC = (selected_gain_entry >> 17) & 0xf; | ||
218 | padrvgnD = (selected_gain_entry >> 21) & 0x3; | ||
219 | |||
220 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
221 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN, txbb1dbgain); | ||
222 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
223 | AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN, txbb6dbgain); | ||
224 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
225 | AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN, txmxrgain); | ||
226 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
227 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA, padrvgnA); | ||
228 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
229 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB, padrvgnB); | ||
230 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
231 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC, padrvgnC); | ||
232 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
233 | AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND, padrvgnD); | ||
234 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
235 | AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL, 0); | ||
236 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
237 | AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN, 0); | ||
238 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCED_DAC_GAIN, 0); | ||
239 | REG_RMW_FIELD(ah, AR_PHY_TPC_1, AR_PHY_TPC_1_FORCE_DAC_GAIN, 0); | ||
240 | } | ||
241 | |||
242 | static inline int find_expn(int num) | ||
243 | { | ||
244 | return fls(num) - 1; | ||
245 | } | ||
246 | |||
247 | static inline int find_proper_scale(int expn, int N) | ||
248 | { | ||
249 | return (expn > N) ? expn - 10 : 0; | ||
250 | } | ||
251 | |||
252 | #define NUM_BIN 23 | ||
253 | |||
254 | static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | ||
255 | { | ||
256 | unsigned int thresh_accum_cnt; | ||
257 | int x_est[NUM_BIN + 1], Y[NUM_BIN + 1], theta[NUM_BIN + 1]; | ||
258 | int PA_in[NUM_BIN + 1]; | ||
259 | int B1_tmp[NUM_BIN + 1], B2_tmp[NUM_BIN + 1]; | ||
260 | unsigned int B1_abs_max, B2_abs_max; | ||
261 | int max_index, scale_factor; | ||
262 | int y_est[NUM_BIN + 1]; | ||
263 | int x_est_fxp1_nonlin, x_tilde[NUM_BIN + 1]; | ||
264 | unsigned int x_tilde_abs; | ||
265 | int G_fxp, Y_intercept, order_x_by_y, M, I, L, sum_y_sqr, sum_y_quad; | ||
266 | int Q_x, Q_B1, Q_B2, beta_raw, alpha_raw, scale_B; | ||
267 | int Q_scale_B, Q_beta, Q_alpha, alpha, beta, order_1, order_2; | ||
268 | int order1_5x, order2_3x, order1_5x_rem, order2_3x_rem; | ||
269 | int y5, y3, tmp; | ||
270 | int theta_low_bin = 0; | ||
271 | int i; | ||
272 | |||
273 | /* disregard any bin that contains <= 16 samples */ | ||
274 | thresh_accum_cnt = 16; | ||
275 | scale_factor = 5; | ||
276 | max_index = 0; | ||
277 | memset(theta, 0, sizeof(theta)); | ||
278 | memset(x_est, 0, sizeof(x_est)); | ||
279 | memset(Y, 0, sizeof(Y)); | ||
280 | memset(y_est, 0, sizeof(y_est)); | ||
281 | memset(x_tilde, 0, sizeof(x_tilde)); | ||
282 | |||
283 | for (i = 0; i < NUM_BIN; i++) { | ||
284 | s32 accum_cnt, accum_tx, accum_rx, accum_ang; | ||
285 | |||
286 | /* number of samples */ | ||
287 | accum_cnt = data_L[i] & 0xffff; | ||
288 | |||
289 | if (accum_cnt <= thresh_accum_cnt) | ||
290 | continue; | ||
291 | |||
292 | /* sum(tx amplitude) */ | ||
293 | accum_tx = ((data_L[i] >> 16) & 0xffff) | | ||
294 | ((data_U[i] & 0x7ff) << 16); | ||
295 | |||
296 | /* sum(rx amplitude distance to lower bin edge) */ | ||
297 | accum_rx = ((data_U[i] >> 11) & 0x1f) | | ||
298 | ((data_L[i + 23] & 0xffff) << 5); | ||
299 | |||
300 | /* sum(angles) */ | ||
301 | accum_ang = ((data_L[i + 23] >> 16) & 0xffff) | | ||
302 | ((data_U[i + 23] & 0x7ff) << 16); | ||
303 | |||
304 | accum_tx <<= scale_factor; | ||
305 | accum_rx <<= scale_factor; | ||
306 | x_est[i + 1] = (((accum_tx + accum_cnt) / accum_cnt) + 32) >> | ||
307 | scale_factor; | ||
308 | |||
309 | Y[i + 1] = ((((accum_rx + accum_cnt) / accum_cnt) + 32) >> | ||
310 | scale_factor) + | ||
311 | (1 << scale_factor) * max_index + 16; | ||
312 | |||
313 | if (accum_ang >= (1 << 26)) | ||
314 | accum_ang -= 1 << 27; | ||
315 | |||
316 | theta[i + 1] = ((accum_ang * (1 << scale_factor)) + accum_cnt) / | ||
317 | accum_cnt; | ||
318 | |||
319 | max_index++; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Find average theta of first 5 bin and all of those to same value. | ||
324 | * Curve is linear at that range. | ||
325 | */ | ||
326 | for (i = 1; i < 6; i++) | ||
327 | theta_low_bin += theta[i]; | ||
328 | |||
329 | theta_low_bin = theta_low_bin / 5; | ||
330 | for (i = 1; i < 6; i++) | ||
331 | theta[i] = theta_low_bin; | ||
332 | |||
333 | /* Set values at origin */ | ||
334 | theta[0] = theta_low_bin; | ||
335 | for (i = 0; i <= max_index; i++) | ||
336 | theta[i] -= theta_low_bin; | ||
337 | |||
338 | x_est[0] = 0; | ||
339 | Y[0] = 0; | ||
340 | scale_factor = 8; | ||
341 | |||
342 | /* low signal gain */ | ||
343 | if (x_est[6] == x_est[3]) | ||
344 | return false; | ||
345 | |||
346 | G_fxp = | ||
347 | (((Y[6] - Y[3]) * 1 << scale_factor) + | ||
348 | (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); | ||
349 | |||
350 | Y_intercept = | ||
351 | (G_fxp * (x_est[0] - x_est[3]) + | ||
352 | (1 << scale_factor)) / (1 << scale_factor) + Y[3]; | ||
353 | |||
354 | for (i = 0; i <= max_index; i++) | ||
355 | y_est[i] = Y[i] - Y_intercept; | ||
356 | |||
357 | for (i = 0; i <= 3; i++) { | ||
358 | y_est[i] = i * 32; | ||
359 | |||
360 | /* prevent division by zero */ | ||
361 | if (G_fxp == 0) | ||
362 | return false; | ||
363 | |||
364 | x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; | ||
365 | } | ||
366 | |||
367 | x_est_fxp1_nonlin = | ||
368 | x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + | ||
369 | G_fxp) / G_fxp; | ||
370 | |||
371 | order_x_by_y = | ||
372 | (x_est_fxp1_nonlin + y_est[max_index]) / y_est[max_index]; | ||
373 | |||
374 | if (order_x_by_y == 0) | ||
375 | M = 10; | ||
376 | else if (order_x_by_y == 1) | ||
377 | M = 9; | ||
378 | else | ||
379 | M = 8; | ||
380 | |||
381 | I = (max_index > 15) ? 7 : max_index >> 1; | ||
382 | L = max_index - I; | ||
383 | scale_factor = 8; | ||
384 | sum_y_sqr = 0; | ||
385 | sum_y_quad = 0; | ||
386 | x_tilde_abs = 0; | ||
387 | |||
388 | for (i = 0; i <= L; i++) { | ||
389 | unsigned int y_sqr; | ||
390 | unsigned int y_quad; | ||
391 | unsigned int tmp_abs; | ||
392 | |||
393 | /* prevent division by zero */ | ||
394 | if (y_est[i + I] == 0) | ||
395 | return false; | ||
396 | |||
397 | x_est_fxp1_nonlin = | ||
398 | x_est[i + I] - ((1 << scale_factor) * y_est[i + I] + | ||
399 | G_fxp) / G_fxp; | ||
400 | |||
401 | x_tilde[i] = | ||
402 | (x_est_fxp1_nonlin * (1 << M) + y_est[i + I]) / y_est[i + | ||
403 | I]; | ||
404 | x_tilde[i] = | ||
405 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
406 | x_tilde[i] = | ||
407 | (x_tilde[i] * (1 << M) + y_est[i + I]) / y_est[i + I]; | ||
408 | y_sqr = | ||
409 | (y_est[i + I] * y_est[i + I] + | ||
410 | (scale_factor * scale_factor)) / (scale_factor * | ||
411 | scale_factor); | ||
412 | tmp_abs = abs(x_tilde[i]); | ||
413 | if (tmp_abs > x_tilde_abs) | ||
414 | x_tilde_abs = tmp_abs; | ||
415 | |||
416 | y_quad = y_sqr * y_sqr; | ||
417 | sum_y_sqr = sum_y_sqr + y_sqr; | ||
418 | sum_y_quad = sum_y_quad + y_quad; | ||
419 | B1_tmp[i] = y_sqr * (L + 1); | ||
420 | B2_tmp[i] = y_sqr; | ||
421 | } | ||
422 | |||
423 | B1_abs_max = 0; | ||
424 | B2_abs_max = 0; | ||
425 | for (i = 0; i <= L; i++) { | ||
426 | int abs_val; | ||
427 | |||
428 | B1_tmp[i] -= sum_y_sqr; | ||
429 | B2_tmp[i] = sum_y_quad - sum_y_sqr * B2_tmp[i]; | ||
430 | |||
431 | abs_val = abs(B1_tmp[i]); | ||
432 | if (abs_val > B1_abs_max) | ||
433 | B1_abs_max = abs_val; | ||
434 | |||
435 | abs_val = abs(B2_tmp[i]); | ||
436 | if (abs_val > B2_abs_max) | ||
437 | B2_abs_max = abs_val; | ||
438 | } | ||
439 | |||
440 | Q_x = find_proper_scale(find_expn(x_tilde_abs), 10); | ||
441 | Q_B1 = find_proper_scale(find_expn(B1_abs_max), 10); | ||
442 | Q_B2 = find_proper_scale(find_expn(B2_abs_max), 10); | ||
443 | |||
444 | beta_raw = 0; | ||
445 | alpha_raw = 0; | ||
446 | for (i = 0; i <= L; i++) { | ||
447 | x_tilde[i] = x_tilde[i] / (1 << Q_x); | ||
448 | B1_tmp[i] = B1_tmp[i] / (1 << Q_B1); | ||
449 | B2_tmp[i] = B2_tmp[i] / (1 << Q_B2); | ||
450 | beta_raw = beta_raw + B1_tmp[i] * x_tilde[i]; | ||
451 | alpha_raw = alpha_raw + B2_tmp[i] * x_tilde[i]; | ||
452 | } | ||
453 | |||
454 | scale_B = | ||
455 | ((sum_y_quad / scale_factor) * (L + 1) - | ||
456 | (sum_y_sqr / scale_factor) * sum_y_sqr) * scale_factor; | ||
457 | |||
458 | Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); | ||
459 | scale_B = scale_B / (1 << Q_scale_B); | ||
460 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
461 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
462 | beta_raw = beta_raw / (1 << Q_beta); | ||
463 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
464 | alpha = (alpha_raw << 10) / scale_B; | ||
465 | beta = (beta_raw << 10) / scale_B; | ||
466 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B; | ||
467 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B; | ||
468 | order1_5x = order_1 / 5; | ||
469 | order2_3x = order_2 / 3; | ||
470 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
471 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
472 | |||
473 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
474 | tmp = i * 32; | ||
475 | y5 = ((beta * tmp) >> 6) >> order1_5x; | ||
476 | y5 = (y5 * tmp) >> order1_5x; | ||
477 | y5 = (y5 * tmp) >> order1_5x; | ||
478 | y5 = (y5 * tmp) >> order1_5x; | ||
479 | y5 = (y5 * tmp) >> order1_5x; | ||
480 | y5 = y5 >> order1_5x_rem; | ||
481 | y3 = (alpha * tmp) >> order2_3x; | ||
482 | y3 = (y3 * tmp) >> order2_3x; | ||
483 | y3 = (y3 * tmp) >> order2_3x; | ||
484 | y3 = y3 >> order2_3x_rem; | ||
485 | PA_in[i] = y5 + y3 + (256 * tmp) / G_fxp; | ||
486 | |||
487 | if (i >= 2) { | ||
488 | tmp = PA_in[i] - PA_in[i - 1]; | ||
489 | if (tmp < 0) | ||
490 | PA_in[i] = | ||
491 | PA_in[i - 1] + (PA_in[i - 1] - | ||
492 | PA_in[i - 2]); | ||
493 | } | ||
494 | |||
495 | PA_in[i] = (PA_in[i] < 1400) ? PA_in[i] : 1400; | ||
496 | } | ||
497 | |||
498 | beta_raw = 0; | ||
499 | alpha_raw = 0; | ||
500 | |||
501 | for (i = 0; i <= L; i++) { | ||
502 | int theta_tilde = | ||
503 | ((theta[i + I] << M) + y_est[i + I]) / y_est[i + I]; | ||
504 | theta_tilde = | ||
505 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
506 | theta_tilde = | ||
507 | ((theta_tilde << M) + y_est[i + I]) / y_est[i + I]; | ||
508 | beta_raw = beta_raw + B1_tmp[i] * theta_tilde; | ||
509 | alpha_raw = alpha_raw + B2_tmp[i] * theta_tilde; | ||
510 | } | ||
511 | |||
512 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | ||
513 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | ||
514 | beta_raw = beta_raw / (1 << Q_beta); | ||
515 | alpha_raw = alpha_raw / (1 << Q_alpha); | ||
516 | |||
517 | alpha = (alpha_raw << 10) / scale_B; | ||
518 | beta = (beta_raw << 10) / scale_B; | ||
519 | order_1 = 3 * M - Q_x - Q_B1 - Q_beta + 10 + Q_scale_B + 5; | ||
520 | order_2 = 3 * M - Q_x - Q_B2 - Q_alpha + 10 + Q_scale_B + 5; | ||
521 | order1_5x = order_1 / 5; | ||
522 | order2_3x = order_2 / 3; | ||
523 | order1_5x_rem = order_1 - 5 * order1_5x; | ||
524 | order2_3x_rem = order_2 - 3 * order2_3x; | ||
525 | |||
526 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
527 | int PA_angle; | ||
528 | |||
529 | /* pa_table[4] is calculated from PA_angle for i=5 */ | ||
530 | if (i == 4) | ||
531 | continue; | ||
532 | |||
533 | tmp = i * 32; | ||
534 | if (beta > 0) | ||
535 | y5 = (((beta * tmp - 64) >> 6) - | ||
536 | (1 << order1_5x)) / (1 << order1_5x); | ||
537 | else | ||
538 | y5 = ((((beta * tmp - 64) >> 6) + | ||
539 | (1 << order1_5x)) / (1 << order1_5x)); | ||
540 | |||
541 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
542 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
543 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
544 | y5 = (y5 * tmp) / (1 << order1_5x); | ||
545 | y5 = y5 / (1 << order1_5x_rem); | ||
546 | |||
547 | if (beta > 0) | ||
548 | y3 = (alpha * tmp - | ||
549 | (1 << order2_3x)) / (1 << order2_3x); | ||
550 | else | ||
551 | y3 = (alpha * tmp + | ||
552 | (1 << order2_3x)) / (1 << order2_3x); | ||
553 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
554 | y3 = (y3 * tmp) / (1 << order2_3x); | ||
555 | y3 = y3 / (1 << order2_3x_rem); | ||
556 | |||
557 | if (i < 4) { | ||
558 | PA_angle = 0; | ||
559 | } else { | ||
560 | PA_angle = y5 + y3; | ||
561 | if (PA_angle < -150) | ||
562 | PA_angle = -150; | ||
563 | else if (PA_angle > 150) | ||
564 | PA_angle = 150; | ||
565 | } | ||
566 | |||
567 | pa_table[i] = ((PA_in[i] & 0x7ff) << 11) + (PA_angle & 0x7ff); | ||
568 | if (i == 5) { | ||
569 | PA_angle = (PA_angle + 2) >> 1; | ||
570 | pa_table[i - 1] = ((PA_in[i - 1] & 0x7ff) << 11) + | ||
571 | (PA_angle & 0x7ff); | ||
572 | } | ||
573 | } | ||
574 | |||
575 | *gain = G_fxp; | ||
576 | return true; | ||
577 | } | ||
578 | |||
579 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
580 | struct ath9k_channel *chan, int chain) | ||
581 | { | ||
582 | u32 *paprd_table_val = chan->pa_table[chain]; | ||
583 | u32 small_signal_gain = chan->small_signal_gain[chain]; | ||
584 | u32 training_power; | ||
585 | u32 reg = 0; | ||
586 | int i; | ||
587 | |||
588 | training_power = | ||
589 | REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
590 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
591 | training_power -= 4; | ||
592 | |||
593 | if (chain == 0) | ||
594 | reg = AR_PHY_PAPRD_MEM_TAB_B0; | ||
595 | else if (chain == 1) | ||
596 | reg = AR_PHY_PAPRD_MEM_TAB_B1; | ||
597 | else if (chain == 2) | ||
598 | reg = AR_PHY_PAPRD_MEM_TAB_B2; | ||
599 | |||
600 | for (i = 0; i < PAPRD_TABLE_SZ; i++) { | ||
601 | REG_WRITE(ah, reg, paprd_table_val[i]); | ||
602 | reg = reg + 4; | ||
603 | } | ||
604 | |||
605 | if (chain == 0) | ||
606 | reg = AR_PHY_PA_GAIN123_B0; | ||
607 | else if (chain == 1) | ||
608 | reg = AR_PHY_PA_GAIN123_B1; | ||
609 | else | ||
610 | reg = AR_PHY_PA_GAIN123_B2; | ||
611 | |||
612 | REG_RMW_FIELD(ah, reg, AR_PHY_PA_GAIN123_PA_GAIN1, small_signal_gain); | ||
613 | |||
614 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B0, | ||
615 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
616 | training_power); | ||
617 | |||
618 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, | ||
619 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
620 | training_power); | ||
621 | |||
622 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, | ||
623 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | ||
624 | training_power); | ||
625 | } | ||
626 | EXPORT_SYMBOL(ar9003_paprd_populate_single_table); | ||
627 | |||
628 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | ||
629 | { | ||
630 | |||
631 | unsigned int i, desired_gain, gain_index; | ||
632 | unsigned int train_power; | ||
633 | |||
634 | train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
635 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
636 | |||
637 | train_power = train_power - 4; | ||
638 | |||
639 | desired_gain = ar9003_get_desired_gain(ah, chain, train_power); | ||
640 | |||
641 | gain_index = 0; | ||
642 | for (i = 0; i < 32; i++) { | ||
643 | if (ah->paprd_gain_table_index[i] >= desired_gain) | ||
644 | break; | ||
645 | gain_index++; | ||
646 | } | ||
647 | |||
648 | ar9003_tx_force_gain(ah, gain_index); | ||
649 | |||
650 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
651 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); | ||
656 | |||
657 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
658 | int chain) | ||
659 | { | ||
660 | u16 *small_signal_gain = &chan->small_signal_gain[chain]; | ||
661 | u32 *pa_table = chan->pa_table[chain]; | ||
662 | u32 *data_L, *data_U; | ||
663 | int i, status = 0; | ||
664 | u32 *buf; | ||
665 | u32 reg; | ||
666 | |||
667 | memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); | ||
668 | |||
669 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); | ||
670 | if (!buf) | ||
671 | return -ENOMEM; | ||
672 | |||
673 | data_L = &buf[0]; | ||
674 | data_U = &buf[48]; | ||
675 | |||
676 | REG_CLR_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
677 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
678 | |||
679 | reg = AR_PHY_CHAN_INFO_TAB_0; | ||
680 | for (i = 0; i < 48; i++) | ||
681 | data_L[i] = REG_READ(ah, reg + (i << 2)); | ||
682 | |||
683 | REG_SET_BIT(ah, AR_PHY_CHAN_INFO_MEMORY, | ||
684 | AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ); | ||
685 | |||
686 | for (i = 0; i < 48; i++) | ||
687 | data_U[i] = REG_READ(ah, reg + (i << 2)); | ||
688 | |||
689 | if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain)) | ||
690 | status = -2; | ||
691 | |||
692 | REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
693 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
694 | |||
695 | kfree(buf); | ||
696 | |||
697 | return status; | ||
698 | } | ||
699 | EXPORT_SYMBOL(ar9003_paprd_create_curve); | ||
700 | |||
701 | int ar9003_paprd_init_table(struct ath_hw *ah) | ||
702 | { | ||
703 | ar9003_paprd_setup_single_table(ah); | ||
704 | ar9003_paprd_get_gain_table(ah); | ||
705 | return 0; | ||
706 | } | ||
707 | EXPORT_SYMBOL(ar9003_paprd_init_table); | ||
708 | |||
709 | bool ar9003_paprd_is_done(struct ath_hw *ah) | ||
710 | { | ||
711 | return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, | ||
712 | AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); | ||
713 | } | ||
714 | EXPORT_SYMBOL(ar9003_paprd_is_done); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c714579b5483..19bc05c41136 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -17,6 +17,28 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9003_phy.h" | 18 | #include "ar9003_phy.h" |
19 | 19 | ||
20 | static const int firstep_table[] = | ||
21 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
22 | { -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */ | ||
23 | |||
24 | static const int cycpwrThr1_table[] = | ||
25 | /* level: 0 1 2 3 4 5 6 7 8 */ | ||
26 | { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ | ||
27 | |||
28 | /* | ||
29 | * register values to turn OFDM weak signal detection OFF | ||
30 | */ | ||
31 | static const int m1ThreshLow_off = 127; | ||
32 | static const int m2ThreshLow_off = 127; | ||
33 | static const int m1Thresh_off = 127; | ||
34 | static const int m2Thresh_off = 127; | ||
35 | static const int m2CountThr_off = 31; | ||
36 | static const int m2CountThrLow_off = 63; | ||
37 | static const int m1ThreshLowExt_off = 127; | ||
38 | static const int m2ThreshLowExt_off = 127; | ||
39 | static const int m1ThreshExt_off = 127; | ||
40 | static const int m2ThreshExt_off = 127; | ||
41 | |||
20 | /** | 42 | /** |
21 | * ar9003_hw_set_channel - set channel on single-chip device | 43 | * ar9003_hw_set_channel - set channel on single-chip device |
22 | * @ah: atheros hardware structure | 44 | * @ah: atheros hardware structure |
@@ -94,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
94 | } | 116 | } |
95 | 117 | ||
96 | /** | 118 | /** |
97 | * ar9003_hw_spur_mitigate - convert baseband spur frequency | 119 | * ar9003_hw_spur_mitigate_mrc_cck - convert baseband spur frequency |
98 | * @ah: atheros hardware structure | 120 | * @ah: atheros hardware structure |
99 | * @chan: | 121 | * @chan: |
100 | * | 122 | * |
@@ -521,15 +543,6 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, | |||
521 | u32 val = INI_RA(iniArr, i, column); | 543 | u32 val = INI_RA(iniArr, i, column); |
522 | 544 | ||
523 | REG_WRITE(ah, reg, val); | 545 | REG_WRITE(ah, reg, val); |
524 | |||
525 | /* | ||
526 | * Determine if this is a shift register value, and insert the | ||
527 | * configured delay if so. | ||
528 | */ | ||
529 | if (reg >= 0x16000 && reg < 0x17000 | ||
530 | && ah->config.analog_shiftreg) | ||
531 | udelay(100); | ||
532 | |||
533 | DO_DELAY(regWrites); | 546 | DO_DELAY(regWrites); |
534 | } | 547 | } |
535 | } | 548 | } |
@@ -732,71 +745,68 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
732 | { | 745 | { |
733 | struct ar5416AniState *aniState = ah->curani; | 746 | struct ar5416AniState *aniState = ah->curani; |
734 | struct ath_common *common = ath9k_hw_common(ah); | 747 | struct ath_common *common = ath9k_hw_common(ah); |
748 | struct ath9k_channel *chan = ah->curchan; | ||
749 | s32 value, value2; | ||
735 | 750 | ||
736 | switch (cmd & ah->ani_function) { | 751 | switch (cmd & ah->ani_function) { |
737 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | ||
738 | u32 level = param; | ||
739 | |||
740 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | ||
741 | ath_print(common, ATH_DBG_ANI, | ||
742 | "level out of range (%u > %u)\n", | ||
743 | level, | ||
744 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); | ||
745 | return false; | ||
746 | } | ||
747 | |||
748 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
749 | AR_PHY_DESIRED_SZ_TOT_DES, | ||
750 | ah->totalSizeDesired[level]); | ||
751 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
752 | AR_PHY_AGC_COARSE_LOW, | ||
753 | ah->coarse_low[level]); | ||
754 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
755 | AR_PHY_AGC_COARSE_HIGH, | ||
756 | ah->coarse_high[level]); | ||
757 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
758 | AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); | ||
759 | |||
760 | if (level > aniState->noiseImmunityLevel) | ||
761 | ah->stats.ast_ani_niup++; | ||
762 | else if (level < aniState->noiseImmunityLevel) | ||
763 | ah->stats.ast_ani_nidown++; | ||
764 | aniState->noiseImmunityLevel = level; | ||
765 | break; | ||
766 | } | ||
767 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | 752 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ |
768 | const int m1ThreshLow[] = { 127, 50 }; | 753 | /* |
769 | const int m2ThreshLow[] = { 127, 40 }; | 754 | * on == 1 means ofdm weak signal detection is ON |
770 | const int m1Thresh[] = { 127, 0x4d }; | 755 | * on == 1 is the default, for less noise immunity |
771 | const int m2Thresh[] = { 127, 0x40 }; | 756 | * |
772 | const int m2CountThr[] = { 31, 16 }; | 757 | * on == 0 means ofdm weak signal detection is OFF |
773 | const int m2CountThrLow[] = { 63, 48 }; | 758 | * on == 0 means more noise imm |
759 | */ | ||
774 | u32 on = param ? 1 : 0; | 760 | u32 on = param ? 1 : 0; |
761 | /* | ||
762 | * make register setting for default | ||
763 | * (weak sig detect ON) come from INI file | ||
764 | */ | ||
765 | int m1ThreshLow = on ? | ||
766 | aniState->iniDef.m1ThreshLow : m1ThreshLow_off; | ||
767 | int m2ThreshLow = on ? | ||
768 | aniState->iniDef.m2ThreshLow : m2ThreshLow_off; | ||
769 | int m1Thresh = on ? | ||
770 | aniState->iniDef.m1Thresh : m1Thresh_off; | ||
771 | int m2Thresh = on ? | ||
772 | aniState->iniDef.m2Thresh : m2Thresh_off; | ||
773 | int m2CountThr = on ? | ||
774 | aniState->iniDef.m2CountThr : m2CountThr_off; | ||
775 | int m2CountThrLow = on ? | ||
776 | aniState->iniDef.m2CountThrLow : m2CountThrLow_off; | ||
777 | int m1ThreshLowExt = on ? | ||
778 | aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; | ||
779 | int m2ThreshLowExt = on ? | ||
780 | aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; | ||
781 | int m1ThreshExt = on ? | ||
782 | aniState->iniDef.m1ThreshExt : m1ThreshExt_off; | ||
783 | int m2ThreshExt = on ? | ||
784 | aniState->iniDef.m2ThreshExt : m2ThreshExt_off; | ||
775 | 785 | ||
776 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 786 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
777 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | 787 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, |
778 | m1ThreshLow[on]); | 788 | m1ThreshLow); |
779 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 789 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
780 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | 790 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, |
781 | m2ThreshLow[on]); | 791 | m2ThreshLow); |
782 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 792 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
783 | AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); | 793 | AR_PHY_SFCORR_M1_THRESH, m1Thresh); |
784 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 794 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
785 | AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); | 795 | AR_PHY_SFCORR_M2_THRESH, m2Thresh); |
786 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | 796 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, |
787 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); | 797 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); |
788 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 798 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
789 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | 799 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, |
790 | m2CountThrLow[on]); | 800 | m2CountThrLow); |
791 | 801 | ||
792 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 802 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
793 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); | 803 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); |
794 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 804 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
795 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); | 805 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); |
796 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 806 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
797 | AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); | 807 | AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); |
798 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | 808 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, |
799 | AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); | 809 | AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); |
800 | 810 | ||
801 | if (on) | 811 | if (on) |
802 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | 812 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, |
@@ -806,6 +816,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
806 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 816 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
807 | 817 | ||
808 | if (!on != aniState->ofdmWeakSigDetectOff) { | 818 | if (!on != aniState->ofdmWeakSigDetectOff) { |
819 | ath_print(common, ATH_DBG_ANI, | ||
820 | "** ch %d: ofdm weak signal: %s=>%s\n", | ||
821 | chan->channel, | ||
822 | !aniState->ofdmWeakSigDetectOff ? | ||
823 | "on" : "off", | ||
824 | on ? "on" : "off"); | ||
809 | if (on) | 825 | if (on) |
810 | ah->stats.ast_ani_ofdmon++; | 826 | ah->stats.ast_ani_ofdmon++; |
811 | else | 827 | else |
@@ -814,64 +830,167 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
814 | } | 830 | } |
815 | break; | 831 | break; |
816 | } | 832 | } |
817 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | ||
818 | const int weakSigThrCck[] = { 8, 6 }; | ||
819 | u32 high = param ? 1 : 0; | ||
820 | |||
821 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | ||
822 | AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, | ||
823 | weakSigThrCck[high]); | ||
824 | if (high != aniState->cckWeakSigThreshold) { | ||
825 | if (high) | ||
826 | ah->stats.ast_ani_cckhigh++; | ||
827 | else | ||
828 | ah->stats.ast_ani_ccklow++; | ||
829 | aniState->cckWeakSigThreshold = high; | ||
830 | } | ||
831 | break; | ||
832 | } | ||
833 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | 833 | case ATH9K_ANI_FIRSTEP_LEVEL:{ |
834 | const int firstep[] = { 0, 4, 8 }; | ||
835 | u32 level = param; | 834 | u32 level = param; |
836 | 835 | ||
837 | if (level >= ARRAY_SIZE(firstep)) { | 836 | if (level >= ARRAY_SIZE(firstep_table)) { |
838 | ath_print(common, ATH_DBG_ANI, | 837 | ath_print(common, ATH_DBG_ANI, |
839 | "level out of range (%u > %u)\n", | 838 | "ATH9K_ANI_FIRSTEP_LEVEL: level " |
839 | "out of range (%u > %u)\n", | ||
840 | level, | 840 | level, |
841 | (unsigned) ARRAY_SIZE(firstep)); | 841 | (unsigned) ARRAY_SIZE(firstep_table)); |
842 | return false; | 842 | return false; |
843 | } | 843 | } |
844 | |||
845 | /* | ||
846 | * make register setting relative to default | ||
847 | * from INI file & cap value | ||
848 | */ | ||
849 | value = firstep_table[level] - | ||
850 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
851 | aniState->iniDef.firstep; | ||
852 | if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
853 | value = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
854 | if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
855 | value = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
844 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | 856 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, |
845 | AR_PHY_FIND_SIG_FIRSTEP, | 857 | AR_PHY_FIND_SIG_FIRSTEP, |
846 | firstep[level]); | 858 | value); |
847 | if (level > aniState->firstepLevel) | 859 | /* |
848 | ah->stats.ast_ani_stepup++; | 860 | * we need to set first step low register too |
849 | else if (level < aniState->firstepLevel) | 861 | * make register setting relative to default |
850 | ah->stats.ast_ani_stepdown++; | 862 | * from INI file & cap value |
851 | aniState->firstepLevel = level; | 863 | */ |
864 | value2 = firstep_table[level] - | ||
865 | firstep_table[ATH9K_ANI_FIRSTEP_LVL_NEW] + | ||
866 | aniState->iniDef.firstepLow; | ||
867 | if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN) | ||
868 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN; | ||
869 | if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX) | ||
870 | value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX; | ||
871 | |||
872 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, | ||
873 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); | ||
874 | |||
875 | if (level != aniState->firstepLevel) { | ||
876 | ath_print(common, ATH_DBG_ANI, | ||
877 | "** ch %d: level %d=>%d[def:%d] " | ||
878 | "firstep[level]=%d ini=%d\n", | ||
879 | chan->channel, | ||
880 | aniState->firstepLevel, | ||
881 | level, | ||
882 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
883 | value, | ||
884 | aniState->iniDef.firstep); | ||
885 | ath_print(common, ATH_DBG_ANI, | ||
886 | "** ch %d: level %d=>%d[def:%d] " | ||
887 | "firstep_low[level]=%d ini=%d\n", | ||
888 | chan->channel, | ||
889 | aniState->firstepLevel, | ||
890 | level, | ||
891 | ATH9K_ANI_FIRSTEP_LVL_NEW, | ||
892 | value2, | ||
893 | aniState->iniDef.firstepLow); | ||
894 | if (level > aniState->firstepLevel) | ||
895 | ah->stats.ast_ani_stepup++; | ||
896 | else if (level < aniState->firstepLevel) | ||
897 | ah->stats.ast_ani_stepdown++; | ||
898 | aniState->firstepLevel = level; | ||
899 | } | ||
852 | break; | 900 | break; |
853 | } | 901 | } |
854 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | 902 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ |
855 | const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
856 | u32 level = param; | 903 | u32 level = param; |
857 | 904 | ||
858 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | 905 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { |
859 | ath_print(common, ATH_DBG_ANI, | 906 | ath_print(common, ATH_DBG_ANI, |
860 | "level out of range (%u > %u)\n", | 907 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " |
908 | "out of range (%u > %u)\n", | ||
861 | level, | 909 | level, |
862 | (unsigned) ARRAY_SIZE(cycpwrThr1)); | 910 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); |
863 | return false; | 911 | return false; |
864 | } | 912 | } |
913 | /* | ||
914 | * make register setting relative to default | ||
915 | * from INI file & cap value | ||
916 | */ | ||
917 | value = cycpwrThr1_table[level] - | ||
918 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
919 | aniState->iniDef.cycpwrThr1; | ||
920 | if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
921 | value = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
922 | if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
923 | value = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
865 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | 924 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, |
866 | AR_PHY_TIMING5_CYCPWR_THR1, | 925 | AR_PHY_TIMING5_CYCPWR_THR1, |
867 | cycpwrThr1[level]); | 926 | value); |
868 | if (level > aniState->spurImmunityLevel) | 927 | |
869 | ah->stats.ast_ani_spurup++; | 928 | /* |
870 | else if (level < aniState->spurImmunityLevel) | 929 | * set AR_PHY_EXT_CCA for extension channel |
871 | ah->stats.ast_ani_spurdown++; | 930 | * make register setting relative to default |
872 | aniState->spurImmunityLevel = level; | 931 | * from INI file & cap value |
932 | */ | ||
933 | value2 = cycpwrThr1_table[level] - | ||
934 | cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL_NEW] + | ||
935 | aniState->iniDef.cycpwrThr1Ext; | ||
936 | if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN) | ||
937 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN; | ||
938 | if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX) | ||
939 | value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX; | ||
940 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, | ||
941 | AR_PHY_EXT_CYCPWR_THR1, value2); | ||
942 | |||
943 | if (level != aniState->spurImmunityLevel) { | ||
944 | ath_print(common, ATH_DBG_ANI, | ||
945 | "** ch %d: level %d=>%d[def:%d] " | ||
946 | "cycpwrThr1[level]=%d ini=%d\n", | ||
947 | chan->channel, | ||
948 | aniState->spurImmunityLevel, | ||
949 | level, | ||
950 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
951 | value, | ||
952 | aniState->iniDef.cycpwrThr1); | ||
953 | ath_print(common, ATH_DBG_ANI, | ||
954 | "** ch %d: level %d=>%d[def:%d] " | ||
955 | "cycpwrThr1Ext[level]=%d ini=%d\n", | ||
956 | chan->channel, | ||
957 | aniState->spurImmunityLevel, | ||
958 | level, | ||
959 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | ||
960 | value2, | ||
961 | aniState->iniDef.cycpwrThr1Ext); | ||
962 | if (level > aniState->spurImmunityLevel) | ||
963 | ah->stats.ast_ani_spurup++; | ||
964 | else if (level < aniState->spurImmunityLevel) | ||
965 | ah->stats.ast_ani_spurdown++; | ||
966 | aniState->spurImmunityLevel = level; | ||
967 | } | ||
873 | break; | 968 | break; |
874 | } | 969 | } |
970 | case ATH9K_ANI_MRC_CCK:{ | ||
971 | /* | ||
972 | * is_on == 1 means MRC CCK ON (default, less noise imm) | ||
973 | * is_on == 0 means MRC CCK is OFF (more noise imm) | ||
974 | */ | ||
975 | bool is_on = param ? 1 : 0; | ||
976 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | ||
977 | AR_PHY_MRC_CCK_ENABLE, is_on); | ||
978 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | ||
979 | AR_PHY_MRC_CCK_MUX_REG, is_on); | ||
980 | if (!is_on != aniState->mrcCCKOff) { | ||
981 | ath_print(common, ATH_DBG_ANI, | ||
982 | "** ch %d: MRC CCK: %s=>%s\n", | ||
983 | chan->channel, | ||
984 | !aniState->mrcCCKOff ? "on" : "off", | ||
985 | is_on ? "on" : "off"); | ||
986 | if (is_on) | ||
987 | ah->stats.ast_ani_ccklow++; | ||
988 | else | ||
989 | ah->stats.ast_ani_cckhigh++; | ||
990 | aniState->mrcCCKOff = !is_on; | ||
991 | } | ||
992 | break; | ||
993 | } | ||
875 | case ATH9K_ANI_PRESENT: | 994 | case ATH9K_ANI_PRESENT: |
876 | break; | 995 | break; |
877 | default: | 996 | default: |
@@ -880,25 +999,19 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
880 | return false; | 999 | return false; |
881 | } | 1000 | } |
882 | 1001 | ||
883 | ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); | ||
884 | ath_print(common, ATH_DBG_ANI, | 1002 | ath_print(common, ATH_DBG_ANI, |
885 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | 1003 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " |
886 | "ofdmWeakSigDetectOff=%d\n", | 1004 | "MRCcck=%s listenTime=%d CC=%d listen=%d " |
887 | aniState->noiseImmunityLevel, | 1005 | "ofdmErrs=%d cckErrs=%d\n", |
888 | aniState->spurImmunityLevel, | 1006 | aniState->spurImmunityLevel, |
889 | !aniState->ofdmWeakSigDetectOff); | 1007 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
890 | ath_print(common, ATH_DBG_ANI, | ||
891 | "cckWeakSigThreshold=%d, " | ||
892 | "firstepLevel=%d, listenTime=%d\n", | ||
893 | aniState->cckWeakSigThreshold, | ||
894 | aniState->firstepLevel, | 1008 | aniState->firstepLevel, |
895 | aniState->listenTime); | 1009 | !aniState->mrcCCKOff ? "on" : "off", |
896 | ath_print(common, ATH_DBG_ANI, | 1010 | aniState->listenTime, |
897 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | 1011 | aniState->cycleCount, |
898 | aniState->cycleCount, | 1012 | aniState->listenTime, |
899 | aniState->ofdmPhyErrCount, | 1013 | aniState->ofdmPhyErrCount, |
900 | aniState->cckPhyErrCount); | 1014 | aniState->cckPhyErrCount); |
901 | |||
902 | return true; | 1015 | return true; |
903 | } | 1016 | } |
904 | 1017 | ||
@@ -1111,6 +1224,70 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1111 | } | 1224 | } |
1112 | } | 1225 | } |
1113 | 1226 | ||
1227 | /* | ||
1228 | * Initialize the ANI register values with default (ini) values. | ||
1229 | * This routine is called during a (full) hardware reset after | ||
1230 | * all the registers are initialised from the INI. | ||
1231 | */ | ||
1232 | static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
1233 | { | ||
1234 | struct ar5416AniState *aniState; | ||
1235 | struct ath_common *common = ath9k_hw_common(ah); | ||
1236 | struct ath9k_channel *chan = ah->curchan; | ||
1237 | struct ath9k_ani_default *iniDef; | ||
1238 | int index; | ||
1239 | u32 val; | ||
1240 | |||
1241 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1242 | aniState = &ah->ani[index]; | ||
1243 | ah->curani = aniState; | ||
1244 | iniDef = &aniState->iniDef; | ||
1245 | |||
1246 | ath_print(common, ATH_DBG_ANI, | ||
1247 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | ||
1248 | ah->hw_version.macVersion, | ||
1249 | ah->hw_version.macRev, | ||
1250 | ah->opmode, | ||
1251 | chan->channel, | ||
1252 | chan->channelFlags); | ||
1253 | |||
1254 | val = REG_READ(ah, AR_PHY_SFCORR); | ||
1255 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | ||
1256 | iniDef->m2Thresh = MS(val, AR_PHY_SFCORR_M2_THRESH); | ||
1257 | iniDef->m2CountThr = MS(val, AR_PHY_SFCORR_M2COUNT_THR); | ||
1258 | |||
1259 | val = REG_READ(ah, AR_PHY_SFCORR_LOW); | ||
1260 | iniDef->m1ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M1_THRESH_LOW); | ||
1261 | iniDef->m2ThreshLow = MS(val, AR_PHY_SFCORR_LOW_M2_THRESH_LOW); | ||
1262 | iniDef->m2CountThrLow = MS(val, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW); | ||
1263 | |||
1264 | val = REG_READ(ah, AR_PHY_SFCORR_EXT); | ||
1265 | iniDef->m1ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH); | ||
1266 | iniDef->m2ThreshExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH); | ||
1267 | iniDef->m1ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M1_THRESH_LOW); | ||
1268 | iniDef->m2ThreshLowExt = MS(val, AR_PHY_SFCORR_EXT_M2_THRESH_LOW); | ||
1269 | iniDef->firstep = REG_READ_FIELD(ah, | ||
1270 | AR_PHY_FIND_SIG, | ||
1271 | AR_PHY_FIND_SIG_FIRSTEP); | ||
1272 | iniDef->firstepLow = REG_READ_FIELD(ah, | ||
1273 | AR_PHY_FIND_SIG_LOW, | ||
1274 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW); | ||
1275 | iniDef->cycpwrThr1 = REG_READ_FIELD(ah, | ||
1276 | AR_PHY_TIMING5, | ||
1277 | AR_PHY_TIMING5_CYCPWR_THR1); | ||
1278 | iniDef->cycpwrThr1Ext = REG_READ_FIELD(ah, | ||
1279 | AR_PHY_EXT_CCA, | ||
1280 | AR_PHY_EXT_CYCPWR_THR1); | ||
1281 | |||
1282 | /* these levels just got reset to defaults by the INI */ | ||
1283 | aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
1284 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1285 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | ||
1286 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; | ||
1287 | |||
1288 | aniState->cycleCount = 0; | ||
1289 | } | ||
1290 | |||
1114 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1291 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1115 | { | 1292 | { |
1116 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1293 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -1131,6 +1308,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1131 | priv_ops->ani_control = ar9003_hw_ani_control; | 1308 | priv_ops->ani_control = ar9003_hw_ani_control; |
1132 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 1309 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
1133 | priv_ops->loadnf = ar9003_hw_loadnf; | 1310 | priv_ops->loadnf = ar9003_hw_loadnf; |
1311 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | ||
1134 | } | 1312 | } |
1135 | 1313 | ||
1136 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | 1314 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 676d3f1123f4..3394dfe52b42 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -149,6 +149,8 @@ | |||
149 | #define AR_PHY_EXT_CCA_THRESH62_S 16 | 149 | #define AR_PHY_EXT_CCA_THRESH62_S 16 |
150 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 | 150 | #define AR_PHY_EXT_MINCCA_PWR 0x01FF0000 |
151 | #define AR_PHY_EXT_MINCCA_PWR_S 16 | 151 | #define AR_PHY_EXT_MINCCA_PWR_S 16 |
152 | #define AR_PHY_EXT_CYCPWR_THR1 0x0000FE00L | ||
153 | #define AR_PHY_EXT_CYCPWR_THR1_S 9 | ||
152 | #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE | 154 | #define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE |
153 | #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 | 155 | #define AR_PHY_TIMING5_CYCPWR_THR1_S 1 |
154 | #define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 | 156 | #define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001 |
@@ -283,6 +285,12 @@ | |||
283 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 | 285 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00 |
284 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 | 286 | #define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9 |
285 | 287 | ||
288 | #define AR_PHY_MRC_CCK_CTRL (AR_AGC_BASE + 0x1d0) | ||
289 | #define AR_PHY_MRC_CCK_ENABLE 0x00000001 | ||
290 | #define AR_PHY_MRC_CCK_ENABLE_S 0 | ||
291 | #define AR_PHY_MRC_CCK_MUX_REG 0x00000002 | ||
292 | #define AR_PHY_MRC_CCK_MUX_REG_S 1 | ||
293 | |||
286 | #define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) | 294 | #define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200) |
287 | 295 | ||
288 | #define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 | 296 | #define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110 |
@@ -451,7 +459,11 @@ | |||
451 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) | 459 | #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) |
452 | 460 | ||
453 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) | 461 | #define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c) |
454 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) | 462 | |
463 | #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170) | ||
464 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008 | ||
465 | #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3 | ||
466 | |||
455 | #define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) | 467 | #define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174) |
456 | #define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) | 468 | #define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178) |
457 | #define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) | 469 | #define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c) |
@@ -467,17 +479,63 @@ | |||
467 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) | 479 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) |
468 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) | 480 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) |
469 | 481 | ||
470 | #define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) | 482 | #define AR_PHY_TPC_1 (AR_SM_BASE + 0x1f8) |
471 | #define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) | 483 | #define AR_PHY_TPC_1_FORCED_DAC_GAIN 0x0000003e |
472 | #define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) | 484 | #define AR_PHY_TPC_1_FORCED_DAC_GAIN_S 1 |
473 | #define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) | 485 | #define AR_PHY_TPC_1_FORCE_DAC_GAIN 0x00000001 |
474 | #define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) | 486 | #define AR_PHY_TPC_1_FORCE_DAC_GAIN_S 0 |
475 | #define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) | 487 | |
488 | #define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204) | ||
489 | #define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208) | ||
490 | #define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c) | ||
491 | |||
492 | #define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220) | ||
493 | #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) | ||
494 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) | ||
495 | #define AR_PHY_TPC_11_OLPC_GAIN_DELTA 0x00ff0000 | ||
496 | #define AR_PHY_TPC_11_OLPC_GAIN_DELTA_S 16 | ||
497 | |||
498 | #define AR_PHY_TPC_12 (AR_SM_BASE + 0x224) | ||
499 | #define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5 0x3e000000 | ||
500 | #define AR_PHY_TPC_12_DESIRED_SCALE_HT40_5_S 25 | ||
501 | |||
502 | #define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c) | ||
503 | #define AR_PHY_TPC_18_THERM_CAL_VALUE 0x000000ff | ||
504 | #define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 | ||
505 | #define AR_PHY_TPC_18_VOLT_CAL_VALUE 0x0000ff00 | ||
506 | #define AR_PHY_TPC_18_VOLT_CAL_VALUE_S 8 | ||
507 | |||
508 | #define AR_PHY_TPC_19 (AR_SM_BASE + 0x240) | ||
509 | #define AR_PHY_TPC_19_ALPHA_VOLT 0x001f0000 | ||
510 | #define AR_PHY_TPC_19_ALPHA_VOLT_S 16 | ||
511 | #define AR_PHY_TPC_19_ALPHA_THERM 0xff | ||
512 | #define AR_PHY_TPC_19_ALPHA_THERM_S 0 | ||
513 | |||
514 | #define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) | ||
515 | #define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN 0x00000001 | ||
516 | #define AR_PHY_TX_FORCED_GAIN_FORCE_TX_GAIN_S 0 | ||
517 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN 0x0000000e | ||
518 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB1DBGAIN_S 1 | ||
519 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN 0x00000030 | ||
520 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXBB6DBGAIN_S 4 | ||
521 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN 0x000003c0 | ||
522 | #define AR_PHY_TX_FORCED_GAIN_FORCED_TXMXRGAIN_S 6 | ||
523 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA 0x00003c00 | ||
524 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNA_S 10 | ||
525 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB 0x0003c000 | ||
526 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNB_S 14 | ||
527 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC 0x003c0000 | ||
528 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGNC_S 18 | ||
529 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND 0x00c00000 | ||
530 | #define AR_PHY_TX_FORCED_GAIN_FORCED_PADRVGND_S 22 | ||
531 | #define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL 0x01000000 | ||
532 | #define AR_PHY_TX_FORCED_GAIN_FORCED_ENABLE_PAL_S 24 | ||
476 | 533 | ||
477 | #define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258) | ||
478 | 534 | ||
479 | #define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) | 535 | #define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280) |
480 | 536 | ||
537 | #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) | ||
538 | |||
481 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) | 539 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) |
482 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) | 540 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) |
483 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) | 541 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) |
@@ -490,7 +548,17 @@ | |||
490 | #define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) | 548 | #define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) |
491 | #define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) | 549 | #define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) |
492 | #define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) | 550 | #define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) |
493 | #define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) | 551 | |
552 | #define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248) | ||
553 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff | ||
554 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 | ||
555 | |||
556 | #define AR_PHY_BB_THERM_ADC_4 (AR_SM_BASE + 0x254) | ||
557 | #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE 0x000000ff | ||
558 | #define AR_PHY_BB_THERM_ADC_4_LATEST_THERM_VALUE_S 0 | ||
559 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE 0x0000ff00 | ||
560 | #define AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE_S 8 | ||
561 | |||
494 | 562 | ||
495 | #define AR_PHY_65NM_CH0_SYNTH4 0x1608c | 563 | #define AR_PHY_65NM_CH0_SYNTH4 0x1608c |
496 | #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 | 564 | #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002 |
@@ -660,17 +728,9 @@ | |||
660 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff | 728 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff |
661 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 | 729 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 |
662 | 730 | ||
663 | #define AR_PHY_TPC_18_THERM_CAL_VALUE 0xff | ||
664 | #define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0 | ||
665 | #define AR_PHY_TPC_19_ALPHA_THERM 0xff | ||
666 | #define AR_PHY_TPC_19_ALPHA_THERM_S 0 | ||
667 | |||
668 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 | 731 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 |
669 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 | 732 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 |
670 | 733 | ||
671 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff | ||
672 | #define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0 | ||
673 | |||
674 | /* | 734 | /* |
675 | * Channel 1 Register Map | 735 | * Channel 1 Register Map |
676 | */ | 736 | */ |
@@ -842,6 +902,144 @@ | |||
842 | 902 | ||
843 | #define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008 | 903 | #define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008 |
844 | 904 | ||
905 | /* | ||
906 | * PAPRD registers | ||
907 | */ | ||
908 | #define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64) | ||
909 | |||
910 | #define AR_PHY_PAPRD_AM2AM (AR_CHAN_BASE + 0xe4) | ||
911 | #define AR_PHY_PAPRD_AM2AM_MASK 0x01ffffff | ||
912 | #define AR_PHY_PAPRD_AM2AM_MASK_S 0 | ||
913 | |||
914 | #define AR_PHY_PAPRD_AM2PM (AR_CHAN_BASE + 0xe8) | ||
915 | #define AR_PHY_PAPRD_AM2PM_MASK 0x01ffffff | ||
916 | #define AR_PHY_PAPRD_AM2PM_MASK_S 0 | ||
917 | |||
918 | #define AR_PHY_PAPRD_HT40 (AR_CHAN_BASE + 0xec) | ||
919 | #define AR_PHY_PAPRD_HT40_MASK 0x01ffffff | ||
920 | #define AR_PHY_PAPRD_HT40_MASK_S 0 | ||
921 | |||
922 | #define AR_PHY_PAPRD_CTRL0_B0 (AR_CHAN_BASE + 0xf0) | ||
923 | #define AR_PHY_PAPRD_CTRL0_B1 (AR_CHAN1_BASE + 0xf0) | ||
924 | #define AR_PHY_PAPRD_CTRL0_B2 (AR_CHAN2_BASE + 0xf0) | ||
925 | #define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE 0x00000001 | ||
926 | #define AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE_S 0 | ||
927 | #define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK 0x00000002 | ||
928 | #define AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK_S 1 | ||
929 | #define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH 0xf8000000 | ||
930 | #define AR_PHY_PAPRD_CTRL0_PAPRD_MAG_THRSH_S 27 | ||
931 | |||
932 | #define AR_PHY_PAPRD_CTRL1_B0 (AR_CHAN_BASE + 0xf4) | ||
933 | #define AR_PHY_PAPRD_CTRL1_B1 (AR_CHAN1_BASE + 0xf4) | ||
934 | #define AR_PHY_PAPRD_CTRL1_B2 (AR_CHAN2_BASE + 0xf4) | ||
935 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA 0x00000001 | ||
936 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_SCALING_ENA_S 0 | ||
937 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE 0x00000002 | ||
938 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2AM_ENABLE_S 1 | ||
939 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE 0x00000004 | ||
940 | #define AR_PHY_PAPRD_CTRL1_ADAPTIVE_AM2PM_ENABLE_S 2 | ||
941 | #define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL 0x000001f8 | ||
942 | #define AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL_S 3 | ||
943 | #define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK 0x0001fe00 | ||
944 | #define AR_PHY_PAPRD_CTRL1_PA_GAIN_SCALE_FACT_MASK_S 9 | ||
945 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 | ||
946 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 | ||
947 | |||
948 | #define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + 0x490) | ||
949 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 | ||
950 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 | ||
951 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e | ||
952 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING_S 1 | ||
953 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE 0x00000100 | ||
954 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_IQCORR_ENABLE_S 8 | ||
955 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE 0x00000200 | ||
956 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_RX_BB_GAIN_FORCE_S 9 | ||
957 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE 0x00000400 | ||
958 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_TX_GAIN_FORCE_S 10 | ||
959 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE 0x00000800 | ||
960 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_ENABLE_S 11 | ||
961 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 | ||
962 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 | ||
963 | |||
964 | #define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + 0x494) | ||
965 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF | ||
966 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 | ||
967 | |||
968 | #define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + 0x498) | ||
969 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f | ||
970 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 | ||
971 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 | ||
972 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP_S 6 | ||
973 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL 0x0001f000 | ||
974 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL_S 12 | ||
975 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES 0x000e0000 | ||
976 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES_S 17 | ||
977 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN 0x00f00000 | ||
978 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_COARSE_CORR_LEN_S 20 | ||
979 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN 0x0f000000 | ||
980 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_FINE_CORR_LEN_S 24 | ||
981 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 | ||
982 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 | ||
983 | |||
984 | #define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + 0x49c) | ||
985 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 | ||
986 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 | ||
987 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 | ||
988 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA_S 12 | ||
989 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR 0x00000fff | ||
990 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_MIN_CORR_S 0 | ||
991 | |||
992 | #define AR_PHY_PAPRD_PRE_POST_SCALE_0_B0 (AR_CHAN_BASE + 0x100) | ||
993 | #define AR_PHY_PAPRD_PRE_POST_SCALE_1_B0 (AR_CHAN_BASE + 0x104) | ||
994 | #define AR_PHY_PAPRD_PRE_POST_SCALE_2_B0 (AR_CHAN_BASE + 0x108) | ||
995 | #define AR_PHY_PAPRD_PRE_POST_SCALE_3_B0 (AR_CHAN_BASE + 0x10c) | ||
996 | #define AR_PHY_PAPRD_PRE_POST_SCALE_4_B0 (AR_CHAN_BASE + 0x110) | ||
997 | #define AR_PHY_PAPRD_PRE_POST_SCALE_5_B0 (AR_CHAN_BASE + 0x114) | ||
998 | #define AR_PHY_PAPRD_PRE_POST_SCALE_6_B0 (AR_CHAN_BASE + 0x118) | ||
999 | #define AR_PHY_PAPRD_PRE_POST_SCALE_7_B0 (AR_CHAN_BASE + 0x11c) | ||
1000 | #define AR_PHY_PAPRD_PRE_POST_SCALING 0x3FFFF | ||
1001 | #define AR_PHY_PAPRD_PRE_POST_SCALING_S 0 | ||
1002 | |||
1003 | #define AR_PHY_PAPRD_TRAINER_STAT1 (AR_SM_BASE + 0x4a0) | ||
1004 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE 0x00000001 | ||
1005 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE_S 0 | ||
1006 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE 0x00000002 | ||
1007 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_INCOMPLETE_S 1 | ||
1008 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR 0x00000004 | ||
1009 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_CORR_ERR_S 2 | ||
1010 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE 0x00000008 | ||
1011 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_ACTIVE_S 3 | ||
1012 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX 0x000001f0 | ||
1013 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_RX_GAIN_IDX_S 4 | ||
1014 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR 0x0001fe00 | ||
1015 | #define AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR_S 9 | ||
1016 | |||
1017 | #define AR_PHY_PAPRD_TRAINER_STAT2 (AR_SM_BASE + 0x4a4) | ||
1018 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL 0x0000ffff | ||
1019 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_VAL_S 0 | ||
1020 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX 0x001f0000 | ||
1021 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_COARSE_IDX_S 16 | ||
1022 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX 0x00600000 | ||
1023 | #define AR_PHY_PAPRD_TRAINER_STAT2_PAPRD_FINE_IDX_S 21 | ||
1024 | |||
1025 | #define AR_PHY_PAPRD_TRAINER_STAT3 (AR_SM_BASE + 0x4a8) | ||
1026 | #define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT 0x000fffff | ||
1027 | #define AR_PHY_PAPRD_TRAINER_STAT3_PAPRD_TRAIN_SAMPLES_CNT_S 0 | ||
1028 | |||
1029 | #define AR_PHY_PAPRD_MEM_TAB_B0 (AR_CHAN_BASE + 0x120) | ||
1030 | #define AR_PHY_PAPRD_MEM_TAB_B1 (AR_CHAN1_BASE + 0x120) | ||
1031 | #define AR_PHY_PAPRD_MEM_TAB_B2 (AR_CHAN2_BASE + 0x120) | ||
1032 | |||
1033 | #define AR_PHY_PA_GAIN123_B0 (AR_CHAN_BASE + 0xf8) | ||
1034 | #define AR_PHY_PA_GAIN123_B1 (AR_CHAN1_BASE + 0xf8) | ||
1035 | #define AR_PHY_PA_GAIN123_B2 (AR_CHAN2_BASE + 0xf8) | ||
1036 | #define AR_PHY_PA_GAIN123_PA_GAIN1 0x3FF | ||
1037 | #define AR_PHY_PA_GAIN123_PA_GAIN1_S 0 | ||
1038 | |||
1039 | #define AR_PHY_POWERTX_RATE5 (AR_SM_BASE + 0x1d0) | ||
1040 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F | ||
1041 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 | ||
1042 | |||
845 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | 1043 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); |
846 | 1044 | ||
847 | #endif /* AR9003_PHY_H */ | 1045 | #endif /* AR9003_PHY_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 82aca4b6154c..8d163ae4255e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/leds.h> | 22 | #include <linux/leds.h> |
23 | #include <linux/completion.h> | ||
23 | 24 | ||
24 | #include "debug.h" | 25 | #include "debug.h" |
25 | #include "common.h" | 26 | #include "common.h" |
@@ -194,6 +195,7 @@ enum ATH_AGGR_STATUS { | |||
194 | 195 | ||
195 | #define ATH_TXFIFO_DEPTH 8 | 196 | #define ATH_TXFIFO_DEPTH 8 |
196 | struct ath_txq { | 197 | struct ath_txq { |
198 | int axq_class; | ||
197 | u32 axq_qnum; | 199 | u32 axq_qnum; |
198 | u32 *axq_link; | 200 | u32 *axq_link; |
199 | struct list_head axq_q; | 201 | struct list_head axq_q; |
@@ -206,7 +208,6 @@ struct ath_txq { | |||
206 | struct list_head txq_fifo_pending; | 208 | struct list_head txq_fifo_pending; |
207 | u8 txq_headidx; | 209 | u8 txq_headidx; |
208 | u8 txq_tailidx; | 210 | u8 txq_tailidx; |
209 | int pending_frames; | ||
210 | }; | 211 | }; |
211 | 212 | ||
212 | struct ath_atx_ac { | 213 | struct ath_atx_ac { |
@@ -224,6 +225,7 @@ struct ath_buf_state { | |||
224 | int bfs_tidno; | 225 | int bfs_tidno; |
225 | int bfs_retries; | 226 | int bfs_retries; |
226 | u8 bf_type; | 227 | u8 bf_type; |
228 | u8 bfs_paprd; | ||
227 | u32 bfs_keyix; | 229 | u32 bfs_keyix; |
228 | enum ath9k_key_type bfs_keytype; | 230 | enum ath9k_key_type bfs_keytype; |
229 | }; | 231 | }; |
@@ -244,7 +246,6 @@ struct ath_buf { | |||
244 | struct ath_buf_state bf_state; | 246 | struct ath_buf_state bf_state; |
245 | dma_addr_t bf_dmacontext; | 247 | dma_addr_t bf_dmacontext; |
246 | struct ath_wiphy *aphy; | 248 | struct ath_wiphy *aphy; |
247 | struct ath_txq *txq; | ||
248 | }; | 249 | }; |
249 | 250 | ||
250 | struct ath_atx_tid { | 251 | struct ath_atx_tid { |
@@ -281,6 +282,7 @@ struct ath_tx_control { | |||
281 | struct ath_txq *txq; | 282 | struct ath_txq *txq; |
282 | int if_id; | 283 | int if_id; |
283 | enum ath9k_internal_frame_type frame_type; | 284 | enum ath9k_internal_frame_type frame_type; |
285 | u8 paprd; | ||
284 | }; | 286 | }; |
285 | 287 | ||
286 | #define ATH_TX_ERROR 0x01 | 288 | #define ATH_TX_ERROR 0x01 |
@@ -290,11 +292,12 @@ struct ath_tx_control { | |||
290 | struct ath_tx { | 292 | struct ath_tx { |
291 | u16 seq_no; | 293 | u16 seq_no; |
292 | u32 txqsetup; | 294 | u32 txqsetup; |
293 | int hwq_map[ATH9K_WME_AC_VO+1]; | 295 | int hwq_map[WME_NUM_AC]; |
294 | spinlock_t txbuflock; | 296 | spinlock_t txbuflock; |
295 | struct list_head txbuf; | 297 | struct list_head txbuf; |
296 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; | 298 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; |
297 | struct ath_descdma txdma; | 299 | struct ath_descdma txdma; |
300 | int pending_frames[WME_NUM_AC]; | ||
298 | }; | 301 | }; |
299 | 302 | ||
300 | struct ath_rx_edma { | 303 | struct ath_rx_edma { |
@@ -417,10 +420,12 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
417 | 420 | ||
418 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | 421 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ |
419 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 422 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
420 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ | 423 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ |
424 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ | ||
421 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 425 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
422 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 426 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
423 | 427 | ||
428 | void ath_paprd_calibrate(struct work_struct *work); | ||
424 | void ath_ani_calibrate(unsigned long data); | 429 | void ath_ani_calibrate(unsigned long data); |
425 | 430 | ||
426 | /**********/ | 431 | /**********/ |
@@ -552,6 +557,9 @@ struct ath_softc { | |||
552 | spinlock_t sc_serial_rw; | 557 | spinlock_t sc_serial_rw; |
553 | spinlock_t sc_pm_lock; | 558 | spinlock_t sc_pm_lock; |
554 | struct mutex mutex; | 559 | struct mutex mutex; |
560 | struct work_struct paprd_work; | ||
561 | struct completion paprd_complete; | ||
562 | int paprd_txok; | ||
555 | 563 | ||
556 | u32 intrstatus; | 564 | u32 intrstatus; |
557 | u32 sc_flags; /* SC_OP_* */ | 565 | u32 sc_flags; /* SC_OP_* */ |
@@ -610,7 +618,6 @@ struct ath_wiphy { | |||
610 | 618 | ||
611 | void ath9k_tasklet(unsigned long data); | 619 | void ath9k_tasklet(unsigned long data); |
612 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 620 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
613 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | ||
614 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 621 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
615 | int ath_cabq_update(struct ath_softc *); | 622 | int ath_cabq_update(struct ath_softc *); |
616 | 623 | ||
@@ -626,8 +633,6 @@ irqreturn_t ath_isr(int irq, void *dev); | |||
626 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | 633 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
627 | const struct ath_bus_ops *bus_ops); | 634 | const struct ath_bus_ops *bus_ops); |
628 | void ath9k_deinit_device(struct ath_softc *sc); | 635 | void ath9k_deinit_device(struct ath_softc *sc); |
629 | const char *ath_mac_bb_name(u32 mac_bb_version); | ||
630 | const char *ath_rf_name(u16 rf_version); | ||
631 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 636 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
632 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | 637 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, |
633 | struct ath9k_channel *ichan); | 638 | struct ath9k_channel *ichan); |
@@ -678,8 +683,6 @@ void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); | |||
678 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | 683 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); |
679 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | 684 | void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); |
680 | 685 | ||
681 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | ||
682 | |||
683 | void ath_start_rfkill_poll(struct ath_softc *sc); | 686 | void ath_start_rfkill_poll(struct ath_softc *sc); |
684 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 687 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
685 | 688 | ||
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index f43d85a302c4..4d4b22d52dfd 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -38,8 +38,7 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
38 | qi.tqi_cwmax = 0; | 38 | qi.tqi_cwmax = 0; |
39 | } else { | 39 | } else { |
40 | /* Adhoc mode; important thing is to use 2x cwmin. */ | 40 | /* Adhoc mode; important thing is to use 2x cwmin. */ |
41 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, | 41 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
42 | ATH9K_WME_AC_BE); | ||
43 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | 42 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); |
44 | qi.tqi_aifs = qi_be.tqi_aifs; | 43 | qi.tqi_aifs = qi_be.tqi_aifs; |
45 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | 44 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index a127bdba5f90..54aae931424e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -630,10 +630,10 @@ static const struct file_operations fops_wiphy = { | |||
630 | do { \ | 630 | do { \ |
631 | len += snprintf(buf + len, size - len, \ | 631 | len += snprintf(buf + len, size - len, \ |
632 | "%s%13u%11u%10u%10u\n", str, \ | 632 | "%s%13u%11u%10u%10u\n", str, \ |
633 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \ | 633 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ |
634 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \ | 634 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ |
635 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \ | 635 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ |
636 | sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \ | 636 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ |
637 | } while(0) | 637 | } while(0) |
638 | 638 | ||
639 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | 639 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, |
@@ -956,6 +956,10 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
956 | sc->debug.debugfs_phy, sc, &fops_regval)) | 956 | sc->debug.debugfs_phy, sc, &fops_regval)) |
957 | goto err; | 957 | goto err; |
958 | 958 | ||
959 | if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, | ||
960 | sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) | ||
961 | goto err; | ||
962 | |||
959 | sc->debug.regidx = 0; | 963 | sc->debug.regidx = 0; |
960 | return 0; | 964 | return 0; |
961 | err: | 965 | err: |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7da7d73c0847..bdd8aa054b80 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -263,7 +263,8 @@ enum eeprom_param { | |||
263 | EEP_PWR_TABLE_OFFSET, | 263 | EEP_PWR_TABLE_OFFSET, |
264 | EEP_DRIVE_STRENGTH, | 264 | EEP_DRIVE_STRENGTH, |
265 | EEP_INTERNAL_REGULATOR, | 265 | EEP_INTERNAL_REGULATOR, |
266 | EEP_SWREG | 266 | EEP_SWREG, |
267 | EEP_PAPRD, | ||
267 | }; | 268 | }; |
268 | 269 | ||
269 | enum ar5416_rates { | 270 | enum ar5416_rates { |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 051b8d89b9f2..58f52a1dc7ea 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -223,15 +223,6 @@ struct ath9k_htc_sta { | |||
223 | enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; | 223 | enum tid_aggr_state tid_state[ATH9K_HTC_MAX_TID]; |
224 | }; | 224 | }; |
225 | 225 | ||
226 | struct ath9k_htc_aggr_work { | ||
227 | u16 tid; | ||
228 | u8 sta_addr[ETH_ALEN]; | ||
229 | struct ieee80211_hw *hw; | ||
230 | struct ieee80211_vif *vif; | ||
231 | enum ieee80211_ampdu_mlme_action action; | ||
232 | struct mutex mutex; | ||
233 | }; | ||
234 | |||
235 | #define ATH9K_HTC_RXBUF 256 | 226 | #define ATH9K_HTC_RXBUF 256 |
236 | #define HTC_RX_FRAME_HEADER_SIZE 40 | 227 | #define HTC_RX_FRAME_HEADER_SIZE 40 |
237 | 228 | ||
@@ -331,11 +322,10 @@ struct htc_beacon_config { | |||
331 | #define OP_LED_ON BIT(4) | 322 | #define OP_LED_ON BIT(4) |
332 | #define OP_PREAMBLE_SHORT BIT(5) | 323 | #define OP_PREAMBLE_SHORT BIT(5) |
333 | #define OP_PROTECT_ENABLE BIT(6) | 324 | #define OP_PROTECT_ENABLE BIT(6) |
334 | #define OP_TXAGGR BIT(7) | 325 | #define OP_ASSOCIATED BIT(7) |
335 | #define OP_ASSOCIATED BIT(8) | 326 | #define OP_ENABLE_BEACON BIT(8) |
336 | #define OP_ENABLE_BEACON BIT(9) | 327 | #define OP_LED_DEINIT BIT(9) |
337 | #define OP_LED_DEINIT BIT(10) | 328 | #define OP_UNPLUGGED BIT(10) |
338 | #define OP_UNPLUGGED BIT(11) | ||
339 | 329 | ||
340 | struct ath9k_htc_priv { | 330 | struct ath9k_htc_priv { |
341 | struct device *dev; | 331 | struct device *dev; |
@@ -376,8 +366,6 @@ struct ath9k_htc_priv { | |||
376 | struct ath9k_htc_rx rx; | 366 | struct ath9k_htc_rx rx; |
377 | struct tasklet_struct tx_tasklet; | 367 | struct tasklet_struct tx_tasklet; |
378 | struct sk_buff_head tx_queue; | 368 | struct sk_buff_head tx_queue; |
379 | struct ath9k_htc_aggr_work aggr_work; | ||
380 | struct delayed_work ath9k_aggr_work; | ||
381 | struct delayed_work ath9k_ani_work; | 369 | struct delayed_work ath9k_ani_work; |
382 | struct work_struct ps_work; | 370 | struct work_struct ps_work; |
383 | 371 | ||
@@ -398,7 +386,7 @@ struct ath9k_htc_priv { | |||
398 | 386 | ||
399 | int beaconq; | 387 | int beaconq; |
400 | int cabq; | 388 | int cabq; |
401 | int hwq_map[ATH9K_WME_AC_VO+1]; | 389 | int hwq_map[WME_NUM_AC]; |
402 | 390 | ||
403 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 391 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
404 | struct ath9k_debug debug; | 392 | struct ath9k_debug debug; |
@@ -431,8 +419,7 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv); | |||
431 | void ath9k_tx_tasklet(unsigned long data); | 419 | void ath9k_tx_tasklet(unsigned long data); |
432 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); | 420 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); |
433 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); | 421 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); |
434 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | 422 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); |
435 | enum ath9k_tx_queue_subtype qtype); | ||
436 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); | 423 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); |
437 | int get_hw_qnum(u16 queue, int *hwq_map); | 424 | int get_hw_qnum(u16 queue, int *hwq_map); |
438 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 425 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 12a3bb0a9159..bd1506e69105 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -227,7 +227,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | |||
227 | { | 227 | { |
228 | struct ath_hw *ah = priv->ah; | 228 | struct ath_hw *ah = priv->ah; |
229 | struct ath9k_tx_queue_info qi, qi_be; | 229 | struct ath9k_tx_queue_info qi, qi_be; |
230 | int qnum = priv->hwq_map[ATH9K_WME_AC_BE]; | 230 | int qnum = priv->hwq_map[WME_AC_BE]; |
231 | 231 | ||
232 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 232 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
233 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | 233 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 7339439f0bef..a63ae88abf3e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -521,23 +521,23 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) | |||
521 | goto err; | 521 | goto err; |
522 | } | 522 | } |
523 | 523 | ||
524 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BE)) { | 524 | if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { |
525 | ath_print(common, ATH_DBG_FATAL, | 525 | ath_print(common, ATH_DBG_FATAL, |
526 | "Unable to setup xmit queue for BE traffic\n"); | 526 | "Unable to setup xmit queue for BE traffic\n"); |
527 | goto err; | 527 | goto err; |
528 | } | 528 | } |
529 | 529 | ||
530 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_BK)) { | 530 | if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { |
531 | ath_print(common, ATH_DBG_FATAL, | 531 | ath_print(common, ATH_DBG_FATAL, |
532 | "Unable to setup xmit queue for BK traffic\n"); | 532 | "Unable to setup xmit queue for BK traffic\n"); |
533 | goto err; | 533 | goto err; |
534 | } | 534 | } |
535 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VI)) { | 535 | if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { |
536 | ath_print(common, ATH_DBG_FATAL, | 536 | ath_print(common, ATH_DBG_FATAL, |
537 | "Unable to setup xmit queue for VI traffic\n"); | 537 | "Unable to setup xmit queue for VI traffic\n"); |
538 | goto err; | 538 | goto err; |
539 | } | 539 | } |
540 | if (!ath9k_htc_txq_setup(priv, ATH9K_WME_AC_VO)) { | 540 | if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { |
541 | ath_print(common, ATH_DBG_FATAL, | 541 | ath_print(common, ATH_DBG_FATAL, |
542 | "Unable to setup xmit queue for VO traffic\n"); | 542 | "Unable to setup xmit queue for VO traffic\n"); |
543 | goto err; | 543 | goto err; |
@@ -569,36 +569,6 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | |||
569 | */ | 569 | */ |
570 | for (i = 0; i < common->keymax; i++) | 570 | for (i = 0; i < common->keymax; i++) |
571 | ath9k_hw_keyreset(priv->ah, (u16) i); | 571 | ath9k_hw_keyreset(priv->ah, (u16) i); |
572 | |||
573 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
574 | ATH9K_CIPHER_TKIP, NULL)) { | ||
575 | /* | ||
576 | * Whether we should enable h/w TKIP MIC. | ||
577 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
578 | * report WMM capable, so it's always safe to turn on | ||
579 | * TKIP MIC in this case. | ||
580 | */ | ||
581 | ath9k_hw_setcapability(priv->ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | * Check whether the separate key cache entries | ||
586 | * are required to handle both tx+rx MIC keys. | ||
587 | * With split mic keys the number of stations is limited | ||
588 | * to 27 otherwise 59. | ||
589 | */ | ||
590 | if (ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
591 | ATH9K_CIPHER_TKIP, NULL) | ||
592 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_CIPHER, | ||
593 | ATH9K_CIPHER_MIC, NULL) | ||
594 | && ath9k_hw_getcapability(priv->ah, ATH9K_CAP_TKIP_SPLIT, | ||
595 | 0, NULL)) | ||
596 | common->splitmic = 1; | ||
597 | |||
598 | /* turn on mcast key search if possible */ | ||
599 | if (!ath9k_hw_getcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
600 | (void)ath9k_hw_setcapability(priv->ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
601 | 1, 1, NULL); | ||
602 | } | 572 | } |
603 | 573 | ||
604 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | 574 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) |
@@ -636,7 +606,6 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
636 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 606 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
637 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 607 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
638 | 608 | ||
639 | priv->op_flags |= OP_TXAGGR; | ||
640 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 609 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
641 | } | 610 | } |
642 | 611 | ||
@@ -668,14 +637,12 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
668 | spin_lock_init(&priv->beacon_lock); | 637 | spin_lock_init(&priv->beacon_lock); |
669 | spin_lock_init(&priv->tx_lock); | 638 | spin_lock_init(&priv->tx_lock); |
670 | mutex_init(&priv->mutex); | 639 | mutex_init(&priv->mutex); |
671 | mutex_init(&priv->aggr_work.mutex); | ||
672 | mutex_init(&priv->htc_pm_lock); | 640 | mutex_init(&priv->htc_pm_lock); |
673 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, | 641 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, |
674 | (unsigned long)priv); | 642 | (unsigned long)priv); |
675 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | 643 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, |
676 | (unsigned long)priv); | 644 | (unsigned long)priv); |
677 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); | 645 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); |
678 | INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); | ||
679 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | 646 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); |
680 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | 647 | INIT_WORK(&priv->ps_work, ath9k_ps_work); |
681 | 648 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7aefbc638770..05445d8a9818 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -27,13 +27,11 @@ static struct dentry *ath9k_debugfs_root; | |||
27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) | 27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) |
28 | { | 28 | { |
29 | struct ath_hw *ah = priv->ah; | 29 | struct ath_hw *ah = priv->ah; |
30 | u32 txpow; | ||
31 | 30 | ||
32 | if (priv->curtxpow != priv->txpowlimit) { | 31 | if (priv->curtxpow != priv->txpowlimit) { |
33 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); | 32 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); |
34 | /* read back in case value is clamped */ | 33 | /* read back in case value is clamped */ |
35 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | 34 | priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
36 | priv->curtxpow = txpow; | ||
37 | } | 35 | } |
38 | } | 36 | } |
39 | 37 | ||
@@ -364,11 +362,8 @@ static void ath9k_htc_setup_rate(struct ath9k_htc_priv *priv, | |||
364 | trate->rates.ht_rates.rs_nrates = j; | 362 | trate->rates.ht_rates.rs_nrates = j; |
365 | 363 | ||
366 | caps = WLAN_RC_HT_FLAG; | 364 | caps = WLAN_RC_HT_FLAG; |
367 | if (priv->ah->caps.tx_chainmask != 1 && | 365 | if (sta->ht_cap.mcs.rx_mask[1]) |
368 | ath9k_hw_getcapability(priv->ah, ATH9K_CAP_DS, 0, NULL)) { | 366 | caps |= WLAN_RC_DS_FLAG; |
369 | if (sta->ht_cap.mcs.rx_mask[1]) | ||
370 | caps |= WLAN_RC_DS_FLAG; | ||
371 | } | ||
372 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 367 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
373 | caps |= WLAN_RC_40_FLAG; | 368 | caps |= WLAN_RC_40_FLAG; |
374 | if (conf_is_ht40(&priv->hw->conf) && | 369 | if (conf_is_ht40(&priv->hw->conf) && |
@@ -443,13 +438,13 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, | |||
443 | bss_conf->bssid, be32_to_cpu(trate.capflags)); | 438 | bss_conf->bssid, be32_to_cpu(trate.capflags)); |
444 | } | 439 | } |
445 | 440 | ||
446 | static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | 441 | int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, |
447 | struct ieee80211_vif *vif, | 442 | struct ieee80211_vif *vif, |
448 | u8 *sta_addr, u8 tid, bool oper) | 443 | struct ieee80211_sta *sta, |
444 | enum ieee80211_ampdu_mlme_action action, u16 tid) | ||
449 | { | 445 | { |
450 | struct ath_common *common = ath9k_hw_common(priv->ah); | 446 | struct ath_common *common = ath9k_hw_common(priv->ah); |
451 | struct ath9k_htc_target_aggr aggr; | 447 | struct ath9k_htc_target_aggr aggr; |
452 | struct ieee80211_sta *sta = NULL; | ||
453 | struct ath9k_htc_sta *ista; | 448 | struct ath9k_htc_sta *ista; |
454 | int ret = 0; | 449 | int ret = 0; |
455 | u8 cmd_rsp; | 450 | u8 cmd_rsp; |
@@ -458,72 +453,28 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | |||
458 | return -EINVAL; | 453 | return -EINVAL; |
459 | 454 | ||
460 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); | 455 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); |
461 | |||
462 | rcu_read_lock(); | ||
463 | |||
464 | /* Check if we are able to retrieve the station */ | ||
465 | sta = ieee80211_find_sta(vif, sta_addr); | ||
466 | if (!sta) { | ||
467 | rcu_read_unlock(); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 456 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
472 | 457 | ||
473 | if (oper) | ||
474 | ista->tid_state[tid] = AGGR_START; | ||
475 | else | ||
476 | ista->tid_state[tid] = AGGR_STOP; | ||
477 | |||
478 | aggr.sta_index = ista->index; | 458 | aggr.sta_index = ista->index; |
479 | 459 | aggr.tidno = tid & 0xf; | |
480 | rcu_read_unlock(); | 460 | aggr.aggr_enable = (action == IEEE80211_AMPDU_TX_START) ? true : false; |
481 | |||
482 | aggr.tidno = tid; | ||
483 | aggr.aggr_enable = oper; | ||
484 | 461 | ||
485 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); | 462 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); |
486 | if (ret) | 463 | if (ret) |
487 | ath_print(common, ATH_DBG_CONFIG, | 464 | ath_print(common, ATH_DBG_CONFIG, |
488 | "Unable to %s TX aggregation for (%pM, %d)\n", | 465 | "Unable to %s TX aggregation for (%pM, %d)\n", |
489 | (oper) ? "start" : "stop", sta->addr, tid); | 466 | (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); |
490 | else | 467 | else |
491 | ath_print(common, ATH_DBG_CONFIG, | 468 | ath_print(common, ATH_DBG_CONFIG, |
492 | "%s aggregation for (%pM, %d)\n", | 469 | "%s TX aggregation for (%pM, %d)\n", |
493 | (oper) ? "Starting" : "Stopping", sta->addr, tid); | 470 | (aggr.aggr_enable) ? "Starting" : "Stopping", |
494 | 471 | sta->addr, tid); | |
495 | return ret; | ||
496 | } | ||
497 | |||
498 | void ath9k_htc_aggr_work(struct work_struct *work) | ||
499 | { | ||
500 | int ret = 0; | ||
501 | struct ath9k_htc_priv *priv = | ||
502 | container_of(work, struct ath9k_htc_priv, | ||
503 | ath9k_aggr_work.work); | ||
504 | struct ath9k_htc_aggr_work *wk = &priv->aggr_work; | ||
505 | |||
506 | mutex_lock(&wk->mutex); | ||
507 | 472 | ||
508 | switch (wk->action) { | 473 | spin_lock_bh(&priv->tx_lock); |
509 | case IEEE80211_AMPDU_TX_START: | 474 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
510 | ret = ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | 475 | spin_unlock_bh(&priv->tx_lock); |
511 | wk->tid, true); | ||
512 | if (!ret) | ||
513 | ieee80211_start_tx_ba_cb(wk->vif, wk->sta_addr, | ||
514 | wk->tid); | ||
515 | break; | ||
516 | case IEEE80211_AMPDU_TX_STOP: | ||
517 | ath9k_htc_aggr_oper(priv, wk->vif, wk->sta_addr, | ||
518 | wk->tid, false); | ||
519 | ieee80211_stop_tx_ba_cb(wk->vif, wk->sta_addr, wk->tid); | ||
520 | break; | ||
521 | default: | ||
522 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
523 | "Unknown AMPDU action\n"); | ||
524 | } | ||
525 | 476 | ||
526 | mutex_unlock(&wk->mutex); | 477 | return ret; |
527 | } | 478 | } |
528 | 479 | ||
529 | /*********/ | 480 | /*********/ |
@@ -1271,7 +1222,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1271 | /* Cancel all the running timers/work .. */ | 1222 | /* Cancel all the running timers/work .. */ |
1272 | cancel_work_sync(&priv->ps_work); | 1223 | cancel_work_sync(&priv->ps_work); |
1273 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1224 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1274 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | ||
1275 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1225 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); |
1276 | ath9k_led_stop_brightness(priv); | 1226 | ath9k_led_stop_brightness(priv); |
1277 | 1227 | ||
@@ -1590,7 +1540,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1590 | } | 1540 | } |
1591 | 1541 | ||
1592 | if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && | 1542 | if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) && |
1593 | (qnum == priv->hwq_map[ATH9K_WME_AC_BE])) | 1543 | (qnum == priv->hwq_map[WME_AC_BE])) |
1594 | ath9k_htc_beaconq_config(priv); | 1544 | ath9k_htc_beaconq_config(priv); |
1595 | out: | 1545 | out: |
1596 | ath9k_htc_ps_restore(priv); | 1546 | ath9k_htc_ps_restore(priv); |
@@ -1772,8 +1722,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1772 | u16 tid, u16 *ssn) | 1722 | u16 tid, u16 *ssn) |
1773 | { | 1723 | { |
1774 | struct ath9k_htc_priv *priv = hw->priv; | 1724 | struct ath9k_htc_priv *priv = hw->priv; |
1775 | struct ath9k_htc_aggr_work *work = &priv->aggr_work; | ||
1776 | struct ath9k_htc_sta *ista; | 1725 | struct ath9k_htc_sta *ista; |
1726 | int ret = 0; | ||
1777 | 1727 | ||
1778 | switch (action) { | 1728 | switch (action) { |
1779 | case IEEE80211_AMPDU_RX_START: | 1729 | case IEEE80211_AMPDU_RX_START: |
@@ -1781,26 +1731,26 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1781 | case IEEE80211_AMPDU_RX_STOP: | 1731 | case IEEE80211_AMPDU_RX_STOP: |
1782 | break; | 1732 | break; |
1783 | case IEEE80211_AMPDU_TX_START: | 1733 | case IEEE80211_AMPDU_TX_START: |
1734 | ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); | ||
1735 | if (!ret) | ||
1736 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1737 | break; | ||
1784 | case IEEE80211_AMPDU_TX_STOP: | 1738 | case IEEE80211_AMPDU_TX_STOP: |
1785 | if (!(priv->op_flags & OP_TXAGGR)) | 1739 | ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); |
1786 | return -ENOTSUPP; | 1740 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1787 | memcpy(work->sta_addr, sta->addr, ETH_ALEN); | ||
1788 | work->hw = hw; | ||
1789 | work->vif = vif; | ||
1790 | work->action = action; | ||
1791 | work->tid = tid; | ||
1792 | ieee80211_queue_delayed_work(hw, &priv->ath9k_aggr_work, 0); | ||
1793 | break; | 1741 | break; |
1794 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1742 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1795 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 1743 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1744 | spin_lock_bh(&priv->tx_lock); | ||
1796 | ista->tid_state[tid] = AGGR_OPERATIONAL; | 1745 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1746 | spin_unlock_bh(&priv->tx_lock); | ||
1797 | break; | 1747 | break; |
1798 | default: | 1748 | default: |
1799 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | 1749 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, |
1800 | "Unknown AMPDU action\n"); | 1750 | "Unknown AMPDU action\n"); |
1801 | } | 1751 | } |
1802 | 1752 | ||
1803 | return 0; | 1753 | return ret; |
1804 | } | 1754 | } |
1805 | 1755 | ||
1806 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | 1756 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f0cca4e36f7d..bd0b4acc3ece 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -34,15 +34,15 @@ int get_hw_qnum(u16 queue, int *hwq_map) | |||
34 | { | 34 | { |
35 | switch (queue) { | 35 | switch (queue) { |
36 | case 0: | 36 | case 0: |
37 | return hwq_map[ATH9K_WME_AC_VO]; | 37 | return hwq_map[WME_AC_VO]; |
38 | case 1: | 38 | case 1: |
39 | return hwq_map[ATH9K_WME_AC_VI]; | 39 | return hwq_map[WME_AC_VI]; |
40 | case 2: | 40 | case 2: |
41 | return hwq_map[ATH9K_WME_AC_BE]; | 41 | return hwq_map[WME_AC_BE]; |
42 | case 3: | 42 | case 3: |
43 | return hwq_map[ATH9K_WME_AC_BK]; | 43 | return hwq_map[WME_AC_BK]; |
44 | default: | 44 | default: |
45 | return hwq_map[ATH9K_WME_AC_BE]; | 45 | return hwq_map[WME_AC_BE]; |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
@@ -187,6 +187,19 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
187 | return htc_send(priv->htc, skb, epid, &tx_ctl); | 187 | return htc_send(priv->htc, skb, epid, &tx_ctl); |
188 | } | 188 | } |
189 | 189 | ||
190 | static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | ||
191 | struct ath9k_htc_sta *ista, u8 tid) | ||
192 | { | ||
193 | bool ret = false; | ||
194 | |||
195 | spin_lock_bh(&priv->tx_lock); | ||
196 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) | ||
197 | ret = true; | ||
198 | spin_unlock_bh(&priv->tx_lock); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
190 | void ath9k_tx_tasklet(unsigned long data) | 203 | void ath9k_tx_tasklet(unsigned long data) |
191 | { | 204 | { |
192 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 205 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
@@ -216,8 +229,7 @@ void ath9k_tx_tasklet(unsigned long data) | |||
216 | /* Check if we need to start aggregation */ | 229 | /* Check if we need to start aggregation */ |
217 | 230 | ||
218 | if (sta && conf_is_ht(&priv->hw->conf) && | 231 | if (sta && conf_is_ht(&priv->hw->conf) && |
219 | (priv->op_flags & OP_TXAGGR) | 232 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
220 | && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
221 | if (ieee80211_is_data_qos(fc)) { | 233 | if (ieee80211_is_data_qos(fc)) { |
222 | u8 *qc, tid; | 234 | u8 *qc, tid; |
223 | struct ath9k_htc_sta *ista; | 235 | struct ath9k_htc_sta *ista; |
@@ -226,10 +238,11 @@ void ath9k_tx_tasklet(unsigned long data) | |||
226 | tid = qc[0] & 0xf; | 238 | tid = qc[0] & 0xf; |
227 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | 239 | ista = (struct ath9k_htc_sta *)sta->drv_priv; |
228 | 240 | ||
229 | if ((tid < ATH9K_HTC_MAX_TID) && | 241 | if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { |
230 | ista->tid_state[tid] == AGGR_STOP) { | ||
231 | ieee80211_start_tx_ba_session(sta, tid); | 242 | ieee80211_start_tx_ba_session(sta, tid); |
243 | spin_lock_bh(&priv->tx_lock); | ||
232 | ista->tid_state[tid] = AGGR_PROGRESS; | 244 | ista->tid_state[tid] = AGGR_PROGRESS; |
245 | spin_unlock_bh(&priv->tx_lock); | ||
233 | } | 246 | } |
234 | } | 247 | } |
235 | } | 248 | } |
@@ -297,8 +310,7 @@ void ath9k_tx_cleanup(struct ath9k_htc_priv *priv) | |||
297 | 310 | ||
298 | } | 311 | } |
299 | 312 | ||
300 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | 313 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype) |
301 | enum ath9k_tx_queue_subtype subtype) | ||
302 | { | 314 | { |
303 | struct ath_hw *ah = priv->ah; | 315 | struct ath_hw *ah = priv->ah; |
304 | struct ath_common *common = ath9k_hw_common(ah); | 316 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -404,9 +416,6 @@ static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | |||
404 | /* configure operational mode */ | 416 | /* configure operational mode */ |
405 | ath9k_hw_setopmode(ah); | 417 | ath9k_hw_setopmode(ah); |
406 | 418 | ||
407 | /* Handle any link-level address change. */ | ||
408 | ath9k_hw_setmac(ah, common->macaddr); | ||
409 | |||
410 | /* calculate and install multicast filter */ | 419 | /* calculate and install multicast filter */ |
411 | mfilt[0] = mfilt[1] = ~0; | 420 | mfilt[0] = mfilt[1] = ~0; |
412 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 421 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -416,7 +425,7 @@ void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | |||
416 | { | 425 | { |
417 | ath9k_hw_rxena(priv->ah); | 426 | ath9k_hw_rxena(priv->ah); |
418 | ath9k_htc_opmode_init(priv); | 427 | ath9k_htc_opmode_init(priv); |
419 | ath9k_hw_startpcureceive(priv->ah); | 428 | ath9k_hw_startpcureceive(priv->ah, (priv->op_flags & OP_SCANNING)); |
420 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; | 429 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; |
421 | } | 430 | } |
422 | 431 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 624422a8169e..381da6c93b14 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -128,6 +128,17 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | |||
128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); | 128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline void ath9k_hw_procmibevent(struct ath_hw *ah) | ||
132 | { | ||
133 | ath9k_hw_ops(ah)->ani_proc_mib_event(ah); | ||
134 | } | ||
135 | |||
136 | static inline void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
137 | struct ath9k_channel *chan) | ||
138 | { | ||
139 | ath9k_hw_ops(ah)->ani_monitor(ah, chan); | ||
140 | } | ||
141 | |||
131 | /* Private hardware call ops */ | 142 | /* Private hardware call ops */ |
132 | 143 | ||
133 | /* PHY ops */ | 144 | /* PHY ops */ |
@@ -277,4 +288,9 @@ static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, | |||
277 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); | 288 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); |
278 | } | 289 | } |
279 | 290 | ||
291 | static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | ||
292 | { | ||
293 | ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning); | ||
294 | } | ||
295 | |||
280 | #endif /* ATH9K_HW_OPS_H */ | 296 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2adc7e78cebf..62597f4ca319 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -23,11 +23,6 @@ | |||
23 | #include "rc.h" | 23 | #include "rc.h" |
24 | #include "ar9003_mac.h" | 24 | #include "ar9003_mac.h" |
25 | 25 | ||
26 | #define ATH9K_CLOCK_RATE_CCK 22 | ||
27 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 | ||
28 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | ||
29 | #define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 | ||
30 | |||
31 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 26 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
32 | 27 | ||
33 | MODULE_AUTHOR("Atheros Communications"); | 28 | MODULE_AUTHOR("Atheros Communications"); |
@@ -80,6 +75,15 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
80 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); | 75 | ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); |
81 | } | 76 | } |
82 | 77 | ||
78 | static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | ||
79 | { | ||
80 | /* You will not have this callback if using the old ANI */ | ||
81 | if (!ath9k_hw_private_ops(ah)->ani_cache_ini_regs) | ||
82 | return; | ||
83 | |||
84 | ath9k_hw_private_ops(ah)->ani_cache_ini_regs(ah); | ||
85 | } | ||
86 | |||
83 | /********************/ | 87 | /********************/ |
84 | /* Helper Functions */ | 88 | /* Helper Functions */ |
85 | /********************/ | 89 | /********************/ |
@@ -371,13 +375,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
371 | ah->config.ofdm_trig_high = 500; | 375 | ah->config.ofdm_trig_high = 500; |
372 | ah->config.cck_trig_high = 200; | 376 | ah->config.cck_trig_high = 200; |
373 | ah->config.cck_trig_low = 100; | 377 | ah->config.cck_trig_low = 100; |
374 | 378 | ah->config.enable_ani = true; | |
375 | /* | ||
376 | * For now ANI is disabled for AR9003, it is still | ||
377 | * being tested. | ||
378 | */ | ||
379 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
380 | ah->config.enable_ani = 1; | ||
381 | 379 | ||
382 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 380 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
383 | ah->config.spurchans[i][0] = AR_NO_SPUR; | 381 | ah->config.spurchans[i][0] = AR_NO_SPUR; |
@@ -427,7 +425,9 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
427 | ah->ah_flags = AH_USE_EEPROM; | 425 | ah->ah_flags = AH_USE_EEPROM; |
428 | 426 | ||
429 | ah->atim_window = 0; | 427 | ah->atim_window = 0; |
430 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; | 428 | ah->sta_id1_defaults = |
429 | AR_STA_ID1_CRPT_MIC_ENABLE | | ||
430 | AR_STA_ID1_MCAST_KSRCH; | ||
431 | ah->beacon_interval = 100; | 431 | ah->beacon_interval = 100; |
432 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 432 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
433 | ah->slottime = (u32) -1; | 433 | ah->slottime = (u32) -1; |
@@ -565,6 +565,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
565 | ah->ani_function = ATH9K_ANI_ALL; | 565 | ah->ani_function = ATH9K_ANI_ALL; |
566 | if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | 566 | if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) |
567 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | 567 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; |
568 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
569 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | ||
568 | 570 | ||
569 | ath9k_hw_init_mode_regs(ah); | 571 | ath9k_hw_init_mode_regs(ah); |
570 | 572 | ||
@@ -1365,6 +1367,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1365 | ath9k_hw_resettxqueue(ah, i); | 1367 | ath9k_hw_resettxqueue(ah, i); |
1366 | 1368 | ||
1367 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1369 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
1370 | ath9k_hw_ani_cache_ini_regs(ah); | ||
1368 | ath9k_hw_init_qos(ah); | 1371 | ath9k_hw_init_qos(ah); |
1369 | 1372 | ||
1370 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 1373 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
@@ -2234,6 +2237,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2234 | pCap->rx_status_len = sizeof(struct ar9003_rxs); | 2237 | pCap->rx_status_len = sizeof(struct ar9003_rxs); |
2235 | pCap->tx_desc_len = sizeof(struct ar9003_txc); | 2238 | pCap->tx_desc_len = sizeof(struct ar9003_txc); |
2236 | pCap->txs_len = sizeof(struct ar9003_txs); | 2239 | pCap->txs_len = sizeof(struct ar9003_txs); |
2240 | if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | ||
2241 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | ||
2237 | } else { | 2242 | } else { |
2238 | pCap->tx_desc_len = sizeof(struct ath_desc); | 2243 | pCap->tx_desc_len = sizeof(struct ath_desc); |
2239 | if (AR_SREV_9280_20(ah) && | 2244 | if (AR_SREV_9280_20(ah) && |
@@ -2252,98 +2257,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2252 | return 0; | 2257 | return 0; |
2253 | } | 2258 | } |
2254 | 2259 | ||
2255 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
2256 | u32 capability, u32 *result) | ||
2257 | { | ||
2258 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
2259 | switch (type) { | ||
2260 | case ATH9K_CAP_CIPHER: | ||
2261 | switch (capability) { | ||
2262 | case ATH9K_CIPHER_AES_CCM: | ||
2263 | case ATH9K_CIPHER_AES_OCB: | ||
2264 | case ATH9K_CIPHER_TKIP: | ||
2265 | case ATH9K_CIPHER_WEP: | ||
2266 | case ATH9K_CIPHER_MIC: | ||
2267 | case ATH9K_CIPHER_CLR: | ||
2268 | return true; | ||
2269 | default: | ||
2270 | return false; | ||
2271 | } | ||
2272 | case ATH9K_CAP_TKIP_MIC: | ||
2273 | switch (capability) { | ||
2274 | case 0: | ||
2275 | return true; | ||
2276 | case 1: | ||
2277 | return (ah->sta_id1_defaults & | ||
2278 | AR_STA_ID1_CRPT_MIC_ENABLE) ? true : | ||
2279 | false; | ||
2280 | } | ||
2281 | case ATH9K_CAP_TKIP_SPLIT: | ||
2282 | return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? | ||
2283 | false : true; | ||
2284 | case ATH9K_CAP_MCAST_KEYSRCH: | ||
2285 | switch (capability) { | ||
2286 | case 0: | ||
2287 | return true; | ||
2288 | case 1: | ||
2289 | if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { | ||
2290 | return false; | ||
2291 | } else { | ||
2292 | return (ah->sta_id1_defaults & | ||
2293 | AR_STA_ID1_MCAST_KSRCH) ? true : | ||
2294 | false; | ||
2295 | } | ||
2296 | } | ||
2297 | return false; | ||
2298 | case ATH9K_CAP_TXPOW: | ||
2299 | switch (capability) { | ||
2300 | case 0: | ||
2301 | return 0; | ||
2302 | case 1: | ||
2303 | *result = regulatory->power_limit; | ||
2304 | return 0; | ||
2305 | case 2: | ||
2306 | *result = regulatory->max_power_level; | ||
2307 | return 0; | ||
2308 | case 3: | ||
2309 | *result = regulatory->tp_scale; | ||
2310 | return 0; | ||
2311 | } | ||
2312 | return false; | ||
2313 | case ATH9K_CAP_DS: | ||
2314 | return (AR_SREV_9280_20_OR_LATER(ah) && | ||
2315 | (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) | ||
2316 | ? false : true; | ||
2317 | default: | ||
2318 | return false; | ||
2319 | } | ||
2320 | } | ||
2321 | EXPORT_SYMBOL(ath9k_hw_getcapability); | ||
2322 | |||
2323 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
2324 | u32 capability, u32 setting, int *status) | ||
2325 | { | ||
2326 | switch (type) { | ||
2327 | case ATH9K_CAP_TKIP_MIC: | ||
2328 | if (setting) | ||
2329 | ah->sta_id1_defaults |= | ||
2330 | AR_STA_ID1_CRPT_MIC_ENABLE; | ||
2331 | else | ||
2332 | ah->sta_id1_defaults &= | ||
2333 | ~AR_STA_ID1_CRPT_MIC_ENABLE; | ||
2334 | return true; | ||
2335 | case ATH9K_CAP_MCAST_KEYSRCH: | ||
2336 | if (setting) | ||
2337 | ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; | ||
2338 | else | ||
2339 | ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; | ||
2340 | return true; | ||
2341 | default: | ||
2342 | return false; | ||
2343 | } | ||
2344 | } | ||
2345 | EXPORT_SYMBOL(ath9k_hw_setcapability); | ||
2346 | |||
2347 | /****************************/ | 2260 | /****************************/ |
2348 | /* GPIO / RFKILL / Antennae */ | 2261 | /* GPIO / RFKILL / Antennae */ |
2349 | /****************************/ | 2262 | /****************************/ |
@@ -2537,12 +2450,6 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | |||
2537 | } | 2450 | } |
2538 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); | 2451 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); |
2539 | 2452 | ||
2540 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) | ||
2541 | { | ||
2542 | memcpy(ath9k_hw_common(ah)->macaddr, mac, ETH_ALEN); | ||
2543 | } | ||
2544 | EXPORT_SYMBOL(ath9k_hw_setmac); | ||
2545 | |||
2546 | void ath9k_hw_setopmode(struct ath_hw *ah) | 2453 | void ath9k_hw_setopmode(struct ath_hw *ah) |
2547 | { | 2454 | { |
2548 | ath9k_hw_set_operating_mode(ah, ah->opmode); | 2455 | ath9k_hw_set_operating_mode(ah, ah->opmode); |
@@ -2615,21 +2522,6 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | |||
2615 | } | 2522 | } |
2616 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); | 2523 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); |
2617 | 2524 | ||
2618 | /* | ||
2619 | * Extend 15-bit time stamp from rx descriptor to | ||
2620 | * a full 64-bit TSF using the current h/w TSF. | ||
2621 | */ | ||
2622 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) | ||
2623 | { | ||
2624 | u64 tsf; | ||
2625 | |||
2626 | tsf = ath9k_hw_gettsf64(ah); | ||
2627 | if ((tsf & 0x7fff) < rstamp) | ||
2628 | tsf -= 0x8000; | ||
2629 | return (tsf & ~0x7fff) | rstamp; | ||
2630 | } | ||
2631 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); | ||
2632 | |||
2633 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 2525 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) |
2634 | { | 2526 | { |
2635 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 2527 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 88bf2fca3736..5ecbfcf7470a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -158,6 +158,9 @@ | |||
158 | #define ATH9K_HW_RX_HP_QDEPTH 16 | 158 | #define ATH9K_HW_RX_HP_QDEPTH 16 |
159 | #define ATH9K_HW_RX_LP_QDEPTH 128 | 159 | #define ATH9K_HW_RX_LP_QDEPTH 128 |
160 | 160 | ||
161 | #define PAPRD_GAIN_TABLE_ENTRIES 32 | ||
162 | #define PAPRD_TABLE_SZ 24 | ||
163 | |||
161 | enum ath_ini_subsys { | 164 | enum ath_ini_subsys { |
162 | ATH_INI_PRE = 0, | 165 | ATH_INI_PRE = 0, |
163 | ATH_INI_CORE, | 166 | ATH_INI_CORE, |
@@ -200,15 +203,7 @@ enum ath9k_hw_caps { | |||
200 | ATH9K_HW_CAP_LDPC = BIT(19), | 203 | ATH9K_HW_CAP_LDPC = BIT(19), |
201 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), | 204 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), |
202 | ATH9K_HW_CAP_SGI_20 = BIT(21), | 205 | ATH9K_HW_CAP_SGI_20 = BIT(21), |
203 | }; | 206 | ATH9K_HW_CAP_PAPRD = BIT(22), |
204 | |||
205 | enum ath9k_capability_type { | ||
206 | ATH9K_CAP_CIPHER = 0, | ||
207 | ATH9K_CAP_TKIP_MIC, | ||
208 | ATH9K_CAP_TKIP_SPLIT, | ||
209 | ATH9K_CAP_TXPOW, | ||
210 | ATH9K_CAP_MCAST_KEYSRCH, | ||
211 | ATH9K_CAP_DS | ||
212 | }; | 207 | }; |
213 | 208 | ||
214 | struct ath9k_hw_capabilities { | 209 | struct ath9k_hw_capabilities { |
@@ -238,7 +233,7 @@ struct ath9k_ops_config { | |||
238 | int sw_beacon_response_time; | 233 | int sw_beacon_response_time; |
239 | int additional_swba_backoff; | 234 | int additional_swba_backoff; |
240 | int ack_6mb; | 235 | int ack_6mb; |
241 | int cwm_ignore_extcca; | 236 | u32 cwm_ignore_extcca; |
242 | u8 pcie_powersave_enable; | 237 | u8 pcie_powersave_enable; |
243 | u8 pcie_clock_req; | 238 | u8 pcie_clock_req; |
244 | u32 pcie_waen; | 239 | u32 pcie_waen; |
@@ -266,6 +261,7 @@ struct ath9k_ops_config { | |||
266 | int spurmode; | 261 | int spurmode; |
267 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; | 262 | u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; |
268 | u8 max_txtrig_level; | 263 | u8 max_txtrig_level; |
264 | u16 ani_poll_interval; /* ANI poll interval in ms */ | ||
269 | }; | 265 | }; |
270 | 266 | ||
271 | enum ath9k_int { | 267 | enum ath9k_int { |
@@ -359,6 +355,9 @@ struct ath9k_channel { | |||
359 | int8_t iCoff; | 355 | int8_t iCoff; |
360 | int8_t qCoff; | 356 | int8_t qCoff; |
361 | int16_t rawNoiseFloor; | 357 | int16_t rawNoiseFloor; |
358 | bool paprd_done; | ||
359 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | ||
360 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | ||
362 | }; | 361 | }; |
363 | 362 | ||
364 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 363 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -511,6 +510,17 @@ struct ath_gen_timer_table { | |||
511 | * @setup_calibration: set up calibration | 510 | * @setup_calibration: set up calibration |
512 | * @iscal_supported: used to query if a type of calibration is supported | 511 | * @iscal_supported: used to query if a type of calibration is supported |
513 | * @loadnf: load noise floor read from each chain on the CCA registers | 512 | * @loadnf: load noise floor read from each chain on the CCA registers |
513 | * | ||
514 | * @ani_reset: reset ANI parameters to default values | ||
515 | * @ani_lower_immunity: lower the noise immunity level. The level controls | ||
516 | * the power-based packet detection on hardware. If a power jump is | ||
517 | * detected the adapter takes it as an indication that a packet has | ||
518 | * arrived. The level ranges from 0-5. Each level corresponds to a | ||
519 | * few dB more of noise immunity. If you have a strong time-varying | ||
520 | * interference that is causing false detections (OFDM timing errors or | ||
521 | * CCK timing errors) the level can be increased. | ||
522 | * @ani_cache_ini_regs: cache the values for ANI from the initial | ||
523 | * register settings through the register initialization. | ||
514 | */ | 524 | */ |
515 | struct ath_hw_private_ops { | 525 | struct ath_hw_private_ops { |
516 | /* Calibration ops */ | 526 | /* Calibration ops */ |
@@ -554,6 +564,11 @@ struct ath_hw_private_ops { | |||
554 | int param); | 564 | int param); |
555 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); | 565 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); |
556 | void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); | 566 | void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); |
567 | |||
568 | /* ANI */ | ||
569 | void (*ani_reset)(struct ath_hw *ah, bool is_scanning); | ||
570 | void (*ani_lower_immunity)(struct ath_hw *ah); | ||
571 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | ||
557 | }; | 572 | }; |
558 | 573 | ||
559 | /** | 574 | /** |
@@ -564,6 +579,11 @@ struct ath_hw_private_ops { | |||
564 | * | 579 | * |
565 | * @config_pci_powersave: | 580 | * @config_pci_powersave: |
566 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC | 581 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC |
582 | * | ||
583 | * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI | ||
584 | * thresholds being reached or having overflowed. | ||
585 | * @ani_monitor: called periodically by the core driver to collect | ||
586 | * MIB stats and adjust ANI if specific thresholds have been reached. | ||
567 | */ | 587 | */ |
568 | struct ath_hw_ops { | 588 | struct ath_hw_ops { |
569 | void (*config_pci_powersave)(struct ath_hw *ah, | 589 | void (*config_pci_powersave)(struct ath_hw *ah, |
@@ -604,6 +624,9 @@ struct ath_hw_ops { | |||
604 | u32 burstDuration); | 624 | u32 burstDuration); |
605 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, | 625 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, |
606 | u32 vmf); | 626 | u32 vmf); |
627 | |||
628 | void (*ani_proc_mib_event)(struct ath_hw *ah); | ||
629 | void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); | ||
607 | }; | 630 | }; |
608 | 631 | ||
609 | struct ath_hw { | 632 | struct ath_hw { |
@@ -793,6 +816,9 @@ struct ath_hw { | |||
793 | 816 | ||
794 | u32 bb_watchdog_last_status; | 817 | u32 bb_watchdog_last_status; |
795 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ | 818 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ |
819 | |||
820 | u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; | ||
821 | u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; | ||
796 | }; | 822 | }; |
797 | 823 | ||
798 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 824 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) |
@@ -822,10 +848,6 @@ int ath9k_hw_init(struct ath_hw *ah); | |||
822 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 848 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
823 | bool bChannelChange); | 849 | bool bChannelChange); |
824 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 850 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
825 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
826 | u32 capability, u32 *result); | ||
827 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | ||
828 | u32 capability, u32 setting, int *status); | ||
829 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 851 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
830 | 852 | ||
831 | /* Key Cache Management */ | 853 | /* Key Cache Management */ |
@@ -860,7 +882,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); | |||
860 | bool ath9k_hw_phy_disable(struct ath_hw *ah); | 882 | bool ath9k_hw_phy_disable(struct ath_hw *ah); |
861 | bool ath9k_hw_disable(struct ath_hw *ah); | 883 | bool ath9k_hw_disable(struct ath_hw *ah); |
862 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); | 884 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); |
863 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); | ||
864 | void ath9k_hw_setopmode(struct ath_hw *ah); | 885 | void ath9k_hw_setopmode(struct ath_hw *ah); |
865 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 886 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
866 | void ath9k_hw_setbssidmask(struct ath_hw *ah); | 887 | void ath9k_hw_setbssidmask(struct ath_hw *ah); |
@@ -869,7 +890,6 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah); | |||
869 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 890 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
870 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 891 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
871 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 892 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
872 | u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); | ||
873 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 893 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
874 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 894 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
875 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 895 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
@@ -922,6 +942,15 @@ void ar9003_hw_set_nf_limits(struct ath_hw *ah); | |||
922 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); | 942 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); |
923 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | 943 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); |
924 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 944 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
945 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | ||
946 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | ||
947 | struct ath9k_channel *chan, int chain); | ||
948 | int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, | ||
949 | int chain); | ||
950 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | ||
951 | int ar9003_paprd_init_table(struct ath_hw *ah); | ||
952 | bool ar9003_paprd_is_done(struct ath_hw *ah); | ||
953 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); | ||
925 | 954 | ||
926 | /* Hardware family op attach helpers */ | 955 | /* Hardware family op attach helpers */ |
927 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 956 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
@@ -934,8 +963,24 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | |||
934 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 963 | void ar9002_hw_attach_ops(struct ath_hw *ah); |
935 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 964 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
936 | 965 | ||
966 | /* | ||
967 | * ANI work can be shared between all families but a next | ||
968 | * generation implementation of ANI will be used only for AR9003 only | ||
969 | * for now as the other families still need to be tested with the same | ||
970 | * next generation ANI. Feel free to start testing it though for the | ||
971 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. | ||
972 | */ | ||
973 | extern int modparam_force_new_ani; | ||
974 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); | ||
975 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah); | ||
976 | |||
937 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 | 977 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 |
938 | #define ATH_PCIE_CAP_LINK_L0S 1 | 978 | #define ATH_PCIE_CAP_LINK_L0S 1 |
939 | #define ATH_PCIE_CAP_LINK_L1 2 | 979 | #define ATH_PCIE_CAP_LINK_L1 2 |
940 | 980 | ||
981 | #define ATH9K_CLOCK_RATE_CCK 22 | ||
982 | #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 | ||
983 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | ||
984 | #define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44 | ||
985 | |||
941 | #endif | 986 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 18d76ede859d..514a4014c198 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -379,36 +379,14 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
379 | for (i = 0; i < common->keymax; i++) | 379 | for (i = 0; i < common->keymax; i++) |
380 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | 380 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); |
381 | 381 | ||
382 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
383 | ATH9K_CIPHER_TKIP, NULL)) { | ||
384 | /* | ||
385 | * Whether we should enable h/w TKIP MIC. | ||
386 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
387 | * report WMM capable, so it's always safe to turn on | ||
388 | * TKIP MIC in this case. | ||
389 | */ | ||
390 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); | ||
391 | } | ||
392 | |||
393 | /* | 382 | /* |
394 | * Check whether the separate key cache entries | 383 | * Check whether the separate key cache entries |
395 | * are required to handle both tx+rx MIC keys. | 384 | * are required to handle both tx+rx MIC keys. |
396 | * With split mic keys the number of stations is limited | 385 | * With split mic keys the number of stations is limited |
397 | * to 27 otherwise 59. | 386 | * to 27 otherwise 59. |
398 | */ | 387 | */ |
399 | if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | 388 | if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) |
400 | ATH9K_CIPHER_TKIP, NULL) | ||
401 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, | ||
402 | ATH9K_CIPHER_MIC, NULL) | ||
403 | && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, | ||
404 | 0, NULL)) | ||
405 | common->splitmic = 1; | 389 | common->splitmic = 1; |
406 | |||
407 | /* turn on mcast key search if possible */ | ||
408 | if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
409 | (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, | ||
410 | 1, 1, NULL); | ||
411 | |||
412 | } | 390 | } |
413 | 391 | ||
414 | static int ath9k_init_btcoex(struct ath_softc *sc) | 392 | static int ath9k_init_btcoex(struct ath_softc *sc) |
@@ -426,7 +404,7 @@ static int ath9k_init_btcoex(struct ath_softc *sc) | |||
426 | r = ath_init_btcoex_timer(sc); | 404 | r = ath_init_btcoex_timer(sc); |
427 | if (r) | 405 | if (r) |
428 | return -1; | 406 | return -1; |
429 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | 407 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
430 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); | 408 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); |
431 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 409 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; |
432 | break; | 410 | break; |
@@ -463,23 +441,23 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
463 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | 441 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; |
464 | ath_cabq_update(sc); | 442 | ath_cabq_update(sc); |
465 | 443 | ||
466 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | 444 | if (!ath_tx_setup(sc, WME_AC_BK)) { |
467 | ath_print(common, ATH_DBG_FATAL, | 445 | ath_print(common, ATH_DBG_FATAL, |
468 | "Unable to setup xmit queue for BK traffic\n"); | 446 | "Unable to setup xmit queue for BK traffic\n"); |
469 | goto err; | 447 | goto err; |
470 | } | 448 | } |
471 | 449 | ||
472 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | 450 | if (!ath_tx_setup(sc, WME_AC_BE)) { |
473 | ath_print(common, ATH_DBG_FATAL, | 451 | ath_print(common, ATH_DBG_FATAL, |
474 | "Unable to setup xmit queue for BE traffic\n"); | 452 | "Unable to setup xmit queue for BE traffic\n"); |
475 | goto err; | 453 | goto err; |
476 | } | 454 | } |
477 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | 455 | if (!ath_tx_setup(sc, WME_AC_VI)) { |
478 | ath_print(common, ATH_DBG_FATAL, | 456 | ath_print(common, ATH_DBG_FATAL, |
479 | "Unable to setup xmit queue for VI traffic\n"); | 457 | "Unable to setup xmit queue for VI traffic\n"); |
480 | goto err; | 458 | goto err; |
481 | } | 459 | } |
482 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | 460 | if (!ath_tx_setup(sc, WME_AC_VO)) { |
483 | ath_print(common, ATH_DBG_FATAL, | 461 | ath_print(common, ATH_DBG_FATAL, |
484 | "Unable to setup xmit queue for VO traffic\n"); | 462 | "Unable to setup xmit queue for VO traffic\n"); |
485 | goto err; | 463 | goto err; |
@@ -736,6 +714,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
736 | goto error_world; | 714 | goto error_world; |
737 | } | 715 | } |
738 | 716 | ||
717 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | ||
739 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 718 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); |
740 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | 719 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); |
741 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | 720 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0e425cb4bbb1..e955bb9d98cb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | ||
18 | 19 | ||
19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 20 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
20 | struct ath9k_tx_queue_info *qi) | 21 | struct ath9k_tx_queue_info *qi) |
@@ -554,8 +555,13 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
554 | REGWRITE_BUFFER_FLUSH(ah); | 555 | REGWRITE_BUFFER_FLUSH(ah); |
555 | DISABLE_REGWRITE_BUFFER(ah); | 556 | DISABLE_REGWRITE_BUFFER(ah); |
556 | 557 | ||
557 | /* cwmin and cwmax should be 0 for beacon queue */ | 558 | /* |
558 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 559 | * cwmin and cwmax should be 0 for beacon queue |
560 | * but not for IBSS as we would create an imbalance | ||
561 | * on beaconing fairness for participating nodes. | ||
562 | */ | ||
563 | if (AR_SREV_9300_20_OR_LATER(ah) && | ||
564 | ah->opmode != NL80211_IFTYPE_ADHOC) { | ||
559 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) | 565 | REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) |
560 | | SM(0, AR_D_LCL_IFS_CWMAX) | 566 | | SM(0, AR_D_LCL_IFS_CWMAX) |
561 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); | 567 | | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); |
@@ -756,11 +762,11 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) | |||
756 | } | 762 | } |
757 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); | 763 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); |
758 | 764 | ||
759 | void ath9k_hw_startpcureceive(struct ath_hw *ah) | 765 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) |
760 | { | 766 | { |
761 | ath9k_enable_mib_counters(ah); | 767 | ath9k_enable_mib_counters(ah); |
762 | 768 | ||
763 | ath9k_ani_reset(ah); | 769 | ath9k_ani_reset(ah, is_scanning); |
764 | 770 | ||
765 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 771 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
766 | } | 772 | } |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 00f3e0c7528a..7559fb2b28a5 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -577,13 +577,8 @@ enum ath9k_tx_queue { | |||
577 | 577 | ||
578 | #define ATH9K_NUM_TX_QUEUES 10 | 578 | #define ATH9K_NUM_TX_QUEUES 10 |
579 | 579 | ||
580 | enum ath9k_tx_queue_subtype { | 580 | /* Used as a queue subtype instead of a WMM AC */ |
581 | ATH9K_WME_AC_BK = 0, | 581 | #define ATH9K_WME_UPSD 4 |
582 | ATH9K_WME_AC_BE, | ||
583 | ATH9K_WME_AC_VI, | ||
584 | ATH9K_WME_AC_VO, | ||
585 | ATH9K_WME_UPSD | ||
586 | }; | ||
587 | 582 | ||
588 | enum ath9k_tx_queue_flags { | 583 | enum ath9k_tx_queue_flags { |
589 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, | 584 | TXQ_FLAG_TXOKINT_ENABLE = 0x0001, |
@@ -617,7 +612,7 @@ enum ath9k_pkt_type { | |||
617 | struct ath9k_tx_queue_info { | 612 | struct ath9k_tx_queue_info { |
618 | u32 tqi_ver; | 613 | u32 tqi_ver; |
619 | enum ath9k_tx_queue tqi_type; | 614 | enum ath9k_tx_queue tqi_type; |
620 | enum ath9k_tx_queue_subtype tqi_subtype; | 615 | int tqi_subtype; |
621 | enum ath9k_tx_queue_flags tqi_qflags; | 616 | enum ath9k_tx_queue_flags tqi_qflags; |
622 | u32 tqi_priority; | 617 | u32 tqi_priority; |
623 | u32 tqi_aifs; | 618 | u32 tqi_aifs; |
@@ -715,7 +710,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
715 | u32 size, u32 flags); | 710 | u32 size, u32 flags); |
716 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 711 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
717 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); | 712 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); |
718 | void ath9k_hw_startpcureceive(struct ath_hw *ah); | 713 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); |
719 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); | 714 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); |
720 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); | 715 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); |
721 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); | 716 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b8b76dd2c11e..c8de50fa6378 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -51,13 +51,11 @@ static void ath_cache_conf_rate(struct ath_softc *sc, | |||
51 | static void ath_update_txpow(struct ath_softc *sc) | 51 | static void ath_update_txpow(struct ath_softc *sc) |
52 | { | 52 | { |
53 | struct ath_hw *ah = sc->sc_ah; | 53 | struct ath_hw *ah = sc->sc_ah; |
54 | u32 txpow; | ||
55 | 54 | ||
56 | if (sc->curtxpow != sc->config.txpowlimit) { | 55 | if (sc->curtxpow != sc->config.txpowlimit) { |
57 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); | 56 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); |
58 | /* read back in case value is clamped */ | 57 | /* read back in case value is clamped */ |
59 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | 58 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; |
60 | sc->curtxpow = txpow; | ||
61 | } | 59 | } |
62 | } | 60 | } |
63 | 61 | ||
@@ -232,6 +230,113 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
232 | return r; | 230 | return r; |
233 | } | 231 | } |
234 | 232 | ||
233 | static void ath_paprd_activate(struct ath_softc *sc) | ||
234 | { | ||
235 | struct ath_hw *ah = sc->sc_ah; | ||
236 | int chain; | ||
237 | |||
238 | if (!ah->curchan->paprd_done) | ||
239 | return; | ||
240 | |||
241 | ath9k_ps_wakeup(sc); | ||
242 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
243 | if (!(ah->caps.tx_chainmask & BIT(chain))) | ||
244 | continue; | ||
245 | |||
246 | ar9003_paprd_populate_single_table(ah, ah->curchan, chain); | ||
247 | } | ||
248 | |||
249 | ar9003_paprd_enable(ah, true); | ||
250 | ath9k_ps_restore(sc); | ||
251 | } | ||
252 | |||
253 | void ath_paprd_calibrate(struct work_struct *work) | ||
254 | { | ||
255 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); | ||
256 | struct ieee80211_hw *hw = sc->hw; | ||
257 | struct ath_hw *ah = sc->sc_ah; | ||
258 | struct ieee80211_hdr *hdr; | ||
259 | struct sk_buff *skb = NULL; | ||
260 | struct ieee80211_tx_info *tx_info; | ||
261 | int band = hw->conf.channel->band; | ||
262 | struct ieee80211_supported_band *sband = &sc->sbands[band]; | ||
263 | struct ath_tx_control txctl; | ||
264 | int qnum, ftype; | ||
265 | int chain_ok = 0; | ||
266 | int chain; | ||
267 | int len = 1800; | ||
268 | int time_left; | ||
269 | int i; | ||
270 | |||
271 | ath9k_ps_wakeup(sc); | ||
272 | skb = alloc_skb(len, GFP_KERNEL); | ||
273 | if (!skb) | ||
274 | return; | ||
275 | |||
276 | tx_info = IEEE80211_SKB_CB(skb); | ||
277 | |||
278 | skb_put(skb, len); | ||
279 | memset(skb->data, 0, len); | ||
280 | hdr = (struct ieee80211_hdr *)skb->data; | ||
281 | ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; | ||
282 | hdr->frame_control = cpu_to_le16(ftype); | ||
283 | hdr->duration_id = 10; | ||
284 | memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); | ||
285 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | ||
286 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | ||
287 | |||
288 | memset(&txctl, 0, sizeof(txctl)); | ||
289 | qnum = sc->tx.hwq_map[WME_AC_BE]; | ||
290 | txctl.txq = &sc->tx.txq[qnum]; | ||
291 | |||
292 | ar9003_paprd_init_table(ah); | ||
293 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
294 | if (!(ah->caps.tx_chainmask & BIT(chain))) | ||
295 | continue; | ||
296 | |||
297 | chain_ok = 0; | ||
298 | memset(tx_info, 0, sizeof(*tx_info)); | ||
299 | tx_info->band = band; | ||
300 | |||
301 | for (i = 0; i < 4; i++) { | ||
302 | tx_info->control.rates[i].idx = sband->n_bitrates - 1; | ||
303 | tx_info->control.rates[i].count = 6; | ||
304 | } | ||
305 | |||
306 | init_completion(&sc->paprd_complete); | ||
307 | ar9003_paprd_setup_gain_table(ah, chain); | ||
308 | txctl.paprd = BIT(chain); | ||
309 | if (ath_tx_start(hw, skb, &txctl) != 0) | ||
310 | break; | ||
311 | |||
312 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | ||
313 | 100); | ||
314 | if (!time_left) { | ||
315 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
316 | "Timeout waiting for paprd training on " | ||
317 | "TX chain %d\n", | ||
318 | chain); | ||
319 | break; | ||
320 | } | ||
321 | |||
322 | if (!ar9003_paprd_is_done(ah)) | ||
323 | break; | ||
324 | |||
325 | if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) | ||
326 | break; | ||
327 | |||
328 | chain_ok = 1; | ||
329 | } | ||
330 | kfree_skb(skb); | ||
331 | |||
332 | if (chain_ok) { | ||
333 | ah->curchan->paprd_done = true; | ||
334 | ath_paprd_activate(sc); | ||
335 | } | ||
336 | |||
337 | ath9k_ps_restore(sc); | ||
338 | } | ||
339 | |||
235 | /* | 340 | /* |
236 | * This routine performs the periodic noise floor calibration function | 341 | * This routine performs the periodic noise floor calibration function |
237 | * that is used to adjust and optimize the chip performance. This | 342 | * that is used to adjust and optimize the chip performance. This |
@@ -285,7 +390,8 @@ void ath_ani_calibrate(unsigned long data) | |||
285 | } | 390 | } |
286 | 391 | ||
287 | /* Verify whether we must check ANI */ | 392 | /* Verify whether we must check ANI */ |
288 | if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { | 393 | if ((timestamp - common->ani.checkani_timer) >= |
394 | ah->config.ani_poll_interval) { | ||
289 | aniflag = true; | 395 | aniflag = true; |
290 | common->ani.checkani_timer = timestamp; | 396 | common->ani.checkani_timer = timestamp; |
291 | } | 397 | } |
@@ -326,15 +432,24 @@ set_timer: | |||
326 | */ | 432 | */ |
327 | cal_interval = ATH_LONG_CALINTERVAL; | 433 | cal_interval = ATH_LONG_CALINTERVAL; |
328 | if (sc->sc_ah->config.enable_ani) | 434 | if (sc->sc_ah->config.enable_ani) |
329 | cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); | 435 | cal_interval = min(cal_interval, |
436 | (u32)ah->config.ani_poll_interval); | ||
330 | if (!common->ani.caldone) | 437 | if (!common->ani.caldone) |
331 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 438 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
332 | 439 | ||
333 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | 440 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
441 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && | ||
442 | !(sc->sc_flags & SC_OP_SCANNING)) { | ||
443 | if (!sc->sc_ah->curchan->paprd_done) | ||
444 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | ||
445 | else | ||
446 | ath_paprd_activate(sc); | ||
447 | } | ||
334 | } | 448 | } |
335 | 449 | ||
336 | static void ath_start_ani(struct ath_common *common) | 450 | static void ath_start_ani(struct ath_common *common) |
337 | { | 451 | { |
452 | struct ath_hw *ah = common->ah; | ||
338 | unsigned long timestamp = jiffies_to_msecs(jiffies); | 453 | unsigned long timestamp = jiffies_to_msecs(jiffies); |
339 | 454 | ||
340 | common->ani.longcal_timer = timestamp; | 455 | common->ani.longcal_timer = timestamp; |
@@ -342,7 +457,8 @@ static void ath_start_ani(struct ath_common *common) | |||
342 | common->ani.checkani_timer = timestamp; | 457 | common->ani.checkani_timer = timestamp; |
343 | 458 | ||
344 | mod_timer(&common->ani.timer, | 459 | mod_timer(&common->ani.timer, |
345 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 460 | jiffies + |
461 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | ||
346 | } | 462 | } |
347 | 463 | ||
348 | /* | 464 | /* |
@@ -804,25 +920,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
804 | return r; | 920 | return r; |
805 | } | 921 | } |
806 | 922 | ||
807 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | 923 | static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) |
808 | { | 924 | { |
809 | int qnum; | 925 | int qnum; |
810 | 926 | ||
811 | switch (queue) { | 927 | switch (queue) { |
812 | case 0: | 928 | case 0: |
813 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; | 929 | qnum = sc->tx.hwq_map[WME_AC_VO]; |
814 | break; | 930 | break; |
815 | case 1: | 931 | case 1: |
816 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; | 932 | qnum = sc->tx.hwq_map[WME_AC_VI]; |
817 | break; | 933 | break; |
818 | case 2: | 934 | case 2: |
819 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; | 935 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
820 | break; | 936 | break; |
821 | case 3: | 937 | case 3: |
822 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; | 938 | qnum = sc->tx.hwq_map[WME_AC_BK]; |
823 | break; | 939 | break; |
824 | default: | 940 | default: |
825 | qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; | 941 | qnum = sc->tx.hwq_map[WME_AC_BE]; |
826 | break; | 942 | break; |
827 | } | 943 | } |
828 | 944 | ||
@@ -834,16 +950,16 @@ int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | |||
834 | int qnum; | 950 | int qnum; |
835 | 951 | ||
836 | switch (queue) { | 952 | switch (queue) { |
837 | case ATH9K_WME_AC_VO: | 953 | case WME_AC_VO: |
838 | qnum = 0; | 954 | qnum = 0; |
839 | break; | 955 | break; |
840 | case ATH9K_WME_AC_VI: | 956 | case WME_AC_VI: |
841 | qnum = 1; | 957 | qnum = 1; |
842 | break; | 958 | break; |
843 | case ATH9K_WME_AC_BE: | 959 | case WME_AC_BE: |
844 | qnum = 2; | 960 | qnum = 2; |
845 | break; | 961 | break; |
846 | case ATH9K_WME_AC_BK: | 962 | case WME_AC_BK: |
847 | qnum = 3; | 963 | qnum = 3; |
848 | break; | 964 | break; |
849 | default: | 965 | default: |
@@ -1127,6 +1243,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1127 | 1243 | ||
1128 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 1244 | cancel_delayed_work_sync(&sc->ath_led_blink_work); |
1129 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1245 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1246 | cancel_work_sync(&sc->paprd_work); | ||
1130 | 1247 | ||
1131 | if (!sc->num_sec_wiphy) { | 1248 | if (!sc->num_sec_wiphy) { |
1132 | cancel_delayed_work_sync(&sc->wiphy_work); | 1249 | cancel_delayed_work_sync(&sc->wiphy_work); |
@@ -1555,7 +1672,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1555 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | 1672 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); |
1556 | 1673 | ||
1557 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) | 1674 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) |
1558 | if ((qnum == sc->tx.hwq_map[ATH9K_WME_AC_BE]) && !ret) | 1675 | if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) |
1559 | ath_beaconq_config(sc); | 1676 | ath_beaconq_config(sc); |
1560 | 1677 | ||
1561 | mutex_unlock(&sc->mutex); | 1678 | mutex_unlock(&sc->mutex); |
@@ -1769,6 +1886,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1769 | struct ath_softc *sc = aphy->sc; | 1886 | struct ath_softc *sc = aphy->sc; |
1770 | int ret = 0; | 1887 | int ret = 0; |
1771 | 1888 | ||
1889 | local_bh_disable(); | ||
1890 | |||
1772 | switch (action) { | 1891 | switch (action) { |
1773 | case IEEE80211_AMPDU_RX_START: | 1892 | case IEEE80211_AMPDU_RX_START: |
1774 | if (!(sc->sc_flags & SC_OP_RXAGGR)) | 1893 | if (!(sc->sc_flags & SC_OP_RXAGGR)) |
@@ -1798,6 +1917,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1798 | "Unknown AMPDU action\n"); | 1917 | "Unknown AMPDU action\n"); |
1799 | } | 1918 | } |
1800 | 1919 | ||
1920 | local_bh_enable(); | ||
1921 | |||
1801 | return ret; | 1922 | return ret; |
1802 | } | 1923 | } |
1803 | 1924 | ||
@@ -1842,6 +1963,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
1842 | ath9k_wiphy_pause_all_forced(sc, aphy); | 1963 | ath9k_wiphy_pause_all_forced(sc, aphy); |
1843 | sc->sc_flags |= SC_OP_SCANNING; | 1964 | sc->sc_flags |= SC_OP_SCANNING; |
1844 | del_timer_sync(&common->ani.timer); | 1965 | del_timer_sync(&common->ani.timer); |
1966 | cancel_work_sync(&sc->paprd_work); | ||
1845 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1967 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1846 | mutex_unlock(&sc->mutex); | 1968 | mutex_unlock(&sc->mutex); |
1847 | } | 1969 | } |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ec836cf1c0d..257b10ba6f57 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
31 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | ||
31 | { 0 } | 32 | { 0 } |
32 | }; | 33 | }; |
33 | 34 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 02b605273ca5..600ee0ba2880 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1203,11 +1203,8 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1203 | 1203 | ||
1204 | if (sta->ht_cap.ht_supported) { | 1204 | if (sta->ht_cap.ht_supported) { |
1205 | caps = WLAN_RC_HT_FLAG; | 1205 | caps = WLAN_RC_HT_FLAG; |
1206 | if (sc->sc_ah->caps.tx_chainmask != 1 && | 1206 | if (sta->ht_cap.mcs.rx_mask[1]) |
1207 | ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { | 1207 | caps |= WLAN_RC_DS_FLAG; |
1208 | if (sta->ht_cap.mcs.rx_mask[1]) | ||
1209 | caps |= WLAN_RC_DS_FLAG; | ||
1210 | } | ||
1211 | if (is_cw40) | 1208 | if (is_cw40) |
1212 | caps |= WLAN_RC_40_FLAG; | 1209 | caps |= WLAN_RC_40_FLAG; |
1213 | if (is_sgi) | 1210 | if (is_sgi) |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d373364ef8a9..da0cfe90c38a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -116,9 +116,6 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
116 | /* configure operational mode */ | 116 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 117 | ath9k_hw_setopmode(ah); |
118 | 118 | ||
119 | /* Handle any link-level address change. */ | ||
120 | ath9k_hw_setmac(ah, common->macaddr); | ||
121 | |||
122 | /* calculate and install multicast filter */ | 119 | /* calculate and install multicast filter */ |
123 | mfilt[0] = mfilt[1] = ~0; | 120 | mfilt[0] = mfilt[1] = ~0; |
124 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 121 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -295,7 +292,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
295 | 292 | ||
296 | ath_opmode_init(sc); | 293 | ath_opmode_init(sc); |
297 | 294 | ||
298 | ath9k_hw_startpcureceive(sc->sc_ah); | 295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); |
299 | } | 296 | } |
300 | 297 | ||
301 | static void ath_edma_stop_recv(struct ath_softc *sc) | 298 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -501,7 +498,7 @@ int ath_startrecv(struct ath_softc *sc) | |||
501 | start_recv: | 498 | start_recv: |
502 | spin_unlock_bh(&sc->rx.rxbuflock); | 499 | spin_unlock_bh(&sc->rx.rxbuflock); |
503 | ath_opmode_init(sc); | 500 | ath_opmode_init(sc); |
504 | ath9k_hw_startpcureceive(ah); | 501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); |
505 | 502 | ||
506 | return 0; | 503 | return 0; |
507 | } | 504 | } |
@@ -1002,8 +999,6 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1002 | struct ieee80211_rx_status *rx_status, | 999 | struct ieee80211_rx_status *rx_status, |
1003 | bool *decrypt_error) | 1000 | bool *decrypt_error) |
1004 | { | 1001 | { |
1005 | struct ath_hw *ah = common->ah; | ||
1006 | |||
1007 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | 1002 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
1008 | 1003 | ||
1009 | /* | 1004 | /* |
@@ -1018,7 +1013,6 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1018 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 1013 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) |
1019 | return -EINVAL; | 1014 | return -EINVAL; |
1020 | 1015 | ||
1021 | rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); | ||
1022 | rx_status->band = hw->conf.channel->band; | 1016 | rx_status->band = hw->conf.channel->band; |
1023 | rx_status->freq = hw->conf.channel->center_freq; | 1017 | rx_status->freq = hw->conf.channel->center_freq; |
1024 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | 1018 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; |
@@ -1100,6 +1094,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1100 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); | 1094 | bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); |
1101 | int dma_type; | 1095 | int dma_type; |
1102 | u8 rx_status_len = ah->caps.rx_status_len; | 1096 | u8 rx_status_len = ah->caps.rx_status_len; |
1097 | u64 tsf = 0; | ||
1098 | u32 tsf_lower = 0; | ||
1103 | 1099 | ||
1104 | if (edma) | 1100 | if (edma) |
1105 | dma_type = DMA_BIDIRECTIONAL; | 1101 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1109,6 +1105,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1109 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; | 1105 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; |
1110 | spin_lock_bh(&sc->rx.rxbuflock); | 1106 | spin_lock_bh(&sc->rx.rxbuflock); |
1111 | 1107 | ||
1108 | tsf = ath9k_hw_gettsf64(ah); | ||
1109 | tsf_lower = tsf & 0xffffffff; | ||
1110 | |||
1112 | do { | 1111 | do { |
1113 | /* If handling rx interrupt and flush is in progress => exit */ | 1112 | /* If handling rx interrupt and flush is in progress => exit */ |
1114 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) | 1113 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) |
@@ -1141,6 +1140,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1141 | if (flush) | 1140 | if (flush) |
1142 | goto requeue; | 1141 | goto requeue; |
1143 | 1142 | ||
1143 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | ||
1144 | if (rs.rs_tstamp > tsf_lower && | ||
1145 | unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) | ||
1146 | rxs->mactime -= 0x100000000ULL; | ||
1147 | |||
1148 | if (rs.rs_tstamp < tsf_lower && | ||
1149 | unlikely(tsf_lower - rs.rs_tstamp > 0x10000000)) | ||
1150 | rxs->mactime += 0x100000000ULL; | ||
1151 | |||
1144 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1152 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, |
1145 | rxs, &decrypt_error); | 1153 | rxs, &decrypt_error); |
1146 | if (retval) | 1154 | if (retval) |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 105ad40968f6..89423ca23d2c 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -219,7 +219,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | |||
219 | info->control.rates[1].idx = -1; | 219 | info->control.rates[1].idx = -1; |
220 | 220 | ||
221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); |
222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; | 222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; |
223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; | 223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; |
224 | 224 | ||
225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | 225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7547c8f9a584..20221b8c04fd 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -941,6 +941,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
941 | if (!ATH_TXQ_SETUP(sc, qnum)) { | 941 | if (!ATH_TXQ_SETUP(sc, qnum)) { |
942 | struct ath_txq *txq = &sc->tx.txq[qnum]; | 942 | struct ath_txq *txq = &sc->tx.txq[qnum]; |
943 | 943 | ||
944 | txq->axq_class = subtype; | ||
944 | txq->axq_qnum = qnum; | 945 | txq->axq_qnum = qnum; |
945 | txq->axq_link = NULL; | 946 | txq->axq_link = NULL; |
946 | INIT_LIST_HEAD(&txq->axq_q); | 947 | INIT_LIST_HEAD(&txq->axq_q); |
@@ -958,32 +959,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
958 | return &sc->tx.txq[qnum]; | 959 | return &sc->tx.txq[qnum]; |
959 | } | 960 | } |
960 | 961 | ||
961 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) | ||
962 | { | ||
963 | int qnum; | ||
964 | |||
965 | switch (qtype) { | ||
966 | case ATH9K_TX_QUEUE_DATA: | ||
967 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { | ||
968 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | ||
969 | "HAL AC %u out of range, max %zu!\n", | ||
970 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); | ||
971 | return -1; | ||
972 | } | ||
973 | qnum = sc->tx.hwq_map[haltype]; | ||
974 | break; | ||
975 | case ATH9K_TX_QUEUE_BEACON: | ||
976 | qnum = sc->beacon.beaconq; | ||
977 | break; | ||
978 | case ATH9K_TX_QUEUE_CAB: | ||
979 | qnum = sc->beacon.cabq->axq_qnum; | ||
980 | break; | ||
981 | default: | ||
982 | qnum = -1; | ||
983 | } | ||
984 | return qnum; | ||
985 | } | ||
986 | |||
987 | int ath_txq_update(struct ath_softc *sc, int qnum, | 962 | int ath_txq_update(struct ath_softc *sc, int qnum, |
988 | struct ath9k_tx_queue_info *qinfo) | 963 | struct ath9k_tx_queue_info *qinfo) |
989 | { | 964 | { |
@@ -1662,12 +1637,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1662 | bf->bf_frmlen -= padsize; | 1637 | bf->bf_frmlen -= padsize; |
1663 | } | 1638 | } |
1664 | 1639 | ||
1665 | if (conf_is_ht(&hw->conf)) { | 1640 | if (!txctl->paprd && conf_is_ht(&hw->conf)) { |
1666 | bf->bf_state.bf_type |= BUF_HT; | 1641 | bf->bf_state.bf_type |= BUF_HT; |
1667 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) | 1642 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) |
1668 | use_ldpc = true; | 1643 | use_ldpc = true; |
1669 | } | 1644 | } |
1670 | 1645 | ||
1646 | bf->bf_state.bfs_paprd = txctl->paprd; | ||
1671 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); | 1647 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); |
1672 | 1648 | ||
1673 | bf->bf_keytype = get_hw_crypto_keytype(skb); | 1649 | bf->bf_keytype = get_hw_crypto_keytype(skb); |
@@ -1742,6 +1718,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1742 | bf->bf_buf_addr, | 1718 | bf->bf_buf_addr, |
1743 | txctl->txq->axq_qnum); | 1719 | txctl->txq->axq_qnum); |
1744 | 1720 | ||
1721 | if (bf->bf_state.bfs_paprd) | ||
1722 | ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); | ||
1723 | |||
1745 | spin_lock_bh(&txctl->txq->axq_lock); | 1724 | spin_lock_bh(&txctl->txq->axq_lock); |
1746 | 1725 | ||
1747 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && | 1726 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && |
@@ -1785,7 +1764,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1785 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1764 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1786 | struct ath_txq *txq = txctl->txq; | 1765 | struct ath_txq *txq = txctl->txq; |
1787 | struct ath_buf *bf; | 1766 | struct ath_buf *bf; |
1788 | int r; | 1767 | int q, r; |
1789 | 1768 | ||
1790 | bf = ath_tx_get_buffer(sc); | 1769 | bf = ath_tx_get_buffer(sc); |
1791 | if (!bf) { | 1770 | if (!bf) { |
@@ -1793,14 +1772,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1793 | return -1; | 1772 | return -1; |
1794 | } | 1773 | } |
1795 | 1774 | ||
1796 | bf->txq = txctl->txq; | ||
1797 | spin_lock_bh(&bf->txq->axq_lock); | ||
1798 | if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { | ||
1799 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | ||
1800 | txq->stopped = 1; | ||
1801 | } | ||
1802 | spin_unlock_bh(&bf->txq->axq_lock); | ||
1803 | |||
1804 | r = ath_tx_setup_buffer(hw, bf, skb, txctl); | 1775 | r = ath_tx_setup_buffer(hw, bf, skb, txctl); |
1805 | if (unlikely(r)) { | 1776 | if (unlikely(r)) { |
1806 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); | 1777 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); |
@@ -1821,6 +1792,17 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1821 | return r; | 1792 | return r; |
1822 | } | 1793 | } |
1823 | 1794 | ||
1795 | q = skb_get_queue_mapping(skb); | ||
1796 | if (q >= 4) | ||
1797 | q = 0; | ||
1798 | |||
1799 | spin_lock_bh(&txq->axq_lock); | ||
1800 | if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { | ||
1801 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | ||
1802 | txq->stopped = 1; | ||
1803 | } | ||
1804 | spin_unlock_bh(&txq->axq_lock); | ||
1805 | |||
1824 | ath_tx_start_dma(sc, bf, txctl); | 1806 | ath_tx_start_dma(sc, bf, txctl); |
1825 | 1807 | ||
1826 | return 0; | 1808 | return 0; |
@@ -1890,7 +1872,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1890 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1872 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1891 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1873 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1892 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | 1874 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1893 | int padpos, padsize; | 1875 | int q, padpos, padsize; |
1894 | 1876 | ||
1895 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1877 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1896 | 1878 | ||
@@ -1929,8 +1911,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1929 | 1911 | ||
1930 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) | 1912 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) |
1931 | ath9k_tx_status(hw, skb); | 1913 | ath9k_tx_status(hw, skb); |
1932 | else | 1914 | else { |
1915 | q = skb_get_queue_mapping(skb); | ||
1916 | if (q >= 4) | ||
1917 | q = 0; | ||
1918 | |||
1919 | if (--sc->tx.pending_frames[q] < 0) | ||
1920 | sc->tx.pending_frames[q] = 0; | ||
1921 | |||
1933 | ieee80211_tx_status(hw, skb); | 1922 | ieee80211_tx_status(hw, skb); |
1923 | } | ||
1934 | } | 1924 | } |
1935 | 1925 | ||
1936 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1926 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1951,16 +1941,15 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1951 | tx_flags |= ATH_TX_XRETRY; | 1941 | tx_flags |= ATH_TX_XRETRY; |
1952 | } | 1942 | } |
1953 | 1943 | ||
1954 | if (bf->txq) { | ||
1955 | spin_lock_bh(&bf->txq->axq_lock); | ||
1956 | bf->txq->pending_frames--; | ||
1957 | spin_unlock_bh(&bf->txq->axq_lock); | ||
1958 | bf->txq = NULL; | ||
1959 | } | ||
1960 | |||
1961 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1944 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1962 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | 1945 | |
1963 | ath_debug_stat_tx(sc, txq, bf, ts); | 1946 | if (bf->bf_state.bfs_paprd) { |
1947 | sc->paprd_txok = txok; | ||
1948 | complete(&sc->paprd_complete); | ||
1949 | } else { | ||
1950 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | ||
1951 | ath_debug_stat_tx(sc, txq, bf, ts); | ||
1952 | } | ||
1964 | 1953 | ||
1965 | /* | 1954 | /* |
1966 | * Return the list of ath_buf of this mpdu to free queue | 1955 | * Return the list of ath_buf of this mpdu to free queue |
@@ -2045,13 +2034,14 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | |||
2045 | { | 2034 | { |
2046 | int qnum; | 2035 | int qnum; |
2047 | 2036 | ||
2037 | qnum = ath_get_mac80211_qnum(txq->axq_class, sc); | ||
2038 | if (qnum == -1) | ||
2039 | return; | ||
2040 | |||
2048 | spin_lock_bh(&txq->axq_lock); | 2041 | spin_lock_bh(&txq->axq_lock); |
2049 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { | 2042 | if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { |
2050 | qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); | 2043 | ath_mac80211_start_queue(sc, qnum); |
2051 | if (qnum != -1) { | 2044 | txq->stopped = 0; |
2052 | ath_mac80211_start_queue(sc, qnum); | ||
2053 | txq->stopped = 0; | ||
2054 | } | ||
2055 | } | 2045 | } |
2056 | spin_unlock_bh(&txq->axq_lock); | 2046 | spin_unlock_bh(&txq->axq_lock); |
2057 | } | 2047 | } |
@@ -2422,26 +2412,8 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2422 | for (acno = 0, ac = &an->ac[acno]; | 2412 | for (acno = 0, ac = &an->ac[acno]; |
2423 | acno < WME_NUM_AC; acno++, ac++) { | 2413 | acno < WME_NUM_AC; acno++, ac++) { |
2424 | ac->sched = false; | 2414 | ac->sched = false; |
2415 | ac->qnum = sc->tx.hwq_map[acno]; | ||
2425 | INIT_LIST_HEAD(&ac->tid_q); | 2416 | INIT_LIST_HEAD(&ac->tid_q); |
2426 | |||
2427 | switch (acno) { | ||
2428 | case WME_AC_BE: | ||
2429 | ac->qnum = ath_tx_get_qnum(sc, | ||
2430 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
2431 | break; | ||
2432 | case WME_AC_BK: | ||
2433 | ac->qnum = ath_tx_get_qnum(sc, | ||
2434 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); | ||
2435 | break; | ||
2436 | case WME_AC_VI: | ||
2437 | ac->qnum = ath_tx_get_qnum(sc, | ||
2438 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); | ||
2439 | break; | ||
2440 | case WME_AC_VO: | ||
2441 | ac->qnum = ath_tx_get_qnum(sc, | ||
2442 | ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); | ||
2443 | break; | ||
2444 | } | ||
2445 | } | 2417 | } |
2446 | } | 2418 | } |
2447 | 2419 | ||
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index db72461c486b..29b31a694b59 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -594,6 +594,7 @@ static int prism2_config(struct pcmcia_device *link) | |||
594 | local_info_t *local; | 594 | local_info_t *local; |
595 | int ret = 1; | 595 | int ret = 1; |
596 | struct hostap_cs_priv *hw_priv; | 596 | struct hostap_cs_priv *hw_priv; |
597 | unsigned long flags; | ||
597 | 598 | ||
598 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); | 599 | PDEBUG(DEBUG_FLOW, "prism2_config()\n"); |
599 | 600 | ||
@@ -625,9 +626,15 @@ static int prism2_config(struct pcmcia_device *link) | |||
625 | local->hw_priv = hw_priv; | 626 | local->hw_priv = hw_priv; |
626 | hw_priv->link = link; | 627 | hw_priv->link = link; |
627 | 628 | ||
629 | /* | ||
630 | * Make sure the IRQ handler cannot proceed until at least | ||
631 | * dev->base_addr is initialized. | ||
632 | */ | ||
633 | spin_lock_irqsave(&local->irq_init_lock, flags); | ||
634 | |||
628 | ret = pcmcia_request_irq(link, prism2_interrupt); | 635 | ret = pcmcia_request_irq(link, prism2_interrupt); |
629 | if (ret) | 636 | if (ret) |
630 | goto failed; | 637 | goto failed_unlock; |
631 | 638 | ||
632 | /* | 639 | /* |
633 | * This actually configures the PCMCIA socket -- setting up | 640 | * This actually configures the PCMCIA socket -- setting up |
@@ -636,11 +643,13 @@ static int prism2_config(struct pcmcia_device *link) | |||
636 | */ | 643 | */ |
637 | ret = pcmcia_request_configuration(link, &link->conf); | 644 | ret = pcmcia_request_configuration(link, &link->conf); |
638 | if (ret) | 645 | if (ret) |
639 | goto failed; | 646 | goto failed_unlock; |
640 | 647 | ||
641 | dev->irq = link->irq; | 648 | dev->irq = link->irq; |
642 | dev->base_addr = link->io.BasePort1; | 649 | dev->base_addr = link->io.BasePort1; |
643 | 650 | ||
651 | spin_unlock_irqrestore(&local->irq_init_lock, flags); | ||
652 | |||
644 | /* Finally, report what we've done */ | 653 | /* Finally, report what we've done */ |
645 | printk(KERN_INFO "%s: index 0x%02x: ", | 654 | printk(KERN_INFO "%s: index 0x%02x: ", |
646 | dev_info, link->conf.ConfigIndex); | 655 | dev_info, link->conf.ConfigIndex); |
@@ -667,6 +676,8 @@ static int prism2_config(struct pcmcia_device *link) | |||
667 | 676 | ||
668 | return ret; | 677 | return ret; |
669 | 678 | ||
679 | failed_unlock: | ||
680 | spin_unlock_irqrestore(&local->irq_init_lock, flags); | ||
670 | failed: | 681 | failed: |
671 | kfree(hw_priv); | 682 | kfree(hw_priv); |
672 | prism2_release((u_long)link); | 683 | prism2_release((u_long)link); |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ff9b5c882184..2f999fc94f60 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -2621,6 +2621,18 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) | |||
2621 | iface = netdev_priv(dev); | 2621 | iface = netdev_priv(dev); |
2622 | local = iface->local; | 2622 | local = iface->local; |
2623 | 2623 | ||
2624 | /* Detect early interrupt before driver is fully configued */ | ||
2625 | spin_lock(&local->irq_init_lock); | ||
2626 | if (!dev->base_addr) { | ||
2627 | if (net_ratelimit()) { | ||
2628 | printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", | ||
2629 | dev->name); | ||
2630 | } | ||
2631 | spin_unlock(&local->irq_init_lock); | ||
2632 | return IRQ_HANDLED; | ||
2633 | } | ||
2634 | spin_unlock(&local->irq_init_lock); | ||
2635 | |||
2624 | prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); | 2636 | prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); |
2625 | 2637 | ||
2626 | if (local->func->card_present && !local->func->card_present(local)) { | 2638 | if (local->func->card_present && !local->func->card_present(local)) { |
@@ -3138,6 +3150,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, | |||
3138 | spin_lock_init(&local->cmdlock); | 3150 | spin_lock_init(&local->cmdlock); |
3139 | spin_lock_init(&local->baplock); | 3151 | spin_lock_init(&local->baplock); |
3140 | spin_lock_init(&local->lock); | 3152 | spin_lock_init(&local->lock); |
3153 | spin_lock_init(&local->irq_init_lock); | ||
3141 | mutex_init(&local->rid_bap_mtx); | 3154 | mutex_init(&local->rid_bap_mtx); |
3142 | 3155 | ||
3143 | if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) | 3156 | if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) |
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index c02f8667a7e0..1c66b3c1030d 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h | |||
@@ -654,7 +654,7 @@ struct local_info { | |||
654 | rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock | 654 | rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock |
655 | * when removing entries from the list. | 655 | * when removing entries from the list. |
656 | * TX and RX paths can use read lock. */ | 656 | * TX and RX paths can use read lock. */ |
657 | spinlock_t cmdlock, baplock, lock; | 657 | spinlock_t cmdlock, baplock, lock, irq_init_lock; |
658 | struct mutex rid_bap_mtx; | 658 | struct mutex rid_bap_mtx; |
659 | u16 infofid; /* MAC buffer id for info frame */ | 659 | u16 infofid; /* MAC buffer id for info frame */ |
660 | /* txfid, intransmitfid, next_txtid, and next_alloc are protected by | 660 | /* txfid, intransmitfid, next_txtid, and next_alloc are protected by |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 8feaa1d358ea..cb2552a6777c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -96,7 +96,7 @@ static int network_mode = 0; | |||
96 | static u32 ipw_debug_level; | 96 | static u32 ipw_debug_level; |
97 | static int associate; | 97 | static int associate; |
98 | static int auto_create = 1; | 98 | static int auto_create = 1; |
99 | static int led_support = 0; | 99 | static int led_support = 1; |
100 | static int disable = 0; | 100 | static int disable = 0; |
101 | static int bt_coexist = 0; | 101 | static int bt_coexist = 0; |
102 | static int hwcrypto = 0; | 102 | static int hwcrypto = 0; |
@@ -12082,7 +12082,7 @@ module_param(auto_create, int, 0444); | |||
12082 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); | 12082 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); |
12083 | 12083 | ||
12084 | module_param_named(led, led_support, int, 0444); | 12084 | module_param_named(led, led_support, int, 0444); |
12085 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); | 12085 | MODULE_PARM_DESC(led, "enable led control on some systems (default 1 on)"); |
12086 | 12086 | ||
12087 | module_param(debug, int, 0444); | 12087 | module_param(debug, int, 0444); |
12088 | MODULE_PARM_DESC(debug, "debug output mask"); | 12088 | MODULE_PARM_DESC(debug, "debug output mask"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0fa1d51c9c5a..93d513e14186 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -844,7 +844,7 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) | |||
844 | 844 | ||
845 | static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | 845 | static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) |
846 | { | 846 | { |
847 | iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); | 847 | iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma); |
848 | iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); | 848 | iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); |
849 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); | 849 | iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); |
850 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), | 850 | iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 548f51d92de0..0e7b0661d61d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -486,7 +486,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
486 | 486 | ||
487 | /* Tell device where to find RBD circular buffer in DRAM */ | 487 | /* Tell device where to find RBD circular buffer in DRAM */ |
488 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | 488 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, |
489 | (u32)(rxq->dma_addr >> 8)); | 489 | (u32)(rxq->bd_dma >> 8)); |
490 | 490 | ||
491 | /* Tell device where in DRAM to update its Rx status */ | 491 | /* Tell device where in DRAM to update its Rx status */ |
492 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | 492 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, |
@@ -751,7 +751,7 @@ void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
751 | } | 751 | } |
752 | 752 | ||
753 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 753 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
754 | rxq->dma_addr); | 754 | rxq->bd_dma); |
755 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | 755 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
756 | rxq->rb_stts, rxq->rb_stts_dma); | 756 | rxq->rb_stts, rxq->rb_stts_dma); |
757 | rxq->bd = NULL; | 757 | rxq->bd = NULL; |
@@ -904,7 +904,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
904 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 904 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
905 | struct iwl_rx_phy_res *phy_res; | 905 | struct iwl_rx_phy_res *phy_res; |
906 | __le32 rx_pkt_status; | 906 | __le32 rx_pkt_status; |
907 | struct iwl4965_rx_mpdu_res_start *amsdu; | 907 | struct iwl_rx_mpdu_res_start *amsdu; |
908 | u32 len; | 908 | u32 len; |
909 | u32 ampdu_status; | 909 | u32 ampdu_status; |
910 | u32 rate_n_flags; | 910 | u32 rate_n_flags; |
@@ -933,7 +933,7 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
933 | return; | 933 | return; |
934 | } | 934 | } |
935 | phy_res = &priv->_agn.last_phy_res; | 935 | phy_res = &priv->_agn.last_phy_res; |
936 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | 936 | amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; |
937 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | 937 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); |
938 | len = le16_to_cpu(amsdu->byte_count); | 938 | len = le16_to_cpu(amsdu->byte_count); |
939 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | 939 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index f9134ceb69ab..84df7fca750d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -1324,6 +1324,11 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1324 | sta_id = ba_resp->sta_id; | 1324 | sta_id = ba_resp->sta_id; |
1325 | tid = ba_resp->tid; | 1325 | tid = ba_resp->tid; |
1326 | agg = &priv->stations[sta_id].tid[tid].agg; | 1326 | agg = &priv->stations[sta_id].tid[tid].agg; |
1327 | if (unlikely(agg->txq_id != scd_flow)) { | ||
1328 | IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", | ||
1329 | scd_flow, agg->txq_id); | ||
1330 | return; | ||
1331 | } | ||
1327 | 1332 | ||
1328 | /* Find index just before block-ack window */ | 1333 | /* Find index just before block-ack window */ |
1329 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | 1334 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 69e17d782883..d857f8496f69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -941,6 +941,8 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
941 | fill_rx = 1; | 941 | fill_rx = 1; |
942 | 942 | ||
943 | while (i != r) { | 943 | while (i != r) { |
944 | int len; | ||
945 | |||
944 | rxb = rxq->queue[i]; | 946 | rxb = rxq->queue[i]; |
945 | 947 | ||
946 | /* If an RXB doesn't have a Rx queue slot associated with it, | 948 | /* If an RXB doesn't have a Rx queue slot associated with it, |
@@ -955,8 +957,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
955 | PCI_DMA_FROMDEVICE); | 957 | PCI_DMA_FROMDEVICE); |
956 | pkt = rxb_addr(rxb); | 958 | pkt = rxb_addr(rxb); |
957 | 959 | ||
958 | trace_iwlwifi_dev_rx(priv, pkt, | 960 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
959 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 961 | len += sizeof(u32); /* account for status word */ |
962 | trace_iwlwifi_dev_rx(priv, pkt, len); | ||
960 | 963 | ||
961 | /* Reclaim a command buffer only if this packet is a response | 964 | /* Reclaim a command buffer only if this packet is a response |
962 | * to a (driver-originated) command. | 965 | * to a (driver-originated) command. |
@@ -3462,10 +3465,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3462 | int ret; | 3465 | int ret; |
3463 | u8 sta_id; | 3466 | u8 sta_id; |
3464 | 3467 | ||
3465 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3466 | |||
3467 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | 3468 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", |
3468 | sta->addr); | 3469 | sta->addr); |
3470 | mutex_lock(&priv->mutex); | ||
3471 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | ||
3472 | sta->addr); | ||
3473 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3469 | 3474 | ||
3470 | atomic_set(&sta_priv->pending_frames, 0); | 3475 | atomic_set(&sta_priv->pending_frames, 0); |
3471 | if (vif->type == NL80211_IFTYPE_AP) | 3476 | if (vif->type == NL80211_IFTYPE_AP) |
@@ -3477,6 +3482,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3477 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | 3482 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", |
3478 | sta->addr, ret); | 3483 | sta->addr, ret); |
3479 | /* Should we return success if return code is EEXIST ? */ | 3484 | /* Should we return success if return code is EEXIST ? */ |
3485 | mutex_unlock(&priv->mutex); | ||
3480 | return ret; | 3486 | return ret; |
3481 | } | 3487 | } |
3482 | 3488 | ||
@@ -3486,6 +3492,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3486 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | 3492 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3487 | sta->addr); | 3493 | sta->addr); |
3488 | iwl_rs_rate_init(priv, sta, sta_id); | 3494 | iwl_rs_rate_init(priv, sta, sta_id); |
3495 | mutex_unlock(&priv->mutex); | ||
3489 | 3496 | ||
3490 | return 0; | 3497 | return 0; |
3491 | } | 3498 | } |
@@ -3638,6 +3645,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3638 | cancel_delayed_work(&priv->scan_check); | 3645 | cancel_delayed_work(&priv->scan_check); |
3639 | cancel_work_sync(&priv->start_internal_scan); | 3646 | cancel_work_sync(&priv->start_internal_scan); |
3640 | cancel_delayed_work(&priv->alive_start); | 3647 | cancel_delayed_work(&priv->alive_start); |
3648 | cancel_work_sync(&priv->run_time_calib_work); | ||
3641 | cancel_work_sync(&priv->beacon_update); | 3649 | cancel_work_sync(&priv->beacon_update); |
3642 | del_timer_sync(&priv->statistics_periodic); | 3650 | del_timer_sync(&priv->statistics_periodic); |
3643 | del_timer_sync(&priv->ucode_trace); | 3651 | del_timer_sync(&priv->ucode_trace); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 7e8227773213..22fa947e8756 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -846,6 +846,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
846 | } | 846 | } |
847 | } | 847 | } |
848 | 848 | ||
849 | if (active_chains != priv->hw_params.valid_rx_ant && | ||
850 | active_chains != priv->chain_noise_data.active_chains) | ||
851 | IWL_WARN(priv, | ||
852 | "Detected that not all antennas are connected! " | ||
853 | "Connected: %#x, valid: %#x.\n", | ||
854 | active_chains, priv->hw_params.valid_rx_ant); | ||
855 | |||
849 | /* Save for use within RXON, TX, SCAN commands, etc. */ | 856 | /* Save for use within RXON, TX, SCAN commands, etc. */ |
850 | priv->chain_noise_data.active_chains = active_chains; | 857 | priv->chain_noise_data.active_chains = active_chains; |
851 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", | 858 | IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c579965ec556..28b1098334f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1366,7 +1366,7 @@ struct iwl_rx_phy_res { | |||
1366 | __le16 reserved3; | 1366 | __le16 reserved3; |
1367 | } __packed; | 1367 | } __packed; |
1368 | 1368 | ||
1369 | struct iwl4965_rx_mpdu_res_start { | 1369 | struct iwl_rx_mpdu_res_start { |
1370 | __le16 byte_count; | 1370 | __le16 byte_count; |
1371 | __le16 reserved; | 1371 | __le16 reserved; |
1372 | } __packed; | 1372 | } __packed; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d9f21bb9d75d..cee3d12eb383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -1018,8 +1018,13 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1018 | rxq->write); | 1018 | rxq->write); |
1019 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | 1019 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", |
1020 | rxq->free_count); | 1020 | rxq->free_count); |
1021 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | 1021 | if (rxq->rb_stts) { |
1022 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1022 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | 1023 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); |
1024 | } else { | ||
1025 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1026 | "closed_rb_num: Not Allocated\n"); | ||
1027 | } | ||
1023 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1028 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1024 | } | 1029 | } |
1025 | 1030 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index fc6072cdd96f..338b5177029d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -348,7 +348,7 @@ struct iwl_host_cmd { | |||
348 | /** | 348 | /** |
349 | * struct iwl_rx_queue - Rx queue | 349 | * struct iwl_rx_queue - Rx queue |
350 | * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) | 350 | * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) |
351 | * @dma_addr: bus address of buffer of receive buffer descriptors (rbd) | 351 | * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) |
352 | * @read: Shared index to newest available Rx buffer | 352 | * @read: Shared index to newest available Rx buffer |
353 | * @write: Shared index to oldest written Rx packet | 353 | * @write: Shared index to oldest written Rx packet |
354 | * @free_count: Number of pre-allocated buffers in rx_free | 354 | * @free_count: Number of pre-allocated buffers in rx_free |
@@ -362,7 +362,7 @@ struct iwl_host_cmd { | |||
362 | */ | 362 | */ |
363 | struct iwl_rx_queue { | 363 | struct iwl_rx_queue { |
364 | __le32 *bd; | 364 | __le32 *bd; |
365 | dma_addr_t dma_addr; | 365 | dma_addr_t bd_dma; |
366 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; | 366 | struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; |
367 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; | 367 | struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; |
368 | u32 read; | 368 | u32 read; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 5e32057d6938..86a353765796 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -175,7 +175,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
175 | INIT_LIST_HEAD(&rxq->rx_used); | 175 | INIT_LIST_HEAD(&rxq->rx_used); |
176 | 176 | ||
177 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 177 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
178 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, | 178 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, |
179 | GFP_KERNEL); | 179 | GFP_KERNEL); |
180 | if (!rxq->bd) | 180 | if (!rxq->bd) |
181 | goto err_bd; | 181 | goto err_bd; |
@@ -199,7 +199,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
199 | 199 | ||
200 | err_rb: | 200 | err_rb: |
201 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 201 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
202 | rxq->dma_addr); | 202 | rxq->bd_dma); |
203 | err_bd: | 203 | err_bd: |
204 | return -ENOMEM; | 204 | return -ENOMEM; |
205 | } | 205 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index b8bcd48eb8fa..798f93e0ff50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -500,6 +500,7 @@ void iwl_bg_abort_scan(struct work_struct *work) | |||
500 | 500 | ||
501 | mutex_lock(&priv->mutex); | 501 | mutex_lock(&priv->mutex); |
502 | 502 | ||
503 | cancel_delayed_work_sync(&priv->scan_check); | ||
503 | set_bit(STATUS_SCAN_ABORTING, &priv->status); | 504 | set_bit(STATUS_SCAN_ABORTING, &priv->status); |
504 | iwl_send_scan_abort(priv); | 505 | iwl_send_scan_abort(priv); |
505 | 506 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c7127132c298..d57df6c02db3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -1373,10 +1373,14 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw, | |||
1373 | 1373 | ||
1374 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | 1374 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", |
1375 | sta->addr); | 1375 | sta->addr); |
1376 | mutex_lock(&priv->mutex); | ||
1377 | IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", | ||
1378 | sta->addr); | ||
1376 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); | 1379 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); |
1377 | if (ret) | 1380 | if (ret) |
1378 | IWL_ERR(priv, "Error removing station %pM\n", | 1381 | IWL_ERR(priv, "Error removing station %pM\n", |
1379 | sta->addr); | 1382 | sta->addr); |
1383 | mutex_unlock(&priv->mutex); | ||
1380 | return ret; | 1384 | return ret; |
1381 | } | 1385 | } |
1382 | EXPORT_SYMBOL(iwl_mac_sta_remove); | 1386 | EXPORT_SYMBOL(iwl_mac_sta_remove); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0f16c7d518f7..697fa6caaceb 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1171,7 +1171,7 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 1173 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
1174 | rxq->dma_addr); | 1174 | rxq->bd_dma); |
1175 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | 1175 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
1176 | rxq->rb_stts, rxq->rb_stts_dma); | 1176 | rxq->rb_stts, rxq->rb_stts_dma); |
1177 | rxq->bd = NULL; | 1177 | rxq->bd = NULL; |
@@ -1252,6 +1252,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1252 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); | 1252 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); |
1253 | 1253 | ||
1254 | while (i != r) { | 1254 | while (i != r) { |
1255 | int len; | ||
1256 | |||
1255 | rxb = rxq->queue[i]; | 1257 | rxb = rxq->queue[i]; |
1256 | 1258 | ||
1257 | /* If an RXB doesn't have a Rx queue slot associated with it, | 1259 | /* If an RXB doesn't have a Rx queue slot associated with it, |
@@ -1266,8 +1268,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1266 | PCI_DMA_FROMDEVICE); | 1268 | PCI_DMA_FROMDEVICE); |
1267 | pkt = rxb_addr(rxb); | 1269 | pkt = rxb_addr(rxb); |
1268 | 1270 | ||
1269 | trace_iwlwifi_dev_rx(priv, pkt, | 1271 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
1270 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 1272 | len += sizeof(u32); /* account for status word */ |
1273 | trace_iwlwifi_dev_rx(priv, pkt, len); | ||
1271 | 1274 | ||
1272 | /* Reclaim a command buffer only if this packet is a response | 1275 | /* Reclaim a command buffer only if this packet is a response |
1273 | * to a (driver-originated) command. | 1276 | * to a (driver-originated) command. |
@@ -3360,10 +3363,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | |||
3360 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; | 3363 | bool is_ap = vif->type == NL80211_IFTYPE_STATION; |
3361 | u8 sta_id; | 3364 | u8 sta_id; |
3362 | 3365 | ||
3363 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3364 | |||
3365 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", | 3366 | IWL_DEBUG_INFO(priv, "received request to add station %pM\n", |
3366 | sta->addr); | 3367 | sta->addr); |
3368 | mutex_lock(&priv->mutex); | ||
3369 | IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n", | ||
3370 | sta->addr); | ||
3371 | sta_priv->common.sta_id = IWL_INVALID_STATION; | ||
3372 | |||
3367 | 3373 | ||
3368 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, | 3374 | ret = iwl_add_station_common(priv, sta->addr, is_ap, &sta->ht_cap, |
3369 | &sta_id); | 3375 | &sta_id); |
@@ -3371,6 +3377,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | |||
3371 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", | 3377 | IWL_ERR(priv, "Unable to add station %pM (%d)\n", |
3372 | sta->addr, ret); | 3378 | sta->addr, ret); |
3373 | /* Should we return success if return code is EEXIST ? */ | 3379 | /* Should we return success if return code is EEXIST ? */ |
3380 | mutex_unlock(&priv->mutex); | ||
3374 | return ret; | 3381 | return ret; |
3375 | } | 3382 | } |
3376 | 3383 | ||
@@ -3380,6 +3387,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | |||
3380 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", | 3387 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3381 | sta->addr); | 3388 | sta->addr); |
3382 | iwl3945_rs_rate_init(priv, sta, sta_id); | 3389 | iwl3945_rs_rate_init(priv, sta, sta_id); |
3390 | mutex_unlock(&priv->mutex); | ||
3383 | 3391 | ||
3384 | return 0; | 3392 | return 0; |
3385 | } | 3393 | } |
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 6a04c2157f73..817fffc0de4b 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -549,7 +549,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) | |||
549 | 549 | ||
550 | prxpd = (struct rxpd *) skb->data; | 550 | prxpd = (struct rxpd *) skb->data; |
551 | 551 | ||
552 | stats.flag = 0; | 552 | memset(&stats, 0, sizeof(stats)); |
553 | if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) | 553 | if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) |
554 | stats.flag |= RX_FLAG_FAILED_FCS_CRC; | 554 | stats.flag |= RX_FLAG_FAILED_FCS_CRC; |
555 | stats.freq = priv->cur_freq; | 555 | stats.freq = priv->cur_freq; |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 07c4528f6e6b..a5ea89cde8c4 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -41,6 +41,8 @@ static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { | |||
41 | { PCI_DEVICE(0x1260, 0x3877) }, | 41 | { PCI_DEVICE(0x1260, 0x3877) }, |
42 | /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ | 42 | /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ |
43 | { PCI_DEVICE(0x1260, 0x3886) }, | 43 | { PCI_DEVICE(0x1260, 0x3886) }, |
44 | /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ | ||
45 | { PCI_DEVICE(0x1260, 0xffff) }, | ||
44 | { }, | 46 | { }, |
45 | }; | 47 | }; |
46 | 48 | ||
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index b0318ea59b7f..ad595958b7df 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -69,7 +69,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
69 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ | 69 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ |
70 | {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ | 70 | {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ |
71 | {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ | 71 | {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ |
72 | {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ | 72 | /* {USB_DEVICE(0x0cde, 0x0006)}, * Medion MD40900 already listed above, |
73 | * just noting it here for clarity */ | ||
73 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ | 74 | {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ |
74 | {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ | 75 | {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ |
75 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ | 76 | {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 317b7807175e..552f9f4c73d6 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1436,6 +1436,10 @@ struct mac_iveiv_entry { | |||
1436 | #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) | 1436 | #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) |
1437 | #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) | 1437 | #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) |
1438 | #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) | 1438 | #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) |
1439 | #define MAC_WCID_ATTRIBUTE_CIPHER_EXT FIELD32(0x00000400) | ||
1440 | #define MAC_WCID_ATTRIBUTE_BSS_IDX_EXT FIELD32(0x00000800) | ||
1441 | #define MAC_WCID_ATTRIBUTE_WAPI_MCBC FIELD32(0x00008000) | ||
1442 | #define MAC_WCID_ATTRIBUTE_WAPI_KEY_IDX FIELD32(0xff000000) | ||
1439 | 1443 | ||
1440 | /* | 1444 | /* |
1441 | * SHARED_KEY_MODE: | 1445 | * SHARED_KEY_MODE: |
@@ -1557,7 +1561,9 @@ struct mac_iveiv_entry { | |||
1557 | */ | 1561 | */ |
1558 | 1562 | ||
1559 | /* | 1563 | /* |
1560 | * BBP 1: TX Antenna | 1564 | * BBP 1: TX Antenna & Power |
1565 | * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm, | ||
1566 | * 3 - increase tx power by 6dBm | ||
1561 | */ | 1567 | */ |
1562 | #define BBP1_TX_POWER FIELD8(0x07) | 1568 | #define BBP1_TX_POWER FIELD8(0x07) |
1563 | #define BBP1_TX_ANTENNA FIELD8(0x18) | 1569 | #define BBP1_TX_ANTENNA FIELD8(0x18) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ae20e6728b1e..14c361ae87be 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 3 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> |
3 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | 5 | ||
5 | Based on the original rt2800pci.c and rt2800usb.c. | 6 | Based on the original rt2800pci.c and rt2800usb.c. |
6 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | ||
7 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 7 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
8 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 8 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
9 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 9 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -41,10 +41,6 @@ | |||
41 | #include "rt2800lib.h" | 41 | #include "rt2800lib.h" |
42 | #include "rt2800.h" | 42 | #include "rt2800.h" |
43 | 43 | ||
44 | MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); | ||
45 | MODULE_DESCRIPTION("rt2800 library"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | |||
48 | /* | 44 | /* |
49 | * Register access. | 45 | * Register access. |
50 | * All access to the CSR registers will go through the methods | 46 | * All access to the CSR registers will go through the methods |
@@ -558,15 +554,28 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | |||
558 | 554 | ||
559 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | 555 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); |
560 | 556 | ||
561 | rt2800_register_read(rt2x00dev, offset, ®); | 557 | if (crypto->cmd == SET_KEY) { |
562 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | 558 | rt2800_register_read(rt2x00dev, offset, ®); |
563 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | 559 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, |
564 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | 560 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); |
565 | (crypto->cmd == SET_KEY) * crypto->cipher); | 561 | /* |
566 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | 562 | * Both the cipher as the BSS Idx numbers are split in a main |
567 | (crypto->cmd == SET_KEY) * crypto->bssidx); | 563 | * value of 3 bits, and a extended field for adding one additional |
568 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | 564 | * bit to the value. |
569 | rt2800_register_write(rt2x00dev, offset, reg); | 565 | */ |
566 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | ||
567 | (crypto->cipher & 0x7)); | ||
568 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, | ||
569 | (crypto->cipher & 0x8) >> 3); | ||
570 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | ||
571 | (crypto->bssidx & 0x7)); | ||
572 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, | ||
573 | (crypto->bssidx & 0x8) >> 3); | ||
574 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | ||
575 | rt2800_register_write(rt2x00dev, offset, reg); | ||
576 | } else { | ||
577 | rt2800_register_write(rt2x00dev, offset, 0); | ||
578 | } | ||
570 | 579 | ||
571 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | 580 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); |
572 | 581 | ||
@@ -1079,7 +1088,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
1079 | u8 r1; | 1088 | u8 r1; |
1080 | 1089 | ||
1081 | rt2800_bbp_read(rt2x00dev, 1, &r1); | 1090 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
1082 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | 1091 | rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); |
1083 | rt2800_bbp_write(rt2x00dev, 1, r1); | 1092 | rt2800_bbp_write(rt2x00dev, 1, r1); |
1084 | 1093 | ||
1085 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | 1094 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); |
@@ -2497,6 +2506,18 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2497 | rt2x00_eeprom_addr(rt2x00dev, | 2506 | rt2x00_eeprom_addr(rt2x00dev, |
2498 | EEPROM_MAC_ADDR_0)); | 2507 | EEPROM_MAC_ADDR_0)); |
2499 | 2508 | ||
2509 | /* | ||
2510 | * As rt2800 has a global fallback table we cannot specify | ||
2511 | * more then one tx rate per frame but since the hw will | ||
2512 | * try several rates (based on the fallback table) we should | ||
2513 | * still initialize max_rates to the maximum number of rates | ||
2514 | * we are going to try. Otherwise mac80211 will truncate our | ||
2515 | * reported tx rates and the rc algortihm will end up with | ||
2516 | * incorrect data. | ||
2517 | */ | ||
2518 | rt2x00dev->hw->max_rates = 7; | ||
2519 | rt2x00dev->hw->max_rate_tries = 1; | ||
2520 | |||
2500 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | 2521 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); |
2501 | 2522 | ||
2502 | /* | 2523 | /* |
@@ -2749,3 +2770,8 @@ const struct ieee80211_ops rt2800_mac80211_ops = { | |||
2749 | .rfkill_poll = rt2x00mac_rfkill_poll, | 2770 | .rfkill_poll = rt2x00mac_rfkill_poll, |
2750 | }; | 2771 | }; |
2751 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); | 2772 | EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); |
2773 | |||
2774 | MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz"); | ||
2775 | MODULE_VERSION(DRV_VERSION); | ||
2776 | MODULE_DESCRIPTION("Ralink RT2800 library"); | ||
2777 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b5a871eb8881..e5ea670a18db 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -51,7 +51,7 @@ | |||
51 | /* | 51 | /* |
52 | * Allow hardware encryption to be disabled. | 52 | * Allow hardware encryption to be disabled. |
53 | */ | 53 | */ |
54 | static int modparam_nohwcrypt = 1; | 54 | static int modparam_nohwcrypt = 0; |
55 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 55 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
56 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 56 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
57 | 57 | ||
@@ -813,29 +813,24 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
813 | struct txdone_entry_desc txdesc; | 813 | struct txdone_entry_desc txdesc; |
814 | u32 word; | 814 | u32 word; |
815 | u32 reg; | 815 | u32 reg; |
816 | u32 old_reg; | ||
817 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | 816 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; |
818 | u16 mcs, real_mcs; | 817 | u16 mcs, real_mcs; |
818 | int i; | ||
819 | 819 | ||
820 | /* | 820 | /* |
821 | * During each loop we will compare the freshly read | 821 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO |
822 | * TX_STA_FIFO register value with the value read from | 822 | * at most X times and also stop processing once the TX_STA_FIFO_VALID |
823 | * the previous loop. If the 2 values are equal then | 823 | * flag is not set anymore. |
824 | * we should stop processing because the chance it | 824 | * |
825 | * quite big that the device has been unplugged and | 825 | * The legacy drivers use X=TX_RING_SIZE but state in a comment |
826 | * we risk going into an endless loop. | 826 | * that the TX_STA_FIFO stack has a size of 16. We stick to our |
827 | * tx ring size for now. | ||
827 | */ | 828 | */ |
828 | old_reg = 0; | 829 | for (i = 0; i < TX_ENTRIES; i++) { |
829 | |||
830 | while (1) { | ||
831 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | 830 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); |
832 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | 831 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) |
833 | break; | 832 | break; |
834 | 833 | ||
835 | if (old_reg == reg) | ||
836 | break; | ||
837 | old_reg = reg; | ||
838 | |||
839 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | 834 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); |
840 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | 835 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); |
841 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | 836 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); |
@@ -903,8 +898,12 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
903 | txdesc.retry = 7; | 898 | txdesc.retry = 7; |
904 | } | 899 | } |
905 | 900 | ||
906 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | 901 | /* |
907 | 902 | * the frame was retried at least once | |
903 | * -> hw used fallback rates | ||
904 | */ | ||
905 | if (txdesc.retry) | ||
906 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
908 | 907 | ||
909 | rt2x00pci_txdone(entry, &txdesc); | 908 | rt2x00pci_txdone(entry, &txdesc); |
910 | } | 909 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c437960de3ed..f18c12a19cc9 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -45,7 +45,7 @@ | |||
45 | /* | 45 | /* |
46 | * Allow hardware encryption to be disabled. | 46 | * Allow hardware encryption to be disabled. |
47 | */ | 47 | */ |
48 | static int modparam_nohwcrypt = 1; | 48 | static int modparam_nohwcrypt = 0; |
49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
51 | 51 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0b8efe8e6785..339cc84bf4fb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -236,8 +236,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
236 | */ | 236 | */ |
237 | success = | 237 | success = |
238 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || | 238 | test_bit(TXDONE_SUCCESS, &txdesc->flags) || |
239 | test_bit(TXDONE_UNKNOWN, &txdesc->flags) || | 239 | test_bit(TXDONE_UNKNOWN, &txdesc->flags); |
240 | test_bit(TXDONE_FALLBACK, &txdesc->flags); | ||
241 | 240 | ||
242 | /* | 241 | /* |
243 | * Update TX statistics. | 242 | * Update TX statistics. |
@@ -259,11 +258,22 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
259 | /* | 258 | /* |
260 | * Frame was send with retries, hardware tried | 259 | * Frame was send with retries, hardware tried |
261 | * different rates to send out the frame, at each | 260 | * different rates to send out the frame, at each |
262 | * retry it lowered the rate 1 step. | 261 | * retry it lowered the rate 1 step except when the |
262 | * lowest rate was used. | ||
263 | */ | 263 | */ |
264 | for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { | 264 | for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { |
265 | tx_info->status.rates[i].idx = rate_idx - i; | 265 | tx_info->status.rates[i].idx = rate_idx - i; |
266 | tx_info->status.rates[i].flags = rate_flags; | 266 | tx_info->status.rates[i].flags = rate_flags; |
267 | |||
268 | if (rate_idx - i == 0) { | ||
269 | /* | ||
270 | * The lowest rate (index 0) was used until the | ||
271 | * number of max retries was reached. | ||
272 | */ | ||
273 | tx_info->status.rates[i].count = retry_rates - i; | ||
274 | i++; | ||
275 | break; | ||
276 | } | ||
267 | tx_info->status.rates[i].count = 1; | 277 | tx_info->status.rates[i].count = 1; |
268 | } | 278 | } |
269 | if (i < (IEEE80211_TX_MAX_RATES - 1)) | 279 | if (i < (IEEE80211_TX_MAX_RATES - 1)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 35858b178e8f..f91637147116 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -353,13 +353,18 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
353 | /* | 353 | /* |
354 | * Check if more fragments are pending | 354 | * Check if more fragments are pending |
355 | */ | 355 | */ |
356 | if (ieee80211_has_morefrags(hdr->frame_control) || | 356 | if (ieee80211_has_morefrags(hdr->frame_control)) { |
357 | (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) { | ||
358 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | 357 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); |
359 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); | 358 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); |
360 | } | 359 | } |
361 | 360 | ||
362 | /* | 361 | /* |
362 | * Check if more frames (!= fragments) are pending | ||
363 | */ | ||
364 | if (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES) | ||
365 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | ||
366 | |||
367 | /* | ||
363 | * Beacons and probe responses require the tsf timestamp | 368 | * Beacons and probe responses require the tsf timestamp |
364 | * to be inserted into the frame, except for a frame that has been injected | 369 | * to be inserted into the frame, except for a frame that has been injected |
365 | * through a monitor interface. This latter is needed for testing a | 370 | * through a monitor interface. This latter is needed for testing a |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index f79170849add..bd54f55a8cb9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -213,9 +213,16 @@ struct rxdone_entry_desc { | |||
213 | /** | 213 | /** |
214 | * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc | 214 | * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc |
215 | * | 215 | * |
216 | * Every txdone report has to contain the basic result of the | ||
217 | * transmission, either &TXDONE_UNKNOWN, &TXDONE_SUCCESS or | ||
218 | * &TXDONE_FAILURE. The flag &TXDONE_FALLBACK can be used in | ||
219 | * conjunction with all of these flags but should only be set | ||
220 | * if retires > 0. The flag &TXDONE_EXCESSIVE_RETRY can only be used | ||
221 | * in conjunction with &TXDONE_FAILURE. | ||
222 | * | ||
216 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. | 223 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. |
217 | * @TXDONE_SUCCESS: Frame was successfully send | 224 | * @TXDONE_SUCCESS: Frame was successfully send |
218 | * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. | 225 | * @TXDONE_FALLBACK: Hardware used fallback rates for retries |
219 | * @TXDONE_FAILURE: Frame was not successfully send | 226 | * @TXDONE_FAILURE: Frame was not successfully send |
220 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the | 227 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the |
221 | * frame transmission failed due to excessive retries. | 228 | * frame transmission failed due to excessive retries. |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 243df08ae910..7ca383478eeb 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -931,6 +931,9 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
931 | u32 reg; | 931 | u32 reg; |
932 | 932 | ||
933 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); | 933 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); |
934 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); | ||
935 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); | ||
936 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); | ||
934 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, | 937 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, |
935 | libconf->conf->long_frame_max_tx_count); | 938 | libconf->conf->long_frame_max_tx_count); |
936 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 939 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
@@ -2049,29 +2052,24 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2049 | struct txdone_entry_desc txdesc; | 2052 | struct txdone_entry_desc txdesc; |
2050 | u32 word; | 2053 | u32 word; |
2051 | u32 reg; | 2054 | u32 reg; |
2052 | u32 old_reg; | ||
2053 | int type; | 2055 | int type; |
2054 | int index; | 2056 | int index; |
2057 | int i; | ||
2055 | 2058 | ||
2056 | /* | 2059 | /* |
2057 | * During each loop we will compare the freshly read | 2060 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO |
2058 | * STA_CSR4 register value with the value read from | 2061 | * at most X times and also stop processing once the TX_STA_FIFO_VALID |
2059 | * the previous loop. If the 2 values are equal then | 2062 | * flag is not set anymore. |
2060 | * we should stop processing because the chance is | 2063 | * |
2061 | * quite big that the device has been unplugged and | 2064 | * The legacy drivers use X=TX_RING_SIZE but state in a comment |
2062 | * we risk going into an endless loop. | 2065 | * that the TX_STA_FIFO stack has a size of 16. We stick to our |
2066 | * tx ring size for now. | ||
2063 | */ | 2067 | */ |
2064 | old_reg = 0; | 2068 | for (i = 0; i < TX_ENTRIES; i++) { |
2065 | |||
2066 | while (1) { | ||
2067 | rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); | 2069 | rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); |
2068 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) | 2070 | if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) |
2069 | break; | 2071 | break; |
2070 | 2072 | ||
2071 | if (old_reg == reg) | ||
2072 | break; | ||
2073 | old_reg = reg; | ||
2074 | |||
2075 | /* | 2073 | /* |
2076 | * Skip this entry when it contains an invalid | 2074 | * Skip this entry when it contains an invalid |
2077 | * queue identication number. | 2075 | * queue identication number. |
@@ -2130,6 +2128,13 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2130 | } | 2128 | } |
2131 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); | 2129 | txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); |
2132 | 2130 | ||
2131 | /* | ||
2132 | * the frame was retried at least once | ||
2133 | * -> hw used fallback rates | ||
2134 | */ | ||
2135 | if (txdesc.retry) | ||
2136 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
2137 | |||
2133 | rt2x00pci_txdone(entry, &txdesc); | 2138 | rt2x00pci_txdone(entry, &txdesc); |
2134 | } | 2139 | } |
2135 | } | 2140 | } |
@@ -2587,6 +2592,18 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2587 | EEPROM_MAC_ADDR_0)); | 2592 | EEPROM_MAC_ADDR_0)); |
2588 | 2593 | ||
2589 | /* | 2594 | /* |
2595 | * As rt61 has a global fallback table we cannot specify | ||
2596 | * more then one tx rate per frame but since the hw will | ||
2597 | * try several rates (based on the fallback table) we should | ||
2598 | * still initialize max_rates to the maximum number of rates | ||
2599 | * we are going to try. Otherwise mac80211 will truncate our | ||
2600 | * reported tx rates and the rc algortihm will end up with | ||
2601 | * incorrect data. | ||
2602 | */ | ||
2603 | rt2x00dev->hw->max_rates = 7; | ||
2604 | rt2x00dev->hw->max_rate_tries = 1; | ||
2605 | |||
2606 | /* | ||
2590 | * Initialize hw_mode information. | 2607 | * Initialize hw_mode information. |
2591 | */ | 2608 | */ |
2592 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2609 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 113ad690f9d3..d06d90f003e7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -816,6 +816,9 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
816 | u32 reg; | 816 | u32 reg; |
817 | 817 | ||
818 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 818 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
819 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1); | ||
820 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0); | ||
821 | rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); | ||
819 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, | 822 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, |
820 | libconf->conf->long_frame_max_tx_count); | 823 | libconf->conf->long_frame_max_tx_count); |
821 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 824 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 163a8a06b22d..43307bd42a69 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -42,7 +42,8 @@ static struct zd_reg_alpha2_map reg_alpha2_map[] = { | |||
42 | { ZD_REGDOMAIN_IC, "CA" }, | 42 | { ZD_REGDOMAIN_IC, "CA" }, |
43 | { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ | 43 | { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ |
44 | { ZD_REGDOMAIN_JAPAN, "JP" }, | 44 | { ZD_REGDOMAIN_JAPAN, "JP" }, |
45 | { ZD_REGDOMAIN_JAPAN_ADD, "JP" }, | 45 | { ZD_REGDOMAIN_JAPAN_2, "JP" }, |
46 | { ZD_REGDOMAIN_JAPAN_3, "JP" }, | ||
46 | { ZD_REGDOMAIN_SPAIN, "ES" }, | 47 | { ZD_REGDOMAIN_SPAIN, "ES" }, |
47 | { ZD_REGDOMAIN_FRANCE, "FR" }, | 48 | { ZD_REGDOMAIN_FRANCE, "FR" }, |
48 | }; | 49 | }; |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index e4c70e359ced..a6d86b996c79 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -212,8 +212,9 @@ struct zd_mac { | |||
212 | #define ZD_REGDOMAIN_ETSI 0x30 | 212 | #define ZD_REGDOMAIN_ETSI 0x30 |
213 | #define ZD_REGDOMAIN_SPAIN 0x31 | 213 | #define ZD_REGDOMAIN_SPAIN 0x31 |
214 | #define ZD_REGDOMAIN_FRANCE 0x32 | 214 | #define ZD_REGDOMAIN_FRANCE 0x32 |
215 | #define ZD_REGDOMAIN_JAPAN_ADD 0x40 | 215 | #define ZD_REGDOMAIN_JAPAN_2 0x40 |
216 | #define ZD_REGDOMAIN_JAPAN 0x41 | 216 | #define ZD_REGDOMAIN_JAPAN 0x41 |
217 | #define ZD_REGDOMAIN_JAPAN_3 0x49 | ||
217 | 218 | ||
218 | enum { | 219 | enum { |
219 | MIN_CHANNEL24 = 1, | 220 | MIN_CHANNEL24 = 1, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a56bac1e69e0..9c45b905aefc 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -810,6 +810,7 @@ struct cfg80211_disassoc_request { | |||
810 | * @beacon_interval: beacon interval to use | 810 | * @beacon_interval: beacon interval to use |
811 | * @privacy: this is a protected network, keys will be configured | 811 | * @privacy: this is a protected network, keys will be configured |
812 | * after joining | 812 | * after joining |
813 | * @basic_rates: bitmap of basic rates to use when creating the IBSS | ||
813 | */ | 814 | */ |
814 | struct cfg80211_ibss_params { | 815 | struct cfg80211_ibss_params { |
815 | u8 *ssid; | 816 | u8 *ssid; |
@@ -818,6 +819,7 @@ struct cfg80211_ibss_params { | |||
818 | u8 *ie; | 819 | u8 *ie; |
819 | u8 ssid_len, ie_len; | 820 | u8 ssid_len, ie_len; |
820 | u16 beacon_interval; | 821 | u16 beacon_interval; |
822 | u32 basic_rates; | ||
821 | bool channel_fixed; | 823 | bool channel_fixed; |
822 | bool privacy; | 824 | bool privacy; |
823 | }; | 825 | }; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index abb3b1a9ddc9..fe1a3a603375 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/wireless.h> | 19 | #include <linux/wireless.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/ieee80211.h> | 21 | #include <linux/ieee80211.h> |
22 | #include <linux/inetdevice.h> | ||
23 | #include <net/cfg80211.h> | 22 | #include <net/cfg80211.h> |
24 | 23 | ||
25 | /** | 24 | /** |
@@ -147,6 +146,7 @@ struct ieee80211_low_level_stats { | |||
147 | * enabled/disabled (beaconing modes) | 146 | * enabled/disabled (beaconing modes) |
148 | * @BSS_CHANGED_CQM: Connection quality monitor config changed | 147 | * @BSS_CHANGED_CQM: Connection quality monitor config changed |
149 | * @BSS_CHANGED_IBSS: IBSS join status changed | 148 | * @BSS_CHANGED_IBSS: IBSS join status changed |
149 | * @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed. | ||
150 | */ | 150 | */ |
151 | enum ieee80211_bss_change { | 151 | enum ieee80211_bss_change { |
152 | BSS_CHANGED_ASSOC = 1<<0, | 152 | BSS_CHANGED_ASSOC = 1<<0, |
@@ -161,10 +161,18 @@ enum ieee80211_bss_change { | |||
161 | BSS_CHANGED_BEACON_ENABLED = 1<<9, | 161 | BSS_CHANGED_BEACON_ENABLED = 1<<9, |
162 | BSS_CHANGED_CQM = 1<<10, | 162 | BSS_CHANGED_CQM = 1<<10, |
163 | BSS_CHANGED_IBSS = 1<<11, | 163 | BSS_CHANGED_IBSS = 1<<11, |
164 | BSS_CHANGED_ARP_FILTER = 1<<12, | ||
164 | 165 | ||
165 | /* when adding here, make sure to change ieee80211_reconfig */ | 166 | /* when adding here, make sure to change ieee80211_reconfig */ |
166 | }; | 167 | }; |
167 | 168 | ||
169 | /* | ||
170 | * The maximum number of IPv4 addresses listed for ARP filtering. If the number | ||
171 | * of addresses for an interface increase beyond this value, hardware ARP | ||
172 | * filtering will be disabled. | ||
173 | */ | ||
174 | #define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4 | ||
175 | |||
168 | /** | 176 | /** |
169 | * struct ieee80211_bss_conf - holds the BSS's changing parameters | 177 | * struct ieee80211_bss_conf - holds the BSS's changing parameters |
170 | * | 178 | * |
@@ -200,6 +208,15 @@ enum ieee80211_bss_change { | |||
200 | * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value | 208 | * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value |
201 | * implies disabled | 209 | * implies disabled |
202 | * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis | 210 | * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis |
211 | * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The | ||
212 | * may filter ARP queries targeted for other addresses than listed here. | ||
213 | * The driver must allow ARP queries targeted for all address listed here | ||
214 | * to pass through. An empty list implies no ARP queries need to pass. | ||
215 | * @arp_addr_cnt: Number of addresses currently on the list. | ||
216 | * @arp_filter_enabled: Enable ARP filtering - if enabled, the hardware may | ||
217 | * filter ARP queries based on the @arp_addr_list, if disabled, the | ||
218 | * hardware must not perform any ARP filtering. Note, that the filter will | ||
219 | * be enabled also in promiscuous mode. | ||
203 | */ | 220 | */ |
204 | struct ieee80211_bss_conf { | 221 | struct ieee80211_bss_conf { |
205 | const u8 *bssid; | 222 | const u8 *bssid; |
@@ -220,6 +237,9 @@ struct ieee80211_bss_conf { | |||
220 | s32 cqm_rssi_thold; | 237 | s32 cqm_rssi_thold; |
221 | u32 cqm_rssi_hyst; | 238 | u32 cqm_rssi_hyst; |
222 | enum nl80211_channel_type channel_type; | 239 | enum nl80211_channel_type channel_type; |
240 | __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; | ||
241 | u8 arp_addr_cnt; | ||
242 | bool arp_filter_enabled; | ||
223 | }; | 243 | }; |
224 | 244 | ||
225 | /** | 245 | /** |
@@ -675,9 +695,6 @@ enum ieee80211_smps_mode { | |||
675 | * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the | 695 | * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the |
676 | * powersave documentation below. This variable is valid only when | 696 | * powersave documentation below. This variable is valid only when |
677 | * the CONF_PS flag is set. | 697 | * the CONF_PS flag is set. |
678 | * @dynamic_ps_forced_timeout: The dynamic powersave timeout (in ms) configured | ||
679 | * by cfg80211 (essentially, wext) If set, this value overrules the value | ||
680 | * chosen by mac80211 based on ps qos network latency. | ||
681 | * | 698 | * |
682 | * @power_level: requested transmit power (in dBm) | 699 | * @power_level: requested transmit power (in dBm) |
683 | * | 700 | * |
@@ -697,7 +714,7 @@ enum ieee80211_smps_mode { | |||
697 | */ | 714 | */ |
698 | struct ieee80211_conf { | 715 | struct ieee80211_conf { |
699 | u32 flags; | 716 | u32 flags; |
700 | int power_level, dynamic_ps_timeout, dynamic_ps_forced_timeout; | 717 | int power_level, dynamic_ps_timeout; |
701 | int max_sleep_period; | 718 | int max_sleep_period; |
702 | 719 | ||
703 | u16 listen_interval; | 720 | u16 listen_interval; |
@@ -1445,7 +1462,7 @@ enum ieee80211_filter_flags { | |||
1445 | * | 1462 | * |
1446 | * Note that drivers MUST be able to deal with a TX aggregation | 1463 | * Note that drivers MUST be able to deal with a TX aggregation |
1447 | * session being stopped even before they OK'ed starting it by | 1464 | * session being stopped even before they OK'ed starting it by |
1448 | * calling ieee80211_start_tx_ba_cb(_irqsafe), because the peer | 1465 | * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer |
1449 | * might receive the addBA frame and send a delBA right away! | 1466 | * might receive the addBA frame and send a delBA right away! |
1450 | * | 1467 | * |
1451 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation | 1468 | * @IEEE80211_AMPDU_RX_START: start Rx aggregation |
@@ -1529,16 +1546,6 @@ enum ieee80211_ampdu_mlme_action { | |||
1529 | * of the bss parameters has changed when a call is made. The callback | 1546 | * of the bss parameters has changed when a call is made. The callback |
1530 | * can sleep. | 1547 | * can sleep. |
1531 | * | 1548 | * |
1532 | * @configure_arp_filter: Configuration function for hardware ARP query filter. | ||
1533 | * This function is called with all the IP addresses configured to the | ||
1534 | * interface as argument - all ARP queries targeted to any of these | ||
1535 | * addresses must pass through. If the hardware filter does not support | ||
1536 | * enought addresses, hardware filtering must be disabled. The ifa_list | ||
1537 | * argument may be NULL, indicating that filtering must be disabled. | ||
1538 | * This function is called upon association complete with current | ||
1539 | * address(es), and while associated whenever the IP address(es) change. | ||
1540 | * The callback can sleep. | ||
1541 | * | ||
1542 | * @prepare_multicast: Prepare for multicast filter configuration. | 1549 | * @prepare_multicast: Prepare for multicast filter configuration. |
1543 | * This callback is optional, and its return value is passed | 1550 | * This callback is optional, and its return value is passed |
1544 | * to configure_filter(). This callback must be atomic. | 1551 | * to configure_filter(). This callback must be atomic. |
@@ -1640,7 +1647,7 @@ enum ieee80211_ampdu_mlme_action { | |||
1640 | * is the first frame we expect to perform the action on. Notice | 1647 | * is the first frame we expect to perform the action on. Notice |
1641 | * that TX/RX_STOP can pass NULL for this parameter. | 1648 | * that TX/RX_STOP can pass NULL for this parameter. |
1642 | * Returns a negative error code on failure. | 1649 | * Returns a negative error code on failure. |
1643 | * The callback must be atomic. | 1650 | * The callback can sleep. |
1644 | * | 1651 | * |
1645 | * @get_survey: Return per-channel survey information | 1652 | * @get_survey: Return per-channel survey information |
1646 | * | 1653 | * |
@@ -1678,9 +1685,6 @@ struct ieee80211_ops { | |||
1678 | struct ieee80211_vif *vif, | 1685 | struct ieee80211_vif *vif, |
1679 | struct ieee80211_bss_conf *info, | 1686 | struct ieee80211_bss_conf *info, |
1680 | u32 changed); | 1687 | u32 changed); |
1681 | int (*configure_arp_filter)(struct ieee80211_hw *hw, | ||
1682 | struct ieee80211_vif *vif, | ||
1683 | struct in_ifaddr *ifa_list); | ||
1684 | u64 (*prepare_multicast)(struct ieee80211_hw *hw, | 1688 | u64 (*prepare_multicast)(struct ieee80211_hw *hw, |
1685 | struct netdev_hw_addr_list *mc_list); | 1689 | struct netdev_hw_addr_list *mc_list); |
1686 | void (*configure_filter)(struct ieee80211_hw *hw, | 1690 | void (*configure_filter)(struct ieee80211_hw *hw, |
@@ -2314,25 +2318,14 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | |||
2314 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); | 2318 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); |
2315 | 2319 | ||
2316 | /** | 2320 | /** |
2317 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. | ||
2318 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | ||
2319 | * @ra: receiver address of the BA session recipient. | ||
2320 | * @tid: the TID to BA on. | ||
2321 | * | ||
2322 | * This function must be called by low level driver once it has | ||
2323 | * finished with preparations for the BA session. | ||
2324 | */ | ||
2325 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | ||
2326 | |||
2327 | /** | ||
2328 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. | 2321 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. |
2329 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | 2322 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2330 | * @ra: receiver address of the BA session recipient. | 2323 | * @ra: receiver address of the BA session recipient. |
2331 | * @tid: the TID to BA on. | 2324 | * @tid: the TID to BA on. |
2332 | * | 2325 | * |
2333 | * This function must be called by low level driver once it has | 2326 | * This function must be called by low level driver once it has |
2334 | * finished with preparations for the BA session. | 2327 | * finished with preparations for the BA session. It can be called |
2335 | * This version of the function is IRQ-safe. | 2328 | * from any context. |
2336 | */ | 2329 | */ |
2337 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, | 2330 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, |
2338 | u16 tid); | 2331 | u16 tid); |
@@ -2351,25 +2344,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, | |||
2351 | int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid); | 2344 | int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid); |
2352 | 2345 | ||
2353 | /** | 2346 | /** |
2354 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. | ||
2355 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | ||
2356 | * @ra: receiver address of the BA session recipient. | ||
2357 | * @tid: the desired TID to BA on. | ||
2358 | * | ||
2359 | * This function must be called by low level driver once it has | ||
2360 | * finished with preparations for the BA session tear down. | ||
2361 | */ | ||
2362 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | ||
2363 | |||
2364 | /** | ||
2365 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. | 2347 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. |
2366 | * @vif: &struct ieee80211_vif pointer from the add_interface callback | 2348 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2367 | * @ra: receiver address of the BA session recipient. | 2349 | * @ra: receiver address of the BA session recipient. |
2368 | * @tid: the desired TID to BA on. | 2350 | * @tid: the desired TID to BA on. |
2369 | * | 2351 | * |
2370 | * This function must be called by low level driver once it has | 2352 | * This function must be called by low level driver once it has |
2371 | * finished with preparations for the BA session tear down. | 2353 | * finished with preparations for the BA session tear down. It |
2372 | * This version of the function is IRQ-safe. | 2354 | * can be called from any context. |
2373 | */ | 2355 | */ |
2374 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, | 2356 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, |
2375 | u16 tid); | 2357 | u16 tid); |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 6bb9a9a94960..965b272499fd 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -6,39 +6,70 @@ | |||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | 6 | * Copyright 2005-2006, Devicescape Software, Inc. |
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
9 | * Copyright 2007-2008, Intel Corporation | 9 | * Copyright 2007-2010, Intel Corporation |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | /** | ||
17 | * DOC: RX A-MPDU aggregation | ||
18 | * | ||
19 | * Aggregation on the RX side requires only implementing the | ||
20 | * @ampdu_action callback that is invoked to start/stop any | ||
21 | * block-ack sessions for RX aggregation. | ||
22 | * | ||
23 | * When RX aggregation is started by the peer, the driver is | ||
24 | * notified via @ampdu_action function, with the | ||
25 | * %IEEE80211_AMPDU_RX_START action, and may reject the request | ||
26 | * in which case a negative response is sent to the peer, if it | ||
27 | * accepts it a positive response is sent. | ||
28 | * | ||
29 | * While the session is active, the device/driver are required | ||
30 | * to de-aggregate frames and pass them up one by one to mac80211, | ||
31 | * which will handle the reorder buffer. | ||
32 | * | ||
33 | * When the aggregation session is stopped again by the peer or | ||
34 | * ourselves, the driver's @ampdu_action function will be called | ||
35 | * with the action %IEEE80211_AMPDU_RX_STOP. In this case, the | ||
36 | * call must not fail. | ||
37 | */ | ||
38 | |||
16 | #include <linux/ieee80211.h> | 39 | #include <linux/ieee80211.h> |
17 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
18 | #include <net/mac80211.h> | 41 | #include <net/mac80211.h> |
19 | #include "ieee80211_i.h" | 42 | #include "ieee80211_i.h" |
20 | #include "driver-ops.h" | 43 | #include "driver-ops.h" |
21 | 44 | ||
22 | static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 45 | static void ieee80211_free_tid_rx(struct rcu_head *h) |
23 | u16 initiator, u16 reason, | ||
24 | bool from_timer) | ||
25 | { | 46 | { |
26 | struct ieee80211_local *local = sta->local; | 47 | struct tid_ampdu_rx *tid_rx = |
27 | struct tid_ampdu_rx *tid_rx; | 48 | container_of(h, struct tid_ampdu_rx, rcu_head); |
28 | int i; | 49 | int i; |
29 | 50 | ||
30 | spin_lock_bh(&sta->lock); | 51 | for (i = 0; i < tid_rx->buf_size; i++) |
52 | dev_kfree_skb(tid_rx->reorder_buf[i]); | ||
53 | kfree(tid_rx->reorder_buf); | ||
54 | kfree(tid_rx->reorder_time); | ||
55 | kfree(tid_rx); | ||
56 | } | ||
31 | 57 | ||
32 | /* check if TID is in operational state */ | 58 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
33 | if (!sta->ampdu_mlme.tid_active_rx[tid]) { | 59 | u16 initiator, u16 reason) |
34 | spin_unlock_bh(&sta->lock); | 60 | { |
35 | return; | 61 | struct ieee80211_local *local = sta->local; |
36 | } | 62 | struct tid_ampdu_rx *tid_rx; |
37 | 63 | ||
38 | sta->ampdu_mlme.tid_active_rx[tid] = false; | 64 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
39 | 65 | ||
40 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; | 66 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; |
41 | 67 | ||
68 | if (!tid_rx) | ||
69 | return; | ||
70 | |||
71 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL); | ||
72 | |||
42 | #ifdef CONFIG_MAC80211_HT_DEBUG | 73 | #ifdef CONFIG_MAC80211_HT_DEBUG |
43 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 74 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
44 | sta->sta.addr, tid); | 75 | sta->sta.addr, tid); |
@@ -54,32 +85,17 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
54 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 85 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
55 | tid, 0, reason); | 86 | tid, 0, reason); |
56 | 87 | ||
57 | /* free the reordering buffer */ | 88 | del_timer_sync(&tid_rx->session_timer); |
58 | for (i = 0; i < tid_rx->buf_size; i++) { | ||
59 | if (tid_rx->reorder_buf[i]) { | ||
60 | /* release the reordered frames */ | ||
61 | dev_kfree_skb(tid_rx->reorder_buf[i]); | ||
62 | tid_rx->stored_mpdu_num--; | ||
63 | tid_rx->reorder_buf[i] = NULL; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /* free resources */ | ||
68 | kfree(tid_rx->reorder_buf); | ||
69 | kfree(tid_rx->reorder_time); | ||
70 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
71 | |||
72 | spin_unlock_bh(&sta->lock); | ||
73 | 89 | ||
74 | if (!from_timer) | 90 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); |
75 | del_timer_sync(&tid_rx->session_timer); | ||
76 | kfree(tid_rx); | ||
77 | } | 91 | } |
78 | 92 | ||
79 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 93 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
80 | u16 initiator, u16 reason) | 94 | u16 initiator, u16 reason) |
81 | { | 95 | { |
82 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false); | 96 | mutex_lock(&sta->ampdu_mlme.mtx); |
97 | ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | ||
98 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
83 | } | 99 | } |
84 | 100 | ||
85 | /* | 101 | /* |
@@ -100,8 +116,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
100 | #ifdef CONFIG_MAC80211_HT_DEBUG | 116 | #ifdef CONFIG_MAC80211_HT_DEBUG |
101 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 117 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
102 | #endif | 118 | #endif |
103 | ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, | 119 | set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired); |
104 | WLAN_REASON_QSTA_TIMEOUT, true); | 120 | ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work); |
105 | } | 121 | } |
106 | 122 | ||
107 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 123 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
@@ -212,9 +228,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
212 | 228 | ||
213 | 229 | ||
214 | /* examine state machine */ | 230 | /* examine state machine */ |
215 | spin_lock_bh(&sta->lock); | 231 | mutex_lock(&sta->ampdu_mlme.mtx); |
216 | 232 | ||
217 | if (sta->ampdu_mlme.tid_active_rx[tid]) { | 233 | if (sta->ampdu_mlme.tid_rx[tid]) { |
218 | #ifdef CONFIG_MAC80211_HT_DEBUG | 234 | #ifdef CONFIG_MAC80211_HT_DEBUG |
219 | if (net_ratelimit()) | 235 | if (net_ratelimit()) |
220 | printk(KERN_DEBUG "unexpected AddBA Req from " | 236 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -225,9 +241,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
225 | } | 241 | } |
226 | 242 | ||
227 | /* prepare A-MPDU MLME for Rx aggregation */ | 243 | /* prepare A-MPDU MLME for Rx aggregation */ |
228 | sta->ampdu_mlme.tid_rx[tid] = | 244 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); |
229 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | 245 | if (!tid_agg_rx) { |
230 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
231 | #ifdef CONFIG_MAC80211_HT_DEBUG | 246 | #ifdef CONFIG_MAC80211_HT_DEBUG |
232 | if (net_ratelimit()) | 247 | if (net_ratelimit()) |
233 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | 248 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", |
@@ -235,14 +250,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
235 | #endif | 250 | #endif |
236 | goto end; | 251 | goto end; |
237 | } | 252 | } |
238 | /* rx timer */ | ||
239 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
240 | sta_rx_agg_session_timer_expired; | ||
241 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
242 | (unsigned long)&sta->timer_to_tid[tid]; | ||
243 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
244 | 253 | ||
245 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 254 | /* rx timer */ |
255 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | ||
256 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | ||
257 | init_timer(&tid_agg_rx->session_timer); | ||
246 | 258 | ||
247 | /* prepare reordering buffer */ | 259 | /* prepare reordering buffer */ |
248 | tid_agg_rx->reorder_buf = | 260 | tid_agg_rx->reorder_buf = |
@@ -257,8 +269,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
257 | #endif | 269 | #endif |
258 | kfree(tid_agg_rx->reorder_buf); | 270 | kfree(tid_agg_rx->reorder_buf); |
259 | kfree(tid_agg_rx->reorder_time); | 271 | kfree(tid_agg_rx->reorder_time); |
260 | kfree(sta->ampdu_mlme.tid_rx[tid]); | 272 | kfree(tid_agg_rx); |
261 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
262 | goto end; | 273 | goto end; |
263 | } | 274 | } |
264 | 275 | ||
@@ -270,13 +281,12 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
270 | 281 | ||
271 | if (ret) { | 282 | if (ret) { |
272 | kfree(tid_agg_rx->reorder_buf); | 283 | kfree(tid_agg_rx->reorder_buf); |
284 | kfree(tid_agg_rx->reorder_time); | ||
273 | kfree(tid_agg_rx); | 285 | kfree(tid_agg_rx); |
274 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
275 | goto end; | 286 | goto end; |
276 | } | 287 | } |
277 | 288 | ||
278 | /* change state and send addba resp */ | 289 | /* update data */ |
279 | sta->ampdu_mlme.tid_active_rx[tid] = true; | ||
280 | tid_agg_rx->dialog_token = dialog_token; | 290 | tid_agg_rx->dialog_token = dialog_token; |
281 | tid_agg_rx->ssn = start_seq_num; | 291 | tid_agg_rx->ssn = start_seq_num; |
282 | tid_agg_rx->head_seq_num = start_seq_num; | 292 | tid_agg_rx->head_seq_num = start_seq_num; |
@@ -284,8 +294,15 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
284 | tid_agg_rx->timeout = timeout; | 294 | tid_agg_rx->timeout = timeout; |
285 | tid_agg_rx->stored_mpdu_num = 0; | 295 | tid_agg_rx->stored_mpdu_num = 0; |
286 | status = WLAN_STATUS_SUCCESS; | 296 | status = WLAN_STATUS_SUCCESS; |
297 | |||
298 | /* activate it for RX */ | ||
299 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); | ||
300 | |||
301 | if (timeout) | ||
302 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); | ||
303 | |||
287 | end: | 304 | end: |
288 | spin_unlock_bh(&sta->lock); | 305 | mutex_unlock(&sta->ampdu_mlme.mtx); |
289 | 306 | ||
290 | end_no_lock: | 307 | end_no_lock: |
291 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | 308 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index d1b6664a2532..c893f236acea 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | 6 | * Copyright 2005-2006, Devicescape Software, Inc. |
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
9 | * Copyright 2007-2009, Intel Corporation | 9 | * Copyright 2007-2010, Intel Corporation |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -21,28 +21,39 @@ | |||
21 | #include "wme.h" | 21 | #include "wme.h" |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * DOC: TX aggregation | 24 | * DOC: TX A-MPDU aggregation |
25 | * | 25 | * |
26 | * Aggregation on the TX side requires setting the hardware flag | 26 | * Aggregation on the TX side requires setting the hardware flag |
27 | * %IEEE80211_HW_AMPDU_AGGREGATION as well as, if present, the @ampdu_queues | 27 | * %IEEE80211_HW_AMPDU_AGGREGATION. The driver will then be handed |
28 | * hardware parameter to the number of hardware AMPDU queues. If there are no | 28 | * packets with a flag indicating A-MPDU aggregation. The driver |
29 | * hardware queues then the driver will (currently) have to do all frame | 29 | * or device is responsible for actually aggregating the frames, |
30 | * buffering. | 30 | * as well as deciding how many and which to aggregate. |
31 | * | 31 | * |
32 | * When TX aggregation is started by some subsystem (usually the rate control | 32 | * When TX aggregation is started by some subsystem (usually the rate |
33 | * algorithm would be appropriate) by calling the | 33 | * control algorithm would be appropriate) by calling the |
34 | * ieee80211_start_tx_ba_session() function, the driver will be notified via | 34 | * ieee80211_start_tx_ba_session() function, the driver will be |
35 | * its @ampdu_action function, with the %IEEE80211_AMPDU_TX_START action. | 35 | * notified via its @ampdu_action function, with the |
36 | * %IEEE80211_AMPDU_TX_START action. | ||
36 | * | 37 | * |
37 | * In response to that, the driver is later required to call the | 38 | * In response to that, the driver is later required to call the |
38 | * ieee80211_start_tx_ba_cb() (or ieee80211_start_tx_ba_cb_irqsafe()) | 39 | * ieee80211_start_tx_ba_cb_irqsafe() function, which will really |
39 | * function, which will start the aggregation session. | 40 | * start the aggregation session after the peer has also responded. |
41 | * If the peer responds negatively, the session will be stopped | ||
42 | * again right away. Note that it is possible for the aggregation | ||
43 | * session to be stopped before the driver has indicated that it | ||
44 | * is done setting it up, in which case it must not indicate the | ||
45 | * setup completion. | ||
40 | * | 46 | * |
41 | * Similarly, when the aggregation session is stopped by | 47 | * Also note that, since we also need to wait for a response from |
42 | * ieee80211_stop_tx_ba_session(), the driver's @ampdu_action function will | 48 | * the peer, the driver is notified of the completion of the |
43 | * be called with the action %IEEE80211_AMPDU_TX_STOP. In this case, the | 49 | * handshake by the %IEEE80211_AMPDU_TX_OPERATIONAL action to the |
44 | * call must not fail, and the driver must later call ieee80211_stop_tx_ba_cb() | 50 | * @ampdu_action callback. |
45 | * (or ieee80211_stop_tx_ba_cb_irqsafe()). | 51 | * |
52 | * Similarly, when the aggregation session is stopped by the peer | ||
53 | * or something calling ieee80211_stop_tx_ba_session(), the driver's | ||
54 | * @ampdu_action function will be called with the action | ||
55 | * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail, | ||
56 | * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe(). | ||
46 | */ | 57 | */ |
47 | 58 | ||
48 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | 59 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, |
@@ -125,25 +136,53 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
125 | ieee80211_tx_skb(sdata, skb); | 136 | ieee80211_tx_skb(sdata, skb); |
126 | } | 137 | } |
127 | 138 | ||
139 | static void kfree_tid_tx(struct rcu_head *rcu_head) | ||
140 | { | ||
141 | struct tid_ampdu_tx *tid_tx = | ||
142 | container_of(rcu_head, struct tid_ampdu_tx, rcu_head); | ||
143 | |||
144 | kfree(tid_tx); | ||
145 | } | ||
146 | |||
128 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
129 | enum ieee80211_back_parties initiator) | 148 | enum ieee80211_back_parties initiator) |
130 | { | 149 | { |
131 | struct ieee80211_local *local = sta->local; | 150 | struct ieee80211_local *local = sta->local; |
151 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | ||
132 | int ret; | 152 | int ret; |
133 | u8 *state; | 153 | |
154 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | ||
155 | |||
156 | if (!tid_tx) | ||
157 | return -ENOENT; | ||
158 | |||
159 | spin_lock_bh(&sta->lock); | ||
160 | |||
161 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | ||
162 | /* not even started yet! */ | ||
163 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | ||
164 | spin_unlock_bh(&sta->lock); | ||
165 | call_rcu(&tid_tx->rcu_head, kfree_tid_tx); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | spin_unlock_bh(&sta->lock); | ||
134 | 170 | ||
135 | #ifdef CONFIG_MAC80211_HT_DEBUG | 171 | #ifdef CONFIG_MAC80211_HT_DEBUG |
136 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", | 172 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", |
137 | sta->sta.addr, tid); | 173 | sta->sta.addr, tid); |
138 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 174 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
139 | 175 | ||
140 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 176 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); |
141 | 177 | ||
142 | if (*state == HT_AGG_STATE_OPERATIONAL) | 178 | /* |
143 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 179 | * After this packets are no longer handed right through |
180 | * to the driver but are put onto tid_tx->pending instead, | ||
181 | * with locking to ensure proper access. | ||
182 | */ | ||
183 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | ||
144 | 184 | ||
145 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 185 | tid_tx->stop_initiator = initiator; |
146 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
147 | 186 | ||
148 | ret = drv_ampdu_action(local, sta->sdata, | 187 | ret = drv_ampdu_action(local, sta->sdata, |
149 | IEEE80211_AMPDU_TX_STOP, | 188 | IEEE80211_AMPDU_TX_STOP, |
@@ -174,16 +213,14 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
174 | u16 tid = *(u8 *)data; | 213 | u16 tid = *(u8 *)data; |
175 | struct sta_info *sta = container_of((void *)data, | 214 | struct sta_info *sta = container_of((void *)data, |
176 | struct sta_info, timer_to_tid[tid]); | 215 | struct sta_info, timer_to_tid[tid]); |
177 | u8 *state; | 216 | struct tid_ampdu_tx *tid_tx; |
178 | |||
179 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
180 | 217 | ||
181 | /* check if the TID waits for addBA response */ | 218 | /* check if the TID waits for addBA response */ |
182 | spin_lock_bh(&sta->lock); | 219 | rcu_read_lock(); |
183 | if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK | | 220 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]); |
184 | HT_AGG_STATE_REQ_STOP_BA_MSK)) != | 221 | if (!tid_tx || |
185 | HT_ADDBA_REQUESTED_MSK) { | 222 | test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) { |
186 | spin_unlock_bh(&sta->lock); | 223 | rcu_read_unlock(); |
187 | #ifdef CONFIG_MAC80211_HT_DEBUG | 224 | #ifdef CONFIG_MAC80211_HT_DEBUG |
188 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 225 | printk(KERN_DEBUG "timer expired on tid %d but we are not " |
189 | "(or no longer) expecting addBA response there\n", | 226 | "(or no longer) expecting addBA response there\n", |
@@ -196,8 +233,8 @@ static void sta_addba_resp_timer_expired(unsigned long data) | |||
196 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | 233 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); |
197 | #endif | 234 | #endif |
198 | 235 | ||
199 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | 236 | ieee80211_stop_tx_ba_session(&sta->sta, tid); |
200 | spin_unlock_bh(&sta->lock); | 237 | rcu_read_unlock(); |
201 | } | 238 | } |
202 | 239 | ||
203 | static inline int ieee80211_ac_from_tid(int tid) | 240 | static inline int ieee80211_ac_from_tid(int tid) |
@@ -205,14 +242,112 @@ static inline int ieee80211_ac_from_tid(int tid) | |||
205 | return ieee802_1d_to_ac[tid & 7]; | 242 | return ieee802_1d_to_ac[tid & 7]; |
206 | } | 243 | } |
207 | 244 | ||
245 | /* | ||
246 | * When multiple aggregation sessions on multiple stations | ||
247 | * are being created/destroyed simultaneously, we need to | ||
248 | * refcount the global queue stop caused by that in order | ||
249 | * to not get into a situation where one of the aggregation | ||
250 | * setup or teardown re-enables queues before the other is | ||
251 | * ready to handle that. | ||
252 | * | ||
253 | * These two functions take care of this issue by keeping | ||
254 | * a global "agg_queue_stop" refcount. | ||
255 | */ | ||
256 | static void __acquires(agg_queue) | ||
257 | ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) | ||
258 | { | ||
259 | int queue = ieee80211_ac_from_tid(tid); | ||
260 | |||
261 | if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1) | ||
262 | ieee80211_stop_queue_by_reason( | ||
263 | &local->hw, queue, | ||
264 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
265 | __acquire(agg_queue); | ||
266 | } | ||
267 | |||
268 | static void __releases(agg_queue) | ||
269 | ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | ||
270 | { | ||
271 | int queue = ieee80211_ac_from_tid(tid); | ||
272 | |||
273 | if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0) | ||
274 | ieee80211_wake_queue_by_reason( | ||
275 | &local->hw, queue, | ||
276 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
277 | __release(agg_queue); | ||
278 | } | ||
279 | |||
280 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | ||
281 | { | ||
282 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | ||
283 | struct ieee80211_local *local = sta->local; | ||
284 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
285 | u16 start_seq_num; | ||
286 | int ret; | ||
287 | |||
288 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | ||
289 | |||
290 | /* | ||
291 | * While we're asking the driver about the aggregation, | ||
292 | * stop the AC queue so that we don't have to worry | ||
293 | * about frames that came in while we were doing that, | ||
294 | * which would require us to put them to the AC pending | ||
295 | * afterwards which just makes the code more complex. | ||
296 | */ | ||
297 | ieee80211_stop_queue_agg(local, tid); | ||
298 | |||
299 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | ||
300 | |||
301 | /* | ||
302 | * make sure no packets are being processed to get | ||
303 | * valid starting sequence number | ||
304 | */ | ||
305 | synchronize_net(); | ||
306 | |||
307 | start_seq_num = sta->tid_seq[tid] >> 4; | ||
308 | |||
309 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | ||
310 | &sta->sta, tid, &start_seq_num); | ||
311 | if (ret) { | ||
312 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
313 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
314 | " tid %d\n", tid); | ||
315 | #endif | ||
316 | spin_lock_bh(&sta->lock); | ||
317 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | ||
318 | spin_unlock_bh(&sta->lock); | ||
319 | |||
320 | ieee80211_wake_queue_agg(local, tid); | ||
321 | call_rcu(&tid_tx->rcu_head, kfree_tid_tx); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | /* we can take packets again now */ | ||
326 | ieee80211_wake_queue_agg(local, tid); | ||
327 | |||
328 | /* activate the timer for the recipient's addBA response */ | ||
329 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | ||
330 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
331 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
332 | #endif | ||
333 | |||
334 | spin_lock_bh(&sta->lock); | ||
335 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
336 | spin_unlock_bh(&sta->lock); | ||
337 | |||
338 | /* send AddBA request */ | ||
339 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | ||
340 | tid_tx->dialog_token, start_seq_num, | ||
341 | 0x40, 5000); | ||
342 | } | ||
343 | |||
208 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | 344 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) |
209 | { | 345 | { |
210 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 346 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
211 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 347 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
212 | struct ieee80211_local *local = sdata->local; | 348 | struct ieee80211_local *local = sdata->local; |
213 | u8 *state; | 349 | struct tid_ampdu_tx *tid_tx; |
214 | int ret = 0; | 350 | int ret = 0; |
215 | u16 start_seq_num; | ||
216 | 351 | ||
217 | trace_api_start_tx_ba_session(pubsta, tid); | 352 | trace_api_start_tx_ba_session(pubsta, tid); |
218 | 353 | ||
@@ -239,24 +374,15 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
239 | sdata->vif.type != NL80211_IFTYPE_AP) | 374 | sdata->vif.type != NL80211_IFTYPE_AP) |
240 | return -EINVAL; | 375 | return -EINVAL; |
241 | 376 | ||
242 | if (test_sta_flags(sta, WLAN_STA_DISASSOC)) { | ||
243 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
244 | printk(KERN_DEBUG "Disassociation is in progress. " | ||
245 | "Denying BA session request\n"); | ||
246 | #endif | ||
247 | return -EINVAL; | ||
248 | } | ||
249 | |||
250 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { | 377 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
251 | #ifdef CONFIG_MAC80211_HT_DEBUG | 378 | #ifdef CONFIG_MAC80211_HT_DEBUG |
252 | printk(KERN_DEBUG "Suspend in progress. " | 379 | printk(KERN_DEBUG "BA sessions blocked. " |
253 | "Denying BA session request\n"); | 380 | "Denying BA session request\n"); |
254 | #endif | 381 | #endif |
255 | return -EINVAL; | 382 | return -EINVAL; |
256 | } | 383 | } |
257 | 384 | ||
258 | spin_lock_bh(&sta->lock); | 385 | spin_lock_bh(&sta->lock); |
259 | spin_lock(&local->ampdu_lock); | ||
260 | 386 | ||
261 | /* we have tried too many times, receiver does not want A-MPDU */ | 387 | /* we have tried too many times, receiver does not want A-MPDU */ |
262 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | 388 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
@@ -264,9 +390,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
264 | goto err_unlock_sta; | 390 | goto err_unlock_sta; |
265 | } | 391 | } |
266 | 392 | ||
267 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 393 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
268 | /* check if the TID is not in aggregation flow already */ | 394 | /* check if the TID is not in aggregation flow already */ |
269 | if (*state != HT_AGG_STATE_IDLE) { | 395 | if (tid_tx) { |
270 | #ifdef CONFIG_MAC80211_HT_DEBUG | 396 | #ifdef CONFIG_MAC80211_HT_DEBUG |
271 | printk(KERN_DEBUG "BA request denied - session is not " | 397 | printk(KERN_DEBUG "BA request denied - session is not " |
272 | "idle on tid %u\n", tid); | 398 | "idle on tid %u\n", tid); |
@@ -275,96 +401,37 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
275 | goto err_unlock_sta; | 401 | goto err_unlock_sta; |
276 | } | 402 | } |
277 | 403 | ||
278 | /* | ||
279 | * While we're asking the driver about the aggregation, | ||
280 | * stop the AC queue so that we don't have to worry | ||
281 | * about frames that came in while we were doing that, | ||
282 | * which would require us to put them to the AC pending | ||
283 | * afterwards which just makes the code more complex. | ||
284 | */ | ||
285 | ieee80211_stop_queue_by_reason( | ||
286 | &local->hw, ieee80211_ac_from_tid(tid), | ||
287 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
288 | |||
289 | /* prepare A-MPDU MLME for Tx aggregation */ | 404 | /* prepare A-MPDU MLME for Tx aggregation */ |
290 | sta->ampdu_mlme.tid_tx[tid] = | 405 | tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); |
291 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | 406 | if (!tid_tx) { |
292 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
293 | #ifdef CONFIG_MAC80211_HT_DEBUG | 407 | #ifdef CONFIG_MAC80211_HT_DEBUG |
294 | if (net_ratelimit()) | 408 | if (net_ratelimit()) |
295 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | 409 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", |
296 | tid); | 410 | tid); |
297 | #endif | 411 | #endif |
298 | ret = -ENOMEM; | 412 | ret = -ENOMEM; |
299 | goto err_wake_queue; | 413 | goto err_unlock_sta; |
300 | } | 414 | } |
301 | 415 | ||
302 | skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); | 416 | skb_queue_head_init(&tid_tx->pending); |
417 | __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | ||
303 | 418 | ||
304 | /* Tx timer */ | 419 | /* Tx timer */ |
305 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | 420 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; |
306 | sta_addba_resp_timer_expired; | 421 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
307 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | 422 | init_timer(&tid_tx->addba_resp_timer); |
308 | (unsigned long)&sta->timer_to_tid[tid]; | ||
309 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
310 | |||
311 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
312 | * call back right away, it must see that the flow has begun */ | ||
313 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
314 | |||
315 | start_seq_num = sta->tid_seq[tid] >> 4; | ||
316 | |||
317 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | ||
318 | pubsta, tid, &start_seq_num); | ||
319 | 423 | ||
320 | if (ret) { | 424 | /* assign a dialog token */ |
321 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
322 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
323 | " tid %d\n", tid); | ||
324 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
325 | *state = HT_AGG_STATE_IDLE; | ||
326 | goto err_free; | ||
327 | } | ||
328 | |||
329 | /* Driver vetoed or OKed, but we can take packets again now */ | ||
330 | ieee80211_wake_queue_by_reason( | ||
331 | &local->hw, ieee80211_ac_from_tid(tid), | ||
332 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
333 | |||
334 | spin_unlock(&local->ampdu_lock); | ||
335 | |||
336 | /* prepare tid data */ | ||
337 | sta->ampdu_mlme.dialog_token_allocator++; | 425 | sta->ampdu_mlme.dialog_token_allocator++; |
338 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | 426 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; |
339 | sta->ampdu_mlme.dialog_token_allocator; | ||
340 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
341 | 427 | ||
342 | spin_unlock_bh(&sta->lock); | 428 | /* finally, assign it to the array */ |
429 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); | ||
343 | 430 | ||
344 | /* send AddBA request */ | 431 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); |
345 | ieee80211_send_addba_request(sdata, pubsta->addr, tid, | 432 | |
346 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | 433 | /* this flow continues off the work */ |
347 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
348 | 0x40, 5000); | ||
349 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
350 | /* activate the timer for the recipient's addBA response */ | ||
351 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
352 | jiffies + ADDBA_RESP_INTERVAL; | ||
353 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
354 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
355 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
356 | #endif | ||
357 | return 0; | ||
358 | |||
359 | err_free: | ||
360 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
361 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
362 | err_wake_queue: | ||
363 | ieee80211_wake_queue_by_reason( | ||
364 | &local->hw, ieee80211_ac_from_tid(tid), | ||
365 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
366 | err_unlock_sta: | 434 | err_unlock_sta: |
367 | spin_unlock(&local->ampdu_lock); | ||
368 | spin_unlock_bh(&sta->lock); | 435 | spin_unlock_bh(&sta->lock); |
369 | return ret; | 436 | return ret; |
370 | } | 437 | } |
@@ -372,69 +439,65 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | |||
372 | 439 | ||
373 | /* | 440 | /* |
374 | * splice packets from the STA's pending to the local pending, | 441 | * splice packets from the STA's pending to the local pending, |
375 | * requires a call to ieee80211_agg_splice_finish and holding | 442 | * requires a call to ieee80211_agg_splice_finish later |
376 | * local->ampdu_lock across both calls. | ||
377 | */ | 443 | */ |
378 | static void ieee80211_agg_splice_packets(struct ieee80211_local *local, | 444 | static void __acquires(agg_queue) |
379 | struct sta_info *sta, u16 tid) | 445 | ieee80211_agg_splice_packets(struct ieee80211_local *local, |
446 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
380 | { | 447 | { |
448 | int queue = ieee80211_ac_from_tid(tid); | ||
381 | unsigned long flags; | 449 | unsigned long flags; |
382 | u16 queue = ieee80211_ac_from_tid(tid); | ||
383 | |||
384 | ieee80211_stop_queue_by_reason( | ||
385 | &local->hw, queue, | ||
386 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
387 | 450 | ||
388 | if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK)) | 451 | ieee80211_stop_queue_agg(local, tid); |
389 | return; | ||
390 | 452 | ||
391 | if (WARN(!sta->ampdu_mlme.tid_tx[tid], | 453 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" |
392 | "TID %d gone but expected when splicing aggregates from" | 454 | " from the pending queue\n", tid)) |
393 | "the pending queue\n", tid)) | ||
394 | return; | 455 | return; |
395 | 456 | ||
396 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { | 457 | if (!skb_queue_empty(&tid_tx->pending)) { |
397 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 458 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
398 | /* copy over remaining packets */ | 459 | /* copy over remaining packets */ |
399 | skb_queue_splice_tail_init( | 460 | skb_queue_splice_tail_init(&tid_tx->pending, |
400 | &sta->ampdu_mlme.tid_tx[tid]->pending, | 461 | &local->pending[queue]); |
401 | &local->pending[queue]); | ||
402 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 462 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
403 | } | 463 | } |
404 | } | 464 | } |
405 | 465 | ||
406 | static void ieee80211_agg_splice_finish(struct ieee80211_local *local, | 466 | static void __releases(agg_queue) |
407 | struct sta_info *sta, u16 tid) | 467 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) |
408 | { | 468 | { |
409 | u16 queue = ieee80211_ac_from_tid(tid); | 469 | ieee80211_wake_queue_agg(local, tid); |
410 | |||
411 | ieee80211_wake_queue_by_reason( | ||
412 | &local->hw, queue, | ||
413 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | ||
414 | } | 470 | } |
415 | 471 | ||
416 | /* caller must hold sta->lock */ | ||
417 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 472 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
418 | struct sta_info *sta, u16 tid) | 473 | struct sta_info *sta, u16 tid) |
419 | { | 474 | { |
475 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | ||
476 | |||
420 | #ifdef CONFIG_MAC80211_HT_DEBUG | 477 | #ifdef CONFIG_MAC80211_HT_DEBUG |
421 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); | 478 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
422 | #endif | 479 | #endif |
423 | 480 | ||
424 | spin_lock(&local->ampdu_lock); | ||
425 | ieee80211_agg_splice_packets(local, sta, tid); | ||
426 | /* | ||
427 | * NB: we rely on sta->lock being taken in the TX | ||
428 | * processing here when adding to the pending queue, | ||
429 | * otherwise we could only change the state of the | ||
430 | * session to OPERATIONAL _here_. | ||
431 | */ | ||
432 | ieee80211_agg_splice_finish(local, sta, tid); | ||
433 | spin_unlock(&local->ampdu_lock); | ||
434 | |||
435 | drv_ampdu_action(local, sta->sdata, | 481 | drv_ampdu_action(local, sta->sdata, |
436 | IEEE80211_AMPDU_TX_OPERATIONAL, | 482 | IEEE80211_AMPDU_TX_OPERATIONAL, |
437 | &sta->sta, tid, NULL); | 483 | &sta->sta, tid, NULL); |
484 | |||
485 | /* | ||
486 | * synchronize with TX path, while splicing the TX path | ||
487 | * should block so it won't put more packets onto pending. | ||
488 | */ | ||
489 | spin_lock_bh(&sta->lock); | ||
490 | |||
491 | ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); | ||
492 | /* | ||
493 | * Now mark as operational. This will be visible | ||
494 | * in the TX path, and lets it go lock-free in | ||
495 | * the common case. | ||
496 | */ | ||
497 | set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); | ||
498 | ieee80211_agg_splice_finish(local, tid); | ||
499 | |||
500 | spin_unlock_bh(&sta->lock); | ||
438 | } | 501 | } |
439 | 502 | ||
440 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | 503 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) |
@@ -442,7 +505,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
442 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 505 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
443 | struct ieee80211_local *local = sdata->local; | 506 | struct ieee80211_local *local = sdata->local; |
444 | struct sta_info *sta; | 507 | struct sta_info *sta; |
445 | u8 *state; | 508 | struct tid_ampdu_tx *tid_tx; |
446 | 509 | ||
447 | trace_api_start_tx_ba_cb(sdata, ra, tid); | 510 | trace_api_start_tx_ba_cb(sdata, ra, tid); |
448 | 511 | ||
@@ -454,42 +517,36 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
454 | return; | 517 | return; |
455 | } | 518 | } |
456 | 519 | ||
457 | rcu_read_lock(); | 520 | mutex_lock(&local->sta_mtx); |
458 | sta = sta_info_get(sdata, ra); | 521 | sta = sta_info_get(sdata, ra); |
459 | if (!sta) { | 522 | if (!sta) { |
460 | rcu_read_unlock(); | 523 | mutex_unlock(&local->sta_mtx); |
461 | #ifdef CONFIG_MAC80211_HT_DEBUG | 524 | #ifdef CONFIG_MAC80211_HT_DEBUG |
462 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | 525 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
463 | #endif | 526 | #endif |
464 | return; | 527 | return; |
465 | } | 528 | } |
466 | 529 | ||
467 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 530 | mutex_lock(&sta->ampdu_mlme.mtx); |
468 | spin_lock_bh(&sta->lock); | 531 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
469 | 532 | ||
470 | if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) { | 533 | if (WARN_ON(!tid_tx)) { |
471 | #ifdef CONFIG_MAC80211_HT_DEBUG | 534 | #ifdef CONFIG_MAC80211_HT_DEBUG |
472 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | 535 | printk(KERN_DEBUG "addBA was not requested!\n"); |
473 | *state); | ||
474 | #endif | 536 | #endif |
475 | spin_unlock_bh(&sta->lock); | 537 | goto unlock; |
476 | rcu_read_unlock(); | ||
477 | return; | ||
478 | } | 538 | } |
479 | 539 | ||
480 | if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK)) | 540 | if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) |
481 | goto out; | 541 | goto unlock; |
482 | |||
483 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
484 | 542 | ||
485 | if (*state == HT_AGG_STATE_OPERATIONAL) | 543 | if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) |
486 | ieee80211_agg_tx_operational(local, sta, tid); | 544 | ieee80211_agg_tx_operational(local, sta, tid); |
487 | 545 | ||
488 | out: | 546 | unlock: |
489 | spin_unlock_bh(&sta->lock); | 547 | mutex_unlock(&sta->ampdu_mlme.mtx); |
490 | rcu_read_unlock(); | 548 | mutex_unlock(&local->sta_mtx); |
491 | } | 549 | } |
492 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
493 | 550 | ||
494 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | 551 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, |
495 | const u8 *ra, u16 tid) | 552 | const u8 *ra, u16 tid) |
@@ -510,33 +567,24 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
510 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 567 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
511 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 568 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
512 | ra_tid->tid = tid; | 569 | ra_tid->tid = tid; |
513 | ra_tid->vif = vif; | ||
514 | 570 | ||
515 | skb->pkt_type = IEEE80211_ADDBA_MSG; | 571 | skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START; |
516 | skb_queue_tail(&local->skb_queue, skb); | 572 | skb_queue_tail(&sdata->skb_queue, skb); |
517 | tasklet_schedule(&local->tasklet); | 573 | ieee80211_queue_work(&local->hw, &sdata->work); |
518 | } | 574 | } |
519 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | 575 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); |
520 | 576 | ||
521 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 577 | int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
522 | enum ieee80211_back_parties initiator) | 578 | enum ieee80211_back_parties initiator) |
523 | { | 579 | { |
524 | u8 *state; | ||
525 | int ret; | 580 | int ret; |
526 | 581 | ||
527 | /* check if the TID is in aggregation */ | 582 | mutex_lock(&sta->ampdu_mlme.mtx); |
528 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
529 | spin_lock_bh(&sta->lock); | ||
530 | |||
531 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
532 | ret = -ENOENT; | ||
533 | goto unlock; | ||
534 | } | ||
535 | 583 | ||
536 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); | 584 | ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); |
537 | 585 | ||
538 | unlock: | 586 | mutex_unlock(&sta->ampdu_mlme.mtx); |
539 | spin_unlock_bh(&sta->lock); | 587 | |
540 | return ret; | 588 | return ret; |
541 | } | 589 | } |
542 | 590 | ||
@@ -545,6 +593,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
545 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 593 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
546 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 594 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
547 | struct ieee80211_local *local = sdata->local; | 595 | struct ieee80211_local *local = sdata->local; |
596 | struct tid_ampdu_tx *tid_tx; | ||
597 | int ret = 0; | ||
548 | 598 | ||
549 | trace_api_stop_tx_ba_session(pubsta, tid); | 599 | trace_api_stop_tx_ba_session(pubsta, tid); |
550 | 600 | ||
@@ -554,7 +604,26 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
554 | if (tid >= STA_TID_NUM) | 604 | if (tid >= STA_TID_NUM) |
555 | return -EINVAL; | 605 | return -EINVAL; |
556 | 606 | ||
557 | return __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | 607 | spin_lock_bh(&sta->lock); |
608 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | ||
609 | |||
610 | if (!tid_tx) { | ||
611 | ret = -ENOENT; | ||
612 | goto unlock; | ||
613 | } | ||
614 | |||
615 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
616 | /* already in progress stopping it */ | ||
617 | ret = 0; | ||
618 | goto unlock; | ||
619 | } | ||
620 | |||
621 | set_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state); | ||
622 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); | ||
623 | |||
624 | unlock: | ||
625 | spin_unlock_bh(&sta->lock); | ||
626 | return ret; | ||
558 | } | 627 | } |
559 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | 628 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); |
560 | 629 | ||
@@ -563,7 +632,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
563 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 632 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
564 | struct ieee80211_local *local = sdata->local; | 633 | struct ieee80211_local *local = sdata->local; |
565 | struct sta_info *sta; | 634 | struct sta_info *sta; |
566 | u8 *state; | 635 | struct tid_ampdu_tx *tid_tx; |
567 | 636 | ||
568 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | 637 | trace_api_stop_tx_ba_cb(sdata, ra, tid); |
569 | 638 | ||
@@ -580,51 +649,56 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
580 | ra, tid); | 649 | ra, tid); |
581 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 650 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
582 | 651 | ||
583 | rcu_read_lock(); | 652 | mutex_lock(&local->sta_mtx); |
653 | |||
584 | sta = sta_info_get(sdata, ra); | 654 | sta = sta_info_get(sdata, ra); |
585 | if (!sta) { | 655 | if (!sta) { |
586 | #ifdef CONFIG_MAC80211_HT_DEBUG | 656 | #ifdef CONFIG_MAC80211_HT_DEBUG |
587 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | 657 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
588 | #endif | 658 | #endif |
589 | rcu_read_unlock(); | 659 | goto unlock; |
590 | return; | ||
591 | } | 660 | } |
592 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
593 | 661 | ||
594 | /* NOTE: no need to use sta->lock in this state check, as | 662 | mutex_lock(&sta->ampdu_mlme.mtx); |
595 | * ieee80211_stop_tx_ba_session will let only one stop call to | 663 | spin_lock_bh(&sta->lock); |
596 | * pass through per sta/tid | 664 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
597 | */ | 665 | |
598 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 666 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
599 | #ifdef CONFIG_MAC80211_HT_DEBUG | 667 | #ifdef CONFIG_MAC80211_HT_DEBUG |
600 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | 668 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); |
601 | #endif | 669 | #endif |
602 | rcu_read_unlock(); | 670 | goto unlock_sta; |
603 | return; | ||
604 | } | 671 | } |
605 | 672 | ||
606 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | 673 | if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR) |
607 | ieee80211_send_delba(sta->sdata, ra, tid, | 674 | ieee80211_send_delba(sta->sdata, ra, tid, |
608 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 675 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
609 | 676 | ||
610 | spin_lock_bh(&sta->lock); | 677 | /* |
611 | spin_lock(&local->ampdu_lock); | 678 | * When we get here, the TX path will not be lockless any more wrt. |
679 | * aggregation, since the OPERATIONAL bit has long been cleared. | ||
680 | * Thus it will block on getting the lock, if it occurs. So if we | ||
681 | * stop the queue now, we will not get any more packets, and any | ||
682 | * that might be being processed will wait for us here, thereby | ||
683 | * guaranteeing that no packets go to the tid_tx pending queue any | ||
684 | * more. | ||
685 | */ | ||
612 | 686 | ||
613 | ieee80211_agg_splice_packets(local, sta, tid); | 687 | ieee80211_agg_splice_packets(local, tid_tx, tid); |
614 | 688 | ||
615 | *state = HT_AGG_STATE_IDLE; | 689 | /* future packets must not find the tid_tx struct any more */ |
616 | /* from now on packets are no longer put onto sta->pending */ | 690 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); |
617 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
618 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
619 | 691 | ||
620 | ieee80211_agg_splice_finish(local, sta, tid); | 692 | ieee80211_agg_splice_finish(local, tid); |
621 | 693 | ||
622 | spin_unlock(&local->ampdu_lock); | 694 | call_rcu(&tid_tx->rcu_head, kfree_tid_tx); |
623 | spin_unlock_bh(&sta->lock); | ||
624 | 695 | ||
625 | rcu_read_unlock(); | 696 | unlock_sta: |
697 | spin_unlock_bh(&sta->lock); | ||
698 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
699 | unlock: | ||
700 | mutex_unlock(&local->sta_mtx); | ||
626 | } | 701 | } |
627 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
628 | 702 | ||
629 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | 703 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, |
630 | const u8 *ra, u16 tid) | 704 | const u8 *ra, u16 tid) |
@@ -645,11 +719,10 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
645 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 719 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
646 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 720 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
647 | ra_tid->tid = tid; | 721 | ra_tid->tid = tid; |
648 | ra_tid->vif = vif; | ||
649 | 722 | ||
650 | skb->pkt_type = IEEE80211_DELBA_MSG; | 723 | skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP; |
651 | skb_queue_tail(&local->skb_queue, skb); | 724 | skb_queue_tail(&sdata->skb_queue, skb); |
652 | tasklet_schedule(&local->tasklet); | 725 | ieee80211_queue_work(&local->hw, &sdata->work); |
653 | } | 726 | } |
654 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | 727 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); |
655 | 728 | ||
@@ -659,40 +732,40 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
659 | struct ieee80211_mgmt *mgmt, | 732 | struct ieee80211_mgmt *mgmt, |
660 | size_t len) | 733 | size_t len) |
661 | { | 734 | { |
735 | struct tid_ampdu_tx *tid_tx; | ||
662 | u16 capab, tid; | 736 | u16 capab, tid; |
663 | u8 *state; | ||
664 | 737 | ||
665 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 738 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
666 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 739 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
667 | 740 | ||
668 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 741 | mutex_lock(&sta->ampdu_mlme.mtx); |
669 | |||
670 | spin_lock_bh(&sta->lock); | ||
671 | 742 | ||
672 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) | 743 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; |
744 | if (!tid_tx) | ||
673 | goto out; | 745 | goto out; |
674 | 746 | ||
675 | if (mgmt->u.action.u.addba_resp.dialog_token != | 747 | if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) { |
676 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | ||
677 | #ifdef CONFIG_MAC80211_HT_DEBUG | 748 | #ifdef CONFIG_MAC80211_HT_DEBUG |
678 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 749 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
679 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 750 | #endif |
680 | goto out; | 751 | goto out; |
681 | } | 752 | } |
682 | 753 | ||
683 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 754 | del_timer(&tid_tx->addba_resp_timer); |
684 | 755 | ||
685 | #ifdef CONFIG_MAC80211_HT_DEBUG | 756 | #ifdef CONFIG_MAC80211_HT_DEBUG |
686 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 757 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
687 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 758 | #endif |
688 | 759 | ||
689 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 760 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
690 | == WLAN_STATUS_SUCCESS) { | 761 | == WLAN_STATUS_SUCCESS) { |
691 | u8 curstate = *state; | 762 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
692 | 763 | &tid_tx->state)) { | |
693 | *state |= HT_ADDBA_RECEIVED_MSK; | 764 | /* ignore duplicate response */ |
765 | goto out; | ||
766 | } | ||
694 | 767 | ||
695 | if (*state != curstate && *state == HT_AGG_STATE_OPERATIONAL) | 768 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) |
696 | ieee80211_agg_tx_operational(local, sta, tid); | 769 | ieee80211_agg_tx_operational(local, sta, tid); |
697 | 770 | ||
698 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 771 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
@@ -701,5 +774,5 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
701 | } | 774 | } |
702 | 775 | ||
703 | out: | 776 | out: |
704 | spin_unlock_bh(&sta->lock); | 777 | mutex_unlock(&sta->ampdu_mlme.mtx); |
705 | } | 778 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1f76d048388b..ed8c9f5be94f 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1446,7 +1446,6 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1446 | { | 1446 | { |
1447 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1447 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1448 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1448 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1449 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1450 | 1449 | ||
1451 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1450 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1452 | return -EOPNOTSUPP; | 1451 | return -EOPNOTSUPP; |
@@ -1455,11 +1454,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1455 | return -EOPNOTSUPP; | 1454 | return -EOPNOTSUPP; |
1456 | 1455 | ||
1457 | if (enabled == sdata->u.mgd.powersave && | 1456 | if (enabled == sdata->u.mgd.powersave && |
1458 | timeout == conf->dynamic_ps_forced_timeout) | 1457 | timeout == local->dynamic_ps_forced_timeout) |
1459 | return 0; | 1458 | return 0; |
1460 | 1459 | ||
1461 | sdata->u.mgd.powersave = enabled; | 1460 | sdata->u.mgd.powersave = enabled; |
1462 | conf->dynamic_ps_forced_timeout = timeout; | 1461 | local->dynamic_ps_forced_timeout = timeout; |
1463 | 1462 | ||
1464 | /* no change, but if automatic follow powersave */ | 1463 | /* no change, but if automatic follow powersave */ |
1465 | mutex_lock(&sdata->u.mgd.mtx); | 1464 | mutex_lock(&sdata->u.mgd.mtx); |
@@ -1555,9 +1554,55 @@ static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | |||
1555 | bool channel_type_valid, | 1554 | bool channel_type_valid, |
1556 | const u8 *buf, size_t len, u64 *cookie) | 1555 | const u8 *buf, size_t len, u64 *cookie) |
1557 | { | 1556 | { |
1558 | return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan, | 1557 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1559 | channel_type, channel_type_valid, | 1558 | struct ieee80211_local *local = sdata->local; |
1560 | buf, len, cookie); | 1559 | struct sk_buff *skb; |
1560 | struct sta_info *sta; | ||
1561 | const struct ieee80211_mgmt *mgmt = (void *)buf; | ||
1562 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
1563 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1564 | |||
1565 | /* Check that we are on the requested channel for transmission */ | ||
1566 | if (chan != local->tmp_channel && | ||
1567 | chan != local->oper_channel) | ||
1568 | return -EBUSY; | ||
1569 | if (channel_type_valid && | ||
1570 | (channel_type != local->tmp_channel_type && | ||
1571 | channel_type != local->_oper_channel_type)) | ||
1572 | return -EBUSY; | ||
1573 | |||
1574 | switch (sdata->vif.type) { | ||
1575 | case NL80211_IFTYPE_ADHOC: | ||
1576 | if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) | ||
1577 | break; | ||
1578 | rcu_read_lock(); | ||
1579 | sta = sta_info_get(sdata, mgmt->da); | ||
1580 | rcu_read_unlock(); | ||
1581 | if (!sta) | ||
1582 | return -ENOLINK; | ||
1583 | break; | ||
1584 | case NL80211_IFTYPE_STATION: | ||
1585 | if (!(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED)) | ||
1586 | flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
1587 | break; | ||
1588 | default: | ||
1589 | return -EOPNOTSUPP; | ||
1590 | } | ||
1591 | |||
1592 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | ||
1593 | if (!skb) | ||
1594 | return -ENOMEM; | ||
1595 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1596 | |||
1597 | memcpy(skb_put(skb, len), buf, len); | ||
1598 | |||
1599 | IEEE80211_SKB_CB(skb)->flags = flags; | ||
1600 | |||
1601 | skb->dev = sdata->dev; | ||
1602 | ieee80211_tx_skb(sdata, skb); | ||
1603 | |||
1604 | *cookie = (unsigned long) skb; | ||
1605 | return 0; | ||
1561 | } | 1606 | } |
1562 | 1607 | ||
1563 | struct cfg80211_ops mac80211_config_ops = { | 1608 | struct cfg80211_ops mac80211_config_ops = { |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 97c9e46e859e..fa5e76e658ef 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -143,7 +143,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf, | |||
143 | len = p - buf; | 143 | len = p - buf; |
144 | break; | 144 | break; |
145 | case ALG_CCMP: | 145 | case ALG_CCMP: |
146 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { | 146 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) { |
147 | rpn = key->u.ccmp.rx_pn[i]; | 147 | rpn = key->u.ccmp.rx_pn[i]; |
148 | p += scnprintf(p, sizeof(buf)+buf-p, | 148 | p += scnprintf(p, sizeof(buf)+buf-p, |
149 | "%02x%02x%02x%02x%02x%02x\n", | 149 | "%02x%02x%02x%02x%02x%02x\n", |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 576e024715e3..76839d4dfaac 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -121,28 +121,25 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
121 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 121 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
122 | sta->ampdu_mlme.dialog_token_allocator + 1); | 122 | sta->ampdu_mlme.dialog_token_allocator + 1); |
123 | p += scnprintf(p, sizeof(buf) + buf - p, | 123 | p += scnprintf(p, sizeof(buf) + buf - p, |
124 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); | 124 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); |
125 | for (i = 0; i < STA_TID_NUM; i++) { | 125 | for (i = 0; i < STA_TID_NUM; i++) { |
126 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 126 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
127 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 127 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
128 | sta->ampdu_mlme.tid_active_rx[i]); | 128 | !!sta->ampdu_mlme.tid_rx[i]); |
129 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 129 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
130 | sta->ampdu_mlme.tid_active_rx[i] ? | 130 | sta->ampdu_mlme.tid_rx[i] ? |
131 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | 131 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); |
132 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 132 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
133 | sta->ampdu_mlme.tid_active_rx[i] ? | 133 | sta->ampdu_mlme.tid_rx[i] ? |
134 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | 134 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); |
135 | 135 | ||
136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
137 | sta->ampdu_mlme.tid_state_tx[i]); | 137 | !!sta->ampdu_mlme.tid_tx[i]); |
138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
139 | sta->ampdu_mlme.tid_state_tx[i] ? | 139 | sta->ampdu_mlme.tid_tx[i] ? |
140 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); | 140 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); |
141 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | ||
142 | sta->ampdu_mlme.tid_state_tx[i] ? | ||
143 | sta->ampdu_mlme.tid_tx[i]->ssn : 0); | ||
144 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", | 141 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", |
145 | sta->ampdu_mlme.tid_state_tx[i] ? | 142 | sta->ampdu_mlme.tid_tx[i] ? |
146 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); | 143 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); |
147 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); | 144 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); |
148 | } | 145 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 7d18a3245e3d..c33317320eee 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -16,10 +16,11 @@ static inline int drv_start(struct ieee80211_local *local) | |||
16 | 16 | ||
17 | might_sleep(); | 17 | might_sleep(); |
18 | 18 | ||
19 | trace_drv_start(local); | ||
19 | local->started = true; | 20 | local->started = true; |
20 | smp_mb(); | 21 | smp_mb(); |
21 | ret = local->ops->start(&local->hw); | 22 | ret = local->ops->start(&local->hw); |
22 | trace_drv_start(local, ret); | 23 | trace_drv_return_int(local, ret); |
23 | return ret; | 24 | return ret; |
24 | } | 25 | } |
25 | 26 | ||
@@ -27,8 +28,9 @@ static inline void drv_stop(struct ieee80211_local *local) | |||
27 | { | 28 | { |
28 | might_sleep(); | 29 | might_sleep(); |
29 | 30 | ||
30 | local->ops->stop(&local->hw); | ||
31 | trace_drv_stop(local); | 31 | trace_drv_stop(local); |
32 | local->ops->stop(&local->hw); | ||
33 | trace_drv_return_void(local); | ||
32 | 34 | ||
33 | /* sync away all work on the tasklet before clearing started */ | 35 | /* sync away all work on the tasklet before clearing started */ |
34 | tasklet_disable(&local->tasklet); | 36 | tasklet_disable(&local->tasklet); |
@@ -46,8 +48,9 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
46 | 48 | ||
47 | might_sleep(); | 49 | might_sleep(); |
48 | 50 | ||
51 | trace_drv_add_interface(local, vif_to_sdata(vif)); | ||
49 | ret = local->ops->add_interface(&local->hw, vif); | 52 | ret = local->ops->add_interface(&local->hw, vif); |
50 | trace_drv_add_interface(local, vif_to_sdata(vif), ret); | 53 | trace_drv_return_int(local, ret); |
51 | return ret; | 54 | return ret; |
52 | } | 55 | } |
53 | 56 | ||
@@ -56,8 +59,9 @@ static inline void drv_remove_interface(struct ieee80211_local *local, | |||
56 | { | 59 | { |
57 | might_sleep(); | 60 | might_sleep(); |
58 | 61 | ||
59 | local->ops->remove_interface(&local->hw, vif); | ||
60 | trace_drv_remove_interface(local, vif_to_sdata(vif)); | 62 | trace_drv_remove_interface(local, vif_to_sdata(vif)); |
63 | local->ops->remove_interface(&local->hw, vif); | ||
64 | trace_drv_return_void(local); | ||
61 | } | 65 | } |
62 | 66 | ||
63 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 67 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
@@ -66,8 +70,9 @@ static inline int drv_config(struct ieee80211_local *local, u32 changed) | |||
66 | 70 | ||
67 | might_sleep(); | 71 | might_sleep(); |
68 | 72 | ||
73 | trace_drv_config(local, changed); | ||
69 | ret = local->ops->config(&local->hw, changed); | 74 | ret = local->ops->config(&local->hw, changed); |
70 | trace_drv_config(local, changed, ret); | 75 | trace_drv_return_int(local, ret); |
71 | return ret; | 76 | return ret; |
72 | } | 77 | } |
73 | 78 | ||
@@ -78,26 +83,10 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
78 | { | 83 | { |
79 | might_sleep(); | 84 | might_sleep(); |
80 | 85 | ||
86 | trace_drv_bss_info_changed(local, sdata, info, changed); | ||
81 | if (local->ops->bss_info_changed) | 87 | if (local->ops->bss_info_changed) |
82 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); | 88 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); |
83 | trace_drv_bss_info_changed(local, sdata, info, changed); | 89 | trace_drv_return_void(local); |
84 | } | ||
85 | |||
86 | struct in_ifaddr; | ||
87 | static inline int drv_configure_arp_filter(struct ieee80211_local *local, | ||
88 | struct ieee80211_vif *vif, | ||
89 | struct in_ifaddr *ifa_list) | ||
90 | { | ||
91 | int ret = 0; | ||
92 | |||
93 | might_sleep(); | ||
94 | |||
95 | if (local->ops->configure_arp_filter) | ||
96 | ret = local->ops->configure_arp_filter(&local->hw, vif, | ||
97 | ifa_list); | ||
98 | |||
99 | trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret); | ||
100 | return ret; | ||
101 | } | 90 | } |
102 | 91 | ||
103 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 92 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
@@ -105,10 +94,12 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | |||
105 | { | 94 | { |
106 | u64 ret = 0; | 95 | u64 ret = 0; |
107 | 96 | ||
97 | trace_drv_prepare_multicast(local, mc_list->count); | ||
98 | |||
108 | if (local->ops->prepare_multicast) | 99 | if (local->ops->prepare_multicast) |
109 | ret = local->ops->prepare_multicast(&local->hw, mc_list); | 100 | ret = local->ops->prepare_multicast(&local->hw, mc_list); |
110 | 101 | ||
111 | trace_drv_prepare_multicast(local, mc_list->count, ret); | 102 | trace_drv_return_u64(local, ret); |
112 | 103 | ||
113 | return ret; | 104 | return ret; |
114 | } | 105 | } |
@@ -120,19 +111,21 @@ static inline void drv_configure_filter(struct ieee80211_local *local, | |||
120 | { | 111 | { |
121 | might_sleep(); | 112 | might_sleep(); |
122 | 113 | ||
123 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | ||
124 | multicast); | ||
125 | trace_drv_configure_filter(local, changed_flags, total_flags, | 114 | trace_drv_configure_filter(local, changed_flags, total_flags, |
126 | multicast); | 115 | multicast); |
116 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | ||
117 | multicast); | ||
118 | trace_drv_return_void(local); | ||
127 | } | 119 | } |
128 | 120 | ||
129 | static inline int drv_set_tim(struct ieee80211_local *local, | 121 | static inline int drv_set_tim(struct ieee80211_local *local, |
130 | struct ieee80211_sta *sta, bool set) | 122 | struct ieee80211_sta *sta, bool set) |
131 | { | 123 | { |
132 | int ret = 0; | 124 | int ret = 0; |
125 | trace_drv_set_tim(local, sta, set); | ||
133 | if (local->ops->set_tim) | 126 | if (local->ops->set_tim) |
134 | ret = local->ops->set_tim(&local->hw, sta, set); | 127 | ret = local->ops->set_tim(&local->hw, sta, set); |
135 | trace_drv_set_tim(local, sta, set, ret); | 128 | trace_drv_return_int(local, ret); |
136 | return ret; | 129 | return ret; |
137 | } | 130 | } |
138 | 131 | ||
@@ -146,8 +139,9 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
146 | 139 | ||
147 | might_sleep(); | 140 | might_sleep(); |
148 | 141 | ||
142 | trace_drv_set_key(local, cmd, sdata, sta, key); | ||
149 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | 143 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); |
150 | trace_drv_set_key(local, cmd, sdata, sta, key, ret); | 144 | trace_drv_return_int(local, ret); |
151 | return ret; | 145 | return ret; |
152 | } | 146 | } |
153 | 147 | ||
@@ -162,10 +156,11 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
162 | if (sta) | 156 | if (sta) |
163 | ista = &sta->sta; | 157 | ista = &sta->sta; |
164 | 158 | ||
159 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | ||
165 | if (local->ops->update_tkip_key) | 160 | if (local->ops->update_tkip_key) |
166 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, | 161 | local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, |
167 | ista, iv32, phase1key); | 162 | ista, iv32, phase1key); |
168 | trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); | 163 | trace_drv_return_void(local); |
169 | } | 164 | } |
170 | 165 | ||
171 | static inline int drv_hw_scan(struct ieee80211_local *local, | 166 | static inline int drv_hw_scan(struct ieee80211_local *local, |
@@ -176,8 +171,9 @@ static inline int drv_hw_scan(struct ieee80211_local *local, | |||
176 | 171 | ||
177 | might_sleep(); | 172 | might_sleep(); |
178 | 173 | ||
174 | trace_drv_hw_scan(local, sdata, req); | ||
179 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); | 175 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
180 | trace_drv_hw_scan(local, sdata, req, ret); | 176 | trace_drv_return_int(local, ret); |
181 | return ret; | 177 | return ret; |
182 | } | 178 | } |
183 | 179 | ||
@@ -185,18 +181,20 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local) | |||
185 | { | 181 | { |
186 | might_sleep(); | 182 | might_sleep(); |
187 | 183 | ||
184 | trace_drv_sw_scan_start(local); | ||
188 | if (local->ops->sw_scan_start) | 185 | if (local->ops->sw_scan_start) |
189 | local->ops->sw_scan_start(&local->hw); | 186 | local->ops->sw_scan_start(&local->hw); |
190 | trace_drv_sw_scan_start(local); | 187 | trace_drv_return_void(local); |
191 | } | 188 | } |
192 | 189 | ||
193 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 190 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) |
194 | { | 191 | { |
195 | might_sleep(); | 192 | might_sleep(); |
196 | 193 | ||
194 | trace_drv_sw_scan_complete(local); | ||
197 | if (local->ops->sw_scan_complete) | 195 | if (local->ops->sw_scan_complete) |
198 | local->ops->sw_scan_complete(&local->hw); | 196 | local->ops->sw_scan_complete(&local->hw); |
199 | trace_drv_sw_scan_complete(local); | 197 | trace_drv_return_void(local); |
200 | } | 198 | } |
201 | 199 | ||
202 | static inline int drv_get_stats(struct ieee80211_local *local, | 200 | static inline int drv_get_stats(struct ieee80211_local *local, |
@@ -228,9 +226,10 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, | |||
228 | 226 | ||
229 | might_sleep(); | 227 | might_sleep(); |
230 | 228 | ||
229 | trace_drv_set_rts_threshold(local, value); | ||
231 | if (local->ops->set_rts_threshold) | 230 | if (local->ops->set_rts_threshold) |
232 | ret = local->ops->set_rts_threshold(&local->hw, value); | 231 | ret = local->ops->set_rts_threshold(&local->hw, value); |
233 | trace_drv_set_rts_threshold(local, value, ret); | 232 | trace_drv_return_int(local, ret); |
234 | return ret; | 233 | return ret; |
235 | } | 234 | } |
236 | 235 | ||
@@ -240,12 +239,13 @@ static inline int drv_set_coverage_class(struct ieee80211_local *local, | |||
240 | int ret = 0; | 239 | int ret = 0; |
241 | might_sleep(); | 240 | might_sleep(); |
242 | 241 | ||
242 | trace_drv_set_coverage_class(local, value); | ||
243 | if (local->ops->set_coverage_class) | 243 | if (local->ops->set_coverage_class) |
244 | local->ops->set_coverage_class(&local->hw, value); | 244 | local->ops->set_coverage_class(&local->hw, value); |
245 | else | 245 | else |
246 | ret = -EOPNOTSUPP; | 246 | ret = -EOPNOTSUPP; |
247 | 247 | ||
248 | trace_drv_set_coverage_class(local, value, ret); | 248 | trace_drv_return_int(local, ret); |
249 | return ret; | 249 | return ret; |
250 | } | 250 | } |
251 | 251 | ||
@@ -254,9 +254,10 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
254 | enum sta_notify_cmd cmd, | 254 | enum sta_notify_cmd cmd, |
255 | struct ieee80211_sta *sta) | 255 | struct ieee80211_sta *sta) |
256 | { | 256 | { |
257 | trace_drv_sta_notify(local, sdata, cmd, sta); | ||
257 | if (local->ops->sta_notify) | 258 | if (local->ops->sta_notify) |
258 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); | 259 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); |
259 | trace_drv_sta_notify(local, sdata, cmd, sta); | 260 | trace_drv_return_void(local); |
260 | } | 261 | } |
261 | 262 | ||
262 | static inline int drv_sta_add(struct ieee80211_local *local, | 263 | static inline int drv_sta_add(struct ieee80211_local *local, |
@@ -267,10 +268,11 @@ static inline int drv_sta_add(struct ieee80211_local *local, | |||
267 | 268 | ||
268 | might_sleep(); | 269 | might_sleep(); |
269 | 270 | ||
271 | trace_drv_sta_add(local, sdata, sta); | ||
270 | if (local->ops->sta_add) | 272 | if (local->ops->sta_add) |
271 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); | 273 | ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); |
272 | 274 | ||
273 | trace_drv_sta_add(local, sdata, sta, ret); | 275 | trace_drv_return_int(local, ret); |
274 | 276 | ||
275 | return ret; | 277 | return ret; |
276 | } | 278 | } |
@@ -281,10 +283,11 @@ static inline void drv_sta_remove(struct ieee80211_local *local, | |||
281 | { | 283 | { |
282 | might_sleep(); | 284 | might_sleep(); |
283 | 285 | ||
286 | trace_drv_sta_remove(local, sdata, sta); | ||
284 | if (local->ops->sta_remove) | 287 | if (local->ops->sta_remove) |
285 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); | 288 | local->ops->sta_remove(&local->hw, &sdata->vif, sta); |
286 | 289 | ||
287 | trace_drv_sta_remove(local, sdata, sta); | 290 | trace_drv_return_void(local); |
288 | } | 291 | } |
289 | 292 | ||
290 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 293 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
@@ -294,9 +297,10 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | |||
294 | 297 | ||
295 | might_sleep(); | 298 | might_sleep(); |
296 | 299 | ||
300 | trace_drv_conf_tx(local, queue, params); | ||
297 | if (local->ops->conf_tx) | 301 | if (local->ops->conf_tx) |
298 | ret = local->ops->conf_tx(&local->hw, queue, params); | 302 | ret = local->ops->conf_tx(&local->hw, queue, params); |
299 | trace_drv_conf_tx(local, queue, params, ret); | 303 | trace_drv_return_int(local, ret); |
300 | return ret; | 304 | return ret; |
301 | } | 305 | } |
302 | 306 | ||
@@ -306,9 +310,10 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local) | |||
306 | 310 | ||
307 | might_sleep(); | 311 | might_sleep(); |
308 | 312 | ||
313 | trace_drv_get_tsf(local); | ||
309 | if (local->ops->get_tsf) | 314 | if (local->ops->get_tsf) |
310 | ret = local->ops->get_tsf(&local->hw); | 315 | ret = local->ops->get_tsf(&local->hw); |
311 | trace_drv_get_tsf(local, ret); | 316 | trace_drv_return_u64(local, ret); |
312 | return ret; | 317 | return ret; |
313 | } | 318 | } |
314 | 319 | ||
@@ -316,18 +321,20 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | |||
316 | { | 321 | { |
317 | might_sleep(); | 322 | might_sleep(); |
318 | 323 | ||
324 | trace_drv_set_tsf(local, tsf); | ||
319 | if (local->ops->set_tsf) | 325 | if (local->ops->set_tsf) |
320 | local->ops->set_tsf(&local->hw, tsf); | 326 | local->ops->set_tsf(&local->hw, tsf); |
321 | trace_drv_set_tsf(local, tsf); | 327 | trace_drv_return_void(local); |
322 | } | 328 | } |
323 | 329 | ||
324 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 330 | static inline void drv_reset_tsf(struct ieee80211_local *local) |
325 | { | 331 | { |
326 | might_sleep(); | 332 | might_sleep(); |
327 | 333 | ||
334 | trace_drv_reset_tsf(local); | ||
328 | if (local->ops->reset_tsf) | 335 | if (local->ops->reset_tsf) |
329 | local->ops->reset_tsf(&local->hw); | 336 | local->ops->reset_tsf(&local->hw); |
330 | trace_drv_reset_tsf(local); | 337 | trace_drv_return_void(local); |
331 | } | 338 | } |
332 | 339 | ||
333 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 340 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
@@ -336,9 +343,10 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) | |||
336 | 343 | ||
337 | might_sleep(); | 344 | might_sleep(); |
338 | 345 | ||
346 | trace_drv_tx_last_beacon(local); | ||
339 | if (local->ops->tx_last_beacon) | 347 | if (local->ops->tx_last_beacon) |
340 | ret = local->ops->tx_last_beacon(&local->hw); | 348 | ret = local->ops->tx_last_beacon(&local->hw); |
341 | trace_drv_tx_last_beacon(local, ret); | 349 | trace_drv_return_int(local, ret); |
342 | return ret; | 350 | return ret; |
343 | } | 351 | } |
344 | 352 | ||
@@ -349,10 +357,17 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
349 | u16 *ssn) | 357 | u16 *ssn) |
350 | { | 358 | { |
351 | int ret = -EOPNOTSUPP; | 359 | int ret = -EOPNOTSUPP; |
360 | |||
361 | might_sleep(); | ||
362 | |||
363 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn); | ||
364 | |||
352 | if (local->ops->ampdu_action) | 365 | if (local->ops->ampdu_action) |
353 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, | 366 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, |
354 | sta, tid, ssn); | 367 | sta, tid, ssn); |
355 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); | 368 | |
369 | trace_drv_return_int(local, ret); | ||
370 | |||
356 | return ret; | 371 | return ret; |
357 | } | 372 | } |
358 | 373 | ||
@@ -381,6 +396,7 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop) | |||
381 | trace_drv_flush(local, drop); | 396 | trace_drv_flush(local, drop); |
382 | if (local->ops->flush) | 397 | if (local->ops->flush) |
383 | local->ops->flush(&local->hw, drop); | 398 | local->ops->flush(&local->hw, drop); |
399 | trace_drv_return_void(local); | ||
384 | } | 400 | } |
385 | 401 | ||
386 | static inline void drv_channel_switch(struct ieee80211_local *local, | 402 | static inline void drv_channel_switch(struct ieee80211_local *local, |
@@ -388,9 +404,9 @@ static inline void drv_channel_switch(struct ieee80211_local *local, | |||
388 | { | 404 | { |
389 | might_sleep(); | 405 | might_sleep(); |
390 | 406 | ||
391 | local->ops->channel_switch(&local->hw, ch_switch); | ||
392 | |||
393 | trace_drv_channel_switch(local, ch_switch); | 407 | trace_drv_channel_switch(local, ch_switch); |
408 | local->ops->channel_switch(&local->hw, ch_switch); | ||
409 | trace_drv_return_void(local); | ||
394 | } | 410 | } |
395 | 411 | ||
396 | #endif /* __MAC80211_DRIVER_OPS */ | 412 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 6b90630151ab..8da31caff931 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -36,20 +36,58 @@ static inline void trace_ ## name(proto) {} | |||
36 | * Tracing for driver callbacks. | 36 | * Tracing for driver callbacks. |
37 | */ | 37 | */ |
38 | 38 | ||
39 | TRACE_EVENT(drv_start, | 39 | TRACE_EVENT(drv_return_void, |
40 | TP_PROTO(struct ieee80211_local *local, int ret), | 40 | TP_PROTO(struct ieee80211_local *local), |
41 | TP_ARGS(local), | ||
42 | TP_STRUCT__entry( | ||
43 | LOCAL_ENTRY | ||
44 | ), | ||
45 | TP_fast_assign( | ||
46 | LOCAL_ASSIGN; | ||
47 | ), | ||
48 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) | ||
49 | ); | ||
41 | 50 | ||
51 | TRACE_EVENT(drv_return_int, | ||
52 | TP_PROTO(struct ieee80211_local *local, int ret), | ||
42 | TP_ARGS(local, ret), | 53 | TP_ARGS(local, ret), |
43 | |||
44 | TP_STRUCT__entry( | 54 | TP_STRUCT__entry( |
45 | LOCAL_ENTRY | 55 | LOCAL_ENTRY |
46 | __field(int, ret) | 56 | __field(int, ret) |
47 | ), | 57 | ), |
58 | TP_fast_assign( | ||
59 | LOCAL_ASSIGN; | ||
60 | __entry->ret = ret; | ||
61 | ), | ||
62 | TP_printk(LOCAL_PR_FMT " - %d", LOCAL_PR_ARG, __entry->ret) | ||
63 | ); | ||
48 | 64 | ||
65 | TRACE_EVENT(drv_return_u64, | ||
66 | TP_PROTO(struct ieee80211_local *local, u64 ret), | ||
67 | TP_ARGS(local, ret), | ||
68 | TP_STRUCT__entry( | ||
69 | LOCAL_ENTRY | ||
70 | __field(u64, ret) | ||
71 | ), | ||
49 | TP_fast_assign( | 72 | TP_fast_assign( |
50 | LOCAL_ASSIGN; | 73 | LOCAL_ASSIGN; |
51 | __entry->ret = ret; | 74 | __entry->ret = ret; |
52 | ), | 75 | ), |
76 | TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret) | ||
77 | ); | ||
78 | |||
79 | TRACE_EVENT(drv_start, | ||
80 | TP_PROTO(struct ieee80211_local *local), | ||
81 | |||
82 | TP_ARGS(local), | ||
83 | |||
84 | TP_STRUCT__entry( | ||
85 | LOCAL_ENTRY | ||
86 | ), | ||
87 | |||
88 | TP_fast_assign( | ||
89 | LOCAL_ASSIGN; | ||
90 | ), | ||
53 | 91 | ||
54 | TP_printk( | 92 | TP_printk( |
55 | LOCAL_PR_FMT, LOCAL_PR_ARG | 93 | LOCAL_PR_FMT, LOCAL_PR_ARG |
@@ -76,28 +114,25 @@ TRACE_EVENT(drv_stop, | |||
76 | 114 | ||
77 | TRACE_EVENT(drv_add_interface, | 115 | TRACE_EVENT(drv_add_interface, |
78 | TP_PROTO(struct ieee80211_local *local, | 116 | TP_PROTO(struct ieee80211_local *local, |
79 | struct ieee80211_sub_if_data *sdata, | 117 | struct ieee80211_sub_if_data *sdata), |
80 | int ret), | ||
81 | 118 | ||
82 | TP_ARGS(local, sdata, ret), | 119 | TP_ARGS(local, sdata), |
83 | 120 | ||
84 | TP_STRUCT__entry( | 121 | TP_STRUCT__entry( |
85 | LOCAL_ENTRY | 122 | LOCAL_ENTRY |
86 | VIF_ENTRY | 123 | VIF_ENTRY |
87 | __array(char, addr, 6) | 124 | __array(char, addr, 6) |
88 | __field(int, ret) | ||
89 | ), | 125 | ), |
90 | 126 | ||
91 | TP_fast_assign( | 127 | TP_fast_assign( |
92 | LOCAL_ASSIGN; | 128 | LOCAL_ASSIGN; |
93 | VIF_ASSIGN; | 129 | VIF_ASSIGN; |
94 | memcpy(__entry->addr, sdata->vif.addr, 6); | 130 | memcpy(__entry->addr, sdata->vif.addr, 6); |
95 | __entry->ret = ret; | ||
96 | ), | 131 | ), |
97 | 132 | ||
98 | TP_printk( | 133 | TP_printk( |
99 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM ret:%d", | 134 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", |
100 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr, __entry->ret | 135 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr |
101 | ) | 136 | ) |
102 | ); | 137 | ); |
103 | 138 | ||
@@ -126,15 +161,13 @@ TRACE_EVENT(drv_remove_interface, | |||
126 | 161 | ||
127 | TRACE_EVENT(drv_config, | 162 | TRACE_EVENT(drv_config, |
128 | TP_PROTO(struct ieee80211_local *local, | 163 | TP_PROTO(struct ieee80211_local *local, |
129 | u32 changed, | 164 | u32 changed), |
130 | int ret), | ||
131 | 165 | ||
132 | TP_ARGS(local, changed, ret), | 166 | TP_ARGS(local, changed), |
133 | 167 | ||
134 | TP_STRUCT__entry( | 168 | TP_STRUCT__entry( |
135 | LOCAL_ENTRY | 169 | LOCAL_ENTRY |
136 | __field(u32, changed) | 170 | __field(u32, changed) |
137 | __field(int, ret) | ||
138 | __field(u32, flags) | 171 | __field(u32, flags) |
139 | __field(int, power_level) | 172 | __field(int, power_level) |
140 | __field(int, dynamic_ps_timeout) | 173 | __field(int, dynamic_ps_timeout) |
@@ -150,7 +183,6 @@ TRACE_EVENT(drv_config, | |||
150 | TP_fast_assign( | 183 | TP_fast_assign( |
151 | LOCAL_ASSIGN; | 184 | LOCAL_ASSIGN; |
152 | __entry->changed = changed; | 185 | __entry->changed = changed; |
153 | __entry->ret = ret; | ||
154 | __entry->flags = local->hw.conf.flags; | 186 | __entry->flags = local->hw.conf.flags; |
155 | __entry->power_level = local->hw.conf.power_level; | 187 | __entry->power_level = local->hw.conf.power_level; |
156 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; | 188 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; |
@@ -164,8 +196,8 @@ TRACE_EVENT(drv_config, | |||
164 | ), | 196 | ), |
165 | 197 | ||
166 | TP_printk( | 198 | TP_printk( |
167 | LOCAL_PR_FMT " ch:%#x freq:%d ret:%d", | 199 | LOCAL_PR_FMT " ch:%#x freq:%d", |
168 | LOCAL_PR_ARG, __entry->changed, __entry->center_freq, __entry->ret | 200 | LOCAL_PR_ARG, __entry->changed, __entry->center_freq |
169 | ) | 201 | ) |
170 | ); | 202 | ); |
171 | 203 | ||
@@ -219,52 +251,24 @@ TRACE_EVENT(drv_bss_info_changed, | |||
219 | ) | 251 | ) |
220 | ); | 252 | ); |
221 | 253 | ||
222 | TRACE_EVENT(drv_configure_arp_filter, | ||
223 | TP_PROTO(struct ieee80211_local *local, | ||
224 | struct ieee80211_sub_if_data *sdata, | ||
225 | struct in_ifaddr *ifa_list, int ret), | ||
226 | |||
227 | TP_ARGS(local, sdata, ifa_list, ret), | ||
228 | |||
229 | TP_STRUCT__entry( | ||
230 | LOCAL_ENTRY | ||
231 | VIF_ENTRY | ||
232 | __field(int, ret) | ||
233 | ), | ||
234 | |||
235 | TP_fast_assign( | ||
236 | LOCAL_ASSIGN; | ||
237 | VIF_ASSIGN; | ||
238 | __entry->ret = ret; | ||
239 | ), | ||
240 | |||
241 | TP_printk( | ||
242 | VIF_PR_FMT LOCAL_PR_FMT " ret:%d", | ||
243 | VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret | ||
244 | ) | ||
245 | ); | ||
246 | |||
247 | TRACE_EVENT(drv_prepare_multicast, | 254 | TRACE_EVENT(drv_prepare_multicast, |
248 | TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret), | 255 | TP_PROTO(struct ieee80211_local *local, int mc_count), |
249 | 256 | ||
250 | TP_ARGS(local, mc_count, ret), | 257 | TP_ARGS(local, mc_count), |
251 | 258 | ||
252 | TP_STRUCT__entry( | 259 | TP_STRUCT__entry( |
253 | LOCAL_ENTRY | 260 | LOCAL_ENTRY |
254 | __field(int, mc_count) | 261 | __field(int, mc_count) |
255 | __field(u64, ret) | ||
256 | ), | 262 | ), |
257 | 263 | ||
258 | TP_fast_assign( | 264 | TP_fast_assign( |
259 | LOCAL_ASSIGN; | 265 | LOCAL_ASSIGN; |
260 | __entry->mc_count = mc_count; | 266 | __entry->mc_count = mc_count; |
261 | __entry->ret = ret; | ||
262 | ), | 267 | ), |
263 | 268 | ||
264 | TP_printk( | 269 | TP_printk( |
265 | LOCAL_PR_FMT " prepare mc (%d): %llx", | 270 | LOCAL_PR_FMT " prepare mc (%d)", |
266 | LOCAL_PR_ARG, __entry->mc_count, | 271 | LOCAL_PR_ARG, __entry->mc_count |
267 | (unsigned long long) __entry->ret | ||
268 | ) | 272 | ) |
269 | ); | 273 | ); |
270 | 274 | ||
@@ -298,27 +302,25 @@ TRACE_EVENT(drv_configure_filter, | |||
298 | 302 | ||
299 | TRACE_EVENT(drv_set_tim, | 303 | TRACE_EVENT(drv_set_tim, |
300 | TP_PROTO(struct ieee80211_local *local, | 304 | TP_PROTO(struct ieee80211_local *local, |
301 | struct ieee80211_sta *sta, bool set, int ret), | 305 | struct ieee80211_sta *sta, bool set), |
302 | 306 | ||
303 | TP_ARGS(local, sta, set, ret), | 307 | TP_ARGS(local, sta, set), |
304 | 308 | ||
305 | TP_STRUCT__entry( | 309 | TP_STRUCT__entry( |
306 | LOCAL_ENTRY | 310 | LOCAL_ENTRY |
307 | STA_ENTRY | 311 | STA_ENTRY |
308 | __field(bool, set) | 312 | __field(bool, set) |
309 | __field(int, ret) | ||
310 | ), | 313 | ), |
311 | 314 | ||
312 | TP_fast_assign( | 315 | TP_fast_assign( |
313 | LOCAL_ASSIGN; | 316 | LOCAL_ASSIGN; |
314 | STA_ASSIGN; | 317 | STA_ASSIGN; |
315 | __entry->set = set; | 318 | __entry->set = set; |
316 | __entry->ret = ret; | ||
317 | ), | 319 | ), |
318 | 320 | ||
319 | TP_printk( | 321 | TP_printk( |
320 | LOCAL_PR_FMT STA_PR_FMT " set:%d ret:%d", | 322 | LOCAL_PR_FMT STA_PR_FMT " set:%d", |
321 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set, __entry->ret | 323 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set |
322 | ) | 324 | ) |
323 | ); | 325 | ); |
324 | 326 | ||
@@ -326,9 +328,9 @@ TRACE_EVENT(drv_set_key, | |||
326 | TP_PROTO(struct ieee80211_local *local, | 328 | TP_PROTO(struct ieee80211_local *local, |
327 | enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, | 329 | enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, |
328 | struct ieee80211_sta *sta, | 330 | struct ieee80211_sta *sta, |
329 | struct ieee80211_key_conf *key, int ret), | 331 | struct ieee80211_key_conf *key), |
330 | 332 | ||
331 | TP_ARGS(local, cmd, sdata, sta, key, ret), | 333 | TP_ARGS(local, cmd, sdata, sta, key), |
332 | 334 | ||
333 | TP_STRUCT__entry( | 335 | TP_STRUCT__entry( |
334 | LOCAL_ENTRY | 336 | LOCAL_ENTRY |
@@ -338,7 +340,6 @@ TRACE_EVENT(drv_set_key, | |||
338 | __field(u8, hw_key_idx) | 340 | __field(u8, hw_key_idx) |
339 | __field(u8, flags) | 341 | __field(u8, flags) |
340 | __field(s8, keyidx) | 342 | __field(s8, keyidx) |
341 | __field(int, ret) | ||
342 | ), | 343 | ), |
343 | 344 | ||
344 | TP_fast_assign( | 345 | TP_fast_assign( |
@@ -349,12 +350,11 @@ TRACE_EVENT(drv_set_key, | |||
349 | __entry->flags = key->flags; | 350 | __entry->flags = key->flags; |
350 | __entry->keyidx = key->keyidx; | 351 | __entry->keyidx = key->keyidx; |
351 | __entry->hw_key_idx = key->hw_key_idx; | 352 | __entry->hw_key_idx = key->hw_key_idx; |
352 | __entry->ret = ret; | ||
353 | ), | 353 | ), |
354 | 354 | ||
355 | TP_printk( | 355 | TP_printk( |
356 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", | 356 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, |
357 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret | 357 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG |
358 | ) | 358 | ) |
359 | ); | 359 | ); |
360 | 360 | ||
@@ -389,25 +389,23 @@ TRACE_EVENT(drv_update_tkip_key, | |||
389 | TRACE_EVENT(drv_hw_scan, | 389 | TRACE_EVENT(drv_hw_scan, |
390 | TP_PROTO(struct ieee80211_local *local, | 390 | TP_PROTO(struct ieee80211_local *local, |
391 | struct ieee80211_sub_if_data *sdata, | 391 | struct ieee80211_sub_if_data *sdata, |
392 | struct cfg80211_scan_request *req, int ret), | 392 | struct cfg80211_scan_request *req), |
393 | 393 | ||
394 | TP_ARGS(local, sdata, req, ret), | 394 | TP_ARGS(local, sdata, req), |
395 | 395 | ||
396 | TP_STRUCT__entry( | 396 | TP_STRUCT__entry( |
397 | LOCAL_ENTRY | 397 | LOCAL_ENTRY |
398 | VIF_ENTRY | 398 | VIF_ENTRY |
399 | __field(int, ret) | ||
400 | ), | 399 | ), |
401 | 400 | ||
402 | TP_fast_assign( | 401 | TP_fast_assign( |
403 | LOCAL_ASSIGN; | 402 | LOCAL_ASSIGN; |
404 | VIF_ASSIGN; | 403 | VIF_ASSIGN; |
405 | __entry->ret = ret; | ||
406 | ), | 404 | ), |
407 | 405 | ||
408 | TP_printk( | 406 | TP_printk( |
409 | LOCAL_PR_FMT VIF_PR_FMT " ret:%d", | 407 | LOCAL_PR_FMT VIF_PR_FMT, |
410 | LOCAL_PR_ARG,VIF_PR_ARG, __entry->ret | 408 | LOCAL_PR_ARG,VIF_PR_ARG |
411 | ) | 409 | ) |
412 | ); | 410 | ); |
413 | 411 | ||
@@ -504,48 +502,44 @@ TRACE_EVENT(drv_get_tkip_seq, | |||
504 | ); | 502 | ); |
505 | 503 | ||
506 | TRACE_EVENT(drv_set_rts_threshold, | 504 | TRACE_EVENT(drv_set_rts_threshold, |
507 | TP_PROTO(struct ieee80211_local *local, u32 value, int ret), | 505 | TP_PROTO(struct ieee80211_local *local, u32 value), |
508 | 506 | ||
509 | TP_ARGS(local, value, ret), | 507 | TP_ARGS(local, value), |
510 | 508 | ||
511 | TP_STRUCT__entry( | 509 | TP_STRUCT__entry( |
512 | LOCAL_ENTRY | 510 | LOCAL_ENTRY |
513 | __field(u32, value) | 511 | __field(u32, value) |
514 | __field(int, ret) | ||
515 | ), | 512 | ), |
516 | 513 | ||
517 | TP_fast_assign( | 514 | TP_fast_assign( |
518 | LOCAL_ASSIGN; | 515 | LOCAL_ASSIGN; |
519 | __entry->ret = ret; | ||
520 | __entry->value = value; | 516 | __entry->value = value; |
521 | ), | 517 | ), |
522 | 518 | ||
523 | TP_printk( | 519 | TP_printk( |
524 | LOCAL_PR_FMT " value:%d ret:%d", | 520 | LOCAL_PR_FMT " value:%d", |
525 | LOCAL_PR_ARG, __entry->value, __entry->ret | 521 | LOCAL_PR_ARG, __entry->value |
526 | ) | 522 | ) |
527 | ); | 523 | ); |
528 | 524 | ||
529 | TRACE_EVENT(drv_set_coverage_class, | 525 | TRACE_EVENT(drv_set_coverage_class, |
530 | TP_PROTO(struct ieee80211_local *local, u8 value, int ret), | 526 | TP_PROTO(struct ieee80211_local *local, u8 value), |
531 | 527 | ||
532 | TP_ARGS(local, value, ret), | 528 | TP_ARGS(local, value), |
533 | 529 | ||
534 | TP_STRUCT__entry( | 530 | TP_STRUCT__entry( |
535 | LOCAL_ENTRY | 531 | LOCAL_ENTRY |
536 | __field(u8, value) | 532 | __field(u8, value) |
537 | __field(int, ret) | ||
538 | ), | 533 | ), |
539 | 534 | ||
540 | TP_fast_assign( | 535 | TP_fast_assign( |
541 | LOCAL_ASSIGN; | 536 | LOCAL_ASSIGN; |
542 | __entry->ret = ret; | ||
543 | __entry->value = value; | 537 | __entry->value = value; |
544 | ), | 538 | ), |
545 | 539 | ||
546 | TP_printk( | 540 | TP_printk( |
547 | LOCAL_PR_FMT " value:%d ret:%d", | 541 | LOCAL_PR_FMT " value:%d", |
548 | LOCAL_PR_ARG, __entry->value, __entry->ret | 542 | LOCAL_PR_ARG, __entry->value |
549 | ) | 543 | ) |
550 | ); | 544 | ); |
551 | 545 | ||
@@ -580,27 +574,25 @@ TRACE_EVENT(drv_sta_notify, | |||
580 | TRACE_EVENT(drv_sta_add, | 574 | TRACE_EVENT(drv_sta_add, |
581 | TP_PROTO(struct ieee80211_local *local, | 575 | TP_PROTO(struct ieee80211_local *local, |
582 | struct ieee80211_sub_if_data *sdata, | 576 | struct ieee80211_sub_if_data *sdata, |
583 | struct ieee80211_sta *sta, int ret), | 577 | struct ieee80211_sta *sta), |
584 | 578 | ||
585 | TP_ARGS(local, sdata, sta, ret), | 579 | TP_ARGS(local, sdata, sta), |
586 | 580 | ||
587 | TP_STRUCT__entry( | 581 | TP_STRUCT__entry( |
588 | LOCAL_ENTRY | 582 | LOCAL_ENTRY |
589 | VIF_ENTRY | 583 | VIF_ENTRY |
590 | STA_ENTRY | 584 | STA_ENTRY |
591 | __field(int, ret) | ||
592 | ), | 585 | ), |
593 | 586 | ||
594 | TP_fast_assign( | 587 | TP_fast_assign( |
595 | LOCAL_ASSIGN; | 588 | LOCAL_ASSIGN; |
596 | VIF_ASSIGN; | 589 | VIF_ASSIGN; |
597 | STA_ASSIGN; | 590 | STA_ASSIGN; |
598 | __entry->ret = ret; | ||
599 | ), | 591 | ), |
600 | 592 | ||
601 | TP_printk( | 593 | TP_printk( |
602 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", | 594 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, |
603 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret | 595 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG |
604 | ) | 596 | ) |
605 | ); | 597 | ); |
606 | 598 | ||
@@ -631,10 +623,9 @@ TRACE_EVENT(drv_sta_remove, | |||
631 | 623 | ||
632 | TRACE_EVENT(drv_conf_tx, | 624 | TRACE_EVENT(drv_conf_tx, |
633 | TP_PROTO(struct ieee80211_local *local, u16 queue, | 625 | TP_PROTO(struct ieee80211_local *local, u16 queue, |
634 | const struct ieee80211_tx_queue_params *params, | 626 | const struct ieee80211_tx_queue_params *params), |
635 | int ret), | ||
636 | 627 | ||
637 | TP_ARGS(local, queue, params, ret), | 628 | TP_ARGS(local, queue, params), |
638 | 629 | ||
639 | TP_STRUCT__entry( | 630 | TP_STRUCT__entry( |
640 | LOCAL_ENTRY | 631 | LOCAL_ENTRY |
@@ -643,13 +634,11 @@ TRACE_EVENT(drv_conf_tx, | |||
643 | __field(u16, cw_min) | 634 | __field(u16, cw_min) |
644 | __field(u16, cw_max) | 635 | __field(u16, cw_max) |
645 | __field(u8, aifs) | 636 | __field(u8, aifs) |
646 | __field(int, ret) | ||
647 | ), | 637 | ), |
648 | 638 | ||
649 | TP_fast_assign( | 639 | TP_fast_assign( |
650 | LOCAL_ASSIGN; | 640 | LOCAL_ASSIGN; |
651 | __entry->queue = queue; | 641 | __entry->queue = queue; |
652 | __entry->ret = ret; | ||
653 | __entry->txop = params->txop; | 642 | __entry->txop = params->txop; |
654 | __entry->cw_max = params->cw_max; | 643 | __entry->cw_max = params->cw_max; |
655 | __entry->cw_min = params->cw_min; | 644 | __entry->cw_min = params->cw_min; |
@@ -657,29 +646,27 @@ TRACE_EVENT(drv_conf_tx, | |||
657 | ), | 646 | ), |
658 | 647 | ||
659 | TP_printk( | 648 | TP_printk( |
660 | LOCAL_PR_FMT " queue:%d ret:%d", | 649 | LOCAL_PR_FMT " queue:%d", |
661 | LOCAL_PR_ARG, __entry->queue, __entry->ret | 650 | LOCAL_PR_ARG, __entry->queue |
662 | ) | 651 | ) |
663 | ); | 652 | ); |
664 | 653 | ||
665 | TRACE_EVENT(drv_get_tsf, | 654 | TRACE_EVENT(drv_get_tsf, |
666 | TP_PROTO(struct ieee80211_local *local, u64 ret), | 655 | TP_PROTO(struct ieee80211_local *local), |
667 | 656 | ||
668 | TP_ARGS(local, ret), | 657 | TP_ARGS(local), |
669 | 658 | ||
670 | TP_STRUCT__entry( | 659 | TP_STRUCT__entry( |
671 | LOCAL_ENTRY | 660 | LOCAL_ENTRY |
672 | __field(u64, ret) | ||
673 | ), | 661 | ), |
674 | 662 | ||
675 | TP_fast_assign( | 663 | TP_fast_assign( |
676 | LOCAL_ASSIGN; | 664 | LOCAL_ASSIGN; |
677 | __entry->ret = ret; | ||
678 | ), | 665 | ), |
679 | 666 | ||
680 | TP_printk( | 667 | TP_printk( |
681 | LOCAL_PR_FMT " ret:%llu", | 668 | LOCAL_PR_FMT, |
682 | LOCAL_PR_ARG, (unsigned long long)__entry->ret | 669 | LOCAL_PR_ARG |
683 | ) | 670 | ) |
684 | ); | 671 | ); |
685 | 672 | ||
@@ -723,23 +710,21 @@ TRACE_EVENT(drv_reset_tsf, | |||
723 | ); | 710 | ); |
724 | 711 | ||
725 | TRACE_EVENT(drv_tx_last_beacon, | 712 | TRACE_EVENT(drv_tx_last_beacon, |
726 | TP_PROTO(struct ieee80211_local *local, int ret), | 713 | TP_PROTO(struct ieee80211_local *local), |
727 | 714 | ||
728 | TP_ARGS(local, ret), | 715 | TP_ARGS(local), |
729 | 716 | ||
730 | TP_STRUCT__entry( | 717 | TP_STRUCT__entry( |
731 | LOCAL_ENTRY | 718 | LOCAL_ENTRY |
732 | __field(int, ret) | ||
733 | ), | 719 | ), |
734 | 720 | ||
735 | TP_fast_assign( | 721 | TP_fast_assign( |
736 | LOCAL_ASSIGN; | 722 | LOCAL_ASSIGN; |
737 | __entry->ret = ret; | ||
738 | ), | 723 | ), |
739 | 724 | ||
740 | TP_printk( | 725 | TP_printk( |
741 | LOCAL_PR_FMT " ret:%d", | 726 | LOCAL_PR_FMT, |
742 | LOCAL_PR_ARG, __entry->ret | 727 | LOCAL_PR_ARG |
743 | ) | 728 | ) |
744 | ); | 729 | ); |
745 | 730 | ||
@@ -748,9 +733,9 @@ TRACE_EVENT(drv_ampdu_action, | |||
748 | struct ieee80211_sub_if_data *sdata, | 733 | struct ieee80211_sub_if_data *sdata, |
749 | enum ieee80211_ampdu_mlme_action action, | 734 | enum ieee80211_ampdu_mlme_action action, |
750 | struct ieee80211_sta *sta, u16 tid, | 735 | struct ieee80211_sta *sta, u16 tid, |
751 | u16 *ssn, int ret), | 736 | u16 *ssn), |
752 | 737 | ||
753 | TP_ARGS(local, sdata, action, sta, tid, ssn, ret), | 738 | TP_ARGS(local, sdata, action, sta, tid, ssn), |
754 | 739 | ||
755 | TP_STRUCT__entry( | 740 | TP_STRUCT__entry( |
756 | LOCAL_ENTRY | 741 | LOCAL_ENTRY |
@@ -758,7 +743,6 @@ TRACE_EVENT(drv_ampdu_action, | |||
758 | __field(u32, action) | 743 | __field(u32, action) |
759 | __field(u16, tid) | 744 | __field(u16, tid) |
760 | __field(u16, ssn) | 745 | __field(u16, ssn) |
761 | __field(int, ret) | ||
762 | VIF_ENTRY | 746 | VIF_ENTRY |
763 | ), | 747 | ), |
764 | 748 | ||
@@ -766,15 +750,14 @@ TRACE_EVENT(drv_ampdu_action, | |||
766 | LOCAL_ASSIGN; | 750 | LOCAL_ASSIGN; |
767 | VIF_ASSIGN; | 751 | VIF_ASSIGN; |
768 | STA_ASSIGN; | 752 | STA_ASSIGN; |
769 | __entry->ret = ret; | ||
770 | __entry->action = action; | 753 | __entry->action = action; |
771 | __entry->tid = tid; | 754 | __entry->tid = tid; |
772 | __entry->ssn = ssn ? *ssn : 0; | 755 | __entry->ssn = ssn ? *ssn : 0; |
773 | ), | 756 | ), |
774 | 757 | ||
775 | TP_printk( | 758 | TP_printk( |
776 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", | 759 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d", |
777 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | 760 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid |
778 | ) | 761 | ) |
779 | ); | 762 | ); |
780 | 763 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 2ab106a0a491..be928ef7ef51 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | 6 | * Copyright 2005-2006, Devicescape Software, Inc. |
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
9 | * Copyright 2007-2008, Intel Corporation | 9 | * Copyright 2007-2010, Intel Corporation |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
@@ -105,6 +105,8 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) | |||
105 | { | 105 | { |
106 | int i; | 106 | int i; |
107 | 107 | ||
108 | cancel_work_sync(&sta->ampdu_mlme.work); | ||
109 | |||
108 | for (i = 0; i < STA_TID_NUM; i++) { | 110 | for (i = 0; i < STA_TID_NUM; i++) { |
109 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); | 111 | __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); |
110 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 112 | __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
@@ -112,6 +114,43 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) | |||
112 | } | 114 | } |
113 | } | 115 | } |
114 | 116 | ||
117 | void ieee80211_ba_session_work(struct work_struct *work) | ||
118 | { | ||
119 | struct sta_info *sta = | ||
120 | container_of(work, struct sta_info, ampdu_mlme.work); | ||
121 | struct tid_ampdu_tx *tid_tx; | ||
122 | int tid; | ||
123 | |||
124 | /* | ||
125 | * When this flag is set, new sessions should be | ||
126 | * blocked, and existing sessions will be torn | ||
127 | * down by the code that set the flag, so this | ||
128 | * need not run. | ||
129 | */ | ||
130 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) | ||
131 | return; | ||
132 | |||
133 | mutex_lock(&sta->ampdu_mlme.mtx); | ||
134 | for (tid = 0; tid < STA_TID_NUM; tid++) { | ||
135 | if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) | ||
136 | ___ieee80211_stop_rx_ba_session( | ||
137 | sta, tid, WLAN_BACK_RECIPIENT, | ||
138 | WLAN_REASON_QSTA_TIMEOUT); | ||
139 | |||
140 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | ||
141 | if (!tid_tx) | ||
142 | continue; | ||
143 | |||
144 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) | ||
145 | ieee80211_tx_ba_session_handle_start(sta, tid); | ||
146 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | ||
147 | &tid_tx->state)) | ||
148 | ___ieee80211_stop_tx_ba_session(sta, tid, | ||
149 | WLAN_BACK_INITIATOR); | ||
150 | } | ||
151 | mutex_unlock(&sta->ampdu_mlme.mtx); | ||
152 | } | ||
153 | |||
115 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 154 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
116 | const u8 *da, u16 tid, | 155 | const u8 *da, u16 tid, |
117 | u16 initiator, u16 reason_code) | 156 | u16 initiator, u16 reason_code) |
@@ -176,13 +215,8 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
176 | 215 | ||
177 | if (initiator == WLAN_BACK_INITIATOR) | 216 | if (initiator == WLAN_BACK_INITIATOR) |
178 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); | 217 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); |
179 | else { /* WLAN_BACK_RECIPIENT */ | 218 | else |
180 | spin_lock_bh(&sta->lock); | 219 | __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT); |
181 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) | ||
182 | ___ieee80211_stop_tx_ba_session(sta, tid, | ||
183 | WLAN_BACK_RECIPIENT); | ||
184 | spin_unlock_bh(&sta->lock); | ||
185 | } | ||
186 | } | 220 | } |
187 | 221 | ||
188 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | 222 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index d7a96ced2c83..d4e84b22a66d 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -172,11 +172,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
172 | rcu_assign_pointer(ifibss->presp, skb); | 172 | rcu_assign_pointer(ifibss->presp, skb); |
173 | 173 | ||
174 | sdata->vif.bss_conf.beacon_int = beacon_int; | 174 | sdata->vif.bss_conf.beacon_int = beacon_int; |
175 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
175 | bss_change = BSS_CHANGED_BEACON_INT; | 176 | bss_change = BSS_CHANGED_BEACON_INT; |
176 | bss_change |= ieee80211_reset_erp_info(sdata); | 177 | bss_change |= ieee80211_reset_erp_info(sdata); |
177 | bss_change |= BSS_CHANGED_BSSID; | 178 | bss_change |= BSS_CHANGED_BSSID; |
178 | bss_change |= BSS_CHANGED_BEACON; | 179 | bss_change |= BSS_CHANGED_BEACON; |
179 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 180 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
181 | bss_change |= BSS_CHANGED_BASIC_RATES; | ||
180 | bss_change |= BSS_CHANGED_IBSS; | 182 | bss_change |= BSS_CHANGED_IBSS; |
181 | sdata->vif.bss_conf.ibss_joined = true; | 183 | sdata->vif.bss_conf.ibss_joined = true; |
182 | ieee80211_bss_info_change_notify(sdata, bss_change); | 184 | ieee80211_bss_info_change_notify(sdata, bss_change); |
@@ -529,7 +531,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
529 | sdata->drop_unencrypted = 0; | 531 | sdata->drop_unencrypted = 0; |
530 | 532 | ||
531 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, | 533 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
532 | ifibss->channel, 3, /* first two are basic */ | 534 | ifibss->channel, ifibss->basic_rates, |
533 | capability, 0); | 535 | capability, 0); |
534 | } | 536 | } |
535 | 537 | ||
@@ -727,8 +729,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
727 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); | 729 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); |
728 | } | 730 | } |
729 | 731 | ||
730 | static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 732 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
731 | struct sk_buff *skb) | 733 | struct sk_buff *skb) |
732 | { | 734 | { |
733 | struct ieee80211_rx_status *rx_status; | 735 | struct ieee80211_rx_status *rx_status; |
734 | struct ieee80211_mgmt *mgmt; | 736 | struct ieee80211_mgmt *mgmt; |
@@ -754,33 +756,11 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
754 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); | 756 | ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); |
755 | break; | 757 | break; |
756 | } | 758 | } |
757 | |||
758 | kfree_skb(skb); | ||
759 | } | 759 | } |
760 | 760 | ||
761 | static void ieee80211_ibss_work(struct work_struct *work) | 761 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) |
762 | { | 762 | { |
763 | struct ieee80211_sub_if_data *sdata = | 763 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
764 | container_of(work, struct ieee80211_sub_if_data, u.ibss.work); | ||
765 | struct ieee80211_local *local = sdata->local; | ||
766 | struct ieee80211_if_ibss *ifibss; | ||
767 | struct sk_buff *skb; | ||
768 | |||
769 | if (WARN_ON(local->suspended)) | ||
770 | return; | ||
771 | |||
772 | if (!ieee80211_sdata_running(sdata)) | ||
773 | return; | ||
774 | |||
775 | if (local->scanning) | ||
776 | return; | ||
777 | |||
778 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC)) | ||
779 | return; | ||
780 | ifibss = &sdata->u.ibss; | ||
781 | |||
782 | while ((skb = skb_dequeue(&ifibss->skb_queue))) | ||
783 | ieee80211_ibss_rx_queued_mgmt(sdata, skb); | ||
784 | 764 | ||
785 | if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request)) | 765 | if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request)) |
786 | return; | 766 | return; |
@@ -804,7 +784,7 @@ static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata) | |||
804 | struct ieee80211_local *local = sdata->local; | 784 | struct ieee80211_local *local = sdata->local; |
805 | 785 | ||
806 | set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); | 786 | set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); |
807 | ieee80211_queue_work(&local->hw, &ifibss->work); | 787 | ieee80211_queue_work(&local->hw, &sdata->work); |
808 | } | 788 | } |
809 | 789 | ||
810 | static void ieee80211_ibss_timer(unsigned long data) | 790 | static void ieee80211_ibss_timer(unsigned long data) |
@@ -827,7 +807,6 @@ void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) | |||
827 | { | 807 | { |
828 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 808 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
829 | 809 | ||
830 | cancel_work_sync(&ifibss->work); | ||
831 | if (del_timer_sync(&ifibss->timer)) | 810 | if (del_timer_sync(&ifibss->timer)) |
832 | ifibss->timer_running = true; | 811 | ifibss->timer_running = true; |
833 | } | 812 | } |
@@ -847,10 +826,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
847 | { | 826 | { |
848 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 827 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
849 | 828 | ||
850 | INIT_WORK(&ifibss->work, ieee80211_ibss_work); | ||
851 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, | 829 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, |
852 | (unsigned long) sdata); | 830 | (unsigned long) sdata); |
853 | skb_queue_head_init(&ifibss->skb_queue); | ||
854 | } | 831 | } |
855 | 832 | ||
856 | /* scan finished notification */ | 833 | /* scan finished notification */ |
@@ -872,32 +849,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
872 | mutex_unlock(&local->iflist_mtx); | 849 | mutex_unlock(&local->iflist_mtx); |
873 | } | 850 | } |
874 | 851 | ||
875 | ieee80211_rx_result | ||
876 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
877 | { | ||
878 | struct ieee80211_local *local = sdata->local; | ||
879 | struct ieee80211_mgmt *mgmt; | ||
880 | u16 fc; | ||
881 | |||
882 | if (skb->len < 24) | ||
883 | return RX_DROP_MONITOR; | ||
884 | |||
885 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
886 | fc = le16_to_cpu(mgmt->frame_control); | ||
887 | |||
888 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
889 | case IEEE80211_STYPE_PROBE_RESP: | ||
890 | case IEEE80211_STYPE_BEACON: | ||
891 | case IEEE80211_STYPE_PROBE_REQ: | ||
892 | case IEEE80211_STYPE_AUTH: | ||
893 | skb_queue_tail(&sdata->u.ibss.skb_queue, skb); | ||
894 | ieee80211_queue_work(&local->hw, &sdata->u.ibss.work); | ||
895 | return RX_QUEUED; | ||
896 | } | ||
897 | |||
898 | return RX_DROP_MONITOR; | ||
899 | } | ||
900 | |||
901 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 852 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
902 | struct cfg80211_ibss_params *params) | 853 | struct cfg80211_ibss_params *params) |
903 | { | 854 | { |
@@ -910,6 +861,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
910 | sdata->u.ibss.fixed_bssid = false; | 861 | sdata->u.ibss.fixed_bssid = false; |
911 | 862 | ||
912 | sdata->u.ibss.privacy = params->privacy; | 863 | sdata->u.ibss.privacy = params->privacy; |
864 | sdata->u.ibss.basic_rates = params->basic_rates; | ||
913 | 865 | ||
914 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 866 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
915 | 867 | ||
@@ -957,7 +909,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
957 | ieee80211_recalc_idle(sdata->local); | 909 | ieee80211_recalc_idle(sdata->local); |
958 | 910 | ||
959 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 911 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
960 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work); | 912 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
961 | 913 | ||
962 | return 0; | 914 | return 0; |
963 | } | 915 | } |
@@ -965,10 +917,35 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
965 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | 917 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) |
966 | { | 918 | { |
967 | struct sk_buff *skb; | 919 | struct sk_buff *skb; |
920 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
921 | struct ieee80211_local *local = sdata->local; | ||
922 | struct cfg80211_bss *cbss; | ||
923 | u16 capability; | ||
924 | int active_ibss = 0; | ||
925 | |||
926 | active_ibss = ieee80211_sta_active_ibss(sdata); | ||
927 | |||
928 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
929 | capability = WLAN_CAPABILITY_IBSS; | ||
930 | |||
931 | if (ifibss->privacy) | ||
932 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
933 | |||
934 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel, | ||
935 | ifibss->bssid, ifibss->ssid, | ||
936 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
937 | WLAN_CAPABILITY_PRIVACY, | ||
938 | capability); | ||
939 | |||
940 | if (cbss) { | ||
941 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
942 | cfg80211_put_bss(cbss); | ||
943 | } | ||
944 | } | ||
968 | 945 | ||
969 | del_timer_sync(&sdata->u.ibss.timer); | 946 | del_timer_sync(&sdata->u.ibss.timer); |
970 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 947 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
971 | cancel_work_sync(&sdata->u.ibss.work); | 948 | cancel_work_sync(&sdata->work); |
972 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 949 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); |
973 | 950 | ||
974 | sta_info_flush(sdata->local, sdata); | 951 | sta_info_flush(sdata->local, sdata); |
@@ -983,7 +960,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
983 | synchronize_rcu(); | 960 | synchronize_rcu(); |
984 | kfree_skb(skb); | 961 | kfree_skb(skb); |
985 | 962 | ||
986 | skb_queue_purge(&sdata->u.ibss.skb_queue); | 963 | skb_queue_purge(&sdata->skb_queue); |
987 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); | 964 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); |
988 | sdata->u.ibss.ssid_len = 0; | 965 | sdata->u.ibss.ssid_len = 0; |
989 | 966 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1e779e833473..6f905f153ed7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -325,7 +325,6 @@ struct ieee80211_if_managed { | |||
325 | struct timer_list conn_mon_timer; | 325 | struct timer_list conn_mon_timer; |
326 | struct timer_list bcn_mon_timer; | 326 | struct timer_list bcn_mon_timer; |
327 | struct timer_list chswitch_timer; | 327 | struct timer_list chswitch_timer; |
328 | struct work_struct work; | ||
329 | struct work_struct monitor_work; | 328 | struct work_struct monitor_work; |
330 | struct work_struct chswitch_work; | 329 | struct work_struct chswitch_work; |
331 | struct work_struct beacon_connection_loss_work; | 330 | struct work_struct beacon_connection_loss_work; |
@@ -340,8 +339,6 @@ struct ieee80211_if_managed { | |||
340 | 339 | ||
341 | u16 aid; | 340 | u16 aid; |
342 | 341 | ||
343 | struct sk_buff_head skb_queue; | ||
344 | |||
345 | unsigned long timers_running; /* used for quiesce/restart */ | 342 | unsigned long timers_running; /* used for quiesce/restart */ |
346 | bool powersave; /* powersave requested for this iface */ | 343 | bool powersave; /* powersave requested for this iface */ |
347 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 344 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
@@ -386,13 +383,12 @@ enum ieee80211_ibss_request { | |||
386 | 383 | ||
387 | struct ieee80211_if_ibss { | 384 | struct ieee80211_if_ibss { |
388 | struct timer_list timer; | 385 | struct timer_list timer; |
389 | struct work_struct work; | ||
390 | |||
391 | struct sk_buff_head skb_queue; | ||
392 | 386 | ||
393 | unsigned long request; | 387 | unsigned long request; |
394 | unsigned long last_scan_completed; | 388 | unsigned long last_scan_completed; |
395 | 389 | ||
390 | u32 basic_rates; | ||
391 | |||
396 | bool timer_running; | 392 | bool timer_running; |
397 | 393 | ||
398 | bool fixed_bssid; | 394 | bool fixed_bssid; |
@@ -416,11 +412,9 @@ struct ieee80211_if_ibss { | |||
416 | }; | 412 | }; |
417 | 413 | ||
418 | struct ieee80211_if_mesh { | 414 | struct ieee80211_if_mesh { |
419 | struct work_struct work; | ||
420 | struct timer_list housekeeping_timer; | 415 | struct timer_list housekeeping_timer; |
421 | struct timer_list mesh_path_timer; | 416 | struct timer_list mesh_path_timer; |
422 | struct timer_list mesh_path_root_timer; | 417 | struct timer_list mesh_path_root_timer; |
423 | struct sk_buff_head skb_queue; | ||
424 | 418 | ||
425 | unsigned long timers_running; | 419 | unsigned long timers_running; |
426 | 420 | ||
@@ -517,6 +511,11 @@ struct ieee80211_sub_if_data { | |||
517 | 511 | ||
518 | u16 sequence_number; | 512 | u16 sequence_number; |
519 | 513 | ||
514 | struct work_struct work; | ||
515 | struct sk_buff_head skb_queue; | ||
516 | |||
517 | bool arp_filter_state; | ||
518 | |||
520 | /* | 519 | /* |
521 | * AP this belongs to: self in AP mode and | 520 | * AP this belongs to: self in AP mode and |
522 | * corresponding AP in VLAN mode, NULL for | 521 | * corresponding AP in VLAN mode, NULL for |
@@ -569,11 +568,15 @@ ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | |||
569 | #endif | 568 | #endif |
570 | } | 569 | } |
571 | 570 | ||
571 | enum sdata_queue_type { | ||
572 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | ||
573 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | ||
574 | IEEE80211_SDATA_QUEUE_AGG_STOP = 2, | ||
575 | }; | ||
576 | |||
572 | enum { | 577 | enum { |
573 | IEEE80211_RX_MSG = 1, | 578 | IEEE80211_RX_MSG = 1, |
574 | IEEE80211_TX_STATUS_MSG = 2, | 579 | IEEE80211_TX_STATUS_MSG = 2, |
575 | IEEE80211_DELBA_MSG = 3, | ||
576 | IEEE80211_ADDBA_MSG = 4, | ||
577 | }; | 580 | }; |
578 | 581 | ||
579 | enum queue_stop_reason { | 582 | enum queue_stop_reason { |
@@ -724,13 +727,7 @@ struct ieee80211_local { | |||
724 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; | 727 | struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; |
725 | struct tasklet_struct tx_pending_tasklet; | 728 | struct tasklet_struct tx_pending_tasklet; |
726 | 729 | ||
727 | /* | 730 | atomic_t agg_queue_stop[IEEE80211_MAX_QUEUES]; |
728 | * This lock is used to prevent concurrent A-MPDU | ||
729 | * session start/stop processing, this thus also | ||
730 | * synchronises the ->ampdu_action() callback to | ||
731 | * drivers and limits it to one at a time. | ||
732 | */ | ||
733 | spinlock_t ampdu_lock; | ||
734 | 731 | ||
735 | /* number of interfaces with corresponding IFF_ flags */ | 732 | /* number of interfaces with corresponding IFF_ flags */ |
736 | atomic_t iff_allmultis, iff_promiscs; | 733 | atomic_t iff_allmultis, iff_promiscs; |
@@ -853,6 +850,12 @@ struct ieee80211_local { | |||
853 | struct notifier_block network_latency_notifier; | 850 | struct notifier_block network_latency_notifier; |
854 | struct notifier_block ifa_notifier; | 851 | struct notifier_block ifa_notifier; |
855 | 852 | ||
853 | /* | ||
854 | * The dynamic ps timeout configured from user space via WEXT - | ||
855 | * this will override whatever chosen by mac80211 internally. | ||
856 | */ | ||
857 | int dynamic_ps_forced_timeout; | ||
858 | |||
856 | int user_power_level; /* in dBm */ | 859 | int user_power_level; /* in dBm */ |
857 | int power_constr_level; /* in dBm */ | 860 | int power_constr_level; /* in dBm */ |
858 | 861 | ||
@@ -875,9 +878,8 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | |||
875 | return netdev_priv(dev); | 878 | return netdev_priv(dev); |
876 | } | 879 | } |
877 | 880 | ||
878 | /* this struct represents 802.11n's RA/TID combination along with our vif */ | 881 | /* this struct represents 802.11n's RA/TID combination */ |
879 | struct ieee80211_ra_tid { | 882 | struct ieee80211_ra_tid { |
880 | struct ieee80211_vif *vif; | ||
881 | u8 ra[ETH_ALEN]; | 883 | u8 ra[ETH_ALEN]; |
882 | u16 tid; | 884 | u16 tid; |
883 | }; | 885 | }; |
@@ -986,13 +988,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
986 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 988 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
987 | struct cfg80211_disassoc_request *req, | 989 | struct cfg80211_disassoc_request *req, |
988 | void *cookie); | 990 | void *cookie); |
989 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
990 | struct ieee80211_channel *chan, | ||
991 | enum nl80211_channel_type channel_type, | ||
992 | bool channel_type_valid, | ||
993 | const u8 *buf, size_t len, u64 *cookie); | ||
994 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
995 | struct sk_buff *skb); | ||
996 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 991 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
997 | struct ieee80211_sub_if_data *sdata); | 992 | struct ieee80211_sub_if_data *sdata); |
998 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 993 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); |
@@ -1005,12 +1000,13 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1005 | u64 timestamp); | 1000 | u64 timestamp); |
1006 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); | 1001 | void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata); |
1007 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 1002 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
1003 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | ||
1004 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1005 | struct sk_buff *skb); | ||
1008 | 1006 | ||
1009 | /* IBSS code */ | 1007 | /* IBSS code */ |
1010 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1008 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
1011 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); | 1009 | void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); |
1012 | ieee80211_rx_result | ||
1013 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | ||
1014 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 1010 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
1015 | u8 *bssid, u8 *addr, u32 supp_rates, | 1011 | u8 *bssid, u8 *addr, u32 supp_rates, |
1016 | gfp_t gfp); | 1012 | gfp_t gfp); |
@@ -1019,6 +1015,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1019 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); | 1015 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); |
1020 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); | 1016 | void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata); |
1021 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); | 1017 | void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata); |
1018 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata); | ||
1019 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1020 | struct sk_buff *skb); | ||
1021 | |||
1022 | /* mesh code */ | ||
1023 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | ||
1024 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1025 | struct sk_buff *skb); | ||
1022 | 1026 | ||
1023 | /* scan/BSS handling */ | 1027 | /* scan/BSS handling */ |
1024 | void ieee80211_scan_work(struct work_struct *work); | 1028 | void ieee80211_scan_work(struct work_struct *work); |
@@ -1102,6 +1106,8 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1102 | enum ieee80211_smps_mode smps, const u8 *da, | 1106 | enum ieee80211_smps_mode smps, const u8 *da, |
1103 | const u8 *bssid); | 1107 | const u8 *bssid); |
1104 | 1108 | ||
1109 | void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | ||
1110 | u16 initiator, u16 reason); | ||
1105 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1111 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1106 | u16 initiator, u16 reason); | 1112 | u16 initiator, u16 reason); |
1107 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1113 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); |
@@ -1121,6 +1127,10 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
1121 | enum ieee80211_back_parties initiator); | 1127 | enum ieee80211_back_parties initiator); |
1122 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 1128 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
1123 | enum ieee80211_back_parties initiator); | 1129 | enum ieee80211_back_parties initiator); |
1130 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | ||
1131 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | ||
1132 | void ieee80211_ba_session_work(struct work_struct *work); | ||
1133 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); | ||
1124 | 1134 | ||
1125 | /* Spectrum management */ | 1135 | /* Spectrum management */ |
1126 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 1136 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 1afa9ec81fe8..910729fc18cd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -339,7 +339,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
339 | { | 339 | { |
340 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 340 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
341 | struct ieee80211_local *local = sdata->local; | 341 | struct ieee80211_local *local = sdata->local; |
342 | struct sta_info *sta; | ||
343 | unsigned long flags; | 342 | unsigned long flags; |
344 | struct sk_buff *skb, *tmp; | 343 | struct sk_buff *skb, *tmp; |
345 | u32 hw_reconf_flags = 0; | 344 | u32 hw_reconf_flags = 0; |
@@ -356,18 +355,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
356 | ieee80211_work_purge(sdata); | 355 | ieee80211_work_purge(sdata); |
357 | 356 | ||
358 | /* | 357 | /* |
359 | * Now delete all active aggregation sessions. | ||
360 | */ | ||
361 | rcu_read_lock(); | ||
362 | |||
363 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
364 | if (sta->sdata == sdata) | ||
365 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
366 | } | ||
367 | |||
368 | rcu_read_unlock(); | ||
369 | |||
370 | /* | ||
371 | * Remove all stations associated with this interface. | 358 | * Remove all stations associated with this interface. |
372 | * | 359 | * |
373 | * This must be done before calling ops->remove_interface() | 360 | * This must be done before calling ops->remove_interface() |
@@ -473,27 +460,14 @@ static int ieee80211_stop(struct net_device *dev) | |||
473 | * whether the interface is running, which, at this point, | 460 | * whether the interface is running, which, at this point, |
474 | * it no longer is. | 461 | * it no longer is. |
475 | */ | 462 | */ |
476 | cancel_work_sync(&sdata->u.mgd.work); | ||
477 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 463 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
478 | cancel_work_sync(&sdata->u.mgd.monitor_work); | 464 | cancel_work_sync(&sdata->u.mgd.monitor_work); |
479 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); | 465 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); |
480 | 466 | ||
481 | /* | ||
482 | * When we get here, the interface is marked down. | ||
483 | * Call synchronize_rcu() to wait for the RX path | ||
484 | * should it be using the interface and enqueuing | ||
485 | * frames at this very time on another CPU. | ||
486 | */ | ||
487 | synchronize_rcu(); | ||
488 | skb_queue_purge(&sdata->u.mgd.skb_queue); | ||
489 | /* fall through */ | 467 | /* fall through */ |
490 | case NL80211_IFTYPE_ADHOC: | 468 | case NL80211_IFTYPE_ADHOC: |
491 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 469 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
492 | del_timer_sync(&sdata->u.ibss.timer); | 470 | del_timer_sync(&sdata->u.ibss.timer); |
493 | cancel_work_sync(&sdata->u.ibss.work); | ||
494 | synchronize_rcu(); | ||
495 | skb_queue_purge(&sdata->u.ibss.skb_queue); | ||
496 | } | ||
497 | /* fall through */ | 471 | /* fall through */ |
498 | case NL80211_IFTYPE_MESH_POINT: | 472 | case NL80211_IFTYPE_MESH_POINT: |
499 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 473 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -508,6 +482,16 @@ static int ieee80211_stop(struct net_device *dev) | |||
508 | } | 482 | } |
509 | /* fall through */ | 483 | /* fall through */ |
510 | default: | 484 | default: |
485 | flush_work(&sdata->work); | ||
486 | /* | ||
487 | * When we get here, the interface is marked down. | ||
488 | * Call synchronize_rcu() to wait for the RX path | ||
489 | * should it be using the interface and enqueuing | ||
490 | * frames at this very time on another CPU. | ||
491 | */ | ||
492 | synchronize_rcu(); | ||
493 | skb_queue_purge(&sdata->skb_queue); | ||
494 | |||
511 | if (local->scan_sdata == sdata) | 495 | if (local->scan_sdata == sdata) |
512 | ieee80211_scan_cancel(local); | 496 | ieee80211_scan_cancel(local); |
513 | 497 | ||
@@ -717,6 +701,136 @@ static void ieee80211_if_setup(struct net_device *dev) | |||
717 | dev->destructor = free_netdev; | 701 | dev->destructor = free_netdev; |
718 | } | 702 | } |
719 | 703 | ||
704 | static void ieee80211_iface_work(struct work_struct *work) | ||
705 | { | ||
706 | struct ieee80211_sub_if_data *sdata = | ||
707 | container_of(work, struct ieee80211_sub_if_data, work); | ||
708 | struct ieee80211_local *local = sdata->local; | ||
709 | struct sk_buff *skb; | ||
710 | struct sta_info *sta; | ||
711 | struct ieee80211_ra_tid *ra_tid; | ||
712 | |||
713 | if (!ieee80211_sdata_running(sdata)) | ||
714 | return; | ||
715 | |||
716 | if (local->scanning) | ||
717 | return; | ||
718 | |||
719 | /* | ||
720 | * ieee80211_queue_work() should have picked up most cases, | ||
721 | * here we'll pick the rest. | ||
722 | */ | ||
723 | if (WARN(local->suspended, | ||
724 | "interface work scheduled while going to suspend\n")) | ||
725 | return; | ||
726 | |||
727 | /* first process frames */ | ||
728 | while ((skb = skb_dequeue(&sdata->skb_queue))) { | ||
729 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
730 | |||
731 | if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) { | ||
732 | ra_tid = (void *)&skb->cb; | ||
733 | ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra, | ||
734 | ra_tid->tid); | ||
735 | } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) { | ||
736 | ra_tid = (void *)&skb->cb; | ||
737 | ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, | ||
738 | ra_tid->tid); | ||
739 | } else if (ieee80211_is_action(mgmt->frame_control) && | ||
740 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { | ||
741 | int len = skb->len; | ||
742 | |||
743 | mutex_lock(&local->sta_mtx); | ||
744 | sta = sta_info_get(sdata, mgmt->sa); | ||
745 | if (sta) { | ||
746 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
747 | case WLAN_ACTION_ADDBA_REQ: | ||
748 | ieee80211_process_addba_request( | ||
749 | local, sta, mgmt, len); | ||
750 | break; | ||
751 | case WLAN_ACTION_ADDBA_RESP: | ||
752 | ieee80211_process_addba_resp(local, sta, | ||
753 | mgmt, len); | ||
754 | break; | ||
755 | case WLAN_ACTION_DELBA: | ||
756 | ieee80211_process_delba(sdata, sta, | ||
757 | mgmt, len); | ||
758 | break; | ||
759 | default: | ||
760 | WARN_ON(1); | ||
761 | break; | ||
762 | } | ||
763 | } | ||
764 | mutex_unlock(&local->sta_mtx); | ||
765 | } else if (ieee80211_is_data_qos(mgmt->frame_control)) { | ||
766 | struct ieee80211_hdr *hdr = (void *)mgmt; | ||
767 | /* | ||
768 | * So the frame isn't mgmt, but frame_control | ||
769 | * is at the right place anyway, of course, so | ||
770 | * the if statement is correct. | ||
771 | * | ||
772 | * Warn if we have other data frame types here, | ||
773 | * they must not get here. | ||
774 | */ | ||
775 | WARN_ON(hdr->frame_control & | ||
776 | cpu_to_le16(IEEE80211_STYPE_NULLFUNC)); | ||
777 | WARN_ON(!(hdr->seq_ctrl & | ||
778 | cpu_to_le16(IEEE80211_SCTL_FRAG))); | ||
779 | /* | ||
780 | * This was a fragment of a frame, received while | ||
781 | * a block-ack session was active. That cannot be | ||
782 | * right, so terminate the session. | ||
783 | */ | ||
784 | mutex_lock(&local->sta_mtx); | ||
785 | sta = sta_info_get(sdata, mgmt->sa); | ||
786 | if (sta) { | ||
787 | u16 tid = *ieee80211_get_qos_ctl(hdr) & | ||
788 | IEEE80211_QOS_CTL_TID_MASK; | ||
789 | |||
790 | __ieee80211_stop_rx_ba_session( | ||
791 | sta, tid, WLAN_BACK_RECIPIENT, | ||
792 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
793 | } | ||
794 | mutex_unlock(&local->sta_mtx); | ||
795 | } else switch (sdata->vif.type) { | ||
796 | case NL80211_IFTYPE_STATION: | ||
797 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | ||
798 | break; | ||
799 | case NL80211_IFTYPE_ADHOC: | ||
800 | ieee80211_ibss_rx_queued_mgmt(sdata, skb); | ||
801 | break; | ||
802 | case NL80211_IFTYPE_MESH_POINT: | ||
803 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
804 | break; | ||
805 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
806 | break; | ||
807 | default: | ||
808 | WARN(1, "frame for unexpected interface type"); | ||
809 | break; | ||
810 | } | ||
811 | |||
812 | kfree_skb(skb); | ||
813 | } | ||
814 | |||
815 | /* then other type-dependent work */ | ||
816 | switch (sdata->vif.type) { | ||
817 | case NL80211_IFTYPE_STATION: | ||
818 | ieee80211_sta_work(sdata); | ||
819 | break; | ||
820 | case NL80211_IFTYPE_ADHOC: | ||
821 | ieee80211_ibss_work(sdata); | ||
822 | break; | ||
823 | case NL80211_IFTYPE_MESH_POINT: | ||
824 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
825 | break; | ||
826 | ieee80211_mesh_work(sdata); | ||
827 | break; | ||
828 | default: | ||
829 | break; | ||
830 | } | ||
831 | } | ||
832 | |||
833 | |||
720 | /* | 834 | /* |
721 | * Helper function to initialise an interface to a specific type. | 835 | * Helper function to initialise an interface to a specific type. |
722 | */ | 836 | */ |
@@ -734,6 +848,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
734 | /* only monitor differs */ | 848 | /* only monitor differs */ |
735 | sdata->dev->type = ARPHRD_ETHER; | 849 | sdata->dev->type = ARPHRD_ETHER; |
736 | 850 | ||
851 | skb_queue_head_init(&sdata->skb_queue); | ||
852 | INIT_WORK(&sdata->work, ieee80211_iface_work); | ||
853 | |||
737 | switch (type) { | 854 | switch (type) { |
738 | case NL80211_IFTYPE_AP: | 855 | case NL80211_IFTYPE_AP: |
739 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 856 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
@@ -959,6 +1076,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
959 | sdata->wdev.wiphy = local->hw.wiphy; | 1076 | sdata->wdev.wiphy = local->hw.wiphy; |
960 | sdata->local = local; | 1077 | sdata->local = local; |
961 | sdata->dev = ndev; | 1078 | sdata->dev = ndev; |
1079 | #ifdef CONFIG_INET | ||
1080 | sdata->arp_filter_state = true; | ||
1081 | #endif | ||
962 | 1082 | ||
963 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 1083 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
964 | skb_queue_head_init(&sdata->fragments[i].skb_list); | 1084 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index d0d9001a4a6a..50d1cff23d8e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -273,7 +273,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
273 | key->conf.iv_len = CCMP_HDR_LEN; | 273 | key->conf.iv_len = CCMP_HDR_LEN; |
274 | key->conf.icv_len = CCMP_MIC_LEN; | 274 | key->conf.icv_len = CCMP_MIC_LEN; |
275 | if (seq) { | 275 | if (seq) { |
276 | for (i = 0; i < NUM_RX_DATA_QUEUES; i++) | 276 | for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++) |
277 | for (j = 0; j < CCMP_PN_LEN; j++) | 277 | for (j = 0; j < CCMP_PN_LEN; j++) |
278 | key->u.ccmp.rx_pn[i][j] = | 278 | key->u.ccmp.rx_pn[i][j] = |
279 | seq[CCMP_PN_LEN - j - 1]; | 279 | seq[CCMP_PN_LEN - j - 1]; |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 9996e3be6e63..a3849fa3fce8 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -77,7 +77,13 @@ struct ieee80211_key { | |||
77 | } tkip; | 77 | } tkip; |
78 | struct { | 78 | struct { |
79 | u8 tx_pn[6]; | 79 | u8 tx_pn[6]; |
80 | u8 rx_pn[NUM_RX_DATA_QUEUES][6]; | 80 | /* |
81 | * Last received packet number. The first | ||
82 | * NUM_RX_DATA_QUEUES counters are used with Data | ||
83 | * frames and the last counter is used with Robust | ||
84 | * Management frames. | ||
85 | */ | ||
86 | u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; | ||
81 | struct crypto_cipher *tfm; | 87 | struct crypto_cipher *tfm; |
82 | u32 replays; /* dot11RSNAStatsCCMPReplays */ | 88 | u32 replays; /* dot11RSNAStatsCCMPReplays */ |
83 | /* scratch buffers for virt_to_page() (crypto API) */ | 89 | /* scratch buffers for virt_to_page() (crypto API) */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 88b671a16a41..edf7aff93268 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
21 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
22 | #include <linux/pm_qos_params.h> | 22 | #include <linux/pm_qos_params.h> |
23 | #include <linux/inetdevice.h> | ||
23 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
24 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
25 | 26 | ||
@@ -259,7 +260,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
259 | { | 260 | { |
260 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 261 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
261 | struct sk_buff *skb; | 262 | struct sk_buff *skb; |
262 | struct ieee80211_ra_tid *ra_tid; | ||
263 | 263 | ||
264 | while ((skb = skb_dequeue(&local->skb_queue)) || | 264 | while ((skb = skb_dequeue(&local->skb_queue)) || |
265 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | 265 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { |
@@ -274,18 +274,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
274 | skb->pkt_type = 0; | 274 | skb->pkt_type = 0; |
275 | ieee80211_tx_status(local_to_hw(local), skb); | 275 | ieee80211_tx_status(local_to_hw(local), skb); |
276 | break; | 276 | break; |
277 | case IEEE80211_DELBA_MSG: | ||
278 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
279 | ieee80211_stop_tx_ba_cb(ra_tid->vif, ra_tid->ra, | ||
280 | ra_tid->tid); | ||
281 | dev_kfree_skb(skb); | ||
282 | break; | ||
283 | case IEEE80211_ADDBA_MSG: | ||
284 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
285 | ieee80211_start_tx_ba_cb(ra_tid->vif, ra_tid->ra, | ||
286 | ra_tid->tid); | ||
287 | dev_kfree_skb(skb); | ||
288 | break ; | ||
289 | default: | 277 | default: |
290 | WARN(1, "mac80211: Packet is of unknown type %d\n", | 278 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
291 | skb->pkt_type); | 279 | skb->pkt_type); |
@@ -330,23 +318,6 @@ static void ieee80211_recalc_smps_work(struct work_struct *work) | |||
330 | } | 318 | } |
331 | 319 | ||
332 | #ifdef CONFIG_INET | 320 | #ifdef CONFIG_INET |
333 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata) | ||
334 | { | ||
335 | struct in_device *idev; | ||
336 | int ret = 0; | ||
337 | |||
338 | BUG_ON(!sdata); | ||
339 | ASSERT_RTNL(); | ||
340 | |||
341 | idev = sdata->dev->ip_ptr; | ||
342 | if (!idev) | ||
343 | return 0; | ||
344 | |||
345 | ret = drv_configure_arp_filter(sdata->local, &sdata->vif, | ||
346 | idev->ifa_list); | ||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | static int ieee80211_ifa_changed(struct notifier_block *nb, | 321 | static int ieee80211_ifa_changed(struct notifier_block *nb, |
351 | unsigned long data, void *arg) | 322 | unsigned long data, void *arg) |
352 | { | 323 | { |
@@ -356,8 +327,11 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
356 | ifa_notifier); | 327 | ifa_notifier); |
357 | struct net_device *ndev = ifa->ifa_dev->dev; | 328 | struct net_device *ndev = ifa->ifa_dev->dev; |
358 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | 329 | struct wireless_dev *wdev = ndev->ieee80211_ptr; |
330 | struct in_device *idev; | ||
359 | struct ieee80211_sub_if_data *sdata; | 331 | struct ieee80211_sub_if_data *sdata; |
332 | struct ieee80211_bss_conf *bss_conf; | ||
360 | struct ieee80211_if_managed *ifmgd; | 333 | struct ieee80211_if_managed *ifmgd; |
334 | int c = 0; | ||
361 | 335 | ||
362 | if (!netif_running(ndev)) | 336 | if (!netif_running(ndev)) |
363 | return NOTIFY_DONE; | 337 | return NOTIFY_DONE; |
@@ -369,17 +343,44 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
369 | if (wdev->wiphy != local->hw.wiphy) | 343 | if (wdev->wiphy != local->hw.wiphy) |
370 | return NOTIFY_DONE; | 344 | return NOTIFY_DONE; |
371 | 345 | ||
372 | /* We are concerned about IP addresses only when associated */ | ||
373 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 346 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); |
347 | bss_conf = &sdata->vif.bss_conf; | ||
374 | 348 | ||
375 | /* ARP filtering is only supported in managed mode */ | 349 | /* ARP filtering is only supported in managed mode */ |
376 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 350 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
377 | return NOTIFY_DONE; | 351 | return NOTIFY_DONE; |
378 | 352 | ||
353 | idev = sdata->dev->ip_ptr; | ||
354 | if (!idev) | ||
355 | return NOTIFY_DONE; | ||
356 | |||
379 | ifmgd = &sdata->u.mgd; | 357 | ifmgd = &sdata->u.mgd; |
380 | mutex_lock(&ifmgd->mtx); | 358 | mutex_lock(&ifmgd->mtx); |
381 | if (ifmgd->associated) | 359 | |
382 | ieee80211_set_arp_filter(sdata); | 360 | /* Copy the addresses to the bss_conf list */ |
361 | ifa = idev->ifa_list; | ||
362 | while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) { | ||
363 | bss_conf->arp_addr_list[c] = ifa->ifa_address; | ||
364 | ifa = ifa->ifa_next; | ||
365 | c++; | ||
366 | } | ||
367 | |||
368 | /* If not all addresses fit the list, disable filtering */ | ||
369 | if (ifa) { | ||
370 | sdata->arp_filter_state = false; | ||
371 | c = 0; | ||
372 | } else { | ||
373 | sdata->arp_filter_state = true; | ||
374 | } | ||
375 | bss_conf->arp_addr_cnt = c; | ||
376 | |||
377 | /* Configure driver only if associated */ | ||
378 | if (ifmgd->associated) { | ||
379 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | ||
380 | ieee80211_bss_info_change_notify(sdata, | ||
381 | BSS_CHANGED_ARP_FILTER); | ||
382 | } | ||
383 | |||
383 | mutex_unlock(&ifmgd->mtx); | 384 | mutex_unlock(&ifmgd->mtx); |
384 | 385 | ||
385 | return NOTIFY_DONE; | 386 | return NOTIFY_DONE; |
@@ -476,8 +477,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
476 | 477 | ||
477 | sta_info_init(local); | 478 | sta_info_init(local); |
478 | 479 | ||
479 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) | 480 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
480 | skb_queue_head_init(&local->pending[i]); | 481 | skb_queue_head_init(&local->pending[i]); |
482 | atomic_set(&local->agg_queue_stop[i], 0); | ||
483 | } | ||
481 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, | 484 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, |
482 | (unsigned long)local); | 485 | (unsigned long)local); |
483 | 486 | ||
@@ -488,8 +491,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
488 | skb_queue_head_init(&local->skb_queue); | 491 | skb_queue_head_init(&local->skb_queue); |
489 | skb_queue_head_init(&local->skb_queue_unreliable); | 492 | skb_queue_head_init(&local->skb_queue_unreliable); |
490 | 493 | ||
491 | spin_lock_init(&local->ampdu_lock); | ||
492 | |||
493 | return local_to_hw(local); | 494 | return local_to_hw(local); |
494 | } | 495 | } |
495 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 496 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -629,7 +630,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
629 | 630 | ||
630 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 631 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
631 | 632 | ||
632 | local->hw.conf.dynamic_ps_forced_timeout = -1; | 633 | local->dynamic_ps_forced_timeout = -1; |
633 | 634 | ||
634 | result = sta_info_start(local); | 635 | result = sta_info_start(local); |
635 | if (result < 0) | 636 | if (result < 0) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index bde81031727a..c8a4f19ed13b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
54 | return; | 54 | return; |
55 | } | 55 | } |
56 | 56 | ||
57 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 57 | ieee80211_queue_work(&local->hw, &sdata->work); |
58 | } | 58 | } |
59 | 59 | ||
60 | /** | 60 | /** |
@@ -345,7 +345,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
345 | return; | 345 | return; |
346 | } | 346 | } |
347 | 347 | ||
348 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 348 | ieee80211_queue_work(&local->hw, &sdata->work); |
349 | } | 349 | } |
350 | 350 | ||
351 | static void ieee80211_mesh_path_root_timer(unsigned long data) | 351 | static void ieee80211_mesh_path_root_timer(unsigned long data) |
@@ -362,7 +362,7 @@ static void ieee80211_mesh_path_root_timer(unsigned long data) | |||
362 | return; | 362 | return; |
363 | } | 363 | } |
364 | 364 | ||
365 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 365 | ieee80211_queue_work(&local->hw, &sdata->work); |
366 | } | 366 | } |
367 | 367 | ||
368 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | 368 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) |
@@ -484,9 +484,6 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | |||
484 | { | 484 | { |
485 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 485 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
486 | 486 | ||
487 | /* might restart the timer but that doesn't matter */ | ||
488 | cancel_work_sync(&ifmsh->work); | ||
489 | |||
490 | /* use atomic bitops in case both timers fire at the same time */ | 487 | /* use atomic bitops in case both timers fire at the same time */ |
491 | 488 | ||
492 | if (del_timer_sync(&ifmsh->housekeeping_timer)) | 489 | if (del_timer_sync(&ifmsh->housekeeping_timer)) |
@@ -518,7 +515,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
518 | 515 | ||
519 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 516 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
520 | ieee80211_mesh_root_setup(ifmsh); | 517 | ieee80211_mesh_root_setup(ifmsh); |
521 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 518 | ieee80211_queue_work(&local->hw, &sdata->work); |
522 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 519 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
523 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 520 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
524 | BSS_CHANGED_BEACON_ENABLED | | 521 | BSS_CHANGED_BEACON_ENABLED | |
@@ -536,16 +533,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
536 | * whether the interface is running, which, at this point, | 533 | * whether the interface is running, which, at this point, |
537 | * it no longer is. | 534 | * it no longer is. |
538 | */ | 535 | */ |
539 | cancel_work_sync(&sdata->u.mesh.work); | 536 | cancel_work_sync(&sdata->work); |
540 | |||
541 | /* | ||
542 | * When we get here, the interface is marked down. | ||
543 | * Call synchronize_rcu() to wait for the RX path | ||
544 | * should it be using the interface and enqueuing | ||
545 | * frames at this very time on another CPU. | ||
546 | */ | ||
547 | rcu_barrier(); /* Wait for RX path and call_rcu()'s */ | ||
548 | skb_queue_purge(&sdata->u.mesh.skb_queue); | ||
549 | } | 537 | } |
550 | 538 | ||
551 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 539 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
@@ -608,8 +596,8 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
608 | } | 596 | } |
609 | } | 597 | } |
610 | 598 | ||
611 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 599 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
612 | struct sk_buff *skb) | 600 | struct sk_buff *skb) |
613 | { | 601 | { |
614 | struct ieee80211_rx_status *rx_status; | 602 | struct ieee80211_rx_status *rx_status; |
615 | struct ieee80211_if_mesh *ifmsh; | 603 | struct ieee80211_if_mesh *ifmsh; |
@@ -632,26 +620,11 @@ static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
632 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | 620 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); |
633 | break; | 621 | break; |
634 | } | 622 | } |
635 | |||
636 | kfree_skb(skb); | ||
637 | } | 623 | } |
638 | 624 | ||
639 | static void ieee80211_mesh_work(struct work_struct *work) | 625 | void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) |
640 | { | 626 | { |
641 | struct ieee80211_sub_if_data *sdata = | ||
642 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); | ||
643 | struct ieee80211_local *local = sdata->local; | ||
644 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 627 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
645 | struct sk_buff *skb; | ||
646 | |||
647 | if (!ieee80211_sdata_running(sdata)) | ||
648 | return; | ||
649 | |||
650 | if (local->scanning) | ||
651 | return; | ||
652 | |||
653 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | ||
654 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
655 | 628 | ||
656 | if (ifmsh->preq_queue_len && | 629 | if (ifmsh->preq_queue_len && |
657 | time_after(jiffies, | 630 | time_after(jiffies, |
@@ -678,7 +651,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | |||
678 | rcu_read_lock(); | 651 | rcu_read_lock(); |
679 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 652 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
680 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 653 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
681 | ieee80211_queue_work(&local->hw, &sdata->u.mesh.work); | 654 | ieee80211_queue_work(&local->hw, &sdata->work); |
682 | rcu_read_unlock(); | 655 | rcu_read_unlock(); |
683 | } | 656 | } |
684 | 657 | ||
@@ -686,11 +659,9 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
686 | { | 659 | { |
687 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 660 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
688 | 661 | ||
689 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); | ||
690 | setup_timer(&ifmsh->housekeeping_timer, | 662 | setup_timer(&ifmsh->housekeeping_timer, |
691 | ieee80211_mesh_housekeeping_timer, | 663 | ieee80211_mesh_housekeeping_timer, |
692 | (unsigned long) sdata); | 664 | (unsigned long) sdata); |
693 | skb_queue_head_init(&sdata->u.mesh.skb_queue); | ||
694 | 665 | ||
695 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | 666 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; |
696 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | 667 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; |
@@ -731,29 +702,3 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
731 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 702 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
732 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 703 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
733 | } | 704 | } |
734 | |||
735 | ieee80211_rx_result | ||
736 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
737 | { | ||
738 | struct ieee80211_local *local = sdata->local; | ||
739 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
740 | struct ieee80211_mgmt *mgmt; | ||
741 | u16 fc; | ||
742 | |||
743 | if (skb->len < 24) | ||
744 | return RX_DROP_MONITOR; | ||
745 | |||
746 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
747 | fc = le16_to_cpu(mgmt->frame_control); | ||
748 | |||
749 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
750 | case IEEE80211_STYPE_ACTION: | ||
751 | case IEEE80211_STYPE_PROBE_RESP: | ||
752 | case IEEE80211_STYPE_BEACON: | ||
753 | skb_queue_tail(&ifmsh->skb_queue, skb); | ||
754 | ieee80211_queue_work(&local->hw, &ifmsh->work); | ||
755 | return RX_QUEUED; | ||
756 | } | ||
757 | |||
758 | return RX_CONTINUE; | ||
759 | } | ||
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index c88087f1cd0f..ebd3f1d9d889 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -237,8 +237,6 @@ void ieee80211s_update_metric(struct ieee80211_local *local, | |||
237 | struct sta_info *stainfo, struct sk_buff *skb); | 237 | struct sta_info *stainfo, struct sk_buff *skb); |
238 | void ieee80211s_stop(void); | 238 | void ieee80211s_stop(void); |
239 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 239 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
240 | ieee80211_rx_result | ||
241 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | ||
242 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | 240 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); |
243 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | 241 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); |
244 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); | 242 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 0705018d8d1e..829e08a657d0 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -805,14 +805,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
805 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 805 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
806 | 806 | ||
807 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) | 807 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) |
808 | ieee80211_queue_work(&sdata->local->hw, &ifmsh->work); | 808 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
809 | 809 | ||
810 | else if (time_before(jiffies, ifmsh->last_preq)) { | 810 | else if (time_before(jiffies, ifmsh->last_preq)) { |
811 | /* avoid long wait if did not send preqs for a long time | 811 | /* avoid long wait if did not send preqs for a long time |
812 | * and jiffies wrapped around | 812 | * and jiffies wrapped around |
813 | */ | 813 | */ |
814 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; | 814 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; |
815 | ieee80211_queue_work(&sdata->local->hw, &ifmsh->work); | 815 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
816 | } else | 816 | } else |
817 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + | 817 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + |
818 | min_preq_int_jiff(sdata)); | 818 | min_preq_int_jiff(sdata)); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 181ffd6efd81..349e466cf08b 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -315,7 +315,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
315 | read_unlock(&pathtbl_resize_lock); | 315 | read_unlock(&pathtbl_resize_lock); |
316 | if (grow) { | 316 | if (grow) { |
317 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); | 317 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); |
318 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 318 | ieee80211_queue_work(&local->hw, &sdata->work); |
319 | } | 319 | } |
320 | return 0; | 320 | return 0; |
321 | 321 | ||
@@ -425,7 +425,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
425 | read_unlock(&pathtbl_resize_lock); | 425 | read_unlock(&pathtbl_resize_lock); |
426 | if (grow) { | 426 | if (grow) { |
427 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); | 427 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); |
428 | ieee80211_queue_work(&local->hw, &ifmsh->work); | 428 | ieee80211_queue_work(&local->hw, &sdata->work); |
429 | } | 429 | } |
430 | return 0; | 430 | return 0; |
431 | 431 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8fb85c3a043d..85c3ca33333e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -561,23 +561,19 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
561 | beaconint_us = ieee80211_tu_to_usec( | 561 | beaconint_us = ieee80211_tu_to_usec( |
562 | found->vif.bss_conf.beacon_int); | 562 | found->vif.bss_conf.beacon_int); |
563 | 563 | ||
564 | timeout = local->hw.conf.dynamic_ps_forced_timeout; | 564 | timeout = local->dynamic_ps_forced_timeout; |
565 | if (timeout < 0) { | 565 | if (timeout < 0) { |
566 | /* | 566 | /* |
567 | * Go to full PSM if the user configures a very low | ||
568 | * latency requirement. | ||
567 | * The 2 second value is there for compatibility until | 569 | * The 2 second value is there for compatibility until |
568 | * the PM_QOS_NETWORK_LATENCY is configured with real | 570 | * the PM_QOS_NETWORK_LATENCY is configured with real |
569 | * values. | 571 | * values. |
570 | */ | 572 | */ |
571 | if (latency == 2000000000) | 573 | if (latency > 1900000000 && latency != 2000000000) |
572 | timeout = 100; | ||
573 | else if (latency <= 50000) | ||
574 | timeout = 300; | ||
575 | else if (latency <= 100000) | ||
576 | timeout = 100; | ||
577 | else if (latency <= 500000) | ||
578 | timeout = 50; | ||
579 | else | ||
580 | timeout = 0; | 574 | timeout = 0; |
575 | else | ||
576 | timeout = 100; | ||
581 | } | 577 | } |
582 | local->hw.conf.dynamic_ps_timeout = timeout; | 578 | local->hw.conf.dynamic_ps_timeout = timeout; |
583 | 579 | ||
@@ -806,11 +802,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
806 | { | 802 | { |
807 | struct ieee80211_bss *bss = (void *)cbss->priv; | 803 | struct ieee80211_bss *bss = (void *)cbss->priv; |
808 | struct ieee80211_local *local = sdata->local; | 804 | struct ieee80211_local *local = sdata->local; |
805 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
809 | 806 | ||
810 | bss_info_changed |= BSS_CHANGED_ASSOC; | 807 | bss_info_changed |= BSS_CHANGED_ASSOC; |
811 | /* set timing information */ | 808 | /* set timing information */ |
812 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | 809 | bss_conf->beacon_int = cbss->beacon_interval; |
813 | sdata->vif.bss_conf.timestamp = cbss->tsf; | 810 | bss_conf->timestamp = cbss->tsf; |
814 | 811 | ||
815 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | 812 | bss_info_changed |= BSS_CHANGED_BEACON_INT; |
816 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 813 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
@@ -835,7 +832,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
835 | 832 | ||
836 | ieee80211_led_assoc(local, 1); | 833 | ieee80211_led_assoc(local, 1); |
837 | 834 | ||
838 | sdata->vif.bss_conf.assoc = 1; | 835 | bss_conf->assoc = 1; |
839 | /* | 836 | /* |
840 | * For now just always ask the driver to update the basic rateset | 837 | * For now just always ask the driver to update the basic rateset |
841 | * when we have associated, we aren't checking whether it actually | 838 | * when we have associated, we aren't checking whether it actually |
@@ -848,9 +845,15 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
848 | 845 | ||
849 | /* Tell the driver to monitor connection quality (if supported) */ | 846 | /* Tell the driver to monitor connection quality (if supported) */ |
850 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && | 847 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && |
851 | sdata->vif.bss_conf.cqm_rssi_thold) | 848 | bss_conf->cqm_rssi_thold) |
852 | bss_info_changed |= BSS_CHANGED_CQM; | 849 | bss_info_changed |= BSS_CHANGED_CQM; |
853 | 850 | ||
851 | /* Enable ARP filtering */ | ||
852 | if (bss_conf->arp_filter_enabled != sdata->arp_filter_state) { | ||
853 | bss_conf->arp_filter_enabled = sdata->arp_filter_state; | ||
854 | bss_info_changed |= BSS_CHANGED_ARP_FILTER; | ||
855 | } | ||
856 | |||
854 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 857 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
855 | 858 | ||
856 | mutex_lock(&local->iflist_mtx); | 859 | mutex_lock(&local->iflist_mtx); |
@@ -898,13 +901,13 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
898 | netif_tx_stop_all_queues(sdata->dev); | 901 | netif_tx_stop_all_queues(sdata->dev); |
899 | netif_carrier_off(sdata->dev); | 902 | netif_carrier_off(sdata->dev); |
900 | 903 | ||
901 | rcu_read_lock(); | 904 | mutex_lock(&local->sta_mtx); |
902 | sta = sta_info_get(sdata, bssid); | 905 | sta = sta_info_get(sdata, bssid); |
903 | if (sta) { | 906 | if (sta) { |
904 | set_sta_flags(sta, WLAN_STA_DISASSOC); | 907 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
905 | ieee80211_sta_tear_down_BA_sessions(sta); | 908 | ieee80211_sta_tear_down_BA_sessions(sta); |
906 | } | 909 | } |
907 | rcu_read_unlock(); | 910 | mutex_unlock(&local->sta_mtx); |
908 | 911 | ||
909 | changed |= ieee80211_reset_erp_info(sdata); | 912 | changed |= ieee80211_reset_erp_info(sdata); |
910 | 913 | ||
@@ -932,6 +935,12 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
932 | 935 | ||
933 | ieee80211_hw_config(local, config_changed); | 936 | ieee80211_hw_config(local, config_changed); |
934 | 937 | ||
938 | /* Disable ARP filtering */ | ||
939 | if (sdata->vif.bss_conf.arp_filter_enabled) { | ||
940 | sdata->vif.bss_conf.arp_filter_enabled = false; | ||
941 | changed |= BSS_CHANGED_ARP_FILTER; | ||
942 | } | ||
943 | |||
935 | /* The BSSID (not really interesting) and HT changed */ | 944 | /* The BSSID (not really interesting) and HT changed */ |
936 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 945 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
937 | ieee80211_bss_info_change_notify(sdata, changed); | 946 | ieee80211_bss_info_change_notify(sdata, changed); |
@@ -1633,35 +1642,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1633 | ieee80211_bss_info_change_notify(sdata, changed); | 1642 | ieee80211_bss_info_change_notify(sdata, changed); |
1634 | } | 1643 | } |
1635 | 1644 | ||
1636 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 1645 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1637 | struct sk_buff *skb) | 1646 | struct sk_buff *skb) |
1638 | { | ||
1639 | struct ieee80211_local *local = sdata->local; | ||
1640 | struct ieee80211_mgmt *mgmt; | ||
1641 | u16 fc; | ||
1642 | |||
1643 | if (skb->len < 24) | ||
1644 | return RX_DROP_MONITOR; | ||
1645 | |||
1646 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
1647 | fc = le16_to_cpu(mgmt->frame_control); | ||
1648 | |||
1649 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1650 | case IEEE80211_STYPE_PROBE_RESP: | ||
1651 | case IEEE80211_STYPE_BEACON: | ||
1652 | case IEEE80211_STYPE_DEAUTH: | ||
1653 | case IEEE80211_STYPE_DISASSOC: | ||
1654 | case IEEE80211_STYPE_ACTION: | ||
1655 | skb_queue_tail(&sdata->u.mgd.skb_queue, skb); | ||
1656 | ieee80211_queue_work(&local->hw, &sdata->u.mgd.work); | ||
1657 | return RX_QUEUED; | ||
1658 | } | ||
1659 | |||
1660 | return RX_DROP_MONITOR; | ||
1661 | } | ||
1662 | |||
1663 | static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1664 | struct sk_buff *skb) | ||
1665 | { | 1647 | { |
1666 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1648 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1667 | struct ieee80211_rx_status *rx_status; | 1649 | struct ieee80211_rx_status *rx_status; |
@@ -1693,44 +1675,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1693 | break; | 1675 | break; |
1694 | case IEEE80211_STYPE_ACTION: | 1676 | case IEEE80211_STYPE_ACTION: |
1695 | switch (mgmt->u.action.category) { | 1677 | switch (mgmt->u.action.category) { |
1696 | case WLAN_CATEGORY_BACK: { | ||
1697 | struct ieee80211_local *local = sdata->local; | ||
1698 | int len = skb->len; | ||
1699 | struct sta_info *sta; | ||
1700 | |||
1701 | rcu_read_lock(); | ||
1702 | sta = sta_info_get(sdata, mgmt->sa); | ||
1703 | if (!sta) { | ||
1704 | rcu_read_unlock(); | ||
1705 | break; | ||
1706 | } | ||
1707 | |||
1708 | local_bh_disable(); | ||
1709 | |||
1710 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
1711 | case WLAN_ACTION_ADDBA_REQ: | ||
1712 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1713 | sizeof(mgmt->u.action.u.addba_req))) | ||
1714 | break; | ||
1715 | ieee80211_process_addba_request(local, sta, mgmt, len); | ||
1716 | break; | ||
1717 | case WLAN_ACTION_ADDBA_RESP: | ||
1718 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1719 | sizeof(mgmt->u.action.u.addba_resp))) | ||
1720 | break; | ||
1721 | ieee80211_process_addba_resp(local, sta, mgmt, len); | ||
1722 | break; | ||
1723 | case WLAN_ACTION_DELBA: | ||
1724 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1725 | sizeof(mgmt->u.action.u.delba))) | ||
1726 | break; | ||
1727 | ieee80211_process_delba(sdata, sta, mgmt, len); | ||
1728 | break; | ||
1729 | } | ||
1730 | local_bh_enable(); | ||
1731 | rcu_read_unlock(); | ||
1732 | break; | ||
1733 | } | ||
1734 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1678 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1735 | ieee80211_sta_process_chanswitch(sdata, | 1679 | ieee80211_sta_process_chanswitch(sdata, |
1736 | &mgmt->u.action.u.chan_switch.sw_elem, | 1680 | &mgmt->u.action.u.chan_switch.sw_elem, |
@@ -1754,7 +1698,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1754 | default: | 1698 | default: |
1755 | WARN(1, "unexpected: %d", rma); | 1699 | WARN(1, "unexpected: %d", rma); |
1756 | } | 1700 | } |
1757 | goto out; | 1701 | return; |
1758 | } | 1702 | } |
1759 | 1703 | ||
1760 | mutex_unlock(&ifmgd->mtx); | 1704 | mutex_unlock(&ifmgd->mtx); |
@@ -1799,8 +1743,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1799 | 1743 | ||
1800 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1744 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
1801 | } | 1745 | } |
1802 | out: | ||
1803 | kfree_skb(skb); | ||
1804 | } | 1746 | } |
1805 | 1747 | ||
1806 | static void ieee80211_sta_timer(unsigned long data) | 1748 | static void ieee80211_sta_timer(unsigned long data) |
@@ -1815,39 +1757,13 @@ static void ieee80211_sta_timer(unsigned long data) | |||
1815 | return; | 1757 | return; |
1816 | } | 1758 | } |
1817 | 1759 | ||
1818 | ieee80211_queue_work(&local->hw, &ifmgd->work); | 1760 | ieee80211_queue_work(&local->hw, &sdata->work); |
1819 | } | 1761 | } |
1820 | 1762 | ||
1821 | static void ieee80211_sta_work(struct work_struct *work) | 1763 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
1822 | { | 1764 | { |
1823 | struct ieee80211_sub_if_data *sdata = | ||
1824 | container_of(work, struct ieee80211_sub_if_data, u.mgd.work); | ||
1825 | struct ieee80211_local *local = sdata->local; | 1765 | struct ieee80211_local *local = sdata->local; |
1826 | struct ieee80211_if_managed *ifmgd; | 1766 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1827 | struct sk_buff *skb; | ||
1828 | |||
1829 | if (!ieee80211_sdata_running(sdata)) | ||
1830 | return; | ||
1831 | |||
1832 | if (local->scanning) | ||
1833 | return; | ||
1834 | |||
1835 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
1836 | return; | ||
1837 | |||
1838 | /* | ||
1839 | * ieee80211_queue_work() should have picked up most cases, | ||
1840 | * here we'll pick the rest. | ||
1841 | */ | ||
1842 | if (WARN(local->suspended, "STA MLME work scheduled while " | ||
1843 | "going to suspend\n")) | ||
1844 | return; | ||
1845 | |||
1846 | ifmgd = &sdata->u.mgd; | ||
1847 | |||
1848 | /* first process frames to avoid timing out while a frame is pending */ | ||
1849 | while ((skb = skb_dequeue(&ifmgd->skb_queue))) | ||
1850 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | ||
1851 | 1767 | ||
1852 | /* then process the rest of the work */ | 1768 | /* then process the rest of the work */ |
1853 | mutex_lock(&ifmgd->mtx); | 1769 | mutex_lock(&ifmgd->mtx); |
@@ -1942,8 +1858,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
1942 | ieee80211_queue_work(&sdata->local->hw, | 1858 | ieee80211_queue_work(&sdata->local->hw, |
1943 | &sdata->u.mgd.monitor_work); | 1859 | &sdata->u.mgd.monitor_work); |
1944 | /* and do all the other regular work too */ | 1860 | /* and do all the other regular work too */ |
1945 | ieee80211_queue_work(&sdata->local->hw, | 1861 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
1946 | &sdata->u.mgd.work); | ||
1947 | } | 1862 | } |
1948 | } | 1863 | } |
1949 | 1864 | ||
@@ -1958,7 +1873,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1958 | * time -- the code here is properly synchronised. | 1873 | * time -- the code here is properly synchronised. |
1959 | */ | 1874 | */ |
1960 | 1875 | ||
1961 | cancel_work_sync(&ifmgd->work); | ||
1962 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 1876 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1963 | if (del_timer_sync(&ifmgd->timer)) | 1877 | if (del_timer_sync(&ifmgd->timer)) |
1964 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1878 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -1990,7 +1904,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1990 | struct ieee80211_if_managed *ifmgd; | 1904 | struct ieee80211_if_managed *ifmgd; |
1991 | 1905 | ||
1992 | ifmgd = &sdata->u.mgd; | 1906 | ifmgd = &sdata->u.mgd; |
1993 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | ||
1994 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | 1907 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); |
1995 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1908 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1996 | INIT_WORK(&ifmgd->beacon_connection_loss_work, | 1909 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
@@ -2003,7 +1916,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2003 | (unsigned long) sdata); | 1916 | (unsigned long) sdata); |
2004 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, | 1917 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, |
2005 | (unsigned long) sdata); | 1918 | (unsigned long) sdata); |
2006 | skb_queue_head_init(&ifmgd->skb_queue); | ||
2007 | 1919 | ||
2008 | ifmgd->flags = 0; | 1920 | ifmgd->flags = 0; |
2009 | 1921 | ||
@@ -2152,18 +2064,9 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, | |||
2152 | cfg80211_send_assoc_timeout(wk->sdata->dev, | 2064 | cfg80211_send_assoc_timeout(wk->sdata->dev, |
2153 | wk->filter_ta); | 2065 | wk->filter_ta); |
2154 | return WORK_DONE_DESTROY; | 2066 | return WORK_DONE_DESTROY; |
2155 | } else { | ||
2156 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2157 | #ifdef CONFIG_INET | ||
2158 | /* | ||
2159 | * configure ARP filter IP addresses to the driver, | ||
2160 | * intentionally outside the mgd mutex. | ||
2161 | */ | ||
2162 | rtnl_lock(); | ||
2163 | ieee80211_set_arp_filter(wk->sdata); | ||
2164 | rtnl_unlock(); | ||
2165 | #endif | ||
2166 | } | 2067 | } |
2068 | |||
2069 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2167 | } | 2070 | } |
2168 | 2071 | ||
2169 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); | 2072 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); |
@@ -2292,14 +2195,16 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2292 | struct ieee80211_local *local = sdata->local; | 2195 | struct ieee80211_local *local = sdata->local; |
2293 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2196 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2294 | struct ieee80211_work *wk; | 2197 | struct ieee80211_work *wk; |
2295 | const u8 *bssid = req->bss->bssid; | 2198 | u8 bssid[ETH_ALEN]; |
2199 | bool assoc_bss = false; | ||
2296 | 2200 | ||
2297 | mutex_lock(&ifmgd->mtx); | 2201 | mutex_lock(&ifmgd->mtx); |
2298 | 2202 | ||
2203 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | ||
2299 | if (ifmgd->associated == req->bss) { | 2204 | if (ifmgd->associated == req->bss) { |
2300 | bssid = req->bss->bssid; | 2205 | ieee80211_set_disassoc(sdata, false); |
2301 | ieee80211_set_disassoc(sdata, true); | ||
2302 | mutex_unlock(&ifmgd->mtx); | 2206 | mutex_unlock(&ifmgd->mtx); |
2207 | assoc_bss = true; | ||
2303 | } else { | 2208 | } else { |
2304 | bool not_auth_yet = false; | 2209 | bool not_auth_yet = false; |
2305 | 2210 | ||
@@ -2345,6 +2250,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2345 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, | 2250 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, |
2346 | req->reason_code, cookie, | 2251 | req->reason_code, cookie, |
2347 | !req->local_state_change); | 2252 | !req->local_state_change); |
2253 | if (assoc_bss) | ||
2254 | sta_info_destroy_addr(sdata, bssid); | ||
2348 | 2255 | ||
2349 | ieee80211_recalc_idle(sdata->local); | 2256 | ieee80211_recalc_idle(sdata->local); |
2350 | 2257 | ||
@@ -2389,44 +2296,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2389 | return 0; | 2296 | return 0; |
2390 | } | 2297 | } |
2391 | 2298 | ||
2392 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
2393 | struct ieee80211_channel *chan, | ||
2394 | enum nl80211_channel_type channel_type, | ||
2395 | bool channel_type_valid, | ||
2396 | const u8 *buf, size_t len, u64 *cookie) | ||
2397 | { | ||
2398 | struct ieee80211_local *local = sdata->local; | ||
2399 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2400 | struct sk_buff *skb; | ||
2401 | |||
2402 | /* Check that we are on the requested channel for transmission */ | ||
2403 | if (chan != local->tmp_channel && | ||
2404 | chan != local->oper_channel) | ||
2405 | return -EBUSY; | ||
2406 | if (channel_type_valid && | ||
2407 | (channel_type != local->tmp_channel_type && | ||
2408 | channel_type != local->_oper_channel_type)) | ||
2409 | return -EBUSY; | ||
2410 | |||
2411 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | ||
2412 | if (!skb) | ||
2413 | return -ENOMEM; | ||
2414 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2415 | |||
2416 | memcpy(skb_put(skb, len), buf, len); | ||
2417 | |||
2418 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | ||
2419 | IEEE80211_SKB_CB(skb)->flags |= | ||
2420 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2421 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
2422 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
2423 | skb->dev = sdata->dev; | ||
2424 | ieee80211_tx_skb(sdata, skb); | ||
2425 | |||
2426 | *cookie = (unsigned long) skb; | ||
2427 | return 0; | ||
2428 | } | ||
2429 | |||
2430 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | 2299 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, |
2431 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 2300 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
2432 | gfp_t gfp) | 2301 | gfp_t gfp) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 75202b295a4e..d287fde0431d 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -40,22 +40,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
40 | list_for_each_entry(sdata, &local->interfaces, list) | 40 | list_for_each_entry(sdata, &local->interfaces, list) |
41 | ieee80211_disable_keys(sdata); | 41 | ieee80211_disable_keys(sdata); |
42 | 42 | ||
43 | /* Tear down aggregation sessions */ | 43 | /* tear down aggregation sessions and remove STAs */ |
44 | 44 | mutex_lock(&local->sta_mtx); | |
45 | rcu_read_lock(); | 45 | list_for_each_entry(sta, &local->sta_list, list) { |
46 | 46 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | |
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | ||
48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
49 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | 47 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
50 | ieee80211_sta_tear_down_BA_sessions(sta); | 48 | ieee80211_sta_tear_down_BA_sessions(sta); |
51 | } | 49 | } |
52 | } | ||
53 | 50 | ||
54 | rcu_read_unlock(); | ||
55 | |||
56 | /* remove STAs */ | ||
57 | mutex_lock(&local->sta_mtx); | ||
58 | list_for_each_entry(sta, &local->sta_list, list) { | ||
59 | if (sta->uploaded) { | 51 | if (sta->uploaded) { |
60 | sdata = sta->sdata; | 52 | sdata = sta->sdata; |
61 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 53 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
@@ -72,6 +64,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
72 | 64 | ||
73 | /* remove all interfaces */ | 65 | /* remove all interfaces */ |
74 | list_for_each_entry(sdata, &local->interfaces, list) { | 66 | list_for_each_entry(sdata, &local->interfaces, list) { |
67 | cancel_work_sync(&sdata->work); | ||
68 | |||
75 | switch(sdata->vif.type) { | 69 | switch(sdata->vif.type) { |
76 | case NL80211_IFTYPE_STATION: | 70 | case NL80211_IFTYPE_STATION: |
77 | ieee80211_sta_quiesce(sdata); | 71 | ieee80211_sta_quiesce(sdata); |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c23f08251da4..7a04951fcb1f 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -365,7 +365,7 @@ minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, stru | |||
365 | return; | 365 | return; |
366 | 366 | ||
367 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 367 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
368 | if (likely(sta->ampdu_mlme.tid_state_tx[tid] != HT_AGG_STATE_IDLE)) | 368 | if (likely(sta->ampdu_mlme.tid_tx[tid])) |
369 | return; | 369 | return; |
370 | 370 | ||
371 | ieee80211_start_tx_ba_session(pubsta, tid); | 371 | ieee80211_start_tx_ba_session(pubsta, tid); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6a15632e7eca..a8aa0f2411a2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -719,16 +719,13 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
719 | 719 | ||
720 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 720 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
721 | 721 | ||
722 | spin_lock(&sta->lock); | 722 | tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); |
723 | 723 | if (!tid_agg_rx) | |
724 | if (!sta->ampdu_mlme.tid_active_rx[tid]) | 724 | goto dont_reorder; |
725 | goto dont_reorder_unlock; | ||
726 | |||
727 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
728 | 725 | ||
729 | /* qos null data frames are excluded */ | 726 | /* qos null data frames are excluded */ |
730 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 727 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
731 | goto dont_reorder_unlock; | 728 | goto dont_reorder; |
732 | 729 | ||
733 | /* new, potentially un-ordered, ampdu frame - process it */ | 730 | /* new, potentially un-ordered, ampdu frame - process it */ |
734 | 731 | ||
@@ -740,20 +737,22 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
740 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 737 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
741 | sc = le16_to_cpu(hdr->seq_ctrl); | 738 | sc = le16_to_cpu(hdr->seq_ctrl); |
742 | if (sc & IEEE80211_SCTL_FRAG) { | 739 | if (sc & IEEE80211_SCTL_FRAG) { |
743 | spin_unlock(&sta->lock); | 740 | skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; |
744 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | 741 | skb_queue_tail(&rx->sdata->skb_queue, skb); |
745 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 742 | ieee80211_queue_work(&local->hw, &rx->sdata->work); |
746 | dev_kfree_skb(skb); | ||
747 | return; | 743 | return; |
748 | } | 744 | } |
749 | 745 | ||
750 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) { | 746 | /* |
751 | spin_unlock(&sta->lock); | 747 | * No locking needed -- we will only ever process one |
748 | * RX packet at a time, and thus own tid_agg_rx. All | ||
749 | * other code manipulating it needs to (and does) make | ||
750 | * sure that we cannot get to it any more before doing | ||
751 | * anything with it. | ||
752 | */ | ||
753 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | ||
752 | return; | 754 | return; |
753 | } | ||
754 | 755 | ||
755 | dont_reorder_unlock: | ||
756 | spin_unlock(&sta->lock); | ||
757 | dont_reorder: | 756 | dont_reorder: |
758 | __skb_queue_tail(frames, skb); | 757 | __skb_queue_tail(frames, skb); |
759 | } | 758 | } |
@@ -1268,11 +1267,13 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1268 | rx->queue, &(rx->skb)); | 1267 | rx->queue, &(rx->skb)); |
1269 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 1268 | if (rx->key && rx->key->conf.alg == ALG_CCMP && |
1270 | ieee80211_has_protected(fc)) { | 1269 | ieee80211_has_protected(fc)) { |
1270 | int queue = ieee80211_is_mgmt(fc) ? | ||
1271 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1271 | /* Store CCMP PN so that we can verify that the next | 1272 | /* Store CCMP PN so that we can verify that the next |
1272 | * fragment has a sequential PN value. */ | 1273 | * fragment has a sequential PN value. */ |
1273 | entry->ccmp = 1; | 1274 | entry->ccmp = 1; |
1274 | memcpy(entry->last_pn, | 1275 | memcpy(entry->last_pn, |
1275 | rx->key->u.ccmp.rx_pn[rx->queue], | 1276 | rx->key->u.ccmp.rx_pn[queue], |
1276 | CCMP_PN_LEN); | 1277 | CCMP_PN_LEN); |
1277 | } | 1278 | } |
1278 | return RX_QUEUED; | 1279 | return RX_QUEUED; |
@@ -1292,6 +1293,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1292 | if (entry->ccmp) { | 1293 | if (entry->ccmp) { |
1293 | int i; | 1294 | int i; |
1294 | u8 pn[CCMP_PN_LEN], *rpn; | 1295 | u8 pn[CCMP_PN_LEN], *rpn; |
1296 | int queue; | ||
1295 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) | 1297 | if (!rx->key || rx->key->conf.alg != ALG_CCMP) |
1296 | return RX_DROP_UNUSABLE; | 1298 | return RX_DROP_UNUSABLE; |
1297 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); | 1299 | memcpy(pn, entry->last_pn, CCMP_PN_LEN); |
@@ -1300,7 +1302,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1300 | if (pn[i]) | 1302 | if (pn[i]) |
1301 | break; | 1303 | break; |
1302 | } | 1304 | } |
1303 | rpn = rx->key->u.ccmp.rx_pn[rx->queue]; | 1305 | queue = ieee80211_is_mgmt(fc) ? |
1306 | NUM_RX_DATA_QUEUES : rx->queue; | ||
1307 | rpn = rx->key->u.ccmp.rx_pn[queue]; | ||
1304 | if (memcmp(pn, rpn, CCMP_PN_LEN)) | 1308 | if (memcmp(pn, rpn, CCMP_PN_LEN)) |
1305 | return RX_DROP_UNUSABLE; | 1309 | return RX_DROP_UNUSABLE; |
1306 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); | 1310 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); |
@@ -1830,13 +1834,11 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1830 | &bar_data, sizeof(bar_data))) | 1834 | &bar_data, sizeof(bar_data))) |
1831 | return RX_DROP_MONITOR; | 1835 | return RX_DROP_MONITOR; |
1832 | 1836 | ||
1833 | spin_lock(&rx->sta->lock); | ||
1834 | tid = le16_to_cpu(bar_data.control) >> 12; | 1837 | tid = le16_to_cpu(bar_data.control) >> 12; |
1835 | if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { | 1838 | |
1836 | spin_unlock(&rx->sta->lock); | 1839 | tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]); |
1840 | if (!tid_agg_rx) | ||
1837 | return RX_DROP_MONITOR; | 1841 | return RX_DROP_MONITOR; |
1838 | } | ||
1839 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | ||
1840 | 1842 | ||
1841 | start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; | 1843 | start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; |
1842 | 1844 | ||
@@ -1849,7 +1851,6 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1849 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1851 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1850 | frames); | 1852 | frames); |
1851 | kfree_skb(skb); | 1853 | kfree_skb(skb); |
1852 | spin_unlock(&rx->sta->lock); | ||
1853 | return RX_QUEUED; | 1854 | return RX_QUEUED; |
1854 | } | 1855 | } |
1855 | 1856 | ||
@@ -1950,30 +1951,27 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1950 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1951 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) |
1951 | break; | 1952 | break; |
1952 | 1953 | ||
1953 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
1954 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | ||
1955 | |||
1956 | switch (mgmt->u.action.u.addba_req.action_code) { | 1954 | switch (mgmt->u.action.u.addba_req.action_code) { |
1957 | case WLAN_ACTION_ADDBA_REQ: | 1955 | case WLAN_ACTION_ADDBA_REQ: |
1958 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1956 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1959 | sizeof(mgmt->u.action.u.addba_req))) | 1957 | sizeof(mgmt->u.action.u.addba_req))) |
1960 | return RX_DROP_MONITOR; | 1958 | goto invalid; |
1961 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | 1959 | break; |
1962 | goto handled; | ||
1963 | case WLAN_ACTION_ADDBA_RESP: | 1960 | case WLAN_ACTION_ADDBA_RESP: |
1964 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1961 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1965 | sizeof(mgmt->u.action.u.addba_resp))) | 1962 | sizeof(mgmt->u.action.u.addba_resp))) |
1966 | break; | 1963 | goto invalid; |
1967 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | 1964 | break; |
1968 | goto handled; | ||
1969 | case WLAN_ACTION_DELBA: | 1965 | case WLAN_ACTION_DELBA: |
1970 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1966 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1971 | sizeof(mgmt->u.action.u.delba))) | 1967 | sizeof(mgmt->u.action.u.delba))) |
1972 | break; | 1968 | goto invalid; |
1973 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | 1969 | break; |
1974 | goto handled; | 1970 | default: |
1971 | goto invalid; | ||
1975 | } | 1972 | } |
1976 | break; | 1973 | |
1974 | goto queue; | ||
1977 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1975 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1978 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 1976 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) |
1979 | break; | 1977 | break; |
@@ -2003,7 +2001,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2003 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 2001 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
2004 | break; | 2002 | break; |
2005 | 2003 | ||
2006 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 2004 | goto queue; |
2007 | } | 2005 | } |
2008 | break; | 2006 | break; |
2009 | case WLAN_CATEGORY_SA_QUERY: | 2007 | case WLAN_CATEGORY_SA_QUERY: |
@@ -2021,11 +2019,12 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2021 | break; | 2019 | break; |
2022 | case WLAN_CATEGORY_MESH_PLINK: | 2020 | case WLAN_CATEGORY_MESH_PLINK: |
2023 | case WLAN_CATEGORY_MESH_PATH_SEL: | 2021 | case WLAN_CATEGORY_MESH_PATH_SEL: |
2024 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2022 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2025 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2023 | break; |
2026 | break; | 2024 | goto queue; |
2027 | } | 2025 | } |
2028 | 2026 | ||
2027 | invalid: | ||
2029 | /* | 2028 | /* |
2030 | * For AP mode, hostapd is responsible for handling any action | 2029 | * For AP mode, hostapd is responsible for handling any action |
2031 | * frames that we didn't handle, including returning unknown | 2030 | * frames that we didn't handle, including returning unknown |
@@ -2045,8 +2044,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2045 | */ | 2044 | */ |
2046 | status = IEEE80211_SKB_RXCB(rx->skb); | 2045 | status = IEEE80211_SKB_RXCB(rx->skb); |
2047 | 2046 | ||
2048 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 2047 | if (cfg80211_rx_action(rx->sdata->dev, status->freq, |
2049 | cfg80211_rx_action(rx->sdata->dev, status->freq, | ||
2050 | rx->skb->data, rx->skb->len, | 2048 | rx->skb->data, rx->skb->len, |
2051 | GFP_ATOMIC)) | 2049 | GFP_ATOMIC)) |
2052 | goto handled; | 2050 | goto handled; |
@@ -2074,6 +2072,14 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2074 | rx->sta->rx_packets++; | 2072 | rx->sta->rx_packets++; |
2075 | dev_kfree_skb(rx->skb); | 2073 | dev_kfree_skb(rx->skb); |
2076 | return RX_QUEUED; | 2074 | return RX_QUEUED; |
2075 | |||
2076 | queue: | ||
2077 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; | ||
2078 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2079 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
2080 | if (rx->sta) | ||
2081 | rx->sta->rx_packets++; | ||
2082 | return RX_QUEUED; | ||
2077 | } | 2083 | } |
2078 | 2084 | ||
2079 | static ieee80211_rx_result debug_noinline | 2085 | static ieee80211_rx_result debug_noinline |
@@ -2081,10 +2087,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2081 | { | 2087 | { |
2082 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2088 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
2083 | ieee80211_rx_result rxs; | 2089 | ieee80211_rx_result rxs; |
2090 | struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; | ||
2091 | __le16 stype; | ||
2084 | 2092 | ||
2085 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 2093 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
2086 | return RX_DROP_MONITOR; | 2094 | return RX_DROP_MONITOR; |
2087 | 2095 | ||
2096 | if (rx->skb->len < 24) | ||
2097 | return RX_DROP_MONITOR; | ||
2098 | |||
2088 | if (ieee80211_drop_unencrypted_mgmt(rx)) | 2099 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
2089 | return RX_DROP_UNUSABLE; | 2100 | return RX_DROP_UNUSABLE; |
2090 | 2101 | ||
@@ -2092,16 +2103,42 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2092 | if (rxs != RX_CONTINUE) | 2103 | if (rxs != RX_CONTINUE) |
2093 | return rxs; | 2104 | return rxs; |
2094 | 2105 | ||
2095 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2106 | stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); |
2096 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
2097 | 2107 | ||
2098 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 2108 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
2099 | return ieee80211_ibss_rx_mgmt(sdata, rx->skb); | 2109 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2110 | sdata->vif.type != NL80211_IFTYPE_STATION) | ||
2111 | return RX_DROP_MONITOR; | ||
2112 | |||
2113 | switch (stype) { | ||
2114 | case cpu_to_le16(IEEE80211_STYPE_BEACON): | ||
2115 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): | ||
2116 | /* process for all: mesh, mlme, ibss */ | ||
2117 | break; | ||
2118 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
2119 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): | ||
2120 | /* process only for station */ | ||
2121 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
2122 | return RX_DROP_MONITOR; | ||
2123 | break; | ||
2124 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | ||
2125 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
2126 | /* process only for ibss */ | ||
2127 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
2128 | return RX_DROP_MONITOR; | ||
2129 | break; | ||
2130 | default: | ||
2131 | return RX_DROP_MONITOR; | ||
2132 | } | ||
2100 | 2133 | ||
2101 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | 2134 | /* queue up frame and kick off work to process it */ |
2102 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 2135 | rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; |
2136 | skb_queue_tail(&sdata->skb_queue, rx->skb); | ||
2137 | ieee80211_queue_work(&rx->local->hw, &sdata->work); | ||
2138 | if (rx->sta) | ||
2139 | rx->sta->rx_packets++; | ||
2103 | 2140 | ||
2104 | return RX_DROP_MONITOR; | 2141 | return RX_QUEUED; |
2105 | } | 2142 | } |
2106 | 2143 | ||
2107 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, | 2144 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4607da9a6ff7..67656cbf2b15 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -235,6 +235,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
235 | spin_lock_init(&sta->lock); | 235 | spin_lock_init(&sta->lock); |
236 | spin_lock_init(&sta->flaglock); | 236 | spin_lock_init(&sta->flaglock); |
237 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 237 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
238 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | ||
239 | mutex_init(&sta->ampdu_mlme.mtx); | ||
238 | 240 | ||
239 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 241 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
240 | sta->local = local; | 242 | sta->local = local; |
@@ -246,14 +248,12 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
246 | } | 248 | } |
247 | 249 | ||
248 | for (i = 0; i < STA_TID_NUM; i++) { | 250 | for (i = 0; i < STA_TID_NUM; i++) { |
249 | /* timer_to_tid must be initialized with identity mapping to | 251 | /* |
250 | * enable session_timer's data differentiation. refer to | 252 | * timer_to_tid must be initialized with identity mapping |
251 | * sta_rx_agg_session_timer_expired for useage */ | 253 | * to enable session_timer's data differentiation. See |
254 | * sta_rx_agg_session_timer_expired for usage. | ||
255 | */ | ||
252 | sta->timer_to_tid[i] = i; | 256 | sta->timer_to_tid[i] = i; |
253 | /* tx */ | ||
254 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; | ||
255 | sta->ampdu_mlme.tid_tx[i] = NULL; | ||
256 | sta->ampdu_mlme.addba_req_num[i] = 0; | ||
257 | } | 257 | } |
258 | skb_queue_head_init(&sta->ps_tx_buf); | 258 | skb_queue_head_init(&sta->ps_tx_buf); |
259 | skb_queue_head_init(&sta->tx_filtered); | 259 | skb_queue_head_init(&sta->tx_filtered); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 813da34db733..10d0fcb417ae 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -42,9 +42,6 @@ | |||
42 | * be in the queues | 42 | * be in the queues |
43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping | 43 | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
44 | * station in power-save mode, reply when the driver unblocks. | 44 | * station in power-save mode, reply when the driver unblocks. |
45 | * @WLAN_STA_DISASSOC: Disassociation in progress. | ||
46 | * This is used to reject TX BA session requests when disassociation | ||
47 | * is in progress. | ||
48 | */ | 45 | */ |
49 | enum ieee80211_sta_info_flags { | 46 | enum ieee80211_sta_info_flags { |
50 | WLAN_STA_AUTH = 1<<0, | 47 | WLAN_STA_AUTH = 1<<0, |
@@ -60,38 +57,44 @@ enum ieee80211_sta_info_flags { | |||
60 | WLAN_STA_BLOCK_BA = 1<<11, | 57 | WLAN_STA_BLOCK_BA = 1<<11, |
61 | WLAN_STA_PS_DRIVER = 1<<12, | 58 | WLAN_STA_PS_DRIVER = 1<<12, |
62 | WLAN_STA_PSPOLL = 1<<13, | 59 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | ||
64 | }; | 60 | }; |
65 | 61 | ||
66 | #define STA_TID_NUM 16 | 62 | #define STA_TID_NUM 16 |
67 | #define ADDBA_RESP_INTERVAL HZ | 63 | #define ADDBA_RESP_INTERVAL HZ |
68 | #define HT_AGG_MAX_RETRIES (0x3) | 64 | #define HT_AGG_MAX_RETRIES 0x3 |
69 | 65 | ||
70 | #define HT_AGG_STATE_INITIATOR_SHIFT (4) | 66 | #define HT_AGG_STATE_DRV_READY 0 |
71 | 67 | #define HT_AGG_STATE_RESPONSE_RECEIVED 1 | |
72 | #define HT_ADDBA_REQUESTED_MSK BIT(0) | 68 | #define HT_AGG_STATE_OPERATIONAL 2 |
73 | #define HT_ADDBA_DRV_READY_MSK BIT(1) | 69 | #define HT_AGG_STATE_STOPPING 3 |
74 | #define HT_ADDBA_RECEIVED_MSK BIT(2) | 70 | #define HT_AGG_STATE_WANT_START 4 |
75 | #define HT_AGG_STATE_REQ_STOP_BA_MSK BIT(3) | 71 | #define HT_AGG_STATE_WANT_STOP 5 |
76 | #define HT_AGG_STATE_INITIATOR_MSK BIT(HT_AGG_STATE_INITIATOR_SHIFT) | ||
77 | #define HT_AGG_STATE_IDLE (0x0) | ||
78 | #define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \ | ||
79 | HT_ADDBA_DRV_READY_MSK | \ | ||
80 | HT_ADDBA_RECEIVED_MSK) | ||
81 | 72 | ||
82 | /** | 73 | /** |
83 | * struct tid_ampdu_tx - TID aggregation information (Tx). | 74 | * struct tid_ampdu_tx - TID aggregation information (Tx). |
84 | * | 75 | * |
76 | * @rcu_head: rcu head for freeing structure | ||
85 | * @addba_resp_timer: timer for peer's response to addba request | 77 | * @addba_resp_timer: timer for peer's response to addba request |
86 | * @pending: pending frames queue -- use sta's spinlock to protect | 78 | * @pending: pending frames queue -- use sta's spinlock to protect |
87 | * @ssn: Starting Sequence Number expected to be aggregated. | ||
88 | * @dialog_token: dialog token for aggregation session | 79 | * @dialog_token: dialog token for aggregation session |
80 | * @state: session state (see above) | ||
81 | * @stop_initiator: initiator of a session stop | ||
82 | * | ||
83 | * This structure is protected by RCU and the per-station | ||
84 | * spinlock. Assignments to the array holding it must hold | ||
85 | * the spinlock, only the TX path can access it under RCU | ||
86 | * lock-free if, and only if, the state has the flag | ||
87 | * %HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path | ||
88 | * must also acquire the spinlock and re-check the state, | ||
89 | * see comments in the tx code touching it. | ||
89 | */ | 90 | */ |
90 | struct tid_ampdu_tx { | 91 | struct tid_ampdu_tx { |
92 | struct rcu_head rcu_head; | ||
91 | struct timer_list addba_resp_timer; | 93 | struct timer_list addba_resp_timer; |
92 | struct sk_buff_head pending; | 94 | struct sk_buff_head pending; |
93 | u16 ssn; | 95 | unsigned long state; |
94 | u8 dialog_token; | 96 | u8 dialog_token; |
97 | u8 stop_initiator; | ||
95 | }; | 98 | }; |
96 | 99 | ||
97 | /** | 100 | /** |
@@ -106,8 +109,18 @@ struct tid_ampdu_tx { | |||
106 | * @buf_size: buffer size for incoming A-MPDUs | 109 | * @buf_size: buffer size for incoming A-MPDUs |
107 | * @timeout: reset timer value (in TUs). | 110 | * @timeout: reset timer value (in TUs). |
108 | * @dialog_token: dialog token for aggregation session | 111 | * @dialog_token: dialog token for aggregation session |
112 | * @rcu_head: RCU head used for freeing this struct | ||
113 | * | ||
114 | * This structure is protected by RCU and the per-station | ||
115 | * spinlock. Assignments to the array holding it must hold | ||
116 | * the spinlock, only the RX path can access it under RCU | ||
117 | * lock-free. The RX path, since it is single-threaded, | ||
118 | * can even modify the structure without locking since the | ||
119 | * only other modifications to it are done when the struct | ||
120 | * can not yet or no longer be found by the RX path. | ||
109 | */ | 121 | */ |
110 | struct tid_ampdu_rx { | 122 | struct tid_ampdu_rx { |
123 | struct rcu_head rcu_head; | ||
111 | struct sk_buff **reorder_buf; | 124 | struct sk_buff **reorder_buf; |
112 | unsigned long *reorder_time; | 125 | unsigned long *reorder_time; |
113 | struct timer_list session_timer; | 126 | struct timer_list session_timer; |
@@ -122,19 +135,23 @@ struct tid_ampdu_rx { | |||
122 | /** | 135 | /** |
123 | * struct sta_ampdu_mlme - STA aggregation information. | 136 | * struct sta_ampdu_mlme - STA aggregation information. |
124 | * | 137 | * |
125 | * @tid_active_rx: TID's state in Rx session state machine. | 138 | * @tid_rx: aggregation info for Rx per TID -- RCU protected |
126 | * @tid_rx: aggregation info for Rx per TID | ||
127 | * @tid_state_tx: TID's state in Tx session state machine. | ||
128 | * @tid_tx: aggregation info for Tx per TID | 139 | * @tid_tx: aggregation info for Tx per TID |
129 | * @addba_req_num: number of times addBA request has been sent. | 140 | * @addba_req_num: number of times addBA request has been sent. |
130 | * @dialog_token_allocator: dialog token enumerator for each new session; | 141 | * @dialog_token_allocator: dialog token enumerator for each new session; |
142 | * @work: work struct for starting/stopping aggregation | ||
143 | * @tid_rx_timer_expired: bitmap indicating on which TIDs the | ||
144 | * RX timer expired until the work for it runs | ||
145 | * @mtx: mutex to protect all TX data (except non-NULL assignments | ||
146 | * to tid_tx[idx], which are protected by the sta spinlock) | ||
131 | */ | 147 | */ |
132 | struct sta_ampdu_mlme { | 148 | struct sta_ampdu_mlme { |
149 | struct mutex mtx; | ||
133 | /* rx */ | 150 | /* rx */ |
134 | bool tid_active_rx[STA_TID_NUM]; | ||
135 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 151 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
152 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; | ||
136 | /* tx */ | 153 | /* tx */ |
137 | u8 tid_state_tx[STA_TID_NUM]; | 154 | struct work_struct work; |
138 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; | 155 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; |
139 | u8 addba_req_num[STA_TID_NUM]; | 156 | u8 addba_req_num[STA_TID_NUM]; |
140 | u8 dialog_token_allocator; | 157 | u8 dialog_token_allocator; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 680bcb7093db..698d4718b1a4 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1092,6 +1092,59 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
1092 | return true; | 1092 | return true; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | ||
1096 | struct sk_buff *skb, | ||
1097 | struct ieee80211_tx_info *info, | ||
1098 | struct tid_ampdu_tx *tid_tx, | ||
1099 | int tid) | ||
1100 | { | ||
1101 | bool queued = false; | ||
1102 | |||
1103 | if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { | ||
1104 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
1105 | } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | ||
1106 | /* | ||
1107 | * nothing -- this aggregation session is being started | ||
1108 | * but that might still fail with the driver | ||
1109 | */ | ||
1110 | } else { | ||
1111 | spin_lock(&tx->sta->lock); | ||
1112 | /* | ||
1113 | * Need to re-check now, because we may get here | ||
1114 | * | ||
1115 | * 1) in the window during which the setup is actually | ||
1116 | * already done, but not marked yet because not all | ||
1117 | * packets are spliced over to the driver pending | ||
1118 | * queue yet -- if this happened we acquire the lock | ||
1119 | * either before or after the splice happens, but | ||
1120 | * need to recheck which of these cases happened. | ||
1121 | * | ||
1122 | * 2) during session teardown, if the OPERATIONAL bit | ||
1123 | * was cleared due to the teardown but the pointer | ||
1124 | * hasn't been assigned NULL yet (or we loaded it | ||
1125 | * before it was assigned) -- in this case it may | ||
1126 | * now be NULL which means we should just let the | ||
1127 | * packet pass through because splicing the frames | ||
1128 | * back is already done. | ||
1129 | */ | ||
1130 | tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; | ||
1131 | |||
1132 | if (!tid_tx) { | ||
1133 | /* do nothing, let packet pass through */ | ||
1134 | } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { | ||
1135 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
1136 | } else { | ||
1137 | queued = true; | ||
1138 | info->control.vif = &tx->sdata->vif; | ||
1139 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1140 | __skb_queue_tail(&tid_tx->pending, skb); | ||
1141 | } | ||
1142 | spin_unlock(&tx->sta->lock); | ||
1143 | } | ||
1144 | |||
1145 | return queued; | ||
1146 | } | ||
1147 | |||
1095 | /* | 1148 | /* |
1096 | * initialises @tx | 1149 | * initialises @tx |
1097 | */ | 1150 | */ |
@@ -1104,8 +1157,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1104 | struct ieee80211_hdr *hdr; | 1157 | struct ieee80211_hdr *hdr; |
1105 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1158 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1106 | int hdrlen, tid; | 1159 | int hdrlen, tid; |
1107 | u8 *qc, *state; | 1160 | u8 *qc; |
1108 | bool queued = false; | ||
1109 | 1161 | ||
1110 | memset(tx, 0, sizeof(*tx)); | 1162 | memset(tx, 0, sizeof(*tx)); |
1111 | tx->skb = skb; | 1163 | tx->skb = skb; |
@@ -1157,35 +1209,16 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1157 | qc = ieee80211_get_qos_ctl(hdr); | 1209 | qc = ieee80211_get_qos_ctl(hdr); |
1158 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 1210 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
1159 | 1211 | ||
1160 | spin_lock(&tx->sta->lock); | 1212 | tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); |
1161 | /* | 1213 | if (tid_tx) { |
1162 | * XXX: This spinlock could be fairly expensive, but see the | 1214 | bool queued; |
1163 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). | ||
1164 | * One way to solve this would be to do something RCU-like | ||
1165 | * for managing the tid_tx struct and using atomic bitops | ||
1166 | * for the actual state -- by introducing an actual | ||
1167 | * 'operational' bit that would be possible. It would | ||
1168 | * require changing ieee80211_agg_tx_operational() to | ||
1169 | * set that bit, and changing the way tid_tx is managed | ||
1170 | * everywhere, including races between that bit and | ||
1171 | * tid_tx going away (tid_tx being added can be easily | ||
1172 | * committed to memory before the 'operational' bit). | ||
1173 | */ | ||
1174 | tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; | ||
1175 | state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; | ||
1176 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
1177 | info->flags |= IEEE80211_TX_CTL_AMPDU; | ||
1178 | } else if (*state != HT_AGG_STATE_IDLE) { | ||
1179 | /* in progress */ | ||
1180 | queued = true; | ||
1181 | info->control.vif = &sdata->vif; | ||
1182 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1183 | __skb_queue_tail(&tid_tx->pending, skb); | ||
1184 | } | ||
1185 | spin_unlock(&tx->sta->lock); | ||
1186 | 1215 | ||
1187 | if (unlikely(queued)) | 1216 | queued = ieee80211_tx_prep_agg(tx, skb, info, |
1188 | return TX_QUEUED; | 1217 | tid_tx, tid); |
1218 | |||
1219 | if (unlikely(queued)) | ||
1220 | return TX_QUEUED; | ||
1221 | } | ||
1189 | } | 1222 | } |
1190 | 1223 | ||
1191 | if (is_multicast_ether_addr(hdr->addr1)) { | 1224 | if (is_multicast_ether_addr(hdr->addr1)) { |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5b79d552780a..a54cf146ed50 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1138,18 +1138,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1138 | } | 1138 | } |
1139 | mutex_unlock(&local->sta_mtx); | 1139 | mutex_unlock(&local->sta_mtx); |
1140 | 1140 | ||
1141 | /* Clear Suspend state so that ADDBA requests can be processed */ | ||
1142 | |||
1143 | rcu_read_lock(); | ||
1144 | |||
1145 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | ||
1146 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
1147 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | rcu_read_unlock(); | ||
1152 | |||
1153 | /* setup RTS threshold */ | 1141 | /* setup RTS threshold */ |
1154 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | 1142 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); |
1155 | 1143 | ||
@@ -1202,13 +1190,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1202 | } | 1190 | } |
1203 | } | 1191 | } |
1204 | 1192 | ||
1205 | rcu_read_lock(); | 1193 | /* |
1194 | * Clear the WLAN_STA_BLOCK_BA flag so new aggregation | ||
1195 | * sessions can be established after a resume. | ||
1196 | * | ||
1197 | * Also tear down aggregation sessions since reconfiguring | ||
1198 | * them in a hardware restart scenario is not easily done | ||
1199 | * right now, and the hardware will have lost information | ||
1200 | * about the sessions, but we and the AP still think they | ||
1201 | * are active. This is really a workaround though. | ||
1202 | */ | ||
1206 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 1203 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
1207 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 1204 | mutex_lock(&local->sta_mtx); |
1205 | |||
1206 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1208 | ieee80211_sta_tear_down_BA_sessions(sta); | 1207 | ieee80211_sta_tear_down_BA_sessions(sta); |
1208 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); | ||
1209 | } | 1209 | } |
1210 | |||
1211 | mutex_unlock(&local->sta_mtx); | ||
1210 | } | 1212 | } |
1211 | rcu_read_unlock(); | ||
1212 | 1213 | ||
1213 | /* add back keys */ | 1214 | /* add back keys */ |
1214 | list_for_each_entry(sdata, &local->interfaces, list) | 1215 | list_for_each_entry(sdata, &local->interfaces, list) |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 4157717ed786..c22a71c5cb45 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -715,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
715 | struct ieee80211_rx_status *rx_status; | 715 | struct ieee80211_rx_status *rx_status; |
716 | struct ieee80211_mgmt *mgmt; | 716 | struct ieee80211_mgmt *mgmt; |
717 | struct ieee80211_work *wk; | 717 | struct ieee80211_work *wk; |
718 | enum work_action rma; | 718 | enum work_action rma = WORK_ACT_NONE; |
719 | u16 fc; | 719 | u16 fc; |
720 | 720 | ||
721 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 721 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 0adbcc941ac9..a14e67707476 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -436,6 +436,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
436 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 436 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
437 | u8 pn[CCMP_PN_LEN]; | 437 | u8 pn[CCMP_PN_LEN]; |
438 | int data_len; | 438 | int data_len; |
439 | int queue; | ||
439 | 440 | ||
440 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 441 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
441 | 442 | ||
@@ -453,7 +454,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
453 | 454 | ||
454 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 455 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
455 | 456 | ||
456 | if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) { | 457 | queue = ieee80211_is_mgmt(hdr->frame_control) ? |
458 | NUM_RX_DATA_QUEUES : rx->queue; | ||
459 | |||
460 | if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { | ||
457 | key->u.ccmp.replays++; | 461 | key->u.ccmp.replays++; |
458 | return RX_DROP_UNUSABLE; | 462 | return RX_DROP_UNUSABLE; |
459 | } | 463 | } |
@@ -470,7 +474,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
470 | return RX_DROP_UNUSABLE; | 474 | return RX_DROP_UNUSABLE; |
471 | } | 475 | } |
472 | 476 | ||
473 | memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN); | 477 | memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); |
474 | 478 | ||
475 | /* Remove CCMP header and MIC */ | 479 | /* Remove CCMP header and MIC */ |
476 | skb_trim(skb, skb->len - CCMP_MIC_LEN); | 480 | skb_trim(skb, skb->len - CCMP_MIC_LEN); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index f69ae19f497f..9f95354f859f 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -846,8 +846,9 @@ int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | |||
846 | if (!wdev->current_bss || | 846 | if (!wdev->current_bss || |
847 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, | 847 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, |
848 | ETH_ALEN) != 0 || | 848 | ETH_ALEN) != 0 || |
849 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, | 849 | (wdev->iftype == NL80211_IFTYPE_STATION && |
850 | ETH_ALEN) != 0) | 850 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, |
851 | ETH_ALEN) != 0)) | ||
851 | return -ENOTCONN; | 852 | return -ENOTCONN; |
852 | } | 853 | } |
853 | 854 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3a7b8a2f2d5a..6b41d15c4a05 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3955,6 +3955,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
3955 | } | 3955 | } |
3956 | } | 3956 | } |
3957 | 3957 | ||
3958 | if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) { | ||
3959 | u8 *rates = | ||
3960 | nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
3961 | int n_rates = | ||
3962 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | ||
3963 | struct ieee80211_supported_band *sband = | ||
3964 | wiphy->bands[ibss.channel->band]; | ||
3965 | int i, j; | ||
3966 | |||
3967 | if (n_rates == 0) { | ||
3968 | err = -EINVAL; | ||
3969 | goto out; | ||
3970 | } | ||
3971 | |||
3972 | for (i = 0; i < n_rates; i++) { | ||
3973 | int rate = (rates[i] & 0x7f) * 5; | ||
3974 | bool found = false; | ||
3975 | |||
3976 | for (j = 0; j < sband->n_bitrates; j++) { | ||
3977 | if (sband->bitrates[j].bitrate == rate) { | ||
3978 | found = true; | ||
3979 | ibss.basic_rates |= BIT(j); | ||
3980 | break; | ||
3981 | } | ||
3982 | } | ||
3983 | if (!found) { | ||
3984 | err = -EINVAL; | ||
3985 | goto out; | ||
3986 | } | ||
3987 | } | ||
3988 | } else { | ||
3989 | /* | ||
3990 | * If no rates were explicitly configured, | ||
3991 | * use the mandatory rate set for 11b or | ||
3992 | * 11a for maximum compatibility. | ||
3993 | */ | ||
3994 | struct ieee80211_supported_band *sband = | ||
3995 | wiphy->bands[ibss.channel->band]; | ||
3996 | int j; | ||
3997 | u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ? | ||
3998 | IEEE80211_RATE_MANDATORY_A : | ||
3999 | IEEE80211_RATE_MANDATORY_B; | ||
4000 | |||
4001 | for (j = 0; j < sband->n_bitrates; j++) { | ||
4002 | if (sband->bitrates[j].flags & flag) | ||
4003 | ibss.basic_rates |= BIT(j); | ||
4004 | } | ||
4005 | } | ||
4006 | |||
3958 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); | 4007 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
3959 | 4008 | ||
3960 | out: | 4009 | out: |
@@ -4653,7 +4702,8 @@ static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | |||
4653 | if (err) | 4702 | if (err) |
4654 | goto unlock_rtnl; | 4703 | goto unlock_rtnl; |
4655 | 4704 | ||
4656 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4705 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4706 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | ||
4657 | err = -EOPNOTSUPP; | 4707 | err = -EOPNOTSUPP; |
4658 | goto out; | 4708 | goto out; |
4659 | } | 4709 | } |
@@ -4703,7 +4753,8 @@ static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | |||
4703 | goto out; | 4753 | goto out; |
4704 | } | 4754 | } |
4705 | 4755 | ||
4706 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | 4756 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
4757 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC) { | ||
4707 | err = -EOPNOTSUPP; | 4758 | err = -EOPNOTSUPP; |
4708 | goto out; | 4759 | goto out; |
4709 | } | 4760 | } |