diff options
102 files changed, 3660 insertions, 2377 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9d12977b6baf..424887b4a414 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5127,6 +5127,7 @@ RALINK RT2X00 WIRELESS LAN DRIVER | |||
5127 | P: rt2x00 project | 5127 | P: rt2x00 project |
5128 | M: Ivo van Doorn <IvDoorn@gmail.com> | 5128 | M: Ivo van Doorn <IvDoorn@gmail.com> |
5129 | M: Gertjan van Wingerde <gwingerde@gmail.com> | 5129 | M: Gertjan van Wingerde <gwingerde@gmail.com> |
5130 | M: Helmut Schaa <helmut.schaa@googlemail.com> | ||
5130 | L: linux-wireless@vger.kernel.org | 5131 | L: linux-wireless@vger.kernel.org |
5131 | L: users@rt2x00.serialmonkey.com (moderated for non-subscribers) | 5132 | L: users@rt2x00.serialmonkey.com (moderated for non-subscribers) |
5132 | W: http://rt2x00.serialmonkey.com/ | 5133 | W: http://rt2x00.serialmonkey.com/ |
@@ -6767,12 +6768,12 @@ S: Maintained | |||
6767 | F: drivers/net/wireless/wl1251/* | 6768 | F: drivers/net/wireless/wl1251/* |
6768 | 6769 | ||
6769 | WL1271 WIRELESS DRIVER | 6770 | WL1271 WIRELESS DRIVER |
6770 | M: Luciano Coelho <luciano.coelho@nokia.com> | 6771 | M: Luciano Coelho <coelho@ti.com> |
6771 | L: linux-wireless@vger.kernel.org | 6772 | L: linux-wireless@vger.kernel.org |
6772 | W: http://wireless.kernel.org | 6773 | W: http://wireless.kernel.org/en/users/Drivers/wl12xx |
6773 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git | 6774 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git |
6774 | S: Maintained | 6775 | S: Maintained |
6775 | F: drivers/net/wireless/wl12xx/wl1271* | 6776 | F: drivers/net/wireless/wl12xx/ |
6776 | F: include/linux/wl12xx.h | 6777 | F: include/linux/wl12xx.h |
6777 | 6778 | ||
6778 | WL3501 WIRELESS PCMCIA CARD DRIVER | 6779 | WL3501 WIRELESS PCMCIA CARD DRIVER |
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index e0793319389d..e18a9aa7b6ca 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig | |||
@@ -40,6 +40,17 @@ config ATH5K_DEBUG | |||
40 | 40 | ||
41 | modprobe ath5k debug=0x00000400 | 41 | modprobe ath5k debug=0x00000400 |
42 | 42 | ||
43 | config ATH5K_TRACER | ||
44 | bool "Atheros 5xxx tracer" | ||
45 | depends on ATH5K | ||
46 | depends on EVENT_TRACING | ||
47 | ---help--- | ||
48 | Say Y here to enable tracepoints for the ath5k driver | ||
49 | using the kernel tracing infrastructure. Select this | ||
50 | option if you are interested in debugging the driver. | ||
51 | |||
52 | If unsure, say N. | ||
53 | |||
43 | config ATH5K_AHB | 54 | config ATH5K_AHB |
44 | bool "Atheros 5xxx AHB bus support" | 55 | bool "Atheros 5xxx AHB bus support" |
45 | depends on (ATHEROS_AR231X && !PCI) | 56 | depends on (ATHEROS_AR231X && !PCI) |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 407e39c2b10b..e43175a89d67 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -210,14 +210,9 @@ | |||
210 | /* Initial values */ | 210 | /* Initial values */ |
211 | #define AR5K_INIT_CYCRSSI_THR1 2 | 211 | #define AR5K_INIT_CYCRSSI_THR1 2 |
212 | 212 | ||
213 | /* Tx retry limits */ | 213 | /* Tx retry limit defaults from standard */ |
214 | #define AR5K_INIT_SH_RETRY 10 | 214 | #define AR5K_INIT_RETRY_SHORT 7 |
215 | #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY | 215 | #define AR5K_INIT_RETRY_LONG 4 |
216 | /* For station mode */ | ||
217 | #define AR5K_INIT_SSH_RETRY 32 | ||
218 | #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY | ||
219 | #define AR5K_INIT_TX_RETRY 10 | ||
220 | |||
221 | 216 | ||
222 | /* Slot time */ | 217 | /* Slot time */ |
223 | #define AR5K_INIT_SLOT_TIME_TURBO 6 | 218 | #define AR5K_INIT_SLOT_TIME_TURBO 6 |
@@ -1057,7 +1052,9 @@ struct ath5k_hw { | |||
1057 | #define ah_modes ah_capabilities.cap_mode | 1052 | #define ah_modes ah_capabilities.cap_mode |
1058 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version | 1053 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version |
1059 | 1054 | ||
1060 | u32 ah_limit_tx_retries; | 1055 | u8 ah_retry_long; |
1056 | u8 ah_retry_short; | ||
1057 | |||
1061 | u8 ah_coverage_class; | 1058 | u8 ah_coverage_class; |
1062 | bool ah_ack_bitrate_high; | 1059 | bool ah_ack_bitrate_high; |
1063 | u8 ah_bwmode; | 1060 | u8 ah_bwmode; |
@@ -1067,7 +1064,6 @@ struct ath5k_hw { | |||
1067 | u8 ah_ant_mode; | 1064 | u8 ah_ant_mode; |
1068 | u8 ah_tx_ant; | 1065 | u8 ah_tx_ant; |
1069 | u8 ah_def_ant; | 1066 | u8 ah_def_ant; |
1070 | bool ah_software_retry; | ||
1071 | 1067 | ||
1072 | struct ath5k_capabilities ah_capabilities; | 1068 | struct ath5k_capabilities ah_capabilities; |
1073 | 1069 | ||
@@ -1250,6 +1246,8 @@ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
1250 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, | 1246 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, |
1251 | enum ath5k_tx_queue queue_type, | 1247 | enum ath5k_tx_queue queue_type, |
1252 | struct ath5k_txq_info *queue_info); | 1248 | struct ath5k_txq_info *queue_info); |
1249 | void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | ||
1250 | unsigned int queue); | ||
1253 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | 1251 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); |
1254 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1252 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1255 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1253 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index cdac5cff0177..c71fdbb4c439 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -118,8 +118,8 @@ int ath5k_hw_init(struct ath5k_softc *sc) | |||
118 | ah->ah_bwmode = AR5K_BWMODE_DEFAULT; | 118 | ah->ah_bwmode = AR5K_BWMODE_DEFAULT; |
119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; |
120 | ah->ah_imr = 0; | 120 | ah->ah_imr = 0; |
121 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 121 | ah->ah_retry_short = AR5K_INIT_RETRY_SHORT; |
122 | ah->ah_software_retry = false; | 122 | ah->ah_retry_long = AR5K_INIT_RETRY_LONG; |
123 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | 123 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; |
124 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ | 124 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ |
125 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; | 125 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index dae0bdcef257..dbc45e085434 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -61,6 +61,9 @@ | |||
61 | #include "debug.h" | 61 | #include "debug.h" |
62 | #include "ani.h" | 62 | #include "ani.h" |
63 | 63 | ||
64 | #define CREATE_TRACE_POINTS | ||
65 | #include "trace.h" | ||
66 | |||
64 | int ath5k_modparam_nohwcrypt; | 67 | int ath5k_modparam_nohwcrypt; |
65 | module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); | 68 | module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); |
66 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 69 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -1379,7 +1382,7 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1379 | sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short) | 1382 | sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short) |
1380 | rxs->flag |= RX_FLAG_SHORTPRE; | 1383 | rxs->flag |= RX_FLAG_SHORTPRE; |
1381 | 1384 | ||
1382 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 1385 | trace_ath5k_rx(sc, skb); |
1383 | 1386 | ||
1384 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); | 1387 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); |
1385 | 1388 | ||
@@ -1524,7 +1527,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1524 | unsigned long flags; | 1527 | unsigned long flags; |
1525 | int padsize; | 1528 | int padsize; |
1526 | 1529 | ||
1527 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 1530 | trace_ath5k_tx(sc, skb, txq); |
1528 | 1531 | ||
1529 | /* | 1532 | /* |
1530 | * The hardware expects the header padded to 4 byte boundaries. | 1533 | * The hardware expects the header padded to 4 byte boundaries. |
@@ -1573,7 +1576,7 @@ drop_packet: | |||
1573 | 1576 | ||
1574 | static void | 1577 | static void |
1575 | ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | 1578 | ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, |
1576 | struct ath5k_tx_status *ts) | 1579 | struct ath5k_txq *txq, struct ath5k_tx_status *ts) |
1577 | { | 1580 | { |
1578 | struct ieee80211_tx_info *info; | 1581 | struct ieee80211_tx_info *info; |
1579 | int i; | 1582 | int i; |
@@ -1625,6 +1628,7 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1625 | else | 1628 | else |
1626 | sc->stats.antenna_tx[0]++; /* invalid */ | 1629 | sc->stats.antenna_tx[0]++; /* invalid */ |
1627 | 1630 | ||
1631 | trace_ath5k_tx_complete(sc, skb, txq, ts); | ||
1628 | ieee80211_tx_status(sc->hw, skb); | 1632 | ieee80211_tx_status(sc->hw, skb); |
1629 | } | 1633 | } |
1630 | 1634 | ||
@@ -1661,7 +1665,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1661 | 1665 | ||
1662 | dma_unmap_single(sc->dev, bf->skbaddr, skb->len, | 1666 | dma_unmap_single(sc->dev, bf->skbaddr, skb->len, |
1663 | DMA_TO_DEVICE); | 1667 | DMA_TO_DEVICE); |
1664 | ath5k_tx_frame_completed(sc, skb, &ts); | 1668 | ath5k_tx_frame_completed(sc, skb, txq, &ts); |
1665 | } | 1669 | } |
1666 | 1670 | ||
1667 | /* | 1671 | /* |
@@ -1803,8 +1807,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1803 | goto out; | 1807 | goto out; |
1804 | } | 1808 | } |
1805 | 1809 | ||
1806 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | ||
1807 | |||
1808 | ath5k_txbuf_free_skb(sc, avf->bbuf); | 1810 | ath5k_txbuf_free_skb(sc, avf->bbuf); |
1809 | avf->bbuf->skb = skb; | 1811 | avf->bbuf->skb = skb; |
1810 | ret = ath5k_beacon_setup(sc, avf->bbuf); | 1812 | ret = ath5k_beacon_setup(sc, avf->bbuf); |
@@ -1899,6 +1901,8 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
1899 | sc->opmode == NL80211_IFTYPE_MESH_POINT) | 1901 | sc->opmode == NL80211_IFTYPE_MESH_POINT) |
1900 | ath5k_beacon_update(sc->hw, vif); | 1902 | ath5k_beacon_update(sc->hw, vif); |
1901 | 1903 | ||
1904 | trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]); | ||
1905 | |||
1902 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); | 1906 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); |
1903 | ath5k_hw_start_tx_dma(ah, sc->bhalq); | 1907 | ath5k_hw_start_tx_dma(ah, sc->bhalq); |
1904 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", | 1908 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", |
@@ -2399,7 +2403,8 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) | |||
2399 | /* set up multi-rate retry capabilities */ | 2403 | /* set up multi-rate retry capabilities */ |
2400 | if (sc->ah->ah_version == AR5K_AR5212) { | 2404 | if (sc->ah->ah_version == AR5K_AR5212) { |
2401 | hw->max_rates = 4; | 2405 | hw->max_rates = 4; |
2402 | hw->max_rate_tries = 11; | 2406 | hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, |
2407 | AR5K_INIT_RETRY_LONG); | ||
2403 | } | 2408 | } |
2404 | 2409 | ||
2405 | hw->vif_data_size = sizeof(struct ath5k_vif); | 2410 | hw->vif_data_size = sizeof(struct ath5k_vif); |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 31cad80e9b01..f77e8a703c5c 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -32,23 +32,24 @@ | |||
32 | */ | 32 | */ |
33 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | 33 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah) |
34 | { | 34 | { |
35 | struct ath5k_capabilities *caps = &ah->ah_capabilities; | ||
35 | u16 ee_header; | 36 | u16 ee_header; |
36 | 37 | ||
37 | /* Capabilities stored in the EEPROM */ | 38 | /* Capabilities stored in the EEPROM */ |
38 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | 39 | ee_header = caps->cap_eeprom.ee_header; |
39 | 40 | ||
40 | if (ah->ah_version == AR5K_AR5210) { | 41 | if (ah->ah_version == AR5K_AR5210) { |
41 | /* | 42 | /* |
42 | * Set radio capabilities | 43 | * Set radio capabilities |
43 | * (The AR5110 only supports the middle 5GHz band) | 44 | * (The AR5110 only supports the middle 5GHz band) |
44 | */ | 45 | */ |
45 | ah->ah_capabilities.cap_range.range_5ghz_min = 5120; | 46 | caps->cap_range.range_5ghz_min = 5120; |
46 | ah->ah_capabilities.cap_range.range_5ghz_max = 5430; | 47 | caps->cap_range.range_5ghz_max = 5430; |
47 | ah->ah_capabilities.cap_range.range_2ghz_min = 0; | 48 | caps->cap_range.range_2ghz_min = 0; |
48 | ah->ah_capabilities.cap_range.range_2ghz_max = 0; | 49 | caps->cap_range.range_2ghz_max = 0; |
49 | 50 | ||
50 | /* Set supported modes */ | 51 | /* Set supported modes */ |
51 | __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); | 52 | __set_bit(AR5K_MODE_11A, caps->cap_mode); |
52 | } else { | 53 | } else { |
53 | /* | 54 | /* |
54 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz | 55 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz |
@@ -56,9 +57,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
56 | * XXX current ieee80211 implementation because the IEEE | 57 | * XXX current ieee80211 implementation because the IEEE |
57 | * XXX channel mapping does not support negative channel | 58 | * XXX channel mapping does not support negative channel |
58 | * XXX numbers (2312MHz is channel -19). Of course, this | 59 | * XXX numbers (2312MHz is channel -19). Of course, this |
59 | * XXX doesn't matter because these channels are out of range | 60 | * XXX doesn't matter because these channels are out of the |
60 | * XXX but some regulation domains like MKK (Japan) will | 61 | * XXX legal range. |
61 | * XXX support frequencies somewhere around 4.8GHz. | ||
62 | */ | 62 | */ |
63 | 63 | ||
64 | /* | 64 | /* |
@@ -66,13 +66,14 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
66 | */ | 66 | */ |
67 | 67 | ||
68 | if (AR5K_EEPROM_HDR_11A(ee_header)) { | 68 | if (AR5K_EEPROM_HDR_11A(ee_header)) { |
69 | /* 4920 */ | 69 | if (ath_is_49ghz_allowed(caps->cap_eeprom.ee_regdomain)) |
70 | ah->ah_capabilities.cap_range.range_5ghz_min = 5005; | 70 | caps->cap_range.range_5ghz_min = 4920; |
71 | ah->ah_capabilities.cap_range.range_5ghz_max = 6100; | 71 | else |
72 | caps->cap_range.range_5ghz_min = 5005; | ||
73 | caps->cap_range.range_5ghz_max = 6100; | ||
72 | 74 | ||
73 | /* Set supported modes */ | 75 | /* Set supported modes */ |
74 | __set_bit(AR5K_MODE_11A, | 76 | __set_bit(AR5K_MODE_11A, caps->cap_mode); |
75 | ah->ah_capabilities.cap_mode); | ||
76 | } | 77 | } |
77 | 78 | ||
78 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | 79 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is |
@@ -81,32 +82,29 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
81 | (AR5K_EEPROM_HDR_11G(ee_header) && | 82 | (AR5K_EEPROM_HDR_11G(ee_header) && |
82 | ah->ah_version != AR5K_AR5211)) { | 83 | ah->ah_version != AR5K_AR5211)) { |
83 | /* 2312 */ | 84 | /* 2312 */ |
84 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; | 85 | caps->cap_range.range_2ghz_min = 2412; |
85 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | 86 | caps->cap_range.range_2ghz_max = 2732; |
86 | 87 | ||
87 | if (AR5K_EEPROM_HDR_11B(ee_header)) | 88 | if (AR5K_EEPROM_HDR_11B(ee_header)) |
88 | __set_bit(AR5K_MODE_11B, | 89 | __set_bit(AR5K_MODE_11B, caps->cap_mode); |
89 | ah->ah_capabilities.cap_mode); | ||
90 | 90 | ||
91 | if (AR5K_EEPROM_HDR_11G(ee_header) && | 91 | if (AR5K_EEPROM_HDR_11G(ee_header) && |
92 | ah->ah_version != AR5K_AR5211) | 92 | ah->ah_version != AR5K_AR5211) |
93 | __set_bit(AR5K_MODE_11G, | 93 | __set_bit(AR5K_MODE_11G, caps->cap_mode); |
94 | ah->ah_capabilities.cap_mode); | ||
95 | } | 94 | } |
96 | } | 95 | } |
97 | 96 | ||
98 | /* Set number of supported TX queues */ | 97 | /* Set number of supported TX queues */ |
99 | if (ah->ah_version == AR5K_AR5210) | 98 | if (ah->ah_version == AR5K_AR5210) |
100 | ah->ah_capabilities.cap_queues.q_tx_num = | 99 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; |
101 | AR5K_NUM_TX_QUEUES_NOQCU; | ||
102 | else | 100 | else |
103 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 101 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
104 | 102 | ||
105 | /* newer hardware has PHY error counters */ | 103 | /* newer hardware has PHY error counters */ |
106 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | 104 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) |
107 | ah->ah_capabilities.cap_has_phyerr_counters = true; | 105 | caps->cap_has_phyerr_counters = true; |
108 | else | 106 | else |
109 | ah->ah_capabilities.cap_has_phyerr_counters = false; | 107 | caps->cap_has_phyerr_counters = false; |
110 | 108 | ||
111 | return 0; | 109 | return 0; |
112 | } | 110 | } |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index d2f84d76bb07..0230f30e9e9a 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -308,8 +308,6 @@ static const struct { | |||
308 | { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, | 308 | { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, |
309 | { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, | 309 | { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, |
310 | { ATH5K_DEBUG_LED, "led", "LED management" }, | 310 | { ATH5K_DEBUG_LED, "led", "LED management" }, |
311 | { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, | ||
312 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | ||
313 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 311 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
314 | { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, | 312 | { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, |
315 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | 313 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, |
@@ -1036,24 +1034,6 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
1036 | } | 1034 | } |
1037 | 1035 | ||
1038 | void | 1036 | void |
1039 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
1040 | struct sk_buff *skb, const char *prefix, int tx) | ||
1041 | { | ||
1042 | char buf[16]; | ||
1043 | |||
1044 | if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || | ||
1045 | (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) | ||
1046 | return; | ||
1047 | |||
1048 | snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); | ||
1049 | |||
1050 | print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, | ||
1051 | min(200U, skb->len)); | ||
1052 | |||
1053 | printk(KERN_DEBUG "\n"); | ||
1054 | } | ||
1055 | |||
1056 | void | ||
1057 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) | 1037 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) |
1058 | { | 1038 | { |
1059 | struct ath5k_desc *ds = bf->desc; | 1039 | struct ath5k_desc *ds = bf->desc; |
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 3e34428d5126..b0355aef68d3 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -116,8 +116,6 @@ enum ath5k_debug_level { | |||
116 | ATH5K_DEBUG_CALIBRATE = 0x00000020, | 116 | ATH5K_DEBUG_CALIBRATE = 0x00000020, |
117 | ATH5K_DEBUG_TXPOWER = 0x00000040, | 117 | ATH5K_DEBUG_TXPOWER = 0x00000040, |
118 | ATH5K_DEBUG_LED = 0x00000080, | 118 | ATH5K_DEBUG_LED = 0x00000080, |
119 | ATH5K_DEBUG_DUMP_RX = 0x00000100, | ||
120 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | ||
121 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 119 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
122 | ATH5K_DEBUG_DMA = 0x00000800, | 120 | ATH5K_DEBUG_DMA = 0x00000800, |
123 | ATH5K_DEBUG_ANI = 0x00002000, | 121 | ATH5K_DEBUG_ANI = 0x00002000, |
@@ -152,10 +150,6 @@ void | |||
152 | ath5k_debug_dump_bands(struct ath5k_softc *sc); | 150 | ath5k_debug_dump_bands(struct ath5k_softc *sc); |
153 | 151 | ||
154 | void | 152 | void |
155 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
156 | struct sk_buff *skb, const char *prefix, int tx); | ||
157 | |||
158 | void | ||
159 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); | 153 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); |
160 | 154 | ||
161 | #else /* no debugging */ | 155 | #else /* no debugging */ |
@@ -182,10 +176,6 @@ static inline void | |||
182 | ath5k_debug_dump_bands(struct ath5k_softc *sc) {} | 176 | ath5k_debug_dump_bands(struct ath5k_softc *sc) {} |
183 | 177 | ||
184 | static inline void | 178 | static inline void |
185 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
186 | struct sk_buff *skb, const char *prefix, int tx) {} | ||
187 | |||
188 | static inline void | ||
189 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} | 179 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} |
190 | 180 | ||
191 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ | 181 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 0064be7ce5c9..21091c26a9a5 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -838,9 +838,9 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah) | |||
838 | for (i = 0; i < qmax; i++) { | 838 | for (i = 0; i < qmax; i++) { |
839 | err = ath5k_hw_stop_tx_dma(ah, i); | 839 | err = ath5k_hw_stop_tx_dma(ah, i); |
840 | /* -EINVAL -> queue inactive */ | 840 | /* -EINVAL -> queue inactive */ |
841 | if (err != -EINVAL) | 841 | if (err && err != -EINVAL) |
842 | return err; | 842 | return err; |
843 | } | 843 | } |
844 | 844 | ||
845 | return err; | 845 | return 0; |
846 | } | 846 | } |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index d76d68c99f72..36a51995a7bc 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -226,6 +226,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
226 | struct ath5k_hw *ah = sc->ah; | 226 | struct ath5k_hw *ah = sc->ah; |
227 | struct ieee80211_conf *conf = &hw->conf; | 227 | struct ieee80211_conf *conf = &hw->conf; |
228 | int ret = 0; | 228 | int ret = 0; |
229 | int i; | ||
229 | 230 | ||
230 | mutex_lock(&sc->lock); | 231 | mutex_lock(&sc->lock); |
231 | 232 | ||
@@ -243,6 +244,14 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
243 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); | 244 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); |
244 | } | 245 | } |
245 | 246 | ||
247 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { | ||
248 | ah->ah_retry_long = conf->long_frame_max_tx_count; | ||
249 | ah->ah_retry_short = conf->short_frame_max_tx_count; | ||
250 | |||
251 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) | ||
252 | ath5k_hw_set_tx_retry_limits(ah, i); | ||
253 | } | ||
254 | |||
246 | /* TODO: | 255 | /* TODO: |
247 | * 1) Move this on config_interface and handle each case | 256 | * 1) Move this on config_interface and handle each case |
248 | * separately eg. when we have only one STA vif, use | 257 | * separately eg. when we have only one STA vif, use |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index e5f2b96a4c63..a702817daf72 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -86,7 +86,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | |||
86 | if (!ah->ah_bwmode) { | 86 | if (!ah->ah_bwmode) { |
87 | dur = ieee80211_generic_frame_duration(sc->hw, | 87 | dur = ieee80211_generic_frame_duration(sc->hw, |
88 | NULL, len, rate); | 88 | NULL, len, rate); |
89 | return dur; | 89 | return le16_to_cpu(dur); |
90 | } | 90 | } |
91 | 91 | ||
92 | bitrate = rate->bitrate; | 92 | bitrate = rate->bitrate; |
@@ -265,8 +265,6 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | |||
265 | * what rate we should choose to TX ACKs. */ | 265 | * what rate we should choose to TX ACKs. */ |
266 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); | 266 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); |
267 | 267 | ||
268 | tx_time = le16_to_cpu(tx_time); | ||
269 | |||
270 | ath5k_hw_reg_write(ah, tx_time, reg); | 268 | ath5k_hw_reg_write(ah, tx_time, reg); |
271 | 269 | ||
272 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | 270 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 2c9c9e793d4e..3343fb9e4940 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -228,24 +228,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
228 | /* | 228 | /* |
229 | * Set tx retry limits on DCU | 229 | * Set tx retry limits on DCU |
230 | */ | 230 | */ |
231 | static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | 231 | void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, |
232 | unsigned int queue) | 232 | unsigned int queue) |
233 | { | 233 | { |
234 | u32 retry_lg, retry_sh; | ||
235 | |||
236 | /* | ||
237 | * Calculate and set retry limits | ||
238 | */ | ||
239 | if (ah->ah_software_retry) { | ||
240 | /* XXX Need to test this */ | ||
241 | retry_lg = ah->ah_limit_tx_retries; | ||
242 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? | ||
243 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; | ||
244 | } else { | ||
245 | retry_lg = AR5K_INIT_LG_RETRY; | ||
246 | retry_sh = AR5K_INIT_SH_RETRY; | ||
247 | } | ||
248 | |||
249 | /* Single data queue on AR5210 */ | 234 | /* Single data queue on AR5210 */ |
250 | if (ah->ah_version == AR5K_AR5210) { | 235 | if (ah->ah_version == AR5K_AR5210) { |
251 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 236 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
@@ -255,25 +240,26 @@ static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | |||
255 | 240 | ||
256 | ath5k_hw_reg_write(ah, | 241 | ath5k_hw_reg_write(ah, |
257 | (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | 242 | (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) |
258 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | 243 | | AR5K_REG_SM(ah->ah_retry_long, |
259 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | 244 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) |
260 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | 245 | | AR5K_REG_SM(ah->ah_retry_short, |
261 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | 246 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) |
262 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | 247 | | AR5K_REG_SM(ah->ah_retry_long, |
263 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), | 248 | AR5K_NODCU_RETRY_LMT_LG_RETRY) |
249 | | AR5K_REG_SM(ah->ah_retry_short, | ||
250 | AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
264 | AR5K_NODCU_RETRY_LMT); | 251 | AR5K_NODCU_RETRY_LMT); |
265 | /* DCU on AR5211+ */ | 252 | /* DCU on AR5211+ */ |
266 | } else { | 253 | } else { |
267 | ath5k_hw_reg_write(ah, | 254 | ath5k_hw_reg_write(ah, |
268 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | 255 | AR5K_REG_SM(ah->ah_retry_long, |
269 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | | 256 | AR5K_DCU_RETRY_LMT_RTS) |
270 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | 257 | | AR5K_REG_SM(ah->ah_retry_long, |
271 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | | 258 | AR5K_DCU_RETRY_LMT_STA_RTS) |
272 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | | 259 | | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short), |
273 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), | 260 | AR5K_DCU_RETRY_LMT_STA_DATA), |
274 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | 261 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); |
275 | } | 262 | } |
276 | return; | ||
277 | } | 263 | } |
278 | 264 | ||
279 | /** | 265 | /** |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index fd14b9103951..e1c9abd8c879 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -686,16 +686,15 @@ | |||
686 | 686 | ||
687 | /* | 687 | /* |
688 | * DCU retry limit registers | 688 | * DCU retry limit registers |
689 | * all these fields don't allow zero values | ||
689 | */ | 690 | */ |
690 | #define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ | 691 | #define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ |
691 | #define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ | 692 | #define AR5K_DCU_RETRY_LMT_RTS 0x0000000f /* RTS failure limit. Transmission fails if no CTS is received for this number of times */ |
692 | #define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 | 693 | #define AR5K_DCU_RETRY_LMT_RTS_S 0 |
693 | #define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ | 694 | #define AR5K_DCU_RETRY_LMT_STA_RTS 0x00003f00 /* STA RTS failure limit. If exceeded CW reset */ |
694 | #define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 | 695 | #define AR5K_DCU_RETRY_LMT_STA_RTS_S 8 |
695 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ | 696 | #define AR5K_DCU_RETRY_LMT_STA_DATA 0x000fc000 /* STA data failure limit. If exceeded CW reset. */ |
696 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 | 697 | #define AR5K_DCU_RETRY_LMT_STA_DATA_S 14 |
697 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ | ||
698 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 | ||
699 | #define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) | 698 | #define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) |
700 | 699 | ||
701 | /* | 700 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h new file mode 100644 index 000000000000..2de68adb6240 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/trace.h | |||
@@ -0,0 +1,107 @@ | |||
1 | #if !defined(__TRACE_ATH5K_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __TRACE_ATH5K_H | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | #include "base.h" | ||
6 | |||
7 | #ifndef CONFIG_ATH5K_TRACER | ||
8 | #undef TRACE_EVENT | ||
9 | #define TRACE_EVENT(name, proto, ...) \ | ||
10 | static inline void trace_ ## name(proto) {} | ||
11 | #endif | ||
12 | |||
13 | struct sk_buff; | ||
14 | |||
15 | #define PRIV_ENTRY __field(struct ath5k_softc *, priv) | ||
16 | #define PRIV_ASSIGN __entry->priv = priv | ||
17 | |||
18 | #undef TRACE_SYSTEM | ||
19 | #define TRACE_SYSTEM ath5k | ||
20 | |||
21 | TRACE_EVENT(ath5k_rx, | ||
22 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb), | ||
23 | TP_ARGS(priv, skb), | ||
24 | TP_STRUCT__entry( | ||
25 | PRIV_ENTRY | ||
26 | __field(unsigned long, skbaddr) | ||
27 | __dynamic_array(u8, frame, skb->len) | ||
28 | ), | ||
29 | TP_fast_assign( | ||
30 | PRIV_ASSIGN; | ||
31 | __entry->skbaddr = (unsigned long) skb; | ||
32 | memcpy(__get_dynamic_array(frame), skb->data, skb->len); | ||
33 | ), | ||
34 | TP_printk( | ||
35 | "[%p] RX skb=%lx", __entry->priv, __entry->skbaddr | ||
36 | ) | ||
37 | ); | ||
38 | |||
39 | TRACE_EVENT(ath5k_tx, | ||
40 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, | ||
41 | struct ath5k_txq *q), | ||
42 | |||
43 | TP_ARGS(priv, skb, q), | ||
44 | |||
45 | TP_STRUCT__entry( | ||
46 | PRIV_ENTRY | ||
47 | __field(unsigned long, skbaddr) | ||
48 | __field(u8, qnum) | ||
49 | __dynamic_array(u8, frame, skb->len) | ||
50 | ), | ||
51 | |||
52 | TP_fast_assign( | ||
53 | PRIV_ASSIGN; | ||
54 | __entry->skbaddr = (unsigned long) skb; | ||
55 | __entry->qnum = (u8) q->qnum; | ||
56 | memcpy(__get_dynamic_array(frame), skb->data, skb->len); | ||
57 | ), | ||
58 | |||
59 | TP_printk( | ||
60 | "[%p] TX skb=%lx q=%d", __entry->priv, __entry->skbaddr, | ||
61 | __entry->qnum | ||
62 | ) | ||
63 | ); | ||
64 | |||
65 | TRACE_EVENT(ath5k_tx_complete, | ||
66 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, | ||
67 | struct ath5k_txq *q, struct ath5k_tx_status *ts), | ||
68 | |||
69 | TP_ARGS(priv, skb, q, ts), | ||
70 | |||
71 | TP_STRUCT__entry( | ||
72 | PRIV_ENTRY | ||
73 | __field(unsigned long, skbaddr) | ||
74 | __field(u8, qnum) | ||
75 | __field(u8, ts_status) | ||
76 | __field(s8, ts_rssi) | ||
77 | __field(u8, ts_antenna) | ||
78 | ), | ||
79 | |||
80 | TP_fast_assign( | ||
81 | PRIV_ASSIGN; | ||
82 | __entry->skbaddr = (unsigned long) skb; | ||
83 | __entry->qnum = (u8) q->qnum; | ||
84 | __entry->ts_status = ts->ts_status; | ||
85 | __entry->ts_rssi = ts->ts_rssi; | ||
86 | __entry->ts_antenna = ts->ts_antenna; | ||
87 | ), | ||
88 | |||
89 | TP_printk( | ||
90 | "[%p] TX end skb=%lx q=%d stat=%x rssi=%d ant=%x", | ||
91 | __entry->priv, __entry->skbaddr, __entry->qnum, | ||
92 | __entry->ts_status, __entry->ts_rssi, __entry->ts_antenna | ||
93 | ) | ||
94 | ); | ||
95 | |||
96 | #endif /* __TRACE_ATH5K_H */ | ||
97 | |||
98 | #ifdef CONFIG_ATH5K_TRACER | ||
99 | |||
100 | #undef TRACE_INCLUDE_PATH | ||
101 | #define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k | ||
102 | #undef TRACE_INCLUDE_FILE | ||
103 | #define TRACE_INCLUDE_FILE trace | ||
104 | |||
105 | #include <trace/define_trace.h> | ||
106 | |||
107 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index aca01621c205..4d66ca8042eb 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -4,7 +4,6 @@ ath9k-y += beacon.o \ | |||
4 | main.o \ | 4 | main.o \ |
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | virtual.o \ | ||
8 | 7 | ||
9 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | 8 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
10 | ath9k-$(CONFIG_PCI) += pci.o | 9 | ath9k-$(CONFIG_PCI) += pci.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 25a6e4417cdb..993672105963 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -54,7 +54,6 @@ static struct ath_bus_ops ath_ahb_bus_ops = { | |||
54 | static int ath_ahb_probe(struct platform_device *pdev) | 54 | static int ath_ahb_probe(struct platform_device *pdev) |
55 | { | 55 | { |
56 | void __iomem *mem; | 56 | void __iomem *mem; |
57 | struct ath_wiphy *aphy; | ||
58 | struct ath_softc *sc; | 57 | struct ath_softc *sc; |
59 | struct ieee80211_hw *hw; | 58 | struct ieee80211_hw *hw; |
60 | struct resource *res; | 59 | struct resource *res; |
@@ -92,8 +91,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
92 | 91 | ||
93 | irq = res->start; | 92 | irq = res->start; |
94 | 93 | ||
95 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 94 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
96 | sizeof(struct ath_softc), &ath9k_ops); | ||
97 | if (hw == NULL) { | 95 | if (hw == NULL) { |
98 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | 96 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); |
99 | ret = -ENOMEM; | 97 | ret = -ENOMEM; |
@@ -103,11 +101,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
103 | SET_IEEE80211_DEV(hw, &pdev->dev); | 101 | SET_IEEE80211_DEV(hw, &pdev->dev); |
104 | platform_set_drvdata(pdev, hw); | 102 | platform_set_drvdata(pdev, hw); |
105 | 103 | ||
106 | aphy = hw->priv; | 104 | sc = hw->priv; |
107 | sc = (struct ath_softc *) (aphy + 1); | ||
108 | aphy->sc = sc; | ||
109 | aphy->hw = hw; | ||
110 | sc->pri_wiphy = aphy; | ||
111 | sc->hw = hw; | 105 | sc->hw = hw; |
112 | sc->dev = &pdev->dev; | 106 | sc->dev = &pdev->dev; |
113 | sc->mem = mem; | 107 | sc->mem = mem; |
@@ -151,8 +145,7 @@ static int ath_ahb_remove(struct platform_device *pdev) | |||
151 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | 145 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); |
152 | 146 | ||
153 | if (hw) { | 147 | if (hw) { |
154 | struct ath_wiphy *aphy = hw->priv; | 148 | struct ath_softc *sc = hw->priv; |
155 | struct ath_softc *sc = aphy->sc; | ||
156 | void __iomem *mem = sc->mem; | 149 | void __iomem *mem = sc->mem; |
157 | 150 | ||
158 | ath9k_deinit_device(sc); | 151 | ath9k_deinit_device(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f8a7771faee2..f44c84ab5dce 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -426,9 +426,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
426 | } | 426 | } |
427 | 427 | ||
428 | /* WAR for ASPM system hang */ | 428 | /* WAR for ASPM system hang */ |
429 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | 429 | if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) |
430 | val |= (AR_WA_BIT6 | AR_WA_BIT7); | 430 | val |= (AR_WA_BIT6 | AR_WA_BIT7); |
431 | } | ||
432 | 431 | ||
433 | if (AR_SREV_9285E_20(ah)) | 432 | if (AR_SREV_9285E_20(ah)) |
434 | val |= AR_WA_BIT23; | 433 | val |= AR_WA_BIT23; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a25655640f48..4a9271802991 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3673,7 +3673,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) | |||
3673 | return; | 3673 | return; |
3674 | 3674 | ||
3675 | reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) | | 3675 | reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) | |
3676 | (7 << 14) | (6 << 17) | (1 << 20) | | 3676 | (2 << 14) | (6 << 17) | (1 << 20) | |
3677 | (3 << 24) | (1 << 28); | 3677 | (3 << 24) | (1 << 28); |
3678 | 3678 | ||
3679 | REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set); | 3679 | REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 6636f3c6dcf9..bd85e311c51b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -233,7 +233,6 @@ struct ath_buf { | |||
233 | bool bf_stale; | 233 | bool bf_stale; |
234 | u16 bf_flags; | 234 | u16 bf_flags; |
235 | struct ath_buf_state bf_state; | 235 | struct ath_buf_state bf_state; |
236 | struct ath_wiphy *aphy; | ||
237 | }; | 236 | }; |
238 | 237 | ||
239 | struct ath_atx_tid { | 238 | struct ath_atx_tid { |
@@ -311,6 +310,8 @@ struct ath_rx { | |||
311 | struct ath_descdma rxdma; | 310 | struct ath_descdma rxdma; |
312 | struct ath_buf *rx_bufptr; | 311 | struct ath_buf *rx_bufptr; |
313 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 312 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
313 | |||
314 | struct sk_buff *frag; | ||
314 | }; | 315 | }; |
315 | 316 | ||
316 | int ath_startrecv(struct ath_softc *sc); | 317 | int ath_startrecv(struct ath_softc *sc); |
@@ -388,7 +389,6 @@ struct ath_beacon { | |||
388 | u32 ast_be_xmit; | 389 | u32 ast_be_xmit; |
389 | u64 bc_tstamp; | 390 | u64 bc_tstamp; |
390 | struct ieee80211_vif *bslot[ATH_BCBUF]; | 391 | struct ieee80211_vif *bslot[ATH_BCBUF]; |
391 | struct ath_wiphy *bslot_aphy[ATH_BCBUF]; | ||
392 | int slottime; | 392 | int slottime; |
393 | int slotupdate; | 393 | int slotupdate; |
394 | struct ath9k_tx_queue_info beacon_qi; | 394 | struct ath9k_tx_queue_info beacon_qi; |
@@ -399,7 +399,7 @@ struct ath_beacon { | |||
399 | 399 | ||
400 | void ath_beacon_tasklet(unsigned long data); | 400 | void ath_beacon_tasklet(unsigned long data); |
401 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); | 401 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); |
402 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); | 402 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); |
403 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); | 403 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); |
404 | int ath_beaconq_config(struct ath_softc *sc); | 404 | int ath_beaconq_config(struct ath_softc *sc); |
405 | 405 | ||
@@ -536,7 +536,6 @@ struct ath_ant_comb { | |||
536 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 536 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
537 | #define ATH_MAX_SW_RETRIES 10 | 537 | #define ATH_MAX_SW_RETRIES 10 |
538 | #define ATH_CHAN_MAX 255 | 538 | #define ATH_CHAN_MAX 255 |
539 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | ||
540 | 539 | ||
541 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 540 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
542 | #define ATH_RATE_DUMMY_MARKER 0 | 541 | #define ATH_RATE_DUMMY_MARKER 0 |
@@ -564,7 +563,6 @@ struct ath_ant_comb { | |||
564 | #define PS_WAIT_FOR_TX_ACK BIT(3) | 563 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
565 | #define PS_BEACON_SYNC BIT(4) | 564 | #define PS_BEACON_SYNC BIT(4) |
566 | 565 | ||
567 | struct ath_wiphy; | ||
568 | struct ath_rate_table; | 566 | struct ath_rate_table; |
569 | 567 | ||
570 | struct ath9k_vif_iter_data { | 568 | struct ath9k_vif_iter_data { |
@@ -585,20 +583,8 @@ struct ath_softc { | |||
585 | struct ieee80211_hw *hw; | 583 | struct ieee80211_hw *hw; |
586 | struct device *dev; | 584 | struct device *dev; |
587 | 585 | ||
588 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ | ||
589 | struct ath_wiphy *pri_wiphy; | ||
590 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may | ||
591 | * have NULL entries */ | ||
592 | int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ | ||
593 | int chan_idx; | 586 | int chan_idx; |
594 | int chan_is_ht; | 587 | int chan_is_ht; |
595 | struct ath_wiphy *next_wiphy; | ||
596 | struct work_struct chan_work; | ||
597 | int wiphy_select_failures; | ||
598 | unsigned long wiphy_select_first_fail; | ||
599 | struct delayed_work wiphy_work; | ||
600 | unsigned long wiphy_scheduler_int; | ||
601 | int wiphy_scheduler_index; | ||
602 | struct survey_info *cur_survey; | 588 | struct survey_info *cur_survey; |
603 | struct survey_info survey[ATH9K_NUM_CHANNELS]; | 589 | struct survey_info survey[ATH9K_NUM_CHANNELS]; |
604 | 590 | ||
@@ -642,6 +628,9 @@ struct ath_softc { | |||
642 | int led_on_cnt; | 628 | int led_on_cnt; |
643 | int led_off_cnt; | 629 | int led_off_cnt; |
644 | 630 | ||
631 | struct ath9k_hw_cal_data caldata; | ||
632 | int last_rssi; | ||
633 | |||
645 | int beacon_interval; | 634 | int beacon_interval; |
646 | 635 | ||
647 | #ifdef CONFIG_ATH9K_DEBUGFS | 636 | #ifdef CONFIG_ATH9K_DEBUGFS |
@@ -652,6 +641,7 @@ struct ath_softc { | |||
652 | #endif | 641 | #endif |
653 | struct ath_beacon_config cur_beacon_conf; | 642 | struct ath_beacon_config cur_beacon_conf; |
654 | struct delayed_work tx_complete_work; | 643 | struct delayed_work tx_complete_work; |
644 | struct delayed_work hw_pll_work; | ||
655 | struct ath_btcoex btcoex; | 645 | struct ath_btcoex btcoex; |
656 | 646 | ||
657 | struct ath_descdma txsdma; | 647 | struct ath_descdma txsdma; |
@@ -661,23 +651,6 @@ struct ath_softc { | |||
661 | struct pm_qos_request_list pm_qos_req; | 651 | struct pm_qos_request_list pm_qos_req; |
662 | }; | 652 | }; |
663 | 653 | ||
664 | struct ath_wiphy { | ||
665 | struct ath_softc *sc; /* shared for all virtual wiphys */ | ||
666 | struct ieee80211_hw *hw; | ||
667 | struct ath9k_hw_cal_data caldata; | ||
668 | enum ath_wiphy_state { | ||
669 | ATH_WIPHY_INACTIVE, | ||
670 | ATH_WIPHY_ACTIVE, | ||
671 | ATH_WIPHY_PAUSING, | ||
672 | ATH_WIPHY_PAUSED, | ||
673 | ATH_WIPHY_SCAN, | ||
674 | } state; | ||
675 | bool idle; | ||
676 | int chan_idx; | ||
677 | int chan_is_ht; | ||
678 | int last_rssi; | ||
679 | }; | ||
680 | |||
681 | void ath9k_tasklet(unsigned long data); | 654 | void ath9k_tasklet(unsigned long data); |
682 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 655 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
683 | int ath_cabq_update(struct ath_softc *); | 656 | int ath_cabq_update(struct ath_softc *); |
@@ -699,8 +672,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
699 | const struct ath_bus_ops *bus_ops); | 672 | const struct ath_bus_ops *bus_ops); |
700 | void ath9k_deinit_device(struct ath_softc *sc); | 673 | void ath9k_deinit_device(struct ath_softc *sc); |
701 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 674 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
702 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
703 | struct ath9k_channel *ichan); | ||
704 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 675 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
705 | struct ath9k_channel *hchan); | 676 | struct ath9k_channel *hchan); |
706 | 677 | ||
@@ -731,24 +702,6 @@ void ath9k_ps_restore(struct ath_softc *sc); | |||
731 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | 702 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); |
732 | 703 | ||
733 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 704 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
734 | int ath9k_wiphy_add(struct ath_softc *sc); | ||
735 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | ||
736 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype); | ||
737 | int ath9k_wiphy_pause(struct ath_wiphy *aphy); | ||
738 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
739 | int ath9k_wiphy_select(struct ath_wiphy *aphy); | ||
740 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); | ||
741 | void ath9k_wiphy_chan_work(struct work_struct *work); | ||
742 | bool ath9k_wiphy_started(struct ath_softc *sc); | ||
743 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
744 | struct ath_wiphy *selected); | ||
745 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | ||
746 | void ath9k_wiphy_work(struct work_struct *work); | ||
747 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | ||
748 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); | ||
749 | |||
750 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | ||
751 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | ||
752 | 705 | ||
753 | void ath_start_rfkill_poll(struct ath_softc *sc); | 706 | void ath_start_rfkill_poll(struct ath_softc *sc); |
754 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 707 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index ab8c05cf62f3..87ba44c06692 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -112,8 +112,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
112 | 112 | ||
113 | static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | 113 | static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) |
114 | { | 114 | { |
115 | struct ath_wiphy *aphy = hw->priv; | 115 | struct ath_softc *sc = hw->priv; |
116 | struct ath_softc *sc = aphy->sc; | ||
117 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 116 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
118 | struct ath_tx_control txctl; | 117 | struct ath_tx_control txctl; |
119 | 118 | ||
@@ -132,8 +131,7 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
132 | static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | 131 | static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, |
133 | struct ieee80211_vif *vif) | 132 | struct ieee80211_vif *vif) |
134 | { | 133 | { |
135 | struct ath_wiphy *aphy = hw->priv; | 134 | struct ath_softc *sc = hw->priv; |
136 | struct ath_softc *sc = aphy->sc; | ||
137 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 135 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
138 | struct ath_buf *bf; | 136 | struct ath_buf *bf; |
139 | struct ath_vif *avp; | 137 | struct ath_vif *avp; |
@@ -142,9 +140,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
142 | struct ieee80211_tx_info *info; | 140 | struct ieee80211_tx_info *info; |
143 | int cabq_depth; | 141 | int cabq_depth; |
144 | 142 | ||
145 | if (aphy->state != ATH_WIPHY_ACTIVE) | ||
146 | return NULL; | ||
147 | |||
148 | avp = (void *)vif->drv_priv; | 143 | avp = (void *)vif->drv_priv; |
149 | cabq = sc->beacon.cabq; | 144 | cabq = sc->beacon.cabq; |
150 | 145 | ||
@@ -225,9 +220,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
225 | return bf; | 220 | return bf; |
226 | } | 221 | } |
227 | 222 | ||
228 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | 223 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) |
229 | { | 224 | { |
230 | struct ath_softc *sc = aphy->sc; | ||
231 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 225 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
232 | struct ath_vif *avp; | 226 | struct ath_vif *avp; |
233 | struct ath_buf *bf; | 227 | struct ath_buf *bf; |
@@ -261,7 +255,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
261 | } | 255 | } |
262 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); | 256 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); |
263 | sc->beacon.bslot[avp->av_bslot] = vif; | 257 | sc->beacon.bslot[avp->av_bslot] = vif; |
264 | sc->beacon.bslot_aphy[avp->av_bslot] = aphy; | ||
265 | sc->nbcnvifs++; | 258 | sc->nbcnvifs++; |
266 | } | 259 | } |
267 | } | 260 | } |
@@ -332,7 +325,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | |||
332 | 325 | ||
333 | if (avp->av_bslot != -1) { | 326 | if (avp->av_bslot != -1) { |
334 | sc->beacon.bslot[avp->av_bslot] = NULL; | 327 | sc->beacon.bslot[avp->av_bslot] = NULL; |
335 | sc->beacon.bslot_aphy[avp->av_bslot] = NULL; | ||
336 | sc->nbcnvifs--; | 328 | sc->nbcnvifs--; |
337 | } | 329 | } |
338 | 330 | ||
@@ -358,7 +350,6 @@ void ath_beacon_tasklet(unsigned long data) | |||
358 | struct ath_common *common = ath9k_hw_common(ah); | 350 | struct ath_common *common = ath9k_hw_common(ah); |
359 | struct ath_buf *bf = NULL; | 351 | struct ath_buf *bf = NULL; |
360 | struct ieee80211_vif *vif; | 352 | struct ieee80211_vif *vif; |
361 | struct ath_wiphy *aphy; | ||
362 | int slot; | 353 | int slot; |
363 | u32 bfaddr, bc = 0, tsftu; | 354 | u32 bfaddr, bc = 0, tsftu; |
364 | u64 tsf; | 355 | u64 tsf; |
@@ -416,7 +407,6 @@ void ath_beacon_tasklet(unsigned long data) | |||
416 | */ | 407 | */ |
417 | slot = ATH_BCBUF - slot - 1; | 408 | slot = ATH_BCBUF - slot - 1; |
418 | vif = sc->beacon.bslot[slot]; | 409 | vif = sc->beacon.bslot[slot]; |
419 | aphy = sc->beacon.bslot_aphy[slot]; | ||
420 | 410 | ||
421 | ath_dbg(common, ATH_DBG_BEACON, | 411 | ath_dbg(common, ATH_DBG_BEACON, |
422 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | 412 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", |
@@ -424,7 +414,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
424 | 414 | ||
425 | bfaddr = 0; | 415 | bfaddr = 0; |
426 | if (vif) { | 416 | if (vif) { |
427 | bf = ath_beacon_generate(aphy->hw, vif); | 417 | bf = ath_beacon_generate(sc->hw, vif); |
428 | if (bf != NULL) { | 418 | if (bf != NULL) { |
429 | bfaddr = bf->bf_daddr; | 419 | bfaddr = bf->bf_daddr; |
430 | bc = 1; | 420 | bc = 1; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index a126bddebb0a..4c7020b3a5a0 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -23,8 +23,6 @@ | |||
23 | 23 | ||
24 | /* Common header for Atheros 802.11n base driver cores */ | 24 | /* Common header for Atheros 802.11n base driver cores */ |
25 | 25 | ||
26 | #define IEEE80211_WEP_NKID 4 | ||
27 | |||
28 | #define WME_NUM_TID 16 | 26 | #define WME_NUM_TID 16 |
29 | #define WME_BA_BMP_SIZE 64 | 27 | #define WME_BA_BMP_SIZE 64 |
30 | #define WME_MAX_BA WME_BA_BMP_SIZE | 28 | #define WME_MAX_BA WME_BA_BMP_SIZE |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index f0c80ec290d1..9cdc41b0ec44 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -381,41 +381,21 @@ static const struct file_operations fops_interrupt = { | |||
381 | .llseek = default_llseek, | 381 | .llseek = default_llseek, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static const char * ath_wiphy_state_str(enum ath_wiphy_state state) | ||
385 | { | ||
386 | switch (state) { | ||
387 | case ATH_WIPHY_INACTIVE: | ||
388 | return "INACTIVE"; | ||
389 | case ATH_WIPHY_ACTIVE: | ||
390 | return "ACTIVE"; | ||
391 | case ATH_WIPHY_PAUSING: | ||
392 | return "PAUSING"; | ||
393 | case ATH_WIPHY_PAUSED: | ||
394 | return "PAUSED"; | ||
395 | case ATH_WIPHY_SCAN: | ||
396 | return "SCAN"; | ||
397 | } | ||
398 | return "?"; | ||
399 | } | ||
400 | |||
401 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | 384 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, |
402 | size_t count, loff_t *ppos) | 385 | size_t count, loff_t *ppos) |
403 | { | 386 | { |
404 | struct ath_softc *sc = file->private_data; | 387 | struct ath_softc *sc = file->private_data; |
405 | struct ath_wiphy *aphy = sc->pri_wiphy; | 388 | struct ieee80211_channel *chan = sc->hw->conf.channel; |
406 | struct ieee80211_channel *chan = aphy->hw->conf.channel; | ||
407 | char buf[512]; | 389 | char buf[512]; |
408 | unsigned int len = 0; | 390 | unsigned int len = 0; |
409 | int i; | ||
410 | u8 addr[ETH_ALEN]; | 391 | u8 addr[ETH_ALEN]; |
411 | u32 tmp; | 392 | u32 tmp; |
412 | 393 | ||
413 | len += snprintf(buf + len, sizeof(buf) - len, | 394 | len += snprintf(buf + len, sizeof(buf) - len, |
414 | "primary: %s (%s chan=%d ht=%d)\n", | 395 | "%s (chan=%d ht=%d)\n", |
415 | wiphy_name(sc->pri_wiphy->hw->wiphy), | 396 | wiphy_name(sc->hw->wiphy), |
416 | ath_wiphy_state_str(sc->pri_wiphy->state), | ||
417 | ieee80211_frequency_to_channel(chan->center_freq), | 397 | ieee80211_frequency_to_channel(chan->center_freq), |
418 | aphy->chan_is_ht); | 398 | conf_is_ht(&sc->hw->conf)); |
419 | 399 | ||
420 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | 400 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); |
421 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | 401 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); |
@@ -457,136 +437,28 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
457 | else | 437 | else |
458 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | 438 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); |
459 | 439 | ||
460 | /* Put variable-length stuff down here, and check for overflows. */ | ||
461 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
462 | struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i]; | ||
463 | if (aphy_tmp == NULL) | ||
464 | continue; | ||
465 | chan = aphy_tmp->hw->conf.channel; | ||
466 | len += snprintf(buf + len, sizeof(buf) - len, | ||
467 | "secondary: %s (%s chan=%d ht=%d)\n", | ||
468 | wiphy_name(aphy_tmp->hw->wiphy), | ||
469 | ath_wiphy_state_str(aphy_tmp->state), | ||
470 | ieee80211_frequency_to_channel(chan->center_freq), | ||
471 | aphy_tmp->chan_is_ht); | ||
472 | } | ||
473 | if (len > sizeof(buf)) | 440 | if (len > sizeof(buf)) |
474 | len = sizeof(buf); | 441 | len = sizeof(buf); |
475 | 442 | ||
476 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 443 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
477 | } | 444 | } |
478 | 445 | ||
479 | static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) | ||
480 | { | ||
481 | int i; | ||
482 | if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) | ||
483 | return sc->pri_wiphy; | ||
484 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
485 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
486 | if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) | ||
487 | return aphy; | ||
488 | } | ||
489 | return NULL; | ||
490 | } | ||
491 | |||
492 | static int del_wiphy(struct ath_softc *sc, const char *name) | ||
493 | { | ||
494 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
495 | if (!aphy) | ||
496 | return -ENOENT; | ||
497 | return ath9k_wiphy_del(aphy); | ||
498 | } | ||
499 | |||
500 | static int pause_wiphy(struct ath_softc *sc, const char *name) | ||
501 | { | ||
502 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
503 | if (!aphy) | ||
504 | return -ENOENT; | ||
505 | return ath9k_wiphy_pause(aphy); | ||
506 | } | ||
507 | |||
508 | static int unpause_wiphy(struct ath_softc *sc, const char *name) | ||
509 | { | ||
510 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
511 | if (!aphy) | ||
512 | return -ENOENT; | ||
513 | return ath9k_wiphy_unpause(aphy); | ||
514 | } | ||
515 | |||
516 | static int select_wiphy(struct ath_softc *sc, const char *name) | ||
517 | { | ||
518 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
519 | if (!aphy) | ||
520 | return -ENOENT; | ||
521 | return ath9k_wiphy_select(aphy); | ||
522 | } | ||
523 | |||
524 | static int schedule_wiphy(struct ath_softc *sc, const char *msec) | ||
525 | { | ||
526 | ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, | ||
531 | size_t count, loff_t *ppos) | ||
532 | { | ||
533 | struct ath_softc *sc = file->private_data; | ||
534 | char buf[50]; | ||
535 | size_t len; | ||
536 | |||
537 | len = min(count, sizeof(buf) - 1); | ||
538 | if (copy_from_user(buf, user_buf, len)) | ||
539 | return -EFAULT; | ||
540 | buf[len] = '\0'; | ||
541 | if (len > 0 && buf[len - 1] == '\n') | ||
542 | buf[len - 1] = '\0'; | ||
543 | |||
544 | if (strncmp(buf, "add", 3) == 0) { | ||
545 | int res = ath9k_wiphy_add(sc); | ||
546 | if (res < 0) | ||
547 | return res; | ||
548 | } else if (strncmp(buf, "del=", 4) == 0) { | ||
549 | int res = del_wiphy(sc, buf + 4); | ||
550 | if (res < 0) | ||
551 | return res; | ||
552 | } else if (strncmp(buf, "pause=", 6) == 0) { | ||
553 | int res = pause_wiphy(sc, buf + 6); | ||
554 | if (res < 0) | ||
555 | return res; | ||
556 | } else if (strncmp(buf, "unpause=", 8) == 0) { | ||
557 | int res = unpause_wiphy(sc, buf + 8); | ||
558 | if (res < 0) | ||
559 | return res; | ||
560 | } else if (strncmp(buf, "select=", 7) == 0) { | ||
561 | int res = select_wiphy(sc, buf + 7); | ||
562 | if (res < 0) | ||
563 | return res; | ||
564 | } else if (strncmp(buf, "schedule=", 9) == 0) { | ||
565 | int res = schedule_wiphy(sc, buf + 9); | ||
566 | if (res < 0) | ||
567 | return res; | ||
568 | } else | ||
569 | return -EOPNOTSUPP; | ||
570 | |||
571 | return count; | ||
572 | } | ||
573 | |||
574 | static const struct file_operations fops_wiphy = { | 446 | static const struct file_operations fops_wiphy = { |
575 | .read = read_file_wiphy, | 447 | .read = read_file_wiphy, |
576 | .write = write_file_wiphy, | ||
577 | .open = ath9k_debugfs_open, | 448 | .open = ath9k_debugfs_open, |
578 | .owner = THIS_MODULE, | 449 | .owner = THIS_MODULE, |
579 | .llseek = default_llseek, | 450 | .llseek = default_llseek, |
580 | }; | 451 | }; |
581 | 452 | ||
453 | #define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum | ||
582 | #define PR(str, elem) \ | 454 | #define PR(str, elem) \ |
583 | do { \ | 455 | do { \ |
584 | len += snprintf(buf + len, size - len, \ | 456 | len += snprintf(buf + len, size - len, \ |
585 | "%s%13u%11u%10u%10u\n", str, \ | 457 | "%s%13u%11u%10u%10u\n", str, \ |
586 | sc->debug.stats.txstats[WME_AC_BE].elem, \ | 458 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \ |
587 | sc->debug.stats.txstats[WME_AC_BK].elem, \ | 459 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \ |
588 | sc->debug.stats.txstats[WME_AC_VI].elem, \ | 460 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \ |
589 | sc->debug.stats.txstats[WME_AC_VO].elem); \ | 461 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \ |
590 | if (len >= size) \ | 462 | if (len >= size) \ |
591 | goto done; \ | 463 | goto done; \ |
592 | } while(0) | 464 | } while(0) |
@@ -595,10 +467,10 @@ static const struct file_operations fops_wiphy = { | |||
595 | do { \ | 467 | do { \ |
596 | len += snprintf(buf + len, size - len, \ | 468 | len += snprintf(buf + len, size - len, \ |
597 | "%s%13u%11u%10u%10u\n", str, \ | 469 | "%s%13u%11u%10u%10u\n", str, \ |
598 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BE].elem), \ | 470 | (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \ |
599 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BK].elem), \ | 471 | (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \ |
600 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VI].elem), \ | 472 | (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \ |
601 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VO].elem)); \ | 473 | (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \ |
602 | if (len >= size) \ | 474 | if (len >= size) \ |
603 | goto done; \ | 475 | goto done; \ |
604 | } while(0) | 476 | } while(0) |
@@ -607,10 +479,10 @@ do { \ | |||
607 | do { \ | 479 | do { \ |
608 | len += snprintf(buf + len, size - len, \ | 480 | len += snprintf(buf + len, size - len, \ |
609 | "%s%13i%11i%10i%10i\n", str, \ | 481 | "%s%13i%11i%10i%10i\n", str, \ |
610 | list_empty(&sc->tx.txq[ATH_TXQ_AC_BE].elem), \ | 482 | list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \ |
611 | list_empty(&sc->tx.txq[ATH_TXQ_AC_BK].elem), \ | 483 | list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \ |
612 | list_empty(&sc->tx.txq[ATH_TXQ_AC_VI].elem), \ | 484 | list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \ |
613 | list_empty(&sc->tx.txq[ATH_TXQ_AC_VO].elem)); \ | 485 | list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \ |
614 | if (len >= size) \ | 486 | if (len >= size) \ |
615 | goto done; \ | 487 | goto done; \ |
616 | } while (0) | 488 | } while (0) |
@@ -657,10 +529,10 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
657 | PR("hw-tx-proc-desc: ", txprocdesc); | 529 | PR("hw-tx-proc-desc: ", txprocdesc); |
658 | len += snprintf(buf + len, size - len, | 530 | len += snprintf(buf + len, size - len, |
659 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", | 531 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", |
660 | &(sc->tx.txq[ATH_TXQ_AC_BE]), | 532 | &(sc->tx.txq_map[WME_AC_BE]), |
661 | &(sc->tx.txq[ATH_TXQ_AC_BK]), | 533 | &(sc->tx.txq_map[WME_AC_BK]), |
662 | &(sc->tx.txq[ATH_TXQ_AC_VI]), | 534 | &(sc->tx.txq_map[WME_AC_VI]), |
663 | &(sc->tx.txq[ATH_TXQ_AC_VO])); | 535 | &(sc->tx.txq_map[WME_AC_VO])); |
664 | if (len >= size) | 536 | if (len >= size) |
665 | goto done; | 537 | goto done; |
666 | 538 | ||
@@ -880,9 +752,9 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, | |||
880 | } | 752 | } |
881 | 753 | ||
882 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | 754 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, |
883 | struct ath_tx_status *ts) | 755 | struct ath_tx_status *ts, struct ath_txq *txq) |
884 | { | 756 | { |
885 | int qnum = skb_get_queue_mapping(bf->bf_mpdu); | 757 | int qnum = txq->axq_qnum; |
886 | 758 | ||
887 | TX_STAT_INC(qnum, tx_pkts_all); | 759 | TX_STAT_INC(qnum, tx_pkts_all); |
888 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; | 760 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 980c9fa194b9..59338de0ce19 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -175,7 +175,7 @@ int ath9k_init_debug(struct ath_hw *ah); | |||
175 | 175 | ||
176 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 176 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
177 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | 177 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, |
178 | struct ath_tx_status *ts); | 178 | struct ath_tx_status *ts, struct ath_txq *txq); |
179 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); | 179 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); |
180 | 180 | ||
181 | #else | 181 | #else |
@@ -192,7 +192,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | |||
192 | 192 | ||
193 | static inline void ath_debug_stat_tx(struct ath_softc *sc, | 193 | static inline void ath_debug_stat_tx(struct ath_softc *sc, |
194 | struct ath_buf *bf, | 194 | struct ath_buf *bf, |
195 | struct ath_tx_status *ts) | 195 | struct ath_tx_status *ts, |
196 | struct ath_txq *txq) | ||
196 | { | 197 | { |
197 | } | 198 | } |
198 | 199 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index c9318ff40964..fccd87df7300 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -247,9 +247,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | /* Enable fixup for AR_AN_TOP2 if necessary */ | 249 | /* Enable fixup for AR_AN_TOP2 if necessary */ |
250 | if (AR_SREV_9280_20_OR_LATER(ah) && | 250 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && |
251 | (eep->baseEepHeader.version & 0xff) > 0x0a && | 251 | ((eep->baseEepHeader.version & 0xff) > 0x0a) && |
252 | eep->baseEepHeader.pwdclkind == 0) | 252 | (eep->baseEepHeader.pwdclkind == 0)) |
253 | ah->need_an_top2_fixup = 1; | 253 | ah->need_an_top2_fixup = 1; |
254 | 254 | ||
255 | if ((common->bus_ops->ath_bus_type == ATH_USB) && | 255 | if ((common->bus_ops->ath_bus_type == ATH_USB) && |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 133764069246..fb4f17a5183d 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -201,8 +201,7 @@ static bool ath_is_rfkill_set(struct ath_softc *sc) | |||
201 | 201 | ||
202 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | 202 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) |
203 | { | 203 | { |
204 | struct ath_wiphy *aphy = hw->priv; | 204 | struct ath_softc *sc = hw->priv; |
205 | struct ath_softc *sc = aphy->sc; | ||
206 | bool blocked = !!ath_is_rfkill_set(sc); | 205 | bool blocked = !!ath_is_rfkill_set(sc); |
207 | 206 | ||
208 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | 207 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8e04586c5256..a7bc26d1bd66 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -142,9 +142,6 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) | |||
142 | { | 142 | { |
143 | ath9k_htc_exit_debug(priv->ah); | 143 | ath9k_htc_exit_debug(priv->ah); |
144 | ath9k_hw_deinit(priv->ah); | 144 | ath9k_hw_deinit(priv->ah); |
145 | tasklet_kill(&priv->swba_tasklet); | ||
146 | tasklet_kill(&priv->rx_tasklet); | ||
147 | tasklet_kill(&priv->tx_tasklet); | ||
148 | kfree(priv->ah); | 145 | kfree(priv->ah); |
149 | priv->ah = NULL; | 146 | priv->ah = NULL; |
150 | } | 147 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f14f37d29f45..a702089f18d0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1026,12 +1026,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1026 | int ret = 0; | 1026 | int ret = 0; |
1027 | u8 cmd_rsp; | 1027 | u8 cmd_rsp; |
1028 | 1028 | ||
1029 | /* Cancel all the running timers/work .. */ | ||
1030 | cancel_work_sync(&priv->fatal_work); | ||
1031 | cancel_work_sync(&priv->ps_work); | ||
1032 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1033 | ath9k_led_stop_brightness(priv); | ||
1034 | |||
1035 | mutex_lock(&priv->mutex); | 1029 | mutex_lock(&priv->mutex); |
1036 | 1030 | ||
1037 | if (priv->op_flags & OP_INVALID) { | 1031 | if (priv->op_flags & OP_INVALID) { |
@@ -1045,8 +1039,23 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1045 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 1039 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1046 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 1040 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
1047 | WMI_CMD(WMI_STOP_RECV_CMDID); | 1041 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1042 | |||
1043 | tasklet_kill(&priv->swba_tasklet); | ||
1044 | tasklet_kill(&priv->rx_tasklet); | ||
1045 | tasklet_kill(&priv->tx_tasklet); | ||
1046 | |||
1048 | skb_queue_purge(&priv->tx_queue); | 1047 | skb_queue_purge(&priv->tx_queue); |
1049 | 1048 | ||
1049 | mutex_unlock(&priv->mutex); | ||
1050 | |||
1051 | /* Cancel all the running timers/work .. */ | ||
1052 | cancel_work_sync(&priv->fatal_work); | ||
1053 | cancel_work_sync(&priv->ps_work); | ||
1054 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1055 | ath9k_led_stop_brightness(priv); | ||
1056 | |||
1057 | mutex_lock(&priv->mutex); | ||
1058 | |||
1050 | /* Remove monitor interface here */ | 1059 | /* Remove monitor interface here */ |
1051 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | 1060 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { |
1052 | if (ath9k_htc_remove_monitor_interface(priv)) | 1061 | if (ath9k_htc_remove_monitor_interface(priv)) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 4615fd9c9aa0..f9cf81551817 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -671,13 +671,50 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) | |||
671 | REGWRITE_BUFFER_FLUSH(ah); | 671 | REGWRITE_BUFFER_FLUSH(ah); |
672 | } | 672 | } |
673 | 673 | ||
674 | unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) | ||
675 | { | ||
676 | REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); | ||
677 | udelay(100); | ||
678 | REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); | ||
679 | |||
680 | while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) | ||
681 | udelay(100); | ||
682 | |||
683 | return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; | ||
684 | } | ||
685 | EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); | ||
686 | |||
687 | #define DPLL2_KD_VAL 0x3D | ||
688 | #define DPLL2_KI_VAL 0x06 | ||
689 | #define DPLL3_PHASE_SHIFT_VAL 0x1 | ||
690 | |||
674 | static void ath9k_hw_init_pll(struct ath_hw *ah, | 691 | static void ath9k_hw_init_pll(struct ath_hw *ah, |
675 | struct ath9k_channel *chan) | 692 | struct ath9k_channel *chan) |
676 | { | 693 | { |
677 | u32 pll; | 694 | u32 pll; |
678 | 695 | ||
679 | if (AR_SREV_9485(ah)) | 696 | if (AR_SREV_9485(ah)) { |
680 | REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); | 697 | REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); |
698 | REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); | ||
699 | |||
700 | REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, | ||
701 | AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); | ||
702 | |||
703 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); | ||
704 | udelay(100); | ||
705 | |||
706 | REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); | ||
707 | |||
708 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
709 | AR_CH0_DPLL2_KD, DPLL2_KD_VAL); | ||
710 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
711 | AR_CH0_DPLL2_KI, DPLL2_KI_VAL); | ||
712 | |||
713 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | ||
714 | AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); | ||
715 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); | ||
716 | udelay(110); | ||
717 | } | ||
681 | 718 | ||
682 | pll = ath9k_hw_compute_pll_control(ah, chan); | 719 | pll = ath9k_hw_compute_pll_control(ah, chan); |
683 | 720 | ||
@@ -1349,8 +1386,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1349 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1386 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1350 | ah->eep_ops->set_board_values(ah, chan); | 1387 | ah->eep_ops->set_board_values(ah, chan); |
1351 | 1388 | ||
1352 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1353 | |||
1354 | ENABLE_REGWRITE_BUFFER(ah); | 1389 | ENABLE_REGWRITE_BUFFER(ah); |
1355 | 1390 | ||
1356 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | 1391 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); |
@@ -1368,6 +1403,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1368 | 1403 | ||
1369 | REGWRITE_BUFFER_FLUSH(ah); | 1404 | REGWRITE_BUFFER_FLUSH(ah); |
1370 | 1405 | ||
1406 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1407 | |||
1371 | r = ath9k_hw_rf_set_freq(ah, chan); | 1408 | r = ath9k_hw_rf_set_freq(ah, chan); |
1372 | if (r) | 1409 | if (r) |
1373 | return r; | 1410 | return r; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ad8c2c702130..ef79f4c876ca 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -929,6 +929,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | |||
929 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 929 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
930 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 930 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
931 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 931 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
932 | unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); | ||
932 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 933 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
933 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 934 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
934 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 935 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5279653c90c7..e5c1eead98a2 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -254,8 +254,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
254 | struct regulatory_request *request) | 254 | struct regulatory_request *request) |
255 | { | 255 | { |
256 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 256 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
257 | struct ath_wiphy *aphy = hw->priv; | 257 | struct ath_softc *sc = hw->priv; |
258 | struct ath_softc *sc = aphy->sc; | ||
259 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | 258 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); |
260 | 259 | ||
261 | return ath_reg_notifier_apply(wiphy, request, reg); | 260 | return ath_reg_notifier_apply(wiphy, request, reg); |
@@ -517,10 +516,8 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
517 | 516 | ||
518 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 517 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
519 | 518 | ||
520 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 519 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) |
521 | sc->beacon.bslot[i] = NULL; | 520 | sc->beacon.bslot[i] = NULL; |
522 | sc->beacon.bslot_aphy[i] = NULL; | ||
523 | } | ||
524 | 521 | ||
525 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | 522 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
526 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | 523 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; |
@@ -556,7 +553,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
556 | common->btcoex_enabled = ath9k_btcoex_enable == 1; | 553 | common->btcoex_enabled = ath9k_btcoex_enable == 1; |
557 | spin_lock_init(&common->cc_lock); | 554 | spin_lock_init(&common->cc_lock); |
558 | 555 | ||
559 | spin_lock_init(&sc->wiphy_lock); | ||
560 | spin_lock_init(&sc->sc_serial_rw); | 556 | spin_lock_init(&sc->sc_serial_rw); |
561 | spin_lock_init(&sc->sc_pm_lock); | 557 | spin_lock_init(&sc->sc_pm_lock); |
562 | mutex_init(&sc->mutex); | 558 | mutex_init(&sc->mutex); |
@@ -604,8 +600,6 @@ err_btcoex: | |||
604 | err_queues: | 600 | err_queues: |
605 | ath9k_hw_deinit(ah); | 601 | ath9k_hw_deinit(ah); |
606 | err_hw: | 602 | err_hw: |
607 | tasklet_kill(&sc->intr_tq); | ||
608 | tasklet_kill(&sc->bcon_tasklet); | ||
609 | 603 | ||
610 | kfree(ah); | 604 | kfree(ah); |
611 | sc->sc_ah = NULL; | 605 | sc->sc_ah = NULL; |
@@ -707,7 +701,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
707 | const struct ath_bus_ops *bus_ops) | 701 | const struct ath_bus_ops *bus_ops) |
708 | { | 702 | { |
709 | struct ieee80211_hw *hw = sc->hw; | 703 | struct ieee80211_hw *hw = sc->hw; |
710 | struct ath_wiphy *aphy = hw->priv; | ||
711 | struct ath_common *common; | 704 | struct ath_common *common; |
712 | struct ath_hw *ah; | 705 | struct ath_hw *ah; |
713 | int error = 0; | 706 | int error = 0; |
@@ -762,10 +755,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
762 | 755 | ||
763 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | 756 | INIT_WORK(&sc->hw_check_work, ath_hw_check); |
764 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 757 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
765 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 758 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
766 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | ||
767 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
768 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
769 | 759 | ||
770 | ath_init_leds(sc); | 760 | ath_init_leds(sc); |
771 | ath_start_rfkill_poll(sc); | 761 | ath_start_rfkill_poll(sc); |
@@ -813,9 +803,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
813 | 803 | ||
814 | ath9k_hw_deinit(sc->sc_ah); | 804 | ath9k_hw_deinit(sc->sc_ah); |
815 | 805 | ||
816 | tasklet_kill(&sc->intr_tq); | ||
817 | tasklet_kill(&sc->bcon_tasklet); | ||
818 | |||
819 | kfree(sc->sc_ah); | 806 | kfree(sc->sc_ah); |
820 | sc->sc_ah = NULL; | 807 | sc->sc_ah = NULL; |
821 | } | 808 | } |
@@ -823,28 +810,19 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
823 | void ath9k_deinit_device(struct ath_softc *sc) | 810 | void ath9k_deinit_device(struct ath_softc *sc) |
824 | { | 811 | { |
825 | struct ieee80211_hw *hw = sc->hw; | 812 | struct ieee80211_hw *hw = sc->hw; |
826 | int i = 0; | ||
827 | 813 | ||
828 | ath9k_ps_wakeup(sc); | 814 | ath9k_ps_wakeup(sc); |
829 | 815 | ||
830 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 816 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
831 | ath_deinit_leds(sc); | 817 | ath_deinit_leds(sc); |
832 | 818 | ||
833 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 819 | ath9k_ps_restore(sc); |
834 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
835 | if (aphy == NULL) | ||
836 | continue; | ||
837 | sc->sec_wiphy[i] = NULL; | ||
838 | ieee80211_unregister_hw(aphy->hw); | ||
839 | ieee80211_free_hw(aphy->hw); | ||
840 | } | ||
841 | 820 | ||
842 | ieee80211_unregister_hw(hw); | 821 | ieee80211_unregister_hw(hw); |
843 | pm_qos_remove_request(&sc->pm_qos_req); | 822 | pm_qos_remove_request(&sc->pm_qos_req); |
844 | ath_rx_cleanup(sc); | 823 | ath_rx_cleanup(sc); |
845 | ath_tx_cleanup(sc); | 824 | ath_tx_cleanup(sc); |
846 | ath9k_deinit_softc(sc); | 825 | ath9k_deinit_softc(sc); |
847 | kfree(sc->sec_wiphy); | ||
848 | } | 826 | } |
849 | 827 | ||
850 | void ath_descdma_cleanup(struct ath_softc *sc, | 828 | void ath_descdma_cleanup(struct ath_softc *sc, |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 7512f97e8f49..04d58ae923bb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -639,6 +639,8 @@ enum ath9k_rx_filter { | |||
639 | ATH9K_RX_FILTER_PHYERR = 0x00000100, | 639 | ATH9K_RX_FILTER_PHYERR = 0x00000100, |
640 | ATH9K_RX_FILTER_MYBEACON = 0x00000200, | 640 | ATH9K_RX_FILTER_MYBEACON = 0x00000200, |
641 | ATH9K_RX_FILTER_COMP_BAR = 0x00000400, | 641 | ATH9K_RX_FILTER_COMP_BAR = 0x00000400, |
642 | ATH9K_RX_FILTER_COMP_BA = 0x00000800, | ||
643 | ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000, | ||
642 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, | 644 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, |
643 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, | 645 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, |
644 | ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, | 646 | ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index facff102dd0e..1447b55a8d0a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -73,7 +73,7 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | |||
73 | 73 | ||
74 | chan_idx = curchan->hw_value; | 74 | chan_idx = curchan->hw_value; |
75 | channel = &sc->sc_ah->channels[chan_idx]; | 75 | channel = &sc->sc_ah->channels[chan_idx]; |
76 | ath9k_update_ichannel(sc, hw, channel); | 76 | ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); |
77 | return channel; | 77 | return channel; |
78 | } | 78 | } |
79 | 79 | ||
@@ -215,7 +215,6 @@ static void ath_update_survey_stats(struct ath_softc *sc) | |||
215 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 215 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
216 | struct ath9k_channel *hchan) | 216 | struct ath9k_channel *hchan) |
217 | { | 217 | { |
218 | struct ath_wiphy *aphy = hw->priv; | ||
219 | struct ath_hw *ah = sc->sc_ah; | 218 | struct ath_hw *ah = sc->sc_ah; |
220 | struct ath_common *common = ath9k_hw_common(ah); | 219 | struct ath_common *common = ath9k_hw_common(ah); |
221 | struct ieee80211_conf *conf = &common->hw->conf; | 220 | struct ieee80211_conf *conf = &common->hw->conf; |
@@ -231,6 +230,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
231 | cancel_work_sync(&sc->paprd_work); | 230 | cancel_work_sync(&sc->paprd_work); |
232 | cancel_work_sync(&sc->hw_check_work); | 231 | cancel_work_sync(&sc->hw_check_work); |
233 | cancel_delayed_work_sync(&sc->tx_complete_work); | 232 | cancel_delayed_work_sync(&sc->tx_complete_work); |
233 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
234 | 234 | ||
235 | ath9k_ps_wakeup(sc); | 235 | ath9k_ps_wakeup(sc); |
236 | 236 | ||
@@ -262,7 +262,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
262 | fastcc = false; | 262 | fastcc = false; |
263 | 263 | ||
264 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) | 264 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) |
265 | caldata = &aphy->caldata; | 265 | caldata = &sc->caldata; |
266 | 266 | ||
267 | ath_dbg(common, ATH_DBG_CONFIG, | 267 | ath_dbg(common, ATH_DBG_CONFIG, |
268 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", | 268 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", |
@@ -291,10 +291,13 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
291 | if (sc->sc_flags & SC_OP_BEACONS) | 291 | if (sc->sc_flags & SC_OP_BEACONS) |
292 | ath_beacon_config(sc, NULL); | 292 | ath_beacon_config(sc, NULL); |
293 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 293 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
294 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); | ||
294 | ath_start_ani(common); | 295 | ath_start_ani(common); |
295 | } | 296 | } |
296 | 297 | ||
297 | ps_restore: | 298 | ps_restore: |
299 | ieee80211_wake_queues(hw); | ||
300 | |||
298 | spin_unlock_bh(&sc->sc_pcu_lock); | 301 | spin_unlock_bh(&sc->sc_pcu_lock); |
299 | 302 | ||
300 | ath9k_ps_restore(sc); | 303 | ath9k_ps_restore(sc); |
@@ -328,6 +331,8 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int | |||
328 | { | 331 | { |
329 | struct ieee80211_hw *hw = sc->hw; | 332 | struct ieee80211_hw *hw = sc->hw; |
330 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 333 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
334 | struct ath_hw *ah = sc->sc_ah; | ||
335 | struct ath_common *common = ath9k_hw_common(ah); | ||
331 | struct ath_tx_control txctl; | 336 | struct ath_tx_control txctl; |
332 | int time_left; | 337 | int time_left; |
333 | 338 | ||
@@ -345,8 +350,12 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int | |||
345 | init_completion(&sc->paprd_complete); | 350 | init_completion(&sc->paprd_complete); |
346 | sc->paprd_pending = true; | 351 | sc->paprd_pending = true; |
347 | txctl.paprd = BIT(chain); | 352 | txctl.paprd = BIT(chain); |
348 | if (ath_tx_start(hw, skb, &txctl) != 0) | 353 | |
354 | if (ath_tx_start(hw, skb, &txctl) != 0) { | ||
355 | ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); | ||
356 | dev_kfree_skb_any(skb); | ||
349 | return false; | 357 | return false; |
358 | } | ||
350 | 359 | ||
351 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | 360 | time_left = wait_for_completion_timeout(&sc->paprd_complete, |
352 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | 361 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); |
@@ -803,54 +812,11 @@ chip_reset: | |||
803 | #undef SCHED_INTR | 812 | #undef SCHED_INTR |
804 | } | 813 | } |
805 | 814 | ||
806 | static u32 ath_get_extchanmode(struct ath_softc *sc, | ||
807 | struct ieee80211_channel *chan, | ||
808 | enum nl80211_channel_type channel_type) | ||
809 | { | ||
810 | u32 chanmode = 0; | ||
811 | |||
812 | switch (chan->band) { | ||
813 | case IEEE80211_BAND_2GHZ: | ||
814 | switch(channel_type) { | ||
815 | case NL80211_CHAN_NO_HT: | ||
816 | case NL80211_CHAN_HT20: | ||
817 | chanmode = CHANNEL_G_HT20; | ||
818 | break; | ||
819 | case NL80211_CHAN_HT40PLUS: | ||
820 | chanmode = CHANNEL_G_HT40PLUS; | ||
821 | break; | ||
822 | case NL80211_CHAN_HT40MINUS: | ||
823 | chanmode = CHANNEL_G_HT40MINUS; | ||
824 | break; | ||
825 | } | ||
826 | break; | ||
827 | case IEEE80211_BAND_5GHZ: | ||
828 | switch(channel_type) { | ||
829 | case NL80211_CHAN_NO_HT: | ||
830 | case NL80211_CHAN_HT20: | ||
831 | chanmode = CHANNEL_A_HT20; | ||
832 | break; | ||
833 | case NL80211_CHAN_HT40PLUS: | ||
834 | chanmode = CHANNEL_A_HT40PLUS; | ||
835 | break; | ||
836 | case NL80211_CHAN_HT40MINUS: | ||
837 | chanmode = CHANNEL_A_HT40MINUS; | ||
838 | break; | ||
839 | } | ||
840 | break; | ||
841 | default: | ||
842 | break; | ||
843 | } | ||
844 | |||
845 | return chanmode; | ||
846 | } | ||
847 | |||
848 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 815 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
849 | struct ieee80211_hw *hw, | 816 | struct ieee80211_hw *hw, |
850 | struct ieee80211_vif *vif, | 817 | struct ieee80211_vif *vif, |
851 | struct ieee80211_bss_conf *bss_conf) | 818 | struct ieee80211_bss_conf *bss_conf) |
852 | { | 819 | { |
853 | struct ath_wiphy *aphy = hw->priv; | ||
854 | struct ath_hw *ah = sc->sc_ah; | 820 | struct ath_hw *ah = sc->sc_ah; |
855 | struct ath_common *common = ath9k_hw_common(ah); | 821 | struct ath_common *common = ath9k_hw_common(ah); |
856 | 822 | ||
@@ -874,7 +840,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
874 | ath_beacon_config(sc, vif); | 840 | ath_beacon_config(sc, vif); |
875 | 841 | ||
876 | /* Reset rssi stats */ | 842 | /* Reset rssi stats */ |
877 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; | 843 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
878 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 844 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
879 | 845 | ||
880 | sc->sc_flags |= SC_OP_ANI_RUN; | 846 | sc->sc_flags |= SC_OP_ANI_RUN; |
@@ -977,8 +943,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
977 | 943 | ||
978 | spin_unlock_bh(&sc->sc_pcu_lock); | 944 | spin_unlock_bh(&sc->sc_pcu_lock); |
979 | ath9k_ps_restore(sc); | 945 | ath9k_ps_restore(sc); |
980 | |||
981 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | ||
982 | } | 946 | } |
983 | 947 | ||
984 | int ath_reset(struct ath_softc *sc, bool retry_tx) | 948 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
@@ -1043,38 +1007,13 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1043 | return r; | 1007 | return r; |
1044 | } | 1008 | } |
1045 | 1009 | ||
1046 | /* XXX: Remove me once we don't depend on ath9k_channel for all | ||
1047 | * this redundant data */ | ||
1048 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
1049 | struct ath9k_channel *ichan) | ||
1050 | { | ||
1051 | struct ieee80211_channel *chan = hw->conf.channel; | ||
1052 | struct ieee80211_conf *conf = &hw->conf; | ||
1053 | |||
1054 | ichan->channel = chan->center_freq; | ||
1055 | ichan->chan = chan; | ||
1056 | |||
1057 | if (chan->band == IEEE80211_BAND_2GHZ) { | ||
1058 | ichan->chanmode = CHANNEL_G; | ||
1059 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; | ||
1060 | } else { | ||
1061 | ichan->chanmode = CHANNEL_A; | ||
1062 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | ||
1063 | } | ||
1064 | |||
1065 | if (conf_is_ht(conf)) | ||
1066 | ichan->chanmode = ath_get_extchanmode(sc, chan, | ||
1067 | conf->channel_type); | ||
1068 | } | ||
1069 | |||
1070 | /**********************/ | 1010 | /**********************/ |
1071 | /* mac80211 callbacks */ | 1011 | /* mac80211 callbacks */ |
1072 | /**********************/ | 1012 | /**********************/ |
1073 | 1013 | ||
1074 | static int ath9k_start(struct ieee80211_hw *hw) | 1014 | static int ath9k_start(struct ieee80211_hw *hw) |
1075 | { | 1015 | { |
1076 | struct ath_wiphy *aphy = hw->priv; | 1016 | struct ath_softc *sc = hw->priv; |
1077 | struct ath_softc *sc = aphy->sc; | ||
1078 | struct ath_hw *ah = sc->sc_ah; | 1017 | struct ath_hw *ah = sc->sc_ah; |
1079 | struct ath_common *common = ath9k_hw_common(ah); | 1018 | struct ath_common *common = ath9k_hw_common(ah); |
1080 | struct ieee80211_channel *curchan = hw->conf.channel; | 1019 | struct ieee80211_channel *curchan = hw->conf.channel; |
@@ -1087,29 +1026,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1087 | 1026 | ||
1088 | mutex_lock(&sc->mutex); | 1027 | mutex_lock(&sc->mutex); |
1089 | 1028 | ||
1090 | if (ath9k_wiphy_started(sc)) { | ||
1091 | if (sc->chan_idx == curchan->hw_value) { | ||
1092 | /* | ||
1093 | * Already on the operational channel, the new wiphy | ||
1094 | * can be marked active. | ||
1095 | */ | ||
1096 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1097 | ieee80211_wake_queues(hw); | ||
1098 | } else { | ||
1099 | /* | ||
1100 | * Another wiphy is on another channel, start the new | ||
1101 | * wiphy in paused state. | ||
1102 | */ | ||
1103 | aphy->state = ATH_WIPHY_PAUSED; | ||
1104 | ieee80211_stop_queues(hw); | ||
1105 | } | ||
1106 | mutex_unlock(&sc->mutex); | ||
1107 | return 0; | ||
1108 | } | ||
1109 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1110 | |||
1111 | /* setup initial channel */ | 1029 | /* setup initial channel */ |
1112 | |||
1113 | sc->chan_idx = curchan->hw_value; | 1030 | sc->chan_idx = curchan->hw_value; |
1114 | 1031 | ||
1115 | init_channel = ath_get_curchannel(sc, hw); | 1032 | init_channel = ath_get_curchannel(sc, hw); |
@@ -1213,19 +1130,11 @@ mutex_unlock: | |||
1213 | static int ath9k_tx(struct ieee80211_hw *hw, | 1130 | static int ath9k_tx(struct ieee80211_hw *hw, |
1214 | struct sk_buff *skb) | 1131 | struct sk_buff *skb) |
1215 | { | 1132 | { |
1216 | struct ath_wiphy *aphy = hw->priv; | 1133 | struct ath_softc *sc = hw->priv; |
1217 | struct ath_softc *sc = aphy->sc; | ||
1218 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1134 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1219 | struct ath_tx_control txctl; | 1135 | struct ath_tx_control txctl; |
1220 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1136 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1221 | 1137 | ||
1222 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | ||
1223 | ath_dbg(common, ATH_DBG_XMIT, | ||
1224 | "ath9k: %s: TX in unexpected wiphy state %d\n", | ||
1225 | wiphy_name(hw->wiphy), aphy->state); | ||
1226 | goto exit; | ||
1227 | } | ||
1228 | |||
1229 | if (sc->ps_enabled) { | 1138 | if (sc->ps_enabled) { |
1230 | /* | 1139 | /* |
1231 | * mac80211 does not set PM field for normal data frames, so we | 1140 | * mac80211 does not set PM field for normal data frames, so we |
@@ -1284,44 +1193,26 @@ exit: | |||
1284 | 1193 | ||
1285 | static void ath9k_stop(struct ieee80211_hw *hw) | 1194 | static void ath9k_stop(struct ieee80211_hw *hw) |
1286 | { | 1195 | { |
1287 | struct ath_wiphy *aphy = hw->priv; | 1196 | struct ath_softc *sc = hw->priv; |
1288 | struct ath_softc *sc = aphy->sc; | ||
1289 | struct ath_hw *ah = sc->sc_ah; | 1197 | struct ath_hw *ah = sc->sc_ah; |
1290 | struct ath_common *common = ath9k_hw_common(ah); | 1198 | struct ath_common *common = ath9k_hw_common(ah); |
1291 | int i; | ||
1292 | 1199 | ||
1293 | mutex_lock(&sc->mutex); | 1200 | mutex_lock(&sc->mutex); |
1294 | 1201 | ||
1295 | aphy->state = ATH_WIPHY_INACTIVE; | ||
1296 | |||
1297 | if (led_blink) | 1202 | if (led_blink) |
1298 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 1203 | cancel_delayed_work_sync(&sc->ath_led_blink_work); |
1299 | 1204 | ||
1300 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1205 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1206 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
1301 | cancel_work_sync(&sc->paprd_work); | 1207 | cancel_work_sync(&sc->paprd_work); |
1302 | cancel_work_sync(&sc->hw_check_work); | 1208 | cancel_work_sync(&sc->hw_check_work); |
1303 | 1209 | ||
1304 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1305 | if (sc->sec_wiphy[i]) | ||
1306 | break; | ||
1307 | } | ||
1308 | |||
1309 | if (i == sc->num_sec_wiphy) { | ||
1310 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
1311 | cancel_work_sync(&sc->chan_work); | ||
1312 | } | ||
1313 | |||
1314 | if (sc->sc_flags & SC_OP_INVALID) { | 1210 | if (sc->sc_flags & SC_OP_INVALID) { |
1315 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); | 1211 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); |
1316 | mutex_unlock(&sc->mutex); | 1212 | mutex_unlock(&sc->mutex); |
1317 | return; | 1213 | return; |
1318 | } | 1214 | } |
1319 | 1215 | ||
1320 | if (ath9k_wiphy_started(sc)) { | ||
1321 | mutex_unlock(&sc->mutex); | ||
1322 | return; /* another wiphy still in use */ | ||
1323 | } | ||
1324 | |||
1325 | /* Ensure HW is awake when we try to shut it down. */ | 1216 | /* Ensure HW is awake when we try to shut it down. */ |
1326 | ath9k_ps_wakeup(sc); | 1217 | ath9k_ps_wakeup(sc); |
1327 | 1218 | ||
@@ -1333,6 +1224,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1333 | 1224 | ||
1334 | spin_lock_bh(&sc->sc_pcu_lock); | 1225 | spin_lock_bh(&sc->sc_pcu_lock); |
1335 | 1226 | ||
1227 | /* prevent tasklets to enable interrupts once we disable them */ | ||
1228 | ah->imask &= ~ATH9K_INT_GLOBAL; | ||
1229 | |||
1336 | /* make sure h/w will not generate any interrupt | 1230 | /* make sure h/w will not generate any interrupt |
1337 | * before setting the invalid flag. */ | 1231 | * before setting the invalid flag. */ |
1338 | ath9k_hw_disable_interrupts(ah); | 1232 | ath9k_hw_disable_interrupts(ah); |
@@ -1344,16 +1238,26 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1344 | } else | 1238 | } else |
1345 | sc->rx.rxlink = NULL; | 1239 | sc->rx.rxlink = NULL; |
1346 | 1240 | ||
1241 | if (sc->rx.frag) { | ||
1242 | dev_kfree_skb_any(sc->rx.frag); | ||
1243 | sc->rx.frag = NULL; | ||
1244 | } | ||
1245 | |||
1347 | /* disable HAL and put h/w to sleep */ | 1246 | /* disable HAL and put h/w to sleep */ |
1348 | ath9k_hw_disable(ah); | 1247 | ath9k_hw_disable(ah); |
1349 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1248 | ath9k_hw_configpcipowersave(ah, 1, 1); |
1350 | 1249 | ||
1351 | spin_unlock_bh(&sc->sc_pcu_lock); | 1250 | spin_unlock_bh(&sc->sc_pcu_lock); |
1352 | 1251 | ||
1252 | /* we can now sync irq and kill any running tasklets, since we already | ||
1253 | * disabled interrupts and not holding a spin lock */ | ||
1254 | synchronize_irq(sc->irq); | ||
1255 | tasklet_kill(&sc->intr_tq); | ||
1256 | tasklet_kill(&sc->bcon_tasklet); | ||
1257 | |||
1353 | ath9k_ps_restore(sc); | 1258 | ath9k_ps_restore(sc); |
1354 | 1259 | ||
1355 | sc->ps_idle = true; | 1260 | sc->ps_idle = true; |
1356 | ath9k_set_wiphy_idle(aphy, true); | ||
1357 | ath_radio_disable(sc, hw); | 1261 | ath_radio_disable(sc, hw); |
1358 | 1262 | ||
1359 | sc->sc_flags |= SC_OP_INVALID; | 1263 | sc->sc_flags |= SC_OP_INVALID; |
@@ -1439,11 +1343,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
1439 | struct ieee80211_vif *vif, | 1343 | struct ieee80211_vif *vif, |
1440 | struct ath9k_vif_iter_data *iter_data) | 1344 | struct ath9k_vif_iter_data *iter_data) |
1441 | { | 1345 | { |
1442 | struct ath_wiphy *aphy = hw->priv; | 1346 | struct ath_softc *sc = hw->priv; |
1443 | struct ath_softc *sc = aphy->sc; | ||
1444 | struct ath_hw *ah = sc->sc_ah; | 1347 | struct ath_hw *ah = sc->sc_ah; |
1445 | struct ath_common *common = ath9k_hw_common(ah); | 1348 | struct ath_common *common = ath9k_hw_common(ah); |
1446 | int i; | ||
1447 | 1349 | ||
1448 | /* | 1350 | /* |
1449 | * Use the hardware MAC address as reference, the hardware uses it | 1351 | * Use the hardware MAC address as reference, the hardware uses it |
@@ -1457,24 +1359,15 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | |||
1457 | ath9k_vif_iter(iter_data, vif->addr, vif); | 1359 | ath9k_vif_iter(iter_data, vif->addr, vif); |
1458 | 1360 | ||
1459 | /* Get list of all active MAC addresses */ | 1361 | /* Get list of all active MAC addresses */ |
1460 | spin_lock_bh(&sc->wiphy_lock); | ||
1461 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | 1362 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, |
1462 | iter_data); | 1363 | iter_data); |
1463 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1464 | if (sc->sec_wiphy[i] == NULL) | ||
1465 | continue; | ||
1466 | ieee80211_iterate_active_interfaces_atomic( | ||
1467 | sc->sec_wiphy[i]->hw, ath9k_vif_iter, iter_data); | ||
1468 | } | ||
1469 | spin_unlock_bh(&sc->wiphy_lock); | ||
1470 | } | 1364 | } |
1471 | 1365 | ||
1472 | /* Called with sc->mutex held. */ | 1366 | /* Called with sc->mutex held. */ |
1473 | static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | 1367 | static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, |
1474 | struct ieee80211_vif *vif) | 1368 | struct ieee80211_vif *vif) |
1475 | { | 1369 | { |
1476 | struct ath_wiphy *aphy = hw->priv; | 1370 | struct ath_softc *sc = hw->priv; |
1477 | struct ath_softc *sc = aphy->sc; | ||
1478 | struct ath_hw *ah = sc->sc_ah; | 1371 | struct ath_hw *ah = sc->sc_ah; |
1479 | struct ath_common *common = ath9k_hw_common(ah); | 1372 | struct ath_common *common = ath9k_hw_common(ah); |
1480 | struct ath9k_vif_iter_data iter_data; | 1373 | struct ath9k_vif_iter_data iter_data; |
@@ -1530,8 +1423,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1530 | static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | 1423 | static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, |
1531 | struct ieee80211_vif *vif) | 1424 | struct ieee80211_vif *vif) |
1532 | { | 1425 | { |
1533 | struct ath_wiphy *aphy = hw->priv; | 1426 | struct ath_softc *sc = hw->priv; |
1534 | struct ath_softc *sc = aphy->sc; | ||
1535 | 1427 | ||
1536 | ath9k_calculate_summary_state(hw, vif); | 1428 | ath9k_calculate_summary_state(hw, vif); |
1537 | 1429 | ||
@@ -1544,7 +1436,7 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1544 | * in the info_changed method and set up beacons properly | 1436 | * in the info_changed method and set up beacons properly |
1545 | * there. | 1437 | * there. |
1546 | */ | 1438 | */ |
1547 | error = ath_beacon_alloc(aphy, vif); | 1439 | error = ath_beacon_alloc(sc, vif); |
1548 | if (error) | 1440 | if (error) |
1549 | ath9k_reclaim_beacon(sc, vif); | 1441 | ath9k_reclaim_beacon(sc, vif); |
1550 | else | 1442 | else |
@@ -1556,8 +1448,7 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1556 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1448 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
1557 | struct ieee80211_vif *vif) | 1449 | struct ieee80211_vif *vif) |
1558 | { | 1450 | { |
1559 | struct ath_wiphy *aphy = hw->priv; | 1451 | struct ath_softc *sc = hw->priv; |
1560 | struct ath_softc *sc = aphy->sc; | ||
1561 | struct ath_hw *ah = sc->sc_ah; | 1452 | struct ath_hw *ah = sc->sc_ah; |
1562 | struct ath_common *common = ath9k_hw_common(ah); | 1453 | struct ath_common *common = ath9k_hw_common(ah); |
1563 | struct ath_vif *avp = (void *)vif->drv_priv; | 1454 | struct ath_vif *avp = (void *)vif->drv_priv; |
@@ -1617,8 +1508,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
1617 | enum nl80211_iftype new_type, | 1508 | enum nl80211_iftype new_type, |
1618 | bool p2p) | 1509 | bool p2p) |
1619 | { | 1510 | { |
1620 | struct ath_wiphy *aphy = hw->priv; | 1511 | struct ath_softc *sc = hw->priv; |
1621 | struct ath_softc *sc = aphy->sc; | ||
1622 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1512 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1623 | int ret = 0; | 1513 | int ret = 0; |
1624 | 1514 | ||
@@ -1660,8 +1550,7 @@ out: | |||
1660 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 1550 | static void ath9k_remove_interface(struct ieee80211_hw *hw, |
1661 | struct ieee80211_vif *vif) | 1551 | struct ieee80211_vif *vif) |
1662 | { | 1552 | { |
1663 | struct ath_wiphy *aphy = hw->priv; | 1553 | struct ath_softc *sc = hw->priv; |
1664 | struct ath_softc *sc = aphy->sc; | ||
1665 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1554 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1666 | 1555 | ||
1667 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); | 1556 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
@@ -1715,12 +1604,11 @@ static void ath9k_disable_ps(struct ath_softc *sc) | |||
1715 | 1604 | ||
1716 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1605 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1717 | { | 1606 | { |
1718 | struct ath_wiphy *aphy = hw->priv; | 1607 | struct ath_softc *sc = hw->priv; |
1719 | struct ath_softc *sc = aphy->sc; | ||
1720 | struct ath_hw *ah = sc->sc_ah; | 1608 | struct ath_hw *ah = sc->sc_ah; |
1721 | struct ath_common *common = ath9k_hw_common(ah); | 1609 | struct ath_common *common = ath9k_hw_common(ah); |
1722 | struct ieee80211_conf *conf = &hw->conf; | 1610 | struct ieee80211_conf *conf = &hw->conf; |
1723 | bool disable_radio; | 1611 | bool disable_radio = false; |
1724 | 1612 | ||
1725 | mutex_lock(&sc->mutex); | 1613 | mutex_lock(&sc->mutex); |
1726 | 1614 | ||
@@ -1731,29 +1619,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1731 | * the end. | 1619 | * the end. |
1732 | */ | 1620 | */ |
1733 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1621 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1734 | bool enable_radio; | 1622 | sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1735 | bool all_wiphys_idle; | 1623 | if (!sc->ps_idle) { |
1736 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
1737 | |||
1738 | spin_lock_bh(&sc->wiphy_lock); | ||
1739 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | ||
1740 | ath9k_set_wiphy_idle(aphy, idle); | ||
1741 | |||
1742 | enable_radio = (!idle && all_wiphys_idle); | ||
1743 | |||
1744 | /* | ||
1745 | * After we unlock here its possible another wiphy | ||
1746 | * can be re-renabled so to account for that we will | ||
1747 | * only disable the radio toward the end of this routine | ||
1748 | * if by then all wiphys are still idle. | ||
1749 | */ | ||
1750 | spin_unlock_bh(&sc->wiphy_lock); | ||
1751 | |||
1752 | if (enable_radio) { | ||
1753 | sc->ps_idle = false; | ||
1754 | ath_radio_enable(sc, hw); | 1624 | ath_radio_enable(sc, hw); |
1755 | ath_dbg(common, ATH_DBG_CONFIG, | 1625 | ath_dbg(common, ATH_DBG_CONFIG, |
1756 | "not-idle: enabling radio\n"); | 1626 | "not-idle: enabling radio\n"); |
1627 | } else { | ||
1628 | disable_radio = true; | ||
1757 | } | 1629 | } |
1758 | } | 1630 | } |
1759 | 1631 | ||
@@ -1794,29 +1666,16 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1794 | if (ah->curchan) | 1666 | if (ah->curchan) |
1795 | old_pos = ah->curchan - &ah->channels[0]; | 1667 | old_pos = ah->curchan - &ah->channels[0]; |
1796 | 1668 | ||
1797 | aphy->chan_idx = pos; | ||
1798 | aphy->chan_is_ht = conf_is_ht(conf); | ||
1799 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | 1669 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) |
1800 | sc->sc_flags |= SC_OP_OFFCHANNEL; | 1670 | sc->sc_flags |= SC_OP_OFFCHANNEL; |
1801 | else | 1671 | else |
1802 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | 1672 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; |
1803 | 1673 | ||
1804 | if (aphy->state == ATH_WIPHY_SCAN || | ||
1805 | aphy->state == ATH_WIPHY_ACTIVE) | ||
1806 | ath9k_wiphy_pause_all_forced(sc, aphy); | ||
1807 | else { | ||
1808 | /* | ||
1809 | * Do not change operational channel based on a paused | ||
1810 | * wiphy changes. | ||
1811 | */ | ||
1812 | goto skip_chan_change; | ||
1813 | } | ||
1814 | |||
1815 | ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 1674 | ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
1816 | curchan->center_freq); | 1675 | curchan->center_freq); |
1817 | 1676 | ||
1818 | /* XXX: remove me eventualy */ | 1677 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], |
1819 | ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); | 1678 | curchan, conf->channel_type); |
1820 | 1679 | ||
1821 | /* update survey stats for the old channel before switching */ | 1680 | /* update survey stats for the old channel before switching */ |
1822 | spin_lock_irqsave(&common->cc_lock, flags); | 1681 | spin_lock_irqsave(&common->cc_lock, flags); |
@@ -1858,7 +1717,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1858 | ath_update_survey_nf(sc, old_pos); | 1717 | ath_update_survey_nf(sc, old_pos); |
1859 | } | 1718 | } |
1860 | 1719 | ||
1861 | skip_chan_change: | ||
1862 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1720 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1863 | sc->config.txpowlimit = 2 * conf->power_level; | 1721 | sc->config.txpowlimit = 2 * conf->power_level; |
1864 | ath9k_ps_wakeup(sc); | 1722 | ath9k_ps_wakeup(sc); |
@@ -1866,13 +1724,8 @@ skip_chan_change: | |||
1866 | ath9k_ps_restore(sc); | 1724 | ath9k_ps_restore(sc); |
1867 | } | 1725 | } |
1868 | 1726 | ||
1869 | spin_lock_bh(&sc->wiphy_lock); | ||
1870 | disable_radio = ath9k_all_wiphys_idle(sc); | ||
1871 | spin_unlock_bh(&sc->wiphy_lock); | ||
1872 | |||
1873 | if (disable_radio) { | 1727 | if (disable_radio) { |
1874 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); | 1728 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); |
1875 | sc->ps_idle = true; | ||
1876 | ath_radio_disable(sc, hw); | 1729 | ath_radio_disable(sc, hw); |
1877 | } | 1730 | } |
1878 | 1731 | ||
@@ -1897,8 +1750,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
1897 | unsigned int *total_flags, | 1750 | unsigned int *total_flags, |
1898 | u64 multicast) | 1751 | u64 multicast) |
1899 | { | 1752 | { |
1900 | struct ath_wiphy *aphy = hw->priv; | 1753 | struct ath_softc *sc = hw->priv; |
1901 | struct ath_softc *sc = aphy->sc; | ||
1902 | u32 rfilt; | 1754 | u32 rfilt; |
1903 | 1755 | ||
1904 | changed_flags &= SUPPORTED_FILTERS; | 1756 | changed_flags &= SUPPORTED_FILTERS; |
@@ -1918,8 +1770,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
1918 | struct ieee80211_vif *vif, | 1770 | struct ieee80211_vif *vif, |
1919 | struct ieee80211_sta *sta) | 1771 | struct ieee80211_sta *sta) |
1920 | { | 1772 | { |
1921 | struct ath_wiphy *aphy = hw->priv; | 1773 | struct ath_softc *sc = hw->priv; |
1922 | struct ath_softc *sc = aphy->sc; | ||
1923 | 1774 | ||
1924 | ath_node_attach(sc, sta); | 1775 | ath_node_attach(sc, sta); |
1925 | 1776 | ||
@@ -1930,8 +1781,7 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, | |||
1930 | struct ieee80211_vif *vif, | 1781 | struct ieee80211_vif *vif, |
1931 | struct ieee80211_sta *sta) | 1782 | struct ieee80211_sta *sta) |
1932 | { | 1783 | { |
1933 | struct ath_wiphy *aphy = hw->priv; | 1784 | struct ath_softc *sc = hw->priv; |
1934 | struct ath_softc *sc = aphy->sc; | ||
1935 | 1785 | ||
1936 | ath_node_detach(sc, sta); | 1786 | ath_node_detach(sc, sta); |
1937 | 1787 | ||
@@ -1941,8 +1791,7 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, | |||
1941 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1791 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
1942 | const struct ieee80211_tx_queue_params *params) | 1792 | const struct ieee80211_tx_queue_params *params) |
1943 | { | 1793 | { |
1944 | struct ath_wiphy *aphy = hw->priv; | 1794 | struct ath_softc *sc = hw->priv; |
1945 | struct ath_softc *sc = aphy->sc; | ||
1946 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1795 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1947 | struct ath_txq *txq; | 1796 | struct ath_txq *txq; |
1948 | struct ath9k_tx_queue_info qi; | 1797 | struct ath9k_tx_queue_info qi; |
@@ -1986,8 +1835,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1986 | struct ieee80211_sta *sta, | 1835 | struct ieee80211_sta *sta, |
1987 | struct ieee80211_key_conf *key) | 1836 | struct ieee80211_key_conf *key) |
1988 | { | 1837 | { |
1989 | struct ath_wiphy *aphy = hw->priv; | 1838 | struct ath_softc *sc = hw->priv; |
1990 | struct ath_softc *sc = aphy->sc; | ||
1991 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1839 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1992 | int ret = 0; | 1840 | int ret = 0; |
1993 | 1841 | ||
@@ -2031,8 +1879,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2031 | struct ieee80211_bss_conf *bss_conf, | 1879 | struct ieee80211_bss_conf *bss_conf, |
2032 | u32 changed) | 1880 | u32 changed) |
2033 | { | 1881 | { |
2034 | struct ath_wiphy *aphy = hw->priv; | 1882 | struct ath_softc *sc = hw->priv; |
2035 | struct ath_softc *sc = aphy->sc; | ||
2036 | struct ath_hw *ah = sc->sc_ah; | 1883 | struct ath_hw *ah = sc->sc_ah; |
2037 | struct ath_common *common = ath9k_hw_common(ah); | 1884 | struct ath_common *common = ath9k_hw_common(ah); |
2038 | struct ath_vif *avp = (void *)vif->drv_priv; | 1885 | struct ath_vif *avp = (void *)vif->drv_priv; |
@@ -2062,7 +1909,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2062 | if ((changed & BSS_CHANGED_BEACON) || | 1909 | if ((changed & BSS_CHANGED_BEACON) || |
2063 | ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { | 1910 | ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { |
2064 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 1911 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2065 | error = ath_beacon_alloc(aphy, vif); | 1912 | error = ath_beacon_alloc(sc, vif); |
2066 | if (!error) | 1913 | if (!error) |
2067 | ath_beacon_config(sc, vif); | 1914 | ath_beacon_config(sc, vif); |
2068 | } | 1915 | } |
@@ -2099,7 +1946,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2099 | if (vif->type == NL80211_IFTYPE_AP) { | 1946 | if (vif->type == NL80211_IFTYPE_AP) { |
2100 | sc->sc_flags |= SC_OP_TSF_RESET; | 1947 | sc->sc_flags |= SC_OP_TSF_RESET; |
2101 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 1948 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2102 | error = ath_beacon_alloc(aphy, vif); | 1949 | error = ath_beacon_alloc(sc, vif); |
2103 | if (!error) | 1950 | if (!error) |
2104 | ath_beacon_config(sc, vif); | 1951 | ath_beacon_config(sc, vif); |
2105 | } else { | 1952 | } else { |
@@ -2137,9 +1984,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2137 | 1984 | ||
2138 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | 1985 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) |
2139 | { | 1986 | { |
1987 | struct ath_softc *sc = hw->priv; | ||
2140 | u64 tsf; | 1988 | u64 tsf; |
2141 | struct ath_wiphy *aphy = hw->priv; | ||
2142 | struct ath_softc *sc = aphy->sc; | ||
2143 | 1989 | ||
2144 | mutex_lock(&sc->mutex); | 1990 | mutex_lock(&sc->mutex); |
2145 | ath9k_ps_wakeup(sc); | 1991 | ath9k_ps_wakeup(sc); |
@@ -2152,8 +1998,7 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | |||
2152 | 1998 | ||
2153 | static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 1999 | static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) |
2154 | { | 2000 | { |
2155 | struct ath_wiphy *aphy = hw->priv; | 2001 | struct ath_softc *sc = hw->priv; |
2156 | struct ath_softc *sc = aphy->sc; | ||
2157 | 2002 | ||
2158 | mutex_lock(&sc->mutex); | 2003 | mutex_lock(&sc->mutex); |
2159 | ath9k_ps_wakeup(sc); | 2004 | ath9k_ps_wakeup(sc); |
@@ -2164,8 +2009,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | |||
2164 | 2009 | ||
2165 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) | 2010 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) |
2166 | { | 2011 | { |
2167 | struct ath_wiphy *aphy = hw->priv; | 2012 | struct ath_softc *sc = hw->priv; |
2168 | struct ath_softc *sc = aphy->sc; | ||
2169 | 2013 | ||
2170 | mutex_lock(&sc->mutex); | 2014 | mutex_lock(&sc->mutex); |
2171 | 2015 | ||
@@ -2182,8 +2026,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2182 | struct ieee80211_sta *sta, | 2026 | struct ieee80211_sta *sta, |
2183 | u16 tid, u16 *ssn, u8 buf_size) | 2027 | u16 tid, u16 *ssn, u8 buf_size) |
2184 | { | 2028 | { |
2185 | struct ath_wiphy *aphy = hw->priv; | 2029 | struct ath_softc *sc = hw->priv; |
2186 | struct ath_softc *sc = aphy->sc; | ||
2187 | int ret = 0; | 2030 | int ret = 0; |
2188 | 2031 | ||
2189 | local_bh_disable(); | 2032 | local_bh_disable(); |
@@ -2228,8 +2071,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2228 | static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | 2071 | static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, |
2229 | struct survey_info *survey) | 2072 | struct survey_info *survey) |
2230 | { | 2073 | { |
2231 | struct ath_wiphy *aphy = hw->priv; | 2074 | struct ath_softc *sc = hw->priv; |
2232 | struct ath_softc *sc = aphy->sc; | ||
2233 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2075 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2234 | struct ieee80211_supported_band *sband; | 2076 | struct ieee80211_supported_band *sband; |
2235 | struct ieee80211_channel *chan; | 2077 | struct ieee80211_channel *chan; |
@@ -2263,47 +2105,9 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | |||
2263 | return 0; | 2105 | return 0; |
2264 | } | 2106 | } |
2265 | 2107 | ||
2266 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | ||
2267 | { | ||
2268 | struct ath_wiphy *aphy = hw->priv; | ||
2269 | struct ath_softc *sc = aphy->sc; | ||
2270 | |||
2271 | mutex_lock(&sc->mutex); | ||
2272 | if (ath9k_wiphy_scanning(sc)) { | ||
2273 | /* | ||
2274 | * There is a race here in mac80211 but fixing it requires | ||
2275 | * we revisit how we handle the scan complete callback. | ||
2276 | * After mac80211 fixes we will not have configured hardware | ||
2277 | * to the home channel nor would we have configured the RX | ||
2278 | * filter yet. | ||
2279 | */ | ||
2280 | mutex_unlock(&sc->mutex); | ||
2281 | return; | ||
2282 | } | ||
2283 | |||
2284 | aphy->state = ATH_WIPHY_SCAN; | ||
2285 | ath9k_wiphy_pause_all_forced(sc, aphy); | ||
2286 | mutex_unlock(&sc->mutex); | ||
2287 | } | ||
2288 | |||
2289 | /* | ||
2290 | * XXX: this requires a revisit after the driver | ||
2291 | * scan_complete gets moved to another place/removed in mac80211. | ||
2292 | */ | ||
2293 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | ||
2294 | { | ||
2295 | struct ath_wiphy *aphy = hw->priv; | ||
2296 | struct ath_softc *sc = aphy->sc; | ||
2297 | |||
2298 | mutex_lock(&sc->mutex); | ||
2299 | aphy->state = ATH_WIPHY_ACTIVE; | ||
2300 | mutex_unlock(&sc->mutex); | ||
2301 | } | ||
2302 | |||
2303 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | 2108 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) |
2304 | { | 2109 | { |
2305 | struct ath_wiphy *aphy = hw->priv; | 2110 | struct ath_softc *sc = hw->priv; |
2306 | struct ath_softc *sc = aphy->sc; | ||
2307 | struct ath_hw *ah = sc->sc_ah; | 2111 | struct ath_hw *ah = sc->sc_ah; |
2308 | 2112 | ||
2309 | mutex_lock(&sc->mutex); | 2113 | mutex_lock(&sc->mutex); |
@@ -2331,8 +2135,6 @@ struct ieee80211_ops ath9k_ops = { | |||
2331 | .reset_tsf = ath9k_reset_tsf, | 2135 | .reset_tsf = ath9k_reset_tsf, |
2332 | .ampdu_action = ath9k_ampdu_action, | 2136 | .ampdu_action = ath9k_ampdu_action, |
2333 | .get_survey = ath9k_get_survey, | 2137 | .get_survey = ath9k_get_survey, |
2334 | .sw_scan_start = ath9k_sw_scan_start, | ||
2335 | .sw_scan_complete = ath9k_sw_scan_complete, | ||
2336 | .rfkill_poll = ath9k_rfkill_poll_state, | 2138 | .rfkill_poll = ath9k_rfkill_poll_state, |
2337 | .set_coverage_class = ath9k_set_coverage_class, | 2139 | .set_coverage_class = ath9k_set_coverage_class, |
2338 | }; | 2140 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 78ef1f13386f..e83128c50f7b 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -126,7 +126,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = { | |||
126 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 126 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
127 | { | 127 | { |
128 | void __iomem *mem; | 128 | void __iomem *mem; |
129 | struct ath_wiphy *aphy; | ||
130 | struct ath_softc *sc; | 129 | struct ath_softc *sc; |
131 | struct ieee80211_hw *hw; | 130 | struct ieee80211_hw *hw; |
132 | u8 csz; | 131 | u8 csz; |
@@ -198,8 +197,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
198 | goto err_iomap; | 197 | goto err_iomap; |
199 | } | 198 | } |
200 | 199 | ||
201 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 200 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
202 | sizeof(struct ath_softc), &ath9k_ops); | ||
203 | if (!hw) { | 201 | if (!hw) { |
204 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); | 202 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
205 | ret = -ENOMEM; | 203 | ret = -ENOMEM; |
@@ -209,11 +207,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
209 | SET_IEEE80211_DEV(hw, &pdev->dev); | 207 | SET_IEEE80211_DEV(hw, &pdev->dev); |
210 | pci_set_drvdata(pdev, hw); | 208 | pci_set_drvdata(pdev, hw); |
211 | 209 | ||
212 | aphy = hw->priv; | 210 | sc = hw->priv; |
213 | sc = (struct ath_softc *) (aphy + 1); | ||
214 | aphy->sc = sc; | ||
215 | aphy->hw = hw; | ||
216 | sc->pri_wiphy = aphy; | ||
217 | sc->hw = hw; | 211 | sc->hw = hw; |
218 | sc->dev = &pdev->dev; | 212 | sc->dev = &pdev->dev; |
219 | sc->mem = mem; | 213 | sc->mem = mem; |
@@ -260,8 +254,7 @@ err_dma: | |||
260 | static void ath_pci_remove(struct pci_dev *pdev) | 254 | static void ath_pci_remove(struct pci_dev *pdev) |
261 | { | 255 | { |
262 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 256 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
263 | struct ath_wiphy *aphy = hw->priv; | 257 | struct ath_softc *sc = hw->priv; |
264 | struct ath_softc *sc = aphy->sc; | ||
265 | void __iomem *mem = sc->mem; | 258 | void __iomem *mem = sc->mem; |
266 | 259 | ||
267 | if (!is_ath9k_unloaded) | 260 | if (!is_ath9k_unloaded) |
@@ -281,8 +274,7 @@ static int ath_pci_suspend(struct device *device) | |||
281 | { | 274 | { |
282 | struct pci_dev *pdev = to_pci_dev(device); | 275 | struct pci_dev *pdev = to_pci_dev(device); |
283 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 276 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
284 | struct ath_wiphy *aphy = hw->priv; | 277 | struct ath_softc *sc = hw->priv; |
285 | struct ath_softc *sc = aphy->sc; | ||
286 | 278 | ||
287 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 279 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
288 | 280 | ||
@@ -293,8 +285,7 @@ static int ath_pci_resume(struct device *device) | |||
293 | { | 285 | { |
294 | struct pci_dev *pdev = to_pci_dev(device); | 286 | struct pci_dev *pdev = to_pci_dev(device); |
295 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 287 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
296 | struct ath_wiphy *aphy = hw->priv; | 288 | struct ath_softc *sc = hw->priv; |
297 | struct ath_softc *sc = aphy->sc; | ||
298 | u32 val; | 289 | u32 val; |
299 | 290 | ||
300 | /* | 291 | /* |
@@ -320,7 +311,6 @@ static int ath_pci_resume(struct device *device) | |||
320 | ath9k_ps_restore(sc); | 311 | ath9k_ps_restore(sc); |
321 | 312 | ||
322 | sc->ps_idle = true; | 313 | sc->ps_idle = true; |
323 | ath9k_set_wiphy_idle(aphy, true); | ||
324 | ath_radio_disable(sc, hw); | 314 | ath_radio_disable(sc, hw); |
325 | 315 | ||
326 | return 0; | 316 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e45147820eae..960d717ca7c2 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1560,8 +1560,7 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, | |||
1560 | 1560 | ||
1561 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 1561 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
1562 | { | 1562 | { |
1563 | struct ath_wiphy *aphy = hw->priv; | 1563 | return hw->priv; |
1564 | return aphy->sc; | ||
1565 | } | 1564 | } |
1566 | 1565 | ||
1567 | static void ath_rate_free(void *priv) | 1566 | static void ath_rate_free(void *priv) |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 116f0582af24..daf171d2f610 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -34,27 +34,6 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | |||
34 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | 34 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); |
35 | } | 35 | } |
36 | 36 | ||
37 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, | ||
38 | struct ieee80211_hdr *hdr) | ||
39 | { | ||
40 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
41 | int i; | ||
42 | |||
43 | spin_lock_bh(&sc->wiphy_lock); | ||
44 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
45 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
46 | if (aphy == NULL) | ||
47 | continue; | ||
48 | if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) | ||
49 | == 0) { | ||
50 | hw = aphy->hw; | ||
51 | break; | ||
52 | } | ||
53 | } | ||
54 | spin_unlock_bh(&sc->wiphy_lock); | ||
55 | return hw; | ||
56 | } | ||
57 | |||
58 | /* | 37 | /* |
59 | * Setup and link descriptors. | 38 | * Setup and link descriptors. |
60 | * | 39 | * |
@@ -230,11 +209,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
230 | int error = 0, i; | 209 | int error = 0, i; |
231 | u32 size; | 210 | u32 size; |
232 | 211 | ||
233 | |||
234 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN + | ||
235 | ah->caps.rx_status_len, | ||
236 | min(common->cachelsz, (u16)64)); | ||
237 | |||
238 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - | 212 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - |
239 | ah->caps.rx_status_len); | 213 | ah->caps.rx_status_len); |
240 | 214 | ||
@@ -321,12 +295,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
321 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 295 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
322 | spin_lock_init(&sc->rx.rxbuflock); | 296 | spin_lock_init(&sc->rx.rxbuflock); |
323 | 297 | ||
298 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | ||
299 | sc->sc_ah->caps.rx_status_len; | ||
300 | |||
324 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 301 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
325 | return ath_rx_edma_init(sc, nbufs); | 302 | return ath_rx_edma_init(sc, nbufs); |
326 | } else { | 303 | } else { |
327 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, | ||
328 | min(common->cachelsz, (u16)64)); | ||
329 | |||
330 | ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", | 304 | ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", |
331 | common->cachelsz, common->rx_bufsize); | 305 | common->cachelsz, common->rx_bufsize); |
332 | 306 | ||
@@ -463,8 +437,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
463 | if (conf_is_ht(&sc->hw->conf)) | 437 | if (conf_is_ht(&sc->hw->conf)) |
464 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 438 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
465 | 439 | ||
466 | if (sc->sec_wiphy || (sc->nvifs > 1) || | 440 | if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
467 | (sc->rx.rxfilter & FIF_OTHER_BSS)) { | ||
468 | /* The following may also be needed for other older chips */ | 441 | /* The following may also be needed for other older chips */ |
469 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 442 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
470 | rfilt |= ATH9K_RX_FILTER_PROM; | 443 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -668,37 +641,6 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
668 | } | 641 | } |
669 | } | 642 | } |
670 | 643 | ||
671 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | ||
672 | struct ath_softc *sc, struct sk_buff *skb) | ||
673 | { | ||
674 | struct ieee80211_hdr *hdr; | ||
675 | |||
676 | hdr = (struct ieee80211_hdr *)skb->data; | ||
677 | |||
678 | /* Send the frame to mac80211 */ | ||
679 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
680 | int i; | ||
681 | /* | ||
682 | * Deliver broadcast/multicast frames to all suitable | ||
683 | * virtual wiphys. | ||
684 | */ | ||
685 | /* TODO: filter based on channel configuration */ | ||
686 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
687 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
688 | struct sk_buff *nskb; | ||
689 | if (aphy == NULL) | ||
690 | continue; | ||
691 | nskb = skb_copy(skb, GFP_ATOMIC); | ||
692 | if (!nskb) | ||
693 | continue; | ||
694 | ieee80211_rx(aphy->hw, nskb); | ||
695 | } | ||
696 | ieee80211_rx(sc->hw, skb); | ||
697 | } else | ||
698 | /* Deliver unicast frames based on receiver address */ | ||
699 | ieee80211_rx(hw, skb); | ||
700 | } | ||
701 | |||
702 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 644 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
703 | enum ath9k_rx_qtype qtype) | 645 | enum ath9k_rx_qtype qtype) |
704 | { | 646 | { |
@@ -868,15 +810,9 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
868 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) | 810 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) |
869 | return false; | 811 | return false; |
870 | 812 | ||
871 | /* | 813 | /* Only use error bits from the last fragment */ |
872 | * rs_more indicates chained descriptors which can be used | ||
873 | * to link buffers together for a sort of scatter-gather | ||
874 | * operation. | ||
875 | * reject the frame, we don't support scatter-gather yet and | ||
876 | * the frame is probably corrupt anyway | ||
877 | */ | ||
878 | if (rx_stats->rs_more) | 814 | if (rx_stats->rs_more) |
879 | return false; | 815 | return true; |
880 | 816 | ||
881 | /* | 817 | /* |
882 | * The rx_stats->rs_status will not be set until the end of the | 818 | * The rx_stats->rs_status will not be set until the end of the |
@@ -980,7 +916,7 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
980 | struct ieee80211_hdr *hdr, | 916 | struct ieee80211_hdr *hdr, |
981 | struct ath_rx_status *rx_stats) | 917 | struct ath_rx_status *rx_stats) |
982 | { | 918 | { |
983 | struct ath_wiphy *aphy = hw->priv; | 919 | struct ath_softc *sc = hw->priv; |
984 | struct ath_hw *ah = common->ah; | 920 | struct ath_hw *ah = common->ah; |
985 | int last_rssi; | 921 | int last_rssi; |
986 | __le16 fc; | 922 | __le16 fc; |
@@ -1000,9 +936,9 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
1000 | } | 936 | } |
1001 | 937 | ||
1002 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) | 938 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) |
1003 | ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); | 939 | ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); |
1004 | 940 | ||
1005 | last_rssi = aphy->last_rssi; | 941 | last_rssi = sc->last_rssi; |
1006 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 942 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
1007 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, | 943 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, |
1008 | ATH_RSSI_EP_MULTIPLIER); | 944 | ATH_RSSI_EP_MULTIPLIER); |
@@ -1034,6 +970,10 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1034 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | 970 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) |
1035 | return -EINVAL; | 971 | return -EINVAL; |
1036 | 972 | ||
973 | /* Only use status info from the last fragment */ | ||
974 | if (rx_stats->rs_more) | ||
975 | return 0; | ||
976 | |||
1037 | ath9k_process_rssi(common, hw, hdr, rx_stats); | 977 | ath9k_process_rssi(common, hw, hdr, rx_stats); |
1038 | 978 | ||
1039 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 979 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) |
@@ -1635,7 +1575,7 @@ div_comb_done: | |||
1635 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1575 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1636 | { | 1576 | { |
1637 | struct ath_buf *bf; | 1577 | struct ath_buf *bf; |
1638 | struct sk_buff *skb = NULL, *requeue_skb; | 1578 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; |
1639 | struct ieee80211_rx_status *rxs; | 1579 | struct ieee80211_rx_status *rxs; |
1640 | struct ath_hw *ah = sc->sc_ah; | 1580 | struct ath_hw *ah = sc->sc_ah; |
1641 | struct ath_common *common = ath9k_hw_common(ah); | 1581 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1644,7 +1584,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1644 | * virtual wiphy so to account for that we iterate over the active | 1584 | * virtual wiphy so to account for that we iterate over the active |
1645 | * wiphys and find the appropriate wiphy and therefore hw. | 1585 | * wiphys and find the appropriate wiphy and therefore hw. |
1646 | */ | 1586 | */ |
1647 | struct ieee80211_hw *hw = NULL; | 1587 | struct ieee80211_hw *hw = sc->hw; |
1648 | struct ieee80211_hdr *hdr; | 1588 | struct ieee80211_hdr *hdr; |
1649 | int retval; | 1589 | int retval; |
1650 | bool decrypt_error = false; | 1590 | bool decrypt_error = false; |
@@ -1686,10 +1626,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1686 | if (!skb) | 1626 | if (!skb) |
1687 | continue; | 1627 | continue; |
1688 | 1628 | ||
1689 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); | 1629 | /* |
1690 | rxs = IEEE80211_SKB_RXCB(skb); | 1630 | * Take frame header from the first fragment and RX status from |
1631 | * the last one. | ||
1632 | */ | ||
1633 | if (sc->rx.frag) | ||
1634 | hdr_skb = sc->rx.frag; | ||
1635 | else | ||
1636 | hdr_skb = skb; | ||
1691 | 1637 | ||
1692 | hw = ath_get_virt_hw(sc, hdr); | 1638 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1639 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | ||
1693 | 1640 | ||
1694 | ath_debug_stat_rx(sc, &rs); | 1641 | ath_debug_stat_rx(sc, &rs); |
1695 | 1642 | ||
@@ -1698,12 +1645,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1698 | * chain it back at the queue without processing it. | 1645 | * chain it back at the queue without processing it. |
1699 | */ | 1646 | */ |
1700 | if (flush) | 1647 | if (flush) |
1701 | goto requeue; | 1648 | goto requeue_drop_frag; |
1702 | 1649 | ||
1703 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1650 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, |
1704 | rxs, &decrypt_error); | 1651 | rxs, &decrypt_error); |
1705 | if (retval) | 1652 | if (retval) |
1706 | goto requeue; | 1653 | goto requeue_drop_frag; |
1707 | 1654 | ||
1708 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1655 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1709 | if (rs.rs_tstamp > tsf_lower && | 1656 | if (rs.rs_tstamp > tsf_lower && |
@@ -1723,7 +1670,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1723 | * skb and put it at the tail of the sc->rx.rxbuf list for | 1670 | * skb and put it at the tail of the sc->rx.rxbuf list for |
1724 | * processing. */ | 1671 | * processing. */ |
1725 | if (!requeue_skb) | 1672 | if (!requeue_skb) |
1726 | goto requeue; | 1673 | goto requeue_drop_frag; |
1727 | 1674 | ||
1728 | /* Unmap the frame */ | 1675 | /* Unmap the frame */ |
1729 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 1676 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
@@ -1734,8 +1681,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1734 | if (ah->caps.rx_status_len) | 1681 | if (ah->caps.rx_status_len) |
1735 | skb_pull(skb, ah->caps.rx_status_len); | 1682 | skb_pull(skb, ah->caps.rx_status_len); |
1736 | 1683 | ||
1737 | ath9k_rx_skb_postprocess(common, skb, &rs, | 1684 | if (!rs.rs_more) |
1738 | rxs, decrypt_error); | 1685 | ath9k_rx_skb_postprocess(common, hdr_skb, &rs, |
1686 | rxs, decrypt_error); | ||
1739 | 1687 | ||
1740 | /* We will now give hardware our shiny new allocated skb */ | 1688 | /* We will now give hardware our shiny new allocated skb */ |
1741 | bf->bf_mpdu = requeue_skb; | 1689 | bf->bf_mpdu = requeue_skb; |
@@ -1748,10 +1696,42 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1748 | bf->bf_mpdu = NULL; | 1696 | bf->bf_mpdu = NULL; |
1749 | bf->bf_buf_addr = 0; | 1697 | bf->bf_buf_addr = 0; |
1750 | ath_err(common, "dma_mapping_error() on RX\n"); | 1698 | ath_err(common, "dma_mapping_error() on RX\n"); |
1751 | ath_rx_send_to_mac80211(hw, sc, skb); | 1699 | ieee80211_rx(hw, skb); |
1752 | break; | 1700 | break; |
1753 | } | 1701 | } |
1754 | 1702 | ||
1703 | if (rs.rs_more) { | ||
1704 | /* | ||
1705 | * rs_more indicates chained descriptors which can be | ||
1706 | * used to link buffers together for a sort of | ||
1707 | * scatter-gather operation. | ||
1708 | */ | ||
1709 | if (sc->rx.frag) { | ||
1710 | /* too many fragments - cannot handle frame */ | ||
1711 | dev_kfree_skb_any(sc->rx.frag); | ||
1712 | dev_kfree_skb_any(skb); | ||
1713 | skb = NULL; | ||
1714 | } | ||
1715 | sc->rx.frag = skb; | ||
1716 | goto requeue; | ||
1717 | } | ||
1718 | |||
1719 | if (sc->rx.frag) { | ||
1720 | int space = skb->len - skb_tailroom(hdr_skb); | ||
1721 | |||
1722 | sc->rx.frag = NULL; | ||
1723 | |||
1724 | if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { | ||
1725 | dev_kfree_skb(skb); | ||
1726 | goto requeue_drop_frag; | ||
1727 | } | ||
1728 | |||
1729 | skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len), | ||
1730 | skb->len); | ||
1731 | dev_kfree_skb_any(skb); | ||
1732 | skb = hdr_skb; | ||
1733 | } | ||
1734 | |||
1755 | /* | 1735 | /* |
1756 | * change the default rx antenna if rx diversity chooses the | 1736 | * change the default rx antenna if rx diversity chooses the |
1757 | * other antenna 3 times in a row. | 1737 | * other antenna 3 times in a row. |
@@ -1775,8 +1755,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1775 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | 1755 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
1776 | ath_ant_comb_scan(sc, &rs); | 1756 | ath_ant_comb_scan(sc, &rs); |
1777 | 1757 | ||
1778 | ath_rx_send_to_mac80211(hw, sc, skb); | 1758 | ieee80211_rx(hw, skb); |
1779 | 1759 | ||
1760 | requeue_drop_frag: | ||
1761 | if (sc->rx.frag) { | ||
1762 | dev_kfree_skb_any(sc->rx.frag); | ||
1763 | sc->rx.frag = NULL; | ||
1764 | } | ||
1780 | requeue: | 1765 | requeue: |
1781 | if (edma) { | 1766 | if (edma) { |
1782 | list_add_tail(&bf->list, &sc->rx.rxbuf); | 1767 | list_add_tail(&bf->list, &sc->rx.rxbuf); |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 4df5659c6c16..b262e98709de 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -1083,6 +1083,17 @@ enum { | |||
1083 | #define AR_ENT_OTP 0x40d8 | 1083 | #define AR_ENT_OTP 0x40d8 |
1084 | #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 | 1084 | #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 |
1085 | #define AR_ENT_OTP_MPSD 0x00800000 | 1085 | #define AR_ENT_OTP_MPSD 0x00800000 |
1086 | #define AR_CH0_BB_DPLL2 0x16184 | ||
1087 | #define AR_CH0_BB_DPLL3 0x16188 | ||
1088 | #define AR_CH0_DDR_DPLL2 0x16244 | ||
1089 | #define AR_CH0_DDR_DPLL3 0x16248 | ||
1090 | #define AR_CH0_DPLL2_KD 0x03F80000 | ||
1091 | #define AR_CH0_DPLL2_KD_S 19 | ||
1092 | #define AR_CH0_DPLL2_KI 0x3C000000 | ||
1093 | #define AR_CH0_DPLL2_KI_S 26 | ||
1094 | #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 | ||
1095 | #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 | ||
1096 | #define AR_PHY_CCA_NOM_VAL_2GHZ -118 | ||
1086 | 1097 | ||
1087 | #define AR_RTC_9300_PLL_DIV 0x000003ff | 1098 | #define AR_RTC_9300_PLL_DIV 0x000003ff |
1088 | #define AR_RTC_9300_PLL_DIV_S 0 | 1099 | #define AR_RTC_9300_PLL_DIV_S 0 |
@@ -1129,6 +1140,12 @@ enum { | |||
1129 | #define AR_RTC_PLL_CLKSEL 0x00000300 | 1140 | #define AR_RTC_PLL_CLKSEL 0x00000300 |
1130 | #define AR_RTC_PLL_CLKSEL_S 8 | 1141 | #define AR_RTC_PLL_CLKSEL_S 8 |
1131 | 1142 | ||
1143 | #define PLL3 0x16188 | ||
1144 | #define PLL3_DO_MEAS_MASK 0x40000000 | ||
1145 | #define PLL4 0x1618c | ||
1146 | #define PLL4_MEAS_DONE 0x8 | ||
1147 | #define SQSUM_DVC_MASK 0x007ffff8 | ||
1148 | |||
1132 | #define AR_RTC_RESET \ | 1149 | #define AR_RTC_RESET \ |
1133 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) | 1150 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) |
1134 | #define AR_RTC_RESET_EN (0x00000001) | 1151 | #define AR_RTC_RESET_EN (0x00000001) |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c deleted file mode 100644 index d205c66cd972..000000000000 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ /dev/null | |||
@@ -1,669 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 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 <linux/slab.h> | ||
18 | |||
19 | #include "ath9k.h" | ||
20 | |||
21 | int ath9k_wiphy_add(struct ath_softc *sc) | ||
22 | { | ||
23 | int i, error; | ||
24 | struct ath_wiphy *aphy; | ||
25 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
26 | struct ieee80211_hw *hw; | ||
27 | u8 addr[ETH_ALEN]; | ||
28 | |||
29 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); | ||
30 | if (hw == NULL) | ||
31 | return -ENOMEM; | ||
32 | |||
33 | spin_lock_bh(&sc->wiphy_lock); | ||
34 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
35 | if (sc->sec_wiphy[i] == NULL) | ||
36 | break; | ||
37 | } | ||
38 | |||
39 | if (i == sc->num_sec_wiphy) { | ||
40 | /* No empty slot available; increase array length */ | ||
41 | struct ath_wiphy **n; | ||
42 | n = krealloc(sc->sec_wiphy, | ||
43 | (sc->num_sec_wiphy + 1) * | ||
44 | sizeof(struct ath_wiphy *), | ||
45 | GFP_ATOMIC); | ||
46 | if (n == NULL) { | ||
47 | spin_unlock_bh(&sc->wiphy_lock); | ||
48 | ieee80211_free_hw(hw); | ||
49 | return -ENOMEM; | ||
50 | } | ||
51 | n[i] = NULL; | ||
52 | sc->sec_wiphy = n; | ||
53 | sc->num_sec_wiphy++; | ||
54 | } | ||
55 | |||
56 | SET_IEEE80211_DEV(hw, sc->dev); | ||
57 | |||
58 | aphy = hw->priv; | ||
59 | aphy->sc = sc; | ||
60 | aphy->hw = hw; | ||
61 | sc->sec_wiphy[i] = aphy; | ||
62 | aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
63 | spin_unlock_bh(&sc->wiphy_lock); | ||
64 | |||
65 | memcpy(addr, common->macaddr, ETH_ALEN); | ||
66 | addr[0] |= 0x02; /* Locally managed address */ | ||
67 | /* | ||
68 | * XOR virtual wiphy index into the least significant bits to generate | ||
69 | * a different MAC address for each virtual wiphy. | ||
70 | */ | ||
71 | addr[5] ^= i & 0xff; | ||
72 | addr[4] ^= (i & 0xff00) >> 8; | ||
73 | addr[3] ^= (i & 0xff0000) >> 16; | ||
74 | |||
75 | SET_IEEE80211_PERM_ADDR(hw, addr); | ||
76 | |||
77 | ath9k_set_hw_capab(sc, hw); | ||
78 | |||
79 | error = ieee80211_register_hw(hw); | ||
80 | |||
81 | if (error == 0) { | ||
82 | /* Make sure wiphy scheduler is started (if enabled) */ | ||
83 | ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); | ||
84 | } | ||
85 | |||
86 | return error; | ||
87 | } | ||
88 | |||
89 | int ath9k_wiphy_del(struct ath_wiphy *aphy) | ||
90 | { | ||
91 | struct ath_softc *sc = aphy->sc; | ||
92 | int i; | ||
93 | |||
94 | spin_lock_bh(&sc->wiphy_lock); | ||
95 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
96 | if (aphy == sc->sec_wiphy[i]) { | ||
97 | sc->sec_wiphy[i] = NULL; | ||
98 | spin_unlock_bh(&sc->wiphy_lock); | ||
99 | ieee80211_unregister_hw(aphy->hw); | ||
100 | ieee80211_free_hw(aphy->hw); | ||
101 | return 0; | ||
102 | } | ||
103 | } | ||
104 | spin_unlock_bh(&sc->wiphy_lock); | ||
105 | return -ENOENT; | ||
106 | } | ||
107 | |||
108 | static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | ||
109 | struct ieee80211_vif *vif, const u8 *bssid, | ||
110 | int ps) | ||
111 | { | ||
112 | struct ath_softc *sc = aphy->sc; | ||
113 | struct ath_tx_control txctl; | ||
114 | struct sk_buff *skb; | ||
115 | struct ieee80211_hdr *hdr; | ||
116 | __le16 fc; | ||
117 | struct ieee80211_tx_info *info; | ||
118 | |||
119 | skb = dev_alloc_skb(24); | ||
120 | if (skb == NULL) | ||
121 | return -ENOMEM; | ||
122 | hdr = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
123 | memset(hdr, 0, 24); | ||
124 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | ||
125 | IEEE80211_FCTL_TODS); | ||
126 | if (ps) | ||
127 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
128 | hdr->frame_control = fc; | ||
129 | memcpy(hdr->addr1, bssid, ETH_ALEN); | ||
130 | memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); | ||
131 | memcpy(hdr->addr3, bssid, ETH_ALEN); | ||
132 | |||
133 | info = IEEE80211_SKB_CB(skb); | ||
134 | memset(info, 0, sizeof(*info)); | ||
135 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
136 | info->control.vif = vif; | ||
137 | info->control.rates[0].idx = 0; | ||
138 | info->control.rates[0].count = 4; | ||
139 | info->control.rates[1].idx = -1; | ||
140 | |||
141 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
142 | txctl.txq = sc->tx.txq_map[WME_AC_VO]; | ||
143 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; | ||
144 | |||
145 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | ||
146 | goto exit; | ||
147 | |||
148 | return 0; | ||
149 | exit: | ||
150 | dev_kfree_skb_any(skb); | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | static bool __ath9k_wiphy_pausing(struct ath_softc *sc) | ||
155 | { | ||
156 | int i; | ||
157 | if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) | ||
158 | return true; | ||
159 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
160 | if (sc->sec_wiphy[i] && | ||
161 | sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) | ||
162 | return true; | ||
163 | } | ||
164 | return false; | ||
165 | } | ||
166 | |||
167 | static bool ath9k_wiphy_pausing(struct ath_softc *sc) | ||
168 | { | ||
169 | bool ret; | ||
170 | spin_lock_bh(&sc->wiphy_lock); | ||
171 | ret = __ath9k_wiphy_pausing(sc); | ||
172 | spin_unlock_bh(&sc->wiphy_lock); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | static bool __ath9k_wiphy_scanning(struct ath_softc *sc) | ||
177 | { | ||
178 | int i; | ||
179 | if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) | ||
180 | return true; | ||
181 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
182 | if (sc->sec_wiphy[i] && | ||
183 | sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) | ||
184 | return true; | ||
185 | } | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | bool ath9k_wiphy_scanning(struct ath_softc *sc) | ||
190 | { | ||
191 | bool ret; | ||
192 | spin_lock_bh(&sc->wiphy_lock); | ||
193 | ret = __ath9k_wiphy_scanning(sc); | ||
194 | spin_unlock_bh(&sc->wiphy_lock); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
199 | |||
200 | /* caller must hold wiphy_lock */ | ||
201 | static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) | ||
202 | { | ||
203 | if (aphy == NULL) | ||
204 | return; | ||
205 | if (aphy->chan_idx != aphy->sc->chan_idx) | ||
206 | return; /* wiphy not on the selected channel */ | ||
207 | __ath9k_wiphy_unpause(aphy); | ||
208 | } | ||
209 | |||
210 | static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) | ||
211 | { | ||
212 | int i; | ||
213 | spin_lock_bh(&sc->wiphy_lock); | ||
214 | __ath9k_wiphy_unpause_ch(sc->pri_wiphy); | ||
215 | for (i = 0; i < sc->num_sec_wiphy; i++) | ||
216 | __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); | ||
217 | spin_unlock_bh(&sc->wiphy_lock); | ||
218 | } | ||
219 | |||
220 | void ath9k_wiphy_chan_work(struct work_struct *work) | ||
221 | { | ||
222 | struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); | ||
223 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
224 | struct ath_wiphy *aphy = sc->next_wiphy; | ||
225 | |||
226 | if (aphy == NULL) | ||
227 | return; | ||
228 | |||
229 | /* | ||
230 | * All pending interfaces paused; ready to change | ||
231 | * channels. | ||
232 | */ | ||
233 | |||
234 | /* Change channels */ | ||
235 | mutex_lock(&sc->mutex); | ||
236 | /* XXX: remove me eventually */ | ||
237 | ath9k_update_ichannel(sc, aphy->hw, | ||
238 | &sc->sc_ah->channels[sc->chan_idx]); | ||
239 | |||
240 | /* sync hw configuration for hw code */ | ||
241 | common->hw = aphy->hw; | ||
242 | |||
243 | if (ath_set_channel(sc, aphy->hw, | ||
244 | &sc->sc_ah->channels[sc->chan_idx]) < 0) { | ||
245 | printk(KERN_DEBUG "ath9k: Failed to set channel for new " | ||
246 | "virtual wiphy\n"); | ||
247 | mutex_unlock(&sc->mutex); | ||
248 | return; | ||
249 | } | ||
250 | mutex_unlock(&sc->mutex); | ||
251 | |||
252 | ath9k_wiphy_unpause_channel(sc); | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * ath9k version of ieee80211_tx_status() for TX frames that are generated | ||
257 | * internally in the driver. | ||
258 | */ | ||
259 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype) | ||
260 | { | ||
261 | struct ath_wiphy *aphy = hw->priv; | ||
262 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
263 | |||
264 | if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) { | ||
265 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { | ||
266 | printk(KERN_DEBUG "ath9k: %s: no ACK for pause " | ||
267 | "frame\n", wiphy_name(hw->wiphy)); | ||
268 | /* | ||
269 | * The AP did not reply; ignore this to allow us to | ||
270 | * continue. | ||
271 | */ | ||
272 | } | ||
273 | aphy->state = ATH_WIPHY_PAUSED; | ||
274 | if (!ath9k_wiphy_pausing(aphy->sc)) { | ||
275 | /* | ||
276 | * Drop from tasklet to work to allow mutex for channel | ||
277 | * change. | ||
278 | */ | ||
279 | ieee80211_queue_work(aphy->sc->hw, | ||
280 | &aphy->sc->chan_work); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | dev_kfree_skb(skb); | ||
285 | } | ||
286 | |||
287 | static void ath9k_mark_paused(struct ath_wiphy *aphy) | ||
288 | { | ||
289 | struct ath_softc *sc = aphy->sc; | ||
290 | aphy->state = ATH_WIPHY_PAUSED; | ||
291 | if (!__ath9k_wiphy_pausing(sc)) | ||
292 | ieee80211_queue_work(sc->hw, &sc->chan_work); | ||
293 | } | ||
294 | |||
295 | static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
296 | { | ||
297 | struct ath_wiphy *aphy = data; | ||
298 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
299 | |||
300 | switch (vif->type) { | ||
301 | case NL80211_IFTYPE_STATION: | ||
302 | if (!vif->bss_conf.assoc) { | ||
303 | ath9k_mark_paused(aphy); | ||
304 | break; | ||
305 | } | ||
306 | /* TODO: could avoid this if already in PS mode */ | ||
307 | if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { | ||
308 | printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", | ||
309 | __func__); | ||
310 | ath9k_mark_paused(aphy); | ||
311 | } | ||
312 | break; | ||
313 | case NL80211_IFTYPE_AP: | ||
314 | /* Beacon transmission is paused by aphy->state change */ | ||
315 | ath9k_mark_paused(aphy); | ||
316 | break; | ||
317 | default: | ||
318 | break; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* caller must hold wiphy_lock */ | ||
323 | static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
324 | { | ||
325 | ieee80211_stop_queues(aphy->hw); | ||
326 | aphy->state = ATH_WIPHY_PAUSING; | ||
327 | /* | ||
328 | * TODO: handle PAUSING->PAUSED for the case where there are multiple | ||
329 | * active vifs (now we do it on the first vif getting ready; should be | ||
330 | * on the last) | ||
331 | */ | ||
332 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, | ||
333 | aphy); | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | int ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
338 | { | ||
339 | int ret; | ||
340 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
341 | ret = __ath9k_wiphy_pause(aphy); | ||
342 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
347 | { | ||
348 | struct ath_wiphy *aphy = data; | ||
349 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
350 | |||
351 | switch (vif->type) { | ||
352 | case NL80211_IFTYPE_STATION: | ||
353 | if (!vif->bss_conf.assoc) | ||
354 | break; | ||
355 | ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); | ||
356 | break; | ||
357 | case NL80211_IFTYPE_AP: | ||
358 | /* Beacon transmission is re-enabled by aphy->state change */ | ||
359 | break; | ||
360 | default: | ||
361 | break; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /* caller must hold wiphy_lock */ | ||
366 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
367 | { | ||
368 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, | ||
369 | ath9k_unpause_iter, aphy); | ||
370 | aphy->state = ATH_WIPHY_ACTIVE; | ||
371 | ieee80211_wake_queues(aphy->hw); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
376 | { | ||
377 | int ret; | ||
378 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
379 | ret = __ath9k_wiphy_unpause(aphy); | ||
380 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) | ||
385 | { | ||
386 | int i; | ||
387 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) | ||
388 | sc->pri_wiphy->state = ATH_WIPHY_PAUSED; | ||
389 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
390 | if (sc->sec_wiphy[i] && | ||
391 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) | ||
392 | sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /* caller must hold wiphy_lock */ | ||
397 | static void __ath9k_wiphy_pause_all(struct ath_softc *sc) | ||
398 | { | ||
399 | int i; | ||
400 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
401 | __ath9k_wiphy_pause(sc->pri_wiphy); | ||
402 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
403 | if (sc->sec_wiphy[i] && | ||
404 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
405 | __ath9k_wiphy_pause(sc->sec_wiphy[i]); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | int ath9k_wiphy_select(struct ath_wiphy *aphy) | ||
410 | { | ||
411 | struct ath_softc *sc = aphy->sc; | ||
412 | bool now; | ||
413 | |||
414 | spin_lock_bh(&sc->wiphy_lock); | ||
415 | if (__ath9k_wiphy_scanning(sc)) { | ||
416 | /* | ||
417 | * For now, we are using mac80211 sw scan and it expects to | ||
418 | * have full control over channel changes, so avoid wiphy | ||
419 | * scheduling during a scan. This could be optimized if the | ||
420 | * scanning control were moved into the driver. | ||
421 | */ | ||
422 | spin_unlock_bh(&sc->wiphy_lock); | ||
423 | return -EBUSY; | ||
424 | } | ||
425 | if (__ath9k_wiphy_pausing(sc)) { | ||
426 | if (sc->wiphy_select_failures == 0) | ||
427 | sc->wiphy_select_first_fail = jiffies; | ||
428 | sc->wiphy_select_failures++; | ||
429 | if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) | ||
430 | { | ||
431 | printk(KERN_DEBUG "ath9k: Previous wiphy select timed " | ||
432 | "out; disable/enable hw to recover\n"); | ||
433 | __ath9k_wiphy_mark_all_paused(sc); | ||
434 | /* | ||
435 | * TODO: this workaround to fix hardware is unlikely to | ||
436 | * be specific to virtual wiphy changes. It can happen | ||
437 | * on normal channel change, too, and as such, this | ||
438 | * should really be made more generic. For example, | ||
439 | * tricker radio disable/enable on GTT interrupt burst | ||
440 | * (say, 10 GTT interrupts received without any TX | ||
441 | * frame being completed) | ||
442 | */ | ||
443 | spin_unlock_bh(&sc->wiphy_lock); | ||
444 | ath_radio_disable(sc, aphy->hw); | ||
445 | ath_radio_enable(sc, aphy->hw); | ||
446 | /* Only the primary wiphy hw is used for queuing work */ | ||
447 | ieee80211_queue_work(aphy->sc->hw, | ||
448 | &aphy->sc->chan_work); | ||
449 | return -EBUSY; /* previous select still in progress */ | ||
450 | } | ||
451 | spin_unlock_bh(&sc->wiphy_lock); | ||
452 | return -EBUSY; /* previous select still in progress */ | ||
453 | } | ||
454 | sc->wiphy_select_failures = 0; | ||
455 | |||
456 | /* Store the new channel */ | ||
457 | sc->chan_idx = aphy->chan_idx; | ||
458 | sc->chan_is_ht = aphy->chan_is_ht; | ||
459 | sc->next_wiphy = aphy; | ||
460 | |||
461 | __ath9k_wiphy_pause_all(sc); | ||
462 | now = !__ath9k_wiphy_pausing(aphy->sc); | ||
463 | spin_unlock_bh(&sc->wiphy_lock); | ||
464 | |||
465 | if (now) { | ||
466 | /* Ready to request channel change immediately */ | ||
467 | ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work); | ||
468 | } | ||
469 | |||
470 | /* | ||
471 | * wiphys will be unpaused in ath9k_tx_status() once channel has been | ||
472 | * changed if any wiphy needs time to become paused. | ||
473 | */ | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | bool ath9k_wiphy_started(struct ath_softc *sc) | ||
479 | { | ||
480 | int i; | ||
481 | spin_lock_bh(&sc->wiphy_lock); | ||
482 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
483 | spin_unlock_bh(&sc->wiphy_lock); | ||
484 | return true; | ||
485 | } | ||
486 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
487 | if (sc->sec_wiphy[i] && | ||
488 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { | ||
489 | spin_unlock_bh(&sc->wiphy_lock); | ||
490 | return true; | ||
491 | } | ||
492 | } | ||
493 | spin_unlock_bh(&sc->wiphy_lock); | ||
494 | return false; | ||
495 | } | ||
496 | |||
497 | static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, | ||
498 | struct ath_wiphy *selected) | ||
499 | { | ||
500 | if (selected->state == ATH_WIPHY_SCAN) { | ||
501 | if (aphy == selected) | ||
502 | return; | ||
503 | /* | ||
504 | * Pause all other wiphys for the duration of the scan even if | ||
505 | * they are on the current channel now. | ||
506 | */ | ||
507 | } else if (aphy->chan_idx == selected->chan_idx) | ||
508 | return; | ||
509 | aphy->state = ATH_WIPHY_PAUSED; | ||
510 | ieee80211_stop_queues(aphy->hw); | ||
511 | } | ||
512 | |||
513 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
514 | struct ath_wiphy *selected) | ||
515 | { | ||
516 | int i; | ||
517 | spin_lock_bh(&sc->wiphy_lock); | ||
518 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
519 | ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); | ||
520 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
521 | if (sc->sec_wiphy[i] && | ||
522 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
523 | ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); | ||
524 | } | ||
525 | spin_unlock_bh(&sc->wiphy_lock); | ||
526 | } | ||
527 | |||
528 | void ath9k_wiphy_work(struct work_struct *work) | ||
529 | { | ||
530 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
531 | wiphy_work.work); | ||
532 | struct ath_wiphy *aphy = NULL; | ||
533 | bool first = true; | ||
534 | |||
535 | spin_lock_bh(&sc->wiphy_lock); | ||
536 | |||
537 | if (sc->wiphy_scheduler_int == 0) { | ||
538 | /* wiphy scheduler is disabled */ | ||
539 | spin_unlock_bh(&sc->wiphy_lock); | ||
540 | return; | ||
541 | } | ||
542 | |||
543 | try_again: | ||
544 | sc->wiphy_scheduler_index++; | ||
545 | while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { | ||
546 | aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; | ||
547 | if (aphy && aphy->state != ATH_WIPHY_INACTIVE) | ||
548 | break; | ||
549 | |||
550 | sc->wiphy_scheduler_index++; | ||
551 | aphy = NULL; | ||
552 | } | ||
553 | if (aphy == NULL) { | ||
554 | sc->wiphy_scheduler_index = 0; | ||
555 | if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { | ||
556 | if (first) { | ||
557 | first = false; | ||
558 | goto try_again; | ||
559 | } | ||
560 | /* No wiphy is ready to be scheduled */ | ||
561 | } else | ||
562 | aphy = sc->pri_wiphy; | ||
563 | } | ||
564 | |||
565 | spin_unlock_bh(&sc->wiphy_lock); | ||
566 | |||
567 | if (aphy && | ||
568 | aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && | ||
569 | ath9k_wiphy_select(aphy)) { | ||
570 | printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " | ||
571 | "change\n"); | ||
572 | } | ||
573 | |||
574 | ieee80211_queue_delayed_work(sc->hw, | ||
575 | &sc->wiphy_work, | ||
576 | sc->wiphy_scheduler_int); | ||
577 | } | ||
578 | |||
579 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | ||
580 | { | ||
581 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
582 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); | ||
583 | if (sc->wiphy_scheduler_int) | ||
584 | ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work, | ||
585 | sc->wiphy_scheduler_int); | ||
586 | } | ||
587 | |||
588 | /* caller must hold wiphy_lock */ | ||
589 | bool ath9k_all_wiphys_idle(struct ath_softc *sc) | ||
590 | { | ||
591 | unsigned int i; | ||
592 | if (!sc->pri_wiphy->idle) | ||
593 | return false; | ||
594 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
595 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
596 | if (!aphy) | ||
597 | continue; | ||
598 | if (!aphy->idle) | ||
599 | return false; | ||
600 | } | ||
601 | return true; | ||
602 | } | ||
603 | |||
604 | /* caller must hold wiphy_lock */ | ||
605 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle) | ||
606 | { | ||
607 | struct ath_softc *sc = aphy->sc; | ||
608 | |||
609 | aphy->idle = idle; | ||
610 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | ||
611 | "Marking %s as %sidle\n", | ||
612 | wiphy_name(aphy->hw->wiphy), idle ? "" : "not-"); | ||
613 | } | ||
614 | /* Only bother starting a queue on an active virtual wiphy */ | ||
615 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) | ||
616 | { | ||
617 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
618 | unsigned int i; | ||
619 | bool txq_started = false; | ||
620 | |||
621 | spin_lock_bh(&sc->wiphy_lock); | ||
622 | |||
623 | /* Start the primary wiphy */ | ||
624 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) { | ||
625 | ieee80211_wake_queue(hw, skb_queue); | ||
626 | txq_started = true; | ||
627 | goto unlock; | ||
628 | } | ||
629 | |||
630 | /* Now start the secondary wiphy queues */ | ||
631 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
632 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
633 | if (!aphy) | ||
634 | continue; | ||
635 | if (aphy->state != ATH_WIPHY_ACTIVE) | ||
636 | continue; | ||
637 | |||
638 | hw = aphy->hw; | ||
639 | ieee80211_wake_queue(hw, skb_queue); | ||
640 | txq_started = true; | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | unlock: | ||
645 | spin_unlock_bh(&sc->wiphy_lock); | ||
646 | return txq_started; | ||
647 | } | ||
648 | |||
649 | /* Go ahead and propagate information to all virtual wiphys, it won't hurt */ | ||
650 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue) | ||
651 | { | ||
652 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
653 | unsigned int i; | ||
654 | |||
655 | spin_lock_bh(&sc->wiphy_lock); | ||
656 | |||
657 | /* Stop the primary wiphy */ | ||
658 | ieee80211_stop_queue(hw, skb_queue); | ||
659 | |||
660 | /* Now stop the secondary wiphy queues */ | ||
661 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
662 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
663 | if (!aphy) | ||
664 | continue; | ||
665 | hw = aphy->hw; | ||
666 | ieee80211_stop_queue(hw, skb_queue); | ||
667 | } | ||
668 | spin_unlock_bh(&sc->wiphy_lock); | ||
669 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index dcac811ddab5..68a1c7612e9b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -55,8 +55,9 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
55 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 55 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
56 | struct list_head *head); | 56 | struct list_head *head); |
57 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); | 57 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); |
58 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | 58 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
59 | int nframes, int nbad, int txok, bool update_rc); | 59 | struct ath_tx_status *ts, int nframes, int nbad, |
60 | int txok, bool update_rc); | ||
60 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 61 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
61 | int seqno); | 62 | int seqno); |
62 | 63 | ||
@@ -295,7 +296,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
295 | 296 | ||
296 | ATH_TXBUF_RESET(tbf); | 297 | ATH_TXBUF_RESET(tbf); |
297 | 298 | ||
298 | tbf->aphy = bf->aphy; | ||
299 | tbf->bf_mpdu = bf->bf_mpdu; | 299 | tbf->bf_mpdu = bf->bf_mpdu; |
300 | tbf->bf_buf_addr = bf->bf_buf_addr; | 300 | tbf->bf_buf_addr = bf->bf_buf_addr; |
301 | memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); | 301 | memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); |
@@ -343,7 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
343 | struct ath_node *an = NULL; | 343 | struct ath_node *an = NULL; |
344 | struct sk_buff *skb; | 344 | struct sk_buff *skb; |
345 | struct ieee80211_sta *sta; | 345 | struct ieee80211_sta *sta; |
346 | struct ieee80211_hw *hw; | 346 | struct ieee80211_hw *hw = sc->hw; |
347 | struct ieee80211_hdr *hdr; | 347 | struct ieee80211_hdr *hdr; |
348 | struct ieee80211_tx_info *tx_info; | 348 | struct ieee80211_tx_info *tx_info; |
349 | struct ath_atx_tid *tid = NULL; | 349 | struct ath_atx_tid *tid = NULL; |
@@ -362,7 +362,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
362 | hdr = (struct ieee80211_hdr *)skb->data; | 362 | hdr = (struct ieee80211_hdr *)skb->data; |
363 | 363 | ||
364 | tx_info = IEEE80211_SKB_CB(skb); | 364 | tx_info = IEEE80211_SKB_CB(skb); |
365 | hw = bf->aphy->hw; | ||
366 | 365 | ||
367 | memcpy(rates, tx_info->control.rates, sizeof(rates)); | 366 | memcpy(rates, tx_info->control.rates, sizeof(rates)); |
368 | 367 | ||
@@ -381,7 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
381 | !bf->bf_stale || bf_next != NULL) | 380 | !bf->bf_stale || bf_next != NULL) |
382 | list_move_tail(&bf->list, &bf_head); | 381 | list_move_tail(&bf->list, &bf_head); |
383 | 382 | ||
384 | ath_tx_rc_status(bf, ts, 1, 1, 0, false); | 383 | ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false); |
385 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 384 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
386 | 0, 0); | 385 | 0, 0); |
387 | 386 | ||
@@ -487,10 +486,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
487 | 486 | ||
488 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 487 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
489 | memcpy(tx_info->control.rates, rates, sizeof(rates)); | 488 | memcpy(tx_info->control.rates, rates, sizeof(rates)); |
490 | ath_tx_rc_status(bf, ts, nframes, nbad, txok, true); | 489 | ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true); |
491 | rc_update = false; | 490 | rc_update = false; |
492 | } else { | 491 | } else { |
493 | ath_tx_rc_status(bf, ts, nframes, nbad, txok, false); | 492 | ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false); |
494 | } | 493 | } |
495 | 494 | ||
496 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 495 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
@@ -514,7 +513,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
514 | 513 | ||
515 | bf->bf_state.bf_type |= | 514 | bf->bf_state.bf_type |= |
516 | BUF_XRETRY; | 515 | BUF_XRETRY; |
517 | ath_tx_rc_status(bf, ts, nframes, | 516 | ath_tx_rc_status(sc, bf, ts, nframes, |
518 | nbad, 0, false); | 517 | nbad, 0, false); |
519 | ath_tx_complete_buf(sc, bf, txq, | 518 | ath_tx_complete_buf(sc, bf, txq, |
520 | &bf_head, | 519 | &bf_head, |
@@ -564,8 +563,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
564 | 563 | ||
565 | rcu_read_unlock(); | 564 | rcu_read_unlock(); |
566 | 565 | ||
567 | if (needreset) | 566 | if (needreset) { |
567 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
568 | ath_reset(sc, false); | 568 | ath_reset(sc, false); |
569 | spin_lock_bh(&sc->sc_pcu_lock); | ||
570 | } | ||
569 | } | 571 | } |
570 | 572 | ||
571 | static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | 573 | static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1207,8 +1209,17 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1207 | ath_err(common, "Failed to stop TX DMA!\n"); | 1209 | ath_err(common, "Failed to stop TX DMA!\n"); |
1208 | 1210 | ||
1209 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 1211 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
1210 | if (ATH_TXQ_SETUP(sc, i)) | 1212 | if (!ATH_TXQ_SETUP(sc, i)) |
1211 | ath_draintxq(sc, &sc->tx.txq[i], retry_tx); | 1213 | continue; |
1214 | |||
1215 | /* | ||
1216 | * The caller will resume queues with ieee80211_wake_queues. | ||
1217 | * Mark the queue as not stopped to prevent ath_tx_complete | ||
1218 | * from waking the queue too early. | ||
1219 | */ | ||
1220 | txq = &sc->tx.txq[i]; | ||
1221 | txq->stopped = false; | ||
1222 | ath_draintxq(sc, txq, retry_tx); | ||
1212 | } | 1223 | } |
1213 | 1224 | ||
1214 | return !npend; | 1225 | return !npend; |
@@ -1435,8 +1446,7 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1435 | static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | 1446 | static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, |
1436 | int framelen) | 1447 | int framelen) |
1437 | { | 1448 | { |
1438 | struct ath_wiphy *aphy = hw->priv; | 1449 | struct ath_softc *sc = hw->priv; |
1439 | struct ath_softc *sc = aphy->sc; | ||
1440 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1450 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1441 | struct ieee80211_sta *sta = tx_info->control.sta; | 1451 | struct ieee80211_sta *sta = tx_info->control.sta; |
1442 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | 1452 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
@@ -1654,8 +1664,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, | |||
1654 | struct ath_txq *txq, | 1664 | struct ath_txq *txq, |
1655 | struct sk_buff *skb) | 1665 | struct sk_buff *skb) |
1656 | { | 1666 | { |
1657 | struct ath_wiphy *aphy = hw->priv; | 1667 | struct ath_softc *sc = hw->priv; |
1658 | struct ath_softc *sc = aphy->sc; | ||
1659 | struct ath_hw *ah = sc->sc_ah; | 1668 | struct ath_hw *ah = sc->sc_ah; |
1660 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1669 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1661 | struct ath_frame_info *fi = get_frame_info(skb); | 1670 | struct ath_frame_info *fi = get_frame_info(skb); |
@@ -1671,7 +1680,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, | |||
1671 | 1680 | ||
1672 | ATH_TXBUF_RESET(bf); | 1681 | ATH_TXBUF_RESET(bf); |
1673 | 1682 | ||
1674 | bf->aphy = aphy; | ||
1675 | bf->bf_flags = setup_tx_flags(skb); | 1683 | bf->bf_flags = setup_tx_flags(skb); |
1676 | bf->bf_mpdu = skb; | 1684 | bf->bf_mpdu = skb; |
1677 | 1685 | ||
@@ -1757,8 +1765,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1757 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1765 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1758 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1766 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1759 | struct ieee80211_sta *sta = info->control.sta; | 1767 | struct ieee80211_sta *sta = info->control.sta; |
1760 | struct ath_wiphy *aphy = hw->priv; | 1768 | struct ath_softc *sc = hw->priv; |
1761 | struct ath_softc *sc = aphy->sc; | ||
1762 | struct ath_txq *txq = txctl->txq; | 1769 | struct ath_txq *txq = txctl->txq; |
1763 | struct ath_buf *bf; | 1770 | struct ath_buf *bf; |
1764 | int padpos, padsize; | 1771 | int padpos, padsize; |
@@ -1810,7 +1817,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1810 | spin_lock_bh(&txq->axq_lock); | 1817 | spin_lock_bh(&txq->axq_lock); |
1811 | if (txq == sc->tx.txq_map[q] && | 1818 | if (txq == sc->tx.txq_map[q] && |
1812 | ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { | 1819 | ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { |
1813 | ath_mac80211_stop_queue(sc, q); | 1820 | ieee80211_stop_queue(sc->hw, q); |
1814 | txq->stopped = 1; | 1821 | txq->stopped = 1; |
1815 | } | 1822 | } |
1816 | spin_unlock_bh(&txq->axq_lock); | 1823 | spin_unlock_bh(&txq->axq_lock); |
@@ -1825,8 +1832,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1825 | /*****************/ | 1832 | /*****************/ |
1826 | 1833 | ||
1827 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1834 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1828 | struct ath_wiphy *aphy, int tx_flags, int ftype, | 1835 | int tx_flags, int ftype, struct ath_txq *txq) |
1829 | struct ath_txq *txq) | ||
1830 | { | 1836 | { |
1831 | struct ieee80211_hw *hw = sc->hw; | 1837 | struct ieee80211_hw *hw = sc->hw; |
1832 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1838 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
@@ -1836,9 +1842,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1836 | 1842 | ||
1837 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1843 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1838 | 1844 | ||
1839 | if (aphy) | ||
1840 | hw = aphy->hw; | ||
1841 | |||
1842 | if (tx_flags & ATH_TX_BAR) | 1845 | if (tx_flags & ATH_TX_BAR) |
1843 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1846 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1844 | 1847 | ||
@@ -1868,19 +1871,20 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1868 | PS_WAIT_FOR_TX_ACK)); | 1871 | PS_WAIT_FOR_TX_ACK)); |
1869 | } | 1872 | } |
1870 | 1873 | ||
1871 | if (unlikely(ftype)) | 1874 | q = skb_get_queue_mapping(skb); |
1872 | ath9k_tx_status(hw, skb, ftype); | 1875 | if (txq == sc->tx.txq_map[q]) { |
1873 | else { | 1876 | spin_lock_bh(&txq->axq_lock); |
1874 | q = skb_get_queue_mapping(skb); | 1877 | if (WARN_ON(--txq->pending_frames < 0)) |
1875 | if (txq == sc->tx.txq_map[q]) { | 1878 | txq->pending_frames = 0; |
1876 | spin_lock_bh(&txq->axq_lock); | ||
1877 | if (WARN_ON(--txq->pending_frames < 0)) | ||
1878 | txq->pending_frames = 0; | ||
1879 | spin_unlock_bh(&txq->axq_lock); | ||
1880 | } | ||
1881 | 1879 | ||
1882 | ieee80211_tx_status(hw, skb); | 1880 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { |
1881 | ieee80211_wake_queue(sc->hw, q); | ||
1882 | txq->stopped = 0; | ||
1883 | } | ||
1884 | spin_unlock_bh(&txq->axq_lock); | ||
1883 | } | 1885 | } |
1886 | |||
1887 | ieee80211_tx_status(hw, skb); | ||
1884 | } | 1888 | } |
1885 | 1889 | ||
1886 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1890 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1910,8 +1914,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1910 | else | 1914 | else |
1911 | complete(&sc->paprd_complete); | 1915 | complete(&sc->paprd_complete); |
1912 | } else { | 1916 | } else { |
1913 | ath_debug_stat_tx(sc, bf, ts); | 1917 | ath_debug_stat_tx(sc, bf, ts, txq); |
1914 | ath_tx_complete(sc, skb, bf->aphy, tx_flags, | 1918 | ath_tx_complete(sc, skb, tx_flags, |
1915 | bf->bf_state.bfs_ftype, txq); | 1919 | bf->bf_state.bfs_ftype, txq); |
1916 | } | 1920 | } |
1917 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't | 1921 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't |
@@ -1927,14 +1931,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1927 | spin_unlock_irqrestore(&sc->tx.txbuflock, flags); | 1931 | spin_unlock_irqrestore(&sc->tx.txbuflock, flags); |
1928 | } | 1932 | } |
1929 | 1933 | ||
1930 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | 1934 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
1931 | int nframes, int nbad, int txok, bool update_rc) | 1935 | struct ath_tx_status *ts, int nframes, int nbad, |
1936 | int txok, bool update_rc) | ||
1932 | { | 1937 | { |
1933 | struct sk_buff *skb = bf->bf_mpdu; | 1938 | struct sk_buff *skb = bf->bf_mpdu; |
1934 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1939 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1935 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1940 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1936 | struct ieee80211_hw *hw = bf->aphy->hw; | 1941 | struct ieee80211_hw *hw = sc->hw; |
1937 | struct ath_softc *sc = bf->aphy->sc; | ||
1938 | struct ath_hw *ah = sc->sc_ah; | 1942 | struct ath_hw *ah = sc->sc_ah; |
1939 | u8 i, tx_rateindex; | 1943 | u8 i, tx_rateindex; |
1940 | 1944 | ||
@@ -1985,18 +1989,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | |||
1985 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; | 1989 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; |
1986 | } | 1990 | } |
1987 | 1991 | ||
1988 | /* Has no locking. Must hold spin_lock_bh(&txq->axq_lock) | ||
1989 | * before calling this. | ||
1990 | */ | ||
1991 | static void __ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | ||
1992 | { | ||
1993 | if (txq->mac80211_qnum >= 0 && | ||
1994 | txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { | ||
1995 | if (ath_mac80211_start_queue(sc, txq->mac80211_qnum)) | ||
1996 | txq->stopped = 0; | ||
1997 | } | ||
1998 | } | ||
1999 | |||
2000 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 1992 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
2001 | { | 1993 | { |
2002 | struct ath_hw *ah = sc->sc_ah; | 1994 | struct ath_hw *ah = sc->sc_ah; |
@@ -2007,7 +1999,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2007 | struct ath_tx_status ts; | 1999 | struct ath_tx_status ts; |
2008 | int txok; | 2000 | int txok; |
2009 | int status; | 2001 | int status; |
2010 | int qnum; | ||
2011 | 2002 | ||
2012 | ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", | 2003 | ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", |
2013 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | 2004 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), |
@@ -2086,11 +2077,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2086 | */ | 2077 | */ |
2087 | if (ts.ts_status & ATH9K_TXERR_XRETRY) | 2078 | if (ts.ts_status & ATH9K_TXERR_XRETRY) |
2088 | bf->bf_state.bf_type |= BUF_XRETRY; | 2079 | bf->bf_state.bf_type |= BUF_XRETRY; |
2089 | ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true); | 2080 | ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true); |
2090 | } | 2081 | } |
2091 | 2082 | ||
2092 | qnum = skb_get_queue_mapping(bf->bf_mpdu); | ||
2093 | |||
2094 | if (bf_isampdu(bf)) | 2083 | if (bf_isampdu(bf)) |
2095 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, | 2084 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, |
2096 | true); | 2085 | true); |
@@ -2098,7 +2087,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2098 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); | 2087 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); |
2099 | 2088 | ||
2100 | spin_lock_bh(&txq->axq_lock); | 2089 | spin_lock_bh(&txq->axq_lock); |
2101 | __ath_wake_mac80211_queue(sc, txq); | ||
2102 | 2090 | ||
2103 | if (sc->sc_flags & SC_OP_TXAGGR) | 2091 | if (sc->sc_flags & SC_OP_TXAGGR) |
2104 | ath_txq_schedule(sc, txq); | 2092 | ath_txq_schedule(sc, txq); |
@@ -2106,6 +2094,28 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2106 | } | 2094 | } |
2107 | } | 2095 | } |
2108 | 2096 | ||
2097 | static void ath_hw_pll_work(struct work_struct *work) | ||
2098 | { | ||
2099 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
2100 | hw_pll_work.work); | ||
2101 | static int count; | ||
2102 | |||
2103 | if (AR_SREV_9485(sc->sc_ah)) { | ||
2104 | if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) { | ||
2105 | count++; | ||
2106 | |||
2107 | if (count == 3) { | ||
2108 | /* Rx is hung for more than 500ms. Reset it */ | ||
2109 | ath_reset(sc, true); | ||
2110 | count = 0; | ||
2111 | } | ||
2112 | } else | ||
2113 | count = 0; | ||
2114 | |||
2115 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); | ||
2116 | } | ||
2117 | } | ||
2118 | |||
2109 | static void ath_tx_complete_poll_work(struct work_struct *work) | 2119 | static void ath_tx_complete_poll_work(struct work_struct *work) |
2110 | { | 2120 | { |
2111 | struct ath_softc *sc = container_of(work, struct ath_softc, | 2121 | struct ath_softc *sc = container_of(work, struct ath_softc, |
@@ -2154,7 +2164,6 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2154 | txq->pending_frames, | 2164 | txq->pending_frames, |
2155 | list_empty(&txq->axq_acq), | 2165 | list_empty(&txq->axq_acq), |
2156 | txq->stopped); | 2166 | txq->stopped); |
2157 | __ath_wake_mac80211_queue(sc, txq); | ||
2158 | ath_txq_schedule(sc, txq); | 2167 | ath_txq_schedule(sc, txq); |
2159 | } | 2168 | } |
2160 | } | 2169 | } |
@@ -2196,7 +2205,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2196 | struct list_head bf_head; | 2205 | struct list_head bf_head; |
2197 | int status; | 2206 | int status; |
2198 | int txok; | 2207 | int txok; |
2199 | int qnum; | ||
2200 | 2208 | ||
2201 | for (;;) { | 2209 | for (;;) { |
2202 | status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); | 2210 | status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); |
@@ -2239,11 +2247,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2239 | if (!bf_isampdu(bf)) { | 2247 | if (!bf_isampdu(bf)) { |
2240 | if (txs.ts_status & ATH9K_TXERR_XRETRY) | 2248 | if (txs.ts_status & ATH9K_TXERR_XRETRY) |
2241 | bf->bf_state.bf_type |= BUF_XRETRY; | 2249 | bf->bf_state.bf_type |= BUF_XRETRY; |
2242 | ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true); | 2250 | ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true); |
2243 | } | 2251 | } |
2244 | 2252 | ||
2245 | qnum = skb_get_queue_mapping(bf->bf_mpdu); | ||
2246 | |||
2247 | if (bf_isampdu(bf)) | 2253 | if (bf_isampdu(bf)) |
2248 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, | 2254 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, |
2249 | txok, true); | 2255 | txok, true); |
@@ -2252,7 +2258,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2252 | &txs, txok, 0); | 2258 | &txs, txok, 0); |
2253 | 2259 | ||
2254 | spin_lock_bh(&txq->axq_lock); | 2260 | spin_lock_bh(&txq->axq_lock); |
2255 | __ath_wake_mac80211_queue(sc, txq); | ||
2256 | 2261 | ||
2257 | if (!list_empty(&txq->txq_fifo_pending)) { | 2262 | if (!list_empty(&txq->txq_fifo_pending)) { |
2258 | INIT_LIST_HEAD(&bf_head); | 2263 | INIT_LIST_HEAD(&bf_head); |
@@ -2330,6 +2335,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2330 | } | 2335 | } |
2331 | 2336 | ||
2332 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); | 2337 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); |
2338 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); | ||
2333 | 2339 | ||
2334 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 2340 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
2335 | error = ath_tx_edma_init(sc); | 2341 | error = ath_tx_edma_init(sc); |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 2b14775e6bc6..f828f294ba89 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -158,6 +158,13 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) | |||
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | bool ath_is_49ghz_allowed(u16 regdomain) | ||
162 | { | ||
163 | /* possibly more */ | ||
164 | return regdomain == MKK9_MKKC; | ||
165 | } | ||
166 | EXPORT_SYMBOL(ath_is_49ghz_allowed); | ||
167 | |||
161 | /* Frequency is one where radar detection is required */ | 168 | /* Frequency is one where radar detection is required */ |
162 | static bool ath_is_radar_freq(u16 center_freq) | 169 | static bool ath_is_radar_freq(u16 center_freq) |
163 | { | 170 | { |
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 345dd9721b41..172f63f671cf 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h | |||
@@ -250,6 +250,7 @@ enum CountryCode { | |||
250 | }; | 250 | }; |
251 | 251 | ||
252 | bool ath_is_world_regd(struct ath_regulatory *reg); | 252 | bool ath_is_world_regd(struct ath_regulatory *reg); |
253 | bool ath_is_49ghz_allowed(u16 redomain); | ||
253 | int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, | 254 | int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, |
254 | int (*reg_notifier)(struct wiphy *wiphy, | 255 | int (*reg_notifier)(struct wiphy *wiphy, |
255 | struct regulatory_request *request)); | 256 | struct regulatory_request *request)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 1d9dcd7e3b82..58213e72d107 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -762,8 +762,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
762 | 762 | ||
763 | /* We need to figure out how to get the sta->supp_rates while | 763 | /* We need to figure out how to get the sta->supp_rates while |
764 | * in this running context */ | 764 | * in this running context */ |
765 | rate_mask = IWL_RATES_MASK; | 765 | rate_mask = IWL_RATES_MASK_3945; |
766 | |||
767 | 766 | ||
768 | /* Set retry limit on DATA packets and Probe Responses*/ | 767 | /* Set retry limit on DATA packets and Probe Responses*/ |
769 | if (ieee80211_is_probe_resp(fc)) | 768 | if (ieee80211_is_probe_resp(fc)) |
@@ -1650,7 +1649,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) | |||
1650 | ref_temp); | 1649 | ref_temp); |
1651 | 1650 | ||
1652 | /* set tx power value for all rates, OFDM and CCK */ | 1651 | /* set tx power value for all rates, OFDM and CCK */ |
1653 | for (rate_index = 0; rate_index < IWL_RATE_COUNT; | 1652 | for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945; |
1654 | rate_index++) { | 1653 | rate_index++) { |
1655 | int power_idx = | 1654 | int power_idx = |
1656 | ch_info->power_info[rate_index].base_power_index; | 1655 | ch_info->power_info[rate_index].base_power_index; |
@@ -1890,7 +1889,7 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
1890 | 1889 | ||
1891 | /* If we issue a new RXON command which required a tune then we must | 1890 | /* If we issue a new RXON command which required a tune then we must |
1892 | * send a new TXPOWER command or we won't be able to Tx any frames */ | 1891 | * send a new TXPOWER command or we won't be able to Tx any frames */ |
1893 | rc = priv->cfg->ops->lib->send_tx_power(priv); | 1892 | rc = iwl_set_tx_power(priv, priv->tx_power_next, true); |
1894 | if (rc) { | 1893 | if (rc) { |
1895 | IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); | 1894 | IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); |
1896 | return rc; | 1895 | return rc; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 313e92ed568b..7c14eb31d954 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1571,7 +1571,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c | |||
1571 | 1571 | ||
1572 | /* If we issue a new RXON command which required a tune then we must | 1572 | /* If we issue a new RXON command which required a tune then we must |
1573 | * send a new TXPOWER command or we won't be able to Tx any frames */ | 1573 | * send a new TXPOWER command or we won't be able to Tx any frames */ |
1574 | ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | 1574 | ret = iwl_set_tx_power(priv, priv->tx_power_next, true); |
1575 | if (ret) { | 1575 | if (ret) { |
1576 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); | 1576 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); |
1577 | return ret; | 1577 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index d16bb5ede014..9006293e740c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c | |||
@@ -631,8 +631,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) | |||
631 | } | 631 | } |
632 | 632 | ||
633 | spin_lock_irqsave(&priv->lock, flags); | 633 | spin_lock_irqsave(&priv->lock, flags); |
634 | if (priv->cfg->bt_params && | 634 | if (iwl_bt_statistics(priv)) { |
635 | priv->cfg->bt_params->bt_statistics) { | ||
636 | rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> | 635 | rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> |
637 | rx.general.common); | 636 | rx.general.common); |
638 | ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); | 637 | ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); |
@@ -897,8 +896,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
897 | } | 896 | } |
898 | 897 | ||
899 | spin_lock_irqsave(&priv->lock, flags); | 898 | spin_lock_irqsave(&priv->lock, flags); |
900 | if (priv->cfg->bt_params && | 899 | if (iwl_bt_statistics(priv)) { |
901 | priv->cfg->bt_params->bt_statistics) { | ||
902 | rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> | 900 | rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> |
903 | rx.general.common); | 901 | rx.general.common); |
904 | } else { | 902 | } else { |
@@ -913,8 +911,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) | |||
913 | 911 | ||
914 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); | 912 | rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK); |
915 | rxon_chnum = le16_to_cpu(ctx->staging.channel); | 913 | rxon_chnum = le16_to_cpu(ctx->staging.channel); |
916 | if (priv->cfg->bt_params && | 914 | if (iwl_bt_statistics(priv)) { |
917 | priv->cfg->bt_params->bt_statistics) { | ||
918 | stat_band24 = !!(((struct iwl_bt_notif_statistics *) | 915 | stat_band24 = !!(((struct iwl_bt_notif_statistics *) |
919 | stat_resp)->flag & | 916 | stat_resp)->flag & |
920 | STATISTICS_REPLY_FLG_BAND_24G_MSK); | 917 | STATISTICS_REPLY_FLG_BAND_24G_MSK); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index a6dbd8983dac..b500aaae53ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | |||
@@ -39,8 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) | |||
39 | int p = 0; | 39 | int p = 0; |
40 | u32 flag; | 40 | u32 flag; |
41 | 41 | ||
42 | if (priv->cfg->bt_params && | 42 | if (iwl_bt_statistics(priv)) |
43 | priv->cfg->bt_params->bt_statistics) | ||
44 | flag = le32_to_cpu(priv->_agn.statistics_bt.flag); | 43 | flag = le32_to_cpu(priv->_agn.statistics_bt.flag); |
45 | else | 44 | else |
46 | flag = le32_to_cpu(priv->_agn.statistics.flag); | 45 | flag = le32_to_cpu(priv->_agn.statistics.flag); |
@@ -89,8 +88,7 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, | |||
89 | * the last statistics notification from uCode | 88 | * the last statistics notification from uCode |
90 | * might not reflect the current uCode activity | 89 | * might not reflect the current uCode activity |
91 | */ | 90 | */ |
92 | if (priv->cfg->bt_params && | 91 | if (iwl_bt_statistics(priv)) { |
93 | priv->cfg->bt_params->bt_statistics) { | ||
94 | ofdm = &priv->_agn.statistics_bt.rx.ofdm; | 92 | ofdm = &priv->_agn.statistics_bt.rx.ofdm; |
95 | cck = &priv->_agn.statistics_bt.rx.cck; | 93 | cck = &priv->_agn.statistics_bt.rx.cck; |
96 | general = &priv->_agn.statistics_bt.rx.general.common; | 94 | general = &priv->_agn.statistics_bt.rx.general.common; |
@@ -536,8 +534,7 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, | |||
536 | * the last statistics notification from uCode | 534 | * the last statistics notification from uCode |
537 | * might not reflect the current uCode activity | 535 | * might not reflect the current uCode activity |
538 | */ | 536 | */ |
539 | if (priv->cfg->bt_params && | 537 | if (iwl_bt_statistics(priv)) { |
540 | priv->cfg->bt_params->bt_statistics) { | ||
541 | tx = &priv->_agn.statistics_bt.tx; | 538 | tx = &priv->_agn.statistics_bt.tx; |
542 | accum_tx = &priv->_agn.accum_statistics_bt.tx; | 539 | accum_tx = &priv->_agn.accum_statistics_bt.tx; |
543 | delta_tx = &priv->_agn.delta_statistics_bt.tx; | 540 | delta_tx = &priv->_agn.delta_statistics_bt.tx; |
@@ -737,8 +734,7 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, | |||
737 | * the last statistics notification from uCode | 734 | * the last statistics notification from uCode |
738 | * might not reflect the current uCode activity | 735 | * might not reflect the current uCode activity |
739 | */ | 736 | */ |
740 | if (priv->cfg->bt_params && | 737 | if (iwl_bt_statistics(priv)) { |
741 | priv->cfg->bt_params->bt_statistics) { | ||
742 | general = &priv->_agn.statistics_bt.general.common; | 738 | general = &priv->_agn.statistics_bt.general.common; |
743 | dbg = &priv->_agn.statistics_bt.general.common.dbg; | 739 | dbg = &priv->_agn.statistics_bt.general.common.dbg; |
744 | div = &priv->_agn.statistics_bt.general.common.div; | 740 | div = &priv->_agn.statistics_bt.general.common.div; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 75e50d33ecb3..184828c72b31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -213,6 +213,7 @@ enum { | |||
213 | IWL_CCK_BASIC_RATES_MASK) | 213 | IWL_CCK_BASIC_RATES_MASK) |
214 | 214 | ||
215 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) | 215 | #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) |
216 | #define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1) | ||
216 | 217 | ||
217 | #define IWL_INVALID_VALUE -1 | 218 | #define IWL_INVALID_VALUE -1 |
218 | 219 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index bbd40b7dd597..b192ca842f0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -73,8 +73,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
73 | int bcn_silence_a, bcn_silence_b, bcn_silence_c; | 73 | int bcn_silence_a, bcn_silence_b, bcn_silence_c; |
74 | int last_rx_noise; | 74 | int last_rx_noise; |
75 | 75 | ||
76 | if (priv->cfg->bt_params && | 76 | if (iwl_bt_statistics(priv)) |
77 | priv->cfg->bt_params->bt_statistics) | ||
78 | rx_info = &(priv->_agn.statistics_bt.rx.general.common); | 77 | rx_info = &(priv->_agn.statistics_bt.rx.general.common); |
79 | else | 78 | else |
80 | rx_info = &(priv->_agn.statistics.rx.general); | 79 | rx_info = &(priv->_agn.statistics.rx.general); |
@@ -125,8 +124,7 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
125 | struct statistics_general_common *general, *accum_general; | 124 | struct statistics_general_common *general, *accum_general; |
126 | struct statistics_tx *tx, *accum_tx; | 125 | struct statistics_tx *tx, *accum_tx; |
127 | 126 | ||
128 | if (priv->cfg->bt_params && | 127 | if (iwl_bt_statistics(priv)) { |
129 | priv->cfg->bt_params->bt_statistics) { | ||
130 | prev_stats = (__le32 *)&priv->_agn.statistics_bt; | 128 | prev_stats = (__le32 *)&priv->_agn.statistics_bt; |
131 | accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; | 129 | accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; |
132 | size = sizeof(struct iwl_bt_notif_statistics); | 130 | size = sizeof(struct iwl_bt_notif_statistics); |
@@ -207,8 +205,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, | |||
207 | struct statistics_rx_phy *ofdm; | 205 | struct statistics_rx_phy *ofdm; |
208 | struct statistics_rx_ht_phy *ofdm_ht; | 206 | struct statistics_rx_ht_phy *ofdm_ht; |
209 | 207 | ||
210 | if (priv->cfg->bt_params && | 208 | if (iwl_bt_statistics(priv)) { |
211 | priv->cfg->bt_params->bt_statistics) { | ||
212 | ofdm = &pkt->u.stats_bt.rx.ofdm; | 209 | ofdm = &pkt->u.stats_bt.rx.ofdm; |
213 | ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; | 210 | ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; |
214 | combined_plcp_delta = | 211 | combined_plcp_delta = |
@@ -265,8 +262,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
265 | int change; | 262 | int change; |
266 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 263 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
267 | 264 | ||
268 | if (priv->cfg->bt_params && | 265 | if (iwl_bt_statistics(priv)) { |
269 | priv->cfg->bt_params->bt_statistics) { | ||
270 | IWL_DEBUG_RX(priv, | 266 | IWL_DEBUG_RX(priv, |
271 | "Statistics notification received (%d vs %d).\n", | 267 | "Statistics notification received (%d vs %d).\n", |
272 | (int)sizeof(struct iwl_bt_notif_statistics), | 268 | (int)sizeof(struct iwl_bt_notif_statistics), |
@@ -304,8 +300,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
304 | 300 | ||
305 | iwl_recover_from_statistics(priv, pkt); | 301 | iwl_recover_from_statistics(priv, pkt); |
306 | 302 | ||
307 | if (priv->cfg->bt_params && | 303 | if (iwl_bt_statistics(priv)) |
308 | priv->cfg->bt_params->bt_statistics) | ||
309 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, | 304 | memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, |
310 | sizeof(priv->_agn.statistics_bt)); | 305 | sizeof(priv->_agn.statistics_bt)); |
311 | else | 306 | else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2a4ff832fbb8..6c2adc58d654 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -316,10 +316,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
316 | * If we issue a new RXON command which required a tune then we must | 316 | * If we issue a new RXON command which required a tune then we must |
317 | * send a new TXPOWER command or we won't be able to Tx any frames. | 317 | * send a new TXPOWER command or we won't be able to Tx any frames. |
318 | * | 318 | * |
319 | * FIXME: which RXON requires a tune? Can we optimise this out in | 319 | * It's expected we set power here if channel is changing. |
320 | * some cases? | ||
321 | */ | 320 | */ |
322 | ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | 321 | ret = iwl_set_tx_power(priv, priv->tx_power_next, true); |
323 | if (ret) { | 322 | if (ret) { |
324 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); | 323 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); |
325 | return ret; | 324 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index eb16647cfbe0..646ccb2430b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -3077,8 +3077,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) | |||
3077 | } | 3077 | } |
3078 | 3078 | ||
3079 | if (priv->start_calib) { | 3079 | if (priv->start_calib) { |
3080 | if (priv->cfg->bt_params && | 3080 | if (iwl_bt_statistics(priv)) { |
3081 | priv->cfg->bt_params->bt_statistics) { | ||
3082 | iwl_chain_noise_calibration(priv, | 3081 | iwl_chain_noise_calibration(priv, |
3083 | (void *)&priv->_agn.statistics_bt); | 3082 | (void *)&priv->_agn.statistics_bt); |
3084 | iwl_sensitivity_calibration(priv, | 3083 | iwl_sensitivity_calibration(priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a46ad60216a0..4ad89389a0a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -219,16 +219,12 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
219 | if (!is_channel_valid(ch)) | 219 | if (!is_channel_valid(ch)) |
220 | continue; | 220 | continue; |
221 | 221 | ||
222 | if (is_channel_a_band(ch)) | 222 | sband = &priv->bands[ch->band]; |
223 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
224 | else | ||
225 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
226 | 223 | ||
227 | geo_ch = &sband->channels[sband->n_channels++]; | 224 | geo_ch = &sband->channels[sband->n_channels++]; |
228 | 225 | ||
229 | geo_ch->center_freq = | 226 | geo_ch->center_freq = |
230 | ieee80211_channel_to_frequency(ch->channel, | 227 | ieee80211_channel_to_frequency(ch->channel, ch->band); |
231 | sband->band); | ||
232 | geo_ch->max_power = ch->max_power_avg; | 228 | geo_ch->max_power = ch->max_power_avg; |
233 | geo_ch->max_antenna_gain = 0xff; | 229 | geo_ch->max_antenna_gain = 0xff; |
234 | geo_ch->hw_value = ch->channel; | 230 | geo_ch->hw_value = ch->channel; |
@@ -1162,6 +1158,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1162 | { | 1158 | { |
1163 | int ret; | 1159 | int ret; |
1164 | s8 prev_tx_power; | 1160 | s8 prev_tx_power; |
1161 | bool defer; | ||
1162 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1165 | 1163 | ||
1166 | lockdep_assert_held(&priv->mutex); | 1164 | lockdep_assert_held(&priv->mutex); |
1167 | 1165 | ||
@@ -1189,10 +1187,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1189 | if (!iwl_is_ready_rf(priv)) | 1187 | if (!iwl_is_ready_rf(priv)) |
1190 | return -EIO; | 1188 | return -EIO; |
1191 | 1189 | ||
1192 | /* scan complete use tx_power_next, need to be updated */ | 1190 | /* scan complete and commit_rxon use tx_power_next value, |
1191 | * it always need to be updated for newest request */ | ||
1193 | priv->tx_power_next = tx_power; | 1192 | priv->tx_power_next = tx_power; |
1194 | if (test_bit(STATUS_SCANNING, &priv->status) && !force) { | 1193 | |
1195 | IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n"); | 1194 | /* do not set tx power when scanning or channel changing */ |
1195 | defer = test_bit(STATUS_SCANNING, &priv->status) || | ||
1196 | memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); | ||
1197 | if (defer && !force) { | ||
1198 | IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); | ||
1196 | return 0; | 1199 | return 0; |
1197 | } | 1200 | } |
1198 | 1201 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index bbc5aa7a7f2f..c83fcc60ccc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -741,6 +741,17 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | |||
741 | return priv->hw->wiphy->bands[band]; | 741 | return priv->hw->wiphy->bands[band]; |
742 | } | 742 | } |
743 | 743 | ||
744 | static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv) | ||
745 | { | ||
746 | return priv->cfg->bt_params && | ||
747 | priv->cfg->bt_params->advanced_bt_coexist; | ||
748 | } | ||
749 | |||
750 | static inline bool iwl_bt_statistics(struct iwl_priv *priv) | ||
751 | { | ||
752 | return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics; | ||
753 | } | ||
754 | |||
744 | extern bool bt_coex_active; | 755 | extern bool bt_coex_active; |
745 | extern bool bt_siso_mode; | 756 | extern bool bt_siso_mode; |
746 | 757 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 418c8ac26222..bdcb74279f1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -1765,13 +1765,13 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1765 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); | 1765 | DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); |
1766 | if (priv->cfg->base_params->ucode_tracing) | 1766 | if (priv->cfg->base_params->ucode_tracing) |
1767 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); | 1767 | DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); |
1768 | if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics) | 1768 | if (iwl_bt_statistics(priv)) |
1769 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); | 1769 | DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); |
1770 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); | 1770 | DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR); |
1771 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); | 1771 | DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); |
1772 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 1772 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
1773 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | 1773 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); |
1774 | if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) | 1774 | if (iwl_advanced_bt_coexist(priv)) |
1775 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 1775 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); |
1776 | if (priv->cfg->base_params->sensitivity_calib_by_driver) | 1776 | if (priv->cfg->base_params->sensitivity_calib_by_driver) |
1777 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, | 1777 | DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 6fa1383d72ec..b5f21e041953 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -138,7 +138,7 @@ struct iwl_queue { | |||
138 | * space more than this */ | 138 | * space more than this */ |
139 | int high_mark; /* high watermark, stop queue if free | 139 | int high_mark; /* high watermark, stop queue if free |
140 | * space less than this */ | 140 | * space less than this */ |
141 | } __packed; | 141 | }; |
142 | 142 | ||
143 | /* One for each TFD */ | 143 | /* One for each TFD */ |
144 | struct iwl_tx_info { | 144 | struct iwl_tx_info { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c index 927fe37a43ab..e1ace3ce30b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-legacy.c +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c | |||
@@ -85,10 +85,9 @@ int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
85 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", | 85 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", |
86 | channel->hw_value, changed); | 86 | channel->hw_value, changed); |
87 | 87 | ||
88 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && | 88 | if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { |
89 | test_bit(STATUS_SCANNING, &priv->status))) { | ||
90 | scan_active = 1; | 89 | scan_active = 1; |
91 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); | 90 | IWL_DEBUG_MAC80211(priv, "scan active\n"); |
92 | } | 91 | } |
93 | 92 | ||
94 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | 93 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 1eec18d909d8..25f7d474f346 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -226,8 +226,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
226 | else | 226 | else |
227 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; | 227 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; |
228 | 228 | ||
229 | if (priv->cfg->bt_params && | 229 | if (iwl_advanced_bt_coexist(priv)) { |
230 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
231 | if (!priv->cfg->bt_params->bt_sco_disable) | 230 | if (!priv->cfg->bt_params->bt_sco_disable) |
232 | cmd->flags |= IWL_POWER_BT_SCO_ENA; | 231 | cmd->flags |= IWL_POWER_BT_SCO_ENA; |
233 | else | 232 | else |
@@ -313,8 +312,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, | |||
313 | else | 312 | else |
314 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; | 313 | cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA; |
315 | 314 | ||
316 | if (priv->cfg->bt_params && | 315 | if (iwl_advanced_bt_coexist(priv)) { |
317 | priv->cfg->bt_params->advanced_bt_coexist) { | ||
318 | if (!priv->cfg->bt_params->bt_sco_disable) | 316 | if (!priv->cfg->bt_params->bt_sco_disable) |
319 | cmd->flags |= IWL_POWER_BT_SCO_ENA; | 317 | cmd->flags |= IWL_POWER_BT_SCO_ENA; |
320 | else | 318 | else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 12d9363d0afe..08f1bea8b652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -257,8 +257,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
257 | queue_work(priv->workqueue, &priv->scan_completed); | 257 | queue_work(priv->workqueue, &priv->scan_completed); |
258 | 258 | ||
259 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && | 259 | if (priv->iw_mode != NL80211_IFTYPE_ADHOC && |
260 | priv->cfg->bt_params && | 260 | iwl_advanced_bt_coexist(priv) && |
261 | priv->cfg->bt_params->advanced_bt_coexist && | ||
262 | priv->bt_status != scan_notif->bt_status) { | 261 | priv->bt_status != scan_notif->bt_status) { |
263 | if (scan_notif->bt_status) { | 262 | if (scan_notif->bt_status) { |
264 | /* BT on */ | 263 | /* BT on */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9c986f272c2d..2945acd955f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2517,7 +2517,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2517 | 2517 | ||
2518 | ieee80211_wake_queues(priv->hw); | 2518 | ieee80211_wake_queues(priv->hw); |
2519 | 2519 | ||
2520 | priv->active_rate = IWL_RATES_MASK; | 2520 | priv->active_rate = IWL_RATES_MASK_3945; |
2521 | 2521 | ||
2522 | iwl_power_update_mode(priv, true); | 2522 | iwl_power_update_mode(priv, true); |
2523 | 2523 | ||
@@ -2535,13 +2535,14 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2535 | /* Configure Bluetooth device coexistence support */ | 2535 | /* Configure Bluetooth device coexistence support */ |
2536 | priv->cfg->ops->hcmd->send_bt_config(priv); | 2536 | priv->cfg->ops->hcmd->send_bt_config(priv); |
2537 | 2537 | ||
2538 | set_bit(STATUS_READY, &priv->status); | ||
2539 | |||
2538 | /* Configure the adapter for unassociated operation */ | 2540 | /* Configure the adapter for unassociated operation */ |
2539 | iwl3945_commit_rxon(priv, ctx); | 2541 | iwl3945_commit_rxon(priv, ctx); |
2540 | 2542 | ||
2541 | iwl3945_reg_txpower_periodic(priv); | 2543 | iwl3945_reg_txpower_periodic(priv); |
2542 | 2544 | ||
2543 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2545 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2544 | set_bit(STATUS_READY, &priv->status); | ||
2545 | wake_up_interruptible(&priv->wait_command_queue); | 2546 | wake_up_interruptible(&priv->wait_command_queue); |
2546 | 2547 | ||
2547 | return; | 2548 | return; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 54ca49ad3472..2725f3c4442e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -46,7 +46,7 @@ | |||
46 | * These indirect registers work with busy bits, | 46 | * These indirect registers work with busy bits, |
47 | * and we will try maximal REGISTER_BUSY_COUNT times to access | 47 | * and we will try maximal REGISTER_BUSY_COUNT times to access |
48 | * the register while taking a REGISTER_BUSY_DELAY us delay | 48 | * the register while taking a REGISTER_BUSY_DELAY us delay |
49 | * between each attampt. When the busy bit is still set at that time, | 49 | * between each attempt. When the busy bit is still set at that time, |
50 | * the access attempt is considered to have failed, | 50 | * the access attempt is considered to have failed, |
51 | * and we will print an error. | 51 | * and we will print an error. |
52 | */ | 52 | */ |
@@ -305,9 +305,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
305 | * Enable synchronisation. | 305 | * Enable synchronisation. |
306 | */ | 306 | */ |
307 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 307 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
308 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
309 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 308 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
310 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
311 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 309 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
312 | } | 310 | } |
313 | 311 | ||
@@ -647,6 +645,11 @@ static void rt2400pci_start_queue(struct data_queue *queue) | |||
647 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 645 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); |
648 | break; | 646 | break; |
649 | case QID_BEACON: | 647 | case QID_BEACON: |
648 | /* | ||
649 | * Allow the tbtt tasklet to be scheduled. | ||
650 | */ | ||
651 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
652 | |||
650 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 653 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
651 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 654 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
652 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 655 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
@@ -708,6 +711,11 @@ static void rt2400pci_stop_queue(struct data_queue *queue) | |||
708 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 711 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
709 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 712 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
710 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 713 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
714 | |||
715 | /* | ||
716 | * Wait for possibly running tbtt tasklets. | ||
717 | */ | ||
718 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
711 | break; | 719 | break; |
712 | default: | 720 | default: |
713 | break; | 721 | break; |
@@ -963,9 +971,9 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
963 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 971 | static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
964 | enum dev_state state) | 972 | enum dev_state state) |
965 | { | 973 | { |
966 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 974 | int mask = (state == STATE_RADIO_IRQ_OFF); |
967 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
968 | u32 reg; | 975 | u32 reg; |
976 | unsigned long flags; | ||
969 | 977 | ||
970 | /* | 978 | /* |
971 | * When interrupts are being enabled, the interrupt registers | 979 | * When interrupts are being enabled, the interrupt registers |
@@ -974,12 +982,20 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
974 | if (state == STATE_RADIO_IRQ_ON) { | 982 | if (state == STATE_RADIO_IRQ_ON) { |
975 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 983 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); |
976 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 984 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); |
985 | |||
986 | /* | ||
987 | * Enable tasklets. | ||
988 | */ | ||
989 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
990 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
977 | } | 991 | } |
978 | 992 | ||
979 | /* | 993 | /* |
980 | * Only toggle the interrupts bits we are going to use. | 994 | * Only toggle the interrupts bits we are going to use. |
981 | * Non-checked interrupt bits are disabled by default. | 995 | * Non-checked interrupt bits are disabled by default. |
982 | */ | 996 | */ |
997 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
998 | |||
983 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 999 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
984 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 1000 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
985 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 1001 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
@@ -987,6 +1003,17 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
987 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 1003 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
988 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 1004 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
989 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1005 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1006 | |||
1007 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1008 | |||
1009 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1010 | /* | ||
1011 | * Ensure that all tasklets are finished before | ||
1012 | * disabling the interrupts. | ||
1013 | */ | ||
1014 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1015 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1016 | } | ||
990 | } | 1017 | } |
991 | 1018 | ||
992 | static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1019 | static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1059,9 +1086,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1059 | rt2400pci_disable_radio(rt2x00dev); | 1086 | rt2400pci_disable_radio(rt2x00dev); |
1060 | break; | 1087 | break; |
1061 | case STATE_RADIO_IRQ_ON: | 1088 | case STATE_RADIO_IRQ_ON: |
1062 | case STATE_RADIO_IRQ_ON_ISR: | ||
1063 | case STATE_RADIO_IRQ_OFF: | 1089 | case STATE_RADIO_IRQ_OFF: |
1064 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1065 | rt2400pci_toggle_irq(rt2x00dev, state); | 1090 | rt2400pci_toggle_irq(rt2x00dev, state); |
1066 | break; | 1091 | break; |
1067 | case STATE_DEEP_SLEEP: | 1092 | case STATE_DEEP_SLEEP: |
@@ -1183,8 +1208,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, | |||
1183 | /* | 1208 | /* |
1184 | * Enable beaconing again. | 1209 | * Enable beaconing again. |
1185 | */ | 1210 | */ |
1186 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
1187 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
1188 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1211 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1189 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1212 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
1190 | } | 1213 | } |
@@ -1289,57 +1312,71 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1289 | } | 1312 | } |
1290 | } | 1313 | } |
1291 | 1314 | ||
1292 | static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) | 1315 | static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
1316 | struct rt2x00_field32 irq_field) | ||
1293 | { | 1317 | { |
1294 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1318 | unsigned long flags; |
1295 | u32 reg = rt2x00dev->irqvalue[0]; | 1319 | u32 reg; |
1296 | 1320 | ||
1297 | /* | 1321 | /* |
1298 | * Handle interrupts, walk through all bits | 1322 | * Enable a single interrupt. The interrupt mask register |
1299 | * and run the tasks, the bits are checked in order of | 1323 | * access needs locking. |
1300 | * priority. | ||
1301 | */ | 1324 | */ |
1325 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1302 | 1326 | ||
1303 | /* | 1327 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1304 | * 1 - Beacon timer expired interrupt. | 1328 | rt2x00_set_field32(®, irq_field, 0); |
1305 | */ | 1329 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1306 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1307 | rt2x00lib_beacondone(rt2x00dev); | ||
1308 | 1330 | ||
1309 | /* | 1331 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1310 | * 2 - Rx ring done interrupt. | 1332 | } |
1311 | */ | ||
1312 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) | ||
1313 | rt2x00pci_rxdone(rt2x00dev); | ||
1314 | 1333 | ||
1315 | /* | 1334 | static void rt2400pci_txstatus_tasklet(unsigned long data) |
1316 | * 3 - Atim ring transmit done interrupt. | 1335 | { |
1317 | */ | 1336 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1318 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) | 1337 | u32 reg; |
1319 | rt2400pci_txdone(rt2x00dev, QID_ATIM); | 1338 | unsigned long flags; |
1320 | 1339 | ||
1321 | /* | 1340 | /* |
1322 | * 4 - Priority ring transmit done interrupt. | 1341 | * Handle all tx queues. |
1323 | */ | 1342 | */ |
1324 | if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) | 1343 | rt2400pci_txdone(rt2x00dev, QID_ATIM); |
1325 | rt2400pci_txdone(rt2x00dev, QID_AC_VO); | 1344 | rt2400pci_txdone(rt2x00dev, QID_AC_VO); |
1345 | rt2400pci_txdone(rt2x00dev, QID_AC_VI); | ||
1326 | 1346 | ||
1327 | /* | 1347 | /* |
1328 | * 5 - Tx ring transmit done interrupt. | 1348 | * Enable all TXDONE interrupts again. |
1329 | */ | 1349 | */ |
1330 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1350 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1331 | rt2400pci_txdone(rt2x00dev, QID_AC_VI); | ||
1332 | 1351 | ||
1333 | /* Enable interrupts again. */ | 1352 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1334 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1353 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); |
1335 | STATE_RADIO_IRQ_ON_ISR); | 1354 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); |
1336 | return IRQ_HANDLED; | 1355 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); |
1356 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1357 | |||
1358 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1359 | } | ||
1360 | |||
1361 | static void rt2400pci_tbtt_tasklet(unsigned long data) | ||
1362 | { | ||
1363 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1364 | rt2x00lib_beacondone(rt2x00dev); | ||
1365 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); | ||
1366 | } | ||
1367 | |||
1368 | static void rt2400pci_rxdone_tasklet(unsigned long data) | ||
1369 | { | ||
1370 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1371 | rt2x00pci_rxdone(rt2x00dev); | ||
1372 | rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | ||
1337 | } | 1373 | } |
1338 | 1374 | ||
1339 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | 1375 | static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) |
1340 | { | 1376 | { |
1341 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1377 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1342 | u32 reg; | 1378 | u32 reg, mask; |
1379 | unsigned long flags; | ||
1343 | 1380 | ||
1344 | /* | 1381 | /* |
1345 | * Get the interrupt sources & saved to local variable. | 1382 | * Get the interrupt sources & saved to local variable. |
@@ -1354,14 +1391,44 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) | |||
1354 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1391 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1355 | return IRQ_HANDLED; | 1392 | return IRQ_HANDLED; |
1356 | 1393 | ||
1357 | /* Store irqvalues for use in the interrupt thread. */ | 1394 | mask = reg; |
1358 | rt2x00dev->irqvalue[0] = reg; | ||
1359 | 1395 | ||
1360 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 1396 | /* |
1361 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1397 | * Schedule tasklets for interrupt handling. |
1362 | STATE_RADIO_IRQ_OFF_ISR); | 1398 | */ |
1399 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1400 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
1363 | 1401 | ||
1364 | return IRQ_WAKE_THREAD; | 1402 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) |
1403 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
1404 | |||
1405 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || | ||
1406 | rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || | ||
1407 | rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { | ||
1408 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
1409 | /* | ||
1410 | * Mask out all txdone interrupts. | ||
1411 | */ | ||
1412 | rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); | ||
1413 | rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); | ||
1414 | rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); | ||
1415 | } | ||
1416 | |||
1417 | /* | ||
1418 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
1419 | * the tasklet will reenable the appropriate interrupts. | ||
1420 | */ | ||
1421 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1422 | |||
1423 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1424 | reg |= mask; | ||
1425 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1426 | |||
1427 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1428 | |||
1429 | |||
1430 | |||
1431 | return IRQ_HANDLED; | ||
1365 | } | 1432 | } |
1366 | 1433 | ||
1367 | /* | 1434 | /* |
@@ -1655,7 +1722,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1655 | 1722 | ||
1656 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | 1723 | static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { |
1657 | .irq_handler = rt2400pci_interrupt, | 1724 | .irq_handler = rt2400pci_interrupt, |
1658 | .irq_handler_thread = rt2400pci_interrupt_thread, | 1725 | .txstatus_tasklet = rt2400pci_txstatus_tasklet, |
1726 | .tbtt_tasklet = rt2400pci_tbtt_tasklet, | ||
1727 | .rxdone_tasklet = rt2400pci_rxdone_tasklet, | ||
1659 | .probe_hw = rt2400pci_probe_hw, | 1728 | .probe_hw = rt2400pci_probe_hw, |
1660 | .initialize = rt2x00pci_initialize, | 1729 | .initialize = rt2x00pci_initialize, |
1661 | .uninitialize = rt2x00pci_uninitialize, | 1730 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a9ff26a27724..3ef1fb4185c0 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -311,9 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
311 | * Enable synchronisation. | 311 | * Enable synchronisation. |
312 | */ | 312 | */ |
313 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 313 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
314 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
315 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); | 314 | rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); |
316 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
317 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 315 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
318 | } | 316 | } |
319 | 317 | ||
@@ -737,6 +735,11 @@ static void rt2500pci_start_queue(struct data_queue *queue) | |||
737 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); | 735 | rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); |
738 | break; | 736 | break; |
739 | case QID_BEACON: | 737 | case QID_BEACON: |
738 | /* | ||
739 | * Allow the tbtt tasklet to be scheduled. | ||
740 | */ | ||
741 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
742 | |||
740 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | 743 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); |
741 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | 744 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); |
742 | rt2x00_set_field32(®, CSR14_TBCN, 1); | 745 | rt2x00_set_field32(®, CSR14_TBCN, 1); |
@@ -798,6 +801,11 @@ static void rt2500pci_stop_queue(struct data_queue *queue) | |||
798 | rt2x00_set_field32(®, CSR14_TBCN, 0); | 801 | rt2x00_set_field32(®, CSR14_TBCN, 0); |
799 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | 802 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); |
800 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 803 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
804 | |||
805 | /* | ||
806 | * Wait for possibly running tbtt tasklets. | ||
807 | */ | ||
808 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
801 | break; | 809 | break; |
802 | default: | 810 | default: |
803 | break; | 811 | break; |
@@ -1118,9 +1126,9 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1118 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1126 | static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1119 | enum dev_state state) | 1127 | enum dev_state state) |
1120 | { | 1128 | { |
1121 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 1129 | int mask = (state == STATE_RADIO_IRQ_OFF); |
1122 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1123 | u32 reg; | 1130 | u32 reg; |
1131 | unsigned long flags; | ||
1124 | 1132 | ||
1125 | /* | 1133 | /* |
1126 | * When interrupts are being enabled, the interrupt registers | 1134 | * When interrupts are being enabled, the interrupt registers |
@@ -1129,12 +1137,20 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1129 | if (state == STATE_RADIO_IRQ_ON) { | 1137 | if (state == STATE_RADIO_IRQ_ON) { |
1130 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); | 1138 | rt2x00pci_register_read(rt2x00dev, CSR7, ®); |
1131 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); | 1139 | rt2x00pci_register_write(rt2x00dev, CSR7, reg); |
1140 | |||
1141 | /* | ||
1142 | * Enable tasklets. | ||
1143 | */ | ||
1144 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
1145 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
1132 | } | 1146 | } |
1133 | 1147 | ||
1134 | /* | 1148 | /* |
1135 | * Only toggle the interrupts bits we are going to use. | 1149 | * Only toggle the interrupts bits we are going to use. |
1136 | * Non-checked interrupt bits are disabled by default. | 1150 | * Non-checked interrupt bits are disabled by default. |
1137 | */ | 1151 | */ |
1152 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1153 | |||
1138 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | 1154 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1139 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); | 1155 | rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); |
1140 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); | 1156 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); |
@@ -1142,6 +1158,16 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1142 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); | 1158 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); |
1143 | rt2x00_set_field32(®, CSR8_RXDONE, mask); | 1159 | rt2x00_set_field32(®, CSR8_RXDONE, mask); |
1144 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | 1160 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1161 | |||
1162 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1163 | |||
1164 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1165 | /* | ||
1166 | * Ensure that all tasklets are finished. | ||
1167 | */ | ||
1168 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1169 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1170 | } | ||
1145 | } | 1171 | } |
1146 | 1172 | ||
1147 | static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1173 | static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1214,9 +1240,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1214 | rt2500pci_disable_radio(rt2x00dev); | 1240 | rt2500pci_disable_radio(rt2x00dev); |
1215 | break; | 1241 | break; |
1216 | case STATE_RADIO_IRQ_ON: | 1242 | case STATE_RADIO_IRQ_ON: |
1217 | case STATE_RADIO_IRQ_ON_ISR: | ||
1218 | case STATE_RADIO_IRQ_OFF: | 1243 | case STATE_RADIO_IRQ_OFF: |
1219 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1220 | rt2500pci_toggle_irq(rt2x00dev, state); | 1244 | rt2500pci_toggle_irq(rt2x00dev, state); |
1221 | break; | 1245 | break; |
1222 | case STATE_DEEP_SLEEP: | 1246 | case STATE_DEEP_SLEEP: |
@@ -1337,8 +1361,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, | |||
1337 | /* | 1361 | /* |
1338 | * Enable beaconing again. | 1362 | * Enable beaconing again. |
1339 | */ | 1363 | */ |
1340 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); | ||
1341 | rt2x00_set_field32(®, CSR14_TBCN, 1); | ||
1342 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); | 1364 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); |
1343 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | 1365 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); |
1344 | } | 1366 | } |
@@ -1422,58 +1444,71 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, | |||
1422 | } | 1444 | } |
1423 | } | 1445 | } |
1424 | 1446 | ||
1425 | static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) | 1447 | static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
1448 | struct rt2x00_field32 irq_field) | ||
1426 | { | 1449 | { |
1427 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1450 | unsigned long flags; |
1428 | u32 reg = rt2x00dev->irqvalue[0]; | 1451 | u32 reg; |
1429 | 1452 | ||
1430 | /* | 1453 | /* |
1431 | * Handle interrupts, walk through all bits | 1454 | * Enable a single interrupt. The interrupt mask register |
1432 | * and run the tasks, the bits are checked in order of | 1455 | * access needs locking. |
1433 | * priority. | ||
1434 | */ | 1456 | */ |
1457 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1435 | 1458 | ||
1436 | /* | 1459 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); |
1437 | * 1 - Beacon timer expired interrupt. | 1460 | rt2x00_set_field32(®, irq_field, 0); |
1438 | */ | 1461 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); |
1439 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1440 | rt2x00lib_beacondone(rt2x00dev); | ||
1441 | 1462 | ||
1442 | /* | 1463 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1443 | * 2 - Rx ring done interrupt. | 1464 | } |
1444 | */ | ||
1445 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) | ||
1446 | rt2x00pci_rxdone(rt2x00dev); | ||
1447 | 1465 | ||
1448 | /* | 1466 | static void rt2500pci_txstatus_tasklet(unsigned long data) |
1449 | * 3 - Atim ring transmit done interrupt. | 1467 | { |
1450 | */ | 1468 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
1451 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) | 1469 | u32 reg; |
1452 | rt2500pci_txdone(rt2x00dev, QID_ATIM); | 1470 | unsigned long flags; |
1453 | 1471 | ||
1454 | /* | 1472 | /* |
1455 | * 4 - Priority ring transmit done interrupt. | 1473 | * Handle all tx queues. |
1456 | */ | 1474 | */ |
1457 | if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) | 1475 | rt2500pci_txdone(rt2x00dev, QID_ATIM); |
1458 | rt2500pci_txdone(rt2x00dev, QID_AC_VO); | 1476 | rt2500pci_txdone(rt2x00dev, QID_AC_VO); |
1477 | rt2500pci_txdone(rt2x00dev, QID_AC_VI); | ||
1459 | 1478 | ||
1460 | /* | 1479 | /* |
1461 | * 5 - Tx ring transmit done interrupt. | 1480 | * Enable all TXDONE interrupts again. |
1462 | */ | 1481 | */ |
1463 | if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) | 1482 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
1464 | rt2500pci_txdone(rt2x00dev, QID_AC_VI); | 1483 | |
1484 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1485 | rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); | ||
1486 | rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); | ||
1487 | rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); | ||
1488 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1465 | 1489 | ||
1466 | /* Enable interrupts again. */ | 1490 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
1467 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1491 | } |
1468 | STATE_RADIO_IRQ_ON_ISR); | ||
1469 | 1492 | ||
1470 | return IRQ_HANDLED; | 1493 | static void rt2500pci_tbtt_tasklet(unsigned long data) |
1494 | { | ||
1495 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1496 | rt2x00lib_beacondone(rt2x00dev); | ||
1497 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); | ||
1498 | } | ||
1499 | |||
1500 | static void rt2500pci_rxdone_tasklet(unsigned long data) | ||
1501 | { | ||
1502 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
1503 | rt2x00pci_rxdone(rt2x00dev); | ||
1504 | rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); | ||
1471 | } | 1505 | } |
1472 | 1506 | ||
1473 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | 1507 | static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) |
1474 | { | 1508 | { |
1475 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1509 | struct rt2x00_dev *rt2x00dev = dev_instance; |
1476 | u32 reg; | 1510 | u32 reg, mask; |
1511 | unsigned long flags; | ||
1477 | 1512 | ||
1478 | /* | 1513 | /* |
1479 | * Get the interrupt sources & saved to local variable. | 1514 | * Get the interrupt sources & saved to local variable. |
@@ -1488,14 +1523,42 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) | |||
1488 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 1523 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
1489 | return IRQ_HANDLED; | 1524 | return IRQ_HANDLED; |
1490 | 1525 | ||
1491 | /* Store irqvalues for use in the interrupt thread. */ | 1526 | mask = reg; |
1492 | rt2x00dev->irqvalue[0] = reg; | ||
1493 | 1527 | ||
1494 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 1528 | /* |
1495 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 1529 | * Schedule tasklets for interrupt handling. |
1496 | STATE_RADIO_IRQ_OFF_ISR); | 1530 | */ |
1531 | if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) | ||
1532 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); | ||
1497 | 1533 | ||
1498 | return IRQ_WAKE_THREAD; | 1534 | if (rt2x00_get_field32(reg, CSR7_RXDONE)) |
1535 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
1536 | |||
1537 | if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || | ||
1538 | rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || | ||
1539 | rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { | ||
1540 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
1541 | /* | ||
1542 | * Mask out all txdone interrupts. | ||
1543 | */ | ||
1544 | rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); | ||
1545 | rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); | ||
1546 | rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); | ||
1547 | } | ||
1548 | |||
1549 | /* | ||
1550 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
1551 | * the tasklet will reenable the appropriate interrupts. | ||
1552 | */ | ||
1553 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1554 | |||
1555 | rt2x00pci_register_read(rt2x00dev, CSR8, ®); | ||
1556 | reg |= mask; | ||
1557 | rt2x00pci_register_write(rt2x00dev, CSR8, reg); | ||
1558 | |||
1559 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1560 | |||
1561 | return IRQ_HANDLED; | ||
1499 | } | 1562 | } |
1500 | 1563 | ||
1501 | /* | 1564 | /* |
@@ -1952,7 +2015,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1952 | 2015 | ||
1953 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | 2016 | static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { |
1954 | .irq_handler = rt2500pci_interrupt, | 2017 | .irq_handler = rt2500pci_interrupt, |
1955 | .irq_handler_thread = rt2500pci_interrupt_thread, | 2018 | .txstatus_tasklet = rt2500pci_txstatus_tasklet, |
2019 | .tbtt_tasklet = rt2500pci_tbtt_tasklet, | ||
2020 | .rxdone_tasklet = rt2500pci_rxdone_tasklet, | ||
1956 | .probe_hw = rt2500pci_probe_hw, | 2021 | .probe_hw = rt2500pci_probe_hw, |
1957 | .initialize = rt2x00pci_initialize, | 2022 | .initialize = rt2x00pci_initialize, |
1958 | .uninitialize = rt2x00pci_uninitialize, | 2023 | .uninitialize = rt2x00pci_uninitialize, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 6b3b1de46792..01f385d5846c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -478,9 +478,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
478 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); | 478 | rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); |
479 | 479 | ||
480 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | 480 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); |
481 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); | ||
482 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); | 481 | rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); |
483 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); | ||
484 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | 482 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); |
485 | } | 483 | } |
486 | 484 | ||
@@ -1056,9 +1054,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1056 | rt2500usb_disable_radio(rt2x00dev); | 1054 | rt2500usb_disable_radio(rt2x00dev); |
1057 | break; | 1055 | break; |
1058 | case STATE_RADIO_IRQ_ON: | 1056 | case STATE_RADIO_IRQ_ON: |
1059 | case STATE_RADIO_IRQ_ON_ISR: | ||
1060 | case STATE_RADIO_IRQ_OFF: | 1057 | case STATE_RADIO_IRQ_OFF: |
1061 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1062 | /* No support, but no error either */ | 1058 | /* No support, but no error either */ |
1063 | break; | 1059 | break; |
1064 | case STATE_DEEP_SLEEP: | 1060 | case STATE_DEEP_SLEEP: |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index c7e615cebac1..ec8159ce0ee8 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -372,8 +372,12 @@ | |||
372 | 372 | ||
373 | /* | 373 | /* |
374 | * US_CYC_CNT | 374 | * US_CYC_CNT |
375 | * BT_MODE_EN: Bluetooth mode enable | ||
376 | * CLOCK CYCLE: Clock cycle count in 1us. | ||
377 | * PCI:0x21, PCIE:0x7d, USB:0x1e | ||
375 | */ | 378 | */ |
376 | #define US_CYC_CNT 0x02a4 | 379 | #define US_CYC_CNT 0x02a4 |
380 | #define US_CYC_CNT_BT_MODE_EN FIELD32(0x00000100) | ||
377 | #define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) | 381 | #define US_CYC_CNT_CLOCK_CYCLE FIELD32(0x000000ff) |
378 | 382 | ||
379 | /* | 383 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index f8ba01cbc6dd..c9bf074342ba 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -818,8 +818,6 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
818 | /* | 818 | /* |
819 | * Enable beaconing again. | 819 | * Enable beaconing again. |
820 | */ | 820 | */ |
821 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
822 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
823 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | 821 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); |
824 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 822 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
825 | 823 | ||
@@ -831,8 +829,8 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
831 | } | 829 | } |
832 | EXPORT_SYMBOL_GPL(rt2800_write_beacon); | 830 | EXPORT_SYMBOL_GPL(rt2800_write_beacon); |
833 | 831 | ||
834 | static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, | 832 | static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, |
835 | unsigned int beacon_base) | 833 | unsigned int beacon_base) |
836 | { | 834 | { |
837 | int i; | 835 | int i; |
838 | 836 | ||
@@ -845,6 +843,33 @@ static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, | |||
845 | rt2800_register_write(rt2x00dev, beacon_base + i, 0); | 843 | rt2800_register_write(rt2x00dev, beacon_base + i, 0); |
846 | } | 844 | } |
847 | 845 | ||
846 | void rt2800_clear_beacon(struct queue_entry *entry) | ||
847 | { | ||
848 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
849 | u32 reg; | ||
850 | |||
851 | /* | ||
852 | * Disable beaconing while we are reloading the beacon data, | ||
853 | * otherwise we might be sending out invalid data. | ||
854 | */ | ||
855 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
856 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
857 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
858 | |||
859 | /* | ||
860 | * Clear beacon. | ||
861 | */ | ||
862 | rt2800_clear_beacon_register(rt2x00dev, | ||
863 | HW_BEACON_OFFSET(entry->entry_idx)); | ||
864 | |||
865 | /* | ||
866 | * Enabled beaconing again. | ||
867 | */ | ||
868 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
869 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
870 | } | ||
871 | EXPORT_SYMBOL_GPL(rt2800_clear_beacon); | ||
872 | |||
848 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | 873 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS |
849 | const struct rt2x00debug rt2800_rt2x00debug = { | 874 | const struct rt2x00debug rt2800_rt2x00debug = { |
850 | .owner = THIS_MODULE, | 875 | .owner = THIS_MODULE, |
@@ -1005,7 +1030,7 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | |||
1005 | 1030 | ||
1006 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | 1031 | memset(&wcid_entry, 0, sizeof(wcid_entry)); |
1007 | if (crypto->cmd == SET_KEY) | 1032 | if (crypto->cmd == SET_KEY) |
1008 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | 1033 | memcpy(wcid_entry.mac, crypto->address, ETH_ALEN); |
1009 | rt2800_register_multiwrite(rt2x00dev, offset, | 1034 | rt2800_register_multiwrite(rt2x00dev, offset, |
1010 | &wcid_entry, sizeof(wcid_entry)); | 1035 | &wcid_entry, sizeof(wcid_entry)); |
1011 | } | 1036 | } |
@@ -1155,29 +1180,11 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, | |||
1155 | 1180 | ||
1156 | if (flags & CONFIG_UPDATE_TYPE) { | 1181 | if (flags & CONFIG_UPDATE_TYPE) { |
1157 | /* | 1182 | /* |
1158 | * Clear current synchronisation setup. | ||
1159 | */ | ||
1160 | rt2800_clear_beacon(rt2x00dev, | ||
1161 | HW_BEACON_OFFSET(intf->beacon->entry_idx)); | ||
1162 | /* | ||
1163 | * Enable synchronisation. | 1183 | * Enable synchronisation. |
1164 | */ | 1184 | */ |
1165 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 1185 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
1166 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
1167 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | 1186 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); |
1168 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, | ||
1169 | (conf->sync == TSF_SYNC_ADHOC || | ||
1170 | conf->sync == TSF_SYNC_AP_NONE)); | ||
1171 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1187 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1172 | |||
1173 | /* | ||
1174 | * Enable pre tbtt interrupt for beaconing modes | ||
1175 | */ | ||
1176 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
1177 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, | ||
1178 | (conf->sync == TSF_SYNC_AP_NONE)); | ||
1179 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
1180 | |||
1181 | } | 1188 | } |
1182 | 1189 | ||
1183 | if (flags & CONFIG_UPDATE_MAC) { | 1190 | if (flags & CONFIG_UPDATE_MAC) { |
@@ -2187,19 +2194,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
2187 | /* | 2194 | /* |
2188 | * Clear all beacons | 2195 | * Clear all beacons |
2189 | */ | 2196 | */ |
2190 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0); | 2197 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0); |
2191 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1); | 2198 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1); |
2192 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2); | 2199 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2); |
2193 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3); | 2200 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3); |
2194 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4); | 2201 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4); |
2195 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5); | 2202 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5); |
2196 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6); | 2203 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6); |
2197 | rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7); | 2204 | rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7); |
2198 | 2205 | ||
2199 | if (rt2x00_is_usb(rt2x00dev)) { | 2206 | if (rt2x00_is_usb(rt2x00dev)) { |
2200 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); | 2207 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); |
2201 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); | 2208 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30); |
2202 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); | 2209 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); |
2210 | } else if (rt2x00_is_pcie(rt2x00dev)) { | ||
2211 | rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); | ||
2212 | rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125); | ||
2213 | rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); | ||
2203 | } | 2214 | } |
2204 | 2215 | ||
2205 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); | 2216 | rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 3efafb78ff77..0c92d86a36f4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -156,6 +156,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | |||
156 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status); | 156 | void rt2800_txdone_entry(struct queue_entry *entry, u32 status); |
157 | 157 | ||
158 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 158 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
159 | void rt2800_clear_beacon(struct queue_entry *entry); | ||
159 | 160 | ||
160 | extern const struct rt2x00debug rt2800_rt2x00debug; | 161 | extern const struct rt2x00debug rt2800_rt2x00debug; |
161 | 162 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index bfc2fc5c1c22..8f4dfc3d8023 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -200,11 +200,22 @@ static void rt2800pci_start_queue(struct data_queue *queue) | |||
200 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 200 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
201 | break; | 201 | break; |
202 | case QID_BEACON: | 202 | case QID_BEACON: |
203 | /* | ||
204 | * Allow beacon tasklets to be scheduled for periodic | ||
205 | * beacon updates. | ||
206 | */ | ||
207 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
208 | tasklet_enable(&rt2x00dev->pretbtt_tasklet); | ||
209 | |||
203 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 210 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
204 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | 211 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); |
205 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | 212 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); |
206 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | 213 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); |
207 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 214 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
215 | |||
216 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
217 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); | ||
218 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
208 | break; | 219 | break; |
209 | default: | 220 | default: |
210 | break; | 221 | break; |
@@ -250,6 +261,16 @@ static void rt2800pci_stop_queue(struct data_queue *queue) | |||
250 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | 261 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); |
251 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | 262 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); |
252 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 263 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
264 | |||
265 | rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); | ||
266 | rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); | ||
267 | rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); | ||
268 | |||
269 | /* | ||
270 | * Wait for tbtt tasklets to finish. | ||
271 | */ | ||
272 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
273 | tasklet_disable(&rt2x00dev->pretbtt_tasklet); | ||
253 | break; | 274 | break; |
254 | default: | 275 | default: |
255 | break; | 276 | break; |
@@ -397,9 +418,9 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
397 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 418 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
398 | enum dev_state state) | 419 | enum dev_state state) |
399 | { | 420 | { |
400 | int mask = (state == STATE_RADIO_IRQ_ON) || | 421 | int mask = (state == STATE_RADIO_IRQ_ON); |
401 | (state == STATE_RADIO_IRQ_ON_ISR); | ||
402 | u32 reg; | 422 | u32 reg; |
423 | unsigned long flags; | ||
403 | 424 | ||
404 | /* | 425 | /* |
405 | * When interrupts are being enabled, the interrupt registers | 426 | * When interrupts are being enabled, the interrupt registers |
@@ -408,8 +429,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
408 | if (state == STATE_RADIO_IRQ_ON) { | 429 | if (state == STATE_RADIO_IRQ_ON) { |
409 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 430 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
410 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | 431 | rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); |
432 | |||
433 | /* | ||
434 | * Enable tasklets. The beacon related tasklets are | ||
435 | * enabled when the beacon queue is started. | ||
436 | */ | ||
437 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
438 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
439 | tasklet_enable(&rt2x00dev->autowake_tasklet); | ||
411 | } | 440 | } |
412 | 441 | ||
442 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
413 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | 443 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); |
414 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); | 444 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); |
415 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); | 445 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); |
@@ -430,6 +460,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
430 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); | 460 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); |
431 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); | 461 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); |
432 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | 462 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); |
463 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
464 | |||
465 | if (state == STATE_RADIO_IRQ_OFF) { | ||
466 | /* | ||
467 | * Ensure that all tasklets are finished before | ||
468 | * disabling the interrupts. | ||
469 | */ | ||
470 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
471 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
472 | tasklet_disable(&rt2x00dev->autowake_tasklet); | ||
473 | } | ||
433 | } | 474 | } |
434 | 475 | ||
435 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | 476 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) |
@@ -522,9 +563,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
522 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); | 563 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); |
523 | break; | 564 | break; |
524 | case STATE_RADIO_IRQ_ON: | 565 | case STATE_RADIO_IRQ_ON: |
525 | case STATE_RADIO_IRQ_ON_ISR: | ||
526 | case STATE_RADIO_IRQ_OFF: | 566 | case STATE_RADIO_IRQ_OFF: |
527 | case STATE_RADIO_IRQ_OFF_ISR: | ||
528 | rt2800pci_toggle_irq(rt2x00dev, state); | 567 | rt2800pci_toggle_irq(rt2x00dev, state); |
529 | break; | 568 | break; |
530 | case STATE_DEEP_SLEEP: | 569 | case STATE_DEEP_SLEEP: |
@@ -636,6 +675,12 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
636 | */ | 675 | */ |
637 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 676 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
638 | 677 | ||
678 | /* | ||
679 | * The hardware has already checked the Michael Mic and has | ||
680 | * stripped it from the frame. Signal this to mac80211. | ||
681 | */ | ||
682 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
683 | |||
639 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | 684 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) |
640 | rxdesc->flags |= RX_FLAG_DECRYPTED; | 685 | rxdesc->flags |= RX_FLAG_DECRYPTED; |
641 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | 686 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) |
@@ -710,45 +755,60 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
710 | } | 755 | } |
711 | } | 756 | } |
712 | 757 | ||
713 | static void rt2800pci_txstatus_tasklet(unsigned long data) | 758 | static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
714 | { | 759 | struct rt2x00_field32 irq_field) |
715 | rt2800pci_txdone((struct rt2x00_dev *)data); | ||
716 | } | ||
717 | |||
718 | static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | ||
719 | { | 760 | { |
720 | struct rt2x00_dev *rt2x00dev = dev_instance; | 761 | unsigned long flags; |
721 | u32 reg = rt2x00dev->irqvalue[0]; | 762 | u32 reg; |
722 | 763 | ||
723 | /* | 764 | /* |
724 | * 1 - Pre TBTT interrupt. | 765 | * Enable a single interrupt. The interrupt mask register |
766 | * access needs locking. | ||
725 | */ | 767 | */ |
726 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) | 768 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
727 | rt2x00lib_pretbtt(rt2x00dev); | 769 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); |
770 | rt2x00_set_field32(®, irq_field, 1); | ||
771 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
772 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
773 | } | ||
728 | 774 | ||
729 | /* | 775 | static void rt2800pci_txstatus_tasklet(unsigned long data) |
730 | * 2 - Beacondone interrupt. | 776 | { |
731 | */ | 777 | rt2800pci_txdone((struct rt2x00_dev *)data); |
732 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) | ||
733 | rt2x00lib_beacondone(rt2x00dev); | ||
734 | 778 | ||
735 | /* | 779 | /* |
736 | * 3 - Rx ring done interrupt. | 780 | * No need to enable the tx status interrupt here as we always |
781 | * leave it enabled to minimize the possibility of a tx status | ||
782 | * register overflow. See comment in interrupt handler. | ||
737 | */ | 783 | */ |
738 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | 784 | } |
739 | rt2x00pci_rxdone(rt2x00dev); | ||
740 | 785 | ||
741 | /* | 786 | static void rt2800pci_pretbtt_tasklet(unsigned long data) |
742 | * 4 - Auto wakeup interrupt. | 787 | { |
743 | */ | 788 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
744 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | 789 | rt2x00lib_pretbtt(rt2x00dev); |
745 | rt2800pci_wakeup(rt2x00dev); | 790 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); |
791 | } | ||
746 | 792 | ||
747 | /* Enable interrupts again. */ | 793 | static void rt2800pci_tbtt_tasklet(unsigned long data) |
748 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 794 | { |
749 | STATE_RADIO_IRQ_ON_ISR); | 795 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; |
796 | rt2x00lib_beacondone(rt2x00dev); | ||
797 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); | ||
798 | } | ||
750 | 799 | ||
751 | return IRQ_HANDLED; | 800 | static void rt2800pci_rxdone_tasklet(unsigned long data) |
801 | { | ||
802 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
803 | rt2x00pci_rxdone(rt2x00dev); | ||
804 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); | ||
805 | } | ||
806 | |||
807 | static void rt2800pci_autowake_tasklet(unsigned long data) | ||
808 | { | ||
809 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
810 | rt2800pci_wakeup(rt2x00dev); | ||
811 | rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP); | ||
752 | } | 812 | } |
753 | 813 | ||
754 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | 814 | static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) |
@@ -794,8 +854,8 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) | |||
794 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 854 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) |
795 | { | 855 | { |
796 | struct rt2x00_dev *rt2x00dev = dev_instance; | 856 | struct rt2x00_dev *rt2x00dev = dev_instance; |
797 | u32 reg; | 857 | u32 reg, mask; |
798 | irqreturn_t ret = IRQ_HANDLED; | 858 | unsigned long flags; |
799 | 859 | ||
800 | /* Read status and ACK all interrupts */ | 860 | /* Read status and ACK all interrupts */ |
801 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | 861 | rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); |
@@ -807,38 +867,44 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
807 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 867 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
808 | return IRQ_HANDLED; | 868 | return IRQ_HANDLED; |
809 | 869 | ||
810 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 870 | /* |
811 | rt2800pci_txstatus_interrupt(rt2x00dev); | 871 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits |
872 | * for interrupts and interrupt masks we can just use the value of | ||
873 | * INT_SOURCE_CSR to create the interrupt mask. | ||
874 | */ | ||
875 | mask = ~reg; | ||
812 | 876 | ||
813 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || | 877 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { |
814 | rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || | 878 | rt2800pci_txstatus_interrupt(rt2x00dev); |
815 | rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || | ||
816 | rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { | ||
817 | /* | 879 | /* |
818 | * All other interrupts are handled in the interrupt thread. | 880 | * Never disable the TX_FIFO_STATUS interrupt. |
819 | * Store irqvalue for use in the interrupt thread. | ||
820 | */ | 881 | */ |
821 | rt2x00dev->irqvalue[0] = reg; | 882 | rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); |
883 | } | ||
822 | 884 | ||
823 | /* | 885 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) |
824 | * Disable interrupts, will be enabled again in the | 886 | tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); |
825 | * interrupt thread. | ||
826 | */ | ||
827 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | ||
828 | STATE_RADIO_IRQ_OFF_ISR); | ||
829 | 887 | ||
830 | /* | 888 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) |
831 | * Leave the TX_FIFO_STATUS interrupt enabled to not lose any | 889 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); |
832 | * tx status reports. | ||
833 | */ | ||
834 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
835 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); | ||
836 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
837 | 890 | ||
838 | ret = IRQ_WAKE_THREAD; | 891 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) |
839 | } | 892 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); |
840 | 893 | ||
841 | return ret; | 894 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) |
895 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
896 | |||
897 | /* | ||
898 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
899 | * the tasklet will reenable the appropriate interrupts. | ||
900 | */ | ||
901 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
902 | rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
903 | reg &= mask; | ||
904 | rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
905 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
906 | |||
907 | return IRQ_HANDLED; | ||
842 | } | 908 | } |
843 | 909 | ||
844 | /* | 910 | /* |
@@ -953,8 +1019,11 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
953 | 1019 | ||
954 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 1020 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
955 | .irq_handler = rt2800pci_interrupt, | 1021 | .irq_handler = rt2800pci_interrupt, |
956 | .irq_handler_thread = rt2800pci_interrupt_thread, | 1022 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, |
957 | .txstatus_tasklet = rt2800pci_txstatus_tasklet, | 1023 | .pretbtt_tasklet = rt2800pci_pretbtt_tasklet, |
1024 | .tbtt_tasklet = rt2800pci_tbtt_tasklet, | ||
1025 | .rxdone_tasklet = rt2800pci_rxdone_tasklet, | ||
1026 | .autowake_tasklet = rt2800pci_autowake_tasklet, | ||
958 | .probe_hw = rt2800pci_probe_hw, | 1027 | .probe_hw = rt2800pci_probe_hw, |
959 | .get_firmware_name = rt2800pci_get_firmware_name, | 1028 | .get_firmware_name = rt2800pci_get_firmware_name, |
960 | .check_firmware = rt2800_check_firmware, | 1029 | .check_firmware = rt2800_check_firmware, |
@@ -974,6 +1043,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
974 | .write_tx_desc = rt2800pci_write_tx_desc, | 1043 | .write_tx_desc = rt2800pci_write_tx_desc, |
975 | .write_tx_data = rt2800_write_tx_data, | 1044 | .write_tx_data = rt2800_write_tx_data, |
976 | .write_beacon = rt2800_write_beacon, | 1045 | .write_beacon = rt2800_write_beacon, |
1046 | .clear_beacon = rt2800_clear_beacon, | ||
977 | .fill_rxdone = rt2800pci_fill_rxdone, | 1047 | .fill_rxdone = rt2800pci_fill_rxdone, |
978 | .config_shared_key = rt2800_config_shared_key, | 1048 | .config_shared_key = rt2800_config_shared_key, |
979 | .config_pairwise_key = rt2800_config_pairwise_key, | 1049 | .config_pairwise_key = rt2800_config_pairwise_key, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b97a4a54ff4c..5d91561e0de7 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -253,9 +253,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
253 | rt2800usb_set_state(rt2x00dev, STATE_SLEEP); | 253 | rt2800usb_set_state(rt2x00dev, STATE_SLEEP); |
254 | break; | 254 | break; |
255 | case STATE_RADIO_IRQ_ON: | 255 | case STATE_RADIO_IRQ_ON: |
256 | case STATE_RADIO_IRQ_ON_ISR: | ||
257 | case STATE_RADIO_IRQ_OFF: | 256 | case STATE_RADIO_IRQ_OFF: |
258 | case STATE_RADIO_IRQ_OFF_ISR: | ||
259 | /* No support, but no error either */ | 257 | /* No support, but no error either */ |
260 | break; | 258 | break; |
261 | case STATE_DEEP_SLEEP: | 259 | case STATE_DEEP_SLEEP: |
@@ -486,6 +484,12 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
486 | */ | 484 | */ |
487 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 485 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
488 | 486 | ||
487 | /* | ||
488 | * The hardware has already checked the Michael Mic and has | ||
489 | * stripped it from the frame. Signal this to mac80211. | ||
490 | */ | ||
491 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | ||
492 | |||
489 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | 493 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) |
490 | rxdesc->flags |= RX_FLAG_DECRYPTED; | 494 | rxdesc->flags |= RX_FLAG_DECRYPTED; |
491 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | 495 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) |
@@ -633,6 +637,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
633 | .write_tx_desc = rt2800usb_write_tx_desc, | 637 | .write_tx_desc = rt2800usb_write_tx_desc, |
634 | .write_tx_data = rt2800usb_write_tx_data, | 638 | .write_tx_data = rt2800usb_write_tx_data, |
635 | .write_beacon = rt2800_write_beacon, | 639 | .write_beacon = rt2800_write_beacon, |
640 | .clear_beacon = rt2800_clear_beacon, | ||
636 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 641 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
637 | .fill_rxdone = rt2800usb_fill_rxdone, | 642 | .fill_rxdone = rt2800usb_fill_rxdone, |
638 | .config_shared_key = rt2800_config_shared_key, | 643 | .config_shared_key = rt2800_config_shared_key, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 84aaf393da43..39bc2faf1793 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -368,6 +368,7 @@ struct rt2x00_intf { | |||
368 | * dedicated beacon entry. | 368 | * dedicated beacon entry. |
369 | */ | 369 | */ |
370 | struct queue_entry *beacon; | 370 | struct queue_entry *beacon; |
371 | bool enable_beacon; | ||
371 | 372 | ||
372 | /* | 373 | /* |
373 | * Actions that needed rescheduling. | 374 | * Actions that needed rescheduling. |
@@ -511,14 +512,13 @@ struct rt2x00lib_ops { | |||
511 | irq_handler_t irq_handler; | 512 | irq_handler_t irq_handler; |
512 | 513 | ||
513 | /* | 514 | /* |
514 | * Threaded Interrupt handlers. | ||
515 | */ | ||
516 | irq_handler_t irq_handler_thread; | ||
517 | |||
518 | /* | ||
519 | * TX status tasklet handler. | 515 | * TX status tasklet handler. |
520 | */ | 516 | */ |
521 | void (*txstatus_tasklet) (unsigned long data); | 517 | void (*txstatus_tasklet) (unsigned long data); |
518 | void (*pretbtt_tasklet) (unsigned long data); | ||
519 | void (*tbtt_tasklet) (unsigned long data); | ||
520 | void (*rxdone_tasklet) (unsigned long data); | ||
521 | void (*autowake_tasklet) (unsigned long data); | ||
522 | 522 | ||
523 | /* | 523 | /* |
524 | * Device init handlers. | 524 | * Device init handlers. |
@@ -573,6 +573,7 @@ struct rt2x00lib_ops { | |||
573 | struct txentry_desc *txdesc); | 573 | struct txentry_desc *txdesc); |
574 | void (*write_beacon) (struct queue_entry *entry, | 574 | void (*write_beacon) (struct queue_entry *entry, |
575 | struct txentry_desc *txdesc); | 575 | struct txentry_desc *txdesc); |
576 | void (*clear_beacon) (struct queue_entry *entry); | ||
576 | int (*get_tx_data_len) (struct queue_entry *entry); | 577 | int (*get_tx_data_len) (struct queue_entry *entry); |
577 | 578 | ||
578 | /* | 579 | /* |
@@ -788,10 +789,12 @@ struct rt2x00_dev { | |||
788 | * - Open ap interface count. | 789 | * - Open ap interface count. |
789 | * - Open sta interface count. | 790 | * - Open sta interface count. |
790 | * - Association count. | 791 | * - Association count. |
792 | * - Beaconing enabled count. | ||
791 | */ | 793 | */ |
792 | unsigned int intf_ap_count; | 794 | unsigned int intf_ap_count; |
793 | unsigned int intf_sta_count; | 795 | unsigned int intf_sta_count; |
794 | unsigned int intf_associated; | 796 | unsigned int intf_associated; |
797 | unsigned int intf_beaconing; | ||
795 | 798 | ||
796 | /* | 799 | /* |
797 | * Link quality | 800 | * Link quality |
@@ -857,6 +860,13 @@ struct rt2x00_dev { | |||
857 | */ | 860 | */ |
858 | struct ieee80211_low_level_stats low_level_stats; | 861 | struct ieee80211_low_level_stats low_level_stats; |
859 | 862 | ||
863 | /** | ||
864 | * Work queue for all work which should not be placed | ||
865 | * on the mac80211 workqueue (because of dependencies | ||
866 | * between various work structures). | ||
867 | */ | ||
868 | struct workqueue_struct *workqueue; | ||
869 | |||
860 | /* | 870 | /* |
861 | * Scheduled work. | 871 | * Scheduled work. |
862 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 872 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
@@ -887,12 +897,6 @@ struct rt2x00_dev { | |||
887 | const struct firmware *fw; | 897 | const struct firmware *fw; |
888 | 898 | ||
889 | /* | 899 | /* |
890 | * Interrupt values, stored between interrupt service routine | ||
891 | * and interrupt thread routine. | ||
892 | */ | ||
893 | u32 irqvalue[2]; | ||
894 | |||
895 | /* | ||
896 | * FIFO for storing tx status reports between isr and tasklet. | 900 | * FIFO for storing tx status reports between isr and tasklet. |
897 | */ | 901 | */ |
898 | DECLARE_KFIFO_PTR(txstatus_fifo, u32); | 902 | DECLARE_KFIFO_PTR(txstatus_fifo, u32); |
@@ -901,6 +905,15 @@ struct rt2x00_dev { | |||
901 | * Tasklet for processing tx status reports (rt2800pci). | 905 | * Tasklet for processing tx status reports (rt2800pci). |
902 | */ | 906 | */ |
903 | struct tasklet_struct txstatus_tasklet; | 907 | struct tasklet_struct txstatus_tasklet; |
908 | struct tasklet_struct pretbtt_tasklet; | ||
909 | struct tasklet_struct tbtt_tasklet; | ||
910 | struct tasklet_struct rxdone_tasklet; | ||
911 | struct tasklet_struct autowake_tasklet; | ||
912 | |||
913 | /* | ||
914 | * Protect the interrupt mask register. | ||
915 | */ | ||
916 | spinlock_t irqmask_lock; | ||
904 | }; | 917 | }; |
905 | 918 | ||
906 | /* | 919 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 31b7db05abd9..9de9dbe94399 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -121,7 +121,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
121 | return; | 121 | return; |
122 | 122 | ||
123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) | 123 | if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) |
124 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 124 | rt2x00queue_update_beacon(rt2x00dev, vif); |
125 | } | 125 | } |
126 | 126 | ||
127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) | 127 | static void rt2x00lib_intf_scheduled(struct work_struct *work) |
@@ -174,7 +174,13 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac, | |||
174 | vif->type != NL80211_IFTYPE_WDS) | 174 | vif->type != NL80211_IFTYPE_WDS) |
175 | return; | 175 | return; |
176 | 176 | ||
177 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 177 | /* |
178 | * Update the beacon without locking. This is safe on PCI devices | ||
179 | * as they only update the beacon periodically here. This should | ||
180 | * never be called for USB devices. | ||
181 | */ | ||
182 | WARN_ON(rt2x00_is_usb(rt2x00dev)); | ||
183 | rt2x00queue_update_beacon_locked(rt2x00dev, vif); | ||
178 | } | 184 | } |
179 | 185 | ||
180 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | 186 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) |
@@ -183,9 +189,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
183 | return; | 189 | return; |
184 | 190 | ||
185 | /* send buffered bc/mc frames out for every bssid */ | 191 | /* send buffered bc/mc frames out for every bssid */ |
186 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 192 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
187 | rt2x00lib_bc_buffer_iter, | 193 | rt2x00lib_bc_buffer_iter, |
188 | rt2x00dev); | 194 | rt2x00dev); |
189 | /* | 195 | /* |
190 | * Devices with pre tbtt interrupt don't need to update the beacon | 196 | * Devices with pre tbtt interrupt don't need to update the beacon |
191 | * here as they will fetch the next beacon directly prior to | 197 | * here as they will fetch the next beacon directly prior to |
@@ -195,9 +201,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
195 | return; | 201 | return; |
196 | 202 | ||
197 | /* fetch next beacon */ | 203 | /* fetch next beacon */ |
198 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 204 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
199 | rt2x00lib_beaconupdate_iter, | 205 | rt2x00lib_beaconupdate_iter, |
200 | rt2x00dev); | 206 | rt2x00dev); |
201 | } | 207 | } |
202 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 208 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
203 | 209 | ||
@@ -207,9 +213,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) | |||
207 | return; | 213 | return; |
208 | 214 | ||
209 | /* fetch next beacon */ | 215 | /* fetch next beacon */ |
210 | ieee80211_iterate_active_interfaces(rt2x00dev->hw, | 216 | ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, |
211 | rt2x00lib_beaconupdate_iter, | 217 | rt2x00lib_beaconupdate_iter, |
212 | rt2x00dev); | 218 | rt2x00dev); |
213 | } | 219 | } |
214 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | 220 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); |
215 | 221 | ||
@@ -815,15 +821,29 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
815 | GFP_KERNEL); | 821 | GFP_KERNEL); |
816 | if (status) | 822 | if (status) |
817 | return status; | 823 | return status; |
824 | } | ||
818 | 825 | ||
819 | /* tasklet for processing the tx status reports. */ | 826 | /* |
820 | if (rt2x00dev->ops->lib->txstatus_tasklet) | 827 | * Initialize tasklets if used by the driver. Tasklets are |
821 | tasklet_init(&rt2x00dev->txstatus_tasklet, | 828 | * disabled until the interrupts are turned on. The driver |
822 | rt2x00dev->ops->lib->txstatus_tasklet, | 829 | * has to handle that. |
823 | (unsigned long)rt2x00dev); | 830 | */ |
824 | 831 | #define RT2X00_TASKLET_INIT(taskletname) \ | |
832 | if (rt2x00dev->ops->lib->taskletname) { \ | ||
833 | tasklet_init(&rt2x00dev->taskletname, \ | ||
834 | rt2x00dev->ops->lib->taskletname, \ | ||
835 | (unsigned long)rt2x00dev); \ | ||
836 | tasklet_disable(&rt2x00dev->taskletname); \ | ||
825 | } | 837 | } |
826 | 838 | ||
839 | RT2X00_TASKLET_INIT(txstatus_tasklet); | ||
840 | RT2X00_TASKLET_INIT(pretbtt_tasklet); | ||
841 | RT2X00_TASKLET_INIT(tbtt_tasklet); | ||
842 | RT2X00_TASKLET_INIT(rxdone_tasklet); | ||
843 | RT2X00_TASKLET_INIT(autowake_tasklet); | ||
844 | |||
845 | #undef RT2X00_TASKLET_INIT | ||
846 | |||
827 | /* | 847 | /* |
828 | * Register HW. | 848 | * Register HW. |
829 | */ | 849 | */ |
@@ -952,6 +972,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
952 | { | 972 | { |
953 | int retval = -ENOMEM; | 973 | int retval = -ENOMEM; |
954 | 974 | ||
975 | spin_lock_init(&rt2x00dev->irqmask_lock); | ||
955 | mutex_init(&rt2x00dev->csr_mutex); | 976 | mutex_init(&rt2x00dev->csr_mutex); |
956 | 977 | ||
957 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); | 978 | set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); |
@@ -976,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
976 | BIT(NL80211_IFTYPE_WDS); | 997 | BIT(NL80211_IFTYPE_WDS); |
977 | 998 | ||
978 | /* | 999 | /* |
979 | * Initialize configuration work. | 1000 | * Initialize work. |
980 | */ | 1001 | */ |
1002 | rt2x00dev->workqueue = | ||
1003 | alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0); | ||
1004 | if (!rt2x00dev->workqueue) { | ||
1005 | retval = -ENOMEM; | ||
1006 | goto exit; | ||
1007 | } | ||
1008 | |||
981 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 1009 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
982 | 1010 | ||
983 | /* | 1011 | /* |
@@ -1036,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1036 | cancel_work_sync(&rt2x00dev->intf_work); | 1064 | cancel_work_sync(&rt2x00dev->intf_work); |
1037 | cancel_work_sync(&rt2x00dev->rxdone_work); | 1065 | cancel_work_sync(&rt2x00dev->rxdone_work); |
1038 | cancel_work_sync(&rt2x00dev->txdone_work); | 1066 | cancel_work_sync(&rt2x00dev->txdone_work); |
1067 | destroy_workqueue(rt2x00dev->workqueue); | ||
1039 | 1068 | ||
1040 | /* | 1069 | /* |
1041 | * Free the tx status fifo. | 1070 | * Free the tx status fifo. |
@@ -1046,6 +1075,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1046 | * Kill the tx status tasklet. | 1075 | * Kill the tx status tasklet. |
1047 | */ | 1076 | */ |
1048 | tasklet_kill(&rt2x00dev->txstatus_tasklet); | 1077 | tasklet_kill(&rt2x00dev->txstatus_tasklet); |
1078 | tasklet_kill(&rt2x00dev->pretbtt_tasklet); | ||
1079 | tasklet_kill(&rt2x00dev->tbtt_tasklet); | ||
1080 | tasklet_kill(&rt2x00dev->rxdone_tasklet); | ||
1081 | tasklet_kill(&rt2x00dev->autowake_tasklet); | ||
1049 | 1082 | ||
1050 | /* | 1083 | /* |
1051 | * Uninitialize device. | 1084 | * Uninitialize device. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a105c500627b..2d94cbaf5f4a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -157,14 +157,30 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
157 | bool local); | 157 | bool local); |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware | 160 | * rt2x00queue_update_beacon - Send new beacon from mac80211 |
161 | * to hardware. Handles locking by itself (mutex). | ||
161 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 162 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
162 | * @vif: Interface for which the beacon should be updated. | 163 | * @vif: Interface for which the beacon should be updated. |
163 | * @enable_beacon: Enable beaconing | ||
164 | */ | 164 | */ |
165 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | 165 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, |
166 | struct ieee80211_vif *vif, | 166 | struct ieee80211_vif *vif); |
167 | const bool enable_beacon); | 167 | |
168 | /** | ||
169 | * rt2x00queue_update_beacon_locked - Send new beacon from mac80211 | ||
170 | * to hardware. Caller needs to ensure locking. | ||
171 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
172 | * @vif: Interface for which the beacon should be updated. | ||
173 | */ | ||
174 | int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, | ||
175 | struct ieee80211_vif *vif); | ||
176 | |||
177 | /** | ||
178 | * rt2x00queue_clear_beacon - Clear beacon in hardware | ||
179 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
180 | * @vif: Interface for which the beacon should be updated. | ||
181 | */ | ||
182 | int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, | ||
183 | struct ieee80211_vif *vif); | ||
168 | 184 | ||
169 | /** | 185 | /** |
170 | * rt2x00queue_index_inc - Index incrementation function | 186 | * rt2x00queue_index_inc - Index incrementation function |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index bfda60eaf4ef..c975b0a12e95 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -417,7 +417,8 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) | |||
417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) | 417 | !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) |
418 | return; | 418 | return; |
419 | 419 | ||
420 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 420 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
421 | &link->watchdog_work, WATCHDOG_INTERVAL); | ||
421 | } | 422 | } |
422 | 423 | ||
423 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) | 424 | void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) |
@@ -441,7 +442,9 @@ static void rt2x00link_watchdog(struct work_struct *work) | |||
441 | rt2x00dev->ops->lib->watchdog(rt2x00dev); | 442 | rt2x00dev->ops->lib->watchdog(rt2x00dev); |
442 | 443 | ||
443 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 444 | if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
444 | schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); | 445 | ieee80211_queue_delayed_work(rt2x00dev->hw, |
446 | &link->watchdog_work, | ||
447 | WATCHDOG_INTERVAL); | ||
445 | } | 448 | } |
446 | 449 | ||
447 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) | 450 | void rt2x00link_register(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f3da051df39e..6a66021d8f65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -617,11 +617,47 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
617 | bss_conf->bssid); | 617 | bss_conf->bssid); |
618 | 618 | ||
619 | /* | 619 | /* |
620 | * Update the beacon. | 620 | * Update the beacon. This is only required on USB devices. PCI |
621 | * devices fetch beacons periodically. | ||
621 | */ | 622 | */ |
622 | if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) | 623 | if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev)) |
623 | rt2x00queue_update_beacon(rt2x00dev, vif, | 624 | rt2x00queue_update_beacon(rt2x00dev, vif); |
624 | bss_conf->enable_beacon); | 625 | |
626 | /* | ||
627 | * Start/stop beaconing. | ||
628 | */ | ||
629 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
630 | if (!bss_conf->enable_beacon && intf->enable_beacon) { | ||
631 | rt2x00queue_clear_beacon(rt2x00dev, vif); | ||
632 | rt2x00dev->intf_beaconing--; | ||
633 | intf->enable_beacon = false; | ||
634 | |||
635 | if (rt2x00dev->intf_beaconing == 0) { | ||
636 | /* | ||
637 | * Last beaconing interface disabled | ||
638 | * -> stop beacon queue. | ||
639 | */ | ||
640 | mutex_lock(&intf->beacon_skb_mutex); | ||
641 | rt2x00queue_stop_queue(rt2x00dev->bcn); | ||
642 | mutex_unlock(&intf->beacon_skb_mutex); | ||
643 | } | ||
644 | |||
645 | |||
646 | } else if (bss_conf->enable_beacon && !intf->enable_beacon) { | ||
647 | rt2x00dev->intf_beaconing++; | ||
648 | intf->enable_beacon = true; | ||
649 | |||
650 | if (rt2x00dev->intf_beaconing == 1) { | ||
651 | /* | ||
652 | * First beaconing interface enabled | ||
653 | * -> start beacon queue. | ||
654 | */ | ||
655 | mutex_lock(&intf->beacon_skb_mutex); | ||
656 | rt2x00queue_start_queue(rt2x00dev->bcn); | ||
657 | mutex_unlock(&intf->beacon_skb_mutex); | ||
658 | } | ||
659 | } | ||
660 | } | ||
625 | 661 | ||
626 | /* | 662 | /* |
627 | * When the association status has changed we must reset the link | 663 | * When the association status has changed we must reset the link |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index ace0b668c04e..4dd82b0b0520 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -160,10 +160,9 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) | |||
160 | /* | 160 | /* |
161 | * Register interrupt handler. | 161 | * Register interrupt handler. |
162 | */ | 162 | */ |
163 | status = request_threaded_irq(rt2x00dev->irq, | 163 | status = request_irq(rt2x00dev->irq, |
164 | rt2x00dev->ops->lib->irq_handler, | 164 | rt2x00dev->ops->lib->irq_handler, |
165 | rt2x00dev->ops->lib->irq_handler_thread, | 165 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); |
166 | IRQF_SHARED, rt2x00dev->name, rt2x00dev); | ||
167 | if (status) { | 166 | if (status) { |
168 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", | 167 | ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", |
169 | rt2x00dev->irq, status); | 168 | rt2x00dev->irq, status); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index ca82b3a91697..fa17c83b9685 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -566,13 +566,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, | |||
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
568 | 568 | ||
569 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | 569 | int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, |
570 | struct ieee80211_vif *vif, | 570 | struct ieee80211_vif *vif) |
571 | const bool enable_beacon) | ||
572 | { | 571 | { |
573 | struct rt2x00_intf *intf = vif_to_intf(vif); | 572 | struct rt2x00_intf *intf = vif_to_intf(vif); |
574 | struct skb_frame_desc *skbdesc; | ||
575 | struct txentry_desc txdesc; | ||
576 | 573 | ||
577 | if (unlikely(!intf->beacon)) | 574 | if (unlikely(!intf->beacon)) |
578 | return -ENOBUFS; | 575 | return -ENOBUFS; |
@@ -584,17 +581,36 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
584 | */ | 581 | */ |
585 | rt2x00queue_free_skb(intf->beacon); | 582 | rt2x00queue_free_skb(intf->beacon); |
586 | 583 | ||
587 | if (!enable_beacon) { | 584 | /* |
588 | rt2x00queue_stop_queue(intf->beacon->queue); | 585 | * Clear beacon (single bssid devices don't need to clear the beacon |
589 | mutex_unlock(&intf->beacon_skb_mutex); | 586 | * since the beacon queue will get stopped anyway). |
590 | return 0; | 587 | */ |
591 | } | 588 | if (rt2x00dev->ops->lib->clear_beacon) |
589 | rt2x00dev->ops->lib->clear_beacon(intf->beacon); | ||
590 | |||
591 | mutex_unlock(&intf->beacon_skb_mutex); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, | ||
597 | struct ieee80211_vif *vif) | ||
598 | { | ||
599 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
600 | struct skb_frame_desc *skbdesc; | ||
601 | struct txentry_desc txdesc; | ||
602 | |||
603 | if (unlikely(!intf->beacon)) | ||
604 | return -ENOBUFS; | ||
605 | |||
606 | /* | ||
607 | * Clean up the beacon skb. | ||
608 | */ | ||
609 | rt2x00queue_free_skb(intf->beacon); | ||
592 | 610 | ||
593 | intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); | 611 | intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); |
594 | if (!intf->beacon->skb) { | 612 | if (!intf->beacon->skb) |
595 | mutex_unlock(&intf->beacon_skb_mutex); | ||
596 | return -ENOMEM; | 613 | return -ENOMEM; |
597 | } | ||
598 | 614 | ||
599 | /* | 615 | /* |
600 | * Copy all TX descriptor information into txdesc, | 616 | * Copy all TX descriptor information into txdesc, |
@@ -611,13 +627,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | |||
611 | skbdesc->entry = intf->beacon; | 627 | skbdesc->entry = intf->beacon; |
612 | 628 | ||
613 | /* | 629 | /* |
614 | * Send beacon to hardware and enable beacon genaration.. | 630 | * Send beacon to hardware. |
615 | */ | 631 | */ |
616 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); | 632 | rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); |
617 | 633 | ||
634 | return 0; | ||
635 | |||
636 | } | ||
637 | |||
638 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | ||
639 | struct ieee80211_vif *vif) | ||
640 | { | ||
641 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
642 | int ret; | ||
643 | |||
644 | mutex_lock(&intf->beacon_skb_mutex); | ||
645 | ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif); | ||
618 | mutex_unlock(&intf->beacon_skb_mutex); | 646 | mutex_unlock(&intf->beacon_skb_mutex); |
619 | 647 | ||
620 | return 0; | 648 | return ret; |
621 | } | 649 | } |
622 | 650 | ||
623 | void rt2x00queue_for_each_entry(struct data_queue *queue, | 651 | void rt2x00queue_for_each_entry(struct data_queue *queue, |
@@ -885,7 +913,7 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) | |||
885 | * The queue flush has failed... | 913 | * The queue flush has failed... |
886 | */ | 914 | */ |
887 | if (unlikely(!rt2x00queue_empty(queue))) | 915 | if (unlikely(!rt2x00queue_empty(queue))) |
888 | WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid); | 916 | WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid); |
889 | 917 | ||
890 | /* | 918 | /* |
891 | * Restore the queue to the previous status | 919 | * Restore the queue to the previous status |
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e8259ae48ced..6f867eec49cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h | |||
@@ -85,8 +85,6 @@ enum dev_state { | |||
85 | STATE_RADIO_OFF, | 85 | STATE_RADIO_OFF, |
86 | STATE_RADIO_IRQ_ON, | 86 | STATE_RADIO_IRQ_ON, |
87 | STATE_RADIO_IRQ_OFF, | 87 | STATE_RADIO_IRQ_OFF, |
88 | STATE_RADIO_IRQ_ON_ISR, | ||
89 | STATE_RADIO_IRQ_OFF_ISR, | ||
90 | }; | 88 | }; |
91 | 89 | ||
92 | /* | 90 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 1a9937d5aff6..fbe735f5b352 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -227,7 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) | |||
227 | * Schedule the delayed work for reading the TX status | 227 | * Schedule the delayed work for reading the TX status |
228 | * from the device. | 228 | * from the device. |
229 | */ | 229 | */ |
230 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | 230 | queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); |
231 | } | 231 | } |
232 | 232 | ||
233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 233 | static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -320,7 +320,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
320 | * Schedule the delayed work for reading the RX status | 320 | * Schedule the delayed work for reading the RX status |
321 | * from the device. | 321 | * from the device. |
322 | */ | 322 | */ |
323 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); | 323 | queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); |
324 | } | 324 | } |
325 | 325 | ||
326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) | 326 | static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) |
@@ -429,7 +429,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) | |||
429 | * Schedule the completion handler manually, when this | 429 | * Schedule the completion handler manually, when this |
430 | * worker function runs, it should cleanup the queue. | 430 | * worker function runs, it should cleanup the queue. |
431 | */ | 431 | */ |
432 | ieee80211_queue_work(queue->rt2x00dev->hw, completion); | 432 | queue_work(queue->rt2x00dev->workqueue, completion); |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * Wait for a little while to give the driver | 435 | * Wait for a little while to give the driver |
@@ -453,7 +453,7 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) | |||
453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," | 453 | WARNING(queue->rt2x00dev, "TX queue %d status timed out," |
454 | " invoke forced tx handler\n", queue->qid); | 454 | " invoke forced tx handler\n", queue->qid); |
455 | 455 | ||
456 | ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); | 456 | queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work); |
457 | } | 457 | } |
458 | 458 | ||
459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) | 459 | void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8de44dd401e0..dd2164d4d57b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -551,26 +551,14 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, | |||
551 | struct rt2x00intf_conf *conf, | 551 | struct rt2x00intf_conf *conf, |
552 | const unsigned int flags) | 552 | const unsigned int flags) |
553 | { | 553 | { |
554 | unsigned int beacon_base; | ||
555 | u32 reg; | 554 | u32 reg; |
556 | 555 | ||
557 | if (flags & CONFIG_UPDATE_TYPE) { | 556 | if (flags & CONFIG_UPDATE_TYPE) { |
558 | /* | 557 | /* |
559 | * Clear current synchronisation setup. | ||
560 | * For the Beacon base registers, we only need to clear | ||
561 | * the first byte since that byte contains the VALID and OWNER | ||
562 | * bits which (when set to 0) will invalidate the entire beacon. | ||
563 | */ | ||
564 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
565 | rt2x00pci_register_write(rt2x00dev, beacon_base, 0); | ||
566 | |||
567 | /* | ||
568 | * Enable synchronisation. | 558 | * Enable synchronisation. |
569 | */ | 559 | */ |
570 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 560 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
571 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
572 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 561 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
573 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
574 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 562 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
575 | } | 563 | } |
576 | 564 | ||
@@ -1154,6 +1142,11 @@ static void rt61pci_start_queue(struct data_queue *queue) | |||
1154 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); | 1142 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); |
1155 | break; | 1143 | break; |
1156 | case QID_BEACON: | 1144 | case QID_BEACON: |
1145 | /* | ||
1146 | * Allow the tbtt tasklet to be scheduled. | ||
1147 | */ | ||
1148 | tasklet_enable(&rt2x00dev->tbtt_tasklet); | ||
1149 | |||
1157 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | 1150 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); |
1158 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 1151 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
1159 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | 1152 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
@@ -1233,6 +1226,11 @@ static void rt61pci_stop_queue(struct data_queue *queue) | |||
1233 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1226 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1234 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1227 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1235 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 1228 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
1229 | |||
1230 | /* | ||
1231 | * Wait for possibly running tbtt tasklets. | ||
1232 | */ | ||
1233 | tasklet_disable(&rt2x00dev->tbtt_tasklet); | ||
1236 | break; | 1234 | break; |
1237 | default: | 1235 | default: |
1238 | break; | 1236 | break; |
@@ -1719,9 +1717,9 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1719 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | 1717 | static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, |
1720 | enum dev_state state) | 1718 | enum dev_state state) |
1721 | { | 1719 | { |
1722 | int mask = (state == STATE_RADIO_IRQ_OFF) || | 1720 | int mask = (state == STATE_RADIO_IRQ_OFF); |
1723 | (state == STATE_RADIO_IRQ_OFF_ISR); | ||
1724 | u32 reg; | 1721 | u32 reg; |
1722 | unsigned long flags; | ||
1725 | 1723 | ||
1726 | /* | 1724 | /* |
1727 | * When interrupts are being enabled, the interrupt registers | 1725 | * When interrupts are being enabled, the interrupt registers |
@@ -1733,12 +1731,21 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1733 | 1731 | ||
1734 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); | 1732 | rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); |
1735 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); | 1733 | rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); |
1734 | |||
1735 | /* | ||
1736 | * Enable tasklets. | ||
1737 | */ | ||
1738 | tasklet_enable(&rt2x00dev->txstatus_tasklet); | ||
1739 | tasklet_enable(&rt2x00dev->rxdone_tasklet); | ||
1740 | tasklet_enable(&rt2x00dev->autowake_tasklet); | ||
1736 | } | 1741 | } |
1737 | 1742 | ||
1738 | /* | 1743 | /* |
1739 | * Only toggle the interrupts bits we are going to use. | 1744 | * Only toggle the interrupts bits we are going to use. |
1740 | * Non-checked interrupt bits are disabled by default. | 1745 | * Non-checked interrupt bits are disabled by default. |
1741 | */ | 1746 | */ |
1747 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
1748 | |||
1742 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | 1749 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); |
1743 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); | 1750 | rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); |
1744 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); | 1751 | rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); |
@@ -1758,6 +1765,17 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | |||
1758 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); | 1765 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); |
1759 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); | 1766 | rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); |
1760 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | 1767 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
1768 | |||
1769 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
1770 | |||
1771 | if (state == STATE_RADIO_IRQ_OFF) { | ||
1772 | /* | ||
1773 | * Ensure that all tasklets are finished. | ||
1774 | */ | ||
1775 | tasklet_disable(&rt2x00dev->txstatus_tasklet); | ||
1776 | tasklet_disable(&rt2x00dev->rxdone_tasklet); | ||
1777 | tasklet_disable(&rt2x00dev->autowake_tasklet); | ||
1778 | } | ||
1761 | } | 1779 | } |
1762 | 1780 | ||
1763 | static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) | 1781 | static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1833,9 +1851,7 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1833 | rt61pci_disable_radio(rt2x00dev); | 1851 | rt61pci_disable_radio(rt2x00dev); |
1834 | break; | 1852 | break; |
1835 | case STATE_RADIO_IRQ_ON: | 1853 | case STATE_RADIO_IRQ_ON: |
1836 | case STATE_RADIO_IRQ_ON_ISR: | ||
1837 | case STATE_RADIO_IRQ_OFF: | 1854 | case STATE_RADIO_IRQ_OFF: |
1838 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1839 | rt61pci_toggle_irq(rt2x00dev, state); | 1855 | rt61pci_toggle_irq(rt2x00dev, state); |
1840 | break; | 1856 | break; |
1841 | case STATE_DEEP_SLEEP: | 1857 | case STATE_DEEP_SLEEP: |
@@ -2002,8 +2018,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
2002 | */ | 2018 | */ |
2003 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 2019 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
2004 | 2020 | ||
2005 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
2006 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
2007 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 2021 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
2008 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | 2022 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); |
2009 | 2023 | ||
@@ -2014,6 +2028,32 @@ static void rt61pci_write_beacon(struct queue_entry *entry, | |||
2014 | entry->skb = NULL; | 2028 | entry->skb = NULL; |
2015 | } | 2029 | } |
2016 | 2030 | ||
2031 | static void rt61pci_clear_beacon(struct queue_entry *entry) | ||
2032 | { | ||
2033 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
2034 | u32 reg; | ||
2035 | |||
2036 | /* | ||
2037 | * Disable beaconing while we are reloading the beacon data, | ||
2038 | * otherwise we might be sending out invalid data. | ||
2039 | */ | ||
2040 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
2041 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
2042 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2043 | |||
2044 | /* | ||
2045 | * Clear beacon. | ||
2046 | */ | ||
2047 | rt2x00pci_register_write(rt2x00dev, | ||
2048 | HW_BEACON_OFFSET(entry->entry_idx), 0); | ||
2049 | |||
2050 | /* | ||
2051 | * Enable beaconing again. | ||
2052 | */ | ||
2053 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
2054 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2055 | } | ||
2056 | |||
2017 | /* | 2057 | /* |
2018 | * RX control handlers | 2058 | * RX control handlers |
2019 | */ | 2059 | */ |
@@ -2078,9 +2118,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, | |||
2078 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 2118 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
2079 | 2119 | ||
2080 | /* | 2120 | /* |
2081 | * FIXME: Legacy driver indicates that the frame does | 2121 | * The hardware has already checked the Michael Mic and has |
2082 | * contain the Michael Mic. Unfortunately, in rt2x00 | 2122 | * stripped it from the frame. Signal this to mac80211. |
2083 | * the MIC seems to be missing completely... | ||
2084 | */ | 2123 | */ |
2085 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | 2124 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; |
2086 | 2125 | ||
@@ -2211,61 +2250,80 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | |||
2211 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | 2250 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); |
2212 | } | 2251 | } |
2213 | 2252 | ||
2214 | static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance) | 2253 | static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, |
2254 | struct rt2x00_field32 irq_field) | ||
2215 | { | 2255 | { |
2216 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2256 | unsigned long flags; |
2217 | u32 reg = rt2x00dev->irqvalue[0]; | 2257 | u32 reg; |
2218 | u32 reg_mcu = rt2x00dev->irqvalue[1]; | ||
2219 | 2258 | ||
2220 | /* | 2259 | /* |
2221 | * Handle interrupts, walk through all bits | 2260 | * Enable a single interrupt. The interrupt mask register |
2222 | * and run the tasks, the bits are checked in order of | 2261 | * access needs locking. |
2223 | * priority. | ||
2224 | */ | 2262 | */ |
2263 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
2225 | 2264 | ||
2226 | /* | 2265 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); |
2227 | * 1 - Rx ring done interrupt. | 2266 | rt2x00_set_field32(®, irq_field, 0); |
2228 | */ | 2267 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); |
2229 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) | ||
2230 | rt2x00pci_rxdone(rt2x00dev); | ||
2231 | 2268 | ||
2232 | /* | 2269 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
2233 | * 2 - Tx ring done interrupt. | 2270 | } |
2234 | */ | ||
2235 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) | ||
2236 | rt61pci_txdone(rt2x00dev); | ||
2237 | 2271 | ||
2238 | /* | 2272 | static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev, |
2239 | * 3 - Handle MCU command done. | 2273 | struct rt2x00_field32 irq_field) |
2240 | */ | 2274 | { |
2241 | if (reg_mcu) | 2275 | unsigned long flags; |
2242 | rt2x00pci_register_write(rt2x00dev, | 2276 | u32 reg; |
2243 | M2H_CMD_DONE_CSR, 0xffffffff); | ||
2244 | 2277 | ||
2245 | /* | 2278 | /* |
2246 | * 4 - MCU Autowakeup interrupt. | 2279 | * Enable a single MCU interrupt. The interrupt mask register |
2280 | * access needs locking. | ||
2247 | */ | 2281 | */ |
2248 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) | 2282 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); |
2249 | rt61pci_wakeup(rt2x00dev); | ||
2250 | 2283 | ||
2251 | /* | 2284 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); |
2252 | * 5 - Beacon done interrupt. | 2285 | rt2x00_set_field32(®, irq_field, 0); |
2253 | */ | 2286 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); |
2254 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) | ||
2255 | rt2x00lib_beacondone(rt2x00dev); | ||
2256 | 2287 | ||
2257 | /* Enable interrupts again. */ | 2288 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); |
2258 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 2289 | } |
2259 | STATE_RADIO_IRQ_ON_ISR); | 2290 | |
2260 | return IRQ_HANDLED; | 2291 | static void rt61pci_txstatus_tasklet(unsigned long data) |
2292 | { | ||
2293 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2294 | rt61pci_txdone(rt2x00dev); | ||
2295 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE); | ||
2296 | } | ||
2297 | |||
2298 | static void rt61pci_tbtt_tasklet(unsigned long data) | ||
2299 | { | ||
2300 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2301 | rt2x00lib_beacondone(rt2x00dev); | ||
2302 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE); | ||
2303 | } | ||
2304 | |||
2305 | static void rt61pci_rxdone_tasklet(unsigned long data) | ||
2306 | { | ||
2307 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2308 | rt2x00pci_rxdone(rt2x00dev); | ||
2309 | rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); | ||
2261 | } | 2310 | } |
2262 | 2311 | ||
2312 | static void rt61pci_autowake_tasklet(unsigned long data) | ||
2313 | { | ||
2314 | struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; | ||
2315 | rt61pci_wakeup(rt2x00dev); | ||
2316 | rt2x00pci_register_write(rt2x00dev, | ||
2317 | M2H_CMD_DONE_CSR, 0xffffffff); | ||
2318 | rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); | ||
2319 | } | ||
2263 | 2320 | ||
2264 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2321 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) |
2265 | { | 2322 | { |
2266 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2323 | struct rt2x00_dev *rt2x00dev = dev_instance; |
2267 | u32 reg_mcu; | 2324 | u32 reg_mcu, mask_mcu; |
2268 | u32 reg; | 2325 | u32 reg, mask; |
2326 | unsigned long flags; | ||
2269 | 2327 | ||
2270 | /* | 2328 | /* |
2271 | * Get the interrupt sources & saved to local variable. | 2329 | * Get the interrupt sources & saved to local variable. |
@@ -2283,14 +2341,46 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2283 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | 2341 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
2284 | return IRQ_HANDLED; | 2342 | return IRQ_HANDLED; |
2285 | 2343 | ||
2286 | /* Store irqvalues for use in the interrupt thread. */ | 2344 | /* |
2287 | rt2x00dev->irqvalue[0] = reg; | 2345 | * Schedule tasklets for interrupt handling. |
2288 | rt2x00dev->irqvalue[1] = reg_mcu; | 2346 | */ |
2347 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) | ||
2348 | tasklet_schedule(&rt2x00dev->rxdone_tasklet); | ||
2349 | |||
2350 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) | ||
2351 | tasklet_schedule(&rt2x00dev->txstatus_tasklet); | ||
2289 | 2352 | ||
2290 | /* Disable interrupts, will be enabled again in the interrupt thread. */ | 2353 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) |
2291 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, | 2354 | tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); |
2292 | STATE_RADIO_IRQ_OFF_ISR); | 2355 | |
2293 | return IRQ_WAKE_THREAD; | 2356 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) |
2357 | tasklet_schedule(&rt2x00dev->autowake_tasklet); | ||
2358 | |||
2359 | /* | ||
2360 | * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits | ||
2361 | * for interrupts and interrupt masks we can just use the value of | ||
2362 | * INT_SOURCE_CSR to create the interrupt mask. | ||
2363 | */ | ||
2364 | mask = reg; | ||
2365 | mask_mcu = reg_mcu; | ||
2366 | |||
2367 | /* | ||
2368 | * Disable all interrupts for which a tasklet was scheduled right now, | ||
2369 | * the tasklet will reenable the appropriate interrupts. | ||
2370 | */ | ||
2371 | spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); | ||
2372 | |||
2373 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
2374 | reg |= mask; | ||
2375 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
2376 | |||
2377 | rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); | ||
2378 | reg |= mask_mcu; | ||
2379 | rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); | ||
2380 | |||
2381 | spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); | ||
2382 | |||
2383 | return IRQ_HANDLED; | ||
2294 | } | 2384 | } |
2295 | 2385 | ||
2296 | /* | 2386 | /* |
@@ -2884,7 +2974,10 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2884 | 2974 | ||
2885 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | 2975 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { |
2886 | .irq_handler = rt61pci_interrupt, | 2976 | .irq_handler = rt61pci_interrupt, |
2887 | .irq_handler_thread = rt61pci_interrupt_thread, | 2977 | .txstatus_tasklet = rt61pci_txstatus_tasklet, |
2978 | .tbtt_tasklet = rt61pci_tbtt_tasklet, | ||
2979 | .rxdone_tasklet = rt61pci_rxdone_tasklet, | ||
2980 | .autowake_tasklet = rt61pci_autowake_tasklet, | ||
2888 | .probe_hw = rt61pci_probe_hw, | 2981 | .probe_hw = rt61pci_probe_hw, |
2889 | .get_firmware_name = rt61pci_get_firmware_name, | 2982 | .get_firmware_name = rt61pci_get_firmware_name, |
2890 | .check_firmware = rt61pci_check_firmware, | 2983 | .check_firmware = rt61pci_check_firmware, |
@@ -2903,6 +2996,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2903 | .stop_queue = rt61pci_stop_queue, | 2996 | .stop_queue = rt61pci_stop_queue, |
2904 | .write_tx_desc = rt61pci_write_tx_desc, | 2997 | .write_tx_desc = rt61pci_write_tx_desc, |
2905 | .write_beacon = rt61pci_write_beacon, | 2998 | .write_beacon = rt61pci_write_beacon, |
2999 | .clear_beacon = rt61pci_clear_beacon, | ||
2906 | .fill_rxdone = rt61pci_fill_rxdone, | 3000 | .fill_rxdone = rt61pci_fill_rxdone, |
2907 | .config_shared_key = rt61pci_config_shared_key, | 3001 | .config_shared_key = rt61pci_config_shared_key, |
2908 | .config_pairwise_key = rt61pci_config_pairwise_key, | 3002 | .config_pairwise_key = rt61pci_config_pairwise_key, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 029be3c6c030..5ff72deea8d4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -502,26 +502,14 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
502 | struct rt2x00intf_conf *conf, | 502 | struct rt2x00intf_conf *conf, |
503 | const unsigned int flags) | 503 | const unsigned int flags) |
504 | { | 504 | { |
505 | unsigned int beacon_base; | ||
506 | u32 reg; | 505 | u32 reg; |
507 | 506 | ||
508 | if (flags & CONFIG_UPDATE_TYPE) { | 507 | if (flags & CONFIG_UPDATE_TYPE) { |
509 | /* | 508 | /* |
510 | * Clear current synchronisation setup. | ||
511 | * For the Beacon base registers we only need to clear | ||
512 | * the first byte since that byte contains the VALID and OWNER | ||
513 | * bits which (when set to 0) will invalidate the entire beacon. | ||
514 | */ | ||
515 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
516 | rt2x00usb_register_write(rt2x00dev, beacon_base, 0); | ||
517 | |||
518 | /* | ||
519 | * Enable synchronisation. | 509 | * Enable synchronisation. |
520 | */ | 510 | */ |
521 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 511 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
522 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
523 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 512 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
524 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
525 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 513 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
526 | } | 514 | } |
527 | 515 | ||
@@ -1440,9 +1428,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1440 | rt73usb_disable_radio(rt2x00dev); | 1428 | rt73usb_disable_radio(rt2x00dev); |
1441 | break; | 1429 | break; |
1442 | case STATE_RADIO_IRQ_ON: | 1430 | case STATE_RADIO_IRQ_ON: |
1443 | case STATE_RADIO_IRQ_ON_ISR: | ||
1444 | case STATE_RADIO_IRQ_OFF: | 1431 | case STATE_RADIO_IRQ_OFF: |
1445 | case STATE_RADIO_IRQ_OFF_ISR: | ||
1446 | /* No support, but no error either */ | 1432 | /* No support, but no error either */ |
1447 | break; | 1433 | break; |
1448 | case STATE_DEEP_SLEEP: | 1434 | case STATE_DEEP_SLEEP: |
@@ -1590,8 +1576,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry, | |||
1590 | */ | 1576 | */ |
1591 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 1577 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
1592 | 1578 | ||
1593 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | ||
1594 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | ||
1595 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 1579 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
1596 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1580 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1597 | 1581 | ||
@@ -1602,6 +1586,33 @@ static void rt73usb_write_beacon(struct queue_entry *entry, | |||
1602 | entry->skb = NULL; | 1586 | entry->skb = NULL; |
1603 | } | 1587 | } |
1604 | 1588 | ||
1589 | static void rt73usb_clear_beacon(struct queue_entry *entry) | ||
1590 | { | ||
1591 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1592 | unsigned int beacon_base; | ||
1593 | u32 reg; | ||
1594 | |||
1595 | /* | ||
1596 | * Disable beaconing while we are reloading the beacon data, | ||
1597 | * otherwise we might be sending out invalid data. | ||
1598 | */ | ||
1599 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
1600 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
1601 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1602 | |||
1603 | /* | ||
1604 | * Clear beacon. | ||
1605 | */ | ||
1606 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
1607 | rt2x00usb_register_write(rt2x00dev, beacon_base, 0); | ||
1608 | |||
1609 | /* | ||
1610 | * Enable beaconing again. | ||
1611 | */ | ||
1612 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | ||
1613 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1614 | } | ||
1615 | |||
1605 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) | 1616 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) |
1606 | { | 1617 | { |
1607 | int length; | 1618 | int length; |
@@ -1698,9 +1709,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, | |||
1698 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | 1709 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; |
1699 | 1710 | ||
1700 | /* | 1711 | /* |
1701 | * FIXME: Legacy driver indicates that the frame does | 1712 | * The hardware has already checked the Michael Mic and has |
1702 | * contain the Michael Mic. Unfortunately, in rt2x00 | 1713 | * stripped it from the frame. Signal this to mac80211. |
1703 | * the MIC seems to be missing completely... | ||
1704 | */ | 1714 | */ |
1705 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; | 1715 | rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; |
1706 | 1716 | ||
@@ -2313,6 +2323,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2313 | .flush_queue = rt2x00usb_flush_queue, | 2323 | .flush_queue = rt2x00usb_flush_queue, |
2314 | .write_tx_desc = rt73usb_write_tx_desc, | 2324 | .write_tx_desc = rt73usb_write_tx_desc, |
2315 | .write_beacon = rt73usb_write_beacon, | 2325 | .write_beacon = rt73usb_write_beacon, |
2326 | .clear_beacon = rt73usb_clear_beacon, | ||
2316 | .get_tx_data_len = rt73usb_get_tx_data_len, | 2327 | .get_tx_data_len = rt73usb_get_tx_data_len, |
2317 | .fill_rxdone = rt73usb_fill_rxdone, | 2328 | .fill_rxdone = rt73usb_fill_rxdone, |
2318 | .config_shared_key = rt73usb_config_shared_key, | 2329 | .config_shared_key = rt73usb_config_shared_key, |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index b8433f3a9bc2..62876cd5c41a 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
@@ -726,9 +726,9 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) | |||
726 | } | 726 | } |
727 | 727 | ||
728 | static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | 728 | static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, |
729 | u8 efuse_data, u8 offset, int *bcontinual, | 729 | u8 efuse_data, u8 offset, int *bcontinual, |
730 | u8 *write_state, struct pgpkt_struct target_pkt, | 730 | u8 *write_state, struct pgpkt_struct *target_pkt, |
731 | int *repeat_times, int *bresult, u8 word_en) | 731 | int *repeat_times, int *bresult, u8 word_en) |
732 | { | 732 | { |
733 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 733 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
734 | struct pgpkt_struct tmp_pkt; | 734 | struct pgpkt_struct tmp_pkt; |
@@ -744,8 +744,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
744 | tmp_pkt.word_en = tmp_header & 0x0F; | 744 | tmp_pkt.word_en = tmp_header & 0x0F; |
745 | tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); | 745 | tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); |
746 | 746 | ||
747 | if (tmp_pkt.offset != target_pkt.offset) { | 747 | if (tmp_pkt.offset != target_pkt->offset) { |
748 | efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; | 748 | *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; |
749 | *write_state = PG_STATE_HEADER; | 749 | *write_state = PG_STATE_HEADER; |
750 | } else { | 750 | } else { |
751 | for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { | 751 | for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { |
@@ -756,23 +756,23 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
756 | } | 756 | } |
757 | 757 | ||
758 | if (bdataempty == false) { | 758 | if (bdataempty == false) { |
759 | efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; | 759 | *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; |
760 | *write_state = PG_STATE_HEADER; | 760 | *write_state = PG_STATE_HEADER; |
761 | } else { | 761 | } else { |
762 | match_word_en = 0x0F; | 762 | match_word_en = 0x0F; |
763 | if (!((target_pkt.word_en & BIT(0)) | | 763 | if (!((target_pkt->word_en & BIT(0)) | |
764 | (tmp_pkt.word_en & BIT(0)))) | 764 | (tmp_pkt.word_en & BIT(0)))) |
765 | match_word_en &= (~BIT(0)); | 765 | match_word_en &= (~BIT(0)); |
766 | 766 | ||
767 | if (!((target_pkt.word_en & BIT(1)) | | 767 | if (!((target_pkt->word_en & BIT(1)) | |
768 | (tmp_pkt.word_en & BIT(1)))) | 768 | (tmp_pkt.word_en & BIT(1)))) |
769 | match_word_en &= (~BIT(1)); | 769 | match_word_en &= (~BIT(1)); |
770 | 770 | ||
771 | if (!((target_pkt.word_en & BIT(2)) | | 771 | if (!((target_pkt->word_en & BIT(2)) | |
772 | (tmp_pkt.word_en & BIT(2)))) | 772 | (tmp_pkt.word_en & BIT(2)))) |
773 | match_word_en &= (~BIT(2)); | 773 | match_word_en &= (~BIT(2)); |
774 | 774 | ||
775 | if (!((target_pkt.word_en & BIT(3)) | | 775 | if (!((target_pkt->word_en & BIT(3)) | |
776 | (tmp_pkt.word_en & BIT(3)))) | 776 | (tmp_pkt.word_en & BIT(3)))) |
777 | match_word_en &= (~BIT(3)); | 777 | match_word_en &= (~BIT(3)); |
778 | 778 | ||
@@ -780,7 +780,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
780 | badworden = efuse_word_enable_data_write( | 780 | badworden = efuse_word_enable_data_write( |
781 | hw, *efuse_addr + 1, | 781 | hw, *efuse_addr + 1, |
782 | tmp_pkt.word_en, | 782 | tmp_pkt.word_en, |
783 | target_pkt.data); | 783 | target_pkt->data); |
784 | 784 | ||
785 | if (0x0F != (badworden & 0x0F)) { | 785 | if (0x0F != (badworden & 0x0F)) { |
786 | u8 reorg_offset = offset; | 786 | u8 reorg_offset = offset; |
@@ -791,26 +791,26 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
791 | } | 791 | } |
792 | 792 | ||
793 | tmp_word_en = 0x0F; | 793 | tmp_word_en = 0x0F; |
794 | if ((target_pkt.word_en & BIT(0)) ^ | 794 | if ((target_pkt->word_en & BIT(0)) ^ |
795 | (match_word_en & BIT(0))) | 795 | (match_word_en & BIT(0))) |
796 | tmp_word_en &= (~BIT(0)); | 796 | tmp_word_en &= (~BIT(0)); |
797 | 797 | ||
798 | if ((target_pkt.word_en & BIT(1)) ^ | 798 | if ((target_pkt->word_en & BIT(1)) ^ |
799 | (match_word_en & BIT(1))) | 799 | (match_word_en & BIT(1))) |
800 | tmp_word_en &= (~BIT(1)); | 800 | tmp_word_en &= (~BIT(1)); |
801 | 801 | ||
802 | if ((target_pkt.word_en & BIT(2)) ^ | 802 | if ((target_pkt->word_en & BIT(2)) ^ |
803 | (match_word_en & BIT(2))) | 803 | (match_word_en & BIT(2))) |
804 | tmp_word_en &= (~BIT(2)); | 804 | tmp_word_en &= (~BIT(2)); |
805 | 805 | ||
806 | if ((target_pkt.word_en & BIT(3)) ^ | 806 | if ((target_pkt->word_en & BIT(3)) ^ |
807 | (match_word_en & BIT(3))) | 807 | (match_word_en & BIT(3))) |
808 | tmp_word_en &= (~BIT(3)); | 808 | tmp_word_en &= (~BIT(3)); |
809 | 809 | ||
810 | if ((tmp_word_en & 0x0F) != 0x0F) { | 810 | if ((tmp_word_en & 0x0F) != 0x0F) { |
811 | *efuse_addr = efuse_get_current_size(hw); | 811 | *efuse_addr = efuse_get_current_size(hw); |
812 | target_pkt.offset = offset; | 812 | target_pkt->offset = offset; |
813 | target_pkt.word_en = tmp_word_en; | 813 | target_pkt->word_en = tmp_word_en; |
814 | } else | 814 | } else |
815 | *bcontinual = false; | 815 | *bcontinual = false; |
816 | *write_state = PG_STATE_HEADER; | 816 | *write_state = PG_STATE_HEADER; |
@@ -821,8 +821,8 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
821 | } | 821 | } |
822 | } else { | 822 | } else { |
823 | *efuse_addr += (2 * tmp_word_cnts) + 1; | 823 | *efuse_addr += (2 * tmp_word_cnts) + 1; |
824 | target_pkt.offset = offset; | 824 | target_pkt->offset = offset; |
825 | target_pkt.word_en = word_en; | 825 | target_pkt->word_en = word_en; |
826 | *write_state = PG_STATE_HEADER; | 826 | *write_state = PG_STATE_HEADER; |
827 | } | 827 | } |
828 | } | 828 | } |
@@ -938,7 +938,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
938 | efuse_write_data_case1(hw, &efuse_addr, | 938 | efuse_write_data_case1(hw, &efuse_addr, |
939 | efuse_data, offset, | 939 | efuse_data, offset, |
940 | &bcontinual, | 940 | &bcontinual, |
941 | &write_state, target_pkt, | 941 | &write_state, &target_pkt, |
942 | &repeat_times, &bresult, | 942 | &repeat_times, &bresult, |
943 | word_en); | 943 | word_en); |
944 | else | 944 | else |
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index cc4068d2b4a8..afdc601aa7ea 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -751,10 +751,10 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
751 | return 0; | 751 | return 0; |
752 | } | 752 | } |
753 | 753 | ||
754 | int wl1271_acx_rate_policies(struct wl1271 *wl) | 754 | int wl1271_acx_sta_rate_policies(struct wl1271 *wl) |
755 | { | 755 | { |
756 | struct acx_rate_policy *acx; | 756 | struct acx_sta_rate_policy *acx; |
757 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | 757 | struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; |
758 | int idx = 0; | 758 | int idx = 0; |
759 | int ret = 0; | 759 | int ret = 0; |
760 | 760 | ||
@@ -794,6 +794,38 @@ out: | |||
794 | return ret; | 794 | return ret; |
795 | } | 795 | } |
796 | 796 | ||
797 | int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, | ||
798 | u8 idx) | ||
799 | { | ||
800 | struct acx_ap_rate_policy *acx; | ||
801 | int ret = 0; | ||
802 | |||
803 | wl1271_debug(DEBUG_ACX, "acx ap rate policy"); | ||
804 | |||
805 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
806 | if (!acx) { | ||
807 | ret = -ENOMEM; | ||
808 | goto out; | ||
809 | } | ||
810 | |||
811 | acx->rate_policy.enabled_rates = cpu_to_le32(c->enabled_rates); | ||
812 | acx->rate_policy.short_retry_limit = c->short_retry_limit; | ||
813 | acx->rate_policy.long_retry_limit = c->long_retry_limit; | ||
814 | acx->rate_policy.aflags = c->aflags; | ||
815 | |||
816 | acx->rate_policy_idx = cpu_to_le32(idx); | ||
817 | |||
818 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | ||
819 | if (ret < 0) { | ||
820 | wl1271_warning("Setting of ap rate policy failed: %d", ret); | ||
821 | goto out; | ||
822 | } | ||
823 | |||
824 | out: | ||
825 | kfree(acx); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
797 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, | 829 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
798 | u8 aifsn, u16 txop) | 830 | u8 aifsn, u16 txop) |
799 | { | 831 | { |
@@ -1233,6 +1265,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, | |||
1233 | struct wl1271_acx_ht_capabilities *acx; | 1265 | struct wl1271_acx_ht_capabilities *acx; |
1234 | u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 1266 | u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
1235 | int ret = 0; | 1267 | int ret = 0; |
1268 | u32 ht_capabilites = 0; | ||
1236 | 1269 | ||
1237 | wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); | 1270 | wl1271_debug(DEBUG_ACX, "acx ht capabilities setting"); |
1238 | 1271 | ||
@@ -1244,16 +1277,16 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, | |||
1244 | 1277 | ||
1245 | /* Allow HT Operation ? */ | 1278 | /* Allow HT Operation ? */ |
1246 | if (allow_ht_operation) { | 1279 | if (allow_ht_operation) { |
1247 | acx->ht_capabilites = | 1280 | ht_capabilites = |
1248 | WL1271_ACX_FW_CAP_HT_OPERATION; | 1281 | WL1271_ACX_FW_CAP_HT_OPERATION; |
1249 | if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) | 1282 | if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD) |
1250 | acx->ht_capabilites |= | 1283 | ht_capabilites |= |
1251 | WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; | 1284 | WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT; |
1252 | if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) | 1285 | if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) |
1253 | acx->ht_capabilites |= | 1286 | ht_capabilites |= |
1254 | WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; | 1287 | WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS; |
1255 | if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) | 1288 | if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT) |
1256 | acx->ht_capabilites |= | 1289 | ht_capabilites |= |
1257 | WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; | 1290 | WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION; |
1258 | 1291 | ||
1259 | /* get data from A-MPDU parameters field */ | 1292 | /* get data from A-MPDU parameters field */ |
@@ -1261,10 +1294,10 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, | |||
1261 | acx->ampdu_min_spacing = ht_cap->ampdu_density; | 1294 | acx->ampdu_min_spacing = ht_cap->ampdu_density; |
1262 | 1295 | ||
1263 | memcpy(acx->mac_address, mac_address, ETH_ALEN); | 1296 | memcpy(acx->mac_address, mac_address, ETH_ALEN); |
1264 | } else { /* HT operations are not allowed */ | ||
1265 | acx->ht_capabilites = 0; | ||
1266 | } | 1297 | } |
1267 | 1298 | ||
1299 | acx->ht_capabilites = cpu_to_le32(ht_capabilites); | ||
1300 | |||
1268 | ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); | 1301 | ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx)); |
1269 | if (ret < 0) { | 1302 | if (ret < 0) { |
1270 | wl1271_warning("acx ht capabilities setting failed: %d", ret); | 1303 | wl1271_warning("acx ht capabilities setting failed: %d", ret); |
@@ -1309,6 +1342,91 @@ out: | |||
1309 | return ret; | 1342 | return ret; |
1310 | } | 1343 | } |
1311 | 1344 | ||
1345 | /* Configure BA session initiator/receiver parameters setting in the FW. */ | ||
1346 | int wl1271_acx_set_ba_session(struct wl1271 *wl, | ||
1347 | enum ieee80211_back_parties direction, | ||
1348 | u8 tid_index, u8 policy) | ||
1349 | { | ||
1350 | struct wl1271_acx_ba_session_policy *acx; | ||
1351 | int ret; | ||
1352 | |||
1353 | wl1271_debug(DEBUG_ACX, "acx ba session setting"); | ||
1354 | |||
1355 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1356 | if (!acx) { | ||
1357 | ret = -ENOMEM; | ||
1358 | goto out; | ||
1359 | } | ||
1360 | |||
1361 | /* ANY role */ | ||
1362 | acx->role_id = 0xff; | ||
1363 | acx->tid = tid_index; | ||
1364 | acx->enable = policy; | ||
1365 | acx->ba_direction = direction; | ||
1366 | |||
1367 | switch (direction) { | ||
1368 | case WLAN_BACK_INITIATOR: | ||
1369 | acx->win_size = wl->conf.ht.tx_ba_win_size; | ||
1370 | acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; | ||
1371 | break; | ||
1372 | case WLAN_BACK_RECIPIENT: | ||
1373 | acx->win_size = RX_BA_WIN_SIZE; | ||
1374 | acx->inactivity_timeout = 0; | ||
1375 | break; | ||
1376 | default: | ||
1377 | wl1271_error("Incorrect acx command id=%x\n", direction); | ||
1378 | ret = -EINVAL; | ||
1379 | goto out; | ||
1380 | } | ||
1381 | |||
1382 | ret = wl1271_cmd_configure(wl, | ||
1383 | ACX_BA_SESSION_POLICY_CFG, | ||
1384 | acx, | ||
1385 | sizeof(*acx)); | ||
1386 | if (ret < 0) { | ||
1387 | wl1271_warning("acx ba session setting failed: %d", ret); | ||
1388 | goto out; | ||
1389 | } | ||
1390 | |||
1391 | out: | ||
1392 | kfree(acx); | ||
1393 | return ret; | ||
1394 | } | ||
1395 | |||
1396 | /* setup BA session receiver setting in the FW. */ | ||
1397 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, | ||
1398 | bool enable) | ||
1399 | { | ||
1400 | struct wl1271_acx_ba_receiver_setup *acx; | ||
1401 | int ret; | ||
1402 | |||
1403 | wl1271_debug(DEBUG_ACX, "acx ba receiver session setting"); | ||
1404 | |||
1405 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1406 | if (!acx) { | ||
1407 | ret = -ENOMEM; | ||
1408 | goto out; | ||
1409 | } | ||
1410 | |||
1411 | /* Single link for now */ | ||
1412 | acx->link_id = 1; | ||
1413 | acx->tid = tid_index; | ||
1414 | acx->enable = enable; | ||
1415 | acx->win_size = 0; | ||
1416 | acx->ssn = ssn; | ||
1417 | |||
1418 | ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx, | ||
1419 | sizeof(*acx)); | ||
1420 | if (ret < 0) { | ||
1421 | wl1271_warning("acx ba receiver session failed: %d", ret); | ||
1422 | goto out; | ||
1423 | } | ||
1424 | |||
1425 | out: | ||
1426 | kfree(acx); | ||
1427 | return ret; | ||
1428 | } | ||
1429 | |||
1312 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) | 1430 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) |
1313 | { | 1431 | { |
1314 | struct wl1271_acx_fw_tsf_information *tsf_info; | 1432 | struct wl1271_acx_fw_tsf_information *tsf_info; |
@@ -1334,3 +1452,27 @@ out: | |||
1334 | kfree(tsf_info); | 1452 | kfree(tsf_info); |
1335 | return ret; | 1453 | return ret; |
1336 | } | 1454 | } |
1455 | |||
1456 | int wl1271_acx_max_tx_retry(struct wl1271 *wl) | ||
1457 | { | ||
1458 | struct wl1271_acx_max_tx_retry *acx = NULL; | ||
1459 | int ret; | ||
1460 | |||
1461 | wl1271_debug(DEBUG_ACX, "acx max tx retry"); | ||
1462 | |||
1463 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1464 | if (!acx) | ||
1465 | return -ENOMEM; | ||
1466 | |||
1467 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); | ||
1468 | |||
1469 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); | ||
1470 | if (ret < 0) { | ||
1471 | wl1271_warning("acx max tx retry failed: %d", ret); | ||
1472 | goto out; | ||
1473 | } | ||
1474 | |||
1475 | out: | ||
1476 | kfree(acx); | ||
1477 | return ret; | ||
1478 | } | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 7bd8e4db4a71..4bbaf04f434e 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -747,13 +747,23 @@ struct acx_rate_class { | |||
747 | #define ACX_TX_BASIC_RATE 0 | 747 | #define ACX_TX_BASIC_RATE 0 |
748 | #define ACX_TX_AP_FULL_RATE 1 | 748 | #define ACX_TX_AP_FULL_RATE 1 |
749 | #define ACX_TX_RATE_POLICY_CNT 2 | 749 | #define ACX_TX_RATE_POLICY_CNT 2 |
750 | struct acx_rate_policy { | 750 | struct acx_sta_rate_policy { |
751 | struct acx_header header; | 751 | struct acx_header header; |
752 | 752 | ||
753 | __le32 rate_class_cnt; | 753 | __le32 rate_class_cnt; |
754 | struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; | 754 | struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; |
755 | } __packed; | 755 | } __packed; |
756 | 756 | ||
757 | |||
758 | #define ACX_TX_AP_MODE_MGMT_RATE 4 | ||
759 | #define ACX_TX_AP_MODE_BCST_RATE 5 | ||
760 | struct acx_ap_rate_policy { | ||
761 | struct acx_header header; | ||
762 | |||
763 | __le32 rate_policy_idx; | ||
764 | struct acx_rate_class rate_policy; | ||
765 | } __packed; | ||
766 | |||
757 | struct acx_ac_cfg { | 767 | struct acx_ac_cfg { |
758 | struct acx_header header; | 768 | struct acx_header header; |
759 | u8 ac; | 769 | u8 ac; |
@@ -1051,6 +1061,59 @@ struct wl1271_acx_ht_information { | |||
1051 | u8 padding[3]; | 1061 | u8 padding[3]; |
1052 | } __packed; | 1062 | } __packed; |
1053 | 1063 | ||
1064 | #define RX_BA_WIN_SIZE 8 | ||
1065 | |||
1066 | struct wl1271_acx_ba_session_policy { | ||
1067 | struct acx_header header; | ||
1068 | /* | ||
1069 | * Specifies role Id, Range 0-7, 0xFF means ANY role. | ||
1070 | * Future use. For now this field is irrelevant | ||
1071 | */ | ||
1072 | u8 role_id; | ||
1073 | /* | ||
1074 | * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id. | ||
1075 | * Not applicable if Role Id is set to ANY. | ||
1076 | */ | ||
1077 | u8 link_id; | ||
1078 | |||
1079 | u8 tid; | ||
1080 | |||
1081 | u8 enable; | ||
1082 | |||
1083 | /* Windows size in number of packets */ | ||
1084 | u16 win_size; | ||
1085 | |||
1086 | /* | ||
1087 | * As initiator inactivity timeout in time units(TU) of 1024us. | ||
1088 | * As receiver reserved | ||
1089 | */ | ||
1090 | u16 inactivity_timeout; | ||
1091 | |||
1092 | /* Initiator = 1/Receiver = 0 */ | ||
1093 | u8 ba_direction; | ||
1094 | |||
1095 | u8 padding[3]; | ||
1096 | } __packed; | ||
1097 | |||
1098 | struct wl1271_acx_ba_receiver_setup { | ||
1099 | struct acx_header header; | ||
1100 | |||
1101 | /* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id */ | ||
1102 | u8 link_id; | ||
1103 | |||
1104 | u8 tid; | ||
1105 | |||
1106 | u8 enable; | ||
1107 | |||
1108 | u8 padding[1]; | ||
1109 | |||
1110 | /* Windows size in number of packets */ | ||
1111 | u16 win_size; | ||
1112 | |||
1113 | /* BA session starting sequence number. RANGE 0-FFF */ | ||
1114 | u16 ssn; | ||
1115 | } __packed; | ||
1116 | |||
1054 | struct wl1271_acx_fw_tsf_information { | 1117 | struct wl1271_acx_fw_tsf_information { |
1055 | struct acx_header header; | 1118 | struct acx_header header; |
1056 | 1119 | ||
@@ -1062,6 +1125,17 @@ struct wl1271_acx_fw_tsf_information { | |||
1062 | u8 padding[3]; | 1125 | u8 padding[3]; |
1063 | } __packed; | 1126 | } __packed; |
1064 | 1127 | ||
1128 | struct wl1271_acx_max_tx_retry { | ||
1129 | struct acx_header header; | ||
1130 | |||
1131 | /* | ||
1132 | * the number of frames transmission failures before | ||
1133 | * issuing the aging event. | ||
1134 | */ | ||
1135 | __le16 max_tx_retry; | ||
1136 | u8 padding_1[2]; | ||
1137 | } __packed; | ||
1138 | |||
1065 | enum { | 1139 | enum { |
1066 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1140 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
1067 | ACX_MEM_CFG = 0x0003, | 1141 | ACX_MEM_CFG = 0x0003, |
@@ -1113,12 +1187,13 @@ enum { | |||
1113 | ACX_RSSI_SNR_WEIGHTS = 0x0052, | 1187 | ACX_RSSI_SNR_WEIGHTS = 0x0052, |
1114 | ACX_KEEP_ALIVE_MODE = 0x0053, | 1188 | ACX_KEEP_ALIVE_MODE = 0x0053, |
1115 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1189 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
1116 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 1190 | ACX_BA_SESSION_POLICY_CFG = 0x0055, |
1117 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 1191 | ACX_BA_SESSION_RX_SETUP = 0x0056, |
1118 | ACX_PEER_HT_CAP = 0x0057, | 1192 | ACX_PEER_HT_CAP = 0x0057, |
1119 | ACX_HT_BSS_OPERATION = 0x0058, | 1193 | ACX_HT_BSS_OPERATION = 0x0058, |
1120 | ACX_COEX_ACTIVITY = 0x0059, | 1194 | ACX_COEX_ACTIVITY = 0x0059, |
1121 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, | 1195 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1196 | ACX_MAX_TX_FAILURE = 0x0072, | ||
1122 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1197 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1123 | DOT11_CUR_TX_PWR = 0x100D, | 1198 | DOT11_CUR_TX_PWR = 0x100D, |
1124 | DOT11_RX_DOT11_MODE = 0x1012, | 1199 | DOT11_RX_DOT11_MODE = 0x1012, |
@@ -1160,7 +1235,9 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | |||
1160 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1235 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1161 | enum acx_ctsprotect_type ctsprotect); | 1236 | enum acx_ctsprotect_type ctsprotect); |
1162 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1237 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1163 | int wl1271_acx_rate_policies(struct wl1271 *wl); | 1238 | int wl1271_acx_sta_rate_policies(struct wl1271 *wl); |
1239 | int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, | ||
1240 | u8 idx); | ||
1164 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, | 1241 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
1165 | u8 aifsn, u16 txop); | 1242 | u8 aifsn, u16 txop); |
1166 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, | 1243 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
@@ -1185,6 +1262,12 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, | |||
1185 | bool allow_ht_operation); | 1262 | bool allow_ht_operation); |
1186 | int wl1271_acx_set_ht_information(struct wl1271 *wl, | 1263 | int wl1271_acx_set_ht_information(struct wl1271 *wl, |
1187 | u16 ht_operation_mode); | 1264 | u16 ht_operation_mode); |
1265 | int wl1271_acx_set_ba_session(struct wl1271 *wl, | ||
1266 | enum ieee80211_back_parties direction, | ||
1267 | u8 tid_index, u8 policy); | ||
1268 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, | ||
1269 | bool enable); | ||
1188 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1270 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1271 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); | ||
1189 | 1272 | ||
1190 | #endif /* __WL1271_ACX_H__ */ | 1273 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 4df04f84d7f1..1ffbad67d2d8 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "boot.h" | 28 | #include "boot.h" |
29 | #include "io.h" | 29 | #include "io.h" |
30 | #include "event.h" | 30 | #include "event.h" |
31 | #include "rx.h" | ||
31 | 32 | ||
32 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | 33 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { |
33 | [PART_DOWN] = { | 34 | [PART_DOWN] = { |
@@ -100,6 +101,22 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
100 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 101 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
101 | } | 102 | } |
102 | 103 | ||
104 | static void wl1271_parse_fw_ver(struct wl1271 *wl) | ||
105 | { | ||
106 | int ret; | ||
107 | |||
108 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", | ||
109 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], | ||
110 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], | ||
111 | &wl->chip.fw_ver[4]); | ||
112 | |||
113 | if (ret != 5) { | ||
114 | wl1271_warning("fw version incorrect value"); | ||
115 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); | ||
116 | return; | ||
117 | } | ||
118 | } | ||
119 | |||
103 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 120 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
104 | { | 121 | { |
105 | struct wl1271_static_data static_data; | 122 | struct wl1271_static_data static_data; |
@@ -107,11 +124,13 @@ static void wl1271_boot_fw_version(struct wl1271 *wl) | |||
107 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), | 124 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), |
108 | false); | 125 | false); |
109 | 126 | ||
110 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 127 | strncpy(wl->chip.fw_ver_str, static_data.fw_version, |
111 | sizeof(wl->chip.fw_ver)); | 128 | sizeof(wl->chip.fw_ver_str)); |
112 | 129 | ||
113 | /* make sure the string is NULL-terminated */ | 130 | /* make sure the string is NULL-terminated */ |
114 | wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0'; | 131 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; |
132 | |||
133 | wl1271_parse_fw_ver(wl); | ||
115 | } | 134 | } |
116 | 135 | ||
117 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | 136 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, |
@@ -231,7 +250,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
231 | */ | 250 | */ |
232 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || | 251 | if (wl->nvs_len == sizeof(struct wl1271_nvs_file) || |
233 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { | 252 | wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) { |
234 | if (wl->nvs->general_params.dual_mode_select) | 253 | /* for now 11a is unsupported in AP mode */ |
254 | if (wl->bss_type != BSS_TYPE_AP_BSS && | ||
255 | wl->nvs->general_params.dual_mode_select) | ||
235 | wl->enable_11a = true; | 256 | wl->enable_11a = true; |
236 | } | 257 | } |
237 | 258 | ||
@@ -431,6 +452,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
431 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | 452 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | |
432 | SOFT_GEMINI_SENSE_EVENT_ID; | 453 | SOFT_GEMINI_SENSE_EVENT_ID; |
433 | 454 | ||
455 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
456 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; | ||
457 | |||
434 | ret = wl1271_event_unmask(wl); | 458 | ret = wl1271_event_unmask(wl); |
435 | if (ret < 0) { | 459 | if (ret < 0) { |
436 | wl1271_error("EVENT mask setting failed"); | 460 | wl1271_error("EVENT mask setting failed"); |
@@ -595,8 +619,7 @@ int wl1271_boot(struct wl1271 *wl) | |||
595 | wl1271_boot_enable_interrupts(wl); | 619 | wl1271_boot_enable_interrupts(wl); |
596 | 620 | ||
597 | /* set the wl1271 default filters */ | 621 | /* set the wl1271 default filters */ |
598 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 622 | wl1271_set_default_filters(wl); |
599 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | ||
600 | 623 | ||
601 | wl1271_event_mbox_config(wl); | 624 | wl1271_event_mbox_config(wl); |
602 | 625 | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 0106628aa5a2..1bb8be5e805b 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
37 | #include "cmd.h" | 37 | #include "cmd.h" |
38 | #include "event.h" | 38 | #include "event.h" |
39 | #include "tx.h" | ||
39 | 40 | ||
40 | #define WL1271_CMD_FAST_POLL_COUNT 50 | 41 | #define WL1271_CMD_FAST_POLL_COUNT 50 |
41 | 42 | ||
@@ -221,7 +222,7 @@ int wl1271_cmd_ext_radio_parms(struct wl1271 *wl) | |||
221 | * Poll the mailbox event field until any of the bits in the mask is set or a | 222 | * Poll the mailbox event field until any of the bits in the mask is set or a |
222 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 223 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
223 | */ | 224 | */ |
224 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | 225 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) |
225 | { | 226 | { |
226 | u32 events_vector, event; | 227 | u32 events_vector, event; |
227 | unsigned long timeout; | 228 | unsigned long timeout; |
@@ -230,7 +231,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
230 | 231 | ||
231 | do { | 232 | do { |
232 | if (time_after(jiffies, timeout)) { | 233 | if (time_after(jiffies, timeout)) { |
233 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 234 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", |
235 | (int)mask); | ||
234 | return -ETIMEDOUT; | 236 | return -ETIMEDOUT; |
235 | } | 237 | } |
236 | 238 | ||
@@ -248,6 +250,19 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
248 | return 0; | 250 | return 0; |
249 | } | 251 | } |
250 | 252 | ||
253 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
254 | { | ||
255 | int ret; | ||
256 | |||
257 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); | ||
258 | if (ret != 0) { | ||
259 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
251 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | 266 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) |
252 | { | 267 | { |
253 | struct wl1271_cmd_join *join; | 268 | struct wl1271_cmd_join *join; |
@@ -490,8 +505,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
490 | cmd->len = cpu_to_le16(buf_len); | 505 | cmd->len = cpu_to_le16(buf_len); |
491 | cmd->template_type = template_id; | 506 | cmd->template_type = template_id; |
492 | cmd->enabled_rates = cpu_to_le32(rates); | 507 | cmd->enabled_rates = cpu_to_le32(rates); |
493 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; | 508 | cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit; |
494 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; | 509 | cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit; |
495 | cmd->index = index; | 510 | cmd->index = index; |
496 | 511 | ||
497 | if (buf) | 512 | if (buf) |
@@ -659,15 +674,15 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) | |||
659 | 674 | ||
660 | /* llc layer */ | 675 | /* llc layer */ |
661 | memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); | 676 | memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); |
662 | tmpl.llc_type = htons(ETH_P_ARP); | 677 | tmpl.llc_type = cpu_to_be16(ETH_P_ARP); |
663 | 678 | ||
664 | /* arp header */ | 679 | /* arp header */ |
665 | arp_hdr = &tmpl.arp_hdr; | 680 | arp_hdr = &tmpl.arp_hdr; |
666 | arp_hdr->ar_hrd = htons(ARPHRD_ETHER); | 681 | arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); |
667 | arp_hdr->ar_pro = htons(ETH_P_IP); | 682 | arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); |
668 | arp_hdr->ar_hln = ETH_ALEN; | 683 | arp_hdr->ar_hln = ETH_ALEN; |
669 | arp_hdr->ar_pln = 4; | 684 | arp_hdr->ar_pln = 4; |
670 | arp_hdr->ar_op = htons(ARPOP_REPLY); | 685 | arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); |
671 | 686 | ||
672 | /* arp payload */ | 687 | /* arp payload */ |
673 | memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); | 688 | memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); |
@@ -702,9 +717,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
702 | wl->basic_rate); | 717 | wl->basic_rate); |
703 | } | 718 | } |
704 | 719 | ||
705 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 720 | int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) |
706 | { | 721 | { |
707 | struct wl1271_cmd_set_keys *cmd; | 722 | struct wl1271_cmd_set_sta_keys *cmd; |
708 | int ret = 0; | 723 | int ret = 0; |
709 | 724 | ||
710 | wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); | 725 | wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); |
@@ -731,11 +746,42 @@ out: | |||
731 | return ret; | 746 | return ret; |
732 | } | 747 | } |
733 | 748 | ||
734 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 749 | int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) |
750 | { | ||
751 | struct wl1271_cmd_set_ap_keys *cmd; | ||
752 | int ret = 0; | ||
753 | |||
754 | wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id); | ||
755 | |||
756 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
757 | if (!cmd) { | ||
758 | ret = -ENOMEM; | ||
759 | goto out; | ||
760 | } | ||
761 | |||
762 | cmd->hlid = WL1271_AP_BROADCAST_HLID; | ||
763 | cmd->key_id = id; | ||
764 | cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; | ||
765 | cmd->key_action = cpu_to_le16(KEY_SET_ID); | ||
766 | cmd->key_type = KEY_WEP; | ||
767 | |||
768 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | ||
769 | if (ret < 0) { | ||
770 | wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret); | ||
771 | goto out; | ||
772 | } | ||
773 | |||
774 | out: | ||
775 | kfree(cmd); | ||
776 | |||
777 | return ret; | ||
778 | } | ||
779 | |||
780 | int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | ||
735 | u8 key_size, const u8 *key, const u8 *addr, | 781 | u8 key_size, const u8 *key, const u8 *addr, |
736 | u32 tx_seq_32, u16 tx_seq_16) | 782 | u32 tx_seq_32, u16 tx_seq_16) |
737 | { | 783 | { |
738 | struct wl1271_cmd_set_keys *cmd; | 784 | struct wl1271_cmd_set_sta_keys *cmd; |
739 | int ret = 0; | 785 | int ret = 0; |
740 | 786 | ||
741 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 787 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -788,6 +834,67 @@ out: | |||
788 | return ret; | 834 | return ret; |
789 | } | 835 | } |
790 | 836 | ||
837 | int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | ||
838 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | ||
839 | u16 tx_seq_16) | ||
840 | { | ||
841 | struct wl1271_cmd_set_ap_keys *cmd; | ||
842 | int ret = 0; | ||
843 | u8 lid_type; | ||
844 | |||
845 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
846 | if (!cmd) | ||
847 | return -ENOMEM; | ||
848 | |||
849 | if (hlid == WL1271_AP_BROADCAST_HLID) { | ||
850 | if (key_type == KEY_WEP) | ||
851 | lid_type = WEP_DEFAULT_LID_TYPE; | ||
852 | else | ||
853 | lid_type = BROADCAST_LID_TYPE; | ||
854 | } else { | ||
855 | lid_type = UNICAST_LID_TYPE; | ||
856 | } | ||
857 | |||
858 | wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d" | ||
859 | " hlid: %d", (int)action, (int)id, (int)lid_type, | ||
860 | (int)key_type, (int)hlid); | ||
861 | |||
862 | cmd->lid_key_type = lid_type; | ||
863 | cmd->hlid = hlid; | ||
864 | cmd->key_action = cpu_to_le16(action); | ||
865 | cmd->key_size = key_size; | ||
866 | cmd->key_type = key_type; | ||
867 | cmd->key_id = id; | ||
868 | cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); | ||
869 | cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); | ||
870 | |||
871 | if (key_type == KEY_TKIP) { | ||
872 | /* | ||
873 | * We get the key in the following form: | ||
874 | * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) | ||
875 | * but the target is expecting: | ||
876 | * TKIP - RX MIC - TX MIC | ||
877 | */ | ||
878 | memcpy(cmd->key, key, 16); | ||
879 | memcpy(cmd->key + 16, key + 24, 8); | ||
880 | memcpy(cmd->key + 24, key + 16, 8); | ||
881 | } else { | ||
882 | memcpy(cmd->key, key, key_size); | ||
883 | } | ||
884 | |||
885 | wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd)); | ||
886 | |||
887 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | ||
888 | if (ret < 0) { | ||
889 | wl1271_warning("could not set ap keys"); | ||
890 | goto out; | ||
891 | } | ||
892 | |||
893 | out: | ||
894 | kfree(cmd); | ||
895 | return ret; | ||
896 | } | ||
897 | |||
791 | int wl1271_cmd_disconnect(struct wl1271 *wl) | 898 | int wl1271_cmd_disconnect(struct wl1271 *wl) |
792 | { | 899 | { |
793 | struct wl1271_cmd_disconnect *cmd; | 900 | struct wl1271_cmd_disconnect *cmd; |
@@ -850,3 +957,180 @@ out_free: | |||
850 | out: | 957 | out: |
851 | return ret; | 958 | return ret; |
852 | } | 959 | } |
960 | |||
961 | int wl1271_cmd_start_bss(struct wl1271 *wl) | ||
962 | { | ||
963 | struct wl1271_cmd_bss_start *cmd; | ||
964 | struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; | ||
965 | int ret; | ||
966 | |||
967 | wl1271_debug(DEBUG_CMD, "cmd start bss"); | ||
968 | |||
969 | /* | ||
970 | * FIXME: We currently do not support hidden SSID. The real SSID | ||
971 | * should be fetched from mac80211 first. | ||
972 | */ | ||
973 | if (wl->ssid_len == 0) { | ||
974 | wl1271_warning("Hidden SSID currently not supported for AP"); | ||
975 | ret = -EINVAL; | ||
976 | goto out; | ||
977 | } | ||
978 | |||
979 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
980 | if (!cmd) { | ||
981 | ret = -ENOMEM; | ||
982 | goto out; | ||
983 | } | ||
984 | |||
985 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); | ||
986 | |||
987 | cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); | ||
988 | cmd->bss_index = WL1271_AP_BSS_INDEX; | ||
989 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; | ||
990 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; | ||
991 | cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set); | ||
992 | cmd->beacon_interval = cpu_to_le16(wl->beacon_int); | ||
993 | cmd->dtim_interval = bss_conf->dtim_period; | ||
994 | cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | ||
995 | cmd->channel = wl->channel; | ||
996 | cmd->ssid_len = wl->ssid_len; | ||
997 | cmd->ssid_type = SSID_TYPE_PUBLIC; | ||
998 | memcpy(cmd->ssid, wl->ssid, wl->ssid_len); | ||
999 | |||
1000 | switch (wl->band) { | ||
1001 | case IEEE80211_BAND_2GHZ: | ||
1002 | cmd->band = RADIO_BAND_2_4GHZ; | ||
1003 | break; | ||
1004 | case IEEE80211_BAND_5GHZ: | ||
1005 | cmd->band = RADIO_BAND_5GHZ; | ||
1006 | break; | ||
1007 | default: | ||
1008 | wl1271_warning("bss start - unknown band: %d", (int)wl->band); | ||
1009 | cmd->band = RADIO_BAND_2_4GHZ; | ||
1010 | break; | ||
1011 | } | ||
1012 | |||
1013 | ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0); | ||
1014 | if (ret < 0) { | ||
1015 | wl1271_error("failed to initiate cmd start bss"); | ||
1016 | goto out_free; | ||
1017 | } | ||
1018 | |||
1019 | out_free: | ||
1020 | kfree(cmd); | ||
1021 | |||
1022 | out: | ||
1023 | return ret; | ||
1024 | } | ||
1025 | |||
1026 | int wl1271_cmd_stop_bss(struct wl1271 *wl) | ||
1027 | { | ||
1028 | struct wl1271_cmd_bss_start *cmd; | ||
1029 | int ret; | ||
1030 | |||
1031 | wl1271_debug(DEBUG_CMD, "cmd stop bss"); | ||
1032 | |||
1033 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1034 | if (!cmd) { | ||
1035 | ret = -ENOMEM; | ||
1036 | goto out; | ||
1037 | } | ||
1038 | |||
1039 | cmd->bss_index = WL1271_AP_BSS_INDEX; | ||
1040 | |||
1041 | ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0); | ||
1042 | if (ret < 0) { | ||
1043 | wl1271_error("failed to initiate cmd stop bss"); | ||
1044 | goto out_free; | ||
1045 | } | ||
1046 | |||
1047 | out_free: | ||
1048 | kfree(cmd); | ||
1049 | |||
1050 | out: | ||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | ||
1055 | { | ||
1056 | struct wl1271_cmd_add_sta *cmd; | ||
1057 | int ret; | ||
1058 | |||
1059 | wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid); | ||
1060 | |||
1061 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1062 | if (!cmd) { | ||
1063 | ret = -ENOMEM; | ||
1064 | goto out; | ||
1065 | } | ||
1066 | |||
1067 | /* currently we don't support UAPSD */ | ||
1068 | cmd->sp_len = 0; | ||
1069 | |||
1070 | memcpy(cmd->addr, sta->addr, ETH_ALEN); | ||
1071 | cmd->bss_index = WL1271_AP_BSS_INDEX; | ||
1072 | cmd->aid = sta->aid; | ||
1073 | cmd->hlid = hlid; | ||
1074 | |||
1075 | /* | ||
1076 | * FIXME: Does STA support QOS? We need to propagate this info from | ||
1077 | * hostapd. Currently not that important since this is only used for | ||
1078 | * sending the correct flavor of null-data packet in response to a | ||
1079 | * trigger. | ||
1080 | */ | ||
1081 | cmd->wmm = 0; | ||
1082 | |||
1083 | cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, | ||
1084 | sta->supp_rates[wl->band])); | ||
1085 | |||
1086 | wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); | ||
1087 | |||
1088 | ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); | ||
1089 | if (ret < 0) { | ||
1090 | wl1271_error("failed to initiate cmd add sta"); | ||
1091 | goto out_free; | ||
1092 | } | ||
1093 | |||
1094 | out_free: | ||
1095 | kfree(cmd); | ||
1096 | |||
1097 | out: | ||
1098 | return ret; | ||
1099 | } | ||
1100 | |||
1101 | int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) | ||
1102 | { | ||
1103 | struct wl1271_cmd_remove_sta *cmd; | ||
1104 | int ret; | ||
1105 | |||
1106 | wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); | ||
1107 | |||
1108 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1109 | if (!cmd) { | ||
1110 | ret = -ENOMEM; | ||
1111 | goto out; | ||
1112 | } | ||
1113 | |||
1114 | cmd->hlid = hlid; | ||
1115 | /* We never send a deauth, mac80211 is in charge of this */ | ||
1116 | cmd->reason_opcode = 0; | ||
1117 | cmd->send_deauth_flag = 0; | ||
1118 | |||
1119 | ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); | ||
1120 | if (ret < 0) { | ||
1121 | wl1271_error("failed to initiate cmd remove sta"); | ||
1122 | goto out_free; | ||
1123 | } | ||
1124 | |||
1125 | /* | ||
1126 | * We are ok with a timeout here. The event is sometimes not sent | ||
1127 | * due to a firmware bug. | ||
1128 | */ | ||
1129 | wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); | ||
1130 | |||
1131 | out_free: | ||
1132 | kfree(cmd); | ||
1133 | |||
1134 | out: | ||
1135 | return ret; | ||
1136 | } | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 2a1d9db7ceb8..751281414006 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h | |||
@@ -54,12 +54,20 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | |||
54 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); | 54 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); |
55 | int wl1271_build_qos_null_data(struct wl1271 *wl); | 55 | int wl1271_build_qos_null_data(struct wl1271 *wl); |
56 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | 56 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); |
57 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 57 | int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id); |
58 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 58 | int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id); |
59 | u8 key_size, const u8 *key, const u8 *addr, | 59 | int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
60 | u32 tx_seq_32, u16 tx_seq_16); | 60 | u8 key_size, const u8 *key, const u8 *addr, |
61 | u32 tx_seq_32, u16 tx_seq_16); | ||
62 | int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | ||
63 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | ||
64 | u16 tx_seq_16); | ||
61 | int wl1271_cmd_disconnect(struct wl1271 *wl); | 65 | int wl1271_cmd_disconnect(struct wl1271 *wl); |
62 | int wl1271_cmd_set_sta_state(struct wl1271 *wl); | 66 | int wl1271_cmd_set_sta_state(struct wl1271 *wl); |
67 | int wl1271_cmd_start_bss(struct wl1271 *wl); | ||
68 | int wl1271_cmd_stop_bss(struct wl1271 *wl); | ||
69 | int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); | ||
70 | int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid); | ||
63 | 71 | ||
64 | enum wl1271_commands { | 72 | enum wl1271_commands { |
65 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 73 | CMD_INTERROGATE = 1, /*use this to read information elements*/ |
@@ -98,6 +106,12 @@ enum wl1271_commands { | |||
98 | CMD_STOP_PERIODIC_SCAN = 51, | 106 | CMD_STOP_PERIODIC_SCAN = 51, |
99 | CMD_SET_STA_STATE = 52, | 107 | CMD_SET_STA_STATE = 52, |
100 | 108 | ||
109 | /* AP mode commands */ | ||
110 | CMD_BSS_START = 60, | ||
111 | CMD_BSS_STOP = 61, | ||
112 | CMD_ADD_STA = 62, | ||
113 | CMD_REMOVE_STA = 63, | ||
114 | |||
101 | NUM_COMMANDS, | 115 | NUM_COMMANDS, |
102 | MAX_COMMAND_ID = 0xFFFF, | 116 | MAX_COMMAND_ID = 0xFFFF, |
103 | }; | 117 | }; |
@@ -126,6 +140,13 @@ enum cmd_templ { | |||
126 | * For CTS-to-self (FastCTS) mechanism | 140 | * For CTS-to-self (FastCTS) mechanism |
127 | * for BT/WLAN coexistence (SoftGemini). */ | 141 | * for BT/WLAN coexistence (SoftGemini). */ |
128 | CMD_TEMPL_ARP_RSP, | 142 | CMD_TEMPL_ARP_RSP, |
143 | |||
144 | /* AP-mode specific */ | ||
145 | CMD_TEMPL_AP_BEACON = 13, | ||
146 | CMD_TEMPL_AP_PROBE_RESPONSE, | ||
147 | CMD_TEMPL_AP_ARP_RSP, | ||
148 | CMD_TEMPL_DEAUTH_AP, | ||
149 | |||
129 | CMD_TEMPL_MAX = 0xff | 150 | CMD_TEMPL_MAX = 0xff |
130 | }; | 151 | }; |
131 | 152 | ||
@@ -270,7 +291,6 @@ struct wl1271_cmd_ps_params { | |||
270 | 291 | ||
271 | /* HW encryption keys */ | 292 | /* HW encryption keys */ |
272 | #define NUM_ACCESS_CATEGORIES_COPY 4 | 293 | #define NUM_ACCESS_CATEGORIES_COPY 4 |
273 | #define MAX_KEY_SIZE 32 | ||
274 | 294 | ||
275 | enum wl1271_cmd_key_action { | 295 | enum wl1271_cmd_key_action { |
276 | KEY_ADD_OR_REPLACE = 1, | 296 | KEY_ADD_OR_REPLACE = 1, |
@@ -289,7 +309,7 @@ enum wl1271_cmd_key_type { | |||
289 | 309 | ||
290 | /* FIXME: Add description for key-types */ | 310 | /* FIXME: Add description for key-types */ |
291 | 311 | ||
292 | struct wl1271_cmd_set_keys { | 312 | struct wl1271_cmd_set_sta_keys { |
293 | struct wl1271_cmd_header header; | 313 | struct wl1271_cmd_header header; |
294 | 314 | ||
295 | /* Ignored for default WEP key */ | 315 | /* Ignored for default WEP key */ |
@@ -318,6 +338,57 @@ struct wl1271_cmd_set_keys { | |||
318 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | 338 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; |
319 | } __packed; | 339 | } __packed; |
320 | 340 | ||
341 | enum wl1271_cmd_lid_key_type { | ||
342 | UNICAST_LID_TYPE = 0, | ||
343 | BROADCAST_LID_TYPE = 1, | ||
344 | WEP_DEFAULT_LID_TYPE = 2 | ||
345 | }; | ||
346 | |||
347 | struct wl1271_cmd_set_ap_keys { | ||
348 | struct wl1271_cmd_header header; | ||
349 | |||
350 | /* | ||
351 | * Indicates whether the HLID is a unicast key set | ||
352 | * or broadcast key set. A special value 0xFF is | ||
353 | * used to indicate that the HLID is on WEP-default | ||
354 | * (multi-hlids). of type wl1271_cmd_lid_key_type. | ||
355 | */ | ||
356 | u8 hlid; | ||
357 | |||
358 | /* | ||
359 | * In WEP-default network (hlid == 0xFF) used to | ||
360 | * indicate which network STA/IBSS/AP role should be | ||
361 | * changed | ||
362 | */ | ||
363 | u8 lid_key_type; | ||
364 | |||
365 | /* | ||
366 | * Key ID - For TKIP and AES key types, this field | ||
367 | * indicates the value that should be inserted into | ||
368 | * the KeyID field of frames transmitted using this | ||
369 | * key entry. For broadcast keys the index use as a | ||
370 | * marker for TX/RX key. | ||
371 | * For WEP default network (HLID=0xFF), this field | ||
372 | * indicates the ID of the key to add or remove. | ||
373 | */ | ||
374 | u8 key_id; | ||
375 | u8 reserved_1; | ||
376 | |||
377 | /* key_action_e */ | ||
378 | __le16 key_action; | ||
379 | |||
380 | /* key size in bytes */ | ||
381 | u8 key_size; | ||
382 | |||
383 | /* key_type_e */ | ||
384 | u8 key_type; | ||
385 | |||
386 | /* This field holds the security key data to add to the STA table */ | ||
387 | u8 key[MAX_KEY_SIZE]; | ||
388 | __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; | ||
389 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | ||
390 | } __packed; | ||
391 | |||
321 | struct wl1271_cmd_test_header { | 392 | struct wl1271_cmd_test_header { |
322 | u8 id; | 393 | u8 id; |
323 | u8 padding[3]; | 394 | u8 padding[3]; |
@@ -412,4 +483,68 @@ struct wl1271_cmd_set_sta_state { | |||
412 | u8 padding[3]; | 483 | u8 padding[3]; |
413 | } __packed; | 484 | } __packed; |
414 | 485 | ||
486 | enum wl1271_ssid_type { | ||
487 | SSID_TYPE_PUBLIC = 0, | ||
488 | SSID_TYPE_HIDDEN = 1 | ||
489 | }; | ||
490 | |||
491 | struct wl1271_cmd_bss_start { | ||
492 | struct wl1271_cmd_header header; | ||
493 | |||
494 | /* wl1271_ssid_type */ | ||
495 | u8 ssid_type; | ||
496 | u8 ssid_len; | ||
497 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
498 | u8 padding_1[2]; | ||
499 | |||
500 | /* Basic rate set */ | ||
501 | __le32 basic_rate_set; | ||
502 | /* Aging period in seconds*/ | ||
503 | __le16 aging_period; | ||
504 | |||
505 | /* | ||
506 | * This field specifies the time between target beacon | ||
507 | * transmission times (TBTTs), in time units (TUs). | ||
508 | * Valid values are 1 to 1024. | ||
509 | */ | ||
510 | __le16 beacon_interval; | ||
511 | u8 bssid[ETH_ALEN]; | ||
512 | u8 bss_index; | ||
513 | /* Radio band */ | ||
514 | u8 band; | ||
515 | u8 channel; | ||
516 | /* The host link id for the AP's global queue */ | ||
517 | u8 global_hlid; | ||
518 | /* The host link id for the AP's broadcast queue */ | ||
519 | u8 broadcast_hlid; | ||
520 | /* DTIM count */ | ||
521 | u8 dtim_interval; | ||
522 | /* Beacon expiry time in ms */ | ||
523 | u8 beacon_expiry; | ||
524 | u8 padding_2[3]; | ||
525 | } __packed; | ||
526 | |||
527 | struct wl1271_cmd_add_sta { | ||
528 | struct wl1271_cmd_header header; | ||
529 | |||
530 | u8 addr[ETH_ALEN]; | ||
531 | u8 hlid; | ||
532 | u8 aid; | ||
533 | u8 psd_type[NUM_ACCESS_CATEGORIES_COPY]; | ||
534 | __le32 supported_rates; | ||
535 | u8 bss_index; | ||
536 | u8 sp_len; | ||
537 | u8 wmm; | ||
538 | u8 padding1; | ||
539 | } __packed; | ||
540 | |||
541 | struct wl1271_cmd_remove_sta { | ||
542 | struct wl1271_cmd_header header; | ||
543 | |||
544 | u8 hlid; | ||
545 | u8 reason_opcode; | ||
546 | u8 send_deauth_flag; | ||
547 | u8 padding1; | ||
548 | } __packed; | ||
549 | |||
415 | #endif /* __WL1271_CMD_H__ */ | 550 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index a16b3616e430..fd1dac9ab4db 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -496,6 +496,26 @@ struct conf_rx_settings { | |||
496 | CONF_HW_BIT_RATE_2MBPS) | 496 | CONF_HW_BIT_RATE_2MBPS) |
497 | #define CONF_TX_RATE_RETRY_LIMIT 10 | 497 | #define CONF_TX_RATE_RETRY_LIMIT 10 |
498 | 498 | ||
499 | /* | ||
500 | * Rates supported for data packets when operating as AP. Note the absense | ||
501 | * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop | ||
502 | * one. The rate dropped is not mandatory under any operating mode. | ||
503 | */ | ||
504 | #define CONF_TX_AP_ENABLED_RATES (CONF_HW_BIT_RATE_1MBPS | \ | ||
505 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ | ||
506 | CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS | \ | ||
507 | CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS | \ | ||
508 | CONF_HW_BIT_RATE_18MBPS | CONF_HW_BIT_RATE_24MBPS | \ | ||
509 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ | ||
510 | CONF_HW_BIT_RATE_54MBPS) | ||
511 | |||
512 | /* | ||
513 | * Default rates for management traffic when operating in AP mode. This | ||
514 | * should be configured according to the basic rate set of the AP | ||
515 | */ | ||
516 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | ||
517 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) | ||
518 | |||
499 | struct conf_tx_rate_class { | 519 | struct conf_tx_rate_class { |
500 | 520 | ||
501 | /* | 521 | /* |
@@ -636,9 +656,9 @@ struct conf_tx_settings { | |||
636 | 656 | ||
637 | /* | 657 | /* |
638 | * Configuration for rate classes for TX (currently only one | 658 | * Configuration for rate classes for TX (currently only one |
639 | * rate class supported.) | 659 | * rate class supported). Used in non-AP mode. |
640 | */ | 660 | */ |
641 | struct conf_tx_rate_class rc_conf; | 661 | struct conf_tx_rate_class sta_rc_conf; |
642 | 662 | ||
643 | /* | 663 | /* |
644 | * Configuration for access categories for TX rate control. | 664 | * Configuration for access categories for TX rate control. |
@@ -647,6 +667,28 @@ struct conf_tx_settings { | |||
647 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; | 667 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; |
648 | 668 | ||
649 | /* | 669 | /* |
670 | * Configuration for rate classes in AP-mode. These rate classes | ||
671 | * are for the AC TX queues | ||
672 | */ | ||
673 | struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT]; | ||
674 | |||
675 | /* | ||
676 | * Management TX rate class for AP-mode. | ||
677 | */ | ||
678 | struct conf_tx_rate_class ap_mgmt_conf; | ||
679 | |||
680 | /* | ||
681 | * Broadcast TX rate class for AP-mode. | ||
682 | */ | ||
683 | struct conf_tx_rate_class ap_bcst_conf; | ||
684 | |||
685 | /* | ||
686 | * AP-mode - allow this number of TX retries to a station before an | ||
687 | * event is triggered from FW. | ||
688 | */ | ||
689 | u16 ap_max_tx_retries; | ||
690 | |||
691 | /* | ||
650 | * Configuration for TID parameters. | 692 | * Configuration for TID parameters. |
651 | */ | 693 | */ |
652 | u8 tid_conf_count; | 694 | u8 tid_conf_count; |
@@ -687,6 +729,12 @@ struct conf_tx_settings { | |||
687 | * Range: CONF_HW_BIT_RATE_* bit mask | 729 | * Range: CONF_HW_BIT_RATE_* bit mask |
688 | */ | 730 | */ |
689 | u32 basic_rate_5; | 731 | u32 basic_rate_5; |
732 | |||
733 | /* | ||
734 | * TX retry limits for templates | ||
735 | */ | ||
736 | u8 tmpl_short_retry_limit; | ||
737 | u8 tmpl_long_retry_limit; | ||
690 | }; | 738 | }; |
691 | 739 | ||
692 | enum { | 740 | enum { |
@@ -1036,30 +1084,30 @@ struct conf_scan_settings { | |||
1036 | /* | 1084 | /* |
1037 | * The minimum time to wait on each channel for active scans | 1085 | * The minimum time to wait on each channel for active scans |
1038 | * | 1086 | * |
1039 | * Range: 0 - 65536 tu | 1087 | * Range: u32 tu/1000 |
1040 | */ | 1088 | */ |
1041 | u16 min_dwell_time_active; | 1089 | u32 min_dwell_time_active; |
1042 | 1090 | ||
1043 | /* | 1091 | /* |
1044 | * The maximum time to wait on each channel for active scans | 1092 | * The maximum time to wait on each channel for active scans |
1045 | * | 1093 | * |
1046 | * Range: 0 - 65536 tu | 1094 | * Range: u32 tu/1000 |
1047 | */ | 1095 | */ |
1048 | u16 max_dwell_time_active; | 1096 | u32 max_dwell_time_active; |
1049 | 1097 | ||
1050 | /* | 1098 | /* |
1051 | * The maximum time to wait on each channel for passive scans | 1099 | * The minimum time to wait on each channel for passive scans |
1052 | * | 1100 | * |
1053 | * Range: 0 - 65536 tu | 1101 | * Range: u32 tu/1000 |
1054 | */ | 1102 | */ |
1055 | u16 min_dwell_time_passive; | 1103 | u32 min_dwell_time_passive; |
1056 | 1104 | ||
1057 | /* | 1105 | /* |
1058 | * The maximum time to wait on each channel for passive scans | 1106 | * The maximum time to wait on each channel for passive scans |
1059 | * | 1107 | * |
1060 | * Range: 0 - 65536 tu | 1108 | * Range: u32 tu/1000 |
1061 | */ | 1109 | */ |
1062 | u16 max_dwell_time_passive; | 1110 | u32 max_dwell_time_passive; |
1063 | 1111 | ||
1064 | /* | 1112 | /* |
1065 | * Number of probe requests to transmit on each active scan channel | 1113 | * Number of probe requests to transmit on each active scan channel |
@@ -1090,6 +1138,11 @@ struct conf_rf_settings { | |||
1090 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | 1138 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; |
1091 | }; | 1139 | }; |
1092 | 1140 | ||
1141 | struct conf_ht_setting { | ||
1142 | u16 tx_ba_win_size; | ||
1143 | u16 inactivity_timeout; | ||
1144 | }; | ||
1145 | |||
1093 | struct conf_drv_settings { | 1146 | struct conf_drv_settings { |
1094 | struct conf_sg_settings sg; | 1147 | struct conf_sg_settings sg; |
1095 | struct conf_rx_settings rx; | 1148 | struct conf_rx_settings rx; |
@@ -1100,6 +1153,7 @@ struct conf_drv_settings { | |||
1100 | struct conf_roam_trigger_settings roam_trigger; | 1153 | struct conf_roam_trigger_settings roam_trigger; |
1101 | struct conf_scan_settings scan; | 1154 | struct conf_scan_settings scan; |
1102 | struct conf_rf_settings rf; | 1155 | struct conf_rf_settings rf; |
1156 | struct conf_ht_setting ht; | ||
1103 | }; | 1157 | }; |
1104 | 1158 | ||
1105 | #endif | 1159 | #endif |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index ec6077760157..bebfa28a171a 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -261,27 +261,25 @@ static ssize_t gpio_power_write(struct file *file, | |||
261 | unsigned long value; | 261 | unsigned long value; |
262 | int ret; | 262 | int ret; |
263 | 263 | ||
264 | mutex_lock(&wl->mutex); | ||
265 | |||
266 | len = min(count, sizeof(buf) - 1); | 264 | len = min(count, sizeof(buf) - 1); |
267 | if (copy_from_user(buf, user_buf, len)) { | 265 | if (copy_from_user(buf, user_buf, len)) { |
268 | ret = -EFAULT; | 266 | return -EFAULT; |
269 | goto out; | ||
270 | } | 267 | } |
271 | buf[len] = '\0'; | 268 | buf[len] = '\0'; |
272 | 269 | ||
273 | ret = strict_strtoul(buf, 0, &value); | 270 | ret = strict_strtoul(buf, 0, &value); |
274 | if (ret < 0) { | 271 | if (ret < 0) { |
275 | wl1271_warning("illegal value in gpio_power"); | 272 | wl1271_warning("illegal value in gpio_power"); |
276 | goto out; | 273 | return -EINVAL; |
277 | } | 274 | } |
278 | 275 | ||
276 | mutex_lock(&wl->mutex); | ||
277 | |||
279 | if (value) | 278 | if (value) |
280 | wl1271_power_on(wl); | 279 | wl1271_power_on(wl); |
281 | else | 280 | else |
282 | wl1271_power_off(wl); | 281 | wl1271_power_off(wl); |
283 | 282 | ||
284 | out: | ||
285 | mutex_unlock(&wl->mutex); | 283 | mutex_unlock(&wl->mutex); |
286 | return count; | 284 | return count; |
287 | } | 285 | } |
@@ -293,12 +291,13 @@ static const struct file_operations gpio_power_ops = { | |||
293 | .llseek = default_llseek, | 291 | .llseek = default_llseek, |
294 | }; | 292 | }; |
295 | 293 | ||
296 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 294 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
295 | struct dentry *rootdir) | ||
297 | { | 296 | { |
298 | int ret = 0; | 297 | int ret = 0; |
299 | struct dentry *entry, *stats; | 298 | struct dentry *entry, *stats; |
300 | 299 | ||
301 | stats = debugfs_create_dir("fw-statistics", wl->rootdir); | 300 | stats = debugfs_create_dir("fw-statistics", rootdir); |
302 | if (!stats || IS_ERR(stats)) { | 301 | if (!stats || IS_ERR(stats)) { |
303 | entry = stats; | 302 | entry = stats; |
304 | goto err; | 303 | goto err; |
@@ -395,16 +394,11 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
395 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); | 394 | DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); |
396 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | 395 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); |
397 | 396 | ||
398 | DEBUGFS_ADD(tx_queue_len, wl->rootdir); | 397 | DEBUGFS_ADD(tx_queue_len, rootdir); |
399 | DEBUGFS_ADD(retry_count, wl->rootdir); | 398 | DEBUGFS_ADD(retry_count, rootdir); |
400 | DEBUGFS_ADD(excessive_retries, wl->rootdir); | 399 | DEBUGFS_ADD(excessive_retries, rootdir); |
401 | |||
402 | DEBUGFS_ADD(gpio_power, wl->rootdir); | ||
403 | 400 | ||
404 | entry = debugfs_create_x32("debug_level", 0600, wl->rootdir, | 401 | DEBUGFS_ADD(gpio_power, rootdir); |
405 | &wl12xx_debug_level); | ||
406 | if (!entry || IS_ERR(entry)) | ||
407 | goto err; | ||
408 | 402 | ||
409 | return 0; | 403 | return 0; |
410 | 404 | ||
@@ -419,7 +413,7 @@ err: | |||
419 | 413 | ||
420 | void wl1271_debugfs_reset(struct wl1271 *wl) | 414 | void wl1271_debugfs_reset(struct wl1271 *wl) |
421 | { | 415 | { |
422 | if (!wl->rootdir) | 416 | if (!wl->stats.fw_stats) |
423 | return; | 417 | return; |
424 | 418 | ||
425 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); | 419 | memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); |
@@ -430,13 +424,13 @@ void wl1271_debugfs_reset(struct wl1271 *wl) | |||
430 | int wl1271_debugfs_init(struct wl1271 *wl) | 424 | int wl1271_debugfs_init(struct wl1271 *wl) |
431 | { | 425 | { |
432 | int ret; | 426 | int ret; |
427 | struct dentry *rootdir; | ||
433 | 428 | ||
434 | wl->rootdir = debugfs_create_dir(KBUILD_MODNAME, | 429 | rootdir = debugfs_create_dir(KBUILD_MODNAME, |
435 | wl->hw->wiphy->debugfsdir); | 430 | wl->hw->wiphy->debugfsdir); |
436 | 431 | ||
437 | if (IS_ERR(wl->rootdir)) { | 432 | if (IS_ERR(rootdir)) { |
438 | ret = PTR_ERR(wl->rootdir); | 433 | ret = PTR_ERR(rootdir); |
439 | wl->rootdir = NULL; | ||
440 | goto err; | 434 | goto err; |
441 | } | 435 | } |
442 | 436 | ||
@@ -450,7 +444,7 @@ int wl1271_debugfs_init(struct wl1271 *wl) | |||
450 | 444 | ||
451 | wl->stats.fw_stats_update = jiffies; | 445 | wl->stats.fw_stats_update = jiffies; |
452 | 446 | ||
453 | ret = wl1271_debugfs_add_files(wl); | 447 | ret = wl1271_debugfs_add_files(wl, rootdir); |
454 | 448 | ||
455 | if (ret < 0) | 449 | if (ret < 0) |
456 | goto err_file; | 450 | goto err_file; |
@@ -462,8 +456,7 @@ err_file: | |||
462 | wl->stats.fw_stats = NULL; | 456 | wl->stats.fw_stats = NULL; |
463 | 457 | ||
464 | err_fw: | 458 | err_fw: |
465 | debugfs_remove_recursive(wl->rootdir); | 459 | debugfs_remove_recursive(rootdir); |
466 | wl->rootdir = NULL; | ||
467 | 460 | ||
468 | err: | 461 | err: |
469 | return ret; | 462 | return ret; |
@@ -473,8 +466,4 @@ void wl1271_debugfs_exit(struct wl1271 *wl) | |||
473 | { | 466 | { |
474 | kfree(wl->stats.fw_stats); | 467 | kfree(wl->stats.fw_stats); |
475 | wl->stats.fw_stats = NULL; | 468 | wl->stats.fw_stats = NULL; |
476 | |||
477 | debugfs_remove_recursive(wl->rootdir); | ||
478 | wl->rootdir = NULL; | ||
479 | |||
480 | } | 469 | } |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index f9146f5242fb..3376a5de09d7 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -186,6 +186,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
186 | int ret; | 186 | int ret; |
187 | u32 vector; | 187 | u32 vector; |
188 | bool beacon_loss = false; | 188 | bool beacon_loss = false; |
189 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
189 | 190 | ||
190 | wl1271_event_mbox_dump(mbox); | 191 | wl1271_event_mbox_dump(mbox); |
191 | 192 | ||
@@ -218,21 +219,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
218 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | 219 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. |
219 | * | 220 | * |
220 | */ | 221 | */ |
221 | if (vector & BSS_LOSE_EVENT_ID) { | 222 | if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { |
222 | wl1271_info("Beacon loss detected."); | 223 | wl1271_info("Beacon loss detected."); |
223 | 224 | ||
224 | /* indicate to the stack, that beacons have been lost */ | 225 | /* indicate to the stack, that beacons have been lost */ |
225 | beacon_loss = true; | 226 | beacon_loss = true; |
226 | } | 227 | } |
227 | 228 | ||
228 | if (vector & PS_REPORT_EVENT_ID) { | 229 | if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { |
229 | wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); | 230 | wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); |
230 | ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); | 231 | ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); |
231 | if (ret < 0) | 232 | if (ret < 0) |
232 | return ret; | 233 | return ret; |
233 | } | 234 | } |
234 | 235 | ||
235 | if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) | 236 | if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) |
236 | wl1271_event_pspoll_delivery_fail(wl); | 237 | wl1271_event_pspoll_delivery_fail(wl); |
237 | 238 | ||
238 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 239 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 6cce0143adb5..1d5ef670d480 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h | |||
@@ -59,6 +59,7 @@ enum { | |||
59 | BSS_LOSE_EVENT_ID = BIT(18), | 59 | BSS_LOSE_EVENT_ID = BIT(18), |
60 | REGAINED_BSS_EVENT_ID = BIT(19), | 60 | REGAINED_BSS_EVENT_ID = BIT(19), |
61 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), | 61 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), |
62 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */ | ||
62 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | 63 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), |
63 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), | 64 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), |
64 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | 65 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), |
@@ -115,7 +116,12 @@ struct event_mailbox { | |||
115 | u8 scheduled_scan_status; | 116 | u8 scheduled_scan_status; |
116 | u8 ps_status; | 117 | u8 ps_status; |
117 | 118 | ||
118 | u8 reserved_5[29]; | 119 | /* AP FW only */ |
120 | u8 hlid_removed; | ||
121 | __le16 sta_aging_status; | ||
122 | __le16 sta_tx_retry_exceeded; | ||
123 | |||
124 | u8 reserved_5[24]; | ||
119 | } __packed; | 125 | } __packed; |
120 | 126 | ||
121 | int wl1271_event_unmask(struct wl1271 *wl); | 127 | int wl1271_event_unmask(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index 785a5304bfc4..70b3dc88a219 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -30,27 +30,9 @@ | |||
30 | #include "acx.h" | 30 | #include "acx.h" |
31 | #include "cmd.h" | 31 | #include "cmd.h" |
32 | #include "reg.h" | 32 | #include "reg.h" |
33 | #include "tx.h" | ||
33 | 34 | ||
34 | static int wl1271_init_hwenc_config(struct wl1271 *wl) | 35 | int wl1271_sta_init_templates_config(struct wl1271 *wl) |
35 | { | ||
36 | int ret; | ||
37 | |||
38 | ret = wl1271_acx_feature_cfg(wl); | ||
39 | if (ret < 0) { | ||
40 | wl1271_warning("couldn't set feature config"); | ||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key); | ||
45 | if (ret < 0) { | ||
46 | wl1271_warning("couldn't set default key"); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | ||
54 | { | 36 | { |
55 | int ret, i; | 37 | int ret, i; |
56 | 38 | ||
@@ -118,6 +100,132 @@ int wl1271_init_templates_config(struct wl1271 *wl) | |||
118 | return 0; | 100 | return 0; |
119 | } | 101 | } |
120 | 102 | ||
103 | static int wl1271_ap_init_deauth_template(struct wl1271 *wl) | ||
104 | { | ||
105 | struct wl12xx_disconn_template *tmpl; | ||
106 | int ret; | ||
107 | |||
108 | tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); | ||
109 | if (!tmpl) { | ||
110 | ret = -ENOMEM; | ||
111 | goto out; | ||
112 | } | ||
113 | |||
114 | tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
115 | IEEE80211_STYPE_DEAUTH); | ||
116 | |||
117 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, | ||
118 | tmpl, sizeof(*tmpl), 0, | ||
119 | wl1271_tx_min_rate_get(wl)); | ||
120 | |||
121 | out: | ||
122 | kfree(tmpl); | ||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | static int wl1271_ap_init_null_template(struct wl1271 *wl) | ||
127 | { | ||
128 | struct ieee80211_hdr_3addr *nullfunc; | ||
129 | int ret; | ||
130 | |||
131 | nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL); | ||
132 | if (!nullfunc) { | ||
133 | ret = -ENOMEM; | ||
134 | goto out; | ||
135 | } | ||
136 | |||
137 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
138 | IEEE80211_STYPE_NULLFUNC | | ||
139 | IEEE80211_FCTL_FROMDS); | ||
140 | |||
141 | /* nullfunc->addr1 is filled by FW */ | ||
142 | |||
143 | memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); | ||
144 | memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); | ||
145 | |||
146 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, | ||
147 | sizeof(*nullfunc), 0, | ||
148 | wl1271_tx_min_rate_get(wl)); | ||
149 | |||
150 | out: | ||
151 | kfree(nullfunc); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) | ||
156 | { | ||
157 | struct ieee80211_qos_hdr *qosnull; | ||
158 | int ret; | ||
159 | |||
160 | qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL); | ||
161 | if (!qosnull) { | ||
162 | ret = -ENOMEM; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | ||
167 | IEEE80211_STYPE_QOS_NULLFUNC | | ||
168 | IEEE80211_FCTL_FROMDS); | ||
169 | |||
170 | /* qosnull->addr1 is filled by FW */ | ||
171 | |||
172 | memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); | ||
173 | memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); | ||
174 | |||
175 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, | ||
176 | sizeof(*qosnull), 0, | ||
177 | wl1271_tx_min_rate_get(wl)); | ||
178 | |||
179 | out: | ||
180 | kfree(qosnull); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int wl1271_ap_init_templates_config(struct wl1271 *wl) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | /* | ||
189 | * Put very large empty placeholders for all templates. These | ||
190 | * reserve memory for later. | ||
191 | */ | ||
192 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, | ||
193 | sizeof | ||
194 | (struct wl12xx_probe_resp_template), | ||
195 | 0, WL1271_RATE_AUTOMATIC); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, | ||
200 | sizeof | ||
201 | (struct wl12xx_beacon_template), | ||
202 | 0, WL1271_RATE_AUTOMATIC); | ||
203 | if (ret < 0) | ||
204 | return ret; | ||
205 | |||
206 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, | ||
207 | sizeof | ||
208 | (struct wl12xx_disconn_template), | ||
209 | 0, WL1271_RATE_AUTOMATIC); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | |||
213 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | ||
214 | sizeof(struct wl12xx_null_data_template), | ||
215 | 0, WL1271_RATE_AUTOMATIC); | ||
216 | if (ret < 0) | ||
217 | return ret; | ||
218 | |||
219 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | ||
220 | sizeof | ||
221 | (struct wl12xx_qos_null_data_template), | ||
222 | 0, WL1271_RATE_AUTOMATIC); | ||
223 | if (ret < 0) | ||
224 | return ret; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
121 | static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) | 229 | static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) |
122 | { | 230 | { |
123 | int ret; | 231 | int ret; |
@@ -145,10 +253,6 @@ int wl1271_init_phy_config(struct wl1271 *wl) | |||
145 | if (ret < 0) | 253 | if (ret < 0) |
146 | return ret; | 254 | return ret; |
147 | 255 | ||
148 | ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); | ||
149 | if (ret < 0) | ||
150 | return ret; | ||
151 | |||
152 | ret = wl1271_acx_service_period_timeout(wl); | 256 | ret = wl1271_acx_service_period_timeout(wl); |
153 | if (ret < 0) | 257 | if (ret < 0) |
154 | return ret; | 258 | return ret; |
@@ -213,11 +317,186 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) | |||
213 | return 0; | 317 | return 0; |
214 | } | 318 | } |
215 | 319 | ||
320 | static int wl1271_sta_hw_init(struct wl1271 *wl) | ||
321 | { | ||
322 | int ret; | ||
323 | |||
324 | ret = wl1271_cmd_ext_radio_parms(wl); | ||
325 | if (ret < 0) | ||
326 | return ret; | ||
327 | |||
328 | ret = wl1271_sta_init_templates_config(wl); | ||
329 | if (ret < 0) | ||
330 | return ret; | ||
331 | |||
332 | ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | |||
336 | /* Initialize connection monitoring thresholds */ | ||
337 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
338 | if (ret < 0) | ||
339 | return ret; | ||
340 | |||
341 | /* Beacon filtering */ | ||
342 | ret = wl1271_init_beacon_filter(wl); | ||
343 | if (ret < 0) | ||
344 | return ret; | ||
345 | |||
346 | /* Bluetooth WLAN coexistence */ | ||
347 | ret = wl1271_init_pta(wl); | ||
348 | if (ret < 0) | ||
349 | return ret; | ||
350 | |||
351 | /* Beacons and broadcast settings */ | ||
352 | ret = wl1271_init_beacon_broadcast(wl); | ||
353 | if (ret < 0) | ||
354 | return ret; | ||
355 | |||
356 | /* Configure for ELP power saving */ | ||
357 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
358 | if (ret < 0) | ||
359 | return ret; | ||
360 | |||
361 | /* Configure rssi/snr averaging weights */ | ||
362 | ret = wl1271_acx_rssi_snr_avg_weights(wl); | ||
363 | if (ret < 0) | ||
364 | return ret; | ||
365 | |||
366 | ret = wl1271_acx_sta_rate_policies(wl); | ||
367 | if (ret < 0) | ||
368 | return ret; | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) | ||
374 | { | ||
375 | int ret, i; | ||
376 | |||
377 | ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key); | ||
378 | if (ret < 0) { | ||
379 | wl1271_warning("couldn't set default key"); | ||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | /* disable all keep-alive templates */ | ||
384 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
385 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
386 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
387 | if (ret < 0) | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* disable the keep-alive feature */ | ||
392 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
393 | if (ret < 0) | ||
394 | return ret; | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int wl1271_ap_hw_init(struct wl1271 *wl) | ||
400 | { | ||
401 | int ret, i; | ||
402 | |||
403 | ret = wl1271_ap_init_templates_config(wl); | ||
404 | if (ret < 0) | ||
405 | return ret; | ||
406 | |||
407 | /* Configure for power always on */ | ||
408 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
409 | if (ret < 0) | ||
410 | return ret; | ||
411 | |||
412 | /* Configure initial TX rate classes */ | ||
413 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
414 | ret = wl1271_acx_ap_rate_policy(wl, | ||
415 | &wl->conf.tx.ap_rc_conf[i], i); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | ret = wl1271_acx_ap_rate_policy(wl, | ||
421 | &wl->conf.tx.ap_mgmt_conf, | ||
422 | ACX_TX_AP_MODE_MGMT_RATE); | ||
423 | if (ret < 0) | ||
424 | return ret; | ||
425 | |||
426 | ret = wl1271_acx_ap_rate_policy(wl, | ||
427 | &wl->conf.tx.ap_bcst_conf, | ||
428 | ACX_TX_AP_MODE_BCST_RATE); | ||
429 | if (ret < 0) | ||
430 | return ret; | ||
431 | |||
432 | ret = wl1271_acx_max_tx_retry(wl); | ||
433 | if (ret < 0) | ||
434 | return ret; | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | ||
440 | { | ||
441 | int ret; | ||
442 | |||
443 | ret = wl1271_ap_init_deauth_template(wl); | ||
444 | if (ret < 0) | ||
445 | return ret; | ||
446 | |||
447 | ret = wl1271_ap_init_null_template(wl); | ||
448 | if (ret < 0) | ||
449 | return ret; | ||
450 | |||
451 | ret = wl1271_ap_init_qos_null_template(wl); | ||
452 | if (ret < 0) | ||
453 | return ret; | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static void wl1271_check_ba_support(struct wl1271 *wl) | ||
459 | { | ||
460 | /* validate FW cose ver x.x.x.50-60.x */ | ||
461 | if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) && | ||
462 | (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) { | ||
463 | wl->ba_support = true; | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | wl->ba_support = false; | ||
468 | } | ||
469 | |||
470 | static int wl1271_set_ba_policies(struct wl1271 *wl) | ||
471 | { | ||
472 | u8 tid_index; | ||
473 | u8 ret = 0; | ||
474 | |||
475 | /* Reset the BA RX indicators */ | ||
476 | wl->ba_rx_bitmap = 0; | ||
477 | |||
478 | /* validate that FW support BA */ | ||
479 | wl1271_check_ba_support(wl); | ||
480 | |||
481 | if (wl->ba_support) | ||
482 | /* 802.11n initiator BA session setting */ | ||
483 | for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT; | ||
484 | ++tid_index) { | ||
485 | ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR, | ||
486 | tid_index, true); | ||
487 | if (ret < 0) | ||
488 | break; | ||
489 | } | ||
490 | |||
491 | return ret; | ||
492 | } | ||
493 | |||
216 | int wl1271_hw_init(struct wl1271 *wl) | 494 | int wl1271_hw_init(struct wl1271 *wl) |
217 | { | 495 | { |
218 | struct conf_tx_ac_category *conf_ac; | 496 | struct conf_tx_ac_category *conf_ac; |
219 | struct conf_tx_tid *conf_tid; | 497 | struct conf_tx_tid *conf_tid; |
220 | int ret, i; | 498 | int ret, i; |
499 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
221 | 500 | ||
222 | ret = wl1271_cmd_general_parms(wl); | 501 | ret = wl1271_cmd_general_parms(wl); |
223 | if (ret < 0) | 502 | if (ret < 0) |
@@ -227,12 +506,12 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
227 | if (ret < 0) | 506 | if (ret < 0) |
228 | return ret; | 507 | return ret; |
229 | 508 | ||
230 | ret = wl1271_cmd_ext_radio_parms(wl); | 509 | /* Mode specific init */ |
231 | if (ret < 0) | 510 | if (is_ap) |
232 | return ret; | 511 | ret = wl1271_ap_hw_init(wl); |
512 | else | ||
513 | ret = wl1271_sta_hw_init(wl); | ||
233 | 514 | ||
234 | /* Template settings */ | ||
235 | ret = wl1271_init_templates_config(wl); | ||
236 | if (ret < 0) | 515 | if (ret < 0) |
237 | return ret; | 516 | return ret; |
238 | 517 | ||
@@ -259,16 +538,6 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
259 | if (ret < 0) | 538 | if (ret < 0) |
260 | goto out_free_memmap; | 539 | goto out_free_memmap; |
261 | 540 | ||
262 | /* Initialize connection monitoring thresholds */ | ||
263 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
264 | if (ret < 0) | ||
265 | goto out_free_memmap; | ||
266 | |||
267 | /* Beacon filtering */ | ||
268 | ret = wl1271_init_beacon_filter(wl); | ||
269 | if (ret < 0) | ||
270 | goto out_free_memmap; | ||
271 | |||
272 | /* Configure TX patch complete interrupt behavior */ | 541 | /* Configure TX patch complete interrupt behavior */ |
273 | ret = wl1271_acx_tx_config_options(wl); | 542 | ret = wl1271_acx_tx_config_options(wl); |
274 | if (ret < 0) | 543 | if (ret < 0) |
@@ -279,21 +548,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
279 | if (ret < 0) | 548 | if (ret < 0) |
280 | goto out_free_memmap; | 549 | goto out_free_memmap; |
281 | 550 | ||
282 | /* Bluetooth WLAN coexistence */ | ||
283 | ret = wl1271_init_pta(wl); | ||
284 | if (ret < 0) | ||
285 | goto out_free_memmap; | ||
286 | |||
287 | /* Energy detection */ | 551 | /* Energy detection */ |
288 | ret = wl1271_init_energy_detection(wl); | 552 | ret = wl1271_init_energy_detection(wl); |
289 | if (ret < 0) | 553 | if (ret < 0) |
290 | goto out_free_memmap; | 554 | goto out_free_memmap; |
291 | 555 | ||
292 | /* Beacons and boradcast settings */ | ||
293 | ret = wl1271_init_beacon_broadcast(wl); | ||
294 | if (ret < 0) | ||
295 | goto out_free_memmap; | ||
296 | |||
297 | /* Default fragmentation threshold */ | 556 | /* Default fragmentation threshold */ |
298 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); | 557 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); |
299 | if (ret < 0) | 558 | if (ret < 0) |
@@ -321,23 +580,13 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
321 | goto out_free_memmap; | 580 | goto out_free_memmap; |
322 | } | 581 | } |
323 | 582 | ||
324 | /* Configure TX rate classes */ | ||
325 | ret = wl1271_acx_rate_policies(wl); | ||
326 | if (ret < 0) | ||
327 | goto out_free_memmap; | ||
328 | |||
329 | /* Enable data path */ | 583 | /* Enable data path */ |
330 | ret = wl1271_cmd_data_path(wl, 1); | 584 | ret = wl1271_cmd_data_path(wl, 1); |
331 | if (ret < 0) | 585 | if (ret < 0) |
332 | goto out_free_memmap; | 586 | goto out_free_memmap; |
333 | 587 | ||
334 | /* Configure for ELP power saving */ | ||
335 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
336 | if (ret < 0) | ||
337 | goto out_free_memmap; | ||
338 | |||
339 | /* Configure HW encryption */ | 588 | /* Configure HW encryption */ |
340 | ret = wl1271_init_hwenc_config(wl); | 589 | ret = wl1271_acx_feature_cfg(wl); |
341 | if (ret < 0) | 590 | if (ret < 0) |
342 | goto out_free_memmap; | 591 | goto out_free_memmap; |
343 | 592 | ||
@@ -346,21 +595,17 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
346 | if (ret < 0) | 595 | if (ret < 0) |
347 | goto out_free_memmap; | 596 | goto out_free_memmap; |
348 | 597 | ||
349 | /* disable all keep-alive templates */ | 598 | /* Mode specific init - post mem init */ |
350 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | 599 | if (is_ap) |
351 | ret = wl1271_acx_keep_alive_config(wl, i, | 600 | ret = wl1271_ap_hw_init_post_mem(wl); |
352 | ACX_KEEP_ALIVE_TPL_INVALID); | 601 | else |
353 | if (ret < 0) | 602 | ret = wl1271_sta_hw_init_post_mem(wl); |
354 | goto out_free_memmap; | ||
355 | } | ||
356 | 603 | ||
357 | /* disable the keep-alive feature */ | ||
358 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
359 | if (ret < 0) | 604 | if (ret < 0) |
360 | goto out_free_memmap; | 605 | goto out_free_memmap; |
361 | 606 | ||
362 | /* Configure rssi/snr averaging weights */ | 607 | /* Configure initiator BA sessions policies */ |
363 | ret = wl1271_acx_rssi_snr_avg_weights(wl); | 608 | ret = wl1271_set_ba_policies(wl); |
364 | if (ret < 0) | 609 | if (ret < 0) |
365 | goto out_free_memmap; | 610 | goto out_free_memmap; |
366 | 611 | ||
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 7762421f8602..3a8bd3f426d2 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "wl12xx.h" | 27 | #include "wl12xx.h" |
28 | 28 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | 30 | int wl1271_sta_init_templates_config(struct wl1271 *wl); |
31 | int wl1271_init_phy_config(struct wl1271 *wl); | 31 | int wl1271_init_phy_config(struct wl1271 *wl); |
32 | int wl1271_init_pta(struct wl1271 *wl); | 32 | int wl1271_init_pta(struct wl1271 *wl); |
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | 33 | int wl1271_init_energy_detection(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 062247ef3ad2..254b7daccee1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -116,11 +116,11 @@ static struct conf_drv_settings default_conf = { | |||
116 | }, | 116 | }, |
117 | .tx = { | 117 | .tx = { |
118 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
119 | .rc_conf = { | 119 | .sta_rc_conf = { |
120 | .enabled_rates = 0, | 120 | .enabled_rates = 0, |
121 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
122 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
123 | .aflags = 0 | 123 | .aflags = 0, |
124 | }, | 124 | }, |
125 | .ac_conf_count = 4, | 125 | .ac_conf_count = 4, |
126 | .ac_conf = { | 126 | .ac_conf = { |
@@ -153,6 +153,45 @@ static struct conf_drv_settings default_conf = { | |||
153 | .tx_op_limit = 1504, | 153 | .tx_op_limit = 1504, |
154 | }, | 154 | }, |
155 | }, | 155 | }, |
156 | .ap_rc_conf = { | ||
157 | [0] = { | ||
158 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
159 | .short_retry_limit = 10, | ||
160 | .long_retry_limit = 10, | ||
161 | .aflags = 0, | ||
162 | }, | ||
163 | [1] = { | ||
164 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
165 | .short_retry_limit = 10, | ||
166 | .long_retry_limit = 10, | ||
167 | .aflags = 0, | ||
168 | }, | ||
169 | [2] = { | ||
170 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
171 | .short_retry_limit = 10, | ||
172 | .long_retry_limit = 10, | ||
173 | .aflags = 0, | ||
174 | }, | ||
175 | [3] = { | ||
176 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
177 | .short_retry_limit = 10, | ||
178 | .long_retry_limit = 10, | ||
179 | .aflags = 0, | ||
180 | }, | ||
181 | }, | ||
182 | .ap_mgmt_conf = { | ||
183 | .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, | ||
184 | .short_retry_limit = 10, | ||
185 | .long_retry_limit = 10, | ||
186 | .aflags = 0, | ||
187 | }, | ||
188 | .ap_bcst_conf = { | ||
189 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS, | ||
190 | .short_retry_limit = 10, | ||
191 | .long_retry_limit = 10, | ||
192 | .aflags = 0, | ||
193 | }, | ||
194 | .ap_max_tx_retries = 100, | ||
156 | .tid_conf_count = 4, | 195 | .tid_conf_count = 4, |
157 | .tid_conf = { | 196 | .tid_conf = { |
158 | [CONF_TX_AC_BE] = { | 197 | [CONF_TX_AC_BE] = { |
@@ -193,6 +232,8 @@ static struct conf_drv_settings default_conf = { | |||
193 | .tx_compl_threshold = 4, | 232 | .tx_compl_threshold = 4, |
194 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | 233 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, |
195 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | 234 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, |
235 | .tmpl_short_retry_limit = 10, | ||
236 | .tmpl_long_retry_limit = 10, | ||
196 | }, | 237 | }, |
197 | .conn = { | 238 | .conn = { |
198 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 239 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -233,13 +274,13 @@ static struct conf_drv_settings default_conf = { | |||
233 | .avg_weight_rssi_beacon = 20, | 274 | .avg_weight_rssi_beacon = 20, |
234 | .avg_weight_rssi_data = 10, | 275 | .avg_weight_rssi_data = 10, |
235 | .avg_weight_snr_beacon = 20, | 276 | .avg_weight_snr_beacon = 20, |
236 | .avg_weight_snr_data = 10 | 277 | .avg_weight_snr_data = 10, |
237 | }, | 278 | }, |
238 | .scan = { | 279 | .scan = { |
239 | .min_dwell_time_active = 7500, | 280 | .min_dwell_time_active = 7500, |
240 | .max_dwell_time_active = 30000, | 281 | .max_dwell_time_active = 30000, |
241 | .min_dwell_time_passive = 30000, | 282 | .min_dwell_time_passive = 100000, |
242 | .max_dwell_time_passive = 60000, | 283 | .max_dwell_time_passive = 100000, |
243 | .num_probe_reqs = 2, | 284 | .num_probe_reqs = 2, |
244 | }, | 285 | }, |
245 | .rf = { | 286 | .rf = { |
@@ -252,9 +293,14 @@ static struct conf_drv_settings default_conf = { | |||
252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
253 | }, | 294 | }, |
254 | }, | 295 | }, |
296 | .ht = { | ||
297 | .tx_ba_win_size = 64, | ||
298 | .inactivity_timeout = 10000, | ||
299 | }, | ||
255 | }; | 300 | }; |
256 | 301 | ||
257 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 302 | static void __wl1271_op_remove_interface(struct wl1271 *wl); |
303 | static void wl1271_free_ap_keys(struct wl1271 *wl); | ||
258 | 304 | ||
259 | 305 | ||
260 | static void wl1271_device_release(struct device *dev) | 306 | static void wl1271_device_release(struct device *dev) |
@@ -393,7 +439,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
393 | if (ret < 0) | 439 | if (ret < 0) |
394 | return ret; | 440 | return ret; |
395 | 441 | ||
396 | ret = wl1271_init_templates_config(wl); | 442 | ret = wl1271_sta_init_templates_config(wl); |
397 | if (ret < 0) | 443 | if (ret < 0) |
398 | return ret; | 444 | return ret; |
399 | 445 | ||
@@ -616,9 +662,26 @@ out: | |||
616 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 662 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
617 | { | 663 | { |
618 | const struct firmware *fw; | 664 | const struct firmware *fw; |
665 | const char *fw_name; | ||
619 | int ret; | 666 | int ret; |
620 | 667 | ||
621 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); | 668 | switch (wl->bss_type) { |
669 | case BSS_TYPE_AP_BSS: | ||
670 | fw_name = WL1271_AP_FW_NAME; | ||
671 | break; | ||
672 | case BSS_TYPE_IBSS: | ||
673 | case BSS_TYPE_STA_BSS: | ||
674 | fw_name = WL1271_FW_NAME; | ||
675 | break; | ||
676 | default: | ||
677 | wl1271_error("no compatible firmware for bss_type %d", | ||
678 | wl->bss_type); | ||
679 | return -EINVAL; | ||
680 | } | ||
681 | |||
682 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); | ||
683 | |||
684 | ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); | ||
622 | 685 | ||
623 | if (ret < 0) { | 686 | if (ret < 0) { |
624 | wl1271_error("could not get firmware: %d", ret); | 687 | wl1271_error("could not get firmware: %d", ret); |
@@ -632,6 +695,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
632 | goto out; | 695 | goto out; |
633 | } | 696 | } |
634 | 697 | ||
698 | vfree(wl->fw); | ||
635 | wl->fw_len = fw->size; | 699 | wl->fw_len = fw->size; |
636 | wl->fw = vmalloc(wl->fw_len); | 700 | wl->fw = vmalloc(wl->fw_len); |
637 | 701 | ||
@@ -642,7 +706,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
642 | } | 706 | } |
643 | 707 | ||
644 | memcpy(wl->fw, fw->data, wl->fw_len); | 708 | memcpy(wl->fw, fw->data, wl->fw_len); |
645 | 709 | wl->fw_bss_type = wl->bss_type; | |
646 | ret = 0; | 710 | ret = 0; |
647 | 711 | ||
648 | out: | 712 | out: |
@@ -778,7 +842,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
778 | goto out; | 842 | goto out; |
779 | } | 843 | } |
780 | 844 | ||
781 | if (wl->fw == NULL) { | 845 | /* Make sure the firmware type matches the BSS type */ |
846 | if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) { | ||
782 | ret = wl1271_fetch_firmware(wl); | 847 | ret = wl1271_fetch_firmware(wl); |
783 | if (ret < 0) | 848 | if (ret < 0) |
784 | goto out; | 849 | goto out; |
@@ -811,6 +876,8 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
811 | goto out; | 876 | goto out; |
812 | } | 877 | } |
813 | 878 | ||
879 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
880 | |||
814 | while (retries) { | 881 | while (retries) { |
815 | retries--; | 882 | retries--; |
816 | ret = wl1271_chip_wakeup(wl); | 883 | ret = wl1271_chip_wakeup(wl); |
@@ -827,7 +894,7 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
827 | 894 | ||
828 | wl->state = WL1271_STATE_PLT; | 895 | wl->state = WL1271_STATE_PLT; |
829 | wl1271_notice("firmware booted in PLT mode (%s)", | 896 | wl1271_notice("firmware booted in PLT mode (%s)", |
830 | wl->chip.fw_ver); | 897 | wl->chip.fw_ver_str); |
831 | goto out; | 898 | goto out; |
832 | 899 | ||
833 | irq_disable: | 900 | irq_disable: |
@@ -854,12 +921,10 @@ out: | |||
854 | return ret; | 921 | return ret; |
855 | } | 922 | } |
856 | 923 | ||
857 | int wl1271_plt_stop(struct wl1271 *wl) | 924 | int __wl1271_plt_stop(struct wl1271 *wl) |
858 | { | 925 | { |
859 | int ret = 0; | 926 | int ret = 0; |
860 | 927 | ||
861 | mutex_lock(&wl->mutex); | ||
862 | |||
863 | wl1271_notice("power down"); | 928 | wl1271_notice("power down"); |
864 | 929 | ||
865 | if (wl->state != WL1271_STATE_PLT) { | 930 | if (wl->state != WL1271_STATE_PLT) { |
@@ -875,12 +940,21 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
875 | wl->state = WL1271_STATE_OFF; | 940 | wl->state = WL1271_STATE_OFF; |
876 | wl->rx_counter = 0; | 941 | wl->rx_counter = 0; |
877 | 942 | ||
878 | out: | ||
879 | mutex_unlock(&wl->mutex); | 943 | mutex_unlock(&wl->mutex); |
880 | |||
881 | cancel_work_sync(&wl->irq_work); | 944 | cancel_work_sync(&wl->irq_work); |
882 | cancel_work_sync(&wl->recovery_work); | 945 | cancel_work_sync(&wl->recovery_work); |
946 | mutex_lock(&wl->mutex); | ||
947 | out: | ||
948 | return ret; | ||
949 | } | ||
950 | |||
951 | int wl1271_plt_stop(struct wl1271 *wl) | ||
952 | { | ||
953 | int ret; | ||
883 | 954 | ||
955 | mutex_lock(&wl->mutex); | ||
956 | ret = __wl1271_plt_stop(wl); | ||
957 | mutex_unlock(&wl->mutex); | ||
884 | return ret; | 958 | return ret; |
885 | } | 959 | } |
886 | 960 | ||
@@ -902,7 +976,8 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
902 | spin_lock_irqsave(&wl->wl_lock, flags); | 976 | spin_lock_irqsave(&wl->wl_lock, flags); |
903 | if (sta && | 977 | if (sta && |
904 | (sta->supp_rates[conf->channel->band] != | 978 | (sta->supp_rates[conf->channel->band] != |
905 | (wl->sta_rate_set & HW_BG_RATES_MASK))) { | 979 | (wl->sta_rate_set & HW_BG_RATES_MASK)) && |
980 | wl->bss_type != BSS_TYPE_AP_BSS) { | ||
906 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | 981 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; |
907 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | 982 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); |
908 | } | 983 | } |
@@ -967,6 +1042,9 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
967 | * | 1042 | * |
968 | * The MAC address is first known when the corresponding interface | 1043 | * The MAC address is first known when the corresponding interface |
969 | * is added. That is where we will initialize the hardware. | 1044 | * is added. That is where we will initialize the hardware. |
1045 | * | ||
1046 | * In addition, we currently have different firmwares for AP and managed | ||
1047 | * operation. We will know which to boot according to interface type. | ||
970 | */ | 1048 | */ |
971 | 1049 | ||
972 | return 0; | 1050 | return 0; |
@@ -1006,6 +1084,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1006 | wl->bss_type = BSS_TYPE_IBSS; | 1084 | wl->bss_type = BSS_TYPE_IBSS; |
1007 | wl->set_bss_type = BSS_TYPE_STA_BSS; | 1085 | wl->set_bss_type = BSS_TYPE_STA_BSS; |
1008 | break; | 1086 | break; |
1087 | case NL80211_IFTYPE_AP: | ||
1088 | wl->bss_type = BSS_TYPE_AP_BSS; | ||
1089 | break; | ||
1009 | default: | 1090 | default: |
1010 | ret = -EOPNOTSUPP; | 1091 | ret = -EOPNOTSUPP; |
1011 | goto out; | 1092 | goto out; |
@@ -1061,11 +1142,11 @@ power_off: | |||
1061 | 1142 | ||
1062 | wl->vif = vif; | 1143 | wl->vif = vif; |
1063 | wl->state = WL1271_STATE_ON; | 1144 | wl->state = WL1271_STATE_ON; |
1064 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 1145 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
1065 | 1146 | ||
1066 | /* update hw/fw version info in wiphy struct */ | 1147 | /* update hw/fw version info in wiphy struct */ |
1067 | wiphy->hw_version = wl->chip.id; | 1148 | wiphy->hw_version = wl->chip.id; |
1068 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | 1149 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, |
1069 | sizeof(wiphy->fw_version)); | 1150 | sizeof(wiphy->fw_version)); |
1070 | 1151 | ||
1071 | /* | 1152 | /* |
@@ -1151,6 +1232,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1151 | wl->flags = 0; | 1232 | wl->flags = 0; |
1152 | wl->vif = NULL; | 1233 | wl->vif = NULL; |
1153 | wl->filters = 0; | 1234 | wl->filters = 0; |
1235 | wl1271_free_ap_keys(wl); | ||
1236 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | ||
1154 | 1237 | ||
1155 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1238 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1156 | wl->tx_blocks_freed[i] = 0; | 1239 | wl->tx_blocks_freed[i] = 0; |
@@ -1186,8 +1269,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1186 | 1269 | ||
1187 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1270 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1188 | { | 1271 | { |
1189 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1272 | wl1271_set_default_filters(wl); |
1190 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | ||
1191 | 1273 | ||
1192 | /* combine requested filters with current filter config */ | 1274 | /* combine requested filters with current filter config */ |
1193 | filters = wl->filters | filters; | 1275 | filters = wl->filters | filters; |
@@ -1322,25 +1404,7 @@ static void wl1271_set_band_rate(struct wl1271 *wl) | |||
1322 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | 1404 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; |
1323 | } | 1405 | } |
1324 | 1406 | ||
1325 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | 1407 | static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) |
1326 | { | ||
1327 | int i; | ||
1328 | u32 rate = 0; | ||
1329 | |||
1330 | if (!wl->basic_rate_set) { | ||
1331 | WARN_ON(1); | ||
1332 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1333 | } | ||
1334 | |||
1335 | for (i = 0; !rate; i++) { | ||
1336 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1337 | rate = 1 << i; | ||
1338 | } | ||
1339 | |||
1340 | return rate; | ||
1341 | } | ||
1342 | |||
1343 | static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | ||
1344 | { | 1408 | { |
1345 | int ret; | 1409 | int ret; |
1346 | 1410 | ||
@@ -1350,9 +1414,9 @@ static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | |||
1350 | if (ret < 0) | 1414 | if (ret < 0) |
1351 | goto out; | 1415 | goto out; |
1352 | } | 1416 | } |
1353 | wl->rate_set = wl1271_min_rate_get(wl); | 1417 | wl->rate_set = wl1271_tx_min_rate_get(wl); |
1354 | wl->sta_rate_set = 0; | 1418 | wl->sta_rate_set = 0; |
1355 | ret = wl1271_acx_rate_policies(wl); | 1419 | ret = wl1271_acx_sta_rate_policies(wl); |
1356 | if (ret < 0) | 1420 | if (ret < 0) |
1357 | goto out; | 1421 | goto out; |
1358 | ret = wl1271_acx_keep_alive_config( | 1422 | ret = wl1271_acx_keep_alive_config( |
@@ -1381,14 +1445,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1381 | struct wl1271 *wl = hw->priv; | 1445 | struct wl1271 *wl = hw->priv; |
1382 | struct ieee80211_conf *conf = &hw->conf; | 1446 | struct ieee80211_conf *conf = &hw->conf; |
1383 | int channel, ret = 0; | 1447 | int channel, ret = 0; |
1448 | bool is_ap; | ||
1384 | 1449 | ||
1385 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1450 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1386 | 1451 | ||
1387 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", | 1452 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" |
1453 | " changed 0x%x", | ||
1388 | channel, | 1454 | channel, |
1389 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1455 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1390 | conf->power_level, | 1456 | conf->power_level, |
1391 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | 1457 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", |
1458 | changed); | ||
1392 | 1459 | ||
1393 | /* | 1460 | /* |
1394 | * mac80211 will go to idle nearly immediately after transmitting some | 1461 | * mac80211 will go to idle nearly immediately after transmitting some |
@@ -1406,6 +1473,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1406 | goto out; | 1473 | goto out; |
1407 | } | 1474 | } |
1408 | 1475 | ||
1476 | is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
1477 | |||
1409 | ret = wl1271_ps_elp_wakeup(wl, false); | 1478 | ret = wl1271_ps_elp_wakeup(wl, false); |
1410 | if (ret < 0) | 1479 | if (ret < 0) |
1411 | goto out; | 1480 | goto out; |
@@ -1417,31 +1486,34 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1417 | wl->band = conf->channel->band; | 1486 | wl->band = conf->channel->band; |
1418 | wl->channel = channel; | 1487 | wl->channel = channel; |
1419 | 1488 | ||
1420 | /* | 1489 | if (!is_ap) { |
1421 | * FIXME: the mac80211 should really provide a fixed rate | 1490 | /* |
1422 | * to use here. for now, just use the smallest possible rate | 1491 | * FIXME: the mac80211 should really provide a fixed |
1423 | * for the band as a fixed rate for association frames and | 1492 | * rate to use here. for now, just use the smallest |
1424 | * other control messages. | 1493 | * possible rate for the band as a fixed rate for |
1425 | */ | 1494 | * association frames and other control messages. |
1426 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1495 | */ |
1427 | wl1271_set_band_rate(wl); | 1496 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1428 | 1497 | wl1271_set_band_rate(wl); | |
1429 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1430 | ret = wl1271_acx_rate_policies(wl); | ||
1431 | if (ret < 0) | ||
1432 | wl1271_warning("rate policy for update channel " | ||
1433 | "failed %d", ret); | ||
1434 | 1498 | ||
1435 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | 1499 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1436 | ret = wl1271_join(wl, false); | 1500 | ret = wl1271_acx_sta_rate_policies(wl); |
1437 | if (ret < 0) | 1501 | if (ret < 0) |
1438 | wl1271_warning("cmd join to update channel " | 1502 | wl1271_warning("rate policy for channel " |
1439 | "failed %d", ret); | 1503 | "failed %d", ret); |
1504 | |||
1505 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1506 | ret = wl1271_join(wl, false); | ||
1507 | if (ret < 0) | ||
1508 | wl1271_warning("cmd join on channel " | ||
1509 | "failed %d", ret); | ||
1510 | } | ||
1440 | } | 1511 | } |
1441 | } | 1512 | } |
1442 | 1513 | ||
1443 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1514 | if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { |
1444 | ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE); | 1515 | ret = wl1271_sta_handle_idle(wl, |
1516 | conf->flags & IEEE80211_CONF_IDLE); | ||
1445 | if (ret < 0) | 1517 | if (ret < 0) |
1446 | wl1271_warning("idle mode change failed %d", ret); | 1518 | wl1271_warning("idle mode change failed %d", ret); |
1447 | } | 1519 | } |
@@ -1548,7 +1620,8 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1548 | struct wl1271 *wl = hw->priv; | 1620 | struct wl1271 *wl = hw->priv; |
1549 | int ret; | 1621 | int ret; |
1550 | 1622 | ||
1551 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter"); | 1623 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" |
1624 | " total %x", changed, *total); | ||
1552 | 1625 | ||
1553 | mutex_lock(&wl->mutex); | 1626 | mutex_lock(&wl->mutex); |
1554 | 1627 | ||
@@ -1562,15 +1635,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1562 | if (ret < 0) | 1635 | if (ret < 0) |
1563 | goto out; | 1636 | goto out; |
1564 | 1637 | ||
1565 | 1638 | if (wl->bss_type != BSS_TYPE_AP_BSS) { | |
1566 | if (*total & FIF_ALLMULTI) | 1639 | if (*total & FIF_ALLMULTI) |
1567 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1640 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
1568 | else if (fp) | 1641 | else if (fp) |
1569 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, | 1642 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, |
1570 | fp->mc_list, | 1643 | fp->mc_list, |
1571 | fp->mc_list_length); | 1644 | fp->mc_list_length); |
1572 | if (ret < 0) | 1645 | if (ret < 0) |
1573 | goto out_sleep; | 1646 | goto out_sleep; |
1647 | } | ||
1574 | 1648 | ||
1575 | /* determine, whether supported filter values have changed */ | 1649 | /* determine, whether supported filter values have changed */ |
1576 | if (changed == 0) | 1650 | if (changed == 0) |
@@ -1593,38 +1667,192 @@ out: | |||
1593 | kfree(fp); | 1667 | kfree(fp); |
1594 | } | 1668 | } |
1595 | 1669 | ||
1670 | static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, | ||
1671 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | ||
1672 | u16 tx_seq_16) | ||
1673 | { | ||
1674 | struct wl1271_ap_key *ap_key; | ||
1675 | int i; | ||
1676 | |||
1677 | wl1271_debug(DEBUG_CRYPT, "record ap key id %d", (int)id); | ||
1678 | |||
1679 | if (key_size > MAX_KEY_SIZE) | ||
1680 | return -EINVAL; | ||
1681 | |||
1682 | /* | ||
1683 | * Find next free entry in ap_keys. Also check we are not replacing | ||
1684 | * an existing key. | ||
1685 | */ | ||
1686 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1687 | if (wl->recorded_ap_keys[i] == NULL) | ||
1688 | break; | ||
1689 | |||
1690 | if (wl->recorded_ap_keys[i]->id == id) { | ||
1691 | wl1271_warning("trying to record key replacement"); | ||
1692 | return -EINVAL; | ||
1693 | } | ||
1694 | } | ||
1695 | |||
1696 | if (i == MAX_NUM_KEYS) | ||
1697 | return -EBUSY; | ||
1698 | |||
1699 | ap_key = kzalloc(sizeof(*ap_key), GFP_KERNEL); | ||
1700 | if (!ap_key) | ||
1701 | return -ENOMEM; | ||
1702 | |||
1703 | ap_key->id = id; | ||
1704 | ap_key->key_type = key_type; | ||
1705 | ap_key->key_size = key_size; | ||
1706 | memcpy(ap_key->key, key, key_size); | ||
1707 | ap_key->hlid = hlid; | ||
1708 | ap_key->tx_seq_32 = tx_seq_32; | ||
1709 | ap_key->tx_seq_16 = tx_seq_16; | ||
1710 | |||
1711 | wl->recorded_ap_keys[i] = ap_key; | ||
1712 | return 0; | ||
1713 | } | ||
1714 | |||
1715 | static void wl1271_free_ap_keys(struct wl1271 *wl) | ||
1716 | { | ||
1717 | int i; | ||
1718 | |||
1719 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1720 | kfree(wl->recorded_ap_keys[i]); | ||
1721 | wl->recorded_ap_keys[i] = NULL; | ||
1722 | } | ||
1723 | } | ||
1724 | |||
1725 | static int wl1271_ap_init_hwenc(struct wl1271 *wl) | ||
1726 | { | ||
1727 | int i, ret = 0; | ||
1728 | struct wl1271_ap_key *key; | ||
1729 | bool wep_key_added = false; | ||
1730 | |||
1731 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1732 | if (wl->recorded_ap_keys[i] == NULL) | ||
1733 | break; | ||
1734 | |||
1735 | key = wl->recorded_ap_keys[i]; | ||
1736 | ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, | ||
1737 | key->id, key->key_type, | ||
1738 | key->key_size, key->key, | ||
1739 | key->hlid, key->tx_seq_32, | ||
1740 | key->tx_seq_16); | ||
1741 | if (ret < 0) | ||
1742 | goto out; | ||
1743 | |||
1744 | if (key->key_type == KEY_WEP) | ||
1745 | wep_key_added = true; | ||
1746 | } | ||
1747 | |||
1748 | if (wep_key_added) { | ||
1749 | ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key); | ||
1750 | if (ret < 0) | ||
1751 | goto out; | ||
1752 | } | ||
1753 | |||
1754 | out: | ||
1755 | wl1271_free_ap_keys(wl); | ||
1756 | return ret; | ||
1757 | } | ||
1758 | |||
1759 | static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | ||
1760 | u8 key_size, const u8 *key, u32 tx_seq_32, | ||
1761 | u16 tx_seq_16, struct ieee80211_sta *sta) | ||
1762 | { | ||
1763 | int ret; | ||
1764 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
1765 | |||
1766 | if (is_ap) { | ||
1767 | struct wl1271_station *wl_sta; | ||
1768 | u8 hlid; | ||
1769 | |||
1770 | if (sta) { | ||
1771 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
1772 | hlid = wl_sta->hlid; | ||
1773 | } else { | ||
1774 | hlid = WL1271_AP_BROADCAST_HLID; | ||
1775 | } | ||
1776 | |||
1777 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
1778 | /* | ||
1779 | * We do not support removing keys after AP shutdown. | ||
1780 | * Pretend we do to make mac80211 happy. | ||
1781 | */ | ||
1782 | if (action != KEY_ADD_OR_REPLACE) | ||
1783 | return 0; | ||
1784 | |||
1785 | ret = wl1271_record_ap_key(wl, id, | ||
1786 | key_type, key_size, | ||
1787 | key, hlid, tx_seq_32, | ||
1788 | tx_seq_16); | ||
1789 | } else { | ||
1790 | ret = wl1271_cmd_set_ap_key(wl, action, | ||
1791 | id, key_type, key_size, | ||
1792 | key, hlid, tx_seq_32, | ||
1793 | tx_seq_16); | ||
1794 | } | ||
1795 | |||
1796 | if (ret < 0) | ||
1797 | return ret; | ||
1798 | } else { | ||
1799 | const u8 *addr; | ||
1800 | static const u8 bcast_addr[ETH_ALEN] = { | ||
1801 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
1802 | }; | ||
1803 | |||
1804 | addr = sta ? sta->addr : bcast_addr; | ||
1805 | |||
1806 | if (is_zero_ether_addr(addr)) { | ||
1807 | /* We dont support TX only encryption */ | ||
1808 | return -EOPNOTSUPP; | ||
1809 | } | ||
1810 | |||
1811 | /* The wl1271 does not allow to remove unicast keys - they | ||
1812 | will be cleared automatically on next CMD_JOIN. Ignore the | ||
1813 | request silently, as we dont want the mac80211 to emit | ||
1814 | an error message. */ | ||
1815 | if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr)) | ||
1816 | return 0; | ||
1817 | |||
1818 | ret = wl1271_cmd_set_sta_key(wl, action, | ||
1819 | id, key_type, key_size, | ||
1820 | key, addr, tx_seq_32, | ||
1821 | tx_seq_16); | ||
1822 | if (ret < 0) | ||
1823 | return ret; | ||
1824 | |||
1825 | /* the default WEP key needs to be configured at least once */ | ||
1826 | if (key_type == KEY_WEP) { | ||
1827 | ret = wl1271_cmd_set_sta_default_wep_key(wl, | ||
1828 | wl->default_key); | ||
1829 | if (ret < 0) | ||
1830 | return ret; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | return 0; | ||
1835 | } | ||
1836 | |||
1596 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1837 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
1597 | struct ieee80211_vif *vif, | 1838 | struct ieee80211_vif *vif, |
1598 | struct ieee80211_sta *sta, | 1839 | struct ieee80211_sta *sta, |
1599 | struct ieee80211_key_conf *key_conf) | 1840 | struct ieee80211_key_conf *key_conf) |
1600 | { | 1841 | { |
1601 | struct wl1271 *wl = hw->priv; | 1842 | struct wl1271 *wl = hw->priv; |
1602 | const u8 *addr; | ||
1603 | int ret; | 1843 | int ret; |
1604 | u32 tx_seq_32 = 0; | 1844 | u32 tx_seq_32 = 0; |
1605 | u16 tx_seq_16 = 0; | 1845 | u16 tx_seq_16 = 0; |
1606 | u8 key_type; | 1846 | u8 key_type; |
1607 | 1847 | ||
1608 | static const u8 bcast_addr[ETH_ALEN] = | ||
1609 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
1610 | |||
1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); | 1848 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); |
1612 | 1849 | ||
1613 | addr = sta ? sta->addr : bcast_addr; | 1850 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x sta: %p", cmd, sta); |
1614 | |||
1615 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | ||
1616 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | ||
1617 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 1851 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
1618 | key_conf->cipher, key_conf->keyidx, | 1852 | key_conf->cipher, key_conf->keyidx, |
1619 | key_conf->keylen, key_conf->flags); | 1853 | key_conf->keylen, key_conf->flags); |
1620 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 1854 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
1621 | 1855 | ||
1622 | if (is_zero_ether_addr(addr)) { | ||
1623 | /* We dont support TX only encryption */ | ||
1624 | ret = -EOPNOTSUPP; | ||
1625 | goto out; | ||
1626 | } | ||
1627 | |||
1628 | mutex_lock(&wl->mutex); | 1856 | mutex_lock(&wl->mutex); |
1629 | 1857 | ||
1630 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 1858 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
@@ -1671,36 +1899,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1671 | 1899 | ||
1672 | switch (cmd) { | 1900 | switch (cmd) { |
1673 | case SET_KEY: | 1901 | case SET_KEY: |
1674 | ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, | 1902 | ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE, |
1675 | key_conf->keyidx, key_type, | 1903 | key_conf->keyidx, key_type, |
1676 | key_conf->keylen, key_conf->key, | 1904 | key_conf->keylen, key_conf->key, |
1677 | addr, tx_seq_32, tx_seq_16); | 1905 | tx_seq_32, tx_seq_16, sta); |
1678 | if (ret < 0) { | 1906 | if (ret < 0) { |
1679 | wl1271_error("Could not add or replace key"); | 1907 | wl1271_error("Could not add or replace key"); |
1680 | goto out_sleep; | 1908 | goto out_sleep; |
1681 | } | 1909 | } |
1682 | |||
1683 | /* the default WEP key needs to be configured at least once */ | ||
1684 | if (key_type == KEY_WEP) { | ||
1685 | ret = wl1271_cmd_set_default_wep_key(wl, | ||
1686 | wl->default_key); | ||
1687 | if (ret < 0) | ||
1688 | goto out_sleep; | ||
1689 | } | ||
1690 | break; | 1910 | break; |
1691 | 1911 | ||
1692 | case DISABLE_KEY: | 1912 | case DISABLE_KEY: |
1693 | /* The wl1271 does not allow to remove unicast keys - they | 1913 | ret = wl1271_set_key(wl, KEY_REMOVE, |
1694 | will be cleared automatically on next CMD_JOIN. Ignore the | 1914 | key_conf->keyidx, key_type, |
1695 | request silently, as we dont want the mac80211 to emit | 1915 | key_conf->keylen, key_conf->key, |
1696 | an error message. */ | 1916 | 0, 0, sta); |
1697 | if (!is_broadcast_ether_addr(addr)) | ||
1698 | break; | ||
1699 | |||
1700 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | ||
1701 | key_conf->keyidx, key_type, | ||
1702 | key_conf->keylen, key_conf->key, | ||
1703 | addr, 0, 0); | ||
1704 | if (ret < 0) { | 1917 | if (ret < 0) { |
1705 | wl1271_error("Could not remove key"); | 1918 | wl1271_error("Could not remove key"); |
1706 | goto out_sleep; | 1919 | goto out_sleep; |
@@ -1719,7 +1932,6 @@ out_sleep: | |||
1719 | out_unlock: | 1932 | out_unlock: |
1720 | mutex_unlock(&wl->mutex); | 1933 | mutex_unlock(&wl->mutex); |
1721 | 1934 | ||
1722 | out: | ||
1723 | return ret; | 1935 | return ret; |
1724 | } | 1936 | } |
1725 | 1937 | ||
@@ -1821,7 +2033,7 @@ out: | |||
1821 | return ret; | 2033 | return ret; |
1822 | } | 2034 | } |
1823 | 2035 | ||
1824 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 2036 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
1825 | int offset) | 2037 | int offset) |
1826 | { | 2038 | { |
1827 | u8 *ptr = skb->data + offset; | 2039 | u8 *ptr = skb->data + offset; |
@@ -1831,89 +2043,210 @@ static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | |||
1831 | if (ptr[0] == WLAN_EID_SSID) { | 2043 | if (ptr[0] == WLAN_EID_SSID) { |
1832 | wl->ssid_len = ptr[1]; | 2044 | wl->ssid_len = ptr[1]; |
1833 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | 2045 | memcpy(wl->ssid, ptr+2, wl->ssid_len); |
1834 | return; | 2046 | return 0; |
1835 | } | 2047 | } |
1836 | ptr += (ptr[1] + 2); | 2048 | ptr += (ptr[1] + 2); |
1837 | } | 2049 | } |
2050 | |||
1838 | wl1271_error("No SSID in IEs!\n"); | 2051 | wl1271_error("No SSID in IEs!\n"); |
2052 | return -ENOENT; | ||
1839 | } | 2053 | } |
1840 | 2054 | ||
1841 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 2055 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
1842 | struct ieee80211_vif *vif, | ||
1843 | struct ieee80211_bss_conf *bss_conf, | 2056 | struct ieee80211_bss_conf *bss_conf, |
1844 | u32 changed) | 2057 | u32 changed) |
1845 | { | 2058 | { |
1846 | enum wl1271_cmd_ps_mode mode; | 2059 | int ret = 0; |
1847 | struct wl1271 *wl = hw->priv; | ||
1848 | struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
1849 | bool do_join = false; | ||
1850 | bool set_assoc = false; | ||
1851 | int ret; | ||
1852 | 2060 | ||
1853 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 2061 | if (changed & BSS_CHANGED_ERP_SLOT) { |
2062 | if (bss_conf->use_short_slot) | ||
2063 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | ||
2064 | else | ||
2065 | ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); | ||
2066 | if (ret < 0) { | ||
2067 | wl1271_warning("Set slot time failed %d", ret); | ||
2068 | goto out; | ||
2069 | } | ||
2070 | } | ||
1854 | 2071 | ||
1855 | mutex_lock(&wl->mutex); | 2072 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
2073 | if (bss_conf->use_short_preamble) | ||
2074 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | ||
2075 | else | ||
2076 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | ||
2077 | } | ||
1856 | 2078 | ||
1857 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 2079 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
1858 | goto out; | 2080 | if (bss_conf->use_cts_prot) |
2081 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); | ||
2082 | else | ||
2083 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); | ||
2084 | if (ret < 0) { | ||
2085 | wl1271_warning("Set ctsprotect failed %d", ret); | ||
2086 | goto out; | ||
2087 | } | ||
2088 | } | ||
1859 | 2089 | ||
1860 | ret = wl1271_ps_elp_wakeup(wl, false); | 2090 | out: |
1861 | if (ret < 0) | 2091 | return ret; |
1862 | goto out; | 2092 | } |
1863 | 2093 | ||
1864 | if ((changed & BSS_CHANGED_BEACON_INT) && | 2094 | static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, |
1865 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2095 | struct ieee80211_vif *vif, |
1866 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", | 2096 | struct ieee80211_bss_conf *bss_conf, |
2097 | u32 changed) | ||
2098 | { | ||
2099 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
2100 | int ret = 0; | ||
2101 | |||
2102 | if ((changed & BSS_CHANGED_BEACON_INT)) { | ||
2103 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", | ||
1867 | bss_conf->beacon_int); | 2104 | bss_conf->beacon_int); |
1868 | 2105 | ||
1869 | wl->beacon_int = bss_conf->beacon_int; | 2106 | wl->beacon_int = bss_conf->beacon_int; |
1870 | do_join = true; | ||
1871 | } | 2107 | } |
1872 | 2108 | ||
1873 | if ((changed & BSS_CHANGED_BEACON) && | 2109 | if ((changed & BSS_CHANGED_BEACON)) { |
1874 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2110 | struct ieee80211_hdr *hdr; |
1875 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 2111 | int ieoffset = offsetof(struct ieee80211_mgmt, |
2112 | u.beacon.variable); | ||
2113 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | ||
2114 | u16 tmpl_id; | ||
1876 | 2115 | ||
1877 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | 2116 | if (!beacon) |
2117 | goto out; | ||
1878 | 2118 | ||
1879 | if (beacon) { | 2119 | wl1271_debug(DEBUG_MASTER, "beacon updated"); |
1880 | struct ieee80211_hdr *hdr; | ||
1881 | int ieoffset = offsetof(struct ieee80211_mgmt, | ||
1882 | u.beacon.variable); | ||
1883 | 2120 | ||
1884 | wl1271_ssid_set(wl, beacon, ieoffset); | 2121 | ret = wl1271_ssid_set(wl, beacon, ieoffset); |
2122 | if (ret < 0) { | ||
2123 | dev_kfree_skb(beacon); | ||
2124 | goto out; | ||
2125 | } | ||
2126 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | ||
2127 | CMD_TEMPL_BEACON; | ||
2128 | ret = wl1271_cmd_template_set(wl, tmpl_id, | ||
2129 | beacon->data, | ||
2130 | beacon->len, 0, | ||
2131 | wl1271_tx_min_rate_get(wl)); | ||
2132 | if (ret < 0) { | ||
2133 | dev_kfree_skb(beacon); | ||
2134 | goto out; | ||
2135 | } | ||
1885 | 2136 | ||
1886 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 2137 | hdr = (struct ieee80211_hdr *) beacon->data; |
1887 | beacon->data, | 2138 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1888 | beacon->len, 0, | 2139 | IEEE80211_STYPE_PROBE_RESP); |
1889 | wl1271_min_rate_get(wl)); | 2140 | |
2141 | tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE : | ||
2142 | CMD_TEMPL_PROBE_RESPONSE; | ||
2143 | ret = wl1271_cmd_template_set(wl, | ||
2144 | tmpl_id, | ||
2145 | beacon->data, | ||
2146 | beacon->len, 0, | ||
2147 | wl1271_tx_min_rate_get(wl)); | ||
2148 | dev_kfree_skb(beacon); | ||
2149 | if (ret < 0) | ||
2150 | goto out; | ||
2151 | } | ||
1890 | 2152 | ||
1891 | if (ret < 0) { | 2153 | out: |
1892 | dev_kfree_skb(beacon); | 2154 | return ret; |
1893 | goto out_sleep; | 2155 | } |
1894 | } | ||
1895 | 2156 | ||
1896 | hdr = (struct ieee80211_hdr *) beacon->data; | 2157 | /* AP mode changes */ |
1897 | hdr->frame_control = cpu_to_le16( | 2158 | static void wl1271_bss_info_changed_ap(struct wl1271 *wl, |
1898 | IEEE80211_FTYPE_MGMT | | 2159 | struct ieee80211_vif *vif, |
1899 | IEEE80211_STYPE_PROBE_RESP); | 2160 | struct ieee80211_bss_conf *bss_conf, |
2161 | u32 changed) | ||
2162 | { | ||
2163 | int ret = 0; | ||
1900 | 2164 | ||
1901 | ret = wl1271_cmd_template_set(wl, | 2165 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
1902 | CMD_TEMPL_PROBE_RESPONSE, | 2166 | u32 rates = bss_conf->basic_rates; |
1903 | beacon->data, | 2167 | struct conf_tx_rate_class mgmt_rc; |
1904 | beacon->len, 0, | 2168 | |
1905 | wl1271_min_rate_get(wl)); | 2169 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
1906 | dev_kfree_skb(beacon); | 2170 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1907 | if (ret < 0) | 2171 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", |
1908 | goto out_sleep; | 2172 | wl->basic_rate_set); |
2173 | |||
2174 | /* update the AP management rate policy with the new rates */ | ||
2175 | mgmt_rc.enabled_rates = wl->basic_rate_set; | ||
2176 | mgmt_rc.long_retry_limit = 10; | ||
2177 | mgmt_rc.short_retry_limit = 10; | ||
2178 | mgmt_rc.aflags = 0; | ||
2179 | ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, | ||
2180 | ACX_TX_AP_MODE_MGMT_RATE); | ||
2181 | if (ret < 0) { | ||
2182 | wl1271_error("AP mgmt policy change failed %d", ret); | ||
2183 | goto out; | ||
2184 | } | ||
2185 | } | ||
1909 | 2186 | ||
1910 | /* Need to update the SSID (for filtering etc) */ | 2187 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
1911 | do_join = true; | 2188 | if (ret < 0) |
2189 | goto out; | ||
2190 | |||
2191 | if ((changed & BSS_CHANGED_BEACON_ENABLED)) { | ||
2192 | if (bss_conf->enable_beacon) { | ||
2193 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
2194 | ret = wl1271_cmd_start_bss(wl); | ||
2195 | if (ret < 0) | ||
2196 | goto out; | ||
2197 | |||
2198 | set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | ||
2199 | wl1271_debug(DEBUG_AP, "started AP"); | ||
2200 | |||
2201 | ret = wl1271_ap_init_hwenc(wl); | ||
2202 | if (ret < 0) | ||
2203 | goto out; | ||
2204 | } | ||
2205 | } else { | ||
2206 | if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
2207 | ret = wl1271_cmd_stop_bss(wl); | ||
2208 | if (ret < 0) | ||
2209 | goto out; | ||
2210 | |||
2211 | clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | ||
2212 | wl1271_debug(DEBUG_AP, "stopped AP"); | ||
2213 | } | ||
1912 | } | 2214 | } |
1913 | } | 2215 | } |
1914 | 2216 | ||
1915 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | 2217 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
1916 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2218 | if (ret < 0) |
2219 | goto out; | ||
2220 | out: | ||
2221 | return; | ||
2222 | } | ||
2223 | |||
2224 | /* STA/IBSS mode changes */ | ||
2225 | static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | ||
2226 | struct ieee80211_vif *vif, | ||
2227 | struct ieee80211_bss_conf *bss_conf, | ||
2228 | u32 changed) | ||
2229 | { | ||
2230 | bool do_join = false, set_assoc = false; | ||
2231 | bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); | ||
2232 | int ret; | ||
2233 | struct ieee80211_sta *sta; | ||
2234 | |||
2235 | if (is_ibss) { | ||
2236 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, | ||
2237 | changed); | ||
2238 | if (ret < 0) | ||
2239 | goto out; | ||
2240 | } | ||
2241 | |||
2242 | if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss) | ||
2243 | do_join = true; | ||
2244 | |||
2245 | /* Need to update the SSID (for filtering etc) */ | ||
2246 | if ((changed & BSS_CHANGED_BEACON) && is_ibss) | ||
2247 | do_join = true; | ||
2248 | |||
2249 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) { | ||
1917 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | 2250 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", |
1918 | bss_conf->enable_beacon ? "enabled" : "disabled"); | 2251 | bss_conf->enable_beacon ? "enabled" : "disabled"); |
1919 | 2252 | ||
@@ -1924,7 +2257,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1924 | do_join = true; | 2257 | do_join = true; |
1925 | } | 2258 | } |
1926 | 2259 | ||
1927 | if (changed & BSS_CHANGED_CQM) { | 2260 | if ((changed & BSS_CHANGED_CQM)) { |
1928 | bool enable = false; | 2261 | bool enable = false; |
1929 | if (bss_conf->cqm_rssi_thold) | 2262 | if (bss_conf->cqm_rssi_thold) |
1930 | enable = true; | 2263 | enable = true; |
@@ -1942,24 +2275,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1942 | * and enable the BSSID filter | 2275 | * and enable the BSSID filter |
1943 | */ | 2276 | */ |
1944 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 2277 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1945 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 2278 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1946 | 2279 | ||
2280 | if (!is_zero_ether_addr(wl->bssid)) { | ||
1947 | ret = wl1271_cmd_build_null_data(wl); | 2281 | ret = wl1271_cmd_build_null_data(wl); |
1948 | if (ret < 0) | 2282 | if (ret < 0) |
1949 | goto out_sleep; | 2283 | goto out; |
1950 | 2284 | ||
1951 | ret = wl1271_build_qos_null_data(wl); | 2285 | ret = wl1271_build_qos_null_data(wl); |
1952 | if (ret < 0) | 2286 | if (ret < 0) |
1953 | goto out_sleep; | 2287 | goto out; |
1954 | 2288 | ||
1955 | /* filter out all packets not from this BSSID */ | 2289 | /* filter out all packets not from this BSSID */ |
1956 | wl1271_configure_filters(wl, 0); | 2290 | wl1271_configure_filters(wl, 0); |
1957 | 2291 | ||
1958 | /* Need to update the BSSID (for filtering etc) */ | 2292 | /* Need to update the BSSID (for filtering etc) */ |
1959 | do_join = true; | 2293 | do_join = true; |
2294 | } | ||
1960 | } | 2295 | } |
1961 | 2296 | ||
1962 | if (changed & BSS_CHANGED_ASSOC) { | 2297 | if ((changed & BSS_CHANGED_ASSOC)) { |
1963 | if (bss_conf->assoc) { | 2298 | if (bss_conf->assoc) { |
1964 | u32 rates; | 2299 | u32 rates; |
1965 | int ieoffset; | 2300 | int ieoffset; |
@@ -1975,10 +2310,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1975 | rates = bss_conf->basic_rates; | 2310 | rates = bss_conf->basic_rates; |
1976 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | 2311 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, |
1977 | rates); | 2312 | rates); |
1978 | wl->basic_rate = wl1271_min_rate_get(wl); | 2313 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1979 | ret = wl1271_acx_rate_policies(wl); | 2314 | ret = wl1271_acx_sta_rate_policies(wl); |
1980 | if (ret < 0) | 2315 | if (ret < 0) |
1981 | goto out_sleep; | 2316 | goto out; |
1982 | 2317 | ||
1983 | /* | 2318 | /* |
1984 | * with wl1271, we don't need to update the | 2319 | * with wl1271, we don't need to update the |
@@ -1988,7 +2323,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1988 | */ | 2323 | */ |
1989 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); | 2324 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); |
1990 | if (ret < 0) | 2325 | if (ret < 0) |
1991 | goto out_sleep; | 2326 | goto out; |
1992 | 2327 | ||
1993 | /* | 2328 | /* |
1994 | * Get a template for hardware connection maintenance | 2329 | * Get a template for hardware connection maintenance |
@@ -2002,17 +2337,19 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2002 | /* enable the connection monitoring feature */ | 2337 | /* enable the connection monitoring feature */ |
2003 | ret = wl1271_acx_conn_monit_params(wl, true); | 2338 | ret = wl1271_acx_conn_monit_params(wl, true); |
2004 | if (ret < 0) | 2339 | if (ret < 0) |
2005 | goto out_sleep; | 2340 | goto out; |
2006 | 2341 | ||
2007 | /* If we want to go in PSM but we're not there yet */ | 2342 | /* If we want to go in PSM but we're not there yet */ |
2008 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 2343 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
2009 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 2344 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
2345 | enum wl1271_cmd_ps_mode mode; | ||
2346 | |||
2010 | mode = STATION_POWER_SAVE_MODE; | 2347 | mode = STATION_POWER_SAVE_MODE; |
2011 | ret = wl1271_ps_set_mode(wl, mode, | 2348 | ret = wl1271_ps_set_mode(wl, mode, |
2012 | wl->basic_rate, | 2349 | wl->basic_rate, |
2013 | true); | 2350 | true); |
2014 | if (ret < 0) | 2351 | if (ret < 0) |
2015 | goto out_sleep; | 2352 | goto out; |
2016 | } | 2353 | } |
2017 | } else { | 2354 | } else { |
2018 | /* use defaults when not associated */ | 2355 | /* use defaults when not associated */ |
@@ -2029,10 +2366,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2029 | 2366 | ||
2030 | /* revert back to minimum rates for the current band */ | 2367 | /* revert back to minimum rates for the current band */ |
2031 | wl1271_set_band_rate(wl); | 2368 | wl1271_set_band_rate(wl); |
2032 | wl->basic_rate = wl1271_min_rate_get(wl); | 2369 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2033 | ret = wl1271_acx_rate_policies(wl); | 2370 | ret = wl1271_acx_sta_rate_policies(wl); |
2034 | if (ret < 0) | 2371 | if (ret < 0) |
2035 | goto out_sleep; | 2372 | goto out; |
2036 | 2373 | ||
2037 | /* disable connection monitor features */ | 2374 | /* disable connection monitor features */ |
2038 | ret = wl1271_acx_conn_monit_params(wl, false); | 2375 | ret = wl1271_acx_conn_monit_params(wl, false); |
@@ -2040,74 +2377,54 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2040 | /* Disable the keep-alive feature */ | 2377 | /* Disable the keep-alive feature */ |
2041 | ret = wl1271_acx_keep_alive_mode(wl, false); | 2378 | ret = wl1271_acx_keep_alive_mode(wl, false); |
2042 | if (ret < 0) | 2379 | if (ret < 0) |
2043 | goto out_sleep; | 2380 | goto out; |
2044 | 2381 | ||
2045 | /* restore the bssid filter and go to dummy bssid */ | 2382 | /* restore the bssid filter and go to dummy bssid */ |
2046 | wl1271_unjoin(wl); | 2383 | wl1271_unjoin(wl); |
2047 | wl1271_dummy_join(wl); | 2384 | wl1271_dummy_join(wl); |
2048 | } | 2385 | } |
2049 | |||
2050 | } | ||
2051 | |||
2052 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
2053 | if (bss_conf->use_short_slot) | ||
2054 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | ||
2055 | else | ||
2056 | ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); | ||
2057 | if (ret < 0) { | ||
2058 | wl1271_warning("Set slot time failed %d", ret); | ||
2059 | goto out_sleep; | ||
2060 | } | ||
2061 | } | ||
2062 | |||
2063 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
2064 | if (bss_conf->use_short_preamble) | ||
2065 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | ||
2066 | else | ||
2067 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | ||
2068 | } | 2386 | } |
2069 | 2387 | ||
2070 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 2388 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2071 | if (bss_conf->use_cts_prot) | 2389 | if (ret < 0) |
2072 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); | 2390 | goto out; |
2073 | else | ||
2074 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); | ||
2075 | if (ret < 0) { | ||
2076 | wl1271_warning("Set ctsprotect failed %d", ret); | ||
2077 | goto out_sleep; | ||
2078 | } | ||
2079 | } | ||
2080 | 2391 | ||
2081 | /* | 2392 | rcu_read_lock(); |
2082 | * Takes care of: New association with HT enable, | 2393 | sta = ieee80211_find_sta(vif, bss_conf->bssid); |
2083 | * HT information change in beacon. | 2394 | if (sta) { |
2084 | */ | 2395 | /* handle new association with HT and HT information change */ |
2085 | if (sta && | 2396 | if ((changed & BSS_CHANGED_HT) && |
2086 | (changed & BSS_CHANGED_HT) && | 2397 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
2087 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 2398 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, |
2088 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true); | 2399 | true); |
2089 | if (ret < 0) { | 2400 | if (ret < 0) { |
2090 | wl1271_warning("Set ht cap true failed %d", ret); | 2401 | wl1271_warning("Set ht cap true failed %d", |
2091 | goto out_sleep; | 2402 | ret); |
2092 | } | 2403 | rcu_read_unlock(); |
2404 | goto out; | ||
2405 | } | ||
2093 | ret = wl1271_acx_set_ht_information(wl, | 2406 | ret = wl1271_acx_set_ht_information(wl, |
2094 | bss_conf->ht_operation_mode); | 2407 | bss_conf->ht_operation_mode); |
2095 | if (ret < 0) { | 2408 | if (ret < 0) { |
2096 | wl1271_warning("Set ht information failed %d", ret); | 2409 | wl1271_warning("Set ht information failed %d", |
2097 | goto out_sleep; | 2410 | ret); |
2411 | rcu_read_unlock(); | ||
2412 | goto out; | ||
2413 | } | ||
2098 | } | 2414 | } |
2099 | } | 2415 | /* handle new association without HT and disassociation */ |
2100 | /* | 2416 | else if (changed & BSS_CHANGED_ASSOC) { |
2101 | * Takes care of: New association without HT, | 2417 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, |
2102 | * Disassociation. | 2418 | false); |
2103 | */ | 2419 | if (ret < 0) { |
2104 | else if (sta && (changed & BSS_CHANGED_ASSOC)) { | 2420 | wl1271_warning("Set ht cap false failed %d", |
2105 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false); | 2421 | ret); |
2106 | if (ret < 0) { | 2422 | rcu_read_unlock(); |
2107 | wl1271_warning("Set ht cap false failed %d", ret); | 2423 | goto out; |
2108 | goto out_sleep; | 2424 | } |
2109 | } | 2425 | } |
2110 | } | 2426 | } |
2427 | rcu_read_unlock(); | ||
2111 | 2428 | ||
2112 | if (changed & BSS_CHANGED_ARP_FILTER) { | 2429 | if (changed & BSS_CHANGED_ARP_FILTER) { |
2113 | __be32 addr = bss_conf->arp_addr_list[0]; | 2430 | __be32 addr = bss_conf->arp_addr_list[0]; |
@@ -2124,76 +2441,128 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2124 | ret = wl1271_cmd_build_arp_rsp(wl, addr); | 2441 | ret = wl1271_cmd_build_arp_rsp(wl, addr); |
2125 | if (ret < 0) { | 2442 | if (ret < 0) { |
2126 | wl1271_warning("build arp rsp failed: %d", ret); | 2443 | wl1271_warning("build arp rsp failed: %d", ret); |
2127 | goto out_sleep; | 2444 | goto out; |
2128 | } | 2445 | } |
2129 | 2446 | ||
2130 | ret = wl1271_acx_arp_ip_filter(wl, | 2447 | ret = wl1271_acx_arp_ip_filter(wl, |
2131 | (ACX_ARP_FILTER_ARP_FILTERING | | 2448 | ACX_ARP_FILTER_ARP_FILTERING, |
2132 | ACX_ARP_FILTER_AUTO_ARP), | ||
2133 | addr); | 2449 | addr); |
2134 | } else | 2450 | } else |
2135 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); | 2451 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); |
2136 | 2452 | ||
2137 | if (ret < 0) | 2453 | if (ret < 0) |
2138 | goto out_sleep; | 2454 | goto out; |
2139 | } | 2455 | } |
2140 | 2456 | ||
2141 | if (do_join) { | 2457 | if (do_join) { |
2142 | ret = wl1271_join(wl, set_assoc); | 2458 | ret = wl1271_join(wl, set_assoc); |
2143 | if (ret < 0) { | 2459 | if (ret < 0) { |
2144 | wl1271_warning("cmd join failed %d", ret); | 2460 | wl1271_warning("cmd join failed %d", ret); |
2145 | goto out_sleep; | 2461 | goto out; |
2146 | } | 2462 | } |
2147 | } | 2463 | } |
2148 | 2464 | ||
2149 | out_sleep: | ||
2150 | wl1271_ps_elp_sleep(wl); | ||
2151 | |||
2152 | out: | 2465 | out: |
2153 | mutex_unlock(&wl->mutex); | 2466 | return; |
2154 | } | 2467 | } |
2155 | 2468 | ||
2156 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2469 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
2157 | const struct ieee80211_tx_queue_params *params) | 2470 | struct ieee80211_vif *vif, |
2471 | struct ieee80211_bss_conf *bss_conf, | ||
2472 | u32 changed) | ||
2158 | { | 2473 | { |
2159 | struct wl1271 *wl = hw->priv; | 2474 | struct wl1271 *wl = hw->priv; |
2160 | u8 ps_scheme; | 2475 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
2161 | int ret; | 2476 | int ret; |
2162 | 2477 | ||
2163 | mutex_lock(&wl->mutex); | 2478 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", |
2479 | (int)changed); | ||
2164 | 2480 | ||
2165 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | 2481 | mutex_lock(&wl->mutex); |
2166 | 2482 | ||
2167 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 2483 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
2168 | ret = -EAGAIN; | ||
2169 | goto out; | 2484 | goto out; |
2170 | } | ||
2171 | 2485 | ||
2172 | ret = wl1271_ps_elp_wakeup(wl, false); | 2486 | ret = wl1271_ps_elp_wakeup(wl, false); |
2173 | if (ret < 0) | 2487 | if (ret < 0) |
2174 | goto out; | 2488 | goto out; |
2175 | 2489 | ||
2176 | /* the txop is confed in units of 32us by the mac80211, we need us */ | 2490 | if (is_ap) |
2177 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 2491 | wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed); |
2178 | params->cw_min, params->cw_max, | 2492 | else |
2179 | params->aifs, params->txop << 5); | 2493 | wl1271_bss_info_changed_sta(wl, vif, bss_conf, changed); |
2180 | if (ret < 0) | 2494 | |
2181 | goto out_sleep; | 2495 | wl1271_ps_elp_sleep(wl); |
2496 | |||
2497 | out: | ||
2498 | mutex_unlock(&wl->mutex); | ||
2499 | } | ||
2500 | |||
2501 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
2502 | const struct ieee80211_tx_queue_params *params) | ||
2503 | { | ||
2504 | struct wl1271 *wl = hw->priv; | ||
2505 | u8 ps_scheme; | ||
2506 | int ret = 0; | ||
2507 | |||
2508 | mutex_lock(&wl->mutex); | ||
2509 | |||
2510 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
2182 | 2511 | ||
2183 | if (params->uapsd) | 2512 | if (params->uapsd) |
2184 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | 2513 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; |
2185 | else | 2514 | else |
2186 | ps_scheme = CONF_PS_SCHEME_LEGACY; | 2515 | ps_scheme = CONF_PS_SCHEME_LEGACY; |
2187 | 2516 | ||
2188 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 2517 | if (wl->state == WL1271_STATE_OFF) { |
2189 | CONF_CHANNEL_TYPE_EDCF, | 2518 | /* |
2190 | wl1271_tx_get_queue(queue), | 2519 | * If the state is off, the parameters will be recorded and |
2191 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); | 2520 | * configured on init. This happens in AP-mode. |
2192 | if (ret < 0) | 2521 | */ |
2193 | goto out_sleep; | 2522 | struct conf_tx_ac_category *conf_ac = |
2523 | &wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)]; | ||
2524 | struct conf_tx_tid *conf_tid = | ||
2525 | &wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)]; | ||
2526 | |||
2527 | conf_ac->ac = wl1271_tx_get_queue(queue); | ||
2528 | conf_ac->cw_min = (u8)params->cw_min; | ||
2529 | conf_ac->cw_max = params->cw_max; | ||
2530 | conf_ac->aifsn = params->aifs; | ||
2531 | conf_ac->tx_op_limit = params->txop << 5; | ||
2532 | |||
2533 | conf_tid->queue_id = wl1271_tx_get_queue(queue); | ||
2534 | conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF; | ||
2535 | conf_tid->tsid = wl1271_tx_get_queue(queue); | ||
2536 | conf_tid->ps_scheme = ps_scheme; | ||
2537 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; | ||
2538 | conf_tid->apsd_conf[0] = 0; | ||
2539 | conf_tid->apsd_conf[1] = 0; | ||
2540 | } else { | ||
2541 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2542 | if (ret < 0) | ||
2543 | goto out; | ||
2544 | |||
2545 | /* | ||
2546 | * the txop is confed in units of 32us by the mac80211, | ||
2547 | * we need us | ||
2548 | */ | ||
2549 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
2550 | params->cw_min, params->cw_max, | ||
2551 | params->aifs, params->txop << 5); | ||
2552 | if (ret < 0) | ||
2553 | goto out_sleep; | ||
2554 | |||
2555 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
2556 | CONF_CHANNEL_TYPE_EDCF, | ||
2557 | wl1271_tx_get_queue(queue), | ||
2558 | ps_scheme, CONF_ACK_POLICY_LEGACY, | ||
2559 | 0, 0); | ||
2560 | if (ret < 0) | ||
2561 | goto out_sleep; | ||
2194 | 2562 | ||
2195 | out_sleep: | 2563 | out_sleep: |
2196 | wl1271_ps_elp_sleep(wl); | 2564 | wl1271_ps_elp_sleep(wl); |
2565 | } | ||
2197 | 2566 | ||
2198 | out: | 2567 | out: |
2199 | mutex_unlock(&wl->mutex); | 2568 | mutex_unlock(&wl->mutex); |
@@ -2247,6 +2616,173 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | |||
2247 | return 0; | 2616 | return 0; |
2248 | } | 2617 | } |
2249 | 2618 | ||
2619 | static int wl1271_allocate_hlid(struct wl1271 *wl, | ||
2620 | struct ieee80211_sta *sta, | ||
2621 | u8 *hlid) | ||
2622 | { | ||
2623 | struct wl1271_station *wl_sta; | ||
2624 | int id; | ||
2625 | |||
2626 | id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); | ||
2627 | if (id >= AP_MAX_STATIONS) { | ||
2628 | wl1271_warning("could not allocate HLID - too much stations"); | ||
2629 | return -EBUSY; | ||
2630 | } | ||
2631 | |||
2632 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
2633 | |||
2634 | __set_bit(id, wl->ap_hlid_map); | ||
2635 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; | ||
2636 | *hlid = wl_sta->hlid; | ||
2637 | return 0; | ||
2638 | } | ||
2639 | |||
2640 | static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid) | ||
2641 | { | ||
2642 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
2643 | |||
2644 | __clear_bit(id, wl->ap_hlid_map); | ||
2645 | } | ||
2646 | |||
2647 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | ||
2648 | struct ieee80211_vif *vif, | ||
2649 | struct ieee80211_sta *sta) | ||
2650 | { | ||
2651 | struct wl1271 *wl = hw->priv; | ||
2652 | int ret = 0; | ||
2653 | u8 hlid; | ||
2654 | |||
2655 | mutex_lock(&wl->mutex); | ||
2656 | |||
2657 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2658 | goto out; | ||
2659 | |||
2660 | if (wl->bss_type != BSS_TYPE_AP_BSS) | ||
2661 | goto out; | ||
2662 | |||
2663 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); | ||
2664 | |||
2665 | ret = wl1271_allocate_hlid(wl, sta, &hlid); | ||
2666 | if (ret < 0) | ||
2667 | goto out; | ||
2668 | |||
2669 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2670 | if (ret < 0) | ||
2671 | goto out; | ||
2672 | |||
2673 | ret = wl1271_cmd_add_sta(wl, sta, hlid); | ||
2674 | if (ret < 0) | ||
2675 | goto out_sleep; | ||
2676 | |||
2677 | out_sleep: | ||
2678 | wl1271_ps_elp_sleep(wl); | ||
2679 | |||
2680 | out: | ||
2681 | mutex_unlock(&wl->mutex); | ||
2682 | return ret; | ||
2683 | } | ||
2684 | |||
2685 | static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | ||
2686 | struct ieee80211_vif *vif, | ||
2687 | struct ieee80211_sta *sta) | ||
2688 | { | ||
2689 | struct wl1271 *wl = hw->priv; | ||
2690 | struct wl1271_station *wl_sta; | ||
2691 | int ret = 0, id; | ||
2692 | |||
2693 | mutex_lock(&wl->mutex); | ||
2694 | |||
2695 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2696 | goto out; | ||
2697 | |||
2698 | if (wl->bss_type != BSS_TYPE_AP_BSS) | ||
2699 | goto out; | ||
2700 | |||
2701 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); | ||
2702 | |||
2703 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
2704 | id = wl_sta->hlid - WL1271_AP_STA_HLID_START; | ||
2705 | if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) | ||
2706 | goto out; | ||
2707 | |||
2708 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2709 | if (ret < 0) | ||
2710 | goto out; | ||
2711 | |||
2712 | ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid); | ||
2713 | if (ret < 0) | ||
2714 | goto out_sleep; | ||
2715 | |||
2716 | wl1271_free_hlid(wl, wl_sta->hlid); | ||
2717 | |||
2718 | out_sleep: | ||
2719 | wl1271_ps_elp_sleep(wl); | ||
2720 | |||
2721 | out: | ||
2722 | mutex_unlock(&wl->mutex); | ||
2723 | return ret; | ||
2724 | } | ||
2725 | |||
2726 | int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2727 | enum ieee80211_ampdu_mlme_action action, | ||
2728 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
2729 | u8 buf_size) | ||
2730 | { | ||
2731 | struct wl1271 *wl = hw->priv; | ||
2732 | int ret; | ||
2733 | |||
2734 | mutex_lock(&wl->mutex); | ||
2735 | |||
2736 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | ||
2737 | ret = -EAGAIN; | ||
2738 | goto out; | ||
2739 | } | ||
2740 | |||
2741 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2742 | if (ret < 0) | ||
2743 | goto out; | ||
2744 | |||
2745 | switch (action) { | ||
2746 | case IEEE80211_AMPDU_RX_START: | ||
2747 | if (wl->ba_support) { | ||
2748 | ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn, | ||
2749 | true); | ||
2750 | if (!ret) | ||
2751 | wl->ba_rx_bitmap |= BIT(tid); | ||
2752 | } else { | ||
2753 | ret = -ENOTSUPP; | ||
2754 | } | ||
2755 | break; | ||
2756 | |||
2757 | case IEEE80211_AMPDU_RX_STOP: | ||
2758 | ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false); | ||
2759 | if (!ret) | ||
2760 | wl->ba_rx_bitmap &= ~BIT(tid); | ||
2761 | break; | ||
2762 | |||
2763 | /* | ||
2764 | * The BA initiator session management in FW independently. | ||
2765 | * Falling break here on purpose for all TX APDU commands. | ||
2766 | */ | ||
2767 | case IEEE80211_AMPDU_TX_START: | ||
2768 | case IEEE80211_AMPDU_TX_STOP: | ||
2769 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2770 | ret = -EINVAL; | ||
2771 | break; | ||
2772 | |||
2773 | default: | ||
2774 | wl1271_error("Incorrect ampdu action id=%x\n", action); | ||
2775 | ret = -EINVAL; | ||
2776 | } | ||
2777 | |||
2778 | wl1271_ps_elp_sleep(wl); | ||
2779 | |||
2780 | out: | ||
2781 | mutex_unlock(&wl->mutex); | ||
2782 | |||
2783 | return ret; | ||
2784 | } | ||
2785 | |||
2250 | /* can't be const, mac80211 writes to this */ | 2786 | /* can't be const, mac80211 writes to this */ |
2251 | static struct ieee80211_rate wl1271_rates[] = { | 2787 | static struct ieee80211_rate wl1271_rates[] = { |
2252 | { .bitrate = 10, | 2788 | { .bitrate = 10, |
@@ -2305,6 +2841,7 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
2305 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | 2841 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
2306 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | 2842 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
2307 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 2843 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
2844 | { .hw_value = 14, .center_freq = 2484, .max_power = 25 }, | ||
2308 | }; | 2845 | }; |
2309 | 2846 | ||
2310 | /* mapping to indexes for wl1271_rates */ | 2847 | /* mapping to indexes for wl1271_rates */ |
@@ -2493,6 +3030,9 @@ static const struct ieee80211_ops wl1271_ops = { | |||
2493 | .conf_tx = wl1271_op_conf_tx, | 3030 | .conf_tx = wl1271_op_conf_tx, |
2494 | .get_tsf = wl1271_op_get_tsf, | 3031 | .get_tsf = wl1271_op_get_tsf, |
2495 | .get_survey = wl1271_op_get_survey, | 3032 | .get_survey = wl1271_op_get_survey, |
3033 | .sta_add = wl1271_op_sta_add, | ||
3034 | .sta_remove = wl1271_op_sta_remove, | ||
3035 | .ampdu_action = wl1271_op_ampdu_action, | ||
2496 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3036 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
2497 | }; | 3037 | }; |
2498 | 3038 | ||
@@ -2607,6 +3147,18 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
2607 | if (wl->mac80211_registered) | 3147 | if (wl->mac80211_registered) |
2608 | return 0; | 3148 | return 0; |
2609 | 3149 | ||
3150 | ret = wl1271_fetch_nvs(wl); | ||
3151 | if (ret == 0) { | ||
3152 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
3153 | |||
3154 | wl->mac_addr[0] = nvs_ptr[11]; | ||
3155 | wl->mac_addr[1] = nvs_ptr[10]; | ||
3156 | wl->mac_addr[2] = nvs_ptr[6]; | ||
3157 | wl->mac_addr[3] = nvs_ptr[5]; | ||
3158 | wl->mac_addr[4] = nvs_ptr[4]; | ||
3159 | wl->mac_addr[5] = nvs_ptr[3]; | ||
3160 | } | ||
3161 | |||
2610 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 3162 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
2611 | 3163 | ||
2612 | ret = ieee80211_register_hw(wl->hw); | 3164 | ret = ieee80211_register_hw(wl->hw); |
@@ -2629,6 +3181,9 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw); | |||
2629 | 3181 | ||
2630 | void wl1271_unregister_hw(struct wl1271 *wl) | 3182 | void wl1271_unregister_hw(struct wl1271 *wl) |
2631 | { | 3183 | { |
3184 | if (wl->state == WL1271_STATE_PLT) | ||
3185 | __wl1271_plt_stop(wl); | ||
3186 | |||
2632 | unregister_netdevice_notifier(&wl1271_dev_notifier); | 3187 | unregister_netdevice_notifier(&wl1271_dev_notifier); |
2633 | ieee80211_unregister_hw(wl->hw); | 3188 | ieee80211_unregister_hw(wl->hw); |
2634 | wl->mac80211_registered = false; | 3189 | wl->mac80211_registered = false; |
@@ -2667,7 +3222,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2667 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 3222 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
2668 | 3223 | ||
2669 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 3224 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2670 | BIT(NL80211_IFTYPE_ADHOC); | 3225 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); |
2671 | wl->hw->wiphy->max_scan_ssids = 1; | 3226 | wl->hw->wiphy->max_scan_ssids = 1; |
2672 | /* | 3227 | /* |
2673 | * Maximum length of elements in scanning probe request templates | 3228 | * Maximum length of elements in scanning probe request templates |
@@ -2676,8 +3231,20 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2676 | */ | 3231 | */ |
2677 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 3232 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
2678 | sizeof(struct ieee80211_header); | 3233 | sizeof(struct ieee80211_header); |
2679 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 3234 | |
2680 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 3235 | /* |
3236 | * We keep local copies of the band structs because we need to | ||
3237 | * modify them on a per-device basis. | ||
3238 | */ | ||
3239 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, | ||
3240 | sizeof(wl1271_band_2ghz)); | ||
3241 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, | ||
3242 | sizeof(wl1271_band_5ghz)); | ||
3243 | |||
3244 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
3245 | &wl->bands[IEEE80211_BAND_2GHZ]; | ||
3246 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
3247 | &wl->bands[IEEE80211_BAND_5GHZ]; | ||
2681 | 3248 | ||
2682 | wl->hw->queues = 4; | 3249 | wl->hw->queues = 4; |
2683 | wl->hw->max_rates = 1; | 3250 | wl->hw->max_rates = 1; |
@@ -2686,6 +3253,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2686 | 3253 | ||
2687 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 3254 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2688 | 3255 | ||
3256 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | ||
3257 | |||
3258 | wl->hw->max_rx_aggregation_subframes = 8; | ||
3259 | |||
2689 | return 0; | 3260 | return 0; |
2690 | } | 3261 | } |
2691 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | 3262 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); |
@@ -2735,8 +3306,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2735 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 3306 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
2736 | wl->default_key = 0; | 3307 | wl->default_key = 0; |
2737 | wl->rx_counter = 0; | 3308 | wl->rx_counter = 0; |
2738 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 3309 | wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; |
2739 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 3310 | wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; |
2740 | wl->psm_entry_retry = 0; | 3311 | wl->psm_entry_retry = 0; |
2741 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 3312 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2742 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 3313 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
@@ -2748,6 +3319,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2748 | wl->flags = 0; | 3319 | wl->flags = 0; |
2749 | wl->sg_enabled = true; | 3320 | wl->sg_enabled = true; |
2750 | wl->hw_pg_ver = -1; | 3321 | wl->hw_pg_ver = -1; |
3322 | wl->bss_type = MAX_BSS_TYPE; | ||
3323 | wl->set_bss_type = MAX_BSS_TYPE; | ||
3324 | wl->fw_bss_type = MAX_BSS_TYPE; | ||
2751 | 3325 | ||
2752 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3326 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
2753 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3327 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
@@ -2837,9 +3411,9 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2837 | } | 3411 | } |
2838 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | 3412 | EXPORT_SYMBOL_GPL(wl1271_free_hw); |
2839 | 3413 | ||
2840 | u32 wl12xx_debug_level; | 3414 | u32 wl12xx_debug_level = DEBUG_NONE; |
2841 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); | 3415 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); |
2842 | module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE); | 3416 | module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); |
2843 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); | 3417 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); |
2844 | 3418 | ||
2845 | MODULE_LICENSE("GPL"); | 3419 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index ec8d843d41cf..b0c6ddc2a945 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -198,6 +198,16 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
198 | pkt_offset += pkt_length; | 198 | pkt_offset += pkt_length; |
199 | } | 199 | } |
200 | } | 200 | } |
201 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, | 201 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); |
202 | cpu_to_le32(wl->rx_counter)); | 202 | } |
203 | |||
204 | void wl1271_set_default_filters(struct wl1271 *wl) | ||
205 | { | ||
206 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | ||
207 | wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG; | ||
208 | wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER; | ||
209 | } else { | ||
210 | wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; | ||
211 | wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; | ||
212 | } | ||
203 | } | 213 | } |
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index 3abb26fe0364..8d048b36bbba 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h | |||
@@ -86,8 +86,9 @@ | |||
86 | /* | 86 | /* |
87 | * RX Descriptor status | 87 | * RX Descriptor status |
88 | * | 88 | * |
89 | * Bits 0-2 - status | 89 | * Bits 0-2 - error code |
90 | * Bits 3-7 - reserved | 90 | * Bits 3-5 - process_id tag (AP mode FW) |
91 | * Bits 6-7 - reserved | ||
91 | */ | 92 | */ |
92 | #define WL1271_RX_DESC_STATUS_MASK 0x07 | 93 | #define WL1271_RX_DESC_STATUS_MASK 0x07 |
93 | 94 | ||
@@ -110,12 +111,16 @@ struct wl1271_rx_descriptor { | |||
110 | u8 snr; | 111 | u8 snr; |
111 | __le32 timestamp; | 112 | __le32 timestamp; |
112 | u8 packet_class; | 113 | u8 packet_class; |
113 | u8 process_id; | 114 | union { |
115 | u8 process_id; /* STA FW */ | ||
116 | u8 hlid; /* AP FW */ | ||
117 | } __packed; | ||
114 | u8 pad_len; | 118 | u8 pad_len; |
115 | u8 reserved; | 119 | u8 reserved; |
116 | } __packed; | 120 | } __packed; |
117 | 121 | ||
118 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); | 122 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); |
119 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 123 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
124 | void wl1271_set_default_filters(struct wl1271 *wl); | ||
120 | 125 | ||
121 | #endif | 126 | #endif |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 93cbb8d5aba9..d5e874825069 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -345,3 +345,4 @@ MODULE_LICENSE("GPL"); | |||
345 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 345 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
346 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 346 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
347 | MODULE_FIRMWARE(WL1271_FW_NAME); | 347 | MODULE_FIRMWARE(WL1271_FW_NAME); |
348 | MODULE_FIRMWARE(WL1271_AP_FW_NAME); | ||
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 46714910f98c..0132dad756c4 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c | |||
@@ -110,9 +110,9 @@ static void wl1271_spi_reset(struct wl1271 *wl) | |||
110 | spi_message_add_tail(&t, &m); | 110 | spi_message_add_tail(&t, &m); |
111 | 111 | ||
112 | spi_sync(wl_to_spi(wl), &m); | 112 | spi_sync(wl_to_spi(wl), &m); |
113 | kfree(cmd); | ||
114 | 113 | ||
115 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 114 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
115 | kfree(cmd); | ||
116 | } | 116 | } |
117 | 117 | ||
118 | static void wl1271_spi_init(struct wl1271 *wl) | 118 | static void wl1271_spi_init(struct wl1271 *wl) |
@@ -495,4 +495,5 @@ MODULE_LICENSE("GPL"); | |||
495 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 495 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
496 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 496 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
497 | MODULE_FIRMWARE(WL1271_FW_NAME); | 497 | MODULE_FIRMWARE(WL1271_FW_NAME); |
498 | MODULE_FIRMWARE(WL1271_AP_FW_NAME); | ||
498 | MODULE_ALIAS("spi:wl1271"); | 499 | MODULE_ALIAS("spi:wl1271"); |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index b44c75cd8c1e..3507c81c7500 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/etherdevice.h> | ||
26 | 27 | ||
27 | #include "wl12xx.h" | 28 | #include "wl12xx.h" |
28 | #include "io.h" | 29 | #include "io.h" |
@@ -30,6 +31,23 @@ | |||
30 | #include "ps.h" | 31 | #include "ps.h" |
31 | #include "tx.h" | 32 | #include "tx.h" |
32 | 33 | ||
34 | static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) | ||
35 | { | ||
36 | int ret; | ||
37 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
38 | |||
39 | if (is_ap) | ||
40 | ret = wl1271_cmd_set_ap_default_wep_key(wl, id); | ||
41 | else | ||
42 | ret = wl1271_cmd_set_sta_default_wep_key(wl, id); | ||
43 | |||
44 | if (ret < 0) | ||
45 | return ret; | ||
46 | |||
47 | wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
33 | static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | 51 | static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) |
34 | { | 52 | { |
35 | int id; | 53 | int id; |
@@ -99,7 +117,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
99 | { | 117 | { |
100 | struct timespec ts; | 118 | struct timespec ts; |
101 | struct wl1271_tx_hw_descr *desc; | 119 | struct wl1271_tx_hw_descr *desc; |
102 | int pad, ac; | 120 | int pad, ac, rate_idx; |
103 | s64 hosttime; | 121 | s64 hosttime; |
104 | u16 tx_attr; | 122 | u16 tx_attr; |
105 | 123 | ||
@@ -117,7 +135,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
117 | getnstimeofday(&ts); | 135 | getnstimeofday(&ts); |
118 | hosttime = (timespec_to_ns(&ts) >> 10); | 136 | hosttime = (timespec_to_ns(&ts) >> 10); |
119 | desc->start_time = cpu_to_le32(hosttime - wl->time_offset); | 137 | desc->start_time = cpu_to_le32(hosttime - wl->time_offset); |
120 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); | 138 | |
139 | if (wl->bss_type != BSS_TYPE_AP_BSS) | ||
140 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); | ||
141 | else | ||
142 | desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); | ||
121 | 143 | ||
122 | /* configure the tx attributes */ | 144 | /* configure the tx attributes */ |
123 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 145 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
@@ -125,7 +147,41 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
125 | /* queue (we use same identifiers for tid's and ac's */ | 147 | /* queue (we use same identifiers for tid's and ac's */ |
126 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 148 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
127 | desc->tid = ac; | 149 | desc->tid = ac; |
128 | desc->aid = TX_HW_DEFAULT_AID; | 150 | |
151 | if (wl->bss_type != BSS_TYPE_AP_BSS) { | ||
152 | desc->aid = TX_HW_DEFAULT_AID; | ||
153 | |||
154 | /* if the packets are destined for AP (have a STA entry) | ||
155 | send them with AP rate policies, otherwise use default | ||
156 | basic rates */ | ||
157 | if (control->control.sta) | ||
158 | rate_idx = ACX_TX_AP_FULL_RATE; | ||
159 | else | ||
160 | rate_idx = ACX_TX_BASIC_RATE; | ||
161 | } else { | ||
162 | if (control->control.sta) { | ||
163 | struct wl1271_station *wl_sta; | ||
164 | |||
165 | wl_sta = (struct wl1271_station *) | ||
166 | control->control.sta->drv_priv; | ||
167 | desc->hlid = wl_sta->hlid; | ||
168 | rate_idx = ac; | ||
169 | } else { | ||
170 | struct ieee80211_hdr *hdr; | ||
171 | |||
172 | hdr = (struct ieee80211_hdr *) | ||
173 | (skb->data + sizeof(*desc)); | ||
174 | if (ieee80211_is_mgmt(hdr->frame_control)) { | ||
175 | desc->hlid = WL1271_AP_GLOBAL_HLID; | ||
176 | rate_idx = ACX_TX_AP_MODE_MGMT_RATE; | ||
177 | } else { | ||
178 | desc->hlid = WL1271_AP_BROADCAST_HLID; | ||
179 | rate_idx = ACX_TX_AP_MODE_BCST_RATE; | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; | ||
129 | desc->reserved = 0; | 185 | desc->reserved = 0; |
130 | 186 | ||
131 | /* align the length (and store in terms of words) */ | 187 | /* align the length (and store in terms of words) */ |
@@ -136,14 +192,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
136 | pad = pad - skb->len; | 192 | pad = pad - skb->len; |
137 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 193 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
138 | 194 | ||
139 | /* if the packets are destined for AP (have a STA entry) send them | ||
140 | with AP rate policies, otherwise use default basic rates */ | ||
141 | if (control->control.sta) | ||
142 | tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; | ||
143 | |||
144 | desc->tx_attr = cpu_to_le16(tx_attr); | 195 | desc->tx_attr = cpu_to_le16(tx_attr); |
145 | 196 | ||
146 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 197 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d " |
198 | "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid, | ||
199 | le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length), | ||
200 | le16_to_cpu(desc->life_time), desc->total_mem_blocks); | ||
147 | } | 201 | } |
148 | 202 | ||
149 | /* caller must hold wl->mutex */ | 203 | /* caller must hold wl->mutex */ |
@@ -153,7 +207,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
153 | struct ieee80211_tx_info *info; | 207 | struct ieee80211_tx_info *info; |
154 | u32 extra = 0; | 208 | u32 extra = 0; |
155 | int ret = 0; | 209 | int ret = 0; |
156 | u8 idx; | ||
157 | u32 total_len; | 210 | u32 total_len; |
158 | 211 | ||
159 | if (!skb) | 212 | if (!skb) |
@@ -166,11 +219,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, | |||
166 | extra = WL1271_TKIP_IV_SPACE; | 219 | extra = WL1271_TKIP_IV_SPACE; |
167 | 220 | ||
168 | if (info->control.hw_key) { | 221 | if (info->control.hw_key) { |
169 | idx = info->control.hw_key->hw_key_idx; | 222 | bool is_wep; |
223 | u8 idx = info->control.hw_key->hw_key_idx; | ||
224 | u32 cipher = info->control.hw_key->cipher; | ||
225 | |||
226 | is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || | ||
227 | (cipher == WLAN_CIPHER_SUITE_WEP104); | ||
170 | 228 | ||
171 | /* FIXME: do we have to do this if we're not using WEP? */ | 229 | if (unlikely(is_wep && wl->default_key != idx)) { |
172 | if (unlikely(wl->default_key != idx)) { | 230 | ret = wl1271_set_default_wep_key(wl, idx); |
173 | ret = wl1271_cmd_set_default_wep_key(wl, idx); | ||
174 | if (ret < 0) | 231 | if (ret < 0) |
175 | return ret; | 232 | return ret; |
176 | wl->default_key = idx; | 233 | wl->default_key = idx; |
@@ -303,7 +360,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
303 | woken_up = true; | 360 | woken_up = true; |
304 | 361 | ||
305 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | 362 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); |
306 | wl1271_acx_rate_policies(wl); | 363 | wl1271_acx_sta_rate_policies(wl); |
307 | } | 364 | } |
308 | 365 | ||
309 | while ((skb = wl1271_skb_dequeue(wl))) { | 366 | while ((skb = wl1271_skb_dequeue(wl))) { |
@@ -521,3 +578,21 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
521 | 578 | ||
522 | wl1271_warning("Unable to flush all TX buffers, timed out."); | 579 | wl1271_warning("Unable to flush all TX buffers, timed out."); |
523 | } | 580 | } |
581 | |||
582 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl) | ||
583 | { | ||
584 | int i; | ||
585 | u32 rate = 0; | ||
586 | |||
587 | if (!wl->basic_rate_set) { | ||
588 | WARN_ON(1); | ||
589 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
590 | } | ||
591 | |||
592 | for (i = 0; !rate; i++) { | ||
593 | if ((wl->basic_rate_set >> i) & 0x1) | ||
594 | rate = 1 << i; | ||
595 | } | ||
596 | |||
597 | return rate; | ||
598 | } | ||
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 903e5dc69b7a..05722a560d91 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define TX_HW_BLOCK_SIZE 252 | 29 | #define TX_HW_BLOCK_SIZE 252 |
30 | 30 | ||
31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 | 31 | #define TX_HW_MGMT_PKT_LIFETIME_TU 2000 |
32 | #define TX_HW_AP_MODE_PKT_LIFETIME_TU 8000 | ||
32 | /* The chipset reference driver states, that the "aid" value 1 | 33 | /* The chipset reference driver states, that the "aid" value 1 |
33 | * is for infra-BSS, but is still always used */ | 34 | * is for infra-BSS, but is still always used */ |
34 | #define TX_HW_DEFAULT_AID 1 | 35 | #define TX_HW_DEFAULT_AID 1 |
@@ -77,8 +78,12 @@ struct wl1271_tx_hw_descr { | |||
77 | u8 id; | 78 | u8 id; |
78 | /* The packet TID value (as User-Priority) */ | 79 | /* The packet TID value (as User-Priority) */ |
79 | u8 tid; | 80 | u8 tid; |
80 | /* Identifier of the remote STA in IBSS, 1 in infra-BSS */ | 81 | union { |
81 | u8 aid; | 82 | /* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */ |
83 | u8 aid; | ||
84 | /* AP - host link ID (HLID) */ | ||
85 | u8 hlid; | ||
86 | } __packed; | ||
82 | u8 reserved; | 87 | u8 reserved; |
83 | } __packed; | 88 | } __packed; |
84 | 89 | ||
@@ -146,5 +151,6 @@ void wl1271_tx_reset(struct wl1271 *wl); | |||
146 | void wl1271_tx_flush(struct wl1271 *wl); | 151 | void wl1271_tx_flush(struct wl1271 *wl); |
147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 152 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
148 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 153 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |
154 | u32 wl1271_tx_min_rate_get(struct wl1271 *wl); | ||
149 | 155 | ||
150 | #endif | 156 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 9050dd9b62d2..d1de13fe7d9a 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -38,6 +38,13 @@ | |||
38 | #define DRIVER_NAME "wl1271" | 38 | #define DRIVER_NAME "wl1271" |
39 | #define DRIVER_PREFIX DRIVER_NAME ": " | 39 | #define DRIVER_PREFIX DRIVER_NAME ": " |
40 | 40 | ||
41 | /* | ||
42 | * FW versions support BA 11n | ||
43 | * versions marks x.x.x.50-60.x | ||
44 | */ | ||
45 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50 | ||
46 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60 | ||
47 | |||
41 | enum { | 48 | enum { |
42 | DEBUG_NONE = 0, | 49 | DEBUG_NONE = 0, |
43 | DEBUG_IRQ = BIT(0), | 50 | DEBUG_IRQ = BIT(0), |
@@ -57,6 +64,8 @@ enum { | |||
57 | DEBUG_SDIO = BIT(14), | 64 | DEBUG_SDIO = BIT(14), |
58 | DEBUG_FILTERS = BIT(15), | 65 | DEBUG_FILTERS = BIT(15), |
59 | DEBUG_ADHOC = BIT(16), | 66 | DEBUG_ADHOC = BIT(16), |
67 | DEBUG_AP = BIT(17), | ||
68 | DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), | ||
60 | DEBUG_ALL = ~0, | 69 | DEBUG_ALL = ~0, |
61 | }; | 70 | }; |
62 | 71 | ||
@@ -103,16 +112,27 @@ extern u32 wl12xx_debug_level; | |||
103 | true); \ | 112 | true); \ |
104 | } while (0) | 113 | } while (0) |
105 | 114 | ||
106 | #define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ | 115 | #define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN | \ |
107 | CFG_BSSID_FILTER_EN | \ | 116 | CFG_BSSID_FILTER_EN | \ |
108 | CFG_MC_FILTER_EN) | 117 | CFG_MC_FILTER_EN) |
109 | 118 | ||
110 | #define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ | 119 | #define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ |
111 | CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ | 120 | CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ |
112 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 121 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
113 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 122 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
114 | 123 | ||
124 | #define WL1271_DEFAULT_AP_RX_CONFIG 0 | ||
125 | |||
126 | #define WL1271_DEFAULT_AP_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \ | ||
127 | CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ | ||
128 | CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \ | ||
129 | CFG_RX_ASSOC_EN) | ||
130 | |||
131 | |||
132 | |||
115 | #define WL1271_FW_NAME "wl1271-fw.bin" | 133 | #define WL1271_FW_NAME "wl1271-fw.bin" |
134 | #define WL1271_AP_FW_NAME "wl1271-fw-ap.bin" | ||
135 | |||
116 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 136 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
117 | 137 | ||
118 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) | 138 | #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff)) |
@@ -129,6 +149,14 @@ extern u32 wl12xx_debug_level; | |||
129 | #define WL1271_DEFAULT_BEACON_INT 100 | 149 | #define WL1271_DEFAULT_BEACON_INT 100 |
130 | #define WL1271_DEFAULT_DTIM_PERIOD 1 | 150 | #define WL1271_DEFAULT_DTIM_PERIOD 1 |
131 | 151 | ||
152 | #define WL1271_AP_GLOBAL_HLID 0 | ||
153 | #define WL1271_AP_BROADCAST_HLID 1 | ||
154 | #define WL1271_AP_STA_HLID_START 2 | ||
155 | |||
156 | #define WL1271_AP_BSS_INDEX 0 | ||
157 | #define WL1271_AP_DEF_INACTIV_SEC 300 | ||
158 | #define WL1271_AP_DEF_BEACON_EXP 20 | ||
159 | |||
132 | #define ACX_TX_DESCRIPTORS 32 | 160 | #define ACX_TX_DESCRIPTORS 32 |
133 | 161 | ||
134 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) | 162 | #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) |
@@ -161,10 +189,13 @@ struct wl1271_partition_set { | |||
161 | 189 | ||
162 | struct wl1271; | 190 | struct wl1271; |
163 | 191 | ||
192 | #define WL12XX_NUM_FW_VER 5 | ||
193 | |||
164 | /* FIXME: I'm not sure about this structure name */ | 194 | /* FIXME: I'm not sure about this structure name */ |
165 | struct wl1271_chip { | 195 | struct wl1271_chip { |
166 | u32 id; | 196 | u32 id; |
167 | char fw_ver[21]; | 197 | char fw_ver_str[ETHTOOL_BUSINFO_LEN]; |
198 | unsigned int fw_ver[WL12XX_NUM_FW_VER]; | ||
168 | }; | 199 | }; |
169 | 200 | ||
170 | struct wl1271_stats { | 201 | struct wl1271_stats { |
@@ -178,6 +209,11 @@ struct wl1271_stats { | |||
178 | #define NUM_TX_QUEUES 4 | 209 | #define NUM_TX_QUEUES 4 |
179 | #define NUM_RX_PKT_DESC 8 | 210 | #define NUM_RX_PKT_DESC 8 |
180 | 211 | ||
212 | #define AP_MAX_STATIONS 5 | ||
213 | |||
214 | /* Broadcast and Global links + links to stations */ | ||
215 | #define AP_MAX_LINKS (AP_MAX_STATIONS + 2) | ||
216 | |||
181 | /* FW status registers */ | 217 | /* FW status registers */ |
182 | struct wl1271_fw_status { | 218 | struct wl1271_fw_status { |
183 | __le32 intr; | 219 | __le32 intr; |
@@ -188,7 +224,18 @@ struct wl1271_fw_status { | |||
188 | __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; | 224 | __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; |
189 | __le32 tx_released_blks[NUM_TX_QUEUES]; | 225 | __le32 tx_released_blks[NUM_TX_QUEUES]; |
190 | __le32 fw_localtime; | 226 | __le32 fw_localtime; |
191 | __le32 padding[2]; | 227 | |
228 | /* Next fields valid only in AP FW */ | ||
229 | |||
230 | /* | ||
231 | * A bitmap (where each bit represents a single HLID) | ||
232 | * to indicate if the station is in PS mode. | ||
233 | */ | ||
234 | __le32 link_ps_bitmap; | ||
235 | |||
236 | /* Number of freed MBs per HLID */ | ||
237 | u8 tx_lnk_free_blks[AP_MAX_LINKS]; | ||
238 | u8 padding_1[1]; | ||
192 | } __packed; | 239 | } __packed; |
193 | 240 | ||
194 | struct wl1271_rx_mem_pool_addr { | 241 | struct wl1271_rx_mem_pool_addr { |
@@ -218,6 +265,19 @@ struct wl1271_if_operations { | |||
218 | void (*disable_irq)(struct wl1271 *wl); | 265 | void (*disable_irq)(struct wl1271 *wl); |
219 | }; | 266 | }; |
220 | 267 | ||
268 | #define MAX_NUM_KEYS 14 | ||
269 | #define MAX_KEY_SIZE 32 | ||
270 | |||
271 | struct wl1271_ap_key { | ||
272 | u8 id; | ||
273 | u8 key_type; | ||
274 | u8 key_size; | ||
275 | u8 key[MAX_KEY_SIZE]; | ||
276 | u8 hlid; | ||
277 | u32 tx_seq_32; | ||
278 | u16 tx_seq_16; | ||
279 | }; | ||
280 | |||
221 | struct wl1271 { | 281 | struct wl1271 { |
222 | struct platform_device *plat_dev; | 282 | struct platform_device *plat_dev; |
223 | struct ieee80211_hw *hw; | 283 | struct ieee80211_hw *hw; |
@@ -251,6 +311,7 @@ struct wl1271 { | |||
251 | #define WL1271_FLAG_PSPOLL_FAILURE (12) | 311 | #define WL1271_FLAG_PSPOLL_FAILURE (12) |
252 | #define WL1271_FLAG_STA_STATE_SENT (13) | 312 | #define WL1271_FLAG_STA_STATE_SENT (13) |
253 | #define WL1271_FLAG_FW_TX_BUSY (14) | 313 | #define WL1271_FLAG_FW_TX_BUSY (14) |
314 | #define WL1271_FLAG_AP_STARTED (15) | ||
254 | unsigned long flags; | 315 | unsigned long flags; |
255 | 316 | ||
256 | struct wl1271_partition_set part; | 317 | struct wl1271_partition_set part; |
@@ -262,6 +323,7 @@ struct wl1271 { | |||
262 | 323 | ||
263 | u8 *fw; | 324 | u8 *fw; |
264 | size_t fw_len; | 325 | size_t fw_len; |
326 | u8 fw_bss_type; | ||
265 | struct wl1271_nvs_file *nvs; | 327 | struct wl1271_nvs_file *nvs; |
266 | size_t nvs_len; | 328 | size_t nvs_len; |
267 | 329 | ||
@@ -378,7 +440,6 @@ struct wl1271 { | |||
378 | int last_rssi_event; | 440 | int last_rssi_event; |
379 | 441 | ||
380 | struct wl1271_stats stats; | 442 | struct wl1271_stats stats; |
381 | struct dentry *rootdir; | ||
382 | 443 | ||
383 | __le32 buffer_32; | 444 | __le32 buffer_32; |
384 | u32 buffer_cmd; | 445 | u32 buffer_cmd; |
@@ -400,6 +461,23 @@ struct wl1271 { | |||
400 | 461 | ||
401 | /* Most recently reported noise in dBm */ | 462 | /* Most recently reported noise in dBm */ |
402 | s8 noise; | 463 | s8 noise; |
464 | |||
465 | /* map for HLIDs of associated stations - when operating in AP mode */ | ||
466 | unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)]; | ||
467 | |||
468 | /* recoreded keys for AP-mode - set here before AP startup */ | ||
469 | struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS]; | ||
470 | |||
471 | /* bands supported by this instance of wl12xx */ | ||
472 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||
473 | |||
474 | /* RX BA constraint value */ | ||
475 | bool ba_support; | ||
476 | u8 ba_rx_bitmap; | ||
477 | }; | ||
478 | |||
479 | struct wl1271_station { | ||
480 | u8 hlid; | ||
403 | }; | 481 | }; |
404 | 482 | ||
405 | int wl1271_plt_start(struct wl1271 *wl); | 483 | int wl1271_plt_start(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index be21032f4dc1..67dcf8f28cd3 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h | |||
@@ -138,13 +138,13 @@ struct wl12xx_arp_rsp_template { | |||
138 | struct ieee80211_hdr_3addr hdr; | 138 | struct ieee80211_hdr_3addr hdr; |
139 | 139 | ||
140 | u8 llc_hdr[sizeof(rfc1042_header)]; | 140 | u8 llc_hdr[sizeof(rfc1042_header)]; |
141 | u16 llc_type; | 141 | __be16 llc_type; |
142 | 142 | ||
143 | struct arphdr arp_hdr; | 143 | struct arphdr arp_hdr; |
144 | u8 sender_hw[ETH_ALEN]; | 144 | u8 sender_hw[ETH_ALEN]; |
145 | u32 sender_ip; | 145 | __be32 sender_ip; |
146 | u8 target_hw[ETH_ALEN]; | 146 | u8 target_hw[ETH_ALEN]; |
147 | u32 target_ip; | 147 | __be32 target_ip; |
148 | } __packed; | 148 | } __packed; |
149 | 149 | ||
150 | 150 | ||
@@ -160,4 +160,9 @@ struct wl12xx_probe_resp_template { | |||
160 | struct wl12xx_ie_country country; | 160 | struct wl12xx_ie_country country; |
161 | } __packed; | 161 | } __packed; |
162 | 162 | ||
163 | struct wl12xx_disconn_template { | ||
164 | struct ieee80211_header header; | ||
165 | __le16 disconn_reason; | ||
166 | } __packed; | ||
167 | |||
163 | #endif | 168 | #endif |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index af49f8ab7f81..b0be5fb9de19 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
@@ -178,6 +178,11 @@ struct ieee80211_radiotap_header { | |||
178 | * | 178 | * |
179 | * Number of unicast retries a transmitted frame used. | 179 | * Number of unicast retries a transmitted frame used. |
180 | * | 180 | * |
181 | * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless | ||
182 | * | ||
183 | * Contains a bitmap of known fields/flags, the flags, and | ||
184 | * the MCS index. | ||
185 | * | ||
181 | */ | 186 | */ |
182 | enum ieee80211_radiotap_type { | 187 | enum ieee80211_radiotap_type { |
183 | IEEE80211_RADIOTAP_TSFT = 0, | 188 | IEEE80211_RADIOTAP_TSFT = 0, |
@@ -199,6 +204,8 @@ enum ieee80211_radiotap_type { | |||
199 | IEEE80211_RADIOTAP_RTS_RETRIES = 16, | 204 | IEEE80211_RADIOTAP_RTS_RETRIES = 16, |
200 | IEEE80211_RADIOTAP_DATA_RETRIES = 17, | 205 | IEEE80211_RADIOTAP_DATA_RETRIES = 17, |
201 | 206 | ||
207 | IEEE80211_RADIOTAP_MCS = 19, | ||
208 | |||
202 | /* valid in every it_present bitmap, even vendor namespaces */ | 209 | /* valid in every it_present bitmap, even vendor namespaces */ |
203 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, | 210 | IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, |
204 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, | 211 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, |
@@ -245,6 +252,24 @@ enum ieee80211_radiotap_type { | |||
245 | #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ | 252 | #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ |
246 | #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ | 253 | #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ |
247 | 254 | ||
255 | |||
256 | /* For IEEE80211_RADIOTAP_MCS */ | ||
257 | #define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 | ||
258 | #define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 | ||
259 | #define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 | ||
260 | #define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 | ||
261 | #define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 | ||
262 | |||
263 | #define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 | ||
264 | #define IEEE80211_RADIOTAP_MCS_BW_20 0 | ||
265 | #define IEEE80211_RADIOTAP_MCS_BW_40 1 | ||
266 | #define IEEE80211_RADIOTAP_MCS_BW_20L 2 | ||
267 | #define IEEE80211_RADIOTAP_MCS_BW_20U 3 | ||
268 | #define IEEE80211_RADIOTAP_MCS_SGI 0x04 | ||
269 | #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 | ||
270 | #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 | ||
271 | |||
272 | |||
248 | /* Ugly macro to convert literal channel numbers into their mhz equivalents | 273 | /* Ugly macro to convert literal channel numbers into their mhz equivalents |
249 | * There are certianly some conditions that will break this (like feeding it '30') | 274 | * There are certianly some conditions that will break this (like feeding it '30') |
250 | * but they shouldn't arise since nothing talks on channel 30. */ | 275 | * but they shouldn't arise since nothing talks on channel 30. */ |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 2dabdf7680d0..872adb86200c 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -81,6 +81,8 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
81 | IEEE80211_IF_FMT(name, field, "%d\n") | 81 | IEEE80211_IF_FMT(name, field, "%d\n") |
82 | #define IEEE80211_IF_FMT_HEX(name, field) \ | 82 | #define IEEE80211_IF_FMT_HEX(name, field) \ |
83 | IEEE80211_IF_FMT(name, field, "%#x\n") | 83 | IEEE80211_IF_FMT(name, field, "%#x\n") |
84 | #define IEEE80211_IF_FMT_LHEX(name, field) \ | ||
85 | IEEE80211_IF_FMT(name, field, "%#lx\n") | ||
84 | #define IEEE80211_IF_FMT_SIZE(name, field) \ | 86 | #define IEEE80211_IF_FMT_SIZE(name, field) \ |
85 | IEEE80211_IF_FMT(name, field, "%zd\n") | 87 | IEEE80211_IF_FMT(name, field, "%zd\n") |
86 | 88 | ||
@@ -145,6 +147,8 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], | |||
145 | HEX); | 147 | HEX); |
146 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | 148 | IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], |
147 | HEX); | 149 | HEX); |
150 | IEEE80211_IF_FILE(flags, flags, HEX); | ||
151 | IEEE80211_IF_FILE(state, state, LHEX); | ||
148 | 152 | ||
149 | /* STA attributes */ | 153 | /* STA attributes */ |
150 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 154 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
@@ -283,6 +287,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
283 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 287 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
284 | { | 288 | { |
285 | DEBUGFS_ADD(drop_unencrypted); | 289 | DEBUGFS_ADD(drop_unencrypted); |
290 | DEBUGFS_ADD(flags); | ||
291 | DEBUGFS_ADD(state); | ||
286 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 292 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
287 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 293 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
288 | 294 | ||
@@ -296,6 +302,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
296 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 302 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
297 | { | 303 | { |
298 | DEBUGFS_ADD(drop_unencrypted); | 304 | DEBUGFS_ADD(drop_unencrypted); |
305 | DEBUGFS_ADD(flags); | ||
306 | DEBUGFS_ADD(state); | ||
299 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 307 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
300 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 308 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
301 | 309 | ||
@@ -307,6 +315,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
307 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 315 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
308 | { | 316 | { |
309 | DEBUGFS_ADD(drop_unencrypted); | 317 | DEBUGFS_ADD(drop_unencrypted); |
318 | DEBUGFS_ADD(flags); | ||
319 | DEBUGFS_ADD(state); | ||
310 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 320 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
311 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 321 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
312 | 322 | ||
@@ -316,12 +326,16 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
316 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 326 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
317 | { | 327 | { |
318 | DEBUGFS_ADD(drop_unencrypted); | 328 | DEBUGFS_ADD(drop_unencrypted); |
329 | DEBUGFS_ADD(flags); | ||
330 | DEBUGFS_ADD(state); | ||
319 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 331 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
320 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 332 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
321 | } | 333 | } |
322 | 334 | ||
323 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 335 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
324 | { | 336 | { |
337 | DEBUGFS_ADD(flags); | ||
338 | DEBUGFS_ADD(state); | ||
325 | } | 339 | } |
326 | 340 | ||
327 | #ifdef CONFIG_MAC80211_MESH | 341 | #ifdef CONFIG_MAC80211_MESH |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 32210695b8b6..dfa752e5520b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -601,6 +601,14 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
601 | list_for_each_entry(sdata, &local->interfaces, list) { | 601 | list_for_each_entry(sdata, &local->interfaces, list) { |
602 | if (!ieee80211_sdata_running(sdata)) | 602 | if (!ieee80211_sdata_running(sdata)) |
603 | continue; | 603 | continue; |
604 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
605 | /* If an AP vif is found, then disable PS | ||
606 | * by setting the count to zero thereby setting | ||
607 | * ps_sdata to NULL. | ||
608 | */ | ||
609 | count = 0; | ||
610 | break; | ||
611 | } | ||
604 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 612 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
605 | continue; | 613 | continue; |
606 | found = sdata; | 614 | found = sdata; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f36d70f5b062..7185c9316be2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -85,6 +85,9 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
85 | if (len & 1) /* padding for RX_FLAGS if necessary */ | 85 | if (len & 1) /* padding for RX_FLAGS if necessary */ |
86 | len++; | 86 | len++; |
87 | 87 | ||
88 | if (status->flag & RX_FLAG_HT) /* HT info */ | ||
89 | len += 3; | ||
90 | |||
88 | return len; | 91 | return len; |
89 | } | 92 | } |
90 | 93 | ||
@@ -193,6 +196,20 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
193 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; | 196 | rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; |
194 | put_unaligned_le16(rx_flags, pos); | 197 | put_unaligned_le16(rx_flags, pos); |
195 | pos += 2; | 198 | pos += 2; |
199 | |||
200 | if (status->flag & RX_FLAG_HT) { | ||
201 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); | ||
202 | *pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS | | ||
203 | IEEE80211_RADIOTAP_MCS_HAVE_GI | | ||
204 | IEEE80211_RADIOTAP_MCS_HAVE_BW; | ||
205 | *pos = 0; | ||
206 | if (status->flag & RX_FLAG_SHORT_GI) | ||
207 | *pos |= IEEE80211_RADIOTAP_MCS_SGI; | ||
208 | if (status->flag & RX_FLAG_40MHZ) | ||
209 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; | ||
210 | pos++; | ||
211 | *pos++ = status->rate_idx; | ||
212 | } | ||
196 | } | 213 | } |
197 | 214 | ||
198 | /* | 215 | /* |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9b62710891a2..864ddfbeff2f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2718,7 +2718,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
2718 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 2718 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2719 | NL80211_CMD_GET_MESH_CONFIG); | 2719 | NL80211_CMD_GET_MESH_CONFIG); |
2720 | if (!hdr) | 2720 | if (!hdr) |
2721 | goto nla_put_failure; | 2721 | goto out; |
2722 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); | 2722 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); |
2723 | if (!pinfoattr) | 2723 | if (!pinfoattr) |
2724 | goto nla_put_failure; | 2724 | goto nla_put_failure; |
@@ -2759,6 +2759,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
2759 | 2759 | ||
2760 | nla_put_failure: | 2760 | nla_put_failure: |
2761 | genlmsg_cancel(msg, hdr); | 2761 | genlmsg_cancel(msg, hdr); |
2762 | out: | ||
2762 | nlmsg_free(msg); | 2763 | nlmsg_free(msg); |
2763 | return -ENOBUFS; | 2764 | return -ENOBUFS; |
2764 | } | 2765 | } |
@@ -2954,7 +2955,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
2954 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | 2955 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, |
2955 | NL80211_CMD_GET_REG); | 2956 | NL80211_CMD_GET_REG); |
2956 | if (!hdr) | 2957 | if (!hdr) |
2957 | goto nla_put_failure; | 2958 | goto put_failure; |
2958 | 2959 | ||
2959 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, | 2960 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, |
2960 | cfg80211_regdomain->alpha2); | 2961 | cfg80211_regdomain->alpha2); |
@@ -3001,6 +3002,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
3001 | 3002 | ||
3002 | nla_put_failure: | 3003 | nla_put_failure: |
3003 | genlmsg_cancel(msg, hdr); | 3004 | genlmsg_cancel(msg, hdr); |
3005 | put_failure: | ||
3004 | nlmsg_free(msg); | 3006 | nlmsg_free(msg); |
3005 | err = -EMSGSIZE; | 3007 | err = -EMSGSIZE; |
3006 | out: | 3008 | out: |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 4ed065d8bb51..6a750bc6bcfe 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -167,12 +167,15 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
167 | 167 | ||
168 | /* | 168 | /* |
169 | * Disallow pairwise keys with non-zero index unless it's WEP | 169 | * Disallow pairwise keys with non-zero index unless it's WEP |
170 | * (because current deployments use pairwise WEP keys with | 170 | * or a vendor specific cipher (because current deployments use |
171 | * non-zero indizes but 802.11i clearly specifies to use zero) | 171 | * pairwise WEP keys with non-zero indices and for vendor specific |
172 | * ciphers this should be validated in the driver or hardware level | ||
173 | * - but 802.11i clearly specifies to use zero) | ||
172 | */ | 174 | */ |
173 | if (pairwise && key_idx && | 175 | if (pairwise && key_idx && |
174 | params->cipher != WLAN_CIPHER_SUITE_WEP40 && | 176 | ((params->cipher == WLAN_CIPHER_SUITE_TKIP) || |
175 | params->cipher != WLAN_CIPHER_SUITE_WEP104) | 177 | (params->cipher == WLAN_CIPHER_SUITE_CCMP) || |
178 | (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC))) | ||
176 | return -EINVAL; | 179 | return -EINVAL; |
177 | 180 | ||
178 | switch (params->cipher) { | 181 | switch (params->cipher) { |