diff options
author | David S. Miller <davem@davemloft.net> | 2009-07-26 13:01:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-26 13:01:25 -0400 |
commit | c8b201ff867e64b6233d069563081775269f4499 (patch) | |
tree | 35d363e6cb565fd7285480dc877a2da79eafb9a7 | |
parent | 436b355b96042ab6564f43a7dabd5c61d9634ff7 (diff) | |
parent | 249b405cf8145da8a74b70544ae1079d244bdb00 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
134 files changed, 4999 insertions, 3237 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d119ba9e724d..df55d24a2f69 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4984,7 +4984,7 @@ L: linux-wireless@vger.kernel.org | |||
4984 | W: http://linuxwireless.org/ | 4984 | W: http://linuxwireless.org/ |
4985 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 4985 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
4986 | S: Maintained | 4986 | S: Maintained |
4987 | F: drivers/net/wireless/rtl818* | 4987 | F: drivers/net/wireless/rtl818x/rtl8180* |
4988 | 4988 | ||
4989 | RTL8187 WIRELESS DRIVER | 4989 | RTL8187 WIRELESS DRIVER |
4990 | P: Herton Ronaldo Krzesinski | 4990 | P: Herton Ronaldo Krzesinski |
@@ -6466,6 +6466,15 @@ M: mitr@volny.cz | |||
6466 | S: Maintained | 6466 | S: Maintained |
6467 | F: drivers/input/misc/wistron_btns.c | 6467 | F: drivers/input/misc/wistron_btns.c |
6468 | 6468 | ||
6469 | WL1251 WIRELESS DRIVER | ||
6470 | P: Kalle Valo | ||
6471 | M: kalle.valo@nokia.com | ||
6472 | L: linux-wireless@vger.kernel.org | ||
6473 | W: http://wireless.kernel.org | ||
6474 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | ||
6475 | S: Maintained | ||
6476 | F: drivers/net/wireless/wl12xx/wl1251* | ||
6477 | |||
6469 | WL3501 WIRELESS PCMCIA CARD DRIVER | 6478 | WL3501 WIRELESS PCMCIA CARD DRIVER |
6470 | P: Arnaldo Carvalho de Melo | 6479 | P: Arnaldo Carvalho de Melo |
6471 | M: acme@ghostprotocols.net | 6480 | M: acme@ghostprotocols.net |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5bc00db21b24..ca7a8a31d0b9 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -428,10 +428,12 @@ config RTL8187 | |||
428 | Micronet SP907GK V5 | 428 | Micronet SP907GK V5 |
429 | Encore ENUWI-G2 | 429 | Encore ENUWI-G2 |
430 | Trendnet TEW-424UB | 430 | Trendnet TEW-424UB |
431 | ASUS P5B Deluxe | 431 | ASUS P5B Deluxe/P5K Premium motherboards |
432 | Toshiba Satellite Pro series of laptops | 432 | Toshiba Satellite Pro series of laptops |
433 | Asus Wireless Link | 433 | Asus Wireless Link |
434 | Linksys WUSB54GC-EU | 434 | Linksys WUSB54GC-EU v2 |
435 | (v1 = rt73usb; v3 is rt2070-based, | ||
436 | use staging/rt3070 or try rt2800usb) | ||
435 | 437 | ||
436 | Thanks to Realtek for their support! | 438 | Thanks to Realtek for their support! |
437 | 439 | ||
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index ecc93834533f..5695911bc602 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1964,14 +1964,6 @@ static void __devexit adm8211_remove(struct pci_dev *pdev) | |||
1964 | #ifdef CONFIG_PM | 1964 | #ifdef CONFIG_PM |
1965 | static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) | 1965 | static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) |
1966 | { | 1966 | { |
1967 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | ||
1968 | struct adm8211_priv *priv = dev->priv; | ||
1969 | |||
1970 | if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { | ||
1971 | ieee80211_stop_queues(dev); | ||
1972 | adm8211_stop(dev); | ||
1973 | } | ||
1974 | |||
1975 | pci_save_state(pdev); | 1967 | pci_save_state(pdev); |
1976 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 1968 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
1977 | return 0; | 1969 | return 0; |
@@ -1979,17 +1971,8 @@ static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1979 | 1971 | ||
1980 | static int adm8211_resume(struct pci_dev *pdev) | 1972 | static int adm8211_resume(struct pci_dev *pdev) |
1981 | { | 1973 | { |
1982 | struct ieee80211_hw *dev = pci_get_drvdata(pdev); | ||
1983 | struct adm8211_priv *priv = dev->priv; | ||
1984 | |||
1985 | pci_set_power_state(pdev, PCI_D0); | 1974 | pci_set_power_state(pdev, PCI_D0); |
1986 | pci_restore_state(pdev); | 1975 | pci_restore_state(pdev); |
1987 | |||
1988 | if (priv->mode != NL80211_IFTYPE_UNSPECIFIED) { | ||
1989 | adm8211_start(dev); | ||
1990 | ieee80211_wake_queues(dev); | ||
1991 | } | ||
1992 | |||
1993 | return 0; | 1976 | return 0; |
1994 | } | 1977 | } |
1995 | #endif /* CONFIG_PM */ | 1978 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c index d479f4735aaa..f96c634e2d35 100644 --- a/drivers/net/wireless/arlan-main.c +++ b/drivers/net/wireless/arlan-main.c | |||
@@ -1022,7 +1022,7 @@ static int arlan_mac_addr(struct net_device *dev, void *p) | |||
1022 | ARLAN_DEBUG_ENTRY("arlan_mac_addr"); | 1022 | ARLAN_DEBUG_ENTRY("arlan_mac_addr"); |
1023 | return -EINVAL; | 1023 | return -EINVAL; |
1024 | 1024 | ||
1025 | if (!netif_running(dev)) | 1025 | if (netif_running(dev)) |
1026 | return -EBUSY; | 1026 | return -EBUSY; |
1027 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | 1027 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); |
1028 | 1028 | ||
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index bb97981fb248..e6c3ee3e0581 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -109,11 +109,52 @@ struct ar9170_rxstream_mpdu_merge { | |||
109 | bool has_plcp; | 109 | bool has_plcp; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define AR9170_NUM_MAX_BA_RETRY 5 | ||
113 | #define AR9170_NUM_TID 16 | ||
114 | #define WME_BA_BMP_SIZE 64 | ||
115 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) | ||
116 | |||
117 | #define WME_AC_BE 2 | ||
118 | #define WME_AC_BK 3 | ||
119 | #define WME_AC_VI 1 | ||
120 | #define WME_AC_VO 0 | ||
121 | |||
122 | #define TID_TO_WME_AC(_tid) \ | ||
123 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
124 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
125 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
126 | WME_AC_VO) | ||
127 | |||
128 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
129 | ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) | ||
130 | |||
131 | enum ar9170_tid_state { | ||
132 | AR9170_TID_STATE_INVALID, | ||
133 | AR9170_TID_STATE_SHUTDOWN, | ||
134 | AR9170_TID_STATE_PROGRESS, | ||
135 | AR9170_TID_STATE_COMPLETE, | ||
136 | }; | ||
137 | |||
138 | struct ar9170_sta_tid { | ||
139 | struct list_head list; | ||
140 | struct sk_buff_head queue; | ||
141 | u8 addr[ETH_ALEN]; | ||
142 | u16 ssn; | ||
143 | u16 tid; | ||
144 | enum ar9170_tid_state state; | ||
145 | bool active; | ||
146 | u8 retry; | ||
147 | }; | ||
148 | |||
112 | #define AR9170_QUEUE_TIMEOUT 64 | 149 | #define AR9170_QUEUE_TIMEOUT 64 |
113 | #define AR9170_TX_TIMEOUT 8 | 150 | #define AR9170_TX_TIMEOUT 8 |
151 | #define AR9170_BA_TIMEOUT 4 | ||
114 | #define AR9170_JANITOR_DELAY 128 | 152 | #define AR9170_JANITOR_DELAY 128 |
115 | #define AR9170_TX_INVALID_RATE 0xffffffff | 153 | #define AR9170_TX_INVALID_RATE 0xffffffff |
116 | 154 | ||
155 | #define AR9170_NUM_TX_STATUS 128 | ||
156 | #define AR9170_NUM_TX_AGG_MAX 30 | ||
157 | |||
117 | struct ar9170 { | 158 | struct ar9170 { |
118 | struct ieee80211_hw *hw; | 159 | struct ieee80211_hw *hw; |
119 | struct mutex mutex; | 160 | struct mutex mutex; |
@@ -187,14 +228,25 @@ struct ar9170 { | |||
187 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | 228 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; |
188 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; | 229 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; |
189 | struct delayed_work tx_janitor; | 230 | struct delayed_work tx_janitor; |
231 | /* tx ampdu */ | ||
232 | struct sk_buff_head tx_status_ampdu; | ||
233 | spinlock_t tx_ampdu_list_lock; | ||
234 | struct list_head tx_ampdu_list; | ||
235 | unsigned int tx_ampdu_pending; | ||
190 | 236 | ||
191 | /* rxstream mpdu merge */ | 237 | /* rxstream mpdu merge */ |
192 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | 238 | struct ar9170_rxstream_mpdu_merge rx_mpdu; |
193 | struct sk_buff *rx_failover; | 239 | struct sk_buff *rx_failover; |
194 | int rx_failover_missing; | 240 | int rx_failover_missing; |
241 | |||
242 | /* (cached) HW A-MPDU settings */ | ||
243 | u8 global_ampdu_density; | ||
244 | u8 global_ampdu_factor; | ||
195 | }; | 245 | }; |
196 | 246 | ||
197 | struct ar9170_sta_info { | 247 | struct ar9170_sta_info { |
248 | struct ar9170_sta_tid agg[AR9170_NUM_TID]; | ||
249 | unsigned int ampdu_max_len; | ||
198 | }; | 250 | }; |
199 | 251 | ||
200 | #define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) | 252 | #define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 51753ed1b8ba..c7287a883a48 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -49,6 +49,10 @@ static int modparam_nohwcrypt; | |||
49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
51 | 51 | ||
52 | static int modparam_ht; | ||
53 | module_param_named(ht, modparam_ht, bool, S_IRUGO); | ||
54 | MODULE_PARM_DESC(ht, "enable MPDU aggregation."); | ||
55 | |||
52 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | 56 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ |
53 | .bitrate = (_bitrate), \ | 57 | .bitrate = (_bitrate), \ |
54 | .flags = (_flags), \ | 58 | .flags = (_flags), \ |
@@ -148,12 +152,15 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { | |||
148 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ | 152 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ |
149 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | 153 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ |
150 | IEEE80211_HT_CAP_SGI_40 | \ | 154 | IEEE80211_HT_CAP_SGI_40 | \ |
155 | IEEE80211_HT_CAP_GRN_FLD | \ | ||
151 | IEEE80211_HT_CAP_DSSSCCK40 | \ | 156 | IEEE80211_HT_CAP_DSSSCCK40 | \ |
152 | IEEE80211_HT_CAP_SM_PS, \ | 157 | IEEE80211_HT_CAP_SM_PS, \ |
153 | .ampdu_factor = 3, \ | 158 | .ampdu_factor = 3, \ |
154 | .ampdu_density = 6, \ | 159 | .ampdu_density = 6, \ |
155 | .mcs = { \ | 160 | .mcs = { \ |
156 | .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \ | 161 | .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ |
162 | .rx_highest = cpu_to_le16(300), \ | ||
163 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
157 | }, \ | 164 | }, \ |
158 | } | 165 | } |
159 | 166 | ||
@@ -174,8 +181,31 @@ static struct ieee80211_supported_band ar9170_band_5GHz = { | |||
174 | }; | 181 | }; |
175 | 182 | ||
176 | static void ar9170_tx(struct ar9170 *ar); | 183 | static void ar9170_tx(struct ar9170 *ar); |
184 | static bool ar9170_tx_ampdu(struct ar9170 *ar); | ||
177 | 185 | ||
178 | #ifdef AR9170_QUEUE_DEBUG | 186 | static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) |
187 | { | ||
188 | return le16_to_cpu(hdr->seq_ctrl) >> 4; | ||
189 | } | ||
190 | |||
191 | static inline u16 ar9170_get_seq(struct sk_buff *skb) | ||
192 | { | ||
193 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | ||
195 | } | ||
196 | |||
197 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | ||
198 | { | ||
199 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
200 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
201 | |||
202 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
203 | } | ||
204 | |||
205 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | ||
206 | #define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) | ||
207 | |||
208 | #if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) | ||
179 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | 209 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) |
180 | { | 210 | { |
181 | struct ar9170_tx_control *txc = (void *) skb->data; | 211 | struct ar9170_tx_control *txc = (void *) skb->data; |
@@ -183,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | |||
183 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | 213 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; |
184 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 214 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; |
185 | 215 | ||
186 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x " | 216 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " |
187 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | 217 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", |
188 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), | 218 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), |
189 | ieee80211_get_DA(hdr), arinfo->flags, | 219 | ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), |
190 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | 220 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), |
191 | jiffies_to_msecs(arinfo->timeout - jiffies)); | 221 | jiffies_to_msecs(arinfo->timeout - jiffies)); |
192 | } | 222 | } |
@@ -210,7 +240,9 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, | |||
210 | "mismatch %d != %d\n", skb_queue_len(queue), i); | 240 | "mismatch %d != %d\n", skb_queue_len(queue), i); |
211 | printk(KERN_DEBUG "---[ end ]---\n"); | 241 | printk(KERN_DEBUG "---[ end ]---\n"); |
212 | } | 242 | } |
243 | #endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ | ||
213 | 244 | ||
245 | #ifdef AR9170_QUEUE_DEBUG | ||
214 | static void ar9170_dump_txqueue(struct ar9170 *ar, | 246 | static void ar9170_dump_txqueue(struct ar9170 *ar, |
215 | struct sk_buff_head *queue) | 247 | struct sk_buff_head *queue) |
216 | { | 248 | { |
@@ -220,7 +252,9 @@ static void ar9170_dump_txqueue(struct ar9170 *ar, | |||
220 | __ar9170_dump_txqueue(ar, queue); | 252 | __ar9170_dump_txqueue(ar, queue); |
221 | spin_unlock_irqrestore(&queue->lock, flags); | 253 | spin_unlock_irqrestore(&queue->lock, flags); |
222 | } | 254 | } |
255 | #endif /* AR9170_QUEUE_DEBUG */ | ||
223 | 256 | ||
257 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
224 | static void __ar9170_dump_txstats(struct ar9170 *ar) | 258 | static void __ar9170_dump_txstats(struct ar9170 *ar) |
225 | { | 259 | { |
226 | int i; | 260 | int i; |
@@ -229,20 +263,27 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) | |||
229 | wiphy_name(ar->hw->wiphy)); | 263 | wiphy_name(ar->hw->wiphy)); |
230 | 264 | ||
231 | for (i = 0; i < __AR9170_NUM_TXQ; i++) | 265 | for (i = 0; i < __AR9170_NUM_TXQ; i++) |
232 | printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n", | 266 | printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d " |
233 | wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit, | 267 | " stopped:%d\n", wiphy_name(ar->hw->wiphy), i, |
234 | ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i])); | 268 | ar->tx_stats[i].limit, ar->tx_stats[i].len, |
269 | skb_queue_len(&ar->tx_status[i]), | ||
270 | ieee80211_queue_stopped(ar->hw, i)); | ||
235 | } | 271 | } |
272 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
236 | 273 | ||
237 | static void ar9170_dump_txstats(struct ar9170 *ar) | 274 | #ifdef AR9170_TXAGG_DEBUG |
275 | static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) | ||
238 | { | 276 | { |
239 | unsigned long flags; | 277 | unsigned long flags; |
240 | 278 | ||
241 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 279 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); |
242 | __ar9170_dump_txstats(ar); | 280 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", |
243 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 281 | wiphy_name(ar->hw->wiphy)); |
282 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); | ||
283 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); | ||
244 | } | 284 | } |
245 | #endif /* AR9170_QUEUE_DEBUG */ | 285 | |
286 | #endif /* AR9170_TXAGG_DEBUG */ | ||
246 | 287 | ||
247 | /* caller must guarantee exclusive access for _bin_ queue. */ | 288 | /* caller must guarantee exclusive access for _bin_ queue. */ |
248 | static void ar9170_recycle_expired(struct ar9170 *ar, | 289 | static void ar9170_recycle_expired(struct ar9170 *ar, |
@@ -315,6 +356,70 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | |||
315 | ieee80211_tx_status_irqsafe(ar->hw, skb); | 356 | ieee80211_tx_status_irqsafe(ar->hw, skb); |
316 | } | 357 | } |
317 | 358 | ||
359 | static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) | ||
360 | { | ||
361 | struct sk_buff_head success; | ||
362 | struct sk_buff *skb; | ||
363 | unsigned int i; | ||
364 | unsigned long queue_bitmap = 0; | ||
365 | |||
366 | skb_queue_head_init(&success); | ||
367 | |||
368 | while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) | ||
369 | __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); | ||
370 | |||
371 | ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); | ||
372 | |||
373 | #ifdef AR9170_TXAGG_DEBUG | ||
374 | printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", | ||
375 | wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); | ||
376 | __ar9170_dump_txqueue(ar, &success); | ||
377 | #endif /* AR9170_TXAGG_DEBUG */ | ||
378 | |||
379 | while ((skb = __skb_dequeue(&success))) { | ||
380 | struct ieee80211_tx_info *txinfo; | ||
381 | |||
382 | queue_bitmap |= BIT(skb_get_queue_mapping(skb)); | ||
383 | |||
384 | txinfo = IEEE80211_SKB_CB(skb); | ||
385 | ieee80211_tx_info_clear_status(txinfo); | ||
386 | |||
387 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
388 | txinfo->status.rates[0].count = 1; | ||
389 | |||
390 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
391 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
392 | } | ||
393 | |||
394 | for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { | ||
395 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
396 | printk(KERN_DEBUG "%s: wake queue %d\n", | ||
397 | wiphy_name(ar->hw->wiphy), i); | ||
398 | __ar9170_dump_txstats(ar); | ||
399 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
400 | ieee80211_wake_queue(ar->hw, i); | ||
401 | } | ||
402 | |||
403 | if (queue_bitmap) | ||
404 | ar9170_tx(ar); | ||
405 | } | ||
406 | |||
407 | static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
408 | { | ||
409 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
410 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
411 | |||
412 | arinfo->timeout = jiffies + | ||
413 | msecs_to_jiffies(AR9170_BA_TIMEOUT); | ||
414 | |||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | ||
416 | ar9170_tx_fake_ampdu_status(ar); | ||
417 | ar->tx_ampdu_pending--; | ||
418 | |||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | ||
420 | ar9170_tx_ampdu(ar); | ||
421 | } | ||
422 | |||
318 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | 423 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) |
319 | { | 424 | { |
320 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 425 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -336,7 +441,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
336 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 441 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
337 | 442 | ||
338 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { | 443 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { |
339 | dev_kfree_skb_any(skb); | 444 | ar9170_tx_ampdu_callback(ar, skb); |
340 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { | 445 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { |
341 | arinfo->timeout = jiffies + | 446 | arinfo->timeout = jiffies + |
342 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 447 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
@@ -420,6 +525,38 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, | |||
420 | return NULL; | 525 | return NULL; |
421 | } | 526 | } |
422 | 527 | ||
528 | static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) | ||
529 | { | ||
530 | struct sk_buff *skb; | ||
531 | struct ieee80211_tx_info *txinfo; | ||
532 | |||
533 | while (count) { | ||
534 | skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); | ||
535 | if (!skb) | ||
536 | break; | ||
537 | |||
538 | txinfo = IEEE80211_SKB_CB(skb); | ||
539 | ieee80211_tx_info_clear_status(txinfo); | ||
540 | |||
541 | /* FIXME: maybe more ? */ | ||
542 | txinfo->status.rates[0].count = 1; | ||
543 | |||
544 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
545 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
546 | count--; | ||
547 | } | ||
548 | |||
549 | #ifdef AR9170_TXAGG_DEBUG | ||
550 | if (count) { | ||
551 | printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " | ||
552 | "suitable frames left in tx_status queue.\n", | ||
553 | wiphy_name(ar->hw->wiphy), count); | ||
554 | |||
555 | ar9170_dump_tx_status_ampdu(ar); | ||
556 | } | ||
557 | #endif /* AR9170_TXAGG_DEBUG */ | ||
558 | } | ||
559 | |||
423 | /* | 560 | /* |
424 | * This worker tries to keeps an maintain tx_status queues. | 561 | * This worker tries to keeps an maintain tx_status queues. |
425 | * So we can guarantee that incoming tx_status reports are | 562 | * So we can guarantee that incoming tx_status reports are |
@@ -456,6 +593,8 @@ static void ar9170_tx_janitor(struct work_struct *work) | |||
456 | resched = true; | 593 | resched = true; |
457 | } | 594 | } |
458 | 595 | ||
596 | ar9170_tx_fake_ampdu_status(ar); | ||
597 | |||
459 | if (resched) | 598 | if (resched) |
460 | queue_delayed_work(ar->hw->workqueue, | 599 | queue_delayed_work(ar->hw->workqueue, |
461 | &ar->tx_janitor, | 600 | &ar->tx_janitor, |
@@ -528,8 +667,15 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
528 | break; | 667 | break; |
529 | 668 | ||
530 | case 0xc4: | 669 | case 0xc4: |
670 | /* BlockACK bitmap */ | ||
671 | break; | ||
672 | |||
531 | case 0xc5: | 673 | case 0xc5: |
532 | /* BlockACK events */ | 674 | /* BlockACK events */ |
675 | ar9170_handle_block_ack(ar, | ||
676 | le16_to_cpu(cmd->ba_fail_cnt.failed), | ||
677 | le16_to_cpu(cmd->ba_fail_cnt.rate)); | ||
678 | ar9170_tx_fake_ampdu_status(ar); | ||
533 | break; | 679 | break; |
534 | 680 | ||
535 | case 0xc6: | 681 | case 0xc6: |
@@ -1098,6 +1244,10 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1098 | AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ | 1244 | AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ |
1099 | AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ | 1245 | AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ |
1100 | 1246 | ||
1247 | /* set sane AMPDU defaults */ | ||
1248 | ar->global_ampdu_density = 6; | ||
1249 | ar->global_ampdu_factor = 3; | ||
1250 | |||
1101 | ar->bad_hw_nagger = jiffies; | 1251 | ar->bad_hw_nagger = jiffies; |
1102 | 1252 | ||
1103 | err = ar->open(ar); | 1253 | err = ar->open(ar); |
@@ -1143,6 +1293,7 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1143 | flush_workqueue(ar->hw->workqueue); | 1293 | flush_workqueue(ar->hw->workqueue); |
1144 | 1294 | ||
1145 | cancel_delayed_work_sync(&ar->tx_janitor); | 1295 | cancel_delayed_work_sync(&ar->tx_janitor); |
1296 | cancel_delayed_work_sync(&ar->led_work); | ||
1146 | cancel_work_sync(&ar->filter_config_work); | 1297 | cancel_work_sync(&ar->filter_config_work); |
1147 | cancel_work_sync(&ar->beacon_work); | 1298 | cancel_work_sync(&ar->beacon_work); |
1148 | mutex_lock(&ar->mutex); | 1299 | mutex_lock(&ar->mutex); |
@@ -1159,9 +1310,40 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1159 | skb_queue_purge(&ar->tx_pending[i]); | 1310 | skb_queue_purge(&ar->tx_pending[i]); |
1160 | skb_queue_purge(&ar->tx_status[i]); | 1311 | skb_queue_purge(&ar->tx_status[i]); |
1161 | } | 1312 | } |
1313 | skb_queue_purge(&ar->tx_status_ampdu); | ||
1314 | |||
1162 | mutex_unlock(&ar->mutex); | 1315 | mutex_unlock(&ar->mutex); |
1163 | } | 1316 | } |
1164 | 1317 | ||
1318 | static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) | ||
1319 | { | ||
1320 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
1321 | |||
1322 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); | ||
1323 | } | ||
1324 | |||
1325 | static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, | ||
1326 | struct sk_buff *src) | ||
1327 | { | ||
1328 | struct ar9170_tx_control *dst_txc, *src_txc; | ||
1329 | struct ieee80211_tx_info *dst_info, *src_info; | ||
1330 | struct ar9170_tx_info *dst_arinfo, *src_arinfo; | ||
1331 | |||
1332 | src_txc = (void *) src->data; | ||
1333 | src_info = IEEE80211_SKB_CB(src); | ||
1334 | src_arinfo = (void *) src_info->rate_driver_data; | ||
1335 | |||
1336 | dst_txc = (void *) dst->data; | ||
1337 | dst_info = IEEE80211_SKB_CB(dst); | ||
1338 | dst_arinfo = (void *) dst_info->rate_driver_data; | ||
1339 | |||
1340 | dst_txc->phy_control = src_txc->phy_control; | ||
1341 | |||
1342 | /* same MCS for the whole aggregate */ | ||
1343 | memcpy(dst_info->driver_rates, src_info->driver_rates, | ||
1344 | sizeof(dst_info->driver_rates)); | ||
1345 | } | ||
1346 | |||
1165 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | 1347 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) |
1166 | { | 1348 | { |
1167 | struct ieee80211_hdr *hdr; | 1349 | struct ieee80211_hdr *hdr; |
@@ -1230,6 +1412,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1230 | 1412 | ||
1231 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | 1413 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); |
1232 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; | 1414 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; |
1415 | |||
1233 | goto out; | 1416 | goto out; |
1234 | } | 1417 | } |
1235 | 1418 | ||
@@ -1360,6 +1543,159 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) | |||
1360 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); | 1543 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); |
1361 | } | 1544 | } |
1362 | 1545 | ||
1546 | static bool ar9170_tx_ampdu(struct ar9170 *ar) | ||
1547 | { | ||
1548 | struct sk_buff_head agg; | ||
1549 | struct ar9170_sta_tid *tid_info = NULL, *tmp; | ||
1550 | struct sk_buff *skb, *first = NULL; | ||
1551 | unsigned long flags, f2; | ||
1552 | unsigned int i = 0; | ||
1553 | u16 seq, queue, tmpssn; | ||
1554 | bool run = false; | ||
1555 | |||
1556 | skb_queue_head_init(&agg); | ||
1557 | |||
1558 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1559 | if (list_empty(&ar->tx_ampdu_list)) { | ||
1560 | #ifdef AR9170_TXAGG_DEBUG | ||
1561 | printk(KERN_DEBUG "%s: aggregation list is empty.\n", | ||
1562 | wiphy_name(ar->hw->wiphy)); | ||
1563 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1564 | goto out_unlock; | ||
1565 | } | ||
1566 | |||
1567 | list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { | ||
1568 | if (tid_info->state != AR9170_TID_STATE_COMPLETE) { | ||
1569 | #ifdef AR9170_TXAGG_DEBUG | ||
1570 | printk(KERN_DEBUG "%s: dangling aggregation entry!\n", | ||
1571 | wiphy_name(ar->hw->wiphy)); | ||
1572 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1573 | continue; | ||
1574 | } | ||
1575 | |||
1576 | if (++i > 64) { | ||
1577 | #ifdef AR9170_TXAGG_DEBUG | ||
1578 | printk(KERN_DEBUG "%s: enough frames aggregated.\n", | ||
1579 | wiphy_name(ar->hw->wiphy)); | ||
1580 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1581 | break; | ||
1582 | } | ||
1583 | |||
1584 | queue = TID_TO_WME_AC(tid_info->tid); | ||
1585 | |||
1586 | if (skb_queue_len(&ar->tx_pending[queue]) >= | ||
1587 | AR9170_NUM_TX_AGG_MAX) { | ||
1588 | #ifdef AR9170_TXAGG_DEBUG | ||
1589 | printk(KERN_DEBUG "%s: queue %d full.\n", | ||
1590 | wiphy_name(ar->hw->wiphy), queue); | ||
1591 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1592 | continue; | ||
1593 | } | ||
1594 | |||
1595 | list_del_init(&tid_info->list); | ||
1596 | |||
1597 | spin_lock_irqsave(&tid_info->queue.lock, f2); | ||
1598 | tmpssn = seq = tid_info->ssn; | ||
1599 | first = skb_peek(&tid_info->queue); | ||
1600 | |||
1601 | if (likely(first)) | ||
1602 | tmpssn = ar9170_get_seq(first); | ||
1603 | |||
1604 | if (unlikely(tmpssn != seq)) { | ||
1605 | #ifdef AR9170_TXAGG_DEBUG | ||
1606 | printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", | ||
1607 | wiphy_name(ar->hw->wiphy), seq, tmpssn); | ||
1608 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1609 | tid_info->ssn = tmpssn; | ||
1610 | } | ||
1611 | |||
1612 | #ifdef AR9170_TXAGG_DEBUG | ||
1613 | printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " | ||
1614 | "%d queued frames.\n", wiphy_name(ar->hw->wiphy), | ||
1615 | tid_info->tid, tid_info->ssn, | ||
1616 | skb_queue_len(&tid_info->queue)); | ||
1617 | __ar9170_dump_txqueue(ar, &tid_info->queue); | ||
1618 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1619 | |||
1620 | while ((skb = skb_peek(&tid_info->queue))) { | ||
1621 | if (unlikely(ar9170_get_seq(skb) != seq)) | ||
1622 | break; | ||
1623 | |||
1624 | __skb_unlink(skb, &tid_info->queue); | ||
1625 | tid_info->ssn = seq = GET_NEXT_SEQ(seq); | ||
1626 | |||
1627 | if (unlikely(skb_get_queue_mapping(skb) != queue)) { | ||
1628 | #ifdef AR9170_TXAGG_DEBUG | ||
1629 | printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " | ||
1630 | "!match.\n", wiphy_name(ar->hw->wiphy), | ||
1631 | tid_info->tid, | ||
1632 | TID_TO_WME_AC(tid_info->tid), | ||
1633 | skb_get_queue_mapping(skb)); | ||
1634 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1635 | dev_kfree_skb_any(skb); | ||
1636 | continue; | ||
1637 | } | ||
1638 | |||
1639 | if (unlikely(first == skb)) { | ||
1640 | ar9170_tx_prepare_phy(ar, skb); | ||
1641 | __skb_queue_tail(&agg, skb); | ||
1642 | first = skb; | ||
1643 | } else { | ||
1644 | ar9170_tx_copy_phy(ar, skb, first); | ||
1645 | __skb_queue_tail(&agg, skb); | ||
1646 | } | ||
1647 | |||
1648 | if (unlikely(skb_queue_len(&agg) == | ||
1649 | AR9170_NUM_TX_AGG_MAX)) | ||
1650 | break; | ||
1651 | } | ||
1652 | |||
1653 | if (skb_queue_empty(&tid_info->queue)) | ||
1654 | tid_info->active = false; | ||
1655 | else | ||
1656 | list_add_tail(&tid_info->list, | ||
1657 | &ar->tx_ampdu_list); | ||
1658 | |||
1659 | spin_unlock_irqrestore(&tid_info->queue.lock, f2); | ||
1660 | |||
1661 | if (unlikely(skb_queue_empty(&agg))) { | ||
1662 | #ifdef AR9170_TXAGG_DEBUG | ||
1663 | printk(KERN_DEBUG "%s: queued empty list!\n", | ||
1664 | wiphy_name(ar->hw->wiphy)); | ||
1665 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1666 | continue; | ||
1667 | } | ||
1668 | |||
1669 | /* | ||
1670 | * tell the FW/HW that this is the last frame, | ||
1671 | * that way it will wait for the immediate block ack. | ||
1672 | */ | ||
1673 | if (likely(skb_peek_tail(&agg))) | ||
1674 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1675 | |||
1676 | #ifdef AR9170_TXAGG_DEBUG | ||
1677 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | ||
1678 | wiphy_name(ar->hw->wiphy)); | ||
1679 | __ar9170_dump_txqueue(ar, &agg); | ||
1680 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1681 | |||
1682 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1683 | |||
1684 | spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); | ||
1685 | skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); | ||
1686 | spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); | ||
1687 | run = true; | ||
1688 | |||
1689 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1690 | } | ||
1691 | |||
1692 | out_unlock: | ||
1693 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1694 | __skb_queue_purge(&agg); | ||
1695 | |||
1696 | return run; | ||
1697 | } | ||
1698 | |||
1363 | static void ar9170_tx(struct ar9170 *ar) | 1699 | static void ar9170_tx(struct ar9170 *ar) |
1364 | { | 1700 | { |
1365 | struct sk_buff *skb; | 1701 | struct sk_buff *skb; |
@@ -1384,11 +1720,17 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1384 | printk(KERN_DEBUG "%s: queue %d full\n", | 1720 | printk(KERN_DEBUG "%s: queue %d full\n", |
1385 | wiphy_name(ar->hw->wiphy), i); | 1721 | wiphy_name(ar->hw->wiphy), i); |
1386 | 1722 | ||
1387 | __ar9170_dump_txstats(ar); | 1723 | printk(KERN_DEBUG "%s: stuck frames: ===> \n", |
1388 | printk(KERN_DEBUG "stuck frames: ===> \n"); | 1724 | wiphy_name(ar->hw->wiphy)); |
1389 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | 1725 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); |
1390 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | 1726 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); |
1391 | #endif /* AR9170_QUEUE_DEBUG */ | 1727 | #endif /* AR9170_QUEUE_DEBUG */ |
1728 | |||
1729 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1730 | printk(KERN_DEBUG "%s: stop queue %d\n", | ||
1731 | wiphy_name(ar->hw->wiphy), i); | ||
1732 | __ar9170_dump_txstats(ar); | ||
1733 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1392 | ieee80211_stop_queue(ar->hw, i); | 1734 | ieee80211_stop_queue(ar->hw, i); |
1393 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1735 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1394 | continue; | 1736 | continue; |
@@ -1403,8 +1745,6 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1403 | "remaining slots:%d, needed:%d\n", | 1745 | "remaining slots:%d, needed:%d\n", |
1404 | wiphy_name(ar->hw->wiphy), i, remaining_space, | 1746 | wiphy_name(ar->hw->wiphy), i, remaining_space, |
1405 | frames); | 1747 | frames); |
1406 | |||
1407 | ar9170_dump_txstats(ar); | ||
1408 | #endif /* AR9170_QUEUE_DEBUG */ | 1748 | #endif /* AR9170_QUEUE_DEBUG */ |
1409 | frames = remaining_space; | 1749 | frames = remaining_space; |
1410 | } | 1750 | } |
@@ -1432,6 +1772,9 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1432 | arinfo->timeout = jiffies + | 1772 | arinfo->timeout = jiffies + |
1433 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1434 | 1774 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | ||
1776 | ar->tx_ampdu_pending++; | ||
1777 | |||
1435 | #ifdef AR9170_QUEUE_DEBUG | 1778 | #ifdef AR9170_QUEUE_DEBUG |
1436 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
1437 | wiphy_name(ar->hw->wiphy), i); | 1780 | wiphy_name(ar->hw->wiphy), i); |
@@ -1440,6 +1783,9 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1440 | 1783 | ||
1441 | err = ar->tx(ar, skb); | 1784 | err = ar->tx(ar, skb); |
1442 | if (unlikely(err)) { | 1785 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | ||
1787 | ar->tx_ampdu_pending--; | ||
1788 | |||
1443 | frames_failed++; | 1789 | frames_failed++; |
1444 | dev_kfree_skb_any(skb); | 1790 | dev_kfree_skb_any(skb); |
1445 | } else { | 1791 | } else { |
@@ -1461,13 +1807,18 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1461 | 1807 | ||
1462 | if (unlikely(frames_failed)) { | 1808 | if (unlikely(frames_failed)) { |
1463 | #ifdef AR9170_QUEUE_DEBUG | 1809 | #ifdef AR9170_QUEUE_DEBUG |
1464 | printk(KERN_DEBUG "%s: frames failed =>\n", | 1810 | printk(KERN_DEBUG "%s: frames failed %d =>\n", |
1465 | wiphy_name(ar->hw->wiphy), frames_failed); | 1811 | wiphy_name(ar->hw->wiphy), frames_failed); |
1466 | #endif /* AR9170_QUEUE_DEBUG */ | 1812 | #endif /* AR9170_QUEUE_DEBUG */ |
1467 | 1813 | ||
1468 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 1814 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
1469 | ar->tx_stats[i].len -= frames_failed; | 1815 | ar->tx_stats[i].len -= frames_failed; |
1470 | ar->tx_stats[i].count -= frames_failed; | 1816 | ar->tx_stats[i].count -= frames_failed; |
1817 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1818 | printk(KERN_DEBUG "%s: wake queue %d\n", | ||
1819 | wiphy_name(ar->hw->wiphy), i); | ||
1820 | __ar9170_dump_txstats(ar); | ||
1821 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1471 | ieee80211_wake_queue(ar->hw, i); | 1822 | ieee80211_wake_queue(ar->hw, i); |
1472 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1823 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1473 | } | 1824 | } |
@@ -1479,6 +1830,90 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1479 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 1830 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); |
1480 | } | 1831 | } |
1481 | 1832 | ||
1833 | static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) | ||
1834 | { | ||
1835 | struct ieee80211_tx_info *txinfo; | ||
1836 | struct ar9170_sta_info *sta_info; | ||
1837 | struct ar9170_sta_tid *agg; | ||
1838 | struct sk_buff *iter; | ||
1839 | unsigned long flags, f2; | ||
1840 | unsigned int max; | ||
1841 | u16 tid, seq, qseq; | ||
1842 | bool run = false, queue = false; | ||
1843 | |||
1844 | tid = ar9170_get_tid(skb); | ||
1845 | seq = ar9170_get_seq(skb); | ||
1846 | txinfo = IEEE80211_SKB_CB(skb); | ||
1847 | sta_info = (void *) txinfo->control.sta->drv_priv; | ||
1848 | agg = &sta_info->agg[tid]; | ||
1849 | max = sta_info->ampdu_max_len; | ||
1850 | |||
1851 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1852 | |||
1853 | if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { | ||
1854 | #ifdef AR9170_TXAGG_DEBUG | ||
1855 | printk(KERN_DEBUG "%s: BlockACK session not fully initialized " | ||
1856 | "for ESS:%pM tid:%d state:%d.\n", | ||
1857 | wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, | ||
1858 | agg->state); | ||
1859 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1860 | goto err_unlock; | ||
1861 | } | ||
1862 | |||
1863 | if (!agg->active) { | ||
1864 | agg->active = true; | ||
1865 | agg->ssn = seq; | ||
1866 | queue = true; | ||
1867 | } | ||
1868 | |||
1869 | /* check if seq is within the BA window */ | ||
1870 | if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { | ||
1871 | #ifdef AR9170_TXAGG_DEBUG | ||
1872 | printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " | ||
1873 | "fit into BA window (%d - %d)\n", | ||
1874 | wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, | ||
1875 | (agg->ssn + max) & 0xfff); | ||
1876 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1877 | goto err_unlock; | ||
1878 | } | ||
1879 | |||
1880 | spin_lock_irqsave(&agg->queue.lock, f2); | ||
1881 | |||
1882 | skb_queue_reverse_walk(&agg->queue, iter) { | ||
1883 | qseq = ar9170_get_seq(iter); | ||
1884 | |||
1885 | if (GET_NEXT_SEQ(qseq) == seq) { | ||
1886 | __skb_queue_after(&agg->queue, iter, skb); | ||
1887 | goto queued; | ||
1888 | } | ||
1889 | } | ||
1890 | |||
1891 | __skb_queue_head(&agg->queue, skb); | ||
1892 | |||
1893 | queued: | ||
1894 | spin_unlock_irqrestore(&agg->queue.lock, f2); | ||
1895 | |||
1896 | #ifdef AR9170_TXAGG_DEBUG | ||
1897 | printk(KERN_DEBUG "%s: new aggregate %p queued.\n", | ||
1898 | wiphy_name(ar->hw->wiphy), skb); | ||
1899 | __ar9170_dump_txqueue(ar, &agg->queue); | ||
1900 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1901 | |||
1902 | if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) | ||
1903 | run = true; | ||
1904 | |||
1905 | if (queue) | ||
1906 | list_add_tail(&agg->list, &ar->tx_ampdu_list); | ||
1907 | |||
1908 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1909 | return run; | ||
1910 | |||
1911 | err_unlock: | ||
1912 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1913 | dev_kfree_skb_irq(skb); | ||
1914 | return false; | ||
1915 | } | ||
1916 | |||
1482 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1917 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1483 | { | 1918 | { |
1484 | struct ar9170 *ar = hw->priv; | 1919 | struct ar9170 *ar = hw->priv; |
@@ -1492,8 +1927,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1492 | 1927 | ||
1493 | info = IEEE80211_SKB_CB(skb); | 1928 | info = IEEE80211_SKB_CB(skb); |
1494 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1929 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1495 | /* drop frame, we do not allow TX A-MPDU aggregation yet. */ | 1930 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1496 | goto err_free; | 1931 | |
1932 | if (run || !ar->tx_ampdu_pending) | ||
1933 | ar9170_tx_ampdu(ar); | ||
1497 | } else { | 1934 | } else { |
1498 | unsigned int queue = skb_get_queue_mapping(skb); | 1935 | unsigned int queue = skb_get_queue_mapping(skb); |
1499 | 1936 | ||
@@ -1931,6 +2368,53 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, | |||
1931 | enum sta_notify_cmd cmd, | 2368 | enum sta_notify_cmd cmd, |
1932 | struct ieee80211_sta *sta) | 2369 | struct ieee80211_sta *sta) |
1933 | { | 2370 | { |
2371 | struct ar9170 *ar = hw->priv; | ||
2372 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2373 | unsigned int i; | ||
2374 | |||
2375 | switch (cmd) { | ||
2376 | case STA_NOTIFY_ADD: | ||
2377 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2378 | |||
2379 | if (!sta->ht_cap.ht_supported) | ||
2380 | break; | ||
2381 | |||
2382 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | ||
2383 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | ||
2384 | |||
2385 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | ||
2386 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | ||
2387 | |||
2388 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2389 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | ||
2390 | sta_info->agg[i].active = false; | ||
2391 | sta_info->agg[i].ssn = 0; | ||
2392 | sta_info->agg[i].retry = 0; | ||
2393 | sta_info->agg[i].tid = i; | ||
2394 | INIT_LIST_HEAD(&sta_info->agg[i].list); | ||
2395 | skb_queue_head_init(&sta_info->agg[i].queue); | ||
2396 | } | ||
2397 | |||
2398 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | ||
2399 | break; | ||
2400 | |||
2401 | case STA_NOTIFY_REMOVE: | ||
2402 | if (!sta->ht_cap.ht_supported) | ||
2403 | break; | ||
2404 | |||
2405 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2406 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | ||
2407 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2408 | } | ||
2409 | |||
2410 | break; | ||
2411 | |||
2412 | default: | ||
2413 | break; | ||
2414 | } | ||
2415 | |||
2416 | if (IS_STARTED(ar) && ar->filter_changed) | ||
2417 | queue_work(ar->hw->workqueue, &ar->filter_config_work); | ||
1934 | } | 2418 | } |
1935 | 2419 | ||
1936 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2420 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -1985,18 +2469,65 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
1985 | enum ieee80211_ampdu_mlme_action action, | 2469 | enum ieee80211_ampdu_mlme_action action, |
1986 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2470 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
1987 | { | 2471 | { |
2472 | struct ar9170 *ar = hw->priv; | ||
2473 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2474 | struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; | ||
2475 | unsigned long flags; | ||
2476 | |||
2477 | if (!modparam_ht) | ||
2478 | return -EOPNOTSUPP; | ||
2479 | |||
1988 | switch (action) { | 2480 | switch (action) { |
2481 | case IEEE80211_AMPDU_TX_START: | ||
2482 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2483 | if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || | ||
2484 | !list_empty(&tid_info->list)) { | ||
2485 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2486 | #ifdef AR9170_TXAGG_DEBUG | ||
2487 | printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " | ||
2488 | "is in a very bad state!\n", | ||
2489 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2490 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2491 | return -EBUSY; | ||
2492 | } | ||
2493 | |||
2494 | *ssn = tid_info->ssn; | ||
2495 | tid_info->state = AR9170_TID_STATE_PROGRESS; | ||
2496 | tid_info->active = false; | ||
2497 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2498 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | ||
2499 | break; | ||
2500 | |||
2501 | case IEEE80211_AMPDU_TX_STOP: | ||
2502 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2503 | tid_info->state = AR9170_TID_STATE_SHUTDOWN; | ||
2504 | list_del_init(&tid_info->list); | ||
2505 | tid_info->active = false; | ||
2506 | skb_queue_purge(&tid_info->queue); | ||
2507 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2508 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | ||
2509 | break; | ||
2510 | |||
2511 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2512 | #ifdef AR9170_TXAGG_DEBUG | ||
2513 | printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", | ||
2514 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2515 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2516 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2517 | sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; | ||
2518 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2519 | break; | ||
2520 | |||
1989 | case IEEE80211_AMPDU_RX_START: | 2521 | case IEEE80211_AMPDU_RX_START: |
1990 | case IEEE80211_AMPDU_RX_STOP: | 2522 | case IEEE80211_AMPDU_RX_STOP: |
1991 | /* | 2523 | /* Handled by firmware */ |
1992 | * Something goes wrong -- RX locks up | 2524 | break; |
1993 | * after a while of receiving aggregated | 2525 | |
1994 | * frames -- not enabling for now. | ||
1995 | */ | ||
1996 | return -EOPNOTSUPP; | ||
1997 | default: | 2526 | default: |
1998 | return -EOPNOTSUPP; | 2527 | return -EOPNOTSUPP; |
1999 | } | 2528 | } |
2529 | |||
2530 | return 0; | ||
2000 | } | 2531 | } |
2001 | 2532 | ||
2002 | static const struct ieee80211_ops ar9170_ops = { | 2533 | static const struct ieee80211_ops ar9170_ops = { |
@@ -2045,6 +2576,8 @@ void *ar9170_alloc(size_t priv_size) | |||
2045 | mutex_init(&ar->mutex); | 2576 | mutex_init(&ar->mutex); |
2046 | spin_lock_init(&ar->cmdlock); | 2577 | spin_lock_init(&ar->cmdlock); |
2047 | spin_lock_init(&ar->tx_stats_lock); | 2578 | spin_lock_init(&ar->tx_stats_lock); |
2579 | spin_lock_init(&ar->tx_ampdu_list_lock); | ||
2580 | skb_queue_head_init(&ar->tx_status_ampdu); | ||
2048 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 2581 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
2049 | skb_queue_head_init(&ar->tx_status[i]); | 2582 | skb_queue_head_init(&ar->tx_status[i]); |
2050 | skb_queue_head_init(&ar->tx_pending[i]); | 2583 | skb_queue_head_init(&ar->tx_pending[i]); |
@@ -2053,6 +2586,7 @@ void *ar9170_alloc(size_t priv_size) | |||
2053 | INIT_WORK(&ar->filter_config_work, ar9170_set_filters); | 2586 | INIT_WORK(&ar->filter_config_work, ar9170_set_filters); |
2054 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); | 2587 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); |
2055 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); | 2588 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); |
2589 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | ||
2056 | 2590 | ||
2057 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ | 2591 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ |
2058 | ar->channel = &ar9170_2ghz_chantable[0]; | 2592 | ar->channel = &ar9170_2ghz_chantable[0]; |
@@ -2066,6 +2600,13 @@ void *ar9170_alloc(size_t priv_size) | |||
2066 | IEEE80211_HW_SIGNAL_DBM | | 2600 | IEEE80211_HW_SIGNAL_DBM | |
2067 | IEEE80211_HW_NOISE_DBM; | 2601 | IEEE80211_HW_NOISE_DBM; |
2068 | 2602 | ||
2603 | if (modparam_ht) { | ||
2604 | ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
2605 | } else { | ||
2606 | ar9170_band_2GHz.ht_cap.ht_supported = false; | ||
2607 | ar9170_band_5GHz.ht_cap.ht_supported = false; | ||
2608 | } | ||
2609 | |||
2069 | ar->hw->queues = __AR9170_NUM_TXQ; | 2610 | ar->hw->queues = __AR9170_NUM_TXQ; |
2070 | ar->hw->extra_tx_headroom = 8; | 2611 | ar->hw->extra_tx_headroom = 8; |
2071 | ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); | 2612 | ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); |
@@ -2087,10 +2628,10 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2087 | { | 2628 | { |
2088 | #define RW 8 /* number of words to read at once */ | 2629 | #define RW 8 /* number of words to read at once */ |
2089 | #define RB (sizeof(u32) * RW) | 2630 | #define RB (sizeof(u32) * RW) |
2090 | DECLARE_MAC_BUF(mbuf); | ||
2091 | u8 *eeprom = (void *)&ar->eeprom; | 2631 | u8 *eeprom = (void *)&ar->eeprom; |
2092 | u8 *addr = ar->eeprom.mac_address; | 2632 | u8 *addr = ar->eeprom.mac_address; |
2093 | __le32 offsets[RW]; | 2633 | __le32 offsets[RW]; |
2634 | unsigned int rx_streams, tx_streams, tx_params = 0; | ||
2094 | int i, j, err, bands = 0; | 2635 | int i, j, err, bands = 0; |
2095 | 2636 | ||
2096 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); | 2637 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); |
@@ -2127,6 +2668,20 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2127 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; | 2668 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; |
2128 | bands++; | 2669 | bands++; |
2129 | } | 2670 | } |
2671 | |||
2672 | rx_streams = hweight8(ar->eeprom.rx_mask); | ||
2673 | tx_streams = hweight8(ar->eeprom.tx_mask); | ||
2674 | |||
2675 | if (rx_streams != tx_streams) | ||
2676 | tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; | ||
2677 | |||
2678 | if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) | ||
2679 | tx_params = (tx_streams - 1) << | ||
2680 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2681 | |||
2682 | ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2683 | ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2684 | |||
2130 | /* | 2685 | /* |
2131 | * I measured this, a bandswitch takes roughly | 2686 | * I measured this, a bandswitch takes roughly |
2132 | * 135 ms and a frequency switch about 80. | 2687 | * 135 ms and a frequency switch about 80. |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 6809b54a2ad7..debad07d9900 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -339,9 +339,9 @@ | |||
339 | #define AR5K_SISR2 0x008c /* Register Address [5211+] */ | 339 | #define AR5K_SISR2 0x008c /* Register Address [5211+] */ |
340 | #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ | 340 | #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ |
341 | #define AR5K_SISR2_QCU_TXURN_S 0 | 341 | #define AR5K_SISR2_QCU_TXURN_S 0 |
342 | #define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ | 342 | #define AR5K_SISR2_MCABT 0x00010000 /* Master Cycle Abort */ |
343 | #define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ | 343 | #define AR5K_SISR2_SSERR 0x00020000 /* Signaled System Error */ |
344 | #define AR5K_SISR2_DPERR 0x00400000 /* Bus parity error */ | 344 | #define AR5K_SISR2_DPERR 0x00040000 /* Bus parity error */ |
345 | #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ | 345 | #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ |
346 | #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ | 346 | #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ |
347 | #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ | 347 | #define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ |
@@ -430,9 +430,9 @@ | |||
430 | #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ | 430 | #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ |
431 | #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ | 431 | #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ |
432 | #define AR5K_SIMR2_QCU_TXURN_S 0 | 432 | #define AR5K_SIMR2_QCU_TXURN_S 0 |
433 | #define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ | 433 | #define AR5K_SIMR2_MCABT 0x00010000 /* Master Cycle Abort */ |
434 | #define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ | 434 | #define AR5K_SIMR2_SSERR 0x00020000 /* Signaled System Error */ |
435 | #define AR5K_SIMR2_DPERR 0x00400000 /* Bus parity error */ | 435 | #define AR5K_SIMR2_DPERR 0x00040000 /* Bus parity error */ |
436 | #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ | 436 | #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ |
437 | #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ | 437 | #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ |
438 | #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ | 438 | #define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index eb9d5228cb6c..751885a5df47 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -164,7 +164,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
164 | #define WME_NUM_TID 16 | 164 | #define WME_NUM_TID 16 |
165 | #define ATH_TXBUF 512 | 165 | #define ATH_TXBUF 512 |
166 | #define ATH_TXMAXTRY 13 | 166 | #define ATH_TXMAXTRY 13 |
167 | #define ATH_11N_TXMAXTRY 10 | ||
168 | #define ATH_MGT_TXMAXTRY 4 | 167 | #define ATH_MGT_TXMAXTRY 4 |
169 | #define WME_BA_BMP_SIZE 64 | 168 | #define WME_BA_BMP_SIZE 64 |
170 | #define WME_MAX_BA WME_BA_BMP_SIZE | 169 | #define WME_MAX_BA WME_BA_BMP_SIZE |
@@ -226,6 +225,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
226 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) | 225 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) |
227 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) | 226 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
228 | 227 | ||
228 | #define ATH_TX_COMPLETE_POLL_INT 1000 | ||
229 | |||
229 | enum ATH_AGGR_STATUS { | 230 | enum ATH_AGGR_STATUS { |
230 | ATH_AGGR_DONE, | 231 | ATH_AGGR_DONE, |
231 | ATH_AGGR_BAW_CLOSED, | 232 | ATH_AGGR_BAW_CLOSED, |
@@ -241,6 +242,7 @@ struct ath_txq { | |||
241 | u8 axq_aggr_depth; | 242 | u8 axq_aggr_depth; |
242 | u32 axq_totalqueued; | 243 | u32 axq_totalqueued; |
243 | bool stopped; | 244 | bool stopped; |
245 | bool axq_tx_inprogress; | ||
244 | struct ath_buf *axq_linkbuf; | 246 | struct ath_buf *axq_linkbuf; |
245 | 247 | ||
246 | /* first desc of the last descriptor that contains CTS */ | 248 | /* first desc of the last descriptor that contains CTS */ |
@@ -291,12 +293,28 @@ struct ath_tx_control { | |||
291 | #define ATH_TX_XRETRY 0x02 | 293 | #define ATH_TX_XRETRY 0x02 |
292 | #define ATH_TX_BAR 0x04 | 294 | #define ATH_TX_BAR 0x04 |
293 | 295 | ||
296 | #define ATH_RSSI_LPF_LEN 10 | ||
297 | #define RSSI_LPF_THRESHOLD -20 | ||
298 | #define ATH9K_RSSI_BAD 0x80 | ||
299 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) | ||
300 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) | ||
301 | #define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) | ||
302 | #define ATH_LPF_RSSI(x, y, len) \ | ||
303 | ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) | ||
304 | #define ATH_RSSI_LPF(x, y) do { \ | ||
305 | if ((y) >= RSSI_LPF_THRESHOLD) \ | ||
306 | x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | ||
307 | } while (0) | ||
308 | #define ATH_EP_RND(x, mul) \ | ||
309 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
310 | |||
294 | struct ath_node { | 311 | struct ath_node { |
295 | struct ath_softc *an_sc; | 312 | struct ath_softc *an_sc; |
296 | struct ath_atx_tid tid[WME_NUM_TID]; | 313 | struct ath_atx_tid tid[WME_NUM_TID]; |
297 | struct ath_atx_ac ac[WME_NUM_AC]; | 314 | struct ath_atx_ac ac[WME_NUM_AC]; |
298 | u16 maxampdu; | 315 | u16 maxampdu; |
299 | u8 mpdudensity; | 316 | u8 mpdudensity; |
317 | int last_rssi; | ||
300 | }; | 318 | }; |
301 | 319 | ||
302 | struct ath_tx { | 320 | struct ath_tx { |
@@ -541,6 +559,7 @@ struct ath_softc { | |||
541 | spinlock_t sc_resetlock; | 559 | spinlock_t sc_resetlock; |
542 | spinlock_t sc_serial_rw; | 560 | spinlock_t sc_serial_rw; |
543 | spinlock_t ani_lock; | 561 | spinlock_t ani_lock; |
562 | spinlock_t sc_pm_lock; | ||
544 | struct mutex mutex; | 563 | struct mutex mutex; |
545 | 564 | ||
546 | u8 curbssid[ETH_ALEN]; | 565 | u8 curbssid[ETH_ALEN]; |
@@ -557,7 +576,7 @@ struct ath_softc { | |||
557 | u32 keymax; | 576 | u32 keymax; |
558 | DECLARE_BITMAP(keymap, ATH_KEYMAX); | 577 | DECLARE_BITMAP(keymap, ATH_KEYMAX); |
559 | u8 splitmic; | 578 | u8 splitmic; |
560 | atomic_t ps_usecount; | 579 | unsigned long ps_usecount; |
561 | enum ath9k_int imask; | 580 | enum ath9k_int imask; |
562 | enum ath9k_ht_extprotspacing ht_extprotspacing; | 581 | enum ath9k_ht_extprotspacing ht_extprotspacing; |
563 | enum ath9k_ht_macmode tx_chan_width; | 582 | enum ath9k_ht_macmode tx_chan_width; |
@@ -590,6 +609,7 @@ struct ath_softc { | |||
590 | #endif | 609 | #endif |
591 | struct ath_bus_ops *bus_ops; | 610 | struct ath_bus_ops *bus_ops; |
592 | struct ath_beacon_config cur_beacon_conf; | 611 | struct ath_beacon_config cur_beacon_conf; |
612 | struct delayed_work tx_complete_work; | ||
593 | }; | 613 | }; |
594 | 614 | ||
595 | struct ath_wiphy { | 615 | struct ath_wiphy { |
@@ -654,27 +674,8 @@ static inline int ath_ahb_init(void) { return 0; }; | |||
654 | static inline void ath_ahb_exit(void) {}; | 674 | static inline void ath_ahb_exit(void) {}; |
655 | #endif | 675 | #endif |
656 | 676 | ||
657 | static inline void ath9k_ps_wakeup(struct ath_softc *sc) | 677 | void ath9k_ps_wakeup(struct ath_softc *sc); |
658 | { | 678 | void ath9k_ps_restore(struct ath_softc *sc); |
659 | if (atomic_inc_return(&sc->ps_usecount) == 1) | ||
660 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { | ||
661 | sc->sc_ah->restore_mode = sc->sc_ah->power_mode; | ||
662 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | static inline void ath9k_ps_restore(struct ath_softc *sc) | ||
667 | { | ||
668 | if (atomic_dec_and_test(&sc->ps_usecount)) | ||
669 | if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && | ||
670 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | ||
671 | SC_OP_WAIT_FOR_CAB | | ||
672 | SC_OP_WAIT_FOR_PSPOLL_DATA | | ||
673 | SC_OP_WAIT_FOR_TX_ACK))) | ||
674 | ath9k_hw_setpower(sc->sc_ah, | ||
675 | sc->sc_ah->restore_mode); | ||
676 | } | ||
677 | |||
678 | 679 | ||
679 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw); | 680 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw); |
680 | int ath9k_wiphy_add(struct ath_softc *sc); | 681 | int ath9k_wiphy_add(struct ath_softc *sc); |
@@ -690,6 +691,7 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | |||
690 | struct ath_wiphy *selected); | 691 | struct ath_wiphy *selected); |
691 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | 692 | bool ath9k_wiphy_scanning(struct ath_softc *sc); |
692 | void ath9k_wiphy_work(struct work_struct *work); | 693 | void ath9k_wiphy_work(struct work_struct *work); |
694 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | ||
693 | 695 | ||
694 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); | 696 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); |
695 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); | 697 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index a32d7e7fecbe..1f0c5fe4a68b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -691,15 +691,22 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
691 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | 691 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) |
692 | { | 692 | { |
693 | int i, j; | 693 | int i, j; |
694 | s16 noise_floor; | ||
695 | |||
696 | if (AR_SREV_9280(ah)) | ||
697 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | ||
698 | else if (AR_SREV_9285(ah)) | ||
699 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; | ||
700 | else | ||
701 | noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; | ||
694 | 702 | ||
695 | for (i = 0; i < NUM_NF_READINGS; i++) { | 703 | for (i = 0; i < NUM_NF_READINGS; i++) { |
696 | ah->nfCalHist[i].currIndex = 0; | 704 | ah->nfCalHist[i].currIndex = 0; |
697 | ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE; | 705 | ah->nfCalHist[i].privNF = noise_floor; |
698 | ah->nfCalHist[i].invalidNFcount = | 706 | ah->nfCalHist[i].invalidNFcount = |
699 | AR_PHY_CCA_FILTERWINDOW_LENGTH; | 707 | AR_PHY_CCA_FILTERWINDOW_LENGTH; |
700 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { | 708 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { |
701 | ah->nfCalHist[i].nfCalBuffer[j] = | 709 | ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; |
702 | AR_PHY_CCA_MAX_GOOD_VALUE; | ||
703 | } | 710 | } |
704 | } | 711 | } |
705 | } | 712 | } |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index fe5367f14148..547e697b9055 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -25,7 +25,9 @@ extern const struct ath9k_percal_data adc_dc_cal_multi_sample; | |||
25 | extern const struct ath9k_percal_data adc_dc_cal_single_sample; | 25 | extern const struct ath9k_percal_data adc_dc_cal_single_sample; |
26 | extern const struct ath9k_percal_data adc_init_dc_cal; | 26 | extern const struct ath9k_percal_data adc_init_dc_cal; |
27 | 27 | ||
28 | #define AR_PHY_CCA_MAX_GOOD_VALUE -85 | 28 | #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 |
29 | #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 | ||
30 | #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 | ||
29 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 | 31 | #define AR_PHY_CCA_MAX_HIGH_VALUE -62 |
30 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 | 32 | #define AR_PHY_CCA_MIN_BAD_VALUE -140 |
31 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 | 33 | #define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index d82a0f97e6f5..df41ed5fd7c4 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -1208,6 +1208,19 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
1208 | pModal->xatten2Margin[0]); | 1208 | pModal->xatten2Margin[0]); |
1209 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 1209 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
1210 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); | 1210 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); |
1211 | |||
1212 | /* Set the block 1 value to block 0 value */ | ||
1213 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1214 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1215 | pModal->bswMargin[0]); | ||
1216 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1217 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
1218 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1219 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1220 | pModal->xatten2Margin[0]); | ||
1221 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
1222 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
1223 | pModal->xatten2Db[0]); | ||
1211 | } | 1224 | } |
1212 | 1225 | ||
1213 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | 1226 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, |
@@ -1215,6 +1228,11 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
1215 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | 1228 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, |
1216 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | 1229 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); |
1217 | 1230 | ||
1231 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
1232 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
1233 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
1234 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
1235 | |||
1218 | if (AR_SREV_9285_11(ah)) | 1236 | if (AR_SREV_9285_11(ah)) |
1219 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | 1237 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); |
1220 | } | 1238 | } |
@@ -1239,7 +1257,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1239 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); | 1257 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); |
1240 | 1258 | ||
1241 | /* Initialize Ant Diversity settings from EEPROM */ | 1259 | /* Initialize Ant Diversity settings from EEPROM */ |
1242 | if (pModal->version == 3) { | 1260 | if (pModal->version >= 3) { |
1243 | ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); | 1261 | ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); |
1244 | ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); | 1262 | ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); |
1245 | regVal = REG_READ(ah, 0x99ac); | 1263 | regVal = REG_READ(ah, 0x99ac); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index cffb0789f669..605803ae9ed8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2728,7 +2728,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2728 | return true; | 2728 | return true; |
2729 | } | 2729 | } |
2730 | 2730 | ||
2731 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | 2731 | static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, |
2732 | enum ath9k_power_mode mode) | ||
2732 | { | 2733 | { |
2733 | int status = true, setChip = true; | 2734 | int status = true, setChip = true; |
2734 | static const char *modes[] = { | 2735 | static const char *modes[] = { |
@@ -2762,6 +2763,55 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
2762 | return status; | 2763 | return status; |
2763 | } | 2764 | } |
2764 | 2765 | ||
2766 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | ||
2767 | { | ||
2768 | unsigned long flags; | ||
2769 | bool ret; | ||
2770 | |||
2771 | spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags); | ||
2772 | ret = ath9k_hw_setpower_nolock(ah, mode); | ||
2773 | spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags); | ||
2774 | |||
2775 | return ret; | ||
2776 | } | ||
2777 | |||
2778 | void ath9k_ps_wakeup(struct ath_softc *sc) | ||
2779 | { | ||
2780 | unsigned long flags; | ||
2781 | |||
2782 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
2783 | if (++sc->ps_usecount != 1) | ||
2784 | goto unlock; | ||
2785 | |||
2786 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { | ||
2787 | sc->sc_ah->restore_mode = sc->sc_ah->power_mode; | ||
2788 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); | ||
2789 | } | ||
2790 | |||
2791 | unlock: | ||
2792 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
2793 | } | ||
2794 | |||
2795 | void ath9k_ps_restore(struct ath_softc *sc) | ||
2796 | { | ||
2797 | unsigned long flags; | ||
2798 | |||
2799 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
2800 | if (--sc->ps_usecount != 0) | ||
2801 | goto unlock; | ||
2802 | |||
2803 | if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && | ||
2804 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | ||
2805 | SC_OP_WAIT_FOR_CAB | | ||
2806 | SC_OP_WAIT_FOR_PSPOLL_DATA | | ||
2807 | SC_OP_WAIT_FOR_TX_ACK))) | ||
2808 | ath9k_hw_setpower_nolock(sc->sc_ah, | ||
2809 | sc->sc_ah->restore_mode); | ||
2810 | |||
2811 | unlock: | ||
2812 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
2813 | } | ||
2814 | |||
2765 | /* | 2815 | /* |
2766 | * Helper for ASPM support. | 2816 | * Helper for ASPM support. |
2767 | * | 2817 | * |
@@ -3305,7 +3355,6 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3305 | } | 3355 | } |
3306 | 3356 | ||
3307 | if (eeval & AR5416_OPFLAGS_11G) { | 3357 | if (eeval & AR5416_OPFLAGS_11G) { |
3308 | set_bit(ATH9K_MODE_11B, pCap->wireless_modes); | ||
3309 | set_bit(ATH9K_MODE_11G, pCap->wireless_modes); | 3358 | set_bit(ATH9K_MODE_11G, pCap->wireless_modes); |
3310 | if (ah->config.ht_enable) { | 3359 | if (ah->config.ht_enable) { |
3311 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) | 3360 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) |
@@ -3791,19 +3840,14 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) | |||
3791 | 3840 | ||
3792 | void ath9k_hw_reset_tsf(struct ath_hw *ah) | 3841 | void ath9k_hw_reset_tsf(struct ath_hw *ah) |
3793 | { | 3842 | { |
3794 | int count; | 3843 | ath9k_ps_wakeup(ah->ah_sc); |
3844 | if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, | ||
3845 | AH_TSF_WRITE_TIMEOUT)) | ||
3846 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3847 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); | ||
3795 | 3848 | ||
3796 | count = 0; | ||
3797 | while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) { | ||
3798 | count++; | ||
3799 | if (count > 10) { | ||
3800 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | ||
3801 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); | ||
3802 | break; | ||
3803 | } | ||
3804 | udelay(10); | ||
3805 | } | ||
3806 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); | 3849 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); |
3850 | ath9k_ps_restore(ah->ah_sc); | ||
3807 | } | 3851 | } |
3808 | 3852 | ||
3809 | bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | 3853 | bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 9d0b31ad4603..28bffdb365a2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -95,6 +95,7 @@ | |||
95 | 95 | ||
96 | #define MAX_RATE_POWER 63 | 96 | #define MAX_RATE_POWER 63 |
97 | #define AH_WAIT_TIMEOUT 100000 /* (us) */ | 97 | #define AH_WAIT_TIMEOUT 100000 /* (us) */ |
98 | #define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ | ||
98 | #define AH_TIME_QUANTUM 10 | 99 | #define AH_TIME_QUANTUM 10 |
99 | #define AR_KEYTABLE_SIZE 128 | 100 | #define AR_KEYTABLE_SIZE 128 |
100 | #define POWER_UP_TIME 200000 | 101 | #define POWER_UP_TIME 200000 |
@@ -113,15 +114,14 @@ | |||
113 | 114 | ||
114 | enum wireless_mode { | 115 | enum wireless_mode { |
115 | ATH9K_MODE_11A = 0, | 116 | ATH9K_MODE_11A = 0, |
116 | ATH9K_MODE_11B = 2, | 117 | ATH9K_MODE_11G, |
117 | ATH9K_MODE_11G = 3, | 118 | ATH9K_MODE_11NA_HT20, |
118 | ATH9K_MODE_11NA_HT20 = 6, | 119 | ATH9K_MODE_11NG_HT20, |
119 | ATH9K_MODE_11NG_HT20 = 7, | 120 | ATH9K_MODE_11NA_HT40PLUS, |
120 | ATH9K_MODE_11NA_HT40PLUS = 8, | 121 | ATH9K_MODE_11NA_HT40MINUS, |
121 | ATH9K_MODE_11NA_HT40MINUS = 9, | 122 | ATH9K_MODE_11NG_HT40PLUS, |
122 | ATH9K_MODE_11NG_HT40PLUS = 10, | 123 | ATH9K_MODE_11NG_HT40MINUS, |
123 | ATH9K_MODE_11NG_HT40MINUS = 11, | 124 | ATH9K_MODE_MAX, |
124 | ATH9K_MODE_MAX | ||
125 | }; | 125 | }; |
126 | 126 | ||
127 | enum ath9k_hw_caps { | 127 | enum ath9k_hw_caps { |
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index e2f0a34b79a1..f67a2a96cc5c 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h | |||
@@ -2782,7 +2782,7 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2782 | { 0x00008338, 0x00ff0000 }, | 2782 | { 0x00008338, 0x00ff0000 }, |
2783 | { 0x0000833c, 0x00000000 }, | 2783 | { 0x0000833c, 0x00000000 }, |
2784 | { 0x00008340, 0x000107ff }, | 2784 | { 0x00008340, 0x000107ff }, |
2785 | { 0x00008344, 0x00581043 }, | 2785 | { 0x00008344, 0x00481043 }, |
2786 | { 0x00009808, 0x00000000 }, | 2786 | { 0x00009808, 0x00000000 }, |
2787 | { 0x0000980c, 0xafa68e30 }, | 2787 | { 0x0000980c, 0xafa68e30 }, |
2788 | { 0x00009810, 0xfd14e000 }, | 2788 | { 0x00009810, 0xfd14e000 }, |
@@ -3439,7 +3439,7 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { | |||
3439 | {0x00004044, 0x00000000 }, | 3439 | {0x00004044, 0x00000000 }, |
3440 | }; | 3440 | }; |
3441 | 3441 | ||
3442 | /* AR9285 */ | 3442 | /* AR9285 Revsion 10*/ |
3443 | static const u_int32_t ar9285Modes_9285[][6] = { | 3443 | static const u_int32_t ar9285Modes_9285[][6] = { |
3444 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 3444 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
3445 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 3445 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -3955,7 +3955,7 @@ static const u_int32_t ar9285Common_9285[][2] = { | |||
3955 | { 0x00008338, 0x00000000 }, | 3955 | { 0x00008338, 0x00000000 }, |
3956 | { 0x0000833c, 0x00000000 }, | 3956 | { 0x0000833c, 0x00000000 }, |
3957 | { 0x00008340, 0x00010380 }, | 3957 | { 0x00008340, 0x00010380 }, |
3958 | { 0x00008344, 0x00581043 }, | 3958 | { 0x00008344, 0x00481043 }, |
3959 | { 0x00009808, 0x00000000 }, | 3959 | { 0x00009808, 0x00000000 }, |
3960 | { 0x0000980c, 0xafe68e30 }, | 3960 | { 0x0000980c, 0xafe68e30 }, |
3961 | { 0x00009810, 0xfd14e000 }, | 3961 | { 0x00009810, 0xfd14e000 }, |
@@ -4121,8 +4121,9 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { | |||
4121 | {0x00004044, 0x00000000 }, | 4121 | {0x00004044, 0x00000000 }, |
4122 | }; | 4122 | }; |
4123 | 4123 | ||
4124 | /* AR9285 v1_2 PCI Register Writes. Created: 03/04/09 */ | 4124 | /* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ |
4125 | static const u_int32_t ar9285Modes_9285_1_2[][6] = { | 4125 | static const u_int32_t ar9285Modes_9285_1_2[][6] = { |
4126 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ | ||
4126 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 4127 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
4127 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 4128 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
4128 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, | 4129 | { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, |
@@ -4139,6 +4140,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4139 | { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, | 4140 | { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, |
4140 | { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, | 4141 | { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, |
4141 | { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, | 4142 | { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, |
4143 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, | ||
4142 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | 4144 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, |
4143 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, | 4145 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, |
4144 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, | 4146 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, |
@@ -4419,6 +4421,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4419 | { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, | 4421 | { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, |
4420 | { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, | 4422 | { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, |
4421 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, | 4423 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, |
4424 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, | ||
4422 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | 4425 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, |
4423 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | 4426 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, |
4424 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, | 4427 | { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, |
@@ -4618,7 +4621,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4618 | { 0x00008338, 0x00ff0000 }, | 4621 | { 0x00008338, 0x00ff0000 }, |
4619 | { 0x0000833c, 0x00000000 }, | 4622 | { 0x0000833c, 0x00000000 }, |
4620 | { 0x00008340, 0x00010380 }, | 4623 | { 0x00008340, 0x00010380 }, |
4621 | { 0x00008344, 0x00581043 }, | 4624 | { 0x00008344, 0x00481043 }, |
4622 | { 0x00009808, 0x00000000 }, | 4625 | { 0x00009808, 0x00000000 }, |
4623 | { 0x0000980c, 0xafe68e30 }, | 4626 | { 0x0000980c, 0xafe68e30 }, |
4624 | { 0x00009810, 0xfd14e000 }, | 4627 | { 0x00009810, 0xfd14e000 }, |
@@ -4752,18 +4755,18 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4752 | static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { | 4755 | static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { |
4753 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ | 4756 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ |
4754 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 4757 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
4755 | { 0x0000a304, 0x00000000, 0x00000000, 0x00005200, 0x00005200, 0x00000000 }, | 4758 | { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, |
4756 | { 0x0000a308, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, | 4759 | { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, |
4757 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, | 4760 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, |
4758 | { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, | 4761 | { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, |
4759 | { 0x0000a314, 0x00000000, 0x00000000, 0x0000f440, 0x0000f440, 0x00000000 }, | 4762 | { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, |
4760 | { 0x0000a318, 0x00000000, 0x00000000, 0x00014640, 0x00014640, 0x00000000 }, | 4763 | { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, |
4761 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00018680, 0x00018680, 0x00000000 }, | 4764 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, |
4762 | { 0x0000a320, 0x00000000, 0x00000000, 0x00019841, 0x00019841, 0x00000000 }, | 4765 | { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, |
4763 | { 0x0000a324, 0x00000000, 0x00000000, 0x0001ca40, 0x0001ca40, 0x00000000 }, | 4766 | { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, |
4764 | { 0x0000a328, 0x00000000, 0x00000000, 0x0001fa80, 0x0001fa80, 0x00000000 }, | 4767 | { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, |
4765 | { 0x0000a32c, 0x00000000, 0x00000000, 0x00023ac0, 0x00023ac0, 0x00000000 }, | 4768 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, |
4766 | { 0x0000a330, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, | 4769 | { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, |
4767 | { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, | 4770 | { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, |
4768 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | 4771 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, |
4769 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | 4772 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, |
@@ -4776,13 +4779,13 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { | |||
4776 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, | 4779 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, |
4777 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | 4780 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, |
4778 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | 4781 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
4779 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | 4782 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, |
4780 | { 0x0000a278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | 4783 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, |
4781 | { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, | 4784 | { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, |
4782 | { 0x0000a394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | 4785 | { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, |
4783 | { 0x0000a398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, | 4786 | { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, |
4784 | { 0x0000a3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce }, | 4787 | { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, |
4785 | { 0x0000a3e0, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce }, | 4788 | { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, |
4786 | }; | 4789 | }; |
4787 | 4790 | ||
4788 | static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | 4791 | static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 8ae4ec21667b..6f923e318727 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -825,13 +825,29 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
825 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; | 825 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; |
826 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; | 826 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; |
827 | 827 | ||
828 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | 828 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { |
829 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00); | 829 | ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; |
830 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01); | 830 | ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; |
831 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02); | 831 | ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; |
832 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10); | 832 | ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; |
833 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11); | 833 | ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; |
834 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12); | 834 | ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; |
835 | ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; | ||
836 | } else { | ||
837 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | ||
838 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, | ||
839 | AR_RxRSSIAnt00); | ||
840 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, | ||
841 | AR_RxRSSIAnt01); | ||
842 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, | ||
843 | AR_RxRSSIAnt02); | ||
844 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, | ||
845 | AR_RxRSSIAnt10); | ||
846 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, | ||
847 | AR_RxRSSIAnt11); | ||
848 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, | ||
849 | AR_RxRSSIAnt12); | ||
850 | } | ||
835 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | 851 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) |
836 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); | 852 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); |
837 | else | 853 | else |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 961b0ce6ef3e..3436295e0509 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -465,6 +465,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
465 | an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | 465 | an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + |
466 | sta->ht_cap.ampdu_factor); | 466 | sta->ht_cap.ampdu_factor); |
467 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); | 467 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); |
468 | an->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
468 | } | 469 | } |
469 | } | 470 | } |
470 | 471 | ||
@@ -1258,6 +1259,7 @@ void ath_detach(struct ath_softc *sc) | |||
1258 | ath_deinit_leds(sc); | 1259 | ath_deinit_leds(sc); |
1259 | cancel_work_sync(&sc->chan_work); | 1260 | cancel_work_sync(&sc->chan_work); |
1260 | cancel_delayed_work_sync(&sc->wiphy_work); | 1261 | cancel_delayed_work_sync(&sc->wiphy_work); |
1262 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
1261 | 1263 | ||
1262 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 1264 | for (i = 0; i < sc->num_sec_wiphy; i++) { |
1263 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 1265 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; |
@@ -1284,7 +1286,6 @@ void ath_detach(struct ath_softc *sc) | |||
1284 | 1286 | ||
1285 | ath9k_hw_detach(sc->sc_ah); | 1287 | ath9k_hw_detach(sc->sc_ah); |
1286 | ath9k_exit_debug(sc); | 1288 | ath9k_exit_debug(sc); |
1287 | ath9k_ps_restore(sc); | ||
1288 | } | 1289 | } |
1289 | 1290 | ||
1290 | static int ath9k_reg_notifier(struct wiphy *wiphy, | 1291 | static int ath9k_reg_notifier(struct wiphy *wiphy, |
@@ -1315,6 +1316,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
1315 | spin_lock_init(&sc->sc_resetlock); | 1316 | spin_lock_init(&sc->sc_resetlock); |
1316 | spin_lock_init(&sc->sc_serial_rw); | 1317 | spin_lock_init(&sc->sc_serial_rw); |
1317 | spin_lock_init(&sc->ani_lock); | 1318 | spin_lock_init(&sc->ani_lock); |
1319 | spin_lock_init(&sc->sc_pm_lock); | ||
1318 | mutex_init(&sc->mutex); | 1320 | mutex_init(&sc->mutex); |
1319 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | 1321 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); |
1320 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | 1322 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, |
@@ -1540,7 +1542,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1540 | hw->max_rates = 4; | 1542 | hw->max_rates = 4; |
1541 | hw->channel_change_time = 5000; | 1543 | hw->channel_change_time = 5000; |
1542 | hw->max_listen_interval = 10; | 1544 | hw->max_listen_interval = 10; |
1543 | hw->max_rate_tries = ATH_11N_TXMAXTRY; | 1545 | /* Hardware supports 10 but we use 4 */ |
1546 | hw->max_rate_tries = 4; | ||
1544 | hw->sta_data_size = sizeof(struct ath_node); | 1547 | hw->sta_data_size = sizeof(struct ath_node); |
1545 | hw->vif_data_size = sizeof(struct ath_vif); | 1548 | hw->vif_data_size = sizeof(struct ath_vif); |
1546 | 1549 | ||
@@ -1977,6 +1980,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1977 | 1980 | ||
1978 | ieee80211_wake_queues(hw); | 1981 | ieee80211_wake_queues(hw); |
1979 | 1982 | ||
1983 | queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0); | ||
1984 | |||
1980 | mutex_unlock: | 1985 | mutex_unlock: |
1981 | mutex_unlock(&sc->mutex); | 1986 | mutex_unlock(&sc->mutex); |
1982 | 1987 | ||
@@ -2096,8 +2101,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2096 | 2101 | ||
2097 | mutex_lock(&sc->mutex); | 2102 | mutex_lock(&sc->mutex); |
2098 | 2103 | ||
2099 | ieee80211_stop_queues(hw); | ||
2100 | |||
2101 | if (ath9k_wiphy_started(sc)) { | 2104 | if (ath9k_wiphy_started(sc)) { |
2102 | mutex_unlock(&sc->mutex); | 2105 | mutex_unlock(&sc->mutex); |
2103 | return; /* another wiphy still in use */ | 2106 | return; /* another wiphy still in use */ |
@@ -2255,9 +2258,28 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2255 | struct ath_softc *sc = aphy->sc; | 2258 | struct ath_softc *sc = aphy->sc; |
2256 | struct ieee80211_conf *conf = &hw->conf; | 2259 | struct ieee80211_conf *conf = &hw->conf; |
2257 | struct ath_hw *ah = sc->sc_ah; | 2260 | struct ath_hw *ah = sc->sc_ah; |
2261 | bool all_wiphys_idle = false, disable_radio = false; | ||
2258 | 2262 | ||
2259 | mutex_lock(&sc->mutex); | 2263 | mutex_lock(&sc->mutex); |
2260 | 2264 | ||
2265 | /* Leave this as the first check */ | ||
2266 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | ||
2267 | |||
2268 | spin_lock_bh(&sc->wiphy_lock); | ||
2269 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | ||
2270 | spin_unlock_bh(&sc->wiphy_lock); | ||
2271 | |||
2272 | if (conf->flags & IEEE80211_CONF_IDLE){ | ||
2273 | if (all_wiphys_idle) | ||
2274 | disable_radio = true; | ||
2275 | } | ||
2276 | else if (all_wiphys_idle) { | ||
2277 | ath_radio_enable(sc); | ||
2278 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
2279 | "not-idle: enabling radio\n"); | ||
2280 | } | ||
2281 | } | ||
2282 | |||
2261 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 2283 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
2262 | if (conf->flags & IEEE80211_CONF_PS) { | 2284 | if (conf->flags & IEEE80211_CONF_PS) { |
2263 | if (!(ah->caps.hw_caps & | 2285 | if (!(ah->caps.hw_caps & |
@@ -2325,6 +2347,11 @@ skip_chan_change: | |||
2325 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2347 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2326 | sc->config.txpowlimit = 2 * conf->power_level; | 2348 | sc->config.txpowlimit = 2 * conf->power_level; |
2327 | 2349 | ||
2350 | if (disable_radio) { | ||
2351 | DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); | ||
2352 | ath_radio_disable(sc); | ||
2353 | } | ||
2354 | |||
2328 | mutex_unlock(&sc->mutex); | 2355 | mutex_unlock(&sc->mutex); |
2329 | 2356 | ||
2330 | return 0; | 2357 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ba06e78b2f50..a07efa22551e 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -22,133 +22,132 @@ static const struct ath_rate_table ar5416_11na_ratetable = { | |||
22 | { | 22 | { |
23 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | 23 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
24 | 5400, 0x0b, 0x00, 12, | 24 | 5400, 0x0b, 0x00, 12, |
25 | 0, 2, 1, 0, 0, 0, 0, 0 }, | 25 | 0, 0, 0, 0, 0, 0 }, |
26 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | 26 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
27 | 7800, 0x0f, 0x00, 18, | 27 | 7800, 0x0f, 0x00, 18, |
28 | 0, 3, 1, 1, 1, 1, 1, 0 }, | 28 | 0, 1, 1, 1, 1, 0 }, |
29 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | 29 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
30 | 10000, 0x0a, 0x00, 24, | 30 | 10000, 0x0a, 0x00, 24, |
31 | 2, 4, 2, 2, 2, 2, 2, 0 }, | 31 | 2, 2, 2, 2, 2, 0 }, |
32 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | 32 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
33 | 13900, 0x0e, 0x00, 36, | 33 | 13900, 0x0e, 0x00, 36, |
34 | 2, 6, 2, 3, 3, 3, 3, 0 }, | 34 | 2, 3, 3, 3, 3, 0 }, |
35 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | 35 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
36 | 17300, 0x09, 0x00, 48, | 36 | 17300, 0x09, 0x00, 48, |
37 | 4, 10, 3, 4, 4, 4, 4, 0 }, | 37 | 4, 4, 4, 4, 4, 0 }, |
38 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | 38 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
39 | 23000, 0x0d, 0x00, 72, | 39 | 23000, 0x0d, 0x00, 72, |
40 | 4, 14, 3, 5, 5, 5, 5, 0 }, | 40 | 4, 5, 5, 5, 5, 0 }, |
41 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | 41 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
42 | 27400, 0x08, 0x00, 96, | 42 | 27400, 0x08, 0x00, 96, |
43 | 4, 20, 3, 6, 6, 6, 6, 0 }, | 43 | 4, 6, 6, 6, 6, 0 }, |
44 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 44 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
45 | 29300, 0x0c, 0x00, 108, | 45 | 29300, 0x0c, 0x00, 108, |
46 | 4, 23, 3, 7, 7, 7, 7, 0 }, | 46 | 4, 7, 7, 7, 7, 0 }, |
47 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 47 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
48 | 6400, 0x80, 0x00, 0, | 48 | 6400, 0x80, 0x00, 0, |
49 | 0, 2, 3, 8, 24, 8, 24, 3216 }, | 49 | 0, 8, 24, 8, 24, 3216 }, |
50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ | 50 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
51 | 12700, 0x81, 0x00, 1, | 51 | 12700, 0x81, 0x00, 1, |
52 | 2, 4, 3, 9, 25, 9, 25, 6434 }, | 52 | 2, 9, 25, 9, 25, 6434 }, |
53 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 53 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
54 | 18800, 0x82, 0x00, 2, | 54 | 18800, 0x82, 0x00, 2, |
55 | 2, 6, 3, 10, 26, 10, 26, 9650 }, | 55 | 2, 10, 26, 10, 26, 9650 }, |
56 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ | 56 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
57 | 25000, 0x83, 0x00, 3, | 57 | 25000, 0x83, 0x00, 3, |
58 | 4, 10, 3, 11, 27, 11, 27, 12868 }, | 58 | 4, 11, 27, 11, 27, 12868 }, |
59 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ | 59 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
60 | 36700, 0x84, 0x00, 4, | 60 | 36700, 0x84, 0x00, 4, |
61 | 4, 14, 3, 12, 28, 12, 28, 19304 }, | 61 | 4, 12, 28, 12, 28, 19304 }, |
62 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ | 62 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
63 | 48100, 0x85, 0x00, 5, | 63 | 48100, 0x85, 0x00, 5, |
64 | 4, 20, 3, 13, 29, 13, 29, 25740 }, | 64 | 4, 13, 29, 13, 29, 25740 }, |
65 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 65 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
66 | 53500, 0x86, 0x00, 6, | 66 | 53500, 0x86, 0x00, 6, |
67 | 4, 23, 3, 14, 30, 14, 30, 28956 }, | 67 | 4, 14, 30, 14, 30, 28956 }, |
68 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ | 68 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
69 | 59000, 0x87, 0x00, 7, | 69 | 59000, 0x87, 0x00, 7, |
70 | 4, 25, 3, 15, 31, 15, 32, 32180 }, | 70 | 4, 15, 31, 15, 32, 32180 }, |
71 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ | 71 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
72 | 12700, 0x88, 0x00, | 72 | 12700, 0x88, 0x00, |
73 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, | 73 | 8, 3, 16, 33, 16, 33, 6430 }, |
74 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ | 74 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
75 | 24800, 0x89, 0x00, 9, | 75 | 24800, 0x89, 0x00, 9, |
76 | 2, 4, 3, 17, 34, 17, 34, 12860 }, | 76 | 2, 17, 34, 17, 34, 12860 }, |
77 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ | 77 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
78 | 36600, 0x8a, 0x00, 10, | 78 | 36600, 0x8a, 0x00, 10, |
79 | 2, 6, 3, 18, 35, 18, 35, 19300 }, | 79 | 2, 18, 35, 18, 35, 19300 }, |
80 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ | 80 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
81 | 48100, 0x8b, 0x00, 11, | 81 | 48100, 0x8b, 0x00, 11, |
82 | 4, 10, 3, 19, 36, 19, 36, 25736 }, | 82 | 4, 19, 36, 19, 36, 25736 }, |
83 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ | 83 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
84 | 69500, 0x8c, 0x00, 12, | 84 | 69500, 0x8c, 0x00, 12, |
85 | 4, 14, 3, 20, 37, 20, 37, 38600 }, | 85 | 4, 20, 37, 20, 37, 38600 }, |
86 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ | 86 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
87 | 89500, 0x8d, 0x00, 13, | 87 | 89500, 0x8d, 0x00, 13, |
88 | 4, 20, 3, 21, 38, 21, 38, 51472 }, | 88 | 4, 21, 38, 21, 38, 51472 }, |
89 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ | 89 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
90 | 98900, 0x8e, 0x00, 14, | 90 | 98900, 0x8e, 0x00, 14, |
91 | 4, 23, 3, 22, 39, 22, 39, 57890 }, | 91 | 4, 22, 39, 22, 39, 57890 }, |
92 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ | 92 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
93 | 108300, 0x8f, 0x00, 15, | 93 | 108300, 0x8f, 0x00, 15, |
94 | 4, 25, 3, 23, 40, 23, 41, 64320 }, | 94 | 4, 23, 40, 23, 41, 64320 }, |
95 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 95 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
96 | 13200, 0x80, 0x00, 0, | 96 | 13200, 0x80, 0x00, 0, |
97 | 0, 2, 3, 8, 24, 24, 24, 6684 }, | 97 | 0, 8, 24, 24, 24, 6684 }, |
98 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 98 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
99 | 25900, 0x81, 0x00, 1, | 99 | 25900, 0x81, 0x00, 1, |
100 | 2, 4, 3, 9, 25, 25, 25, 13368 }, | 100 | 2, 9, 25, 25, 25, 13368 }, |
101 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 101 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
102 | 38600, 0x82, 0x00, 2, | 102 | 38600, 0x82, 0x00, 2, |
103 | 2, 6, 3, 10, 26, 26, 26, 20052 }, | 103 | 2, 10, 26, 26, 26, 20052 }, |
104 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ | 104 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
105 | 49800, 0x83, 0x00, 3, | 105 | 49800, 0x83, 0x00, 3, |
106 | 4, 10, 3, 11, 27, 27, 27, 26738 }, | 106 | 4, 11, 27, 27, 27, 26738 }, |
107 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ | 107 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
108 | 72200, 0x84, 0x00, 4, | 108 | 72200, 0x84, 0x00, 4, |
109 | 4, 14, 3, 12, 28, 28, 28, 40104 }, | 109 | 4, 12, 28, 28, 28, 40104 }, |
110 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ | 110 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
111 | 92900, 0x85, 0x00, 5, | 111 | 92900, 0x85, 0x00, 5, |
112 | 4, 20, 3, 13, 29, 29, 29, 53476 }, | 112 | 4, 13, 29, 29, 29, 53476 }, |
113 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 113 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
114 | 102700, 0x86, 0x00, 6, | 114 | 102700, 0x86, 0x00, 6, |
115 | 4, 23, 3, 14, 30, 30, 30, 60156 }, | 115 | 4, 14, 30, 30, 30, 60156 }, |
116 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ | 116 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
117 | 112000, 0x87, 0x00, 7, | 117 | 112000, 0x87, 0x00, 7, |
118 | 4, 25, 3, 15, 31, 32, 32, 66840 }, | 118 | 4, 15, 31, 32, 32, 66840 }, |
119 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 119 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
120 | 122000, 0x87, 0x00, 7, | 120 | 122000, 0x87, 0x00, 7, |
121 | 4, 25, 3, 15, 31, 32, 32, 74200 }, | 121 | 4, 15, 31, 32, 32, 74200 }, |
122 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ | 122 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
123 | 25800, 0x88, 0x00, 8, | 123 | 25800, 0x88, 0x00, 8, |
124 | 0, 2, 3, 16, 33, 33, 33, 13360 }, | 124 | 0, 16, 33, 33, 33, 13360 }, |
125 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ | 125 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
126 | 49800, 0x89, 0x00, 9, | 126 | 49800, 0x89, 0x00, 9, |
127 | 2, 4, 3, 17, 34, 34, 34, 26720 }, | 127 | 2, 17, 34, 34, 34, 26720 }, |
128 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ | 128 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
129 | 71900, 0x8a, 0x00, 10, | 129 | 71900, 0x8a, 0x00, 10, |
130 | 2, 6, 3, 18, 35, 35, 35, 40080 }, | 130 | 2, 18, 35, 35, 35, 40080 }, |
131 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ | 131 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
132 | 92500, 0x8b, 0x00, 11, | 132 | 92500, 0x8b, 0x00, 11, |
133 | 4, 10, 3, 19, 36, 36, 36, 53440 }, | 133 | 4, 19, 36, 36, 36, 53440 }, |
134 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ | 134 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
135 | 130300, 0x8c, 0x00, 12, | 135 | 130300, 0x8c, 0x00, 12, |
136 | 4, 14, 3, 20, 37, 37, 37, 80160 }, | 136 | 4, 20, 37, 37, 37, 80160 }, |
137 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ | 137 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
138 | 162800, 0x8d, 0x00, 13, | 138 | 162800, 0x8d, 0x00, 13, |
139 | 4, 20, 3, 21, 38, 38, 38, 106880 }, | 139 | 4, 21, 38, 38, 38, 106880 }, |
140 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ | 140 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
141 | 178200, 0x8e, 0x00, 14, | 141 | 178200, 0x8e, 0x00, 14, |
142 | 4, 23, 3, 22, 39, 39, 39, 120240 }, | 142 | 4, 22, 39, 39, 39, 120240 }, |
143 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ | 143 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
144 | 192100, 0x8f, 0x00, 15, | 144 | 192100, 0x8f, 0x00, 15, |
145 | 4, 25, 3, 23, 40, 41, 41, 133600 }, | 145 | 4, 23, 40, 41, 41, 133600 }, |
146 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 146 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
147 | 207000, 0x8f, 0x00, 15, | 147 | 207000, 0x8f, 0x00, 15, |
148 | 4, 25, 3, 23, 40, 41, 41, 148400 }, | 148 | 4, 23, 40, 41, 41, 148400 }, |
149 | }, | 149 | }, |
150 | 50, /* probe interval */ | 150 | 50, /* probe interval */ |
151 | 50, /* rssi reduce interval */ | ||
152 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 151 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
153 | }; | 152 | }; |
154 | 153 | ||
@@ -160,145 +159,144 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { | |||
160 | { | 159 | { |
161 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ | 160 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
162 | 900, 0x1b, 0x00, 2, | 161 | 900, 0x1b, 0x00, 2, |
163 | 0, 0, 1, 0, 0, 0, 0, 0 }, | 162 | 0, 0, 0, 0, 0, 0 }, |
164 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ | 163 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ |
165 | 1900, 0x1a, 0x04, 4, | 164 | 1900, 0x1a, 0x04, 4, |
166 | 1, 1, 1, 1, 1, 1, 1, 0 }, | 165 | 1, 1, 1, 1, 1, 0 }, |
167 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ | 166 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ |
168 | 4900, 0x19, 0x04, 11, | 167 | 4900, 0x19, 0x04, 11, |
169 | 2, 2, 2, 2, 2, 2, 2, 0 }, | 168 | 2, 2, 2, 2, 2, 0 }, |
170 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ | 169 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ |
171 | 8100, 0x18, 0x04, 22, | 170 | 8100, 0x18, 0x04, 22, |
172 | 3, 3, 2, 3, 3, 3, 3, 0 }, | 171 | 3, 3, 3, 3, 3, 0 }, |
173 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | 172 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
174 | 5400, 0x0b, 0x00, 12, | 173 | 5400, 0x0b, 0x00, 12, |
175 | 4, 2, 1, 4, 4, 4, 4, 0 }, | 174 | 4, 4, 4, 4, 4, 0 }, |
176 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | 175 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
177 | 7800, 0x0f, 0x00, 18, | 176 | 7800, 0x0f, 0x00, 18, |
178 | 4, 3, 1, 5, 5, 5, 5, 0 }, | 177 | 4, 5, 5, 5, 5, 0 }, |
179 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | 178 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
180 | 10100, 0x0a, 0x00, 24, | 179 | 10100, 0x0a, 0x00, 24, |
181 | 6, 4, 1, 6, 6, 6, 6, 0 }, | 180 | 6, 6, 6, 6, 6, 0 }, |
182 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | 181 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
183 | 14100, 0x0e, 0x00, 36, | 182 | 14100, 0x0e, 0x00, 36, |
184 | 6, 6, 2, 7, 7, 7, 7, 0 }, | 183 | 6, 7, 7, 7, 7, 0 }, |
185 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | 184 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
186 | 17700, 0x09, 0x00, 48, | 185 | 17700, 0x09, 0x00, 48, |
187 | 8, 10, 3, 8, 8, 8, 8, 0 }, | 186 | 8, 8, 8, 8, 8, 0 }, |
188 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | 187 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
189 | 23700, 0x0d, 0x00, 72, | 188 | 23700, 0x0d, 0x00, 72, |
190 | 8, 14, 3, 9, 9, 9, 9, 0 }, | 189 | 8, 9, 9, 9, 9, 0 }, |
191 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | 190 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
192 | 27400, 0x08, 0x00, 96, | 191 | 27400, 0x08, 0x00, 96, |
193 | 8, 20, 3, 10, 10, 10, 10, 0 }, | 192 | 8, 10, 10, 10, 10, 0 }, |
194 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 193 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
195 | 30900, 0x0c, 0x00, 108, | 194 | 30900, 0x0c, 0x00, 108, |
196 | 8, 23, 3, 11, 11, 11, 11, 0 }, | 195 | 8, 11, 11, 11, 11, 0 }, |
197 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 196 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
198 | 6400, 0x80, 0x00, 0, | 197 | 6400, 0x80, 0x00, 0, |
199 | 4, 2, 3, 12, 28, 12, 28, 3216 }, | 198 | 4, 12, 28, 12, 28, 3216 }, |
200 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ | 199 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
201 | 12700, 0x81, 0x00, 1, | 200 | 12700, 0x81, 0x00, 1, |
202 | 6, 4, 3, 13, 29, 13, 29, 6434 }, | 201 | 6, 13, 29, 13, 29, 6434 }, |
203 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 202 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
204 | 18800, 0x82, 0x00, 2, | 203 | 18800, 0x82, 0x00, 2, |
205 | 6, 6, 3, 14, 30, 14, 30, 9650 }, | 204 | 6, 14, 30, 14, 30, 9650 }, |
206 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ | 205 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
207 | 25000, 0x83, 0x00, 3, | 206 | 25000, 0x83, 0x00, 3, |
208 | 8, 10, 3, 15, 31, 15, 31, 12868 }, | 207 | 8, 15, 31, 15, 31, 12868 }, |
209 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ | 208 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
210 | 36700, 0x84, 0x00, 4, | 209 | 36700, 0x84, 0x00, 4, |
211 | 8, 14, 3, 16, 32, 16, 32, 19304 }, | 210 | 8, 16, 32, 16, 32, 19304 }, |
212 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ | 211 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
213 | 48100, 0x85, 0x00, 5, | 212 | 48100, 0x85, 0x00, 5, |
214 | 8, 20, 3, 17, 33, 17, 33, 25740 }, | 213 | 8, 17, 33, 17, 33, 25740 }, |
215 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 214 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
216 | 53500, 0x86, 0x00, 6, | 215 | 53500, 0x86, 0x00, 6, |
217 | 8, 23, 3, 18, 34, 18, 34, 28956 }, | 216 | 8, 18, 34, 18, 34, 28956 }, |
218 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ | 217 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
219 | 59000, 0x87, 0x00, 7, | 218 | 59000, 0x87, 0x00, 7, |
220 | 8, 25, 3, 19, 35, 19, 36, 32180 }, | 219 | 8, 19, 35, 19, 36, 32180 }, |
221 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ | 220 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
222 | 12700, 0x88, 0x00, 8, | 221 | 12700, 0x88, 0x00, 8, |
223 | 4, 2, 3, 20, 37, 20, 37, 6430 }, | 222 | 4, 20, 37, 20, 37, 6430 }, |
224 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ | 223 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
225 | 24800, 0x89, 0x00, 9, | 224 | 24800, 0x89, 0x00, 9, |
226 | 6, 4, 3, 21, 38, 21, 38, 12860 }, | 225 | 6, 21, 38, 21, 38, 12860 }, |
227 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ | 226 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
228 | 36600, 0x8a, 0x00, 10, | 227 | 36600, 0x8a, 0x00, 10, |
229 | 6, 6, 3, 22, 39, 22, 39, 19300 }, | 228 | 6, 22, 39, 22, 39, 19300 }, |
230 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ | 229 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
231 | 48100, 0x8b, 0x00, 11, | 230 | 48100, 0x8b, 0x00, 11, |
232 | 8, 10, 3, 23, 40, 23, 40, 25736 }, | 231 | 8, 23, 40, 23, 40, 25736 }, |
233 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ | 232 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
234 | 69500, 0x8c, 0x00, 12, | 233 | 69500, 0x8c, 0x00, 12, |
235 | 8, 14, 3, 24, 41, 24, 41, 38600 }, | 234 | 8, 24, 41, 24, 41, 38600 }, |
236 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ | 235 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
237 | 89500, 0x8d, 0x00, 13, | 236 | 89500, 0x8d, 0x00, 13, |
238 | 8, 20, 3, 25, 42, 25, 42, 51472 }, | 237 | 8, 25, 42, 25, 42, 51472 }, |
239 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ | 238 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
240 | 98900, 0x8e, 0x00, 14, | 239 | 98900, 0x8e, 0x00, 14, |
241 | 8, 23, 3, 26, 43, 26, 44, 57890 }, | 240 | 8, 26, 43, 26, 44, 57890 }, |
242 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ | 241 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
243 | 108300, 0x8f, 0x00, 15, | 242 | 108300, 0x8f, 0x00, 15, |
244 | 8, 25, 3, 27, 44, 27, 45, 64320 }, | 243 | 8, 27, 44, 27, 45, 64320 }, |
245 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 244 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
246 | 13200, 0x80, 0x00, 0, | 245 | 13200, 0x80, 0x00, 0, |
247 | 8, 2, 3, 12, 28, 28, 28, 6684 }, | 246 | 8, 12, 28, 28, 28, 6684 }, |
248 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 247 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
249 | 25900, 0x81, 0x00, 1, | 248 | 25900, 0x81, 0x00, 1, |
250 | 8, 4, 3, 13, 29, 29, 29, 13368 }, | 249 | 8, 13, 29, 29, 29, 13368 }, |
251 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 250 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
252 | 38600, 0x82, 0x00, 2, | 251 | 38600, 0x82, 0x00, 2, |
253 | 8, 6, 3, 14, 30, 30, 30, 20052 }, | 252 | 8, 14, 30, 30, 30, 20052 }, |
254 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ | 253 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
255 | 49800, 0x83, 0x00, 3, | 254 | 49800, 0x83, 0x00, 3, |
256 | 8, 10, 3, 15, 31, 31, 31, 26738 }, | 255 | 8, 15, 31, 31, 31, 26738 }, |
257 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ | 256 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
258 | 72200, 0x84, 0x00, 4, | 257 | 72200, 0x84, 0x00, 4, |
259 | 8, 14, 3, 16, 32, 32, 32, 40104 }, | 258 | 8, 16, 32, 32, 32, 40104 }, |
260 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ | 259 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
261 | 92900, 0x85, 0x00, 5, | 260 | 92900, 0x85, 0x00, 5, |
262 | 8, 20, 3, 17, 33, 33, 33, 53476 }, | 261 | 8, 17, 33, 33, 33, 53476 }, |
263 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 262 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
264 | 102700, 0x86, 0x00, 6, | 263 | 102700, 0x86, 0x00, 6, |
265 | 8, 23, 3, 18, 34, 34, 34, 60156 }, | 264 | 8, 18, 34, 34, 34, 60156 }, |
266 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ | 265 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
267 | 112000, 0x87, 0x00, 7, | 266 | 112000, 0x87, 0x00, 7, |
268 | 8, 23, 3, 19, 35, 36, 36, 66840 }, | 267 | 8, 19, 35, 36, 36, 66840 }, |
269 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 268 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
270 | 122000, 0x87, 0x00, 7, | 269 | 122000, 0x87, 0x00, 7, |
271 | 8, 25, 3, 19, 35, 36, 36, 74200 }, | 270 | 8, 19, 35, 36, 36, 74200 }, |
272 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ | 271 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
273 | 25800, 0x88, 0x00, 8, | 272 | 25800, 0x88, 0x00, 8, |
274 | 8, 2, 3, 20, 37, 37, 37, 13360 }, | 273 | 8, 20, 37, 37, 37, 13360 }, |
275 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ | 274 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
276 | 49800, 0x89, 0x00, 9, | 275 | 49800, 0x89, 0x00, 9, |
277 | 8, 4, 3, 21, 38, 38, 38, 26720 }, | 276 | 8, 21, 38, 38, 38, 26720 }, |
278 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ | 277 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
279 | 71900, 0x8a, 0x00, 10, | 278 | 71900, 0x8a, 0x00, 10, |
280 | 8, 6, 3, 22, 39, 39, 39, 40080 }, | 279 | 8, 22, 39, 39, 39, 40080 }, |
281 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ | 280 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
282 | 92500, 0x8b, 0x00, 11, | 281 | 92500, 0x8b, 0x00, 11, |
283 | 8, 10, 3, 23, 40, 40, 40, 53440 }, | 282 | 8, 23, 40, 40, 40, 53440 }, |
284 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ | 283 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
285 | 130300, 0x8c, 0x00, 12, | 284 | 130300, 0x8c, 0x00, 12, |
286 | 8, 14, 3, 24, 41, 41, 41, 80160 }, | 285 | 8, 24, 41, 41, 41, 80160 }, |
287 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ | 286 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
288 | 162800, 0x8d, 0x00, 13, | 287 | 162800, 0x8d, 0x00, 13, |
289 | 8, 20, 3, 25, 42, 42, 42, 106880 }, | 288 | 8, 25, 42, 42, 42, 106880 }, |
290 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ | 289 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
291 | 178200, 0x8e, 0x00, 14, | 290 | 178200, 0x8e, 0x00, 14, |
292 | 8, 23, 3, 26, 43, 43, 43, 120240 }, | 291 | 8, 26, 43, 43, 43, 120240 }, |
293 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ | 292 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
294 | 192100, 0x8f, 0x00, 15, | 293 | 192100, 0x8f, 0x00, 15, |
295 | 8, 23, 3, 27, 44, 45, 45, 133600 }, | 294 | 8, 27, 44, 45, 45, 133600 }, |
296 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 295 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
297 | 207000, 0x8f, 0x00, 15, | 296 | 207000, 0x8f, 0x00, 15, |
298 | 8, 25, 3, 27, 44, 45, 45, 148400 }, | 297 | 8, 27, 44, 45, 45, 148400 }, |
299 | }, | 298 | }, |
300 | 50, /* probe interval */ | 299 | 50, /* probe interval */ |
301 | 50, /* rssi reduce interval */ | ||
302 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 300 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
303 | }; | 301 | }; |
304 | 302 | ||
@@ -307,31 +305,30 @@ static const struct ath_rate_table ar5416_11a_ratetable = { | |||
307 | { | 305 | { |
308 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | 306 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
309 | 5400, 0x0b, 0x00, (0x80|12), | 307 | 5400, 0x0b, 0x00, (0x80|12), |
310 | 0, 2, 1, 0, 0 }, | 308 | 0, 0, 0 }, |
311 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | 309 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
312 | 7800, 0x0f, 0x00, 18, | 310 | 7800, 0x0f, 0x00, 18, |
313 | 0, 3, 1, 1, 0 }, | 311 | 0, 1, 0 }, |
314 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | 312 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
315 | 10000, 0x0a, 0x00, (0x80|24), | 313 | 10000, 0x0a, 0x00, (0x80|24), |
316 | 2, 4, 2, 2, 0 }, | 314 | 2, 2, 0 }, |
317 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | 315 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
318 | 13900, 0x0e, 0x00, 36, | 316 | 13900, 0x0e, 0x00, 36, |
319 | 2, 6, 2, 3, 0 }, | 317 | 2, 3, 0 }, |
320 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | 318 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
321 | 17300, 0x09, 0x00, (0x80|48), | 319 | 17300, 0x09, 0x00, (0x80|48), |
322 | 4, 10, 3, 4, 0 }, | 320 | 4, 4, 0 }, |
323 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | 321 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
324 | 23000, 0x0d, 0x00, 72, | 322 | 23000, 0x0d, 0x00, 72, |
325 | 4, 14, 3, 5, 0 }, | 323 | 4, 5, 0 }, |
326 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | 324 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
327 | 27400, 0x08, 0x00, 96, | 325 | 27400, 0x08, 0x00, 96, |
328 | 4, 19, 3, 6, 0 }, | 326 | 4, 6, 0 }, |
329 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 327 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
330 | 29300, 0x0c, 0x00, 108, | 328 | 29300, 0x0c, 0x00, 108, |
331 | 4, 23, 3, 7, 0 }, | 329 | 4, 7, 0 }, |
332 | }, | 330 | }, |
333 | 50, /* probe interval */ | 331 | 50, /* probe interval */ |
334 | 50, /* rssi reduce interval */ | ||
335 | 0, /* Phy rates allowed initially */ | 332 | 0, /* Phy rates allowed initially */ |
336 | }; | 333 | }; |
337 | 334 | ||
@@ -340,64 +337,42 @@ static const struct ath_rate_table ar5416_11g_ratetable = { | |||
340 | { | 337 | { |
341 | { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ | 338 | { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
342 | 900, 0x1b, 0x00, 2, | 339 | 900, 0x1b, 0x00, 2, |
343 | 0, 0, 1, 0, 0 }, | 340 | 0, 0, 0 }, |
344 | { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ | 341 | { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ |
345 | 1900, 0x1a, 0x04, 4, | 342 | 1900, 0x1a, 0x04, 4, |
346 | 1, 1, 1, 1, 0 }, | 343 | 1, 1, 0 }, |
347 | { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ | 344 | { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ |
348 | 4900, 0x19, 0x04, 11, | 345 | 4900, 0x19, 0x04, 11, |
349 | 2, 2, 2, 2, 0 }, | 346 | 2, 2, 0 }, |
350 | { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ | 347 | { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ |
351 | 8100, 0x18, 0x04, 22, | 348 | 8100, 0x18, 0x04, 22, |
352 | 3, 3, 2, 3, 0 }, | 349 | 3, 3, 0 }, |
353 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ | 350 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
354 | 5400, 0x0b, 0x00, 12, | 351 | 5400, 0x0b, 0x00, 12, |
355 | 4, 2, 1, 4, 0 }, | 352 | 4, 4, 0 }, |
356 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ | 353 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
357 | 7800, 0x0f, 0x00, 18, | 354 | 7800, 0x0f, 0x00, 18, |
358 | 4, 3, 1, 5, 0 }, | 355 | 4, 5, 0 }, |
359 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ | 356 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
360 | 10000, 0x0a, 0x00, 24, | 357 | 10000, 0x0a, 0x00, 24, |
361 | 6, 4, 1, 6, 0 }, | 358 | 6, 6, 0 }, |
362 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ | 359 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
363 | 13900, 0x0e, 0x00, 36, | 360 | 13900, 0x0e, 0x00, 36, |
364 | 6, 6, 2, 7, 0 }, | 361 | 6, 7, 0 }, |
365 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ | 362 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
366 | 17300, 0x09, 0x00, 48, | 363 | 17300, 0x09, 0x00, 48, |
367 | 8, 10, 3, 8, 0 }, | 364 | 8, 8, 0 }, |
368 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ | 365 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
369 | 23000, 0x0d, 0x00, 72, | 366 | 23000, 0x0d, 0x00, 72, |
370 | 8, 14, 3, 9, 0 }, | 367 | 8, 9, 0 }, |
371 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ | 368 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
372 | 27400, 0x08, 0x00, 96, | 369 | 27400, 0x08, 0x00, 96, |
373 | 8, 19, 3, 10, 0 }, | 370 | 8, 10, 0 }, |
374 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ | 371 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
375 | 29300, 0x0c, 0x00, 108, | 372 | 29300, 0x0c, 0x00, 108, |
376 | 8, 23, 3, 11, 0 }, | 373 | 8, 11, 0 }, |
377 | }, | 374 | }, |
378 | 50, /* probe interval */ | 375 | 50, /* probe interval */ |
379 | 50, /* rssi reduce interval */ | ||
380 | 0, /* Phy rates allowed initially */ | ||
381 | }; | ||
382 | |||
383 | static const struct ath_rate_table ar5416_11b_ratetable = { | ||
384 | 4, | ||
385 | { | ||
386 | { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ | ||
387 | 900, 0x1b, 0x00, (0x80|2), | ||
388 | 0, 0, 1, 0, 0 }, | ||
389 | { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ | ||
390 | 1800, 0x1a, 0x04, (0x80|4), | ||
391 | 1, 1, 1, 1, 0 }, | ||
392 | { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ | ||
393 | 4300, 0x19, 0x04, (0x80|11), | ||
394 | 1, 2, 2, 2, 0 }, | ||
395 | { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ | ||
396 | 7100, 0x18, 0x04, (0x80|22), | ||
397 | 1, 4, 100, 3, 0 }, | ||
398 | }, | ||
399 | 100, /* probe interval */ | ||
400 | 100, /* rssi reduce interval */ | ||
401 | 0, /* Phy rates allowed initially */ | 376 | 0, /* Phy rates allowed initially */ |
402 | }; | 377 | }; |
403 | 378 | ||
@@ -454,13 +429,6 @@ static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, | |||
454 | ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; | 429 | ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; |
455 | } | 430 | } |
456 | 431 | ||
457 | static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, | ||
458 | u8 index) | ||
459 | { | ||
460 | ASSERT(index <= ath_rc_priv->rate_table_size); | ||
461 | return ath_rc_priv->valid_rate_index[index]; | ||
462 | } | ||
463 | |||
464 | static inline | 432 | static inline |
465 | int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | 433 | int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, |
466 | struct ath_rate_priv *ath_rc_priv, | 434 | struct ath_rate_priv *ath_rc_priv, |
@@ -501,9 +469,9 @@ static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | |||
501 | } | 469 | } |
502 | 470 | ||
503 | static inline int | 471 | static inline int |
504 | ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, | 472 | ath_rc_get_lower_rix(const struct ath_rate_table *rate_table, |
505 | struct ath_rate_priv *ath_rc_priv, | 473 | struct ath_rate_priv *ath_rc_priv, |
506 | u8 cur_valid_txrate, u8 *next_idx) | 474 | u8 cur_valid_txrate, u8 *next_idx) |
507 | { | 475 | { |
508 | int8_t i; | 476 | int8_t i; |
509 | 477 | ||
@@ -629,52 +597,20 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, | |||
629 | return hi; | 597 | return hi; |
630 | } | 598 | } |
631 | 599 | ||
632 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | 600 | /* Finds the highest rate index we can use */ |
633 | struct ath_rate_priv *ath_rc_priv, | 601 | static u8 ath_rc_get_highest_rix(struct ath_softc *sc, |
634 | const struct ath_rate_table *rate_table, | 602 | struct ath_rate_priv *ath_rc_priv, |
635 | int *is_probing) | 603 | const struct ath_rate_table *rate_table, |
604 | int *is_probing) | ||
636 | { | 605 | { |
637 | u32 dt, best_thruput, this_thruput, now_msec; | 606 | u32 best_thruput, this_thruput, now_msec; |
638 | u8 rate, next_rate, best_rate, maxindex, minindex; | 607 | u8 rate, next_rate, best_rate, maxindex, minindex; |
639 | int8_t rssi_last, rssi_reduce = 0, index = 0; | 608 | int8_t index = 0; |
640 | |||
641 | *is_probing = 0; | ||
642 | |||
643 | rssi_last = median(ath_rc_priv->rssi_last, | ||
644 | ath_rc_priv->rssi_last_prev, | ||
645 | ath_rc_priv->rssi_last_prev2); | ||
646 | |||
647 | /* | ||
648 | * Age (reduce) last ack rssi based on how old it is. | ||
649 | * The bizarre numbers are so the delta is 160msec, | ||
650 | * meaning we divide by 16. | ||
651 | * 0msec <= dt <= 25msec: don't derate | ||
652 | * 25msec <= dt <= 185msec: derate linearly from 0 to 10dB | ||
653 | * 185msec <= dt: derate by 10dB | ||
654 | */ | ||
655 | 609 | ||
656 | now_msec = jiffies_to_msecs(jiffies); | 610 | now_msec = jiffies_to_msecs(jiffies); |
657 | dt = now_msec - ath_rc_priv->rssi_time; | 611 | *is_probing = 0; |
658 | |||
659 | if (dt >= 185) | ||
660 | rssi_reduce = 10; | ||
661 | else if (dt >= 25) | ||
662 | rssi_reduce = (u8)((dt - 25) >> 4); | ||
663 | |||
664 | /* Now reduce rssi_last by rssi_reduce */ | ||
665 | if (rssi_last < rssi_reduce) | ||
666 | rssi_last = 0; | ||
667 | else | ||
668 | rssi_last -= rssi_reduce; | ||
669 | |||
670 | /* | ||
671 | * Now look up the rate in the rssi table and return it. | ||
672 | * If no rates match then we return 0 (lowest rate) | ||
673 | */ | ||
674 | |||
675 | best_thruput = 0; | 612 | best_thruput = 0; |
676 | maxindex = ath_rc_priv->max_valid_rate-1; | 613 | maxindex = ath_rc_priv->max_valid_rate-1; |
677 | |||
678 | minindex = 0; | 614 | minindex = 0; |
679 | best_rate = minindex; | 615 | best_rate = minindex; |
680 | 616 | ||
@@ -700,7 +636,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
700 | * 10-15 and we would be worse off then staying | 636 | * 10-15 and we would be worse off then staying |
701 | * at the current rate. | 637 | * at the current rate. |
702 | */ | 638 | */ |
703 | per_thres = ath_rc_priv->state[rate].per; | 639 | per_thres = ath_rc_priv->per[rate]; |
704 | if (per_thres < 12) | 640 | if (per_thres < 12) |
705 | per_thres = 12; | 641 | per_thres = 12; |
706 | 642 | ||
@@ -714,7 +650,6 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
714 | } | 650 | } |
715 | 651 | ||
716 | rate = best_rate; | 652 | rate = best_rate; |
717 | ath_rc_priv->rssi_last_lookup = rssi_last; | ||
718 | 653 | ||
719 | /* | 654 | /* |
720 | * Must check the actual rate (ratekbps) to account for | 655 | * Must check the actual rate (ratekbps) to account for |
@@ -741,10 +676,18 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
741 | if (rate > (ath_rc_priv->rate_table_size - 1)) | 676 | if (rate > (ath_rc_priv->rate_table_size - 1)) |
742 | rate = ath_rc_priv->rate_table_size - 1; | 677 | rate = ath_rc_priv->rate_table_size - 1; |
743 | 678 | ||
744 | ASSERT((rate_table->info[rate].valid && | 679 | if (rate_table->info[rate].valid && |
745 | (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) || | 680 | (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) |
746 | (rate_table->info[rate].valid_single_stream && | 681 | return rate; |
747 | !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))); | 682 | |
683 | if (rate_table->info[rate].valid_single_stream && | ||
684 | !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)); | ||
685 | return rate; | ||
686 | |||
687 | /* This should not happen */ | ||
688 | WARN_ON(1); | ||
689 | |||
690 | rate = ath_rc_priv->valid_rate_index[0]; | ||
748 | 691 | ||
749 | return rate; | 692 | return rate; |
750 | } | 693 | } |
@@ -796,7 +739,6 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, | |||
796 | * just CTS. Note that this is only done for OFDM/HT unicast frames. | 739 | * just CTS. Note that this is only done for OFDM/HT unicast frames. |
797 | */ | 740 | */ |
798 | if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && | 741 | if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && |
799 | !(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
800 | (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || | 742 | (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || |
801 | WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { | 743 | WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { |
802 | rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; | 744 | rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; |
@@ -806,50 +748,37 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc, | |||
806 | tx_info->control.rts_cts_rate_idx = cix; | 748 | tx_info->control.rts_cts_rate_idx = cix; |
807 | } | 749 | } |
808 | 750 | ||
809 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, | 751 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, |
810 | struct ath_rate_priv *ath_rc_priv, | 752 | struct ieee80211_tx_rate_control *txrc) |
811 | const struct ath_rate_table *rate_table, | ||
812 | u8 rix, u16 stepdown, | ||
813 | u16 min_rate) | ||
814 | { | ||
815 | u32 j; | ||
816 | u8 nextindex = 0; | ||
817 | |||
818 | if (min_rate) { | ||
819 | for (j = RATE_TABLE_SIZE; j > 0; j--) { | ||
820 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | ||
821 | ath_rc_priv, rix, &nextindex)) | ||
822 | rix = nextindex; | ||
823 | else | ||
824 | break; | ||
825 | } | ||
826 | } else { | ||
827 | for (j = stepdown; j > 0; j--) { | ||
828 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | ||
829 | ath_rc_priv, rix, &nextindex)) | ||
830 | rix = nextindex; | ||
831 | else | ||
832 | break; | ||
833 | } | ||
834 | } | ||
835 | return rix; | ||
836 | } | ||
837 | |||
838 | static void ath_rc_ratefind(struct ath_softc *sc, | ||
839 | struct ath_rate_priv *ath_rc_priv, | ||
840 | struct ieee80211_tx_rate_control *txrc) | ||
841 | { | 753 | { |
754 | struct ath_softc *sc = priv; | ||
755 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
842 | const struct ath_rate_table *rate_table; | 756 | const struct ath_rate_table *rate_table; |
843 | struct sk_buff *skb = txrc->skb; | 757 | struct sk_buff *skb = txrc->skb; |
844 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 758 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
845 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | 759 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
846 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 760 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
847 | __le16 fc = hdr->frame_control; | 761 | __le16 fc = hdr->frame_control; |
848 | u8 try_per_rate = 0, i = 0, rix, nrix; | 762 | u8 try_per_rate, i = 0, rix, nrix; |
849 | int is_probe = 0; | 763 | int is_probe = 0; |
850 | 764 | ||
765 | if (rate_control_send_low(sta, priv_sta, txrc)) | ||
766 | return; | ||
767 | |||
768 | /* | ||
769 | * For Multi Rate Retry we use a different number of | ||
770 | * retry attempt counts. This ends up looking like this: | ||
771 | * | ||
772 | * MRR[0] = 2 | ||
773 | * MRR[1] = 2 | ||
774 | * MRR[2] = 2 | ||
775 | * MRR[3] = 4 | ||
776 | * | ||
777 | */ | ||
778 | try_per_rate = sc->hw->max_rate_tries; | ||
779 | |||
851 | rate_table = sc->cur_rate_table; | 780 | rate_table = sc->cur_rate_table; |
852 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, &is_probe); | 781 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); |
853 | nrix = rix; | 782 | nrix = rix; |
854 | 783 | ||
855 | if (is_probe) { | 784 | if (is_probe) { |
@@ -858,18 +787,15 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
858 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 787 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
859 | 1, nrix, 0); | 788 | 1, nrix, 0); |
860 | 789 | ||
861 | try_per_rate = (ATH_11N_TXMAXTRY/4); | ||
862 | /* Get the next tried/allowed rate. No RTS for the next series | 790 | /* Get the next tried/allowed rate. No RTS for the next series |
863 | * after the probe rate | 791 | * after the probe rate |
864 | */ | 792 | */ |
865 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | 793 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); |
866 | rate_table, nrix, 1, 0); | ||
867 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 794 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
868 | try_per_rate, nrix, 0); | 795 | try_per_rate, nrix, 0); |
869 | 796 | ||
870 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 797 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
871 | } else { | 798 | } else { |
872 | try_per_rate = (ATH_11N_TXMAXTRY/4); | ||
873 | /* Set the choosen rate. No RTS for first series entry. */ | 799 | /* Set the choosen rate. No RTS for first series entry. */ |
874 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 800 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
875 | try_per_rate, nrix, 0); | 801 | try_per_rate, nrix, 0); |
@@ -877,18 +803,14 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
877 | 803 | ||
878 | /* Fill in the other rates for multirate retry */ | 804 | /* Fill in the other rates for multirate retry */ |
879 | for ( ; i < 4; i++) { | 805 | for ( ; i < 4; i++) { |
880 | u8 try_num; | 806 | /* Use twice the number of tries for the last MRR segment. */ |
881 | u8 min_rate; | 807 | if (i + 1 == 4) |
882 | 808 | try_per_rate = 4; | |
883 | try_num = ((i + 1) == 4) ? | ||
884 | ATH_11N_TXMAXTRY - (try_per_rate * i) : try_per_rate ; | ||
885 | min_rate = (((i + 1) == 4) && 0); | ||
886 | 809 | ||
887 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | 810 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); |
888 | rate_table, nrix, 1, min_rate); | ||
889 | /* All other rates in the series have RTS enabled */ | 811 | /* All other rates in the series have RTS enabled */ |
890 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, | 812 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, |
891 | try_num, nrix, 1); | 813 | try_per_rate, nrix, 1); |
892 | } | 814 | } |
893 | 815 | ||
894 | /* | 816 | /* |
@@ -925,9 +847,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
925 | * | 847 | * |
926 | * FIXME: Fix duration | 848 | * FIXME: Fix duration |
927 | */ | 849 | */ |
928 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK) && | 850 | if (ieee80211_has_morefrags(fc) || |
929 | (ieee80211_has_morefrags(fc) || | 851 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { |
930 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG))) { | ||
931 | rates[1].count = rates[2].count = rates[3].count = 0; | 852 | rates[1].count = rates[2].count = rates[3].count = 0; |
932 | rates[1].idx = rates[2].idx = rates[3].idx = 0; | 853 | rates[1].idx = rates[2].idx = rates[3].idx = 0; |
933 | rates[0].count = ATH_TXMAXTRY; | 854 | rates[0].count = ATH_TXMAXTRY; |
@@ -960,13 +881,13 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
960 | 100 * 9 / 10 | 881 | 100 * 9 / 10 |
961 | }; | 882 | }; |
962 | 883 | ||
963 | last_per = ath_rc_priv->state[tx_rate].per; | 884 | last_per = ath_rc_priv->per[tx_rate]; |
964 | 885 | ||
965 | if (xretries) { | 886 | if (xretries) { |
966 | if (xretries == 1) { | 887 | if (xretries == 1) { |
967 | ath_rc_priv->state[tx_rate].per += 30; | 888 | ath_rc_priv->per[tx_rate] += 30; |
968 | if (ath_rc_priv->state[tx_rate].per > 100) | 889 | if (ath_rc_priv->per[tx_rate] > 100) |
969 | ath_rc_priv->state[tx_rate].per = 100; | 890 | ath_rc_priv->per[tx_rate] = 100; |
970 | } else { | 891 | } else { |
971 | /* xretries == 2 */ | 892 | /* xretries == 2 */ |
972 | count = ARRAY_SIZE(nretry_to_per_lookup); | 893 | count = ARRAY_SIZE(nretry_to_per_lookup); |
@@ -974,7 +895,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
974 | retries = count - 1; | 895 | retries = count - 1; |
975 | 896 | ||
976 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 897 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
977 | ath_rc_priv->state[tx_rate].per = | 898 | ath_rc_priv->per[tx_rate] = |
978 | (u8)(last_per - (last_per >> 3) + (100 >> 3)); | 899 | (u8)(last_per - (last_per >> 3) + (100 >> 3)); |
979 | } | 900 | } |
980 | 901 | ||
@@ -1010,18 +931,14 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1010 | n_frames = tx_info_priv->n_frames * (retries + 1); | 931 | n_frames = tx_info_priv->n_frames * (retries + 1); |
1011 | cur_per = (100 * n_bad_frames / n_frames) >> 3; | 932 | cur_per = (100 * n_bad_frames / n_frames) >> 3; |
1012 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); | 933 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); |
1013 | ath_rc_priv->state[tx_rate].per = new_per; | 934 | ath_rc_priv->per[tx_rate] = new_per; |
1014 | } | 935 | } |
1015 | } else { | 936 | } else { |
1016 | ath_rc_priv->state[tx_rate].per = | 937 | ath_rc_priv->per[tx_rate] = |
1017 | (u8)(last_per - (last_per >> 3) + | 938 | (u8)(last_per - (last_per >> 3) + |
1018 | (nretry_to_per_lookup[retries] >> 3)); | 939 | (nretry_to_per_lookup[retries] >> 3)); |
1019 | } | 940 | } |
1020 | 941 | ||
1021 | ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev; | ||
1022 | ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last; | ||
1023 | ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi; | ||
1024 | ath_rc_priv->rssi_time = now_msec; | ||
1025 | 942 | ||
1026 | /* | 943 | /* |
1027 | * If we got at most one retry then increase the max rate if | 944 | * If we got at most one retry then increase the max rate if |
@@ -1045,8 +962,8 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1045 | ath_rc_priv->probe_rate; | 962 | ath_rc_priv->probe_rate; |
1046 | probe_rate = ath_rc_priv->probe_rate; | 963 | probe_rate = ath_rc_priv->probe_rate; |
1047 | 964 | ||
1048 | if (ath_rc_priv->state[probe_rate].per > 30) | 965 | if (ath_rc_priv->per[probe_rate] > 30) |
1049 | ath_rc_priv->state[probe_rate].per = 20; | 966 | ath_rc_priv->per[probe_rate] = 20; |
1050 | 967 | ||
1051 | ath_rc_priv->probe_rate = 0; | 968 | ath_rc_priv->probe_rate = 0; |
1052 | 969 | ||
@@ -1065,18 +982,9 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1065 | /* | 982 | /* |
1066 | * Don't update anything. We don't know if | 983 | * Don't update anything. We don't know if |
1067 | * this was because of collisions or poor signal. | 984 | * this was because of collisions or poor signal. |
1068 | * | ||
1069 | * Later: if rssi_ack is close to | ||
1070 | * ath_rc_priv->state[txRate].rssi_thres and we see lots | ||
1071 | * of retries, then we could increase | ||
1072 | * ath_rc_priv->state[txRate].rssi_thres. | ||
1073 | */ | 985 | */ |
1074 | ath_rc_priv->hw_maxretry_pktcnt = 0; | 986 | ath_rc_priv->hw_maxretry_pktcnt = 0; |
1075 | } else { | 987 | } else { |
1076 | int32_t rssi_ackAvg; | ||
1077 | int8_t rssi_thres; | ||
1078 | int8_t rssi_ack_vmin; | ||
1079 | |||
1080 | /* | 988 | /* |
1081 | * It worked with no retries. First ignore bogus (small) | 989 | * It worked with no retries. First ignore bogus (small) |
1082 | * rssi_ack values. | 990 | * rssi_ack values. |
@@ -1086,43 +994,9 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1086 | ath_rc_priv->hw_maxretry_pktcnt++; | 994 | ath_rc_priv->hw_maxretry_pktcnt++; |
1087 | } | 995 | } |
1088 | 996 | ||
1089 | if (tx_info_priv->tx.ts_rssi < | ||
1090 | rate_table->info[tx_rate].rssi_ack_validmin) | ||
1091 | goto exit; | ||
1092 | |||
1093 | /* Average the rssi */ | ||
1094 | if (tx_rate != ath_rc_priv->rssi_sum_rate) { | ||
1095 | ath_rc_priv->rssi_sum_rate = tx_rate; | ||
1096 | ath_rc_priv->rssi_sum = | ||
1097 | ath_rc_priv->rssi_sum_cnt = 0; | ||
1098 | } | ||
1099 | |||
1100 | ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi; | ||
1101 | ath_rc_priv->rssi_sum_cnt++; | ||
1102 | |||
1103 | if (ath_rc_priv->rssi_sum_cnt < 4) | ||
1104 | goto exit; | ||
1105 | |||
1106 | rssi_ackAvg = | ||
1107 | (ath_rc_priv->rssi_sum + 2) / 4; | ||
1108 | rssi_thres = | ||
1109 | ath_rc_priv->state[tx_rate].rssi_thres; | ||
1110 | rssi_ack_vmin = | ||
1111 | rate_table->info[tx_rate].rssi_ack_validmin; | ||
1112 | |||
1113 | ath_rc_priv->rssi_sum = | ||
1114 | ath_rc_priv->rssi_sum_cnt = 0; | ||
1115 | |||
1116 | /* Now reduce the current rssi threshold */ | ||
1117 | if ((rssi_ackAvg < rssi_thres + 2) && | ||
1118 | (rssi_thres > rssi_ack_vmin)) { | ||
1119 | ath_rc_priv->state[tx_rate].rssi_thres--; | ||
1120 | } | ||
1121 | |||
1122 | state_change = true; | ||
1123 | } | 997 | } |
1124 | } | 998 | } |
1125 | exit: | 999 | |
1126 | return state_change; | 1000 | return state_change; |
1127 | } | 1001 | } |
1128 | 1002 | ||
@@ -1134,11 +1008,6 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1134 | struct ath_tx_info_priv *tx_info_priv, | 1008 | struct ath_tx_info_priv *tx_info_priv, |
1135 | int tx_rate, int xretries, int retries) | 1009 | int tx_rate, int xretries, int retries) |
1136 | { | 1010 | { |
1137 | #define CHK_RSSI(rate) \ | ||
1138 | ((ath_rc_priv->state[(rate)].rssi_thres + \ | ||
1139 | rate_table->info[(rate)].rssi_ack_deltamin) > \ | ||
1140 | ath_rc_priv->state[(rate)+1].rssi_thres) | ||
1141 | |||
1142 | u32 now_msec = jiffies_to_msecs(jiffies); | 1011 | u32 now_msec = jiffies_to_msecs(jiffies); |
1143 | int rate; | 1012 | int rate; |
1144 | u8 last_per; | 1013 | u8 last_per; |
@@ -1149,14 +1018,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1149 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) | 1018 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) |
1150 | return; | 1019 | return; |
1151 | 1020 | ||
1152 | /* To compensate for some imbalance between ctrl and ext. channel */ | 1021 | last_per = ath_rc_priv->per[tx_rate]; |
1153 | |||
1154 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) | ||
1155 | tx_info_priv->tx.ts_rssi = | ||
1156 | tx_info_priv->tx.ts_rssi < 3 ? 0 : | ||
1157 | tx_info_priv->tx.ts_rssi - 3; | ||
1158 | |||
1159 | last_per = ath_rc_priv->state[tx_rate].per; | ||
1160 | 1022 | ||
1161 | /* Update PER first */ | 1023 | /* Update PER first */ |
1162 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, | 1024 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, |
@@ -1167,114 +1029,55 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1167 | * If this rate looks bad (high PER) then stop using it for | 1029 | * If this rate looks bad (high PER) then stop using it for |
1168 | * a while (except if we are probing). | 1030 | * a while (except if we are probing). |
1169 | */ | 1031 | */ |
1170 | if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && | 1032 | if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && |
1171 | rate_table->info[tx_rate].ratekbps <= | 1033 | rate_table->info[tx_rate].ratekbps <= |
1172 | rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { | 1034 | rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { |
1173 | ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, | 1035 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, |
1174 | (u8)tx_rate, &ath_rc_priv->rate_max_phy); | 1036 | (u8)tx_rate, &ath_rc_priv->rate_max_phy); |
1175 | 1037 | ||
1176 | /* Don't probe for a little while. */ | 1038 | /* Don't probe for a little while. */ |
1177 | ath_rc_priv->probe_time = now_msec; | 1039 | ath_rc_priv->probe_time = now_msec; |
1178 | } | 1040 | } |
1179 | 1041 | ||
1180 | if (state_change) { | ||
1181 | /* | ||
1182 | * Make sure the rates above this have higher rssi thresholds. | ||
1183 | * (Note: Monotonicity is kept within the OFDM rates and | ||
1184 | * within the CCK rates. However, no adjustment is | ||
1185 | * made to keep the rssi thresholds monotonically | ||
1186 | * increasing between the CCK and OFDM rates.) | ||
1187 | */ | ||
1188 | for (rate = tx_rate; rate < size - 1; rate++) { | ||
1189 | if (rate_table->info[rate+1].phy != | ||
1190 | rate_table->info[tx_rate].phy) | ||
1191 | break; | ||
1192 | |||
1193 | if (CHK_RSSI(rate)) { | ||
1194 | ath_rc_priv->state[rate+1].rssi_thres = | ||
1195 | ath_rc_priv->state[rate].rssi_thres + | ||
1196 | rate_table->info[rate].rssi_ack_deltamin; | ||
1197 | } | ||
1198 | } | ||
1199 | |||
1200 | /* Make sure the rates below this have lower rssi thresholds. */ | ||
1201 | for (rate = tx_rate - 1; rate >= 0; rate--) { | ||
1202 | if (rate_table->info[rate].phy != | ||
1203 | rate_table->info[tx_rate].phy) | ||
1204 | break; | ||
1205 | |||
1206 | if (CHK_RSSI(rate)) { | ||
1207 | if (ath_rc_priv->state[rate+1].rssi_thres < | ||
1208 | rate_table->info[rate].rssi_ack_deltamin) | ||
1209 | ath_rc_priv->state[rate].rssi_thres = 0; | ||
1210 | else { | ||
1211 | ath_rc_priv->state[rate].rssi_thres = | ||
1212 | ath_rc_priv->state[rate+1].rssi_thres - | ||
1213 | rate_table->info[rate].rssi_ack_deltamin; | ||
1214 | } | ||
1215 | |||
1216 | if (ath_rc_priv->state[rate].rssi_thres < | ||
1217 | rate_table->info[rate].rssi_ack_validmin) { | ||
1218 | ath_rc_priv->state[rate].rssi_thres = | ||
1219 | rate_table->info[rate].rssi_ack_validmin; | ||
1220 | } | ||
1221 | } | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | /* Make sure the rates below this have lower PER */ | 1042 | /* Make sure the rates below this have lower PER */ |
1226 | /* Monotonicity is kept only for rates below the current rate. */ | 1043 | /* Monotonicity is kept only for rates below the current rate. */ |
1227 | if (ath_rc_priv->state[tx_rate].per < last_per) { | 1044 | if (ath_rc_priv->per[tx_rate] < last_per) { |
1228 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1045 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1229 | if (rate_table->info[rate].phy != | 1046 | if (rate_table->info[rate].phy != |
1230 | rate_table->info[tx_rate].phy) | 1047 | rate_table->info[tx_rate].phy) |
1231 | break; | 1048 | break; |
1232 | 1049 | ||
1233 | if (ath_rc_priv->state[rate].per > | 1050 | if (ath_rc_priv->per[rate] > |
1234 | ath_rc_priv->state[rate+1].per) { | 1051 | ath_rc_priv->per[rate+1]) { |
1235 | ath_rc_priv->state[rate].per = | 1052 | ath_rc_priv->per[rate] = |
1236 | ath_rc_priv->state[rate+1].per; | 1053 | ath_rc_priv->per[rate+1]; |
1237 | } | 1054 | } |
1238 | } | 1055 | } |
1239 | } | 1056 | } |
1240 | 1057 | ||
1241 | /* Maintain monotonicity for rates above the current rate */ | 1058 | /* Maintain monotonicity for rates above the current rate */ |
1242 | for (rate = tx_rate; rate < size - 1; rate++) { | 1059 | for (rate = tx_rate; rate < size - 1; rate++) { |
1243 | if (ath_rc_priv->state[rate+1].per < | 1060 | if (ath_rc_priv->per[rate+1] < |
1244 | ath_rc_priv->state[rate].per) | 1061 | ath_rc_priv->per[rate]) |
1245 | ath_rc_priv->state[rate+1].per = | 1062 | ath_rc_priv->per[rate+1] = |
1246 | ath_rc_priv->state[rate].per; | 1063 | ath_rc_priv->per[rate]; |
1247 | } | ||
1248 | |||
1249 | /* Every so often, we reduce the thresholds and | ||
1250 | * PER (different for CCK and OFDM). */ | ||
1251 | if (now_msec - ath_rc_priv->rssi_down_time >= | ||
1252 | rate_table->rssi_reduce_interval) { | ||
1253 | |||
1254 | for (rate = 0; rate < size; rate++) { | ||
1255 | if (ath_rc_priv->state[rate].rssi_thres > | ||
1256 | rate_table->info[rate].rssi_ack_validmin) | ||
1257 | ath_rc_priv->state[rate].rssi_thres -= 1; | ||
1258 | } | ||
1259 | ath_rc_priv->rssi_down_time = now_msec; | ||
1260 | } | 1064 | } |
1261 | 1065 | ||
1262 | /* Every so often, we reduce the thresholds | 1066 | /* Every so often, we reduce the thresholds |
1263 | * and PER (different for CCK and OFDM). */ | 1067 | * and PER (different for CCK and OFDM). */ |
1264 | if (now_msec - ath_rc_priv->per_down_time >= | 1068 | if (now_msec - ath_rc_priv->per_down_time >= |
1265 | rate_table->rssi_reduce_interval) { | 1069 | rate_table->probe_interval) { |
1266 | for (rate = 0; rate < size; rate++) { | 1070 | for (rate = 0; rate < size; rate++) { |
1267 | ath_rc_priv->state[rate].per = | 1071 | ath_rc_priv->per[rate] = |
1268 | 7 * ath_rc_priv->state[rate].per / 8; | 1072 | 7 * ath_rc_priv->per[rate] / 8; |
1269 | } | 1073 | } |
1270 | 1074 | ||
1271 | ath_rc_priv->per_down_time = now_msec; | 1075 | ath_rc_priv->per_down_time = now_msec; |
1272 | } | 1076 | } |
1273 | 1077 | ||
1274 | ath_debug_stat_retries(sc, tx_rate, xretries, retries, | 1078 | ath_debug_stat_retries(sc, tx_rate, xretries, retries, |
1275 | ath_rc_priv->state[tx_rate].per); | 1079 | ath_rc_priv->per[tx_rate]); |
1276 | 1080 | ||
1277 | #undef CHK_RSSI | ||
1278 | } | 1081 | } |
1279 | 1082 | ||
1280 | static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, | 1083 | static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, |
@@ -1410,9 +1213,7 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1410 | 1213 | ||
1411 | /* Initialize thresholds according to the global rate table */ | 1214 | /* Initialize thresholds according to the global rate table */ |
1412 | for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { | 1215 | for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { |
1413 | ath_rc_priv->state[i].rssi_thres = | 1216 | ath_rc_priv->per[i] = 0; |
1414 | rate_table->info[i].rssi_ack_validmin; | ||
1415 | ath_rc_priv->state[i].per = 0; | ||
1416 | } | 1217 | } |
1417 | 1218 | ||
1418 | /* Determine the valid rates */ | 1219 | /* Determine the valid rates */ |
@@ -1521,7 +1322,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1521 | /* | 1322 | /* |
1522 | * If underrun error is seen assume it as an excessive retry only | 1323 | * If underrun error is seen assume it as an excessive retry only |
1523 | * if prefetch trigger level have reached the max (0x3f for 5416) | 1324 | * if prefetch trigger level have reached the max (0x3f for 5416) |
1524 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY | 1325 | * Adjust the long retry as if the frame was tried hw->max_rate_tries |
1525 | * times. This affects how ratectrl updates PER for the failed rate. | 1326 | * times. This affects how ratectrl updates PER for the failed rate. |
1526 | */ | 1327 | */ |
1527 | if (tx_info_priv->tx.ts_flags & | 1328 | if (tx_info_priv->tx.ts_flags & |
@@ -1536,7 +1337,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1536 | tx_status = 1; | 1337 | tx_status = 1; |
1537 | 1338 | ||
1538 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, | 1339 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, |
1539 | (is_underrun) ? ATH_11N_TXMAXTRY : | 1340 | (is_underrun) ? sc->hw->max_rate_tries : |
1540 | tx_info_priv->tx.ts_longretry); | 1341 | tx_info_priv->tx.ts_longretry); |
1541 | 1342 | ||
1542 | /* Check if aggregation has to be enabled for this tid */ | 1343 | /* Check if aggregation has to be enabled for this tid */ |
@@ -1560,31 +1361,6 @@ exit: | |||
1560 | kfree(tx_info_priv); | 1361 | kfree(tx_info_priv); |
1561 | } | 1362 | } |
1562 | 1363 | ||
1563 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | ||
1564 | struct ieee80211_tx_rate_control *txrc) | ||
1565 | { | ||
1566 | struct ieee80211_supported_band *sband = txrc->sband; | ||
1567 | struct sk_buff *skb = txrc->skb; | ||
1568 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1569 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1570 | struct ath_softc *sc = priv; | ||
1571 | struct ath_rate_priv *ath_rc_priv = priv_sta; | ||
1572 | __le16 fc = hdr->frame_control; | ||
1573 | |||
1574 | /* lowest rate for management and NO_ACK frames */ | ||
1575 | if (!ieee80211_is_data(fc) || | ||
1576 | tx_info->flags & IEEE80211_TX_CTL_NO_ACK || !sta) { | ||
1577 | tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); | ||
1578 | tx_info->control.rates[0].count = | ||
1579 | (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) ? | ||
1580 | 1 : ATH_MGT_TXMAXTRY; | ||
1581 | return; | ||
1582 | } | ||
1583 | |||
1584 | /* Find tx rate for unicast frames */ | ||
1585 | ath_rc_ratefind(sc, ath_rc_priv, txrc); | ||
1586 | } | ||
1587 | |||
1588 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 1364 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
1589 | struct ieee80211_sta *sta, void *priv_sta) | 1365 | struct ieee80211_sta *sta, void *priv_sta) |
1590 | { | 1366 | { |
@@ -1697,7 +1473,6 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp | |||
1697 | return NULL; | 1473 | return NULL; |
1698 | } | 1474 | } |
1699 | 1475 | ||
1700 | rate_priv->rssi_down_time = jiffies_to_msecs(jiffies); | ||
1701 | rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; | 1476 | rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; |
1702 | 1477 | ||
1703 | return rate_priv; | 1478 | return rate_priv; |
@@ -1725,8 +1500,6 @@ static struct rate_control_ops ath_rate_ops = { | |||
1725 | 1500 | ||
1726 | void ath_rate_attach(struct ath_softc *sc) | 1501 | void ath_rate_attach(struct ath_softc *sc) |
1727 | { | 1502 | { |
1728 | sc->hw_rate_table[ATH9K_MODE_11B] = | ||
1729 | &ar5416_11b_ratetable; | ||
1730 | sc->hw_rate_table[ATH9K_MODE_11A] = | 1503 | sc->hw_rate_table[ATH9K_MODE_11A] = |
1731 | &ar5416_11a_ratetable; | 1504 | &ar5416_11a_ratetable; |
1732 | sc->hw_rate_table[ATH9K_MODE_11G] = | 1505 | sc->hw_rate_table[ATH9K_MODE_11G] = |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index e3abd76103fd..fa21a628ddd0 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -112,8 +112,6 @@ struct ath_rate_table { | |||
112 | u8 short_preamble; | 112 | u8 short_preamble; |
113 | u8 dot11rate; | 113 | u8 dot11rate; |
114 | u8 ctrl_rate; | 114 | u8 ctrl_rate; |
115 | int8_t rssi_ack_validmin; | ||
116 | int8_t rssi_ack_deltamin; | ||
117 | u8 base_index; | 115 | u8 base_index; |
118 | u8 cw40index; | 116 | u8 cw40index; |
119 | u8 sgi_index; | 117 | u8 sgi_index; |
@@ -121,15 +119,9 @@ struct ath_rate_table { | |||
121 | u32 max_4ms_framelen; | 119 | u32 max_4ms_framelen; |
122 | } info[RATE_TABLE_SIZE]; | 120 | } info[RATE_TABLE_SIZE]; |
123 | u32 probe_interval; | 121 | u32 probe_interval; |
124 | u32 rssi_reduce_interval; | ||
125 | u8 initial_ratemax; | 122 | u8 initial_ratemax; |
126 | }; | 123 | }; |
127 | 124 | ||
128 | struct ath_tx_ratectrl_state { | ||
129 | int8_t rssi_thres; /* required rssi for this rate (dB) */ | ||
130 | u8 per; /* recent estimate of packet error rate (%) */ | ||
131 | }; | ||
132 | |||
133 | struct ath_rateset { | 125 | struct ath_rateset { |
134 | u8 rs_nrates; | 126 | u8 rs_nrates; |
135 | u8 rs_rates[ATH_RATE_MAX]; | 127 | u8 rs_rates[ATH_RATE_MAX]; |
@@ -138,22 +130,14 @@ struct ath_rateset { | |||
138 | /** | 130 | /** |
139 | * struct ath_rate_priv - Rate Control priv data | 131 | * struct ath_rate_priv - Rate Control priv data |
140 | * @state: RC state | 132 | * @state: RC state |
141 | * @rssi_last: last ACK rssi | ||
142 | * @rssi_last_lookup: last ACK rssi used for lookup | ||
143 | * @rssi_last_prev: previous last ACK rssi | ||
144 | * @rssi_last_prev2: 2nd previous last ACK rssi | ||
145 | * @rssi_sum_cnt: count of rssi_sum for averaging | ||
146 | * @rssi_sum_rate: rate that we are averaging | ||
147 | * @rssi_sum: running sum of rssi for averaging | ||
148 | * @probe_rate: rate we are probing at | 133 | * @probe_rate: rate we are probing at |
149 | * @rssi_time: msec timestamp for last ack rssi | ||
150 | * @rssi_down_time: msec timestamp for last down step | ||
151 | * @probe_time: msec timestamp for last probe | 134 | * @probe_time: msec timestamp for last probe |
152 | * @hw_maxretry_pktcnt: num of packets since we got HW max retry error | 135 | * @hw_maxretry_pktcnt: num of packets since we got HW max retry error |
153 | * @max_valid_rate: maximum number of valid rate | 136 | * @max_valid_rate: maximum number of valid rate |
154 | * @per_down_time: msec timestamp for last PER down step | 137 | * @per_down_time: msec timestamp for last PER down step |
155 | * @valid_phy_ratecnt: valid rate count | 138 | * @valid_phy_ratecnt: valid rate count |
156 | * @rate_max_phy: phy index for the max rate | 139 | * @rate_max_phy: phy index for the max rate |
140 | * @per: PER for every valid rate in % | ||
157 | * @probe_interval: interval for ratectrl to probe for other rates | 141 | * @probe_interval: interval for ratectrl to probe for other rates |
158 | * @prev_data_rix: rate idx of last data frame | 142 | * @prev_data_rix: rate idx of last data frame |
159 | * @ht_cap: HT capabilities | 143 | * @ht_cap: HT capabilities |
@@ -161,13 +145,6 @@ struct ath_rateset { | |||
161 | * @neg_ht_rates: Negotiated HT rates | 145 | * @neg_ht_rates: Negotiated HT rates |
162 | */ | 146 | */ |
163 | struct ath_rate_priv { | 147 | struct ath_rate_priv { |
164 | int8_t rssi_last; | ||
165 | int8_t rssi_last_lookup; | ||
166 | int8_t rssi_last_prev; | ||
167 | int8_t rssi_last_prev2; | ||
168 | int32_t rssi_sum_cnt; | ||
169 | int32_t rssi_sum_rate; | ||
170 | int32_t rssi_sum; | ||
171 | u8 rate_table_size; | 148 | u8 rate_table_size; |
172 | u8 probe_rate; | 149 | u8 probe_rate; |
173 | u8 hw_maxretry_pktcnt; | 150 | u8 hw_maxretry_pktcnt; |
@@ -177,14 +154,12 @@ struct ath_rate_priv { | |||
177 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; | 154 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; |
178 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; | 155 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; |
179 | u8 rate_max_phy; | 156 | u8 rate_max_phy; |
180 | u32 rssi_time; | 157 | u8 per[RATE_TABLE_SIZE]; |
181 | u32 rssi_down_time; | ||
182 | u32 probe_time; | 158 | u32 probe_time; |
183 | u32 per_down_time; | 159 | u32 per_down_time; |
184 | u32 probe_interval; | 160 | u32 probe_interval; |
185 | u32 prev_data_rix; | 161 | u32 prev_data_rix; |
186 | u32 tx_triglevel_max; | 162 | u32 tx_triglevel_max; |
187 | struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE]; | ||
188 | struct ath_rateset neg_rates; | 163 | struct ath_rateset neg_rates; |
189 | struct ath_rateset neg_ht_rates; | 164 | struct ath_rateset neg_ht_rates; |
190 | struct ath_rate_softc *asc; | 165 | struct ath_rate_softc *asc; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b3da81db453b..61edfab20ffc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -145,6 +145,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
145 | u8 ratecode; | 145 | u8 ratecode; |
146 | __le16 fc; | 146 | __le16 fc; |
147 | struct ieee80211_hw *hw; | 147 | struct ieee80211_hw *hw; |
148 | struct ieee80211_sta *sta; | ||
149 | struct ath_node *an; | ||
150 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
151 | |||
148 | 152 | ||
149 | hdr = (struct ieee80211_hdr *)skb->data; | 153 | hdr = (struct ieee80211_hdr *)skb->data; |
150 | fc = hdr->frame_control; | 154 | fc = hdr->frame_control; |
@@ -229,11 +233,30 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
229 | } | 233 | } |
230 | } | 234 | } |
231 | 235 | ||
236 | rcu_read_lock(); | ||
237 | sta = ieee80211_find_sta(sc->hw, hdr->addr2); | ||
238 | if (sta) { | ||
239 | an = (struct ath_node *) sta->drv_priv; | ||
240 | if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && | ||
241 | !ds->ds_rxstat.rs_moreaggr) | ||
242 | ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi); | ||
243 | last_rssi = an->last_rssi; | ||
244 | } | ||
245 | rcu_read_unlock(); | ||
246 | |||
247 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
248 | ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi, | ||
249 | ATH_RSSI_EP_MULTIPLIER); | ||
250 | if (ds->ds_rxstat.rs_rssi < 0) | ||
251 | ds->ds_rxstat.rs_rssi = 0; | ||
252 | else if (ds->ds_rxstat.rs_rssi > 127) | ||
253 | ds->ds_rxstat.rs_rssi = 127; | ||
254 | |||
232 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | 255 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); |
233 | rx_status->band = hw->conf.channel->band; | 256 | rx_status->band = hw->conf.channel->band; |
234 | rx_status->freq = hw->conf.channel->center_freq; | 257 | rx_status->freq = hw->conf.channel->center_freq; |
235 | rx_status->noise = sc->ani.noise_floor; | 258 | rx_status->noise = sc->ani.noise_floor; |
236 | rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; | 259 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi; |
237 | rx_status->antenna = ds->ds_rxstat.rs_antenna; | 260 | rx_status->antenna = ds->ds_rxstat.rs_antenna; |
238 | 261 | ||
239 | /* | 262 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 52605246679f..8302aeb62e5d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -574,6 +574,7 @@ | |||
574 | 574 | ||
575 | #define AR_D_GBL_IFS_SIFS 0x1030 | 575 | #define AR_D_GBL_IFS_SIFS 0x1030 |
576 | #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF | 576 | #define AR_D_GBL_IFS_SIFS_M 0x0000FFFF |
577 | #define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB | ||
577 | #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF | 578 | #define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF |
578 | 579 | ||
579 | #define AR_D_TXBLK_BASE 0x1038 | 580 | #define AR_D_TXBLK_BASE 0x1038 |
@@ -589,10 +590,12 @@ | |||
589 | #define AR_D_GBL_IFS_SLOT 0x1070 | 590 | #define AR_D_GBL_IFS_SLOT 0x1070 |
590 | #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF | 591 | #define AR_D_GBL_IFS_SLOT_M 0x0000FFFF |
591 | #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 | 592 | #define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 |
593 | #define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420 | ||
592 | 594 | ||
593 | #define AR_D_GBL_IFS_EIFS 0x10b0 | 595 | #define AR_D_GBL_IFS_EIFS 0x10b0 |
594 | #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF | 596 | #define AR_D_GBL_IFS_EIFS_M 0x0000FFFF |
595 | #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 | 597 | #define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 |
598 | #define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB | ||
596 | 599 | ||
597 | #define AR_D_GBL_IFS_MISC 0x10f0 | 600 | #define AR_D_GBL_IFS_MISC 0x10f0 |
598 | #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 | 601 | #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 |
@@ -738,6 +741,9 @@ | |||
738 | #define AR_SREV_REVISION_9285_10 0 | 741 | #define AR_SREV_REVISION_9285_10 0 |
739 | #define AR_SREV_REVISION_9285_11 1 | 742 | #define AR_SREV_REVISION_9285_11 1 |
740 | #define AR_SREV_REVISION_9285_12 2 | 743 | #define AR_SREV_REVISION_9285_12 2 |
744 | #define AR_SREV_VERSION_9287 0x180 | ||
745 | #define AR_SREV_REVISION_9287_10 0 | ||
746 | #define AR_SREV_REVISION_9287_11 1 | ||
741 | 747 | ||
742 | #define AR_SREV_5416(_ah) \ | 748 | #define AR_SREV_5416(_ah) \ |
743 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 749 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
@@ -794,6 +800,21 @@ | |||
794 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ | 800 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ |
795 | AR_SREV_REVISION_9285_12))) | 801 | AR_SREV_REVISION_9285_12))) |
796 | 802 | ||
803 | #define AR_SREV_9287(_ah) \ | ||
804 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) | ||
805 | #define AR_SREV_9287_10_OR_LATER(_ah) \ | ||
806 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) | ||
807 | #define AR_SREV_9287_10(_ah) \ | ||
808 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
809 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10)) | ||
810 | #define AR_SREV_9287_11(_ah) \ | ||
811 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
812 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) | ||
813 | #define AR_SREV_9287_11_OR_LATER(_ah) \ | ||
814 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | ||
815 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
816 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) | ||
817 | |||
797 | #define AR_RADIO_SREV_MAJOR 0xf0 | 818 | #define AR_RADIO_SREV_MAJOR 0xf0 |
798 | #define AR_RAD5133_SREV_MAJOR 0xc0 | 819 | #define AR_RAD5133_SREV_MAJOR 0xc0 |
799 | #define AR_RAD2133_SREV_MAJOR 0xd0 | 820 | #define AR_RAD2133_SREV_MAJOR 0xd0 |
@@ -809,6 +830,9 @@ | |||
809 | #define AR_AHB_PAGE_SIZE_1K 0x00000000 | 830 | #define AR_AHB_PAGE_SIZE_1K 0x00000000 |
810 | #define AR_AHB_PAGE_SIZE_2K 0x00000008 | 831 | #define AR_AHB_PAGE_SIZE_2K 0x00000008 |
811 | #define AR_AHB_PAGE_SIZE_4K 0x00000010 | 832 | #define AR_AHB_PAGE_SIZE_4K 0x00000010 |
833 | #define AR_AHB_CUSTOM_BURST_EN 0x000000C0 | ||
834 | #define AR_AHB_CUSTOM_BURST_EN_S 6 | ||
835 | #define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3 | ||
812 | 836 | ||
813 | #define AR_INTR_RTC_IRQ 0x00000001 | 837 | #define AR_INTR_RTC_IRQ 0x00000001 |
814 | #define AR_INTR_MAC_IRQ 0x00000002 | 838 | #define AR_INTR_MAC_IRQ 0x00000002 |
@@ -885,6 +909,7 @@ enum { | |||
885 | #define AR_NUM_GPIO 14 | 909 | #define AR_NUM_GPIO 14 |
886 | #define AR928X_NUM_GPIO 10 | 910 | #define AR928X_NUM_GPIO 10 |
887 | #define AR9285_NUM_GPIO 12 | 911 | #define AR9285_NUM_GPIO 12 |
912 | #define AR9287_NUM_GPIO 11 | ||
888 | 913 | ||
889 | #define AR_GPIO_IN_OUT 0x4048 | 914 | #define AR_GPIO_IN_OUT 0x4048 |
890 | #define AR_GPIO_IN_VAL 0x0FFFC000 | 915 | #define AR_GPIO_IN_VAL 0x0FFFC000 |
@@ -893,6 +918,8 @@ enum { | |||
893 | #define AR928X_GPIO_IN_VAL_S 10 | 918 | #define AR928X_GPIO_IN_VAL_S 10 |
894 | #define AR9285_GPIO_IN_VAL 0x00FFF000 | 919 | #define AR9285_GPIO_IN_VAL 0x00FFF000 |
895 | #define AR9285_GPIO_IN_VAL_S 12 | 920 | #define AR9285_GPIO_IN_VAL_S 12 |
921 | #define AR9287_GPIO_IN_VAL 0x003FF800 | ||
922 | #define AR9287_GPIO_IN_VAL_S 11 | ||
896 | 923 | ||
897 | #define AR_GPIO_OE_OUT 0x404c | 924 | #define AR_GPIO_OE_OUT 0x404c |
898 | #define AR_GPIO_OE_OUT_DRV 0x3 | 925 | #define AR_GPIO_OE_OUT_DRV 0x3 |
@@ -1154,6 +1181,33 @@ enum { | |||
1154 | #define AR9285_AN_TOP4 0x7870 | 1181 | #define AR9285_AN_TOP4 0x7870 |
1155 | #define AR9285_AN_TOP4_DEFAULT 0x10142c00 | 1182 | #define AR9285_AN_TOP4_DEFAULT 0x10142c00 |
1156 | 1183 | ||
1184 | #define AR9287_AN_RF2G3_CH0 0x7808 | ||
1185 | #define AR9287_AN_RF2G3_CH1 0x785c | ||
1186 | #define AR9287_AN_RF2G3_DB1 0xE0000000 | ||
1187 | #define AR9287_AN_RF2G3_DB1_S 29 | ||
1188 | #define AR9287_AN_RF2G3_DB2 0x1C000000 | ||
1189 | #define AR9287_AN_RF2G3_DB2_S 26 | ||
1190 | #define AR9287_AN_RF2G3_OB_CCK 0x03800000 | ||
1191 | #define AR9287_AN_RF2G3_OB_CCK_S 23 | ||
1192 | #define AR9287_AN_RF2G3_OB_PSK 0x00700000 | ||
1193 | #define AR9287_AN_RF2G3_OB_PSK_S 20 | ||
1194 | #define AR9287_AN_RF2G3_OB_QAM 0x000E0000 | ||
1195 | #define AR9287_AN_RF2G3_OB_QAM_S 17 | ||
1196 | #define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000 | ||
1197 | #define AR9287_AN_RF2G3_OB_PAL_OFF_S 14 | ||
1198 | |||
1199 | #define AR9287_AN_TXPC0 0x7898 | ||
1200 | #define AR9287_AN_TXPC0_TXPCMODE 0x0000C000 | ||
1201 | #define AR9287_AN_TXPC0_TXPCMODE_S 14 | ||
1202 | #define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0 | ||
1203 | #define AR9287_AN_TXPC0_TXPCMODE_TEST 1 | ||
1204 | #define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2 | ||
1205 | #define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3 | ||
1206 | |||
1207 | #define AR9287_AN_TOP2 0x78b4 | ||
1208 | #define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 | ||
1209 | #define AR9287_AN_TOP2_XPABIAS_LVL_S 30 | ||
1210 | |||
1157 | #define AR_STA_ID0 0x8000 | 1211 | #define AR_STA_ID0 0x8000 |
1158 | #define AR_STA_ID1 0x8004 | 1212 | #define AR_STA_ID1 0x8004 |
1159 | #define AR_STA_ID1_SADH_MASK 0x0000FFFF | 1213 | #define AR_STA_ID1_SADH_MASK 0x0000FFFF |
@@ -1188,6 +1242,7 @@ enum { | |||
1188 | #define AR_TIME_OUT_ACK_S 0 | 1242 | #define AR_TIME_OUT_ACK_S 0 |
1189 | #define AR_TIME_OUT_CTS 0x3FFF0000 | 1243 | #define AR_TIME_OUT_CTS 0x3FFF0000 |
1190 | #define AR_TIME_OUT_CTS_S 16 | 1244 | #define AR_TIME_OUT_CTS_S 16 |
1245 | #define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56 | ||
1191 | 1246 | ||
1192 | #define AR_RSSI_THR 0x8018 | 1247 | #define AR_RSSI_THR 0x8018 |
1193 | #define AR_RSSI_THR_MASK 0x000000FF | 1248 | #define AR_RSSI_THR_MASK 0x000000FF |
@@ -1203,6 +1258,7 @@ enum { | |||
1203 | #define AR_USEC_TX_LAT_S 14 | 1258 | #define AR_USEC_TX_LAT_S 14 |
1204 | #define AR_USEC_RX_LAT 0x1F800000 | 1259 | #define AR_USEC_RX_LAT 0x1F800000 |
1205 | #define AR_USEC_RX_LAT_S 23 | 1260 | #define AR_USEC_RX_LAT_S 23 |
1261 | #define AR_USEC_ASYNC_FIFO_DUR 0x12e00074 | ||
1206 | 1262 | ||
1207 | #define AR_RESET_TSF 0x8020 | 1263 | #define AR_RESET_TSF 0x8020 |
1208 | #define AR_RESET_TSF_ONCE 0x01000000 | 1264 | #define AR_RESET_TSF_ONCE 0x01000000 |
@@ -1468,6 +1524,10 @@ enum { | |||
1468 | #define AR_SLP_MIB_CLEAR 0x00000001 | 1524 | #define AR_SLP_MIB_CLEAR 0x00000001 |
1469 | #define AR_SLP_MIB_PENDING 0x00000002 | 1525 | #define AR_SLP_MIB_PENDING 0x00000002 |
1470 | 1526 | ||
1527 | #define AR_MAC_PCU_LOGIC_ANALYZER 0x8264 | ||
1528 | #define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 | ||
1529 | |||
1530 | |||
1471 | #define AR_2040_MODE 0x8318 | 1531 | #define AR_2040_MODE 0x8318 |
1472 | #define AR_2040_JOINED_RX_CLEAR 0x00000001 | 1532 | #define AR_2040_JOINED_RX_CLEAR 0x00000001 |
1473 | 1533 | ||
@@ -1485,6 +1545,39 @@ enum { | |||
1485 | #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 | 1545 | #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 |
1486 | #define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 | 1546 | #define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 |
1487 | 1547 | ||
1548 | #define AR_PCU_MISC_MODE2_RESERVED 0x00000038 | ||
1549 | #define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040 | ||
1550 | #define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080 | ||
1551 | #define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00 | ||
1552 | #define AR_PCU_MISC_MODE2_MGMT_QOS_S 8 | ||
1553 | #define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000 | ||
1554 | #define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000 | ||
1555 | #define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 | ||
1556 | #define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 | ||
1557 | #define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000 | ||
1558 | |||
1559 | #define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 | ||
1560 | #define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 | ||
1561 | #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 | ||
1562 | |||
1563 | |||
1564 | #define AR_AES_MUTE_MASK0 0x805c | ||
1565 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF | ||
1566 | #define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 | ||
1567 | #define AR_AES_MUTE_MASK0_QOS_S 16 | ||
1568 | |||
1569 | #define AR_AES_MUTE_MASK1 0x8060 | ||
1570 | #define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF | ||
1571 | #define AR_AES_MUTE_MASK1_SEQ_S 0 | ||
1572 | #define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 | ||
1573 | #define AR_AES_MUTE_MASK1_FC_MGMT_S 16 | ||
1574 | |||
1575 | #define AR_RATE_DURATION_0 0x8700 | ||
1576 | #define AR_RATE_DURATION_31 0x87CC | ||
1577 | #define AR_RATE_DURATION_32 0x8780 | ||
1578 | #define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) | ||
1579 | |||
1580 | |||
1488 | #define AR_KEYTABLE_0 0x8800 | 1581 | #define AR_KEYTABLE_0 0x8800 |
1489 | #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) | 1582 | #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) |
1490 | #define AR_KEY_CACHE_SIZE 128 | 1583 | #define AR_KEY_CACHE_SIZE 128 |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 1ff429b027d7..e1d419e02b4a 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -660,3 +660,20 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | |||
660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, | 660 | queue_delayed_work(sc->hw->workqueue, &sc->wiphy_work, |
661 | sc->wiphy_scheduler_int); | 661 | sc->wiphy_scheduler_int); |
662 | } | 662 | } |
663 | |||
664 | /* caller must hold wiphy_lock */ | ||
665 | bool ath9k_all_wiphys_idle(struct ath_softc *sc) | ||
666 | { | ||
667 | unsigned int i; | ||
668 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
669 | return false; | ||
670 | } | ||
671 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
672 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
673 | if (!aphy) | ||
674 | continue; | ||
675 | if (aphy->state != ATH_WIPHY_INACTIVE) | ||
676 | return false; | ||
677 | } | ||
678 | return true; | ||
679 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 5de9878d2c12..4ff155e8ee59 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -242,7 +242,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
242 | spin_unlock_bh(&sc->tx.txbuflock); | 242 | spin_unlock_bh(&sc->tx.txbuflock); |
243 | return NULL; | 243 | return NULL; |
244 | } | 244 | } |
245 | ASSERT(!list_empty((&sc->tx.txbuf))); | ||
246 | tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); | 245 | tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); |
247 | list_del(&tbf->list); | 246 | list_del(&tbf->list); |
248 | spin_unlock_bh(&sc->tx.txbuflock); | 247 | spin_unlock_bh(&sc->tx.txbuflock); |
@@ -383,8 +382,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
383 | struct ath_buf *tbf; | 382 | struct ath_buf *tbf; |
384 | 383 | ||
385 | tbf = ath_clone_txbuf(sc, bf_last); | 384 | tbf = ath_clone_txbuf(sc, bf_last); |
386 | if (!tbf) | 385 | /* |
386 | * Update tx baw and complete the frame with | ||
387 | * failed status if we run out of tx buf | ||
388 | */ | ||
389 | if (!tbf) { | ||
390 | spin_lock_bh(&txq->axq_lock); | ||
391 | ath_tx_update_baw(sc, tid, | ||
392 | bf->bf_seqno); | ||
393 | spin_unlock_bh(&txq->axq_lock); | ||
394 | |||
395 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
396 | ath_tx_rc_status(bf, ds, nbad, | ||
397 | 0, false); | ||
398 | ath_tx_complete_buf(sc, bf, &bf_head, | ||
399 | 0, 0); | ||
387 | break; | 400 | break; |
401 | } | ||
402 | |||
388 | ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); | 403 | ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); |
389 | list_add_tail(&tbf->list, &bf_head); | 404 | list_add_tail(&tbf->list, &bf_head); |
390 | } else { | 405 | } else { |
@@ -857,6 +872,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
857 | txq->axq_aggr_depth = 0; | 872 | txq->axq_aggr_depth = 0; |
858 | txq->axq_totalqueued = 0; | 873 | txq->axq_totalqueued = 0; |
859 | txq->axq_linkbuf = NULL; | 874 | txq->axq_linkbuf = NULL; |
875 | txq->axq_tx_inprogress = false; | ||
860 | sc->tx.txqsetup |= 1<<qnum; | 876 | sc->tx.txqsetup |= 1<<qnum; |
861 | } | 877 | } |
862 | return &sc->tx.txq[qnum]; | 878 | return &sc->tx.txq[qnum]; |
@@ -1023,6 +1039,10 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1023 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); | 1039 | ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); |
1024 | } | 1040 | } |
1025 | 1041 | ||
1042 | spin_lock_bh(&txq->axq_lock); | ||
1043 | txq->axq_tx_inprogress = false; | ||
1044 | spin_unlock_bh(&txq->axq_lock); | ||
1045 | |||
1026 | /* flush any pending frames if aggregation is enabled */ | 1046 | /* flush any pending frames if aggregation is enabled */ |
1027 | if (sc->sc_flags & SC_OP_TXAGGR) { | 1047 | if (sc->sc_flags & SC_OP_TXAGGR) { |
1028 | if (!retry_tx) { | 1048 | if (!retry_tx) { |
@@ -1103,8 +1123,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1103 | if (tid->paused) | 1123 | if (tid->paused) |
1104 | continue; | 1124 | continue; |
1105 | 1125 | ||
1106 | if ((txq->axq_depth % 2) == 0) | 1126 | ath_tx_sched_aggr(sc, txq, tid); |
1107 | ath_tx_sched_aggr(sc, txq, tid); | ||
1108 | 1127 | ||
1109 | /* | 1128 | /* |
1110 | * add tid to round-robin queue if more frames | 1129 | * add tid to round-robin queue if more frames |
@@ -1947,19 +1966,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1947 | if (bf->bf_stale) { | 1966 | if (bf->bf_stale) { |
1948 | bf_held = bf; | 1967 | bf_held = bf; |
1949 | if (list_is_last(&bf_held->list, &txq->axq_q)) { | 1968 | if (list_is_last(&bf_held->list, &txq->axq_q)) { |
1950 | txq->axq_link = NULL; | ||
1951 | txq->axq_linkbuf = NULL; | ||
1952 | spin_unlock_bh(&txq->axq_lock); | 1969 | spin_unlock_bh(&txq->axq_lock); |
1953 | |||
1954 | /* | ||
1955 | * The holding descriptor is the last | ||
1956 | * descriptor in queue. It's safe to remove | ||
1957 | * the last holding descriptor in BH context. | ||
1958 | */ | ||
1959 | spin_lock_bh(&sc->tx.txbuflock); | ||
1960 | list_move_tail(&bf_held->list, &sc->tx.txbuf); | ||
1961 | spin_unlock_bh(&sc->tx.txbuflock); | ||
1962 | |||
1963 | break; | 1970 | break; |
1964 | } else { | 1971 | } else { |
1965 | bf = list_entry(bf_held->list.next, | 1972 | bf = list_entry(bf_held->list.next, |
@@ -1996,6 +2003,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1996 | txq->axq_aggr_depth--; | 2003 | txq->axq_aggr_depth--; |
1997 | 2004 | ||
1998 | txok = (ds->ds_txstat.ts_status == 0); | 2005 | txok = (ds->ds_txstat.ts_status == 0); |
2006 | txq->axq_tx_inprogress = false; | ||
1999 | spin_unlock_bh(&txq->axq_lock); | 2007 | spin_unlock_bh(&txq->axq_lock); |
2000 | 2008 | ||
2001 | if (bf_held) { | 2009 | if (bf_held) { |
@@ -2029,6 +2037,40 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2029 | } | 2037 | } |
2030 | } | 2038 | } |
2031 | 2039 | ||
2040 | void ath_tx_complete_poll_work(struct work_struct *work) | ||
2041 | { | ||
2042 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
2043 | tx_complete_work.work); | ||
2044 | struct ath_txq *txq; | ||
2045 | int i; | ||
2046 | bool needreset = false; | ||
2047 | |||
2048 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
2049 | if (ATH_TXQ_SETUP(sc, i)) { | ||
2050 | txq = &sc->tx.txq[i]; | ||
2051 | spin_lock_bh(&txq->axq_lock); | ||
2052 | if (txq->axq_depth) { | ||
2053 | if (txq->axq_tx_inprogress) { | ||
2054 | needreset = true; | ||
2055 | spin_unlock_bh(&txq->axq_lock); | ||
2056 | break; | ||
2057 | } else { | ||
2058 | txq->axq_tx_inprogress = true; | ||
2059 | } | ||
2060 | } | ||
2061 | spin_unlock_bh(&txq->axq_lock); | ||
2062 | } | ||
2063 | |||
2064 | if (needreset) { | ||
2065 | DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); | ||
2066 | ath_reset(sc, false); | ||
2067 | } | ||
2068 | |||
2069 | queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, | ||
2070 | msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); | ||
2071 | } | ||
2072 | |||
2073 | |||
2032 | 2074 | ||
2033 | void ath_tx_tasklet(struct ath_softc *sc) | 2075 | void ath_tx_tasklet(struct ath_softc *sc) |
2034 | { | 2076 | { |
@@ -2069,6 +2111,8 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2069 | goto err; | 2111 | goto err; |
2070 | } | 2112 | } |
2071 | 2113 | ||
2114 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); | ||
2115 | |||
2072 | err: | 2116 | err: |
2073 | if (error != 0) | 2117 | if (error != 0) |
2074 | ath_tx_cleanup(sc); | 2118 | ath_tx_cleanup(sc); |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e71c8d9cd706..3f4360ad0e4e 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -938,7 +938,6 @@ static void b43_clear_keys(struct b43_wldev *dev) | |||
938 | static void b43_dump_keymemory(struct b43_wldev *dev) | 938 | static void b43_dump_keymemory(struct b43_wldev *dev) |
939 | { | 939 | { |
940 | unsigned int i, index, offset; | 940 | unsigned int i, index, offset; |
941 | DECLARE_MAC_BUF(macbuf); | ||
942 | u8 mac[ETH_ALEN]; | 941 | u8 mac[ETH_ALEN]; |
943 | u16 algo; | 942 | u16 algo; |
944 | u32 rcmta0; | 943 | u32 rcmta0; |
@@ -973,8 +972,7 @@ static void b43_dump_keymemory(struct b43_wldev *dev) | |||
973 | ((index - 4) * 2) + 1); | 972 | ((index - 4) * 2) + 1); |
974 | *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); | 973 | *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); |
975 | *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); | 974 | *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); |
976 | printk(" MAC: %s", | 975 | printk(" MAC: %pM", mac); |
977 | print_mac(macbuf, mac)); | ||
978 | } else | 976 | } else |
979 | printk(" DEFAULT KEY"); | 977 | printk(" DEFAULT KEY"); |
980 | printk("\n"); | 978 | printk("\n"); |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 633740277352..ad8eab4a639b 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -666,7 +666,8 @@ static int prism2_config(struct pcmcia_device *link) | |||
666 | * irq structure is initialized. | 666 | * irq structure is initialized. |
667 | */ | 667 | */ |
668 | if (link->conf.Attributes & CONF_ENABLE_IRQ) { | 668 | if (link->conf.Attributes & CONF_ENABLE_IRQ) { |
669 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 669 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | |
670 | IRQ_HANDLE_PRESENT; | ||
670 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 671 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
671 | link->irq.Handler = prism2_interrupt; | 672 | link->irq.Handler = prism2_interrupt; |
672 | link->irq.Instance = dev; | 673 | link->irq.Instance = dev; |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index d726b3c6077a..2dc1cdbb4939 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -7250,9 +7250,6 @@ static void ipw_bg_qos_activate(struct work_struct *work) | |||
7250 | struct ipw_priv *priv = | 7250 | struct ipw_priv *priv = |
7251 | container_of(work, struct ipw_priv, qos_activate); | 7251 | container_of(work, struct ipw_priv, qos_activate); |
7252 | 7252 | ||
7253 | if (priv == NULL) | ||
7254 | return; | ||
7255 | |||
7256 | mutex_lock(&priv->mutex); | 7253 | mutex_lock(&priv->mutex); |
7257 | 7254 | ||
7258 | if (priv->status & STATUS_ASSOCIATED) | 7255 | if (priv->status & STATUS_ASSOCIATED) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 7da52f1cc1d6..a899be914ebf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | 47 | ||
48 | /* Highest firmware API version supported */ | 48 | /* Highest firmware API version supported */ |
49 | #define IWL1000_UCODE_API_MAX 2 | 49 | #define IWL1000_UCODE_API_MAX 3 |
50 | 50 | ||
51 | /* Lowest firmware API version supported */ | 51 | /* Lowest firmware API version supported */ |
52 | #define IWL1000_UCODE_API_MIN 1 | 52 | #define IWL1000_UCODE_API_MIN 1 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 73f93a0ff2df..b569c6f38e5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -232,9 +232,8 @@ struct iwl3945_eeprom { | |||
232 | #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ | 232 | #define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ |
233 | #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ | 233 | #define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ |
234 | 234 | ||
235 | #define TFD_QUEUE_MIN 0 | 235 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ |
236 | #define TFD_QUEUE_MAX 5 /* 4 DATA + 1 CMD */ | 236 | #define IWL39_NUM_QUEUES 5 |
237 | |||
238 | #define IWL_NUM_SCAN_RATES (2) | 237 | #define IWL_NUM_SCAN_RATES (2) |
239 | 238 | ||
240 | #define IWL_DEFAULT_TX_RETRY 15 | 239 | #define IWL_DEFAULT_TX_RETRY 15 |
@@ -280,8 +279,6 @@ struct iwl3945_eeprom { | |||
280 | /* Size of uCode instruction memory in bootstrap state machine */ | 279 | /* Size of uCode instruction memory in bootstrap state machine */ |
281 | #define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE | 280 | #define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE |
282 | 281 | ||
283 | #define IWL39_MAX_NUM_QUEUES 8 | ||
284 | |||
285 | static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) | 282 | static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) |
286 | { | 283 | { |
287 | return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && | 284 | return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 5eb538d18a80..a16bd4147eac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -673,33 +673,17 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
673 | s8 scale_action = 0; | 673 | s8 scale_action = 0; |
674 | unsigned long flags; | 674 | unsigned long flags; |
675 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 675 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
676 | u16 fc; | 676 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; |
677 | u16 rate_mask = 0; | ||
678 | s8 max_rate_idx = -1; | 677 | s8 max_rate_idx = -1; |
679 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 678 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
680 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 679 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
681 | 680 | ||
682 | IWL_DEBUG_RATE(priv, "enter\n"); | 681 | IWL_DEBUG_RATE(priv, "enter\n"); |
683 | 682 | ||
684 | if (sta) | 683 | if (rate_control_send_low(sta, priv_sta, txrc)) |
685 | rate_mask = sta->supp_rates[sband->band]; | ||
686 | |||
687 | /* Send management frames and NO_ACK data using lowest rate. */ | ||
688 | fc = le16_to_cpu(hdr->frame_control); | ||
689 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
690 | info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
691 | !sta || !priv_sta) { | ||
692 | IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); | ||
693 | if (!rate_mask) | ||
694 | info->control.rates[0].idx = | ||
695 | rate_lowest_index(sband, NULL); | ||
696 | else | ||
697 | info->control.rates[0].idx = | ||
698 | rate_lowest_index(sband, sta); | ||
699 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
700 | info->control.rates[0].count = 1; | ||
701 | return; | 684 | return; |
702 | } | 685 | |
686 | rate_mask = sta->supp_rates[sband->band]; | ||
703 | 687 | ||
704 | /* get user max rate if set */ | 688 | /* get user max rate if set */ |
705 | max_rate_idx = txrc->max_rate_idx; | 689 | max_rate_idx = txrc->max_rate_idx; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b0246dbda99a..8ee403cd9b99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -502,14 +502,14 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | |||
502 | } | 502 | } |
503 | } | 503 | } |
504 | if (print_dump) | 504 | if (print_dump) |
505 | iwl_print_hex_dump(priv, IWL_DL_RX, data, length); | 505 | iwl_print_hex_dump(IWL_DL_RX, data, length); |
506 | } | 506 | } |
507 | 507 | ||
508 | static void iwl3945_dbg_report_frame(struct iwl_priv *priv, | 508 | static void iwl3945_dbg_report_frame(struct iwl_priv *priv, |
509 | struct iwl_rx_packet *pkt, | 509 | struct iwl_rx_packet *pkt, |
510 | struct ieee80211_hdr *header, int group100) | 510 | struct ieee80211_hdr *header, int group100) |
511 | { | 511 | { |
512 | if (priv->debug_level & IWL_DL_RX) | 512 | if (iwl_debug_level & IWL_DL_RX) |
513 | _iwl3945_dbg_report_frame(priv, pkt, header, group100); | 513 | _iwl3945_dbg_report_frame(priv, pkt, header, group100); |
514 | } | 514 | } |
515 | 515 | ||
@@ -963,7 +963,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
963 | goto error; | 963 | goto error; |
964 | 964 | ||
965 | /* Tx queue(s) */ | 965 | /* Tx queue(s) */ |
966 | for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { | 966 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
967 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | 967 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? |
968 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 968 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; |
969 | rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | 969 | rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, |
@@ -1140,7 +1140,7 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1140 | int txq_id; | 1140 | int txq_id; |
1141 | 1141 | ||
1142 | /* Tx queues */ | 1142 | /* Tx queues */ |
1143 | for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) | 1143 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
1144 | if (txq_id == IWL_CMD_QUEUE_NUM) | 1144 | if (txq_id == IWL_CMD_QUEUE_NUM) |
1145 | iwl_cmd_queue_free(priv); | 1145 | iwl_cmd_queue_free(priv); |
1146 | else | 1146 | else |
@@ -1156,7 +1156,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1156 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); | 1156 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); |
1157 | 1157 | ||
1158 | /* reset TFD queues */ | 1158 | /* reset TFD queues */ |
1159 | for (txq_id = 0; txq_id <= priv->hw_params.max_txq_num; txq_id++) { | 1159 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
1160 | iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); | 1160 | iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); |
1161 | iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, | 1161 | iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, |
1162 | FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), | 1162 | FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), |
@@ -2552,7 +2552,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2552 | } | 2552 | } |
2553 | 2553 | ||
2554 | /* Assign number of Usable TX queues */ | 2554 | /* Assign number of Usable TX queues */ |
2555 | priv->hw_params.max_txq_num = TFD_QUEUE_MAX; | 2555 | priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; |
2556 | 2556 | ||
2557 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | 2557 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); |
2558 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; | 2558 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; |
@@ -2786,11 +2786,50 @@ static int iwl3945_load_bsm(struct iwl_priv *priv) | |||
2786 | return 0; | 2786 | return 0; |
2787 | } | 2787 | } |
2788 | 2788 | ||
2789 | #define IWL3945_UCODE_GET(item) \ | ||
2790 | static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
2791 | u32 api_ver) \ | ||
2792 | { \ | ||
2793 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2794 | } | ||
2795 | |||
2796 | static u32 iwl3945_ucode_get_header_size(u32 api_ver) | ||
2797 | { | ||
2798 | return UCODE_HEADER_SIZE(1); | ||
2799 | } | ||
2800 | static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2801 | u32 api_ver) | ||
2802 | { | ||
2803 | return 0; | ||
2804 | } | ||
2805 | static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
2806 | u32 api_ver) | ||
2807 | { | ||
2808 | return (u8 *) ucode->u.v1.data; | ||
2809 | } | ||
2810 | |||
2811 | IWL3945_UCODE_GET(inst_size); | ||
2812 | IWL3945_UCODE_GET(data_size); | ||
2813 | IWL3945_UCODE_GET(init_size); | ||
2814 | IWL3945_UCODE_GET(init_data_size); | ||
2815 | IWL3945_UCODE_GET(boot_size); | ||
2816 | |||
2789 | static struct iwl_hcmd_ops iwl3945_hcmd = { | 2817 | static struct iwl_hcmd_ops iwl3945_hcmd = { |
2790 | .rxon_assoc = iwl3945_send_rxon_assoc, | 2818 | .rxon_assoc = iwl3945_send_rxon_assoc, |
2791 | .commit_rxon = iwl3945_commit_rxon, | 2819 | .commit_rxon = iwl3945_commit_rxon, |
2792 | }; | 2820 | }; |
2793 | 2821 | ||
2822 | static struct iwl_ucode_ops iwl3945_ucode = { | ||
2823 | .get_header_size = iwl3945_ucode_get_header_size, | ||
2824 | .get_build = iwl3945_ucode_get_build, | ||
2825 | .get_inst_size = iwl3945_ucode_get_inst_size, | ||
2826 | .get_data_size = iwl3945_ucode_get_data_size, | ||
2827 | .get_init_size = iwl3945_ucode_get_init_size, | ||
2828 | .get_init_data_size = iwl3945_ucode_get_init_data_size, | ||
2829 | .get_boot_size = iwl3945_ucode_get_boot_size, | ||
2830 | .get_data = iwl3945_ucode_get_data, | ||
2831 | }; | ||
2832 | |||
2794 | static struct iwl_lib_ops iwl3945_lib = { | 2833 | static struct iwl_lib_ops iwl3945_lib = { |
2795 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, | 2834 | .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, |
2796 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, | 2835 | .txq_free_tfd = iwl3945_hw_txq_free_tfd, |
@@ -2831,6 +2870,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | |||
2831 | }; | 2870 | }; |
2832 | 2871 | ||
2833 | static struct iwl_ops iwl3945_ops = { | 2872 | static struct iwl_ops iwl3945_ops = { |
2873 | .ucode = &iwl3945_ucode, | ||
2834 | .lib = &iwl3945_lib, | 2874 | .lib = &iwl3945_lib, |
2835 | .hcmd = &iwl3945_hcmd, | 2875 | .hcmd = &iwl3945_hcmd, |
2836 | .utils = &iwl3945_hcmd_utils, | 2876 | .utils = &iwl3945_hcmd_utils, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fbb3a573463e..f2ffc48cbaf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -111,9 +111,6 @@ enum iwl3945_antenna { | |||
111 | #define IWL_TX_FIFO_HCCA_2 6 | 111 | #define IWL_TX_FIFO_HCCA_2 6 |
112 | #define IWL_TX_FIFO_NONE 7 | 112 | #define IWL_TX_FIFO_NONE 7 |
113 | 113 | ||
114 | /* Minimum number of queues. MAX_NUM is defined in hw specific files */ | ||
115 | #define IWL_MIN_NUM_QUEUES 4 | ||
116 | |||
117 | #define IEEE80211_DATA_LEN 2304 | 114 | #define IEEE80211_DATA_LEN 2304 |
118 | #define IEEE80211_4ADDR_LEN 30 | 115 | #define IEEE80211_4ADDR_LEN 30 |
119 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) | 116 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index edbb0bfd8cb7..c30a1b960576 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -146,7 +146,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) | |||
146 | 146 | ||
147 | IWL_DEBUG_INFO(priv, "Begin load bsm\n"); | 147 | IWL_DEBUG_INFO(priv, "Begin load bsm\n"); |
148 | 148 | ||
149 | priv->ucode_type = UCODE_RT; | 149 | priv->ucode_type = UCODE_INIT; |
150 | 150 | ||
151 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | 151 | /* make sure bootstrap program is no larger than BSM's SRAM size */ |
152 | if (len > IWL49_MAX_BSM_SIZE) | 152 | if (len > IWL49_MAX_BSM_SIZE) |
@@ -256,6 +256,8 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) | |||
256 | */ | 256 | */ |
257 | static void iwl4965_init_alive_start(struct iwl_priv *priv) | 257 | static void iwl4965_init_alive_start(struct iwl_priv *priv) |
258 | { | 258 | { |
259 | int ret; | ||
260 | |||
259 | /* Check alive response for "valid" sign from uCode */ | 261 | /* Check alive response for "valid" sign from uCode */ |
260 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | 262 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { |
261 | /* We had an error bringing up the hardware, so take it | 263 | /* We had an error bringing up the hardware, so take it |
@@ -287,6 +289,28 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) | |||
287 | IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); | 289 | IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); |
288 | goto restart; | 290 | goto restart; |
289 | } | 291 | } |
292 | priv->ucode_type = UCODE_RT; | ||
293 | if (test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) { | ||
294 | IWL_WARN(priv, "Runtime uCode already alive? " | ||
295 | "Waiting for alive anyway\n"); | ||
296 | clear_bit(STATUS_RT_UCODE_ALIVE, &priv->status); | ||
297 | } | ||
298 | ret = wait_event_interruptible_timeout( | ||
299 | priv->wait_command_queue, | ||
300 | test_bit(STATUS_RT_UCODE_ALIVE, &priv->status), | ||
301 | UCODE_ALIVE_TIMEOUT); | ||
302 | if (!ret) { | ||
303 | /* FIXME: if STATUS_RT_UCODE_ALIVE timeout | ||
304 | * go back to restart the download Init uCode again | ||
305 | * this might cause to trap in the restart loop | ||
306 | */ | ||
307 | priv->ucode_type = UCODE_NONE; | ||
308 | if (!test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) { | ||
309 | IWL_ERR(priv, "Runtime timeout after %dms\n", | ||
310 | jiffies_to_msecs(UCODE_ALIVE_TIMEOUT)); | ||
311 | goto restart; | ||
312 | } | ||
313 | } | ||
290 | return; | 314 | return; |
291 | 315 | ||
292 | restart: | 316 | restart: |
@@ -2221,12 +2245,50 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) | |||
2221 | cancel_work_sync(&priv->txpower_work); | 2245 | cancel_work_sync(&priv->txpower_work); |
2222 | } | 2246 | } |
2223 | 2247 | ||
2248 | #define IWL4965_UCODE_GET(item) \ | ||
2249 | static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
2250 | u32 api_ver) \ | ||
2251 | { \ | ||
2252 | return le32_to_cpu(ucode->u.v1.item); \ | ||
2253 | } | ||
2254 | |||
2255 | static u32 iwl4965_ucode_get_header_size(u32 api_ver) | ||
2256 | { | ||
2257 | return UCODE_HEADER_SIZE(1); | ||
2258 | } | ||
2259 | static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
2260 | u32 api_ver) | ||
2261 | { | ||
2262 | return 0; | ||
2263 | } | ||
2264 | static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
2265 | u32 api_ver) | ||
2266 | { | ||
2267 | return (u8 *) ucode->u.v1.data; | ||
2268 | } | ||
2269 | |||
2270 | IWL4965_UCODE_GET(inst_size); | ||
2271 | IWL4965_UCODE_GET(data_size); | ||
2272 | IWL4965_UCODE_GET(init_size); | ||
2273 | IWL4965_UCODE_GET(init_data_size); | ||
2274 | IWL4965_UCODE_GET(boot_size); | ||
2275 | |||
2224 | static struct iwl_hcmd_ops iwl4965_hcmd = { | 2276 | static struct iwl_hcmd_ops iwl4965_hcmd = { |
2225 | .rxon_assoc = iwl4965_send_rxon_assoc, | 2277 | .rxon_assoc = iwl4965_send_rxon_assoc, |
2226 | .commit_rxon = iwl_commit_rxon, | 2278 | .commit_rxon = iwl_commit_rxon, |
2227 | .set_rxon_chain = iwl_set_rxon_chain, | 2279 | .set_rxon_chain = iwl_set_rxon_chain, |
2228 | }; | 2280 | }; |
2229 | 2281 | ||
2282 | static struct iwl_ucode_ops iwl4965_ucode = { | ||
2283 | .get_header_size = iwl4965_ucode_get_header_size, | ||
2284 | .get_build = iwl4965_ucode_get_build, | ||
2285 | .get_inst_size = iwl4965_ucode_get_inst_size, | ||
2286 | .get_data_size = iwl4965_ucode_get_data_size, | ||
2287 | .get_init_size = iwl4965_ucode_get_init_size, | ||
2288 | .get_init_data_size = iwl4965_ucode_get_init_data_size, | ||
2289 | .get_boot_size = iwl4965_ucode_get_boot_size, | ||
2290 | .get_data = iwl4965_ucode_get_data, | ||
2291 | }; | ||
2230 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 2292 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { |
2231 | .get_hcmd_size = iwl4965_get_hcmd_size, | 2293 | .get_hcmd_size = iwl4965_get_hcmd_size, |
2232 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2294 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
@@ -2287,6 +2349,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2287 | }; | 2349 | }; |
2288 | 2350 | ||
2289 | static struct iwl_ops iwl4965_ops = { | 2351 | static struct iwl_ops iwl4965_ops = { |
2352 | .ucode = &iwl4965_ucode, | ||
2290 | .lib = &iwl4965_lib, | 2353 | .lib = &iwl4965_lib, |
2291 | .hcmd = &iwl4965_hcmd, | 2354 | .hcmd = &iwl4965_hcmd, |
2292 | .utils = &iwl4965_hcmd_utils, | 2355 | .utils = &iwl4965_hcmd_utils, |
@@ -2313,8 +2376,6 @@ module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | |||
2313 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2376 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
2314 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2377 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); |
2315 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | 2378 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2316 | module_param_named(debug, iwl4965_mod_params.debug, uint, 0444); | ||
2317 | MODULE_PARM_DESC(debug, "debug output mask"); | ||
2318 | module_param_named( | 2379 | module_param_named( |
2319 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); | 2380 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); |
2320 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 2381 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 85e8bac499a7..702db07fa382 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -239,6 +239,13 @@ static void iwl5000_nic_config(struct iwl_priv *priv) | |||
239 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, | 239 | APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, |
240 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); | 240 | ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); |
241 | 241 | ||
242 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_1000) { | ||
243 | /* Setting digital SVR for 1000 card to 1.32V */ | ||
244 | iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, | ||
245 | APMG_SVR_DIGITAL_VOLTAGE_1_32, | ||
246 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | ||
247 | } | ||
248 | |||
242 | spin_unlock_irqrestore(&priv->lock, flags); | 249 | spin_unlock_irqrestore(&priv->lock, flags); |
243 | } | 250 | } |
244 | 251 | ||
@@ -1449,6 +1456,44 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, | |||
1449 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 1456 | return max_rssi - agc - IWL49_RSSI_OFFSET; |
1450 | } | 1457 | } |
1451 | 1458 | ||
1459 | #define IWL5000_UCODE_GET(item) \ | ||
1460 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
1461 | u32 api_ver) \ | ||
1462 | { \ | ||
1463 | if (api_ver <= 2) \ | ||
1464 | return le32_to_cpu(ucode->u.v1.item); \ | ||
1465 | return le32_to_cpu(ucode->u.v2.item); \ | ||
1466 | } | ||
1467 | |||
1468 | static u32 iwl5000_ucode_get_header_size(u32 api_ver) | ||
1469 | { | ||
1470 | if (api_ver <= 2) | ||
1471 | return UCODE_HEADER_SIZE(1); | ||
1472 | return UCODE_HEADER_SIZE(2); | ||
1473 | } | ||
1474 | |||
1475 | static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
1476 | u32 api_ver) | ||
1477 | { | ||
1478 | if (api_ver <= 2) | ||
1479 | return 0; | ||
1480 | return le32_to_cpu(ucode->u.v2.build); | ||
1481 | } | ||
1482 | |||
1483 | static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
1484 | u32 api_ver) | ||
1485 | { | ||
1486 | if (api_ver <= 2) | ||
1487 | return (u8 *) ucode->u.v1.data; | ||
1488 | return (u8 *) ucode->u.v2.data; | ||
1489 | } | ||
1490 | |||
1491 | IWL5000_UCODE_GET(inst_size); | ||
1492 | IWL5000_UCODE_GET(data_size); | ||
1493 | IWL5000_UCODE_GET(init_size); | ||
1494 | IWL5000_UCODE_GET(init_data_size); | ||
1495 | IWL5000_UCODE_GET(boot_size); | ||
1496 | |||
1452 | struct iwl_hcmd_ops iwl5000_hcmd = { | 1497 | struct iwl_hcmd_ops iwl5000_hcmd = { |
1453 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1498 | .rxon_assoc = iwl5000_send_rxon_assoc, |
1454 | .commit_rxon = iwl_commit_rxon, | 1499 | .commit_rxon = iwl_commit_rxon, |
@@ -1464,6 +1509,17 @@ struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | |||
1464 | .calc_rssi = iwl5000_calc_rssi, | 1509 | .calc_rssi = iwl5000_calc_rssi, |
1465 | }; | 1510 | }; |
1466 | 1511 | ||
1512 | struct iwl_ucode_ops iwl5000_ucode = { | ||
1513 | .get_header_size = iwl5000_ucode_get_header_size, | ||
1514 | .get_build = iwl5000_ucode_get_build, | ||
1515 | .get_inst_size = iwl5000_ucode_get_inst_size, | ||
1516 | .get_data_size = iwl5000_ucode_get_data_size, | ||
1517 | .get_init_size = iwl5000_ucode_get_init_size, | ||
1518 | .get_init_data_size = iwl5000_ucode_get_init_data_size, | ||
1519 | .get_boot_size = iwl5000_ucode_get_boot_size, | ||
1520 | .get_data = iwl5000_ucode_get_data, | ||
1521 | }; | ||
1522 | |||
1467 | struct iwl_lib_ops iwl5000_lib = { | 1523 | struct iwl_lib_ops iwl5000_lib = { |
1468 | .set_hw_params = iwl5000_hw_set_hw_params, | 1524 | .set_hw_params = iwl5000_hw_set_hw_params, |
1469 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 1525 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
@@ -1565,12 +1621,14 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1565 | }; | 1621 | }; |
1566 | 1622 | ||
1567 | struct iwl_ops iwl5000_ops = { | 1623 | struct iwl_ops iwl5000_ops = { |
1624 | .ucode = &iwl5000_ucode, | ||
1568 | .lib = &iwl5000_lib, | 1625 | .lib = &iwl5000_lib, |
1569 | .hcmd = &iwl5000_hcmd, | 1626 | .hcmd = &iwl5000_hcmd, |
1570 | .utils = &iwl5000_hcmd_utils, | 1627 | .utils = &iwl5000_hcmd_utils, |
1571 | }; | 1628 | }; |
1572 | 1629 | ||
1573 | static struct iwl_ops iwl5150_ops = { | 1630 | static struct iwl_ops iwl5150_ops = { |
1631 | .ucode = &iwl5000_ucode, | ||
1574 | .lib = &iwl5150_lib, | 1632 | .lib = &iwl5150_lib, |
1575 | .hcmd = &iwl5000_hcmd, | 1633 | .hcmd = &iwl5000_hcmd, |
1576 | .utils = &iwl5000_hcmd_utils, | 1634 | .utils = &iwl5000_hcmd_utils, |
@@ -1687,8 +1745,6 @@ MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | |||
1687 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); | 1745 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); |
1688 | MODULE_PARM_DESC(swcrypto50, | 1746 | MODULE_PARM_DESC(swcrypto50, |
1689 | "using software crypto engine (default 0 [hardware])\n"); | 1747 | "using software crypto engine (default 0 [hardware])\n"); |
1690 | module_param_named(debug50, iwl50_mod_params.debug, uint, 0444); | ||
1691 | MODULE_PARM_DESC(debug50, "50XX debug output mask"); | ||
1692 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | 1748 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); |
1693 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | 1749 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); |
1694 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); | 1750 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index bd438d8acf55..26c5d4a60d17 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -46,8 +46,8 @@ | |||
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | 47 | ||
48 | /* Highest firmware API version supported */ | 48 | /* Highest firmware API version supported */ |
49 | #define IWL6000_UCODE_API_MAX 2 | 49 | #define IWL6000_UCODE_API_MAX 3 |
50 | #define IWL6050_UCODE_API_MAX 2 | 50 | #define IWL6050_UCODE_API_MAX 3 |
51 | 51 | ||
52 | /* Lowest firmware API version supported */ | 52 | /* Lowest firmware API version supported */ |
53 | #define IWL6000_UCODE_API_MIN 1 | 53 | #define IWL6000_UCODE_API_MIN 1 |
@@ -69,6 +69,7 @@ static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static struct iwl_ops iwl6000_ops = { | 71 | static struct iwl_ops iwl6000_ops = { |
72 | .ucode = &iwl5000_ucode, | ||
72 | .lib = &iwl5000_lib, | 73 | .lib = &iwl5000_lib, |
73 | .hcmd = &iwl5000_hcmd, | 74 | .hcmd = &iwl5000_hcmd, |
74 | .utils = &iwl6000_hcmd_utils, | 75 | .utils = &iwl6000_hcmd_utils, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index ff20e5048a55..63280411fd58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -2466,7 +2466,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2466 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2467 | struct iwl_lq_sta *lq_sta = priv_sta; | 2467 | struct iwl_lq_sta *lq_sta = priv_sta; |
2468 | int rate_idx; | 2468 | int rate_idx; |
2469 | u64 mask_bit = 0; | ||
2470 | 2469 | ||
2471 | IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n"); | 2470 | IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n"); |
2472 | 2471 | ||
@@ -2481,22 +2480,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2481 | lq_sta->max_rate_idx = -1; | 2480 | lq_sta->max_rate_idx = -1; |
2482 | } | 2481 | } |
2483 | 2482 | ||
2484 | if (sta) | ||
2485 | mask_bit = sta->supp_rates[sband->band]; | ||
2486 | |||
2487 | /* Send management frames and NO_ACK data using lowest rate. */ | 2483 | /* Send management frames and NO_ACK data using lowest rate. */ |
2488 | if (!ieee80211_is_data(hdr->frame_control) || | 2484 | if (rate_control_send_low(sta, priv_sta, txrc)) |
2489 | info->flags & IEEE80211_TX_CTL_NO_ACK || !sta || !lq_sta) { | ||
2490 | if (!mask_bit) | ||
2491 | info->control.rates[0].idx = | ||
2492 | rate_lowest_index(sband, NULL); | ||
2493 | else | ||
2494 | info->control.rates[0].idx = | ||
2495 | rate_lowest_index(sband, sta); | ||
2496 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
2497 | info->control.rates[0].count = 1; | ||
2498 | return; | 2485 | return; |
2499 | } | ||
2500 | 2486 | ||
2501 | rate_idx = lq_sta->last_txrate_idx; | 2487 | rate_idx = lq_sta->last_txrate_idx; |
2502 | 2488 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e2cc5994d108..44c7f236a7a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -533,12 +533,16 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, | |||
533 | 533 | ||
534 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { | 534 | if (palive->ver_subtype == INITIALIZE_SUBTYPE) { |
535 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); | 535 | IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); |
536 | set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status); | ||
537 | wake_up_interruptible(&priv->wait_command_queue); | ||
536 | memcpy(&priv->card_alive_init, | 538 | memcpy(&priv->card_alive_init, |
537 | &pkt->u.alive_frame, | 539 | &pkt->u.alive_frame, |
538 | sizeof(struct iwl_init_alive_resp)); | 540 | sizeof(struct iwl_init_alive_resp)); |
539 | pwork = &priv->init_alive_start; | 541 | pwork = &priv->init_alive_start; |
540 | } else { | 542 | } else { |
541 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | 543 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); |
544 | set_bit(STATUS_RT_UCODE_ALIVE, &priv->status); | ||
545 | wake_up_interruptible(&priv->wait_command_queue); | ||
542 | memcpy(&priv->card_alive, &pkt->u.alive_frame, | 546 | memcpy(&priv->card_alive, &pkt->u.alive_frame, |
543 | sizeof(struct iwl_alive_resp)); | 547 | sizeof(struct iwl_alive_resp)); |
544 | pwork = &priv->alive_start; | 548 | pwork = &priv->alive_start; |
@@ -900,7 +904,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
900 | iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); | 904 | iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); |
901 | 905 | ||
902 | #ifdef CONFIG_IWLWIFI_DEBUG | 906 | #ifdef CONFIG_IWLWIFI_DEBUG |
903 | if (priv->debug_level & IWL_DL_ISR) { | 907 | if (iwl_debug_level & IWL_DL_ISR) { |
904 | /* just for debug */ | 908 | /* just for debug */ |
905 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 909 | inta_mask = iwl_read32(priv, CSR_INT_MASK); |
906 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | 910 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", |
@@ -919,7 +923,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
919 | 923 | ||
920 | /* Now service all interrupt bits discovered above. */ | 924 | /* Now service all interrupt bits discovered above. */ |
921 | if (inta & CSR_INT_BIT_HW_ERR) { | 925 | if (inta & CSR_INT_BIT_HW_ERR) { |
922 | IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); | 926 | IWL_ERR(priv, "Hardware error detected. Restarting.\n"); |
923 | 927 | ||
924 | /* Tell the device to stop sending interrupts */ | 928 | /* Tell the device to stop sending interrupts */ |
925 | iwl_disable_interrupts(priv); | 929 | iwl_disable_interrupts(priv); |
@@ -935,7 +939,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
935 | } | 939 | } |
936 | 940 | ||
937 | #ifdef CONFIG_IWLWIFI_DEBUG | 941 | #ifdef CONFIG_IWLWIFI_DEBUG |
938 | if (priv->debug_level & (IWL_DL_ISR)) { | 942 | if (iwl_debug_level & (IWL_DL_ISR)) { |
939 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | 943 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ |
940 | if (inta & CSR_INT_BIT_SCD) { | 944 | if (inta & CSR_INT_BIT_SCD) { |
941 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " | 945 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " |
@@ -960,7 +964,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
960 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 964 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
961 | hw_rf_kill = 1; | 965 | hw_rf_kill = 1; |
962 | 966 | ||
963 | IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", | 967 | IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", |
964 | hw_rf_kill ? "disable radio" : "enable radio"); | 968 | hw_rf_kill ? "disable radio" : "enable radio"); |
965 | 969 | ||
966 | priv->isr_stats.rfkill++; | 970 | priv->isr_stats.rfkill++; |
@@ -1049,7 +1053,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1049 | iwl_enable_interrupts(priv); | 1053 | iwl_enable_interrupts(priv); |
1050 | 1054 | ||
1051 | #ifdef CONFIG_IWLWIFI_DEBUG | 1055 | #ifdef CONFIG_IWLWIFI_DEBUG |
1052 | if (priv->debug_level & (IWL_DL_ISR)) { | 1056 | if (iwl_debug_level & (IWL_DL_ISR)) { |
1053 | inta = iwl_read32(priv, CSR_INT); | 1057 | inta = iwl_read32(priv, CSR_INT); |
1054 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 1058 | inta_mask = iwl_read32(priv, CSR_INT_MASK); |
1055 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | 1059 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); |
@@ -1080,7 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1080 | inta = priv->inta; | 1084 | inta = priv->inta; |
1081 | 1085 | ||
1082 | #ifdef CONFIG_IWLWIFI_DEBUG | 1086 | #ifdef CONFIG_IWLWIFI_DEBUG |
1083 | if (priv->debug_level & IWL_DL_ISR) { | 1087 | if (iwl_debug_level & IWL_DL_ISR) { |
1084 | /* just for debug */ | 1088 | /* just for debug */ |
1085 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 1089 | inta_mask = iwl_read32(priv, CSR_INT_MASK); |
1086 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", | 1090 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", |
@@ -1092,7 +1096,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1092 | 1096 | ||
1093 | /* Now service all interrupt bits discovered above. */ | 1097 | /* Now service all interrupt bits discovered above. */ |
1094 | if (inta & CSR_INT_BIT_HW_ERR) { | 1098 | if (inta & CSR_INT_BIT_HW_ERR) { |
1095 | IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); | 1099 | IWL_ERR(priv, "Hardware error detected. Restarting.\n"); |
1096 | 1100 | ||
1097 | /* Tell the device to stop sending interrupts */ | 1101 | /* Tell the device to stop sending interrupts */ |
1098 | iwl_disable_interrupts(priv); | 1102 | iwl_disable_interrupts(priv); |
@@ -1108,7 +1112,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1108 | } | 1112 | } |
1109 | 1113 | ||
1110 | #ifdef CONFIG_IWLWIFI_DEBUG | 1114 | #ifdef CONFIG_IWLWIFI_DEBUG |
1111 | if (priv->debug_level & (IWL_DL_ISR)) { | 1115 | if (iwl_debug_level & (IWL_DL_ISR)) { |
1112 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | 1116 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ |
1113 | if (inta & CSR_INT_BIT_SCD) { | 1117 | if (inta & CSR_INT_BIT_SCD) { |
1114 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " | 1118 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " |
@@ -1133,7 +1137,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1133 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | 1137 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) |
1134 | hw_rf_kill = 1; | 1138 | hw_rf_kill = 1; |
1135 | 1139 | ||
1136 | IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", | 1140 | IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", |
1137 | hw_rf_kill ? "disable radio" : "enable radio"); | 1141 | hw_rf_kill ? "disable radio" : "enable radio"); |
1138 | 1142 | ||
1139 | priv->isr_stats.rfkill++; | 1143 | priv->isr_stats.rfkill++; |
@@ -1284,7 +1288,7 @@ static void iwl_nic_start(struct iwl_priv *priv) | |||
1284 | */ | 1288 | */ |
1285 | static int iwl_read_ucode(struct iwl_priv *priv) | 1289 | static int iwl_read_ucode(struct iwl_priv *priv) |
1286 | { | 1290 | { |
1287 | struct iwl_ucode *ucode; | 1291 | struct iwl_ucode_header *ucode; |
1288 | int ret = -EINVAL, index; | 1292 | int ret = -EINVAL, index; |
1289 | const struct firmware *ucode_raw; | 1293 | const struct firmware *ucode_raw; |
1290 | const char *name_pre = priv->cfg->fw_name_pre; | 1294 | const char *name_pre = priv->cfg->fw_name_pre; |
@@ -1293,7 +1297,8 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1293 | char buf[25]; | 1297 | char buf[25]; |
1294 | u8 *src; | 1298 | u8 *src; |
1295 | size_t len; | 1299 | size_t len; |
1296 | u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; | 1300 | u32 api_ver, build; |
1301 | u32 inst_size, data_size, init_size, init_data_size, boot_size; | ||
1297 | 1302 | ||
1298 | /* Ask kernel firmware_class module to get the boot firmware off disk. | 1303 | /* Ask kernel firmware_class module to get the boot firmware off disk. |
1299 | * request_firmware() is synchronous, file is in memory on return. */ | 1304 | * request_firmware() is synchronous, file is in memory on return. */ |
@@ -1323,23 +1328,26 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1323 | if (ret < 0) | 1328 | if (ret < 0) |
1324 | goto error; | 1329 | goto error; |
1325 | 1330 | ||
1326 | /* Make sure that we got at least our header! */ | 1331 | /* Make sure that we got at least the v1 header! */ |
1327 | if (ucode_raw->size < sizeof(*ucode)) { | 1332 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { |
1328 | IWL_ERR(priv, "File size way too small!\n"); | 1333 | IWL_ERR(priv, "File size way too small!\n"); |
1329 | ret = -EINVAL; | 1334 | ret = -EINVAL; |
1330 | goto err_release; | 1335 | goto err_release; |
1331 | } | 1336 | } |
1332 | 1337 | ||
1333 | /* Data from ucode file: header followed by uCode images */ | 1338 | /* Data from ucode file: header followed by uCode images */ |
1334 | ucode = (void *)ucode_raw->data; | 1339 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
1335 | 1340 | ||
1336 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 1341 | priv->ucode_ver = le32_to_cpu(ucode->ver); |
1337 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 1342 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
1338 | inst_size = le32_to_cpu(ucode->inst_size); | 1343 | build = priv->cfg->ops->ucode->get_build(ucode, api_ver); |
1339 | data_size = le32_to_cpu(ucode->data_size); | 1344 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); |
1340 | init_size = le32_to_cpu(ucode->init_size); | 1345 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); |
1341 | init_data_size = le32_to_cpu(ucode->init_data_size); | 1346 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); |
1342 | boot_size = le32_to_cpu(ucode->boot_size); | 1347 | init_data_size = |
1348 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); | ||
1349 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | ||
1350 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
1343 | 1351 | ||
1344 | /* api_ver should match the api version forming part of the | 1352 | /* api_ver should match the api version forming part of the |
1345 | * firmware filename ... but we don't check for that and only rely | 1353 | * firmware filename ... but we don't check for that and only rely |
@@ -1365,6 +1373,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1365 | IWL_UCODE_API(priv->ucode_ver), | 1373 | IWL_UCODE_API(priv->ucode_ver), |
1366 | IWL_UCODE_SERIAL(priv->ucode_ver)); | 1374 | IWL_UCODE_SERIAL(priv->ucode_ver)); |
1367 | 1375 | ||
1376 | if (build) | ||
1377 | IWL_DEBUG_INFO(priv, "Build %u\n", build); | ||
1378 | |||
1368 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", | 1379 | IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", |
1369 | priv->ucode_ver); | 1380 | priv->ucode_ver); |
1370 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", | 1381 | IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", |
@@ -1379,12 +1390,14 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1379 | boot_size); | 1390 | boot_size); |
1380 | 1391 | ||
1381 | /* Verify size of file vs. image size info in file's header */ | 1392 | /* Verify size of file vs. image size info in file's header */ |
1382 | if (ucode_raw->size < sizeof(*ucode) + | 1393 | if (ucode_raw->size != |
1394 | priv->cfg->ops->ucode->get_header_size(api_ver) + | ||
1383 | inst_size + data_size + init_size + | 1395 | inst_size + data_size + init_size + |
1384 | init_data_size + boot_size) { | 1396 | init_data_size + boot_size) { |
1385 | 1397 | ||
1386 | IWL_DEBUG_INFO(priv, "uCode file size %d too small\n", | 1398 | IWL_DEBUG_INFO(priv, |
1387 | (int)ucode_raw->size); | 1399 | "uCode file size %d does not match expected size\n", |
1400 | (int)ucode_raw->size); | ||
1388 | ret = -EINVAL; | 1401 | ret = -EINVAL; |
1389 | goto err_release; | 1402 | goto err_release; |
1390 | } | 1403 | } |
@@ -1464,42 +1477,42 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1464 | /* Copy images into buffers for card's bus-master reads ... */ | 1477 | /* Copy images into buffers for card's bus-master reads ... */ |
1465 | 1478 | ||
1466 | /* Runtime instructions (first block of data in file) */ | 1479 | /* Runtime instructions (first block of data in file) */ |
1467 | src = &ucode->data[0]; | 1480 | len = inst_size; |
1468 | len = priv->ucode_code.len; | ||
1469 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); | 1481 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); |
1470 | memcpy(priv->ucode_code.v_addr, src, len); | 1482 | memcpy(priv->ucode_code.v_addr, src, len); |
1483 | src += len; | ||
1484 | |||
1471 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 1485 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
1472 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 1486 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
1473 | 1487 | ||
1474 | /* Runtime data (2nd block) | 1488 | /* Runtime data (2nd block) |
1475 | * NOTE: Copy into backup buffer will be done in iwl_up() */ | 1489 | * NOTE: Copy into backup buffer will be done in iwl_up() */ |
1476 | src = &ucode->data[inst_size]; | 1490 | len = data_size; |
1477 | len = priv->ucode_data.len; | ||
1478 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); | 1491 | IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); |
1479 | memcpy(priv->ucode_data.v_addr, src, len); | 1492 | memcpy(priv->ucode_data.v_addr, src, len); |
1480 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 1493 | memcpy(priv->ucode_data_backup.v_addr, src, len); |
1494 | src += len; | ||
1481 | 1495 | ||
1482 | /* Initialization instructions (3rd block) */ | 1496 | /* Initialization instructions (3rd block) */ |
1483 | if (init_size) { | 1497 | if (init_size) { |
1484 | src = &ucode->data[inst_size + data_size]; | 1498 | len = init_size; |
1485 | len = priv->ucode_init.len; | ||
1486 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", | 1499 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", |
1487 | len); | 1500 | len); |
1488 | memcpy(priv->ucode_init.v_addr, src, len); | 1501 | memcpy(priv->ucode_init.v_addr, src, len); |
1502 | src += len; | ||
1489 | } | 1503 | } |
1490 | 1504 | ||
1491 | /* Initialization data (4th block) */ | 1505 | /* Initialization data (4th block) */ |
1492 | if (init_data_size) { | 1506 | if (init_data_size) { |
1493 | src = &ucode->data[inst_size + data_size + init_size]; | 1507 | len = init_data_size; |
1494 | len = priv->ucode_init_data.len; | ||
1495 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", | 1508 | IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", |
1496 | len); | 1509 | len); |
1497 | memcpy(priv->ucode_init_data.v_addr, src, len); | 1510 | memcpy(priv->ucode_init_data.v_addr, src, len); |
1511 | src += len; | ||
1498 | } | 1512 | } |
1499 | 1513 | ||
1500 | /* Bootstrap instructions (5th block) */ | 1514 | /* Bootstrap instructions (5th block) */ |
1501 | src = &ucode->data[inst_size + data_size + init_size + init_data_size]; | 1515 | len = boot_size; |
1502 | len = priv->ucode_boot.len; | ||
1503 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); | 1516 | IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); |
1504 | memcpy(priv->ucode_boot.v_addr, src, len); | 1517 | memcpy(priv->ucode_boot.v_addr, src, len); |
1505 | 1518 | ||
@@ -1773,6 +1786,7 @@ static int __iwl_up(struct iwl_priv *priv) | |||
1773 | { | 1786 | { |
1774 | int i; | 1787 | int i; |
1775 | int ret; | 1788 | int ret; |
1789 | unsigned long status; | ||
1776 | 1790 | ||
1777 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 1791 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
1778 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | 1792 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); |
@@ -1850,6 +1864,51 @@ static int __iwl_up(struct iwl_priv *priv) | |||
1850 | /* start card; "initialize" will load runtime ucode */ | 1864 | /* start card; "initialize" will load runtime ucode */ |
1851 | iwl_nic_start(priv); | 1865 | iwl_nic_start(priv); |
1852 | 1866 | ||
1867 | /* Just finish download Init or Runtime uCode image to device | ||
1868 | * now we wait here for uCode send REPLY_ALIVE notification | ||
1869 | * to indicate uCode is ready. | ||
1870 | * 1) For Init uCode image, all iwlagn devices should wait here | ||
1871 | * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before | ||
1872 | * receive the REPLY_ALIVE notification, go back and try to | ||
1873 | * download the Init uCode image again. | ||
1874 | * 2) For Runtime uCode image, all iwlagn devices except 4965 | ||
1875 | * wait here on STATUS_RT_UCODE_ALIVE status bit; if | ||
1876 | * timeout before receive the REPLY_ALIVE notification, go back | ||
1877 | * and download the Runtime uCode image again. | ||
1878 | * 3) For 4965 Runtime uCode, it will not go through this path, | ||
1879 | * need to wait for STATUS_RT_UCODE_ALIVE status bit in | ||
1880 | * iwl4965_init_alive_start() function; if timeout, need to | ||
1881 | * restart and download Init uCode image. | ||
1882 | */ | ||
1883 | if (priv->ucode_type == UCODE_INIT) | ||
1884 | status = STATUS_INIT_UCODE_ALIVE; | ||
1885 | else | ||
1886 | status = STATUS_RT_UCODE_ALIVE; | ||
1887 | if (test_bit(status, &priv->status)) { | ||
1888 | IWL_WARN(priv, | ||
1889 | "%s uCode already alive? " | ||
1890 | "Waiting for alive anyway\n", | ||
1891 | (status == STATUS_INIT_UCODE_ALIVE) | ||
1892 | ? "INIT" : "Runtime"); | ||
1893 | clear_bit(status, &priv->status); | ||
1894 | } | ||
1895 | ret = wait_event_interruptible_timeout( | ||
1896 | priv->wait_command_queue, | ||
1897 | test_bit(status, &priv->status), | ||
1898 | UCODE_ALIVE_TIMEOUT); | ||
1899 | if (!ret) { | ||
1900 | if (!test_bit(status, &priv->status)) { | ||
1901 | priv->ucode_type = | ||
1902 | (status == STATUS_INIT_UCODE_ALIVE) | ||
1903 | ? UCODE_NONE : UCODE_INIT; | ||
1904 | IWL_ERR(priv, | ||
1905 | "%s timeout after %dms\n", | ||
1906 | (status == STATUS_INIT_UCODE_ALIVE) | ||
1907 | ? "INIT" : "Runtime", | ||
1908 | jiffies_to_msecs(UCODE_ALIVE_TIMEOUT)); | ||
1909 | continue; | ||
1910 | } | ||
1911 | } | ||
1853 | IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); | 1912 | IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); |
1854 | 1913 | ||
1855 | return 0; | 1914 | return 0; |
@@ -2397,14 +2456,16 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, | |||
2397 | * used for controlling the debug level. | 2456 | * used for controlling the debug level. |
2398 | * | 2457 | * |
2399 | * See the level definitions in iwl for details. | 2458 | * See the level definitions in iwl for details. |
2459 | * | ||
2460 | * FIXME This file can be deprecated as the module parameter is | ||
2461 | * writable and users can thus also change the debug level | ||
2462 | * using the /sys/module/iwl3945/parameters/debug file. | ||
2400 | */ | 2463 | */ |
2401 | 2464 | ||
2402 | static ssize_t show_debug_level(struct device *d, | 2465 | static ssize_t show_debug_level(struct device *d, |
2403 | struct device_attribute *attr, char *buf) | 2466 | struct device_attribute *attr, char *buf) |
2404 | { | 2467 | { |
2405 | struct iwl_priv *priv = dev_get_drvdata(d); | 2468 | return sprintf(buf, "0x%08X\n", iwl_debug_level); |
2406 | |||
2407 | return sprintf(buf, "0x%08X\n", priv->debug_level); | ||
2408 | } | 2469 | } |
2409 | static ssize_t store_debug_level(struct device *d, | 2470 | static ssize_t store_debug_level(struct device *d, |
2410 | struct device_attribute *attr, | 2471 | struct device_attribute *attr, |
@@ -2418,7 +2479,7 @@ static ssize_t store_debug_level(struct device *d, | |||
2418 | if (ret) | 2479 | if (ret) |
2419 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); | 2480 | IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); |
2420 | else | 2481 | else |
2421 | priv->debug_level = val; | 2482 | iwl_debug_level = val; |
2422 | 2483 | ||
2423 | return strnlen(buf, count); | 2484 | return strnlen(buf, count); |
2424 | } | 2485 | } |
@@ -2627,26 +2688,6 @@ static ssize_t show_power_level(struct device *d, | |||
2627 | static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, | 2688 | static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, |
2628 | store_power_level); | 2689 | store_power_level); |
2629 | 2690 | ||
2630 | static ssize_t show_qos(struct device *d, | ||
2631 | struct device_attribute *attr, char *buf) | ||
2632 | { | ||
2633 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
2634 | char *p = buf; | ||
2635 | int q; | ||
2636 | |||
2637 | for (q = 0; q < AC_NUM; q++) { | ||
2638 | p += sprintf(p, "\tcw_min\tcw_max\taifsn\ttxop\n"); | ||
2639 | p += sprintf(p, "AC[%d]\t%u\t%u\t%u\t%u\n", q, | ||
2640 | priv->qos_data.def_qos_parm.ac[q].cw_min, | ||
2641 | priv->qos_data.def_qos_parm.ac[q].cw_max, | ||
2642 | priv->qos_data.def_qos_parm.ac[q].aifsn, | ||
2643 | priv->qos_data.def_qos_parm.ac[q].edca_txop); | ||
2644 | } | ||
2645 | |||
2646 | return p - buf + 1; | ||
2647 | } | ||
2648 | |||
2649 | static DEVICE_ATTR(qos, S_IRUGO, show_qos, NULL); | ||
2650 | 2691 | ||
2651 | static ssize_t show_statistics(struct device *d, | 2692 | static ssize_t show_statistics(struct device *d, |
2652 | struct device_attribute *attr, char *buf) | 2693 | struct device_attribute *attr, char *buf) |
@@ -2747,7 +2788,6 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
2747 | &dev_attr_debug_level.attr, | 2788 | &dev_attr_debug_level.attr, |
2748 | #endif | 2789 | #endif |
2749 | &dev_attr_version.attr, | 2790 | &dev_attr_version.attr, |
2750 | &dev_attr_qos.attr, | ||
2751 | NULL | 2791 | NULL |
2752 | }; | 2792 | }; |
2753 | 2793 | ||
@@ -2791,7 +2831,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2791 | /* Disabling hardware scan means that mac80211 will perform scans | 2831 | /* Disabling hardware scan means that mac80211 will perform scans |
2792 | * "the hard way", rather than using device's scan. */ | 2832 | * "the hard way", rather than using device's scan. */ |
2793 | if (cfg->mod_params->disable_hw_scan) { | 2833 | if (cfg->mod_params->disable_hw_scan) { |
2794 | if (cfg->mod_params->debug & IWL_DL_INFO) | 2834 | if (iwl_debug_level & IWL_DL_INFO) |
2795 | dev_printk(KERN_DEBUG, &(pdev->dev), | 2835 | dev_printk(KERN_DEBUG, &(pdev->dev), |
2796 | "Disabling hw_scan\n"); | 2836 | "Disabling hw_scan\n"); |
2797 | iwl_hw_ops.hw_scan = NULL; | 2837 | iwl_hw_ops.hw_scan = NULL; |
@@ -2813,7 +2853,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2813 | priv->inta_mask = CSR_INI_SET_MASK; | 2853 | priv->inta_mask = CSR_INI_SET_MASK; |
2814 | 2854 | ||
2815 | #ifdef CONFIG_IWLWIFI_DEBUG | 2855 | #ifdef CONFIG_IWLWIFI_DEBUG |
2816 | priv->debug_level = priv->cfg->mod_params->debug; | ||
2817 | atomic_set(&priv->restrict_refcnt, 0); | 2856 | atomic_set(&priv->restrict_refcnt, 0); |
2818 | #endif | 2857 | #endif |
2819 | 2858 | ||
@@ -3173,3 +3212,11 @@ static void __exit iwl_exit(void) | |||
3173 | 3212 | ||
3174 | module_exit(iwl_exit); | 3213 | module_exit(iwl_exit); |
3175 | module_init(iwl_init); | 3214 | module_init(iwl_init); |
3215 | |||
3216 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
3217 | module_param_named(debug50, iwl_debug_level, uint, 0444); | ||
3218 | MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); | ||
3219 | module_param_named(debug, iwl_debug_level, uint, 0644); | ||
3220 | MODULE_PARM_DESC(debug, "debug output mask"); | ||
3221 | #endif | ||
3222 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d5cd9a20edca..6aea02644809 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -59,6 +59,9 @@ MODULE_LICENSE("GPL"); | |||
59 | IWL_RATE_##pp##M_INDEX, \ | 59 | IWL_RATE_##pp##M_INDEX, \ |
60 | IWL_RATE_##np##M_INDEX } | 60 | IWL_RATE_##np##M_INDEX } |
61 | 61 | ||
62 | u32 iwl_debug_level; | ||
63 | EXPORT_SYMBOL(iwl_debug_level); | ||
64 | |||
62 | static irqreturn_t iwl_isr(int irq, void *data); | 65 | static irqreturn_t iwl_isr(int irq, void *data); |
63 | 66 | ||
64 | /* | 67 | /* |
@@ -1275,7 +1278,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | |||
1275 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 1278 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
1276 | 1279 | ||
1277 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); | 1280 | IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); |
1278 | iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | 1281 | iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); |
1279 | IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); | 1282 | IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); |
1280 | IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); | 1283 | IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); |
1281 | IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", | 1284 | IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", |
@@ -1290,6 +1293,209 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv) | |||
1290 | } | 1293 | } |
1291 | #endif | 1294 | #endif |
1292 | 1295 | ||
1296 | static const char *desc_lookup_text[] = { | ||
1297 | "OK", | ||
1298 | "FAIL", | ||
1299 | "BAD_PARAM", | ||
1300 | "BAD_CHECKSUM", | ||
1301 | "NMI_INTERRUPT_WDG", | ||
1302 | "SYSASSERT", | ||
1303 | "FATAL_ERROR", | ||
1304 | "BAD_COMMAND", | ||
1305 | "HW_ERROR_TUNE_LOCK", | ||
1306 | "HW_ERROR_TEMPERATURE", | ||
1307 | "ILLEGAL_CHAN_FREQ", | ||
1308 | "VCC_NOT_STABLE", | ||
1309 | "FH_ERROR", | ||
1310 | "NMI_INTERRUPT_HOST", | ||
1311 | "NMI_INTERRUPT_ACTION_PT", | ||
1312 | "NMI_INTERRUPT_UNKNOWN", | ||
1313 | "UCODE_VERSION_MISMATCH", | ||
1314 | "HW_ERROR_ABS_LOCK", | ||
1315 | "HW_ERROR_CAL_LOCK_FAIL", | ||
1316 | "NMI_INTERRUPT_INST_ACTION_PT", | ||
1317 | "NMI_INTERRUPT_DATA_ACTION_PT", | ||
1318 | "NMI_TRM_HW_ER", | ||
1319 | "NMI_INTERRUPT_TRM", | ||
1320 | "NMI_INTERRUPT_BREAK_POINT" | ||
1321 | "DEBUG_0", | ||
1322 | "DEBUG_1", | ||
1323 | "DEBUG_2", | ||
1324 | "DEBUG_3", | ||
1325 | "UNKNOWN" | ||
1326 | }; | ||
1327 | |||
1328 | static const char *desc_lookup(int i) | ||
1329 | { | ||
1330 | int max = ARRAY_SIZE(desc_lookup_text) - 1; | ||
1331 | |||
1332 | if (i < 0 || i > max) | ||
1333 | i = max; | ||
1334 | |||
1335 | return desc_lookup_text[i]; | ||
1336 | } | ||
1337 | |||
1338 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | ||
1339 | #define ERROR_ELEM_SIZE (7 * sizeof(u32)) | ||
1340 | |||
1341 | static void iwl_dump_nic_error_log(struct iwl_priv *priv) | ||
1342 | { | ||
1343 | u32 data2, line; | ||
1344 | u32 desc, time, count, base, data1; | ||
1345 | u32 blink1, blink2, ilink1, ilink2; | ||
1346 | |||
1347 | switch (priv->ucode_type) { | ||
1348 | case UCODE_RT: | ||
1349 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | ||
1350 | break; | ||
1351 | case UCODE_INIT: | ||
1352 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | ||
1353 | break; | ||
1354 | default: | ||
1355 | IWL_ERR(priv, "uCode image not available\n"); | ||
1356 | return; | ||
1357 | } | ||
1358 | |||
1359 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
1360 | IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); | ||
1361 | return; | ||
1362 | } | ||
1363 | |||
1364 | count = iwl_read_targ_mem(priv, base); | ||
1365 | |||
1366 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | ||
1367 | IWL_ERR(priv, "Start IWL Error Log Dump:\n"); | ||
1368 | IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", | ||
1369 | priv->status, count); | ||
1370 | } | ||
1371 | |||
1372 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | ||
1373 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | ||
1374 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | ||
1375 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); | ||
1376 | ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); | ||
1377 | data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); | ||
1378 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); | ||
1379 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | ||
1380 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | ||
1381 | |||
1382 | IWL_ERR(priv, "Desc Time " | ||
1383 | "data1 data2 line\n"); | ||
1384 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | ||
1385 | desc_lookup(desc), desc, time, data1, data2, line); | ||
1386 | IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); | ||
1387 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, | ||
1388 | ilink1, ilink2); | ||
1389 | |||
1390 | } | ||
1391 | |||
1392 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | ||
1393 | |||
1394 | /** | ||
1395 | * iwl_print_event_log - Dump error event log to syslog | ||
1396 | * | ||
1397 | */ | ||
1398 | static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | ||
1399 | u32 num_events, u32 mode) | ||
1400 | { | ||
1401 | u32 i; | ||
1402 | u32 base; /* SRAM byte address of event log header */ | ||
1403 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | ||
1404 | u32 ptr; /* SRAM byte address of log data */ | ||
1405 | u32 ev, time, data; /* event log data */ | ||
1406 | |||
1407 | if (num_events == 0) | ||
1408 | return; | ||
1409 | switch (priv->ucode_type) { | ||
1410 | case UCODE_RT: | ||
1411 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
1412 | break; | ||
1413 | case UCODE_INIT: | ||
1414 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | ||
1415 | break; | ||
1416 | default: | ||
1417 | IWL_ERR(priv, "uCode image not available\n"); | ||
1418 | return; | ||
1419 | } | ||
1420 | |||
1421 | if (mode == 0) | ||
1422 | event_size = 2 * sizeof(u32); | ||
1423 | else | ||
1424 | event_size = 3 * sizeof(u32); | ||
1425 | |||
1426 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | ||
1427 | |||
1428 | /* "time" is actually "data" for mode 0 (no timestamp). | ||
1429 | * place event id # at far right for easier visual parsing. */ | ||
1430 | for (i = 0; i < num_events; i++) { | ||
1431 | ev = iwl_read_targ_mem(priv, ptr); | ||
1432 | ptr += sizeof(u32); | ||
1433 | time = iwl_read_targ_mem(priv, ptr); | ||
1434 | ptr += sizeof(u32); | ||
1435 | if (mode == 0) { | ||
1436 | /* data, ev */ | ||
1437 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | ||
1438 | } else { | ||
1439 | data = iwl_read_targ_mem(priv, ptr); | ||
1440 | ptr += sizeof(u32); | ||
1441 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1442 | time, data, ev); | ||
1443 | } | ||
1444 | } | ||
1445 | } | ||
1446 | |||
1447 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | ||
1448 | { | ||
1449 | u32 base; /* SRAM byte address of event log header */ | ||
1450 | u32 capacity; /* event log capacity in # entries */ | ||
1451 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
1452 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
1453 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
1454 | u32 size; /* # entries that we'll print */ | ||
1455 | |||
1456 | switch (priv->ucode_type) { | ||
1457 | case UCODE_RT: | ||
1458 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
1459 | break; | ||
1460 | case UCODE_INIT: | ||
1461 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | ||
1462 | break; | ||
1463 | default: | ||
1464 | IWL_ERR(priv, "uCode image not available\n"); | ||
1465 | return; | ||
1466 | } | ||
1467 | |||
1468 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
1469 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | ||
1470 | return; | ||
1471 | } | ||
1472 | |||
1473 | /* event log header */ | ||
1474 | capacity = iwl_read_targ_mem(priv, base); | ||
1475 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
1476 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
1477 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
1478 | |||
1479 | size = num_wraps ? capacity : next_entry; | ||
1480 | |||
1481 | /* bail out if nothing in log */ | ||
1482 | if (size == 0) { | ||
1483 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | ||
1484 | return; | ||
1485 | } | ||
1486 | |||
1487 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | ||
1488 | size, num_wraps); | ||
1489 | |||
1490 | /* if uCode has wrapped back to top of log, start at the oldest entry, | ||
1491 | * i.e the next one that uCode would fill. */ | ||
1492 | if (num_wraps) | ||
1493 | iwl_print_event_log(priv, next_entry, | ||
1494 | capacity - next_entry, mode); | ||
1495 | /* (then/else) start at top of log */ | ||
1496 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
1497 | |||
1498 | } | ||
1293 | /** | 1499 | /** |
1294 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 1500 | * iwl_irq_handle_error - called for HW or SW error interrupt from card |
1295 | */ | 1501 | */ |
@@ -1302,7 +1508,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1302 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1508 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1303 | 1509 | ||
1304 | #ifdef CONFIG_IWLWIFI_DEBUG | 1510 | #ifdef CONFIG_IWLWIFI_DEBUG |
1305 | if (priv->debug_level & IWL_DL_FW_ERRORS) { | 1511 | if (iwl_debug_level & IWL_DL_FW_ERRORS) { |
1306 | iwl_dump_nic_error_log(priv); | 1512 | iwl_dump_nic_error_log(priv); |
1307 | iwl_dump_nic_event_log(priv); | 1513 | iwl_dump_nic_event_log(priv); |
1308 | iwl_print_rx_config_cmd(priv); | 1514 | iwl_print_rx_config_cmd(priv); |
@@ -1543,31 +1749,6 @@ void iwl_uninit_drv(struct iwl_priv *priv) | |||
1543 | } | 1749 | } |
1544 | EXPORT_SYMBOL(iwl_uninit_drv); | 1750 | EXPORT_SYMBOL(iwl_uninit_drv); |
1545 | 1751 | ||
1546 | |||
1547 | void iwl_disable_interrupts(struct iwl_priv *priv) | ||
1548 | { | ||
1549 | clear_bit(STATUS_INT_ENABLED, &priv->status); | ||
1550 | |||
1551 | /* disable interrupts from uCode/NIC to host */ | ||
1552 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
1553 | |||
1554 | /* acknowledge/clear/reset any interrupts still pending | ||
1555 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
1556 | iwl_write32(priv, CSR_INT, 0xffffffff); | ||
1557 | iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); | ||
1558 | IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); | ||
1559 | } | ||
1560 | EXPORT_SYMBOL(iwl_disable_interrupts); | ||
1561 | |||
1562 | void iwl_enable_interrupts(struct iwl_priv *priv) | ||
1563 | { | ||
1564 | IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); | ||
1565 | set_bit(STATUS_INT_ENABLED, &priv->status); | ||
1566 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); | ||
1567 | } | ||
1568 | EXPORT_SYMBOL(iwl_enable_interrupts); | ||
1569 | |||
1570 | |||
1571 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) | 1752 | #define ICT_COUNT (PAGE_SIZE/sizeof(u32)) |
1572 | 1753 | ||
1573 | /* Free dram table */ | 1754 | /* Free dram table */ |
@@ -1801,7 +1982,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
1801 | } | 1982 | } |
1802 | 1983 | ||
1803 | #ifdef CONFIG_IWLWIFI_DEBUG | 1984 | #ifdef CONFIG_IWLWIFI_DEBUG |
1804 | if (priv->debug_level & (IWL_DL_ISR)) { | 1985 | if (iwl_debug_level & (IWL_DL_ISR)) { |
1805 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | 1986 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); |
1806 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " | 1987 | IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " |
1807 | "fh 0x%08x\n", inta, inta_mask, inta_fh); | 1988 | "fh 0x%08x\n", inta, inta_mask, inta_fh); |
@@ -2040,191 +2221,6 @@ int iwl_verify_ucode(struct iwl_priv *priv) | |||
2040 | EXPORT_SYMBOL(iwl_verify_ucode); | 2221 | EXPORT_SYMBOL(iwl_verify_ucode); |
2041 | 2222 | ||
2042 | 2223 | ||
2043 | static const char *desc_lookup_text[] = { | ||
2044 | "OK", | ||
2045 | "FAIL", | ||
2046 | "BAD_PARAM", | ||
2047 | "BAD_CHECKSUM", | ||
2048 | "NMI_INTERRUPT_WDG", | ||
2049 | "SYSASSERT", | ||
2050 | "FATAL_ERROR", | ||
2051 | "BAD_COMMAND", | ||
2052 | "HW_ERROR_TUNE_LOCK", | ||
2053 | "HW_ERROR_TEMPERATURE", | ||
2054 | "ILLEGAL_CHAN_FREQ", | ||
2055 | "VCC_NOT_STABLE", | ||
2056 | "FH_ERROR", | ||
2057 | "NMI_INTERRUPT_HOST", | ||
2058 | "NMI_INTERRUPT_ACTION_PT", | ||
2059 | "NMI_INTERRUPT_UNKNOWN", | ||
2060 | "UCODE_VERSION_MISMATCH", | ||
2061 | "HW_ERROR_ABS_LOCK", | ||
2062 | "HW_ERROR_CAL_LOCK_FAIL", | ||
2063 | "NMI_INTERRUPT_INST_ACTION_PT", | ||
2064 | "NMI_INTERRUPT_DATA_ACTION_PT", | ||
2065 | "NMI_TRM_HW_ER", | ||
2066 | "NMI_INTERRUPT_TRM", | ||
2067 | "NMI_INTERRUPT_BREAK_POINT" | ||
2068 | "DEBUG_0", | ||
2069 | "DEBUG_1", | ||
2070 | "DEBUG_2", | ||
2071 | "DEBUG_3", | ||
2072 | "UNKNOWN" | ||
2073 | }; | ||
2074 | |||
2075 | static const char *desc_lookup(int i) | ||
2076 | { | ||
2077 | int max = ARRAY_SIZE(desc_lookup_text) - 1; | ||
2078 | |||
2079 | if (i < 0 || i > max) | ||
2080 | i = max; | ||
2081 | |||
2082 | return desc_lookup_text[i]; | ||
2083 | } | ||
2084 | |||
2085 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | ||
2086 | #define ERROR_ELEM_SIZE (7 * sizeof(u32)) | ||
2087 | |||
2088 | void iwl_dump_nic_error_log(struct iwl_priv *priv) | ||
2089 | { | ||
2090 | u32 data2, line; | ||
2091 | u32 desc, time, count, base, data1; | ||
2092 | u32 blink1, blink2, ilink1, ilink2; | ||
2093 | |||
2094 | if (priv->ucode_type == UCODE_INIT) | ||
2095 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | ||
2096 | else | ||
2097 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | ||
2098 | |||
2099 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
2100 | IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); | ||
2101 | return; | ||
2102 | } | ||
2103 | |||
2104 | count = iwl_read_targ_mem(priv, base); | ||
2105 | |||
2106 | if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { | ||
2107 | IWL_ERR(priv, "Start IWL Error Log Dump:\n"); | ||
2108 | IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", | ||
2109 | priv->status, count); | ||
2110 | } | ||
2111 | |||
2112 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | ||
2113 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | ||
2114 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | ||
2115 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); | ||
2116 | ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); | ||
2117 | data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); | ||
2118 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); | ||
2119 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | ||
2120 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | ||
2121 | |||
2122 | IWL_ERR(priv, "Desc Time " | ||
2123 | "data1 data2 line\n"); | ||
2124 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | ||
2125 | desc_lookup(desc), desc, time, data1, data2, line); | ||
2126 | IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); | ||
2127 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, | ||
2128 | ilink1, ilink2); | ||
2129 | |||
2130 | } | ||
2131 | EXPORT_SYMBOL(iwl_dump_nic_error_log); | ||
2132 | |||
2133 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | ||
2134 | |||
2135 | /** | ||
2136 | * iwl_print_event_log - Dump error event log to syslog | ||
2137 | * | ||
2138 | */ | ||
2139 | static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | ||
2140 | u32 num_events, u32 mode) | ||
2141 | { | ||
2142 | u32 i; | ||
2143 | u32 base; /* SRAM byte address of event log header */ | ||
2144 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | ||
2145 | u32 ptr; /* SRAM byte address of log data */ | ||
2146 | u32 ev, time, data; /* event log data */ | ||
2147 | |||
2148 | if (num_events == 0) | ||
2149 | return; | ||
2150 | if (priv->ucode_type == UCODE_INIT) | ||
2151 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | ||
2152 | else | ||
2153 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
2154 | |||
2155 | if (mode == 0) | ||
2156 | event_size = 2 * sizeof(u32); | ||
2157 | else | ||
2158 | event_size = 3 * sizeof(u32); | ||
2159 | |||
2160 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | ||
2161 | |||
2162 | /* "time" is actually "data" for mode 0 (no timestamp). | ||
2163 | * place event id # at far right for easier visual parsing. */ | ||
2164 | for (i = 0; i < num_events; i++) { | ||
2165 | ev = iwl_read_targ_mem(priv, ptr); | ||
2166 | ptr += sizeof(u32); | ||
2167 | time = iwl_read_targ_mem(priv, ptr); | ||
2168 | ptr += sizeof(u32); | ||
2169 | if (mode == 0) { | ||
2170 | /* data, ev */ | ||
2171 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | ||
2172 | } else { | ||
2173 | data = iwl_read_targ_mem(priv, ptr); | ||
2174 | ptr += sizeof(u32); | ||
2175 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
2176 | time, data, ev); | ||
2177 | } | ||
2178 | } | ||
2179 | } | ||
2180 | |||
2181 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | ||
2182 | { | ||
2183 | u32 base; /* SRAM byte address of event log header */ | ||
2184 | u32 capacity; /* event log capacity in # entries */ | ||
2185 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
2186 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
2187 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
2188 | u32 size; /* # entries that we'll print */ | ||
2189 | |||
2190 | if (priv->ucode_type == UCODE_INIT) | ||
2191 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | ||
2192 | else | ||
2193 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
2194 | |||
2195 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
2196 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | ||
2197 | return; | ||
2198 | } | ||
2199 | |||
2200 | /* event log header */ | ||
2201 | capacity = iwl_read_targ_mem(priv, base); | ||
2202 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
2203 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
2204 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
2205 | |||
2206 | size = num_wraps ? capacity : next_entry; | ||
2207 | |||
2208 | /* bail out if nothing in log */ | ||
2209 | if (size == 0) { | ||
2210 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | ||
2211 | return; | ||
2212 | } | ||
2213 | |||
2214 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | ||
2215 | size, num_wraps); | ||
2216 | |||
2217 | /* if uCode has wrapped back to top of log, start at the oldest entry, | ||
2218 | * i.e the next one that uCode would fill. */ | ||
2219 | if (num_wraps) | ||
2220 | iwl_print_event_log(priv, next_entry, | ||
2221 | capacity - next_entry, mode); | ||
2222 | /* (then/else) start at top of log */ | ||
2223 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
2224 | |||
2225 | } | ||
2226 | EXPORT_SYMBOL(iwl_dump_nic_event_log); | ||
2227 | |||
2228 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | 2224 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) |
2229 | { | 2225 | { |
2230 | struct iwl_ct_kill_config cmd; | 2226 | struct iwl_ct_kill_config cmd; |
@@ -2293,7 +2289,7 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
2293 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 2289 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
2294 | "notification for %s:\n", | 2290 | "notification for %s:\n", |
2295 | le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); | 2291 | le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); |
2296 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); | 2292 | iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); |
2297 | } | 2293 | } |
2298 | EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); | 2294 | EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); |
2299 | 2295 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a658410e66a4..614ec7cc5b31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -116,6 +116,17 @@ struct iwl_temp_ops { | |||
116 | void (*set_ct_kill)(struct iwl_priv *priv); | 116 | void (*set_ct_kill)(struct iwl_priv *priv); |
117 | }; | 117 | }; |
118 | 118 | ||
119 | struct iwl_ucode_ops { | ||
120 | u32 (*get_header_size)(u32); | ||
121 | u32 (*get_build)(const struct iwl_ucode_header *, u32); | ||
122 | u32 (*get_inst_size)(const struct iwl_ucode_header *, u32); | ||
123 | u32 (*get_data_size)(const struct iwl_ucode_header *, u32); | ||
124 | u32 (*get_init_size)(const struct iwl_ucode_header *, u32); | ||
125 | u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32); | ||
126 | u32 (*get_boot_size)(const struct iwl_ucode_header *, u32); | ||
127 | u8 * (*get_data)(const struct iwl_ucode_header *, u32); | ||
128 | }; | ||
129 | |||
119 | struct iwl_lib_ops { | 130 | struct iwl_lib_ops { |
120 | /* set hw dependent parameters */ | 131 | /* set hw dependent parameters */ |
121 | int (*set_hw_params)(struct iwl_priv *priv); | 132 | int (*set_hw_params)(struct iwl_priv *priv); |
@@ -171,6 +182,7 @@ struct iwl_lib_ops { | |||
171 | }; | 182 | }; |
172 | 183 | ||
173 | struct iwl_ops { | 184 | struct iwl_ops { |
185 | const struct iwl_ucode_ops *ucode; | ||
174 | const struct iwl_lib_ops *lib; | 186 | const struct iwl_lib_ops *lib; |
175 | const struct iwl_hcmd_ops *hcmd; | 187 | const struct iwl_hcmd_ops *hcmd; |
176 | const struct iwl_hcmd_utils_ops *utils; | 188 | const struct iwl_hcmd_utils_ops *utils; |
@@ -178,7 +190,6 @@ struct iwl_ops { | |||
178 | 190 | ||
179 | struct iwl_mod_params { | 191 | struct iwl_mod_params { |
180 | int sw_crypto; /* def: 0 = using hardware encryption */ | 192 | int sw_crypto; /* def: 0 = using hardware encryption */ |
181 | u32 debug; /* def: 0 = minimal debug log messages */ | ||
182 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 193 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
183 | int num_of_queues; /* def: HW dependent */ | 194 | int num_of_queues; /* def: HW dependent */ |
184 | int num_of_ampdu_queues;/* def: HW dependent */ | 195 | int num_of_ampdu_queues;/* def: HW dependent */ |
@@ -447,8 +458,6 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags, | |||
447 | /***************************************************** | 458 | /***************************************************** |
448 | * PCI * | 459 | * PCI * |
449 | *****************************************************/ | 460 | *****************************************************/ |
450 | void iwl_disable_interrupts(struct iwl_priv *priv); | ||
451 | void iwl_enable_interrupts(struct iwl_priv *priv); | ||
452 | irqreturn_t iwl_isr_legacy(int irq, void *data); | 461 | irqreturn_t iwl_isr_legacy(int irq, void *data); |
453 | int iwl_reset_ict(struct iwl_priv *priv); | 462 | int iwl_reset_ict(struct iwl_priv *priv); |
454 | void iwl_disable_ict(struct iwl_priv *priv); | 463 | void iwl_disable_ict(struct iwl_priv *priv); |
@@ -472,7 +481,6 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
472 | /***************************************************** | 481 | /***************************************************** |
473 | * Error Handling Debugging | 482 | * Error Handling Debugging |
474 | ******************************************************/ | 483 | ******************************************************/ |
475 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | ||
476 | void iwl_dump_nic_event_log(struct iwl_priv *priv); | 484 | void iwl_dump_nic_event_log(struct iwl_priv *priv); |
477 | void iwl_clear_isr_stats(struct iwl_priv *priv); | 485 | void iwl_clear_isr_stats(struct iwl_priv *priv); |
478 | 486 | ||
@@ -501,6 +509,8 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
501 | #define STATUS_POWER_PMI 16 | 509 | #define STATUS_POWER_PMI 16 |
502 | #define STATUS_FW_ERROR 17 | 510 | #define STATUS_FW_ERROR 17 |
503 | #define STATUS_MODE_PENDING 18 | 511 | #define STATUS_MODE_PENDING 18 |
512 | #define STATUS_INIT_UCODE_ALIVE 19 | ||
513 | #define STATUS_RT_UCODE_ALIVE 20 | ||
504 | 514 | ||
505 | 515 | ||
506 | static inline int iwl_is_ready(struct iwl_priv *priv) | 516 | static inline int iwl_is_ready(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 65bbce0f1717..9faf0c2ff608 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define __iwl_debug_h__ | 30 | #define __iwl_debug_h__ |
31 | 31 | ||
32 | struct iwl_priv; | 32 | struct iwl_priv; |
33 | extern u32 iwl_debug_level; | ||
33 | 34 | ||
34 | #define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) | 35 | #define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) |
35 | #define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) | 36 | #define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) |
@@ -45,7 +46,7 @@ do { \ | |||
45 | #ifdef CONFIG_IWLWIFI_DEBUG | 46 | #ifdef CONFIG_IWLWIFI_DEBUG |
46 | #define IWL_DEBUG(__priv, level, fmt, args...) \ | 47 | #define IWL_DEBUG(__priv, level, fmt, args...) \ |
47 | do { \ | 48 | do { \ |
48 | if (__priv->debug_level & (level)) \ | 49 | if (iwl_debug_level & (level)) \ |
49 | dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ | 50 | dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ |
50 | "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ | 51 | "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ |
51 | __func__ , ## args); \ | 52 | __func__ , ## args); \ |
@@ -53,15 +54,15 @@ do { \ | |||
53 | 54 | ||
54 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ | 55 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ |
55 | do { \ | 56 | do { \ |
56 | if ((__priv->debug_level & (level)) && net_ratelimit()) \ | 57 | if ((iwl_debug_level & (level)) && net_ratelimit()) \ |
57 | dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ | 58 | dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ |
58 | "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ | 59 | "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ |
59 | __func__ , ## args); \ | 60 | __func__ , ## args); \ |
60 | } while (0) | 61 | } while (0) |
61 | 62 | ||
62 | #define iwl_print_hex_dump(priv, level, p, len) \ | 63 | #define iwl_print_hex_dump(level, p, len) \ |
63 | do { \ | 64 | do { \ |
64 | if (priv->debug_level & level) \ | 65 | if (iwl_debug_level & level) \ |
65 | print_hex_dump(KERN_DEBUG, "iwl data: ", \ | 66 | print_hex_dump(KERN_DEBUG, "iwl data: ", \ |
66 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ | 67 | DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ |
67 | } while (0) | 68 | } while (0) |
@@ -82,6 +83,10 @@ struct iwl_debugfs { | |||
82 | struct dentry *file_channels; | 83 | struct dentry *file_channels; |
83 | struct dentry *file_status; | 84 | struct dentry *file_status; |
84 | struct dentry *file_interrupt; | 85 | struct dentry *file_interrupt; |
86 | struct dentry *file_qos; | ||
87 | #ifdef CONFIG_IWLWIFI_LEDS | ||
88 | struct dentry *file_led; | ||
89 | #endif | ||
85 | } dbgfs_data_files; | 90 | } dbgfs_data_files; |
86 | struct dir_rf_files { | 91 | struct dir_rf_files { |
87 | struct dentry *file_disable_sensitivity; | 92 | struct dentry *file_disable_sensitivity; |
@@ -99,8 +104,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv); | |||
99 | #else | 104 | #else |
100 | #define IWL_DEBUG(__priv, level, fmt, args...) | 105 | #define IWL_DEBUG(__priv, level, fmt, args...) |
101 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) | 106 | #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) |
102 | static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, | 107 | static inline void iwl_print_hex_dump(int level, void *p, u32 len) |
103 | void *p, u32 len) | ||
104 | {} | 108 | {} |
105 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 109 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
106 | 110 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index f32ac74b69ac..0ab3463aa07e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -49,7 +49,8 @@ | |||
49 | 49 | ||
50 | #define DEBUGFS_ADD_FILE(name, parent) do { \ | 50 | #define DEBUGFS_ADD_FILE(name, parent) do { \ |
51 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 51 | dbgfs->dbgfs_##parent##_files.file_##name = \ |
52 | debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \ | 52 | debugfs_create_file(#name, S_IWUSR | S_IRUSR, \ |
53 | dbgfs->dir_##parent, priv, \ | ||
53 | &iwl_dbgfs_##name##_ops); \ | 54 | &iwl_dbgfs_##name##_ops); \ |
54 | if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ | 55 | if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ |
55 | goto err; \ | 56 | goto err; \ |
@@ -57,7 +58,8 @@ | |||
57 | 58 | ||
58 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ | 59 | #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ |
59 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 60 | dbgfs->dbgfs_##parent##_files.file_##name = \ |
60 | debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \ | 61 | debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ |
62 | dbgfs->dir_##parent, ptr); \ | ||
61 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ | 63 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ |
62 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ | 64 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ |
63 | goto err; \ | 65 | goto err; \ |
@@ -65,7 +67,7 @@ | |||
65 | 67 | ||
66 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ | 68 | #define DEBUGFS_ADD_X32(name, parent, ptr) do { \ |
67 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 69 | dbgfs->dbgfs_##parent##_files.file_##name = \ |
68 | debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \ | 70 | debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \ |
69 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ | 71 | if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ |
70 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ | 72 | || !dbgfs->dbgfs_##parent##_files.file_##name) \ |
71 | goto err; \ | 73 | goto err; \ |
@@ -566,6 +568,55 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, | |||
566 | return count; | 568 | return count; |
567 | } | 569 | } |
568 | 570 | ||
571 | static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | ||
572 | size_t count, loff_t *ppos) | ||
573 | { | ||
574 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
575 | int pos = 0, i; | ||
576 | char buf[256]; | ||
577 | const size_t bufsz = sizeof(buf); | ||
578 | ssize_t ret; | ||
579 | |||
580 | for (i = 0; i < AC_NUM; i++) { | ||
581 | pos += scnprintf(buf + pos, bufsz - pos, | ||
582 | "\tcw_min\tcw_max\taifsn\ttxop\n"); | ||
583 | pos += scnprintf(buf + pos, bufsz - pos, | ||
584 | "AC[%d]\t%u\t%u\t%u\t%u\n", i, | ||
585 | priv->qos_data.def_qos_parm.ac[i].cw_min, | ||
586 | priv->qos_data.def_qos_parm.ac[i].cw_max, | ||
587 | priv->qos_data.def_qos_parm.ac[i].aifsn, | ||
588 | priv->qos_data.def_qos_parm.ac[i].edca_txop); | ||
589 | } | ||
590 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
591 | return ret; | ||
592 | } | ||
593 | |||
594 | #ifdef CONFIG_IWLWIFI_LEDS | ||
595 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | ||
596 | size_t count, loff_t *ppos) | ||
597 | { | ||
598 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
599 | int pos = 0; | ||
600 | char buf[256]; | ||
601 | const size_t bufsz = sizeof(buf); | ||
602 | ssize_t ret; | ||
603 | |||
604 | pos += scnprintf(buf + pos, bufsz - pos, | ||
605 | "allow blinking: %s\n", | ||
606 | (priv->allow_blinking) ? "True" : "False"); | ||
607 | if (priv->allow_blinking) { | ||
608 | pos += scnprintf(buf + pos, bufsz - pos, | ||
609 | "Led blinking rate: %u\n", | ||
610 | priv->last_blink_rate); | ||
611 | pos += scnprintf(buf + pos, bufsz - pos, | ||
612 | "Last blink time: %lu\n", | ||
613 | priv->last_blink_time); | ||
614 | } | ||
615 | |||
616 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
617 | return ret; | ||
618 | } | ||
619 | #endif | ||
569 | 620 | ||
570 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 621 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
571 | DEBUGFS_WRITE_FILE_OPS(log_event); | 622 | DEBUGFS_WRITE_FILE_OPS(log_event); |
@@ -576,6 +627,10 @@ DEBUGFS_READ_FILE_OPS(tx_statistics); | |||
576 | DEBUGFS_READ_FILE_OPS(channels); | 627 | DEBUGFS_READ_FILE_OPS(channels); |
577 | DEBUGFS_READ_FILE_OPS(status); | 628 | DEBUGFS_READ_FILE_OPS(status); |
578 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 629 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
630 | DEBUGFS_READ_FILE_OPS(qos); | ||
631 | #ifdef CONFIG_IWLWIFI_LEDS | ||
632 | DEBUGFS_READ_FILE_OPS(led); | ||
633 | #endif | ||
579 | 634 | ||
580 | /* | 635 | /* |
581 | * Create the debugfs files and directories | 636 | * Create the debugfs files and directories |
@@ -612,6 +667,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
612 | DEBUGFS_ADD_FILE(channels, data); | 667 | DEBUGFS_ADD_FILE(channels, data); |
613 | DEBUGFS_ADD_FILE(status, data); | 668 | DEBUGFS_ADD_FILE(status, data); |
614 | DEBUGFS_ADD_FILE(interrupt, data); | 669 | DEBUGFS_ADD_FILE(interrupt, data); |
670 | DEBUGFS_ADD_FILE(qos, data); | ||
671 | #ifdef CONFIG_IWLWIFI_LEDS | ||
672 | DEBUGFS_ADD_FILE(led, data); | ||
673 | #endif | ||
615 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 674 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); |
616 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 675 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, |
617 | &priv->disable_chain_noise_cal); | 676 | &priv->disable_chain_noise_cal); |
@@ -646,6 +705,10 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
646 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); | 705 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); |
647 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); | 706 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); |
648 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); | 707 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); |
708 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); | ||
709 | #ifdef CONFIG_IWLWIFI_LEDS | ||
710 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); | ||
711 | #endif | ||
649 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | 712 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); |
650 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | 713 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); |
651 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); | 714 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1a2fe37d4735..0751891f4ab7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -66,6 +66,7 @@ extern struct iwl_cfg iwl1000_bgn_cfg; | |||
66 | /* shared structures from iwl-5000.c */ | 66 | /* shared structures from iwl-5000.c */ |
67 | extern struct iwl_mod_params iwl50_mod_params; | 67 | extern struct iwl_mod_params iwl50_mod_params; |
68 | extern struct iwl_ops iwl5000_ops; | 68 | extern struct iwl_ops iwl5000_ops; |
69 | extern struct iwl_ucode_ops iwl5000_ucode; | ||
69 | extern struct iwl_lib_ops iwl5000_lib; | 70 | extern struct iwl_lib_ops iwl5000_lib; |
70 | extern struct iwl_hcmd_ops iwl5000_hcmd; | 71 | extern struct iwl_hcmd_ops iwl5000_hcmd; |
71 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; | 72 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; |
@@ -258,8 +259,10 @@ struct iwl_channel_info { | |||
258 | #define IWL_TX_FIFO_HCCA_2 6 | 259 | #define IWL_TX_FIFO_HCCA_2 6 |
259 | #define IWL_TX_FIFO_NONE 7 | 260 | #define IWL_TX_FIFO_NONE 7 |
260 | 261 | ||
261 | /* Minimum number of queues. MAX_NUM is defined in hw specific files */ | 262 | /* Minimum number of queues. MAX_NUM is defined in hw specific files. |
262 | #define IWL_MIN_NUM_QUEUES 4 | 263 | * Set the minimum to accommodate the 4 standard TX queues, 1 command |
264 | * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ | ||
265 | #define IWL_MIN_NUM_QUEUES 10 | ||
263 | 266 | ||
264 | /* Power management (not Tx power) structures */ | 267 | /* Power management (not Tx power) structures */ |
265 | 268 | ||
@@ -523,15 +526,29 @@ struct fw_desc { | |||
523 | }; | 526 | }; |
524 | 527 | ||
525 | /* uCode file layout */ | 528 | /* uCode file layout */ |
526 | struct iwl_ucode { | 529 | struct iwl_ucode_header { |
527 | __le32 ver; /* major/minor/API/serial */ | 530 | __le32 ver; /* major/minor/API/serial */ |
528 | __le32 inst_size; /* bytes of runtime instructions */ | 531 | union { |
529 | __le32 data_size; /* bytes of runtime data */ | 532 | struct { |
530 | __le32 init_size; /* bytes of initialization instructions */ | 533 | __le32 inst_size; /* bytes of runtime code */ |
531 | __le32 init_data_size; /* bytes of initialization data */ | 534 | __le32 data_size; /* bytes of runtime data */ |
532 | __le32 boot_size; /* bytes of bootstrap instructions */ | 535 | __le32 init_size; /* bytes of init code */ |
533 | u8 data[0]; /* data in same order as "size" elements */ | 536 | __le32 init_data_size; /* bytes of init data */ |
537 | __le32 boot_size; /* bytes of bootstrap code */ | ||
538 | u8 data[0]; /* in same order as sizes */ | ||
539 | } v1; | ||
540 | struct { | ||
541 | __le32 build; /* build number */ | ||
542 | __le32 inst_size; /* bytes of runtime code */ | ||
543 | __le32 data_size; /* bytes of runtime data */ | ||
544 | __le32 init_size; /* bytes of init code */ | ||
545 | __le32 init_data_size; /* bytes of init data */ | ||
546 | __le32 boot_size; /* bytes of bootstrap code */ | ||
547 | u8 data[0]; /* in same order as sizes */ | ||
548 | } v2; | ||
549 | } u; | ||
534 | }; | 550 | }; |
551 | #define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28) | ||
535 | 552 | ||
536 | struct iwl4965_ibss_seq { | 553 | struct iwl4965_ibss_seq { |
537 | u8 mac[ETH_ALEN]; | 554 | u8 mac[ETH_ALEN]; |
@@ -755,6 +772,8 @@ struct iwl_calib_result { | |||
755 | size_t buf_len; | 772 | size_t buf_len; |
756 | }; | 773 | }; |
757 | 774 | ||
775 | #define UCODE_ALIVE_TIMEOUT (5 * HZ) | ||
776 | |||
758 | enum ucode_type { | 777 | enum ucode_type { |
759 | UCODE_NONE = 0, | 778 | UCODE_NONE = 0, |
760 | UCODE_INIT, | 779 | UCODE_INIT, |
@@ -1092,7 +1111,6 @@ struct iwl_priv { | |||
1092 | 1111 | ||
1093 | #ifdef CONFIG_IWLWIFI_DEBUG | 1112 | #ifdef CONFIG_IWLWIFI_DEBUG |
1094 | /* debugging info */ | 1113 | /* debugging info */ |
1095 | u32 debug_level; | ||
1096 | u32 framecnt_to_us; | 1114 | u32 framecnt_to_us; |
1097 | atomic_t restrict_refcnt; | 1115 | atomic_t restrict_refcnt; |
1098 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1116 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 7d7554a2f341..51eed7226669 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -159,6 +159,9 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) | |||
159 | 159 | ||
160 | /* OTP only valid for CP/PP and after */ | 160 | /* OTP only valid for CP/PP and after */ |
161 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 161 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { |
162 | case CSR_HW_REV_TYPE_NONE: | ||
163 | IWL_ERR(priv, "Unknown hardware type\n"); | ||
164 | return -ENOENT; | ||
162 | case CSR_HW_REV_TYPE_3945: | 165 | case CSR_HW_REV_TYPE_3945: |
163 | case CSR_HW_REV_TYPE_4965: | 166 | case CSR_HW_REV_TYPE_4965: |
164 | case CSR_HW_REV_TYPE_5300: | 167 | case CSR_HW_REV_TYPE_5300: |
@@ -266,7 +269,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
266 | u32 otpgp; | 269 | u32 otpgp; |
267 | 270 | ||
268 | priv->nvm_device_type = iwlcore_get_nvm_type(priv); | 271 | priv->nvm_device_type = iwlcore_get_nvm_type(priv); |
269 | 272 | if (priv->nvm_device_type == -ENOENT) | |
273 | return -ENOENT; | ||
270 | /* allocate eeprom */ | 274 | /* allocate eeprom */ |
271 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 275 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
272 | priv->cfg->eeprom_size = | 276 | priv->cfg->eeprom_size = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index a1328c3c81ae..bd0b12efb5c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -145,4 +145,25 @@ static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) | |||
145 | #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue | 145 | #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue |
146 | #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue | 146 | #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue |
147 | 147 | ||
148 | static inline void iwl_disable_interrupts(struct iwl_priv *priv) | ||
149 | { | ||
150 | clear_bit(STATUS_INT_ENABLED, &priv->status); | ||
151 | |||
152 | /* disable interrupts from uCode/NIC to host */ | ||
153 | iwl_write32(priv, CSR_INT_MASK, 0x00000000); | ||
154 | |||
155 | /* acknowledge/clear/reset any interrupts still pending | ||
156 | * from uCode or flow handler (Rx/Tx DMA) */ | ||
157 | iwl_write32(priv, CSR_INT, 0xffffffff); | ||
158 | iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); | ||
159 | IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); | ||
160 | } | ||
161 | |||
162 | static inline void iwl_enable_interrupts(struct iwl_priv *priv) | ||
163 | { | ||
164 | IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); | ||
165 | set_bit(STATUS_INT_ENABLED, &priv->status); | ||
166 | iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); | ||
167 | } | ||
168 | |||
148 | #endif /* __iwl_helpers_h__ */ | 169 | #endif /* __iwl_helpers_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 5e64252f80f6..8c8115293b3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -54,7 +54,7 @@ static const char *led_type_str[] = { | |||
54 | 54 | ||
55 | 55 | ||
56 | static const struct { | 56 | static const struct { |
57 | u16 tpt; | 57 | u16 tpt; /* Mb/s */ |
58 | u8 on_time; | 58 | u8 on_time; |
59 | u8 off_time; | 59 | u8 off_time; |
60 | } blink_tbl[] = | 60 | } blink_tbl[] = |
@@ -104,7 +104,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | /* Set led pattern command */ | 106 | /* Set led pattern command */ |
107 | static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, | 107 | static int iwl_led_pattern(struct iwl_priv *priv, int led_id, |
108 | unsigned int idx) | 108 | unsigned int idx) |
109 | { | 109 | { |
110 | struct iwl_led_cmd led_cmd = { | 110 | struct iwl_led_cmd led_cmd = { |
@@ -121,7 +121,7 @@ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, | |||
121 | } | 121 | } |
122 | 122 | ||
123 | /* Set led register off */ | 123 | /* Set led register off */ |
124 | static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) | 124 | static int iwl_led_on_reg(struct iwl_priv *priv, int led_id) |
125 | { | 125 | { |
126 | IWL_DEBUG_LED(priv, "led on %d\n", led_id); | 126 | IWL_DEBUG_LED(priv, "led on %d\n", led_id); |
127 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | 127 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); |
@@ -130,7 +130,7 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) | |||
130 | 130 | ||
131 | #if 0 | 131 | #if 0 |
132 | /* Set led on command */ | 132 | /* Set led on command */ |
133 | static int iwl4965_led_on(struct iwl_priv *priv, int led_id) | 133 | static int iwl_led_on(struct iwl_priv *priv, int led_id) |
134 | { | 134 | { |
135 | struct iwl_led_cmd led_cmd = { | 135 | struct iwl_led_cmd led_cmd = { |
136 | .id = led_id, | 136 | .id = led_id, |
@@ -142,7 +142,7 @@ static int iwl4965_led_on(struct iwl_priv *priv, int led_id) | |||
142 | } | 142 | } |
143 | 143 | ||
144 | /* Set led off command */ | 144 | /* Set led off command */ |
145 | int iwl4965_led_off(struct iwl_priv *priv, int led_id) | 145 | int iwl_led_off(struct iwl_priv *priv, int led_id) |
146 | { | 146 | { |
147 | struct iwl_led_cmd led_cmd = { | 147 | struct iwl_led_cmd led_cmd = { |
148 | .id = led_id, | 148 | .id = led_id, |
@@ -157,7 +157,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) | |||
157 | 157 | ||
158 | 158 | ||
159 | /* Set led register off */ | 159 | /* Set led register off */ |
160 | static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) | 160 | static int iwl_led_off_reg(struct iwl_priv *priv, int led_id) |
161 | { | 161 | { |
162 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | 162 | IWL_DEBUG_LED(priv, "LED Reg off\n"); |
163 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | 163 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); |
@@ -171,7 +171,7 @@ static int iwl_led_associate(struct iwl_priv *priv, int led_id) | |||
171 | { | 171 | { |
172 | IWL_DEBUG_LED(priv, "Associated\n"); | 172 | IWL_DEBUG_LED(priv, "Associated\n"); |
173 | priv->allow_blinking = 1; | 173 | priv->allow_blinking = 1; |
174 | return iwl4965_led_on_reg(priv, led_id); | 174 | return iwl_led_on_reg(priv, led_id); |
175 | } | 175 | } |
176 | static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) | 176 | static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) |
177 | { | 177 | { |
@@ -264,13 +264,15 @@ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, | |||
264 | 264 | ||
265 | 265 | ||
266 | /* | 266 | /* |
267 | * calculate blink rate according to last 2 sec Tx/Rx activities | 267 | * calculate blink rate according to last second Tx/Rx activities |
268 | */ | 268 | */ |
269 | static int iwl_get_blink_rate(struct iwl_priv *priv) | 269 | static int iwl_get_blink_rate(struct iwl_priv *priv) |
270 | { | 270 | { |
271 | int i; | 271 | int i; |
272 | u64 current_tpt = priv->tx_stats[2].bytes; | 272 | /* count both tx and rx traffic to be able to |
273 | /* FIXME: + priv->rx_stats[2].bytes; */ | 273 | * handle traffic in either direction |
274 | */ | ||
275 | u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; | ||
274 | s64 tpt = current_tpt - priv->led_tpt; | 276 | s64 tpt = current_tpt - priv->led_tpt; |
275 | 277 | ||
276 | if (tpt < 0) /* wraparound */ | 278 | if (tpt < 0) /* wraparound */ |
@@ -314,7 +316,7 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
314 | priv->last_blink_time = 0; | 316 | priv->last_blink_time = 0; |
315 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | 317 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { |
316 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | 318 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; |
317 | iwl4965_led_pattern(priv, IWL_LED_LINK, | 319 | iwl_led_pattern(priv, IWL_LED_LINK, |
318 | IWL_SOLID_BLINK_IDX); | 320 | IWL_SOLID_BLINK_IDX); |
319 | } | 321 | } |
320 | return; | 322 | return; |
@@ -328,7 +330,7 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
328 | 330 | ||
329 | /* call only if blink rate change */ | 331 | /* call only if blink rate change */ |
330 | if (blink_idx != priv->last_blink_rate) | 332 | if (blink_idx != priv->last_blink_rate) |
331 | iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx); | 333 | iwl_led_pattern(priv, IWL_LED_LINK, blink_idx); |
332 | 334 | ||
333 | priv->last_blink_time = jiffies; | 335 | priv->last_blink_time = jiffies; |
334 | priv->last_blink_rate = blink_idx; | 336 | priv->last_blink_rate = blink_idx; |
@@ -351,8 +353,8 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
351 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | 353 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", |
352 | wiphy_name(priv->hw->wiphy)); | 354 | wiphy_name(priv->hw->wiphy)); |
353 | 355 | ||
354 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; | 356 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg; |
355 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; | 357 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg; |
356 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | 358 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; |
357 | 359 | ||
358 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], | 360 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], |
@@ -386,7 +388,7 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
386 | 388 | ||
387 | priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; | 389 | priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; |
388 | priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; | 390 | priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; |
389 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; | 391 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern; |
390 | 392 | ||
391 | if (ret) | 393 | if (ret) |
392 | goto exit_fail; | 394 | goto exit_fail; |
@@ -401,7 +403,7 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
401 | 403 | ||
402 | priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; | 404 | priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; |
403 | priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; | 405 | priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; |
404 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; | 406 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern; |
405 | 407 | ||
406 | if (ret) | 408 | if (ret) |
407 | goto exit_fail; | 409 | goto exit_fail; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b9cac3fd216..d393e8f02102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -80,6 +80,8 @@ | |||
80 | #define APMG_RFKILL_REG (APMG_BASE + 0x0014) | 80 | #define APMG_RFKILL_REG (APMG_BASE + 0x0014) |
81 | #define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c) | 81 | #define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c) |
82 | #define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020) | 82 | #define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020) |
83 | #define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058) | ||
84 | #define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C) | ||
83 | 85 | ||
84 | #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) | 86 | #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) |
85 | #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) | 87 | #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) |
@@ -91,7 +93,8 @@ | |||
91 | #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) | 93 | #define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) |
92 | #define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ | 94 | #define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ |
93 | #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) | 95 | #define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) |
94 | 96 | #define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ | |
97 | #define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) | ||
95 | 98 | ||
96 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) | 99 | #define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) |
97 | 100 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 66fe365dd08a..5d5f2153f445 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -646,7 +646,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv, | |||
646 | u32 tsf_low; | 646 | u32 tsf_low; |
647 | int rssi; | 647 | int rssi; |
648 | 648 | ||
649 | if (likely(!(priv->debug_level & IWL_DL_RX))) | 649 | if (likely(!(iwl_debug_level & IWL_DL_RX))) |
650 | return; | 650 | return; |
651 | 651 | ||
652 | /* MAC header */ | 652 | /* MAC header */ |
@@ -742,7 +742,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv, | |||
742 | } | 742 | } |
743 | } | 743 | } |
744 | if (print_dump) | 744 | if (print_dump) |
745 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | 745 | iwl_print_hex_dump(IWL_DL_RX, header, length); |
746 | } | 746 | } |
747 | #endif | 747 | #endif |
748 | 748 | ||
@@ -1061,11 +1061,11 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1061 | 1061 | ||
1062 | /* Set "1" to report good data frames in groups of 100 */ | 1062 | /* Set "1" to report good data frames in groups of 100 */ |
1063 | #ifdef CONFIG_IWLWIFI_DEBUG | 1063 | #ifdef CONFIG_IWLWIFI_DEBUG |
1064 | if (unlikely(priv->debug_level & IWL_DL_RX)) | 1064 | if (unlikely(iwl_debug_level & IWL_DL_RX)) |
1065 | iwl_dbg_report_frame(priv, rx_start, len, header, 1); | 1065 | iwl_dbg_report_frame(priv, rx_start, len, header, 1); |
1066 | #endif | 1066 | #endif |
1067 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", | 1067 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", |
1068 | rx_status.signal, rx_status.noise, rx_status.signal, | 1068 | rx_status.signal, rx_status.noise, rx_status.qual, |
1069 | (unsigned long long)rx_status.mactime); | 1069 | (unsigned long long)rx_status.mactime); |
1070 | 1070 | ||
1071 | /* | 1071 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 2addf735b193..cbe4e26d053f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -566,6 +566,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
566 | unsigned long flags; | 566 | unsigned long flags; |
567 | 567 | ||
568 | spin_lock_irqsave(&priv->sta_lock, flags); | 568 | spin_lock_irqsave(&priv->sta_lock, flags); |
569 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | ||
570 | keyconf->keyidx); | ||
569 | 571 | ||
570 | if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) | 572 | if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) |
571 | IWL_ERR(priv, "index %d not used in uCode key table.\n", | 573 | IWL_ERR(priv, "index %d not used in uCode key table.\n", |
@@ -573,6 +575,11 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
573 | 575 | ||
574 | priv->default_wep_key--; | 576 | priv->default_wep_key--; |
575 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | 577 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); |
578 | if (iwl_is_rfkill(priv)) { | ||
579 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); | ||
580 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
581 | return 0; | ||
582 | } | ||
576 | ret = iwl_send_static_wepkey_cmd(priv, 1); | 583 | ret = iwl_send_static_wepkey_cmd(priv, 1); |
577 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", | 584 | IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", |
578 | keyconf->keyidx, ret); | 585 | keyconf->keyidx, ret); |
@@ -853,6 +860,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
853 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | 860 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; |
854 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 861 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
855 | 862 | ||
863 | if (iwl_is_rfkill(priv)) { | ||
864 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); | ||
865 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
866 | return 0; | ||
867 | } | ||
856 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 868 | ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
857 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 869 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
858 | return ret; | 870 | return ret; |
@@ -1044,11 +1056,10 @@ EXPORT_SYMBOL(iwl_rxon_add_station); | |||
1044 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | 1056 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) |
1045 | { | 1057 | { |
1046 | int sta_id; | 1058 | int sta_id; |
1047 | u16 fc = le16_to_cpu(hdr->frame_control); | 1059 | __le16 fc = hdr->frame_control; |
1048 | 1060 | ||
1049 | /* If this frame is broadcast or management, use broadcast station id */ | 1061 | /* If this frame is broadcast or management, use broadcast station id */ |
1050 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || | 1062 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) |
1051 | is_multicast_ether_addr(hdr->addr1)) | ||
1052 | return priv->hw_params.bcast_sta_id; | 1063 | return priv->hw_params.bcast_sta_id; |
1053 | 1064 | ||
1054 | switch (priv->iw_mode) { | 1065 | switch (priv->iw_mode) { |
@@ -1082,7 +1093,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
1082 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " | 1093 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " |
1083 | "Defaulting to broadcast...\n", | 1094 | "Defaulting to broadcast...\n", |
1084 | hdr->addr1); | 1095 | hdr->addr1); |
1085 | iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | 1096 | iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); |
1086 | return priv->hw_params.bcast_sta_id; | 1097 | return priv->hw_params.bcast_sta_id; |
1087 | 1098 | ||
1088 | default: | 1099 | default: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7073069a61a9..0912987af603 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -869,8 +869,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
869 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 869 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", |
870 | le16_to_cpu(out_cmd->hdr.sequence)); | 870 | le16_to_cpu(out_cmd->hdr.sequence)); |
871 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | 871 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); |
872 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | 872 | iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); |
873 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | 873 | iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); |
874 | 874 | ||
875 | /* Set up entry for this TFD in Tx byte-count array */ | 875 | /* Set up entry for this TFD in Tx byte-count array */ |
876 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 876 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
@@ -940,7 +940,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
940 | !(cmd->meta.flags & CMD_SIZE_HUGE)); | 940 | !(cmd->meta.flags & CMD_SIZE_HUGE)); |
941 | 941 | ||
942 | if (iwl_is_rfkill(priv)) { | 942 | if (iwl_is_rfkill(priv)) { |
943 | IWL_DEBUG_INFO(priv, "Not sending command - RF KILL"); | 943 | IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); |
944 | return -EIO; | 944 | return -EIO; |
945 | } | 945 | } |
946 | 946 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7ff95f80b817..2cc7e30d7743 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -89,7 +89,7 @@ MODULE_LICENSE("GPL"); | |||
89 | 89 | ||
90 | /* module parameters */ | 90 | /* module parameters */ |
91 | struct iwl_mod_params iwl3945_mod_params = { | 91 | struct iwl_mod_params iwl3945_mod_params = { |
92 | .num_of_queues = IWL39_MAX_NUM_QUEUES, | 92 | .num_of_queues = IWL39_NUM_QUEUES, /* Not used */ |
93 | .sw_crypto = 1, | 93 | .sw_crypto = 1, |
94 | .restart_fw = 1, | 94 | .restart_fw = 1, |
95 | /* the rest are 0 by default */ | 95 | /* the rest are 0 by default */ |
@@ -612,8 +612,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
612 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 612 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", |
613 | le16_to_cpu(out_cmd->hdr.sequence)); | 613 | le16_to_cpu(out_cmd->hdr.sequence)); |
614 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); | 614 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); |
615 | iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); | 615 | iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx)); |
616 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, | 616 | iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr, |
617 | ieee80211_hdrlen(fc)); | 617 | ieee80211_hdrlen(fc)); |
618 | 618 | ||
619 | /* | 619 | /* |
@@ -926,7 +926,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, | |||
926 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 926 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
927 | unsigned long status = priv->status; | 927 | unsigned long status = priv->status; |
928 | 928 | ||
929 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", | 929 | IWL_WARN(priv, "Card state received: HW:%s SW:%s\n", |
930 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | 930 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", |
931 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); | 931 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); |
932 | 932 | ||
@@ -1644,7 +1644,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1644 | iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); | 1644 | iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); |
1645 | 1645 | ||
1646 | #ifdef CONFIG_IWLWIFI_DEBUG | 1646 | #ifdef CONFIG_IWLWIFI_DEBUG |
1647 | if (priv->debug_level & IWL_DL_ISR) { | 1647 | if (iwl_debug_level & IWL_DL_ISR) { |
1648 | /* just for debug */ | 1648 | /* just for debug */ |
1649 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 1649 | inta_mask = iwl_read32(priv, CSR_INT_MASK); |
1650 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | 1650 | IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", |
@@ -1663,7 +1663,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1663 | 1663 | ||
1664 | /* Now service all interrupt bits discovered above. */ | 1664 | /* Now service all interrupt bits discovered above. */ |
1665 | if (inta & CSR_INT_BIT_HW_ERR) { | 1665 | if (inta & CSR_INT_BIT_HW_ERR) { |
1666 | IWL_ERR(priv, "Microcode HW error detected. Restarting.\n"); | 1666 | IWL_ERR(priv, "Hardware error detected. Restarting.\n"); |
1667 | 1667 | ||
1668 | /* Tell the device to stop sending interrupts */ | 1668 | /* Tell the device to stop sending interrupts */ |
1669 | iwl_disable_interrupts(priv); | 1669 | iwl_disable_interrupts(priv); |
@@ -1679,7 +1679,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1679 | } | 1679 | } |
1680 | 1680 | ||
1681 | #ifdef CONFIG_IWLWIFI_DEBUG | 1681 | #ifdef CONFIG_IWLWIFI_DEBUG |
1682 | if (priv->debug_level & (IWL_DL_ISR)) { | 1682 | if (iwl_debug_level & (IWL_DL_ISR)) { |
1683 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ | 1683 | /* NIC fires this, but we don't use it, redundant with WAKEUP */ |
1684 | if (inta & CSR_INT_BIT_SCD) { | 1684 | if (inta & CSR_INT_BIT_SCD) { |
1685 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " | 1685 | IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " |
@@ -1758,7 +1758,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1758 | iwl_enable_interrupts(priv); | 1758 | iwl_enable_interrupts(priv); |
1759 | 1759 | ||
1760 | #ifdef CONFIG_IWLWIFI_DEBUG | 1760 | #ifdef CONFIG_IWLWIFI_DEBUG |
1761 | if (priv->debug_level & (IWL_DL_ISR)) { | 1761 | if (iwl_debug_level & (IWL_DL_ISR)) { |
1762 | inta = iwl_read32(priv, CSR_INT); | 1762 | inta = iwl_read32(priv, CSR_INT); |
1763 | inta_mask = iwl_read32(priv, CSR_INT_MASK); | 1763 | inta_mask = iwl_read32(priv, CSR_INT_MASK); |
1764 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); | 1764 | inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); |
@@ -2041,7 +2041,7 @@ static void iwl3945_nic_start(struct iwl_priv *priv) | |||
2041 | */ | 2041 | */ |
2042 | static int iwl3945_read_ucode(struct iwl_priv *priv) | 2042 | static int iwl3945_read_ucode(struct iwl_priv *priv) |
2043 | { | 2043 | { |
2044 | struct iwl_ucode *ucode; | 2044 | const struct iwl_ucode_header *ucode; |
2045 | int ret = -EINVAL, index; | 2045 | int ret = -EINVAL, index; |
2046 | const struct firmware *ucode_raw; | 2046 | const struct firmware *ucode_raw; |
2047 | /* firmware file name contains uCode/driver compatibility version */ | 2047 | /* firmware file name contains uCode/driver compatibility version */ |
@@ -2082,22 +2082,24 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2082 | goto error; | 2082 | goto error; |
2083 | 2083 | ||
2084 | /* Make sure that we got at least our header! */ | 2084 | /* Make sure that we got at least our header! */ |
2085 | if (ucode_raw->size < sizeof(*ucode)) { | 2085 | if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { |
2086 | IWL_ERR(priv, "File size way too small!\n"); | 2086 | IWL_ERR(priv, "File size way too small!\n"); |
2087 | ret = -EINVAL; | 2087 | ret = -EINVAL; |
2088 | goto err_release; | 2088 | goto err_release; |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | /* Data from ucode file: header followed by uCode images */ | 2091 | /* Data from ucode file: header followed by uCode images */ |
2092 | ucode = (void *)ucode_raw->data; | 2092 | ucode = (struct iwl_ucode_header *)ucode_raw->data; |
2093 | 2093 | ||
2094 | priv->ucode_ver = le32_to_cpu(ucode->ver); | 2094 | priv->ucode_ver = le32_to_cpu(ucode->ver); |
2095 | api_ver = IWL_UCODE_API(priv->ucode_ver); | 2095 | api_ver = IWL_UCODE_API(priv->ucode_ver); |
2096 | inst_size = le32_to_cpu(ucode->inst_size); | 2096 | inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); |
2097 | data_size = le32_to_cpu(ucode->data_size); | 2097 | data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); |
2098 | init_size = le32_to_cpu(ucode->init_size); | 2098 | init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); |
2099 | init_data_size = le32_to_cpu(ucode->init_data_size); | 2099 | init_data_size = |
2100 | boot_size = le32_to_cpu(ucode->boot_size); | 2100 | priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); |
2101 | boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); | ||
2102 | src = priv->cfg->ops->ucode->get_data(ucode, api_ver); | ||
2101 | 2103 | ||
2102 | /* api_ver should match the api version forming part of the | 2104 | /* api_ver should match the api version forming part of the |
2103 | * firmware filename ... but we don't check for that and only rely | 2105 | * firmware filename ... but we don't check for that and only rely |
@@ -2138,12 +2140,13 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2138 | 2140 | ||
2139 | 2141 | ||
2140 | /* Verify size of file vs. image size info in file's header */ | 2142 | /* Verify size of file vs. image size info in file's header */ |
2141 | if (ucode_raw->size < sizeof(*ucode) + | 2143 | if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + |
2142 | inst_size + data_size + init_size + | 2144 | inst_size + data_size + init_size + |
2143 | init_data_size + boot_size) { | 2145 | init_data_size + boot_size) { |
2144 | 2146 | ||
2145 | IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n", | 2147 | IWL_DEBUG_INFO(priv, |
2146 | ucode_raw->size); | 2148 | "uCode file size %zd does not match expected size\n", |
2149 | ucode_raw->size); | ||
2147 | ret = -EINVAL; | 2150 | ret = -EINVAL; |
2148 | goto err_release; | 2151 | goto err_release; |
2149 | } | 2152 | } |
@@ -2226,44 +2229,44 @@ static int iwl3945_read_ucode(struct iwl_priv *priv) | |||
2226 | /* Copy images into buffers for card's bus-master reads ... */ | 2229 | /* Copy images into buffers for card's bus-master reads ... */ |
2227 | 2230 | ||
2228 | /* Runtime instructions (first block of data in file) */ | 2231 | /* Runtime instructions (first block of data in file) */ |
2229 | src = &ucode->data[0]; | 2232 | len = inst_size; |
2230 | len = priv->ucode_code.len; | ||
2231 | IWL_DEBUG_INFO(priv, | 2233 | IWL_DEBUG_INFO(priv, |
2232 | "Copying (but not loading) uCode instr len %zd\n", len); | 2234 | "Copying (but not loading) uCode instr len %zd\n", len); |
2233 | memcpy(priv->ucode_code.v_addr, src, len); | 2235 | memcpy(priv->ucode_code.v_addr, src, len); |
2236 | src += len; | ||
2237 | |||
2234 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", | 2238 | IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", |
2235 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); | 2239 | priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); |
2236 | 2240 | ||
2237 | /* Runtime data (2nd block) | 2241 | /* Runtime data (2nd block) |
2238 | * NOTE: Copy into backup buffer will be done in iwl3945_up() */ | 2242 | * NOTE: Copy into backup buffer will be done in iwl3945_up() */ |
2239 | src = &ucode->data[inst_size]; | 2243 | len = data_size; |
2240 | len = priv->ucode_data.len; | ||
2241 | IWL_DEBUG_INFO(priv, | 2244 | IWL_DEBUG_INFO(priv, |
2242 | "Copying (but not loading) uCode data len %zd\n", len); | 2245 | "Copying (but not loading) uCode data len %zd\n", len); |
2243 | memcpy(priv->ucode_data.v_addr, src, len); | 2246 | memcpy(priv->ucode_data.v_addr, src, len); |
2244 | memcpy(priv->ucode_data_backup.v_addr, src, len); | 2247 | memcpy(priv->ucode_data_backup.v_addr, src, len); |
2248 | src += len; | ||
2245 | 2249 | ||
2246 | /* Initialization instructions (3rd block) */ | 2250 | /* Initialization instructions (3rd block) */ |
2247 | if (init_size) { | 2251 | if (init_size) { |
2248 | src = &ucode->data[inst_size + data_size]; | 2252 | len = init_size; |
2249 | len = priv->ucode_init.len; | ||
2250 | IWL_DEBUG_INFO(priv, | 2253 | IWL_DEBUG_INFO(priv, |
2251 | "Copying (but not loading) init instr len %zd\n", len); | 2254 | "Copying (but not loading) init instr len %zd\n", len); |
2252 | memcpy(priv->ucode_init.v_addr, src, len); | 2255 | memcpy(priv->ucode_init.v_addr, src, len); |
2256 | src += len; | ||
2253 | } | 2257 | } |
2254 | 2258 | ||
2255 | /* Initialization data (4th block) */ | 2259 | /* Initialization data (4th block) */ |
2256 | if (init_data_size) { | 2260 | if (init_data_size) { |
2257 | src = &ucode->data[inst_size + data_size + init_size]; | 2261 | len = init_data_size; |
2258 | len = priv->ucode_init_data.len; | ||
2259 | IWL_DEBUG_INFO(priv, | 2262 | IWL_DEBUG_INFO(priv, |
2260 | "Copying (but not loading) init data len %zd\n", len); | 2263 | "Copying (but not loading) init data len %zd\n", len); |
2261 | memcpy(priv->ucode_init_data.v_addr, src, len); | 2264 | memcpy(priv->ucode_init_data.v_addr, src, len); |
2265 | src += len; | ||
2262 | } | 2266 | } |
2263 | 2267 | ||
2264 | /* Bootstrap instructions (5th block) */ | 2268 | /* Bootstrap instructions (5th block) */ |
2265 | src = &ucode->data[inst_size + data_size + init_size + init_data_size]; | 2269 | len = boot_size; |
2266 | len = priv->ucode_boot.len; | ||
2267 | IWL_DEBUG_INFO(priv, | 2270 | IWL_DEBUG_INFO(priv, |
2268 | "Copying (but not loading) boot instr len %zd\n", len); | 2271 | "Copying (but not loading) boot instr len %zd\n", len); |
2269 | memcpy(priv->ucode_boot.v_addr, src, len); | 2272 | memcpy(priv->ucode_boot.v_addr, src, len); |
@@ -3305,13 +3308,15 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3305 | * used for controlling the debug level. | 3308 | * used for controlling the debug level. |
3306 | * | 3309 | * |
3307 | * See the level definitions in iwl for details. | 3310 | * See the level definitions in iwl for details. |
3311 | * | ||
3312 | * FIXME This file can be deprecated as the module parameter is | ||
3313 | * writable and users can thus also change the debug level | ||
3314 | * using the /sys/module/iwl3945/parameters/debug file. | ||
3308 | */ | 3315 | */ |
3309 | static ssize_t show_debug_level(struct device *d, | 3316 | static ssize_t show_debug_level(struct device *d, |
3310 | struct device_attribute *attr, char *buf) | 3317 | struct device_attribute *attr, char *buf) |
3311 | { | 3318 | { |
3312 | struct iwl_priv *priv = dev_get_drvdata(d); | 3319 | return sprintf(buf, "0x%08X\n", iwl_debug_level); |
3313 | |||
3314 | return sprintf(buf, "0x%08X\n", priv->debug_level); | ||
3315 | } | 3320 | } |
3316 | static ssize_t store_debug_level(struct device *d, | 3321 | static ssize_t store_debug_level(struct device *d, |
3317 | struct device_attribute *attr, | 3322 | struct device_attribute *attr, |
@@ -3325,7 +3330,7 @@ static ssize_t store_debug_level(struct device *d, | |||
3325 | if (ret) | 3330 | if (ret) |
3326 | IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); | 3331 | IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); |
3327 | else | 3332 | else |
3328 | priv->debug_level = val; | 3333 | iwl_debug_level = val; |
3329 | 3334 | ||
3330 | return strnlen(buf, count); | 3335 | return strnlen(buf, count); |
3331 | } | 3336 | } |
@@ -3947,15 +3952,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
3947 | priv = hw->priv; | 3952 | priv = hw->priv; |
3948 | SET_IEEE80211_DEV(hw, &pdev->dev); | 3953 | SET_IEEE80211_DEV(hw, &pdev->dev); |
3949 | 3954 | ||
3950 | if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) || | ||
3951 | (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { | ||
3952 | IWL_ERR(priv, | ||
3953 | "invalid queues_num, should be between %d and %d\n", | ||
3954 | IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); | ||
3955 | err = -EINVAL; | ||
3956 | goto out_ieee80211_free_hw; | ||
3957 | } | ||
3958 | |||
3959 | /* | 3955 | /* |
3960 | * Disabling hardware scan means that mac80211 will perform scans | 3956 | * Disabling hardware scan means that mac80211 will perform scans |
3961 | * "the hard way", rather than using device's scan. | 3957 | * "the hard way", rather than using device's scan. |
@@ -3972,7 +3968,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
3972 | priv->inta_mask = CSR_INI_SET_MASK; | 3968 | priv->inta_mask = CSR_INI_SET_MASK; |
3973 | 3969 | ||
3974 | #ifdef CONFIG_IWLWIFI_DEBUG | 3970 | #ifdef CONFIG_IWLWIFI_DEBUG |
3975 | priv->debug_level = iwl3945_mod_params.debug; | ||
3976 | atomic_set(&priv->restrict_refcnt, 0); | 3971 | atomic_set(&priv->restrict_refcnt, 0); |
3977 | #endif | 3972 | #endif |
3978 | 3973 | ||
@@ -4268,14 +4263,12 @@ MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | |||
4268 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); | 4263 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); |
4269 | MODULE_PARM_DESC(swcrypto, | 4264 | MODULE_PARM_DESC(swcrypto, |
4270 | "using software crypto (default 1 [software])\n"); | 4265 | "using software crypto (default 1 [software])\n"); |
4271 | module_param_named(debug, iwl3945_mod_params.debug, uint, 0444); | 4266 | #ifdef CONFIG_IWLWIFI_DEBUG |
4267 | module_param_named(debug, iwl_debug_level, uint, 0644); | ||
4272 | MODULE_PARM_DESC(debug, "debug output mask"); | 4268 | MODULE_PARM_DESC(debug, "debug output mask"); |
4269 | #endif | ||
4273 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); | 4270 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); |
4274 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4271 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
4275 | |||
4276 | module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444); | ||
4277 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
4278 | |||
4279 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); | 4272 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); |
4280 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); | 4273 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); |
4281 | 4274 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 54bebba8e27e..3f5a08fa401f 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -158,34 +158,6 @@ static int iwm_key_init(struct iwm_key *key, u8 key_index, | |||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | static int iwm_reset_profile(struct iwm_priv *iwm) | ||
162 | { | ||
163 | int ret; | ||
164 | |||
165 | if (!iwm->umac_profile_active) | ||
166 | return 0; | ||
167 | |||
168 | /* | ||
169 | * If there is a current active profile, but no | ||
170 | * default key, it's not worth trying to associate again. | ||
171 | */ | ||
172 | if (iwm->default_key < 0) | ||
173 | return 0; | ||
174 | |||
175 | /* | ||
176 | * Here we have an active profile, but a key setting changed. | ||
177 | * We thus have to invalidate the current profile, and push the | ||
178 | * new one. Keys will be pushed when association takes place. | ||
179 | */ | ||
180 | ret = iwm_invalidate_mlme_profile(iwm); | ||
181 | if (ret < 0) { | ||
182 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | return iwm_send_mlme_profile(iwm); | ||
187 | } | ||
188 | |||
189 | static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 161 | static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
190 | u8 key_index, const u8 *mac_addr, | 162 | u8 key_index, const u8 *mac_addr, |
191 | struct key_params *params) | 163 | struct key_params *params) |
@@ -203,32 +175,6 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
203 | return ret; | 175 | return ret; |
204 | } | 176 | } |
205 | 177 | ||
206 | /* | ||
207 | * The WEP keys can be set before or after setting the essid. | ||
208 | * We need to handle both cases by simply pushing the keys after | ||
209 | * we send the profile. | ||
210 | * If the profile is not set yet (i.e. we're pushing keys before | ||
211 | * the essid), we set the cipher appropriately. | ||
212 | * If the profile is set, we havent associated yet because our | ||
213 | * cipher was incorrectly set. So we invalidate and send the | ||
214 | * profile again. | ||
215 | */ | ||
216 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
217 | key->cipher == WLAN_CIPHER_SUITE_WEP104) { | ||
218 | u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher; | ||
219 | u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher; | ||
220 | |||
221 | IWM_DBG_WEXT(iwm, DBG, "WEP key\n"); | ||
222 | |||
223 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40) | ||
224 | *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
225 | if (key->cipher == WLAN_CIPHER_SUITE_WEP104) | ||
226 | *ucast_cipher = *mcast_cipher = | ||
227 | UMAC_CIPHER_TYPE_WEP_104; | ||
228 | |||
229 | return iwm_reset_profile(iwm); | ||
230 | } | ||
231 | |||
232 | return iwm_set_key(iwm, 0, key); | 178 | return iwm_set_key(iwm, 0, key); |
233 | } | 179 | } |
234 | 180 | ||
@@ -271,10 +217,6 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
271 | if (key_index == iwm->default_key) | 217 | if (key_index == iwm->default_key) |
272 | iwm->default_key = -1; | 218 | iwm->default_key = -1; |
273 | 219 | ||
274 | /* If the interface is down, we just cache this */ | ||
275 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | ||
276 | return 0; | ||
277 | |||
278 | return iwm_set_key(iwm, 1, key); | 220 | return iwm_set_key(iwm, 1, key); |
279 | } | 221 | } |
280 | 222 | ||
@@ -283,7 +225,6 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, | |||
283 | u8 key_index) | 225 | u8 key_index) |
284 | { | 226 | { |
285 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | 227 | struct iwm_priv *iwm = ndev_to_iwm(ndev); |
286 | int ret; | ||
287 | 228 | ||
288 | IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); | 229 | IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); |
289 | 230 | ||
@@ -294,15 +235,26 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, | |||
294 | 235 | ||
295 | iwm->default_key = key_index; | 236 | iwm->default_key = key_index; |
296 | 237 | ||
297 | /* If the interface is down, we just cache this */ | 238 | return iwm_set_tx_key(iwm, key_index); |
298 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 239 | } |
299 | return 0; | ||
300 | 240 | ||
301 | ret = iwm_set_tx_key(iwm, key_index); | 241 | int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, |
302 | if (ret < 0) | 242 | u8 *mac, struct station_info *sinfo) |
303 | return ret; | 243 | { |
244 | struct iwm_priv *iwm = ndev_to_iwm(ndev); | ||
245 | |||
246 | if (memcmp(mac, iwm->bssid, ETH_ALEN)) | ||
247 | return -ENOENT; | ||
304 | 248 | ||
305 | return iwm_reset_profile(iwm); | 249 | sinfo->filled |= STATION_INFO_TX_BITRATE; |
250 | sinfo->txrate.legacy = iwm->rate * 10; | ||
251 | |||
252 | if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | ||
253 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
254 | sinfo->signal = iwm->wstats.qual.level; | ||
255 | } | ||
256 | |||
257 | return 0; | ||
306 | } | 258 | } |
307 | 259 | ||
308 | 260 | ||
@@ -500,6 +452,179 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
500 | return 0; | 452 | return 0; |
501 | } | 453 | } |
502 | 454 | ||
455 | static int iwm_set_auth_type(struct iwm_priv *iwm, | ||
456 | enum nl80211_auth_type sme_auth_type) | ||
457 | { | ||
458 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
459 | |||
460 | switch (sme_auth_type) { | ||
461 | case NL80211_AUTHTYPE_AUTOMATIC: | ||
462 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
463 | IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); | ||
464 | *auth_type = UMAC_AUTH_TYPE_OPEN; | ||
465 | break; | ||
466 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
467 | if (iwm->umac_profile->sec.flags & | ||
468 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { | ||
469 | IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); | ||
470 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
471 | } else { | ||
472 | IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); | ||
473 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
474 | } | ||
475 | |||
476 | break; | ||
477 | default: | ||
478 | IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); | ||
479 | return -ENOTSUPP; | ||
480 | } | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) | ||
486 | { | ||
487 | if (!wpa_version) { | ||
488 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | if (wpa_version & NL80211_WPA_VERSION_2) | ||
493 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; | ||
494 | |||
495 | if (wpa_version & NL80211_WPA_VERSION_1) | ||
496 | iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) | ||
502 | { | ||
503 | u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : | ||
504 | &iwm->umac_profile->sec.mcast_cipher; | ||
505 | |||
506 | if (!cipher) { | ||
507 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | switch (cipher) { | ||
512 | case IW_AUTH_CIPHER_NONE: | ||
513 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
514 | break; | ||
515 | case WLAN_CIPHER_SUITE_WEP40: | ||
516 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
517 | break; | ||
518 | case WLAN_CIPHER_SUITE_WEP104: | ||
519 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
520 | break; | ||
521 | case WLAN_CIPHER_SUITE_TKIP: | ||
522 | *profile_cipher = UMAC_CIPHER_TYPE_TKIP; | ||
523 | break; | ||
524 | case WLAN_CIPHER_SUITE_CCMP: | ||
525 | *profile_cipher = UMAC_CIPHER_TYPE_CCMP; | ||
526 | break; | ||
527 | default: | ||
528 | IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); | ||
529 | return -ENOTSUPP; | ||
530 | } | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) | ||
536 | { | ||
537 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
538 | |||
539 | IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); | ||
540 | |||
541 | if (key_mgt == WLAN_AKM_SUITE_8021X) | ||
542 | *auth_type = UMAC_AUTH_TYPE_8021X; | ||
543 | else if (key_mgt == WLAN_AKM_SUITE_PSK) { | ||
544 | if (iwm->umac_profile->sec.flags & | ||
545 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) | ||
546 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
547 | else | ||
548 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
549 | } else { | ||
550 | IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); | ||
551 | return -EINVAL; | ||
552 | } | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | |||
558 | static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | ||
559 | struct cfg80211_connect_params *sme) | ||
560 | { | ||
561 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
562 | struct ieee80211_channel *chan = sme->channel; | ||
563 | int ret; | ||
564 | |||
565 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | ||
566 | return -EIO; | ||
567 | |||
568 | if (!sme->ssid) | ||
569 | return -EINVAL; | ||
570 | |||
571 | if (chan) | ||
572 | iwm->channel = | ||
573 | ieee80211_frequency_to_channel(chan->center_freq); | ||
574 | |||
575 | iwm->umac_profile->ssid.ssid_len = sme->ssid_len; | ||
576 | memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); | ||
577 | |||
578 | if (sme->bssid) { | ||
579 | IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); | ||
580 | memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); | ||
581 | iwm->umac_profile->bss_num = 1; | ||
582 | } else { | ||
583 | memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); | ||
584 | iwm->umac_profile->bss_num = 0; | ||
585 | } | ||
586 | |||
587 | ret = iwm_set_auth_type(iwm, sme->auth_type); | ||
588 | if (ret < 0) | ||
589 | return ret; | ||
590 | |||
591 | ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); | ||
592 | if (ret < 0) | ||
593 | return ret; | ||
594 | |||
595 | if (sme->crypto.n_ciphers_pairwise) { | ||
596 | ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], | ||
597 | true); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | } | ||
601 | |||
602 | ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); | ||
603 | if (ret < 0) | ||
604 | return ret; | ||
605 | |||
606 | if (sme->crypto.n_akm_suites) { | ||
607 | ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); | ||
608 | if (ret < 0) | ||
609 | return ret; | ||
610 | } | ||
611 | |||
612 | return iwm_send_mlme_profile(iwm); | ||
613 | } | ||
614 | |||
615 | static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | ||
616 | u16 reason_code) | ||
617 | { | ||
618 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
619 | |||
620 | IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); | ||
621 | |||
622 | if (iwm->umac_profile_active) | ||
623 | return iwm_invalidate_mlme_profile(iwm); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
503 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, | 628 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, |
504 | enum tx_power_setting type, int dbm) | 629 | enum tx_power_setting type, int dbm) |
505 | { | 630 | { |
@@ -549,8 +674,11 @@ static struct cfg80211_ops iwm_cfg80211_ops = { | |||
549 | .get_key = iwm_cfg80211_get_key, | 674 | .get_key = iwm_cfg80211_get_key, |
550 | .del_key = iwm_cfg80211_del_key, | 675 | .del_key = iwm_cfg80211_del_key, |
551 | .set_default_key = iwm_cfg80211_set_default_key, | 676 | .set_default_key = iwm_cfg80211_set_default_key, |
677 | .get_station = iwm_cfg80211_get_station, | ||
552 | .scan = iwm_cfg80211_scan, | 678 | .scan = iwm_cfg80211_scan, |
553 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, | 679 | .set_wiphy_params = iwm_cfg80211_set_wiphy_params, |
680 | .connect = iwm_cfg80211_connect, | ||
681 | .disconnect = iwm_cfg80211_disconnect, | ||
554 | .join_ibss = iwm_cfg80211_join_ibss, | 682 | .join_ibss = iwm_cfg80211_join_ibss, |
555 | .leave_ibss = iwm_cfg80211_leave_ibss, | 683 | .leave_ibss = iwm_cfg80211_leave_ibss, |
556 | .set_tx_power = iwm_cfg80211_set_txpower, | 684 | .set_tx_power = iwm_cfg80211_set_txpower, |
@@ -558,6 +686,13 @@ static struct cfg80211_ops iwm_cfg80211_ops = { | |||
558 | .set_power_mgmt = iwm_cfg80211_set_power_mgmt, | 686 | .set_power_mgmt = iwm_cfg80211_set_power_mgmt, |
559 | }; | 687 | }; |
560 | 688 | ||
689 | static const u32 cipher_suites[] = { | ||
690 | WLAN_CIPHER_SUITE_WEP40, | ||
691 | WLAN_CIPHER_SUITE_WEP104, | ||
692 | WLAN_CIPHER_SUITE_TKIP, | ||
693 | WLAN_CIPHER_SUITE_CCMP, | ||
694 | }; | ||
695 | |||
561 | struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) | 696 | struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) |
562 | { | 697 | { |
563 | int ret = 0; | 698 | int ret = 0; |
@@ -600,6 +735,9 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) | |||
600 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; | 735 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; |
601 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 736 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
602 | 737 | ||
738 | wdev->wiphy->cipher_suites = cipher_suites; | ||
739 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
740 | |||
603 | ret = wiphy_register(wdev->wiphy); | 741 | ret = wiphy_register(wdev->wiphy); |
604 | if (ret < 0) { | 742 | if (ret < 0) { |
605 | dev_err(dev, "Couldn't register wiphy device\n"); | 743 | dev_err(dev, "Couldn't register wiphy device\n"); |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 0d35afefb61c..0d6637005f42 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c | |||
@@ -87,8 +87,7 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, | |||
87 | test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), | 87 | test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), |
88 | 3 * HZ); | 88 | 3 * HZ); |
89 | 89 | ||
90 | if (!ret) | 90 | return ret ? 0 : -EBUSY; |
91 | ret = -EBUSY; | ||
92 | } | 91 | } |
93 | 92 | ||
94 | return ret; | 93 | return ret; |
@@ -480,8 +479,10 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, | |||
480 | target_cmd.eop = 1; | 479 | target_cmd.eop = 1; |
481 | 480 | ||
482 | ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); | 481 | ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); |
483 | if (ret < 0) | 482 | if (ret < 0) { |
484 | IWM_ERR(iwm, "Couldn't send READ command\n"); | 483 | IWM_ERR(iwm, "Couldn't send READ command\n"); |
484 | return ret; | ||
485 | } | ||
485 | 486 | ||
486 | /* When succeding, the send_target routine returns the seq number */ | 487 | /* When succeding, the send_target routine returns the seq number */ |
487 | seq_num = ret; | 488 | seq_num = ret; |
@@ -501,7 +502,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, | |||
501 | 502 | ||
502 | kfree(cmd); | 503 | kfree(cmd); |
503 | 504 | ||
504 | return ret; | 505 | return 0; |
505 | } | 506 | } |
506 | 507 | ||
507 | int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) | 508 | int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) |
@@ -511,7 +512,7 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) | |||
511 | 512 | ||
512 | ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), | 513 | ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), |
513 | mac_align, sizeof(mac_align)); | 514 | mac_align, sizeof(mac_align)); |
514 | if (ret < 0) | 515 | if (ret) |
515 | return ret; | 516 | return ret; |
516 | 517 | ||
517 | if (is_valid_ether_addr(mac_align)) | 518 | if (is_valid_ether_addr(mac_align)) |
@@ -583,12 +584,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
583 | struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; | 584 | struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; |
584 | struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; | 585 | struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; |
585 | 586 | ||
586 | /* | ||
587 | * We check if our current profile is valid. | ||
588 | * If not, we dont push the key, we just cache them, | ||
589 | * so that with the next siwsessid call, the keys | ||
590 | * will be actually pushed. | ||
591 | */ | ||
592 | if (!remove) { | 587 | if (!remove) { |
593 | ret = iwm_check_profile(iwm); | 588 | ret = iwm_check_profile(iwm); |
594 | if (ret < 0) | 589 | if (ret < 0) |
@@ -714,7 +709,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
714 | ret = iwm_send_wifi_if_cmd(iwm, &key_remove, | 709 | ret = iwm_send_wifi_if_cmd(iwm, &key_remove, |
715 | sizeof(struct iwm_umac_key_remove), | 710 | sizeof(struct iwm_umac_key_remove), |
716 | 1); | 711 | 1); |
717 | if (ret < 0) | 712 | if (ret) |
718 | return ret; | 713 | return ret; |
719 | 714 | ||
720 | iwm->keys[key_idx].key_len = 0; | 715 | iwm->keys[key_idx].key_len = 0; |
@@ -726,7 +721,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) | |||
726 | 721 | ||
727 | int iwm_send_mlme_profile(struct iwm_priv *iwm) | 722 | int iwm_send_mlme_profile(struct iwm_priv *iwm) |
728 | { | 723 | { |
729 | int ret, i; | 724 | int ret; |
730 | struct iwm_umac_profile profile; | 725 | struct iwm_umac_profile profile; |
731 | 726 | ||
732 | memcpy(&profile, iwm->umac_profile, sizeof(profile)); | 727 | memcpy(&profile, iwm->umac_profile, sizeof(profile)); |
@@ -736,32 +731,11 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) | |||
736 | sizeof(struct iwm_umac_wifi_if)); | 731 | sizeof(struct iwm_umac_wifi_if)); |
737 | 732 | ||
738 | ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); | 733 | ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); |
739 | if (ret < 0) { | 734 | if (ret) { |
740 | IWM_ERR(iwm, "Send profile command failed\n"); | 735 | IWM_ERR(iwm, "Send profile command failed\n"); |
741 | return ret; | 736 | return ret; |
742 | } | 737 | } |
743 | 738 | ||
744 | for (i = 0; i < IWM_NUM_KEYS; i++) | ||
745 | if (iwm->keys[i].key_len) { | ||
746 | struct iwm_key *key = &iwm->keys[i]; | ||
747 | |||
748 | /* Wait for the profile before sending the keys */ | ||
749 | wait_event_interruptible_timeout(iwm->mlme_queue, | ||
750 | (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || | ||
751 | test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), | ||
752 | 3 * HZ); | ||
753 | |||
754 | ret = iwm_set_key(iwm, 0, key); | ||
755 | if (ret < 0) | ||
756 | return ret; | ||
757 | |||
758 | if (iwm->default_key == i) { | ||
759 | ret = iwm_set_tx_key(iwm, i); | ||
760 | if (ret < 0) | ||
761 | return ret; | ||
762 | } | ||
763 | } | ||
764 | |||
765 | return 0; | 739 | return 0; |
766 | } | 740 | } |
767 | 741 | ||
@@ -778,15 +752,13 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) | |||
778 | invalid.reason = WLAN_REASON_UNSPECIFIED; | 752 | invalid.reason = WLAN_REASON_UNSPECIFIED; |
779 | 753 | ||
780 | ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); | 754 | ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); |
781 | if (ret < 0) | 755 | if (ret) |
782 | return ret; | 756 | return ret; |
783 | 757 | ||
784 | ret = wait_event_interruptible_timeout(iwm->mlme_queue, | 758 | ret = wait_event_interruptible_timeout(iwm->mlme_queue, |
785 | (iwm->umac_profile_active == 0), 2 * HZ); | 759 | (iwm->umac_profile_active == 0), 2 * HZ); |
786 | if (!ret) | ||
787 | return -EBUSY; | ||
788 | 760 | ||
789 | return 0; | 761 | return ret ? 0 : -EBUSY; |
790 | } | 762 | } |
791 | 763 | ||
792 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) | 764 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) |
@@ -869,7 +841,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, | |||
869 | } | 841 | } |
870 | 842 | ||
871 | ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); | 843 | ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); |
872 | if (ret < 0) { | 844 | if (ret) { |
873 | IWM_ERR(iwm, "Couldn't send scan request\n"); | 845 | IWM_ERR(iwm, "Couldn't send scan request\n"); |
874 | return ret; | 846 | return ret; |
875 | } | 847 | } |
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index ee127fe4f43f..c430418248b4 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c | |||
@@ -105,9 +105,9 @@ | |||
105 | #include "umac.h" | 105 | #include "umac.h" |
106 | #include "debug.h" | 106 | #include "debug.h" |
107 | 107 | ||
108 | static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, | 108 | static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, |
109 | struct iwm_nonwifi_cmd *cmd, | 109 | struct iwm_nonwifi_cmd *cmd, |
110 | struct iwm_udma_nonwifi_cmd *udma_cmd) | 110 | struct iwm_udma_nonwifi_cmd *udma_cmd) |
111 | { | 111 | { |
112 | INIT_LIST_HEAD(&cmd->pending); | 112 | INIT_LIST_HEAD(&cmd->pending); |
113 | 113 | ||
@@ -118,7 +118,7 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, | |||
118 | cmd->seq_num = iwm->nonwifi_seq_num; | 118 | cmd->seq_num = iwm->nonwifi_seq_num; |
119 | udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); | 119 | udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); |
120 | 120 | ||
121 | cmd->seq_num = iwm->nonwifi_seq_num++; | 121 | iwm->nonwifi_seq_num++; |
122 | iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; | 122 | iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; |
123 | 123 | ||
124 | if (udma_cmd->resp) | 124 | if (udma_cmd->resp) |
@@ -130,6 +130,8 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, | |||
130 | cmd->buf.len = 0; | 130 | cmd->buf.len = 0; |
131 | 131 | ||
132 | memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); | 132 | memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); |
133 | |||
134 | return cmd->seq_num; | ||
133 | } | 135 | } |
134 | 136 | ||
135 | u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) | 137 | u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) |
@@ -369,7 +371,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, | |||
369 | const void *payload) | 371 | const void *payload) |
370 | { | 372 | { |
371 | struct iwm_nonwifi_cmd *cmd; | 373 | struct iwm_nonwifi_cmd *cmd; |
372 | int ret; | 374 | int ret, seq_num; |
373 | 375 | ||
374 | cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); | 376 | cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); |
375 | if (!cmd) { | 377 | if (!cmd) { |
@@ -377,7 +379,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, | |||
377 | return -ENOMEM; | 379 | return -ENOMEM; |
378 | } | 380 | } |
379 | 381 | ||
380 | iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); | 382 | seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); |
381 | 383 | ||
382 | if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || | 384 | if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || |
383 | cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { | 385 | cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { |
@@ -393,7 +395,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, | |||
393 | if (ret < 0) | 395 | if (ret < 0) |
394 | return ret; | 396 | return ret; |
395 | 397 | ||
396 | return cmd->seq_num; | 398 | return seq_num; |
397 | } | 399 | } |
398 | 400 | ||
399 | static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, | 401 | static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79d9d89d47ae..2175a481d2f4 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -281,6 +281,11 @@ struct iwm_priv { | |||
281 | struct work_struct reset_worker; | 281 | struct work_struct reset_worker; |
282 | struct mutex mutex; | 282 | struct mutex mutex; |
283 | 283 | ||
284 | u8 *req_ie; | ||
285 | int req_ie_len; | ||
286 | u8 *resp_ie; | ||
287 | int resp_ie_len; | ||
288 | |||
284 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 289 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); |
285 | }; | 290 | }; |
286 | 291 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 484f110151b7..cf2574442b57 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -497,6 +497,13 @@ void iwm_link_off(struct iwm_priv *iwm) | |||
497 | memset(wstats, 0, sizeof(struct iw_statistics)); | 497 | memset(wstats, 0, sizeof(struct iw_statistics)); |
498 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | 498 | wstats->qual.updated = IW_QUAL_ALL_INVALID; |
499 | 499 | ||
500 | kfree(iwm->req_ie); | ||
501 | iwm->req_ie = NULL; | ||
502 | iwm->req_ie_len = 0; | ||
503 | kfree(iwm->resp_ie); | ||
504 | iwm->resp_ie = NULL; | ||
505 | iwm->resp_ie_len = 0; | ||
506 | |||
500 | del_timer_sync(&iwm->watchdog); | 507 | del_timer_sync(&iwm->watchdog); |
501 | } | 508 | } |
502 | 509 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 3909477fb3bf..86079a187eef 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -102,7 +102,6 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, | |||
102 | error = (struct iwm_umac_notif_error *)buf; | 102 | error = (struct iwm_umac_notif_error *)buf; |
103 | fw_err = &error->err; | 103 | fw_err = &error->err; |
104 | 104 | ||
105 | |||
106 | IWM_ERR(iwm, "%cMAC FW ERROR:\n", | 105 | IWM_ERR(iwm, "%cMAC FW ERROR:\n", |
107 | (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); | 106 | (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); |
108 | IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); | 107 | IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); |
@@ -219,17 +218,17 @@ static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, | |||
219 | (buf + sizeof(struct iwm_umac_wifi_in_hdr)); | 218 | (buf + sizeof(struct iwm_umac_wifi_in_hdr)); |
220 | hdr = (struct iwm_umac_wifi_in_hdr *)buf; | 219 | hdr = (struct iwm_umac_wifi_in_hdr *)buf; |
221 | 220 | ||
222 | IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); | 221 | IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); |
223 | 222 | ||
224 | IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n", | 223 | IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n", |
225 | le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); | 224 | le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); |
226 | IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); | 225 | IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); |
227 | IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n", | 226 | IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n", |
228 | le16_to_cpu(tx_resp->retry_cnt)); | 227 | le16_to_cpu(tx_resp->retry_cnt)); |
229 | IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); | 228 | IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); |
230 | IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n", | 229 | IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n", |
231 | le16_to_cpu(tx_resp->byte_cnt)); | 230 | le16_to_cpu(tx_resp->byte_cnt)); |
232 | IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); | 231 | IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); |
233 | 232 | ||
234 | return 0; | 233 | return 0; |
235 | } | 234 | } |
@@ -419,8 +418,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, | |||
419 | if (IS_ERR(ticket_node)) | 418 | if (IS_ERR(ticket_node)) |
420 | return PTR_ERR(ticket_node); | 419 | return PTR_ERR(ticket_node); |
421 | 420 | ||
422 | IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n", | 421 | IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", |
423 | ticket->id); | 422 | ticket->id); |
424 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); | 423 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); |
425 | 424 | ||
426 | /* | 425 | /* |
@@ -455,15 +454,15 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, | |||
455 | u16 id, buf_offset; | 454 | u16 id, buf_offset; |
456 | u32 packet_size; | 455 | u32 packet_size; |
457 | 456 | ||
458 | IWM_DBG_NTF(iwm, DBG, "\n"); | 457 | IWM_DBG_RX(iwm, DBG, "\n"); |
459 | 458 | ||
460 | wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; | 459 | wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; |
461 | id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); | 460 | id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); |
462 | buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); | 461 | buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); |
463 | packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); | 462 | packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); |
464 | 463 | ||
465 | IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", | 464 | IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", |
466 | wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); | 465 | wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); |
467 | IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); | 466 | IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); |
468 | IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); | 467 | IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); |
469 | 468 | ||
@@ -504,13 +503,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
504 | { | 503 | { |
505 | struct iwm_umac_notif_assoc_complete *complete = | 504 | struct iwm_umac_notif_assoc_complete *complete = |
506 | (struct iwm_umac_notif_assoc_complete *)buf; | 505 | (struct iwm_umac_notif_assoc_complete *)buf; |
507 | union iwreq_data wrqu; | ||
508 | 506 | ||
509 | IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", | 507 | IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", |
510 | complete->bssid, complete->status); | 508 | complete->bssid, complete->status); |
511 | 509 | ||
512 | memset(&wrqu, 0, sizeof(wrqu)); | ||
513 | |||
514 | clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); | 510 | clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); |
515 | 511 | ||
516 | switch (le32_to_cpu(complete->status)) { | 512 | switch (le32_to_cpu(complete->status)) { |
@@ -521,7 +517,14 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
521 | 517 | ||
522 | iwm_link_on(iwm); | 518 | iwm_link_on(iwm); |
523 | 519 | ||
524 | memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN); | 520 | if (iwm->conf.mode == UMAC_MODE_IBSS) |
521 | goto ibss; | ||
522 | |||
523 | cfg80211_connect_result(iwm_to_ndev(iwm), | ||
524 | complete->bssid, | ||
525 | iwm->req_ie, iwm->req_ie_len, | ||
526 | iwm->resp_ie, iwm->resp_ie_len, | ||
527 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
525 | break; | 528 | break; |
526 | case UMAC_ASSOC_COMPLETE_FAILURE: | 529 | case UMAC_ASSOC_COMPLETE_FAILURE: |
527 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); | 530 | clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); |
@@ -529,18 +532,22 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
529 | iwm->channel = 0; | 532 | iwm->channel = 0; |
530 | 533 | ||
531 | iwm_link_off(iwm); | 534 | iwm_link_off(iwm); |
535 | |||
536 | if (iwm->conf.mode == UMAC_MODE_IBSS) | ||
537 | goto ibss; | ||
538 | |||
539 | cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, | ||
540 | NULL, 0, NULL, 0, | ||
541 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
542 | GFP_KERNEL); | ||
532 | default: | 543 | default: |
533 | break; | 544 | break; |
534 | } | 545 | } |
535 | 546 | ||
536 | if (iwm->conf.mode == UMAC_MODE_IBSS) { | 547 | return 0; |
537 | cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
542 | wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL); | ||
543 | 548 | ||
549 | ibss: | ||
550 | cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); | ||
544 | return 0; | 551 | return 0; |
545 | } | 552 | } |
546 | 553 | ||
@@ -770,37 +777,46 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, | |||
770 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) | 777 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) |
771 | { | 778 | { |
772 | struct iwm_umac_notif_mgt_frame *mgt_frame = | 779 | struct iwm_umac_notif_mgt_frame *mgt_frame = |
773 | (struct iwm_umac_notif_mgt_frame *)buf; | 780 | (struct iwm_umac_notif_mgt_frame *)buf; |
774 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; | 781 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; |
775 | u8 *ie; | 782 | u8 *ie; |
776 | unsigned int event; | ||
777 | union iwreq_data wrqu; | ||
778 | 783 | ||
779 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, | 784 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, |
780 | le16_to_cpu(mgt_frame->len)); | 785 | le16_to_cpu(mgt_frame->len)); |
781 | 786 | ||
782 | if (ieee80211_is_assoc_req(mgt->frame_control)) { | 787 | if (ieee80211_is_assoc_req(mgt->frame_control)) { |
783 | ie = mgt->u.assoc_req.variable;; | 788 | ie = mgt->u.assoc_req.variable;; |
784 | event = IWEVASSOCREQIE; | 789 | iwm->req_ie_len = |
790 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | ||
791 | kfree(iwm->req_ie); | ||
792 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, | ||
793 | iwm->req_ie_len, GFP_KERNEL); | ||
785 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { | 794 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { |
786 | ie = mgt->u.reassoc_req.variable;; | 795 | ie = mgt->u.reassoc_req.variable;; |
787 | event = IWEVASSOCREQIE; | 796 | iwm->req_ie_len = |
797 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | ||
798 | kfree(iwm->req_ie); | ||
799 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, | ||
800 | iwm->req_ie_len, GFP_KERNEL); | ||
788 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { | 801 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { |
789 | ie = mgt->u.assoc_resp.variable;; | 802 | ie = mgt->u.assoc_resp.variable;; |
790 | event = IWEVASSOCRESPIE; | 803 | iwm->resp_ie_len = |
804 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | ||
805 | kfree(iwm->resp_ie); | ||
806 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, | ||
807 | iwm->resp_ie_len, GFP_KERNEL); | ||
791 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { | 808 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { |
792 | ie = mgt->u.reassoc_resp.variable;; | 809 | ie = mgt->u.reassoc_resp.variable;; |
793 | event = IWEVASSOCRESPIE; | 810 | iwm->resp_ie_len = |
811 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | ||
812 | kfree(iwm->resp_ie); | ||
813 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, | ||
814 | iwm->resp_ie_len, GFP_KERNEL); | ||
794 | } else { | 815 | } else { |
795 | IWM_ERR(iwm, "Unsupported management frame"); | 816 | IWM_ERR(iwm, "Unsupported management frame"); |
796 | return 0; | 817 | return 0; |
797 | } | 818 | } |
798 | 819 | ||
799 | wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | ||
800 | |||
801 | IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length); | ||
802 | wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie); | ||
803 | |||
804 | return 0; | 820 | return 0; |
805 | } | 821 | } |
806 | 822 | ||
@@ -1360,7 +1376,7 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1360 | 1376 | ||
1361 | skb->dev = iwm_to_ndev(iwm); | 1377 | skb->dev = iwm_to_ndev(iwm); |
1362 | skb->protocol = eth_type_trans(skb, ndev); | 1378 | skb->protocol = eth_type_trans(skb, ndev); |
1363 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1379 | skb->ip_summed = CHECKSUM_NONE; |
1364 | memset(skb->cb, 0, sizeof(skb->cb)); | 1380 | memset(skb->cb, 0, sizeof(skb->cb)); |
1365 | 1381 | ||
1366 | ndev->stats.rx_packets++; | 1382 | ndev->stats.rx_packets++; |
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 0af2a3c76281..c5a14ae3160a 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h | |||
@@ -615,6 +615,7 @@ struct iwm_umac_notif_alive { | |||
615 | } __attribute__ ((packed)); | 615 | } __attribute__ ((packed)); |
616 | 616 | ||
617 | struct iwm_umac_notif_init_complete { | 617 | struct iwm_umac_notif_init_complete { |
618 | struct iwm_umac_wifi_in_hdr hdr; | ||
618 | __le16 status; | 619 | __le16 status; |
619 | __le16 reserved; | 620 | __le16 reserved; |
620 | } __attribute__ ((packed)); | 621 | } __attribute__ ((packed)); |
@@ -643,6 +644,11 @@ struct iwm_fw_error_hdr { | |||
643 | __le32 umac_status; | 644 | __le32 umac_status; |
644 | __le32 lmac_status; | 645 | __le32 lmac_status; |
645 | __le32 sdio_status; | 646 | __le32 sdio_status; |
647 | __le32 dbm_sample_ctrl; | ||
648 | __le32 dbm_buf_base; | ||
649 | __le32 dbm_buf_end; | ||
650 | __le32 dbm_buf_write_ptr; | ||
651 | __le32 dbm_buf_cycle_cnt; | ||
646 | } __attribute__ ((packed)); | 652 | } __attribute__ ((packed)); |
647 | 653 | ||
648 | struct iwm_umac_notif_error { | 654 | struct iwm_umac_notif_error { |
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 2e7eaf96cf93..c3c90d5963bf 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c | |||
@@ -21,31 +21,11 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/netdevice.h> | ||
26 | #include <linux/wireless.h> | 24 | #include <linux/wireless.h> |
27 | #include <linux/if_arp.h> | ||
28 | #include <linux/etherdevice.h> | ||
29 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
30 | #include <net/iw_handler.h> | ||
31 | 26 | ||
32 | #include "iwm.h" | 27 | #include "iwm.h" |
33 | #include "umac.h" | ||
34 | #include "commands.h" | 28 | #include "commands.h" |
35 | #include "debug.h" | ||
36 | |||
37 | static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev) | ||
38 | { | ||
39 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
40 | struct iw_statistics *wstats = &iwm->wstats; | ||
41 | |||
42 | if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | ||
43 | memset(wstats, 0, sizeof(struct iw_statistics)); | ||
44 | wstats->qual.updated = IW_QUAL_ALL_INVALID; | ||
45 | } | ||
46 | |||
47 | return wstats; | ||
48 | } | ||
49 | 29 | ||
50 | static int iwm_wext_siwfreq(struct net_device *dev, | 30 | static int iwm_wext_siwfreq(struct net_device *dev, |
51 | struct iw_request_info *info, | 31 | struct iw_request_info *info, |
@@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_device *dev, | |||
53 | { | 33 | { |
54 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 34 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
55 | 35 | ||
56 | if (freq->flags == IW_FREQ_AUTO) | 36 | switch (iwm->conf.mode) { |
57 | return 0; | 37 | case UMAC_MODE_IBSS: |
58 | 38 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | |
59 | /* frequency/channel can only be set in IBSS mode */ | 39 | default: |
60 | if (iwm->conf.mode != UMAC_MODE_IBSS) | ||
61 | return -EOPNOTSUPP; | 40 | return -EOPNOTSUPP; |
62 | 41 | } | |
63 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | ||
64 | } | 42 | } |
65 | 43 | ||
66 | static int iwm_wext_giwfreq(struct net_device *dev, | 44 | static int iwm_wext_giwfreq(struct net_device *dev, |
@@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_device *dev, | |||
69 | { | 47 | { |
70 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 48 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
71 | 49 | ||
72 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 50 | switch (iwm->conf.mode) { |
51 | case UMAC_MODE_IBSS: | ||
73 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); | 52 | return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); |
74 | 53 | case UMAC_MODE_BSS: | |
75 | freq->e = 0; | 54 | return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); |
76 | freq->m = iwm->channel; | 55 | default: |
77 | 56 | return -EOPNOTSUPP; | |
78 | return 0; | 57 | } |
79 | } | 58 | } |
80 | 59 | ||
81 | static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, | 60 | static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, |
82 | struct sockaddr *ap_addr, char *extra) | 61 | struct sockaddr *ap_addr, char *extra) |
83 | { | 62 | { |
84 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 63 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
85 | int ret; | ||
86 | |||
87 | IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); | ||
88 | 64 | ||
89 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 65 | switch (iwm->conf.mode) { |
66 | case UMAC_MODE_IBSS: | ||
90 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); | 67 | return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); |
91 | 68 | case UMAC_MODE_BSS: | |
92 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 69 | return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); |
93 | return -EIO; | 70 | default: |
94 | 71 | return -EOPNOTSUPP; | |
95 | if (is_zero_ether_addr(ap_addr->sa_data) || | ||
96 | is_broadcast_ether_addr(ap_addr->sa_data)) { | ||
97 | IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n", | ||
98 | iwm->umac_profile->bssid[0]); | ||
99 | memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); | ||
100 | iwm->umac_profile->bss_num = 0; | ||
101 | } else { | ||
102 | IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n", | ||
103 | ap_addr->sa_data); | ||
104 | memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data, | ||
105 | ETH_ALEN); | ||
106 | iwm->umac_profile->bss_num = 1; | ||
107 | } | ||
108 | |||
109 | if (iwm->umac_profile_active) { | ||
110 | int i; | ||
111 | |||
112 | if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN)) | ||
113 | return 0; | ||
114 | |||
115 | /* | ||
116 | * If we're clearing the BSSID, and we're associated, | ||
117 | * we have to clear the keys as they're no longer valid. | ||
118 | */ | ||
119 | if (is_zero_ether_addr(ap_addr->sa_data)) { | ||
120 | for (i = 0; i < IWM_NUM_KEYS; i++) | ||
121 | iwm->keys[i].key_len = 0; | ||
122 | } | ||
123 | |||
124 | ret = iwm_invalidate_mlme_profile(iwm); | ||
125 | if (ret < 0) { | ||
126 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
127 | return ret; | ||
128 | } | ||
129 | } | 72 | } |
130 | |||
131 | if (iwm->umac_profile->ssid.ssid_len) | ||
132 | return iwm_send_mlme_profile(iwm); | ||
133 | |||
134 | return 0; | ||
135 | } | 73 | } |
136 | 74 | ||
137 | static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, | 75 | static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, |
@@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, | |||
143 | case UMAC_MODE_IBSS: | 81 | case UMAC_MODE_IBSS: |
144 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); | 82 | return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); |
145 | case UMAC_MODE_BSS: | 83 | case UMAC_MODE_BSS: |
146 | if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { | 84 | return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); |
147 | ap_addr->sa_family = ARPHRD_ETHER; | ||
148 | memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN); | ||
149 | } else | ||
150 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | ||
151 | break; | ||
152 | default: | 85 | default: |
153 | return -EOPNOTSUPP; | 86 | return -EOPNOTSUPP; |
154 | } | 87 | } |
155 | |||
156 | return 0; | ||
157 | } | 88 | } |
158 | 89 | ||
159 | static int iwm_wext_siwessid(struct net_device *dev, | 90 | static int iwm_wext_siwessid(struct net_device *dev, |
@@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_device *dev, | |||
161 | struct iw_point *data, char *ssid) | 92 | struct iw_point *data, char *ssid) |
162 | { | 93 | { |
163 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 94 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
164 | size_t len = data->length; | ||
165 | int ret; | ||
166 | |||
167 | IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); | ||
168 | 95 | ||
169 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 96 | switch (iwm->conf.mode) { |
97 | case UMAC_MODE_IBSS: | ||
170 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); | 98 | return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); |
171 | 99 | case UMAC_MODE_BSS: | |
172 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 100 | return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); |
173 | return -EIO; | 101 | default: |
174 | 102 | return -EOPNOTSUPP; | |
175 | if (len > 0 && ssid[len - 1] == '\0') | ||
176 | len--; | ||
177 | |||
178 | if (iwm->umac_profile_active) { | ||
179 | if (iwm->umac_profile->ssid.ssid_len == len && | ||
180 | !memcmp(iwm->umac_profile->ssid.ssid, ssid, len)) | ||
181 | return 0; | ||
182 | |||
183 | ret = iwm_invalidate_mlme_profile(iwm); | ||
184 | if (ret < 0) { | ||
185 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
186 | return ret; | ||
187 | } | ||
188 | } | 103 | } |
189 | |||
190 | iwm->umac_profile->ssid.ssid_len = len; | ||
191 | memcpy(iwm->umac_profile->ssid.ssid, ssid, len); | ||
192 | |||
193 | return iwm_send_mlme_profile(iwm); | ||
194 | } | 104 | } |
195 | 105 | ||
196 | static int iwm_wext_giwessid(struct net_device *dev, | 106 | static int iwm_wext_giwessid(struct net_device *dev, |
@@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_device *dev, | |||
199 | { | 109 | { |
200 | struct iwm_priv *iwm = ndev_to_iwm(dev); | 110 | struct iwm_priv *iwm = ndev_to_iwm(dev); |
201 | 111 | ||
202 | if (iwm->conf.mode == UMAC_MODE_IBSS) | 112 | switch (iwm->conf.mode) { |
113 | case UMAC_MODE_IBSS: | ||
203 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); | 114 | return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); |
204 | 115 | case UMAC_MODE_BSS: | |
205 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 116 | return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); |
206 | return -EIO; | ||
207 | |||
208 | data->length = iwm->umac_profile->ssid.ssid_len; | ||
209 | if (data->length) { | ||
210 | memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length); | ||
211 | data->flags = 1; | ||
212 | } else | ||
213 | data->flags = 0; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int iwm_wext_giwrate(struct net_device *dev, | ||
219 | struct iw_request_info *info, | ||
220 | struct iw_param *rate, char *extra) | ||
221 | { | ||
222 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
223 | |||
224 | rate->value = iwm->rate * 1000000; | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) | ||
230 | { | ||
231 | if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) | ||
232 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; | ||
233 | else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) | ||
234 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; | ||
235 | else | ||
236 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) | ||
242 | { | ||
243 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
244 | |||
245 | IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); | ||
246 | |||
247 | if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) | ||
248 | *auth_type = UMAC_AUTH_TYPE_8021X; | ||
249 | else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { | ||
250 | if (iwm->umac_profile->sec.flags & | ||
251 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) | ||
252 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
253 | else | ||
254 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
255 | } else { | ||
256 | IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); | ||
257 | return -EINVAL; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast) | ||
264 | { | ||
265 | u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : | ||
266 | &iwm->umac_profile->sec.mcast_cipher; | ||
267 | |||
268 | switch (cipher) { | ||
269 | case IW_AUTH_CIPHER_NONE: | ||
270 | *profile_cipher = UMAC_CIPHER_TYPE_NONE; | ||
271 | break; | ||
272 | case IW_AUTH_CIPHER_WEP40: | ||
273 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; | ||
274 | break; | ||
275 | case IW_AUTH_CIPHER_TKIP: | ||
276 | *profile_cipher = UMAC_CIPHER_TYPE_TKIP; | ||
277 | break; | ||
278 | case IW_AUTH_CIPHER_CCMP: | ||
279 | *profile_cipher = UMAC_CIPHER_TYPE_CCMP; | ||
280 | break; | ||
281 | case IW_AUTH_CIPHER_WEP104: | ||
282 | *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; | ||
283 | break; | ||
284 | default: | ||
285 | IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); | ||
286 | return -ENOTSUPP; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) | ||
293 | { | ||
294 | u8 *auth_type = &iwm->umac_profile->sec.auth_type; | ||
295 | |||
296 | IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); | ||
297 | |||
298 | switch (auth_alg) { | ||
299 | case IW_AUTH_ALG_OPEN_SYSTEM: | ||
300 | *auth_type = UMAC_AUTH_TYPE_OPEN; | ||
301 | break; | ||
302 | case IW_AUTH_ALG_SHARED_KEY: | ||
303 | if (iwm->umac_profile->sec.flags & | ||
304 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { | ||
305 | if (*auth_type == UMAC_AUTH_TYPE_8021X) | ||
306 | return -EINVAL; | ||
307 | *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; | ||
308 | } else { | ||
309 | IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); | ||
310 | *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
311 | } | ||
312 | break; | ||
313 | case IW_AUTH_ALG_LEAP: | ||
314 | default: | ||
315 | IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg); | ||
316 | return -ENOTSUPP; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int iwm_wext_siwauth(struct net_device *dev, | ||
323 | struct iw_request_info *info, | ||
324 | struct iw_param *data, char *extra) | ||
325 | { | ||
326 | struct iwm_priv *iwm = ndev_to_iwm(dev); | ||
327 | int ret; | ||
328 | |||
329 | if ((data->flags) & | ||
330 | (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT | | ||
331 | IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) { | ||
332 | /* We need to invalidate the current profile */ | ||
333 | if (iwm->umac_profile_active) { | ||
334 | ret = iwm_invalidate_mlme_profile(iwm); | ||
335 | if (ret < 0) { | ||
336 | IWM_ERR(iwm, "Couldn't invalidate profile\n"); | ||
337 | return ret; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | switch (data->flags & IW_AUTH_INDEX) { | ||
343 | case IW_AUTH_WPA_VERSION: | ||
344 | return iwm_set_wpa_version(iwm, data->value); | ||
345 | break; | ||
346 | case IW_AUTH_CIPHER_PAIRWISE: | ||
347 | return iwm_set_cipher(iwm, data->value, 1); | ||
348 | break; | ||
349 | case IW_AUTH_CIPHER_GROUP: | ||
350 | return iwm_set_cipher(iwm, data->value, 0); | ||
351 | break; | ||
352 | case IW_AUTH_KEY_MGMT: | ||
353 | return iwm_set_key_mgt(iwm, data->value); | ||
354 | break; | ||
355 | case IW_AUTH_80211_AUTH_ALG: | ||
356 | return iwm_set_auth_alg(iwm, data->value); | ||
357 | break; | ||
358 | default: | 117 | default: |
359 | return -ENOTSUPP; | 118 | return -EOPNOTSUPP; |
360 | } | 119 | } |
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int iwm_wext_giwauth(struct net_device *dev, | ||
366 | struct iw_request_info *info, | ||
367 | struct iw_param *data, char *extra) | ||
368 | { | ||
369 | return 0; | ||
370 | } | 120 | } |
371 | 121 | ||
372 | static const iw_handler iwm_handlers[] = | 122 | static const iw_handler iwm_handlers[] = |
@@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] = | |||
404 | (iw_handler) NULL, /* -- hole -- */ | 154 | (iw_handler) NULL, /* -- hole -- */ |
405 | (iw_handler) NULL, /* -- hole -- */ | 155 | (iw_handler) NULL, /* -- hole -- */ |
406 | (iw_handler) NULL, /* SIOCSIWRATE */ | 156 | (iw_handler) NULL, /* SIOCSIWRATE */ |
407 | (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */ | 157 | (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ |
408 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ | 158 | (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ |
409 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ | 159 | (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ |
410 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ | 160 | (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ |
@@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] = | |||
419 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ | 169 | (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ |
420 | (iw_handler) NULL, /* -- hole -- */ | 170 | (iw_handler) NULL, /* -- hole -- */ |
421 | (iw_handler) NULL, /* -- hole -- */ | 171 | (iw_handler) NULL, /* -- hole -- */ |
422 | (iw_handler) NULL, /* SIOCSIWGENIE */ | 172 | (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ |
423 | (iw_handler) NULL, /* SIOCGIWGENIE */ | 173 | (iw_handler) NULL, /* SIOCGIWGENIE */ |
424 | (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ | 174 | (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ |
425 | (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ | 175 | (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ |
426 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ | 176 | (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ |
427 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ | 177 | (iw_handler) NULL, /* SIOCGIWENCODEEXT */ |
428 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 178 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
@@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] = | |||
432 | const struct iw_handler_def iwm_iw_handler_def = { | 182 | const struct iw_handler_def iwm_iw_handler_def = { |
433 | .num_standard = ARRAY_SIZE(iwm_handlers), | 183 | .num_standard = ARRAY_SIZE(iwm_handlers), |
434 | .standard = (iw_handler *) iwm_handlers, | 184 | .standard = (iw_handler *) iwm_handlers, |
435 | .get_wireless_stats = iwm_get_wireless_stats, | 185 | .get_wireless_stats = cfg80211_wireless_stats, |
436 | }; | 186 | }; |
437 | 187 | ||
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index fbf26499c9a9..385b50f4b105 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -129,7 +129,6 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth | |||
129 | { | 129 | { |
130 | struct cmd_ds_802_11_authenticate cmd; | 130 | struct cmd_ds_802_11_authenticate cmd; |
131 | int ret = -1; | 131 | int ret = -1; |
132 | DECLARE_MAC_BUF(mac); | ||
133 | 132 | ||
134 | lbs_deb_enter(LBS_DEB_JOIN); | 133 | lbs_deb_enter(LBS_DEB_JOIN); |
135 | 134 | ||
@@ -138,8 +137,7 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth | |||
138 | 137 | ||
139 | cmd.authtype = iw_auth_to_ieee_auth(auth); | 138 | cmd.authtype = iw_auth_to_ieee_auth(auth); |
140 | 139 | ||
141 | lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", | 140 | lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype); |
142 | print_mac(mac, bssid), cmd.authtype); | ||
143 | 141 | ||
144 | ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); | 142 | ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); |
145 | 143 | ||
@@ -342,8 +340,6 @@ static int lbs_associate(struct lbs_private *priv, | |||
342 | 340 | ||
343 | /* Firmware v9+ indicate authentication suites as a TLV */ | 341 | /* Firmware v9+ indicate authentication suites as a TLV */ |
344 | if (priv->fwrelease >= 0x09000000) { | 342 | if (priv->fwrelease >= 0x09000000) { |
345 | DECLARE_MAC_BUF(mac); | ||
346 | |||
347 | auth = (struct mrvl_ie_auth_type *) pos; | 343 | auth = (struct mrvl_ie_auth_type *) pos; |
348 | auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | 344 | auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); |
349 | auth->header.len = cpu_to_le16(2); | 345 | auth->header.len = cpu_to_le16(2); |
@@ -351,8 +347,8 @@ static int lbs_associate(struct lbs_private *priv, | |||
351 | auth->auth = cpu_to_le16(tmpauth); | 347 | auth->auth = cpu_to_le16(tmpauth); |
352 | pos += sizeof(auth->header) + 2; | 348 | pos += sizeof(auth->header) + 2; |
353 | 349 | ||
354 | lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", | 350 | lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", |
355 | print_mac(mac, bss->bssid), priv->secinfo.auth_mode); | 351 | bss->bssid, priv->secinfo.auth_mode); |
356 | } | 352 | } |
357 | 353 | ||
358 | /* WPA/WPA2 IEs */ | 354 | /* WPA/WPA2 IEs */ |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e9b5442f1dda..930f5c7da4a6 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -406,7 +406,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
406 | rx_status.freq = data->channel->center_freq; | 406 | rx_status.freq = data->channel->center_freq; |
407 | rx_status.band = data->channel->band; | 407 | rx_status.band = data->channel->band; |
408 | rx_status.rate_idx = info->control.rates[0].idx; | 408 | rx_status.rate_idx = info->control.rates[0].idx; |
409 | /* TODO: simulate signal strength (and optional packet drop) */ | 409 | /* TODO: simulate real signal strength (and optional packet loss) */ |
410 | rx_status.signal = -50; | ||
410 | 411 | ||
411 | if (data->ps != PS_DISABLED) | 412 | if (data->ps != PS_DISABLED) |
412 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 413 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
@@ -836,7 +837,6 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
836 | { | 837 | { |
837 | struct mac80211_hwsim_data *data = dat; | 838 | struct mac80211_hwsim_data *data = dat; |
838 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 839 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
839 | DECLARE_MAC_BUF(buf); | ||
840 | struct sk_buff *skb; | 840 | struct sk_buff *skb; |
841 | struct ieee80211_pspoll *pspoll; | 841 | struct ieee80211_pspoll *pspoll; |
842 | 842 | ||
@@ -866,7 +866,6 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | |||
866 | struct ieee80211_vif *vif, int ps) | 866 | struct ieee80211_vif *vif, int ps) |
867 | { | 867 | { |
868 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; | 868 | struct hwsim_vif_priv *vp = (void *)vif->drv_priv; |
869 | DECLARE_MAC_BUF(buf); | ||
870 | struct sk_buff *skb; | 869 | struct sk_buff *skb; |
871 | struct ieee80211_hdr *hdr; | 870 | struct ieee80211_hdr *hdr; |
872 | 871 | ||
@@ -1024,7 +1023,8 @@ static int __init init_mac80211_hwsim(void) | |||
1024 | BIT(NL80211_IFTYPE_AP) | | 1023 | BIT(NL80211_IFTYPE_AP) | |
1025 | BIT(NL80211_IFTYPE_MESH_POINT); | 1024 | BIT(NL80211_IFTYPE_MESH_POINT); |
1026 | 1025 | ||
1027 | hw->flags = IEEE80211_HW_MFP_CAPABLE; | 1026 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
1027 | IEEE80211_HW_SIGNAL_DBM; | ||
1028 | 1028 | ||
1029 | /* ask mac80211 to reserve space for magic */ | 1029 | /* ask mac80211 to reserve space for magic */ |
1030 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1030 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b9eded88c322..4f725473fb73 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -2271,7 +2271,6 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | |||
2271 | struct mwl8k_cmd_update_sta_db *cmd; | 2271 | struct mwl8k_cmd_update_sta_db *cmd; |
2272 | struct peer_capability_info *peer_info; | 2272 | struct peer_capability_info *peer_info; |
2273 | struct ieee80211_rate *bitrates = mv_vif->legacy_rates; | 2273 | struct ieee80211_rate *bitrates = mv_vif->legacy_rates; |
2274 | DECLARE_MAC_BUF(mac); | ||
2275 | int rc; | 2274 | int rc; |
2276 | __u8 count, *rates; | 2275 | __u8 count, *rates; |
2277 | 2276 | ||
@@ -3480,7 +3479,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3480 | { | 3479 | { |
3481 | struct ieee80211_hw *hw; | 3480 | struct ieee80211_hw *hw; |
3482 | struct mwl8k_priv *priv; | 3481 | struct mwl8k_priv *priv; |
3483 | DECLARE_MAC_BUF(mac); | ||
3484 | int rc; | 3482 | int rc; |
3485 | int i; | 3483 | int i; |
3486 | u8 *fw; | 3484 | u8 *fw; |
@@ -3669,8 +3667,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3669 | MWL8K_DESC); | 3667 | MWL8K_DESC); |
3670 | printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n", | 3668 | printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n", |
3671 | priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]); | 3669 | priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]); |
3672 | printk(KERN_INFO "%s: MAC Address: %s\n", priv->name, | 3670 | printk(KERN_INFO "%s: MAC Address: %pM\n", priv->name, |
3673 | print_mac(mac, hw->wiphy->perm_addr)); | 3671 | hw->wiphy->perm_addr); |
3674 | 3672 | ||
3675 | return 0; | 3673 | return 0; |
3676 | 3674 | ||
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index a2a044ef1012..0efe67deedee 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
21 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
22 | #include <linux/sort.h> | ||
22 | 23 | ||
23 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
24 | 25 | ||
@@ -41,30 +42,6 @@ static struct ieee80211_rate p54_bgrates[] = { | |||
41 | { .bitrate = 540, .hw_value = 11, }, | 42 | { .bitrate = 540, .hw_value = 11, }, |
42 | }; | 43 | }; |
43 | 44 | ||
44 | static struct ieee80211_channel p54_bgchannels[] = { | ||
45 | { .center_freq = 2412, .hw_value = 1, }, | ||
46 | { .center_freq = 2417, .hw_value = 2, }, | ||
47 | { .center_freq = 2422, .hw_value = 3, }, | ||
48 | { .center_freq = 2427, .hw_value = 4, }, | ||
49 | { .center_freq = 2432, .hw_value = 5, }, | ||
50 | { .center_freq = 2437, .hw_value = 6, }, | ||
51 | { .center_freq = 2442, .hw_value = 7, }, | ||
52 | { .center_freq = 2447, .hw_value = 8, }, | ||
53 | { .center_freq = 2452, .hw_value = 9, }, | ||
54 | { .center_freq = 2457, .hw_value = 10, }, | ||
55 | { .center_freq = 2462, .hw_value = 11, }, | ||
56 | { .center_freq = 2467, .hw_value = 12, }, | ||
57 | { .center_freq = 2472, .hw_value = 13, }, | ||
58 | { .center_freq = 2484, .hw_value = 14, }, | ||
59 | }; | ||
60 | |||
61 | static struct ieee80211_supported_band band_2GHz = { | ||
62 | .channels = p54_bgchannels, | ||
63 | .n_channels = ARRAY_SIZE(p54_bgchannels), | ||
64 | .bitrates = p54_bgrates, | ||
65 | .n_bitrates = ARRAY_SIZE(p54_bgrates), | ||
66 | }; | ||
67 | |||
68 | static struct ieee80211_rate p54_arates[] = { | 45 | static struct ieee80211_rate p54_arates[] = { |
69 | { .bitrate = 60, .hw_value = 4, }, | 46 | { .bitrate = 60, .hw_value = 4, }, |
70 | { .bitrate = 90, .hw_value = 5, }, | 47 | { .bitrate = 90, .hw_value = 5, }, |
@@ -76,51 +53,257 @@ static struct ieee80211_rate p54_arates[] = { | |||
76 | { .bitrate = 540, .hw_value = 11, }, | 53 | { .bitrate = 540, .hw_value = 11, }, |
77 | }; | 54 | }; |
78 | 55 | ||
79 | static struct ieee80211_channel p54_achannels[] = { | 56 | #define CHAN_HAS_CAL BIT(0) |
80 | { .center_freq = 4920 }, | 57 | #define CHAN_HAS_LIMIT BIT(1) |
81 | { .center_freq = 4940 }, | 58 | #define CHAN_HAS_CURVE BIT(2) |
82 | { .center_freq = 4960 }, | 59 | #define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE) |
83 | { .center_freq = 4980 }, | 60 | |
84 | { .center_freq = 5040 }, | 61 | struct p54_channel_entry { |
85 | { .center_freq = 5060 }, | 62 | u16 freq; |
86 | { .center_freq = 5080 }, | 63 | u16 data; |
87 | { .center_freq = 5170 }, | 64 | int index; |
88 | { .center_freq = 5180 }, | 65 | enum ieee80211_band band; |
89 | { .center_freq = 5190 }, | ||
90 | { .center_freq = 5200 }, | ||
91 | { .center_freq = 5210 }, | ||
92 | { .center_freq = 5220 }, | ||
93 | { .center_freq = 5230 }, | ||
94 | { .center_freq = 5240 }, | ||
95 | { .center_freq = 5260 }, | ||
96 | { .center_freq = 5280 }, | ||
97 | { .center_freq = 5300 }, | ||
98 | { .center_freq = 5320 }, | ||
99 | { .center_freq = 5500 }, | ||
100 | { .center_freq = 5520 }, | ||
101 | { .center_freq = 5540 }, | ||
102 | { .center_freq = 5560 }, | ||
103 | { .center_freq = 5580 }, | ||
104 | { .center_freq = 5600 }, | ||
105 | { .center_freq = 5620 }, | ||
106 | { .center_freq = 5640 }, | ||
107 | { .center_freq = 5660 }, | ||
108 | { .center_freq = 5680 }, | ||
109 | { .center_freq = 5700 }, | ||
110 | { .center_freq = 5745 }, | ||
111 | { .center_freq = 5765 }, | ||
112 | { .center_freq = 5785 }, | ||
113 | { .center_freq = 5805 }, | ||
114 | { .center_freq = 5825 }, | ||
115 | }; | 66 | }; |
116 | 67 | ||
117 | static struct ieee80211_supported_band band_5GHz = { | 68 | struct p54_channel_list { |
118 | .channels = p54_achannels, | 69 | struct p54_channel_entry *channels; |
119 | .n_channels = ARRAY_SIZE(p54_achannels), | 70 | size_t entries; |
120 | .bitrates = p54_arates, | 71 | size_t max_entries; |
121 | .n_bitrates = ARRAY_SIZE(p54_arates), | 72 | size_t band_channel_num[IEEE80211_NUM_BANDS]; |
122 | }; | 73 | }; |
123 | 74 | ||
75 | static int p54_get_band_from_freq(u16 freq) | ||
76 | { | ||
77 | /* FIXME: sync these values with the 802.11 spec */ | ||
78 | |||
79 | if ((freq >= 2412) && (freq <= 2484)) | ||
80 | return IEEE80211_BAND_2GHZ; | ||
81 | |||
82 | if ((freq >= 4920) && (freq <= 5825)) | ||
83 | return IEEE80211_BAND_5GHZ; | ||
84 | |||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | static int p54_compare_channels(const void *_a, | ||
89 | const void *_b) | ||
90 | { | ||
91 | const struct p54_channel_entry *a = _a; | ||
92 | const struct p54_channel_entry *b = _b; | ||
93 | |||
94 | return a->index - b->index; | ||
95 | } | ||
96 | |||
97 | static int p54_fill_band_bitrates(struct ieee80211_hw *dev, | ||
98 | struct ieee80211_supported_band *band_entry, | ||
99 | enum ieee80211_band band) | ||
100 | { | ||
101 | /* TODO: generate rate array dynamically */ | ||
102 | |||
103 | switch (band) { | ||
104 | case IEEE80211_BAND_2GHZ: | ||
105 | band_entry->bitrates = p54_bgrates; | ||
106 | band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); | ||
107 | break; | ||
108 | case IEEE80211_BAND_5GHZ: | ||
109 | band_entry->bitrates = p54_arates; | ||
110 | band_entry->n_bitrates = ARRAY_SIZE(p54_arates); | ||
111 | break; | ||
112 | default: | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int p54_generate_band(struct ieee80211_hw *dev, | ||
120 | struct p54_channel_list *list, | ||
121 | enum ieee80211_band band) | ||
122 | { | ||
123 | struct p54_common *priv = dev->priv; | ||
124 | struct ieee80211_supported_band *tmp, *old; | ||
125 | unsigned int i, j; | ||
126 | int ret = -ENOMEM; | ||
127 | |||
128 | if ((!list->entries) || (!list->band_channel_num[band])) | ||
129 | return 0; | ||
130 | |||
131 | tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); | ||
132 | if (!tmp) | ||
133 | goto err_out; | ||
134 | |||
135 | tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * | ||
136 | list->band_channel_num[band], GFP_KERNEL); | ||
137 | if (!tmp->channels) | ||
138 | goto err_out; | ||
139 | |||
140 | ret = p54_fill_band_bitrates(dev, tmp, band); | ||
141 | if (ret) | ||
142 | goto err_out; | ||
143 | |||
144 | for (i = 0, j = 0; (j < list->band_channel_num[band]) && | ||
145 | (i < list->entries); i++) { | ||
146 | |||
147 | if (list->channels[i].band != band) | ||
148 | continue; | ||
149 | |||
150 | if (list->channels[i].data != CHAN_HAS_ALL) { | ||
151 | printk(KERN_ERR "%s:%s%s%s is/are missing for " | ||
152 | "channel:%d [%d MHz].\n", | ||
153 | wiphy_name(dev->wiphy), | ||
154 | (list->channels[i].data & CHAN_HAS_CAL ? "" : | ||
155 | " [iqauto calibration data]"), | ||
156 | (list->channels[i].data & CHAN_HAS_LIMIT ? "" : | ||
157 | " [output power limits]"), | ||
158 | (list->channels[i].data & CHAN_HAS_CURVE ? "" : | ||
159 | " [curve data]"), | ||
160 | list->channels[i].index, list->channels[i].freq); | ||
161 | } | ||
162 | |||
163 | tmp->channels[j].band = list->channels[i].band; | ||
164 | tmp->channels[j].center_freq = list->channels[i].freq; | ||
165 | j++; | ||
166 | } | ||
167 | |||
168 | tmp->n_channels = list->band_channel_num[band]; | ||
169 | old = priv->band_table[band]; | ||
170 | priv->band_table[band] = tmp; | ||
171 | if (old) { | ||
172 | kfree(old->channels); | ||
173 | kfree(old); | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | |||
178 | err_out: | ||
179 | if (tmp) { | ||
180 | kfree(tmp->channels); | ||
181 | kfree(tmp); | ||
182 | } | ||
183 | |||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static void p54_update_channel_param(struct p54_channel_list *list, | ||
188 | u16 freq, u16 data) | ||
189 | { | ||
190 | int band, i; | ||
191 | |||
192 | /* | ||
193 | * usually all lists in the eeprom are mostly sorted. | ||
194 | * so it's very likely that the entry we are looking for | ||
195 | * is right at the end of the list | ||
196 | */ | ||
197 | for (i = list->entries; i >= 0; i--) { | ||
198 | if (freq == list->channels[i].freq) { | ||
199 | list->channels[i].data |= data; | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | if ((i < 0) && (list->entries < list->max_entries)) { | ||
205 | /* entry does not exist yet. Initialize a new one. */ | ||
206 | band = p54_get_band_from_freq(freq); | ||
207 | |||
208 | /* | ||
209 | * filter out frequencies which don't belong into | ||
210 | * any supported band. | ||
211 | */ | ||
212 | if (band < 0) | ||
213 | return ; | ||
214 | |||
215 | i = list->entries++; | ||
216 | list->band_channel_num[band]++; | ||
217 | |||
218 | list->channels[i].freq = freq; | ||
219 | list->channels[i].data = data; | ||
220 | list->channels[i].band = band; | ||
221 | list->channels[i].index = ieee80211_frequency_to_channel(freq); | ||
222 | /* TODO: parse output_limit and fill max_power */ | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static int p54_generate_channel_lists(struct ieee80211_hw *dev) | ||
227 | { | ||
228 | struct p54_common *priv = dev->priv; | ||
229 | struct p54_channel_list *list; | ||
230 | unsigned int i, j, max_channel_num; | ||
231 | int ret = -ENOMEM; | ||
232 | u16 freq; | ||
233 | |||
234 | if ((priv->iq_autocal_len != priv->curve_data->entries) || | ||
235 | (priv->iq_autocal_len != priv->output_limit->entries)) | ||
236 | printk(KERN_ERR "%s: EEPROM is damaged... you may not be able" | ||
237 | "to use all channels with this device.\n", | ||
238 | wiphy_name(dev->wiphy)); | ||
239 | |||
240 | max_channel_num = max_t(unsigned int, priv->output_limit->entries, | ||
241 | priv->iq_autocal_len); | ||
242 | max_channel_num = max_t(unsigned int, max_channel_num, | ||
243 | priv->curve_data->entries); | ||
244 | |||
245 | list = kzalloc(sizeof(*list), GFP_KERNEL); | ||
246 | if (!list) | ||
247 | goto free; | ||
248 | |||
249 | list->max_entries = max_channel_num; | ||
250 | list->channels = kzalloc(sizeof(struct p54_channel_entry) * | ||
251 | max_channel_num, GFP_KERNEL); | ||
252 | if (!list->channels) | ||
253 | goto free; | ||
254 | |||
255 | for (i = 0; i < max_channel_num; i++) { | ||
256 | if (i < priv->iq_autocal_len) { | ||
257 | freq = le16_to_cpu(priv->iq_autocal[i].freq); | ||
258 | p54_update_channel_param(list, freq, CHAN_HAS_CAL); | ||
259 | } | ||
260 | |||
261 | if (i < priv->output_limit->entries) { | ||
262 | freq = le16_to_cpup((__le16 *) (i * | ||
263 | priv->output_limit->entry_size + | ||
264 | priv->output_limit->offset + | ||
265 | priv->output_limit->data)); | ||
266 | |||
267 | p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); | ||
268 | } | ||
269 | |||
270 | if (i < priv->curve_data->entries) { | ||
271 | freq = le16_to_cpup((__le16 *) (i * | ||
272 | priv->curve_data->entry_size + | ||
273 | priv->curve_data->offset + | ||
274 | priv->curve_data->data)); | ||
275 | |||
276 | p54_update_channel_param(list, freq, CHAN_HAS_CURVE); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* sort the list by the channel index */ | ||
281 | sort(list->channels, list->entries, sizeof(struct p54_channel_entry), | ||
282 | p54_compare_channels, NULL); | ||
283 | |||
284 | for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
285 | if (list->band_channel_num[i]) { | ||
286 | ret = p54_generate_band(dev, list, i); | ||
287 | if (ret) | ||
288 | goto free; | ||
289 | |||
290 | j++; | ||
291 | } | ||
292 | } | ||
293 | if (j == 0) { | ||
294 | /* no useable band available. */ | ||
295 | ret = -EINVAL; | ||
296 | } | ||
297 | |||
298 | free: | ||
299 | if (list) { | ||
300 | kfree(list->channels); | ||
301 | kfree(list); | ||
302 | } | ||
303 | |||
304 | return ret; | ||
305 | } | ||
306 | |||
124 | static int p54_convert_rev0(struct ieee80211_hw *dev, | 307 | static int p54_convert_rev0(struct ieee80211_hw *dev, |
125 | struct pda_pa_curve_data *curve_data) | 308 | struct pda_pa_curve_data *curve_data) |
126 | { | 309 | { |
@@ -346,7 +529,7 @@ static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src, | |||
346 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | 529 | int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) |
347 | { | 530 | { |
348 | struct p54_common *priv = dev->priv; | 531 | struct p54_common *priv = dev->priv; |
349 | struct eeprom_pda_wrap *wrap = NULL; | 532 | struct eeprom_pda_wrap *wrap; |
350 | struct pda_entry *entry; | 533 | struct pda_entry *entry; |
351 | unsigned int data_len, entry_len; | 534 | unsigned int data_len, entry_len; |
352 | void *tmp; | 535 | void *tmp; |
@@ -487,13 +670,19 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
487 | goto err; | 670 | goto err; |
488 | } | 671 | } |
489 | 672 | ||
673 | err = p54_generate_channel_lists(dev); | ||
674 | if (err) | ||
675 | goto err; | ||
676 | |||
490 | priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; | 677 | priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; |
491 | if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) | 678 | if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) |
492 | p54_init_xbow_synth(priv); | 679 | p54_init_xbow_synth(priv); |
493 | if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) | 680 | if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) |
494 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; | 681 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = |
682 | priv->band_table[IEEE80211_BAND_2GHZ]; | ||
495 | if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) | 683 | if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) |
496 | dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; | 684 | dev->wiphy->bands[IEEE80211_BAND_5GHZ] = |
685 | priv->band_table[IEEE80211_BAND_5GHZ]; | ||
497 | if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) | 686 | if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) |
498 | priv->rx_diversity_mask = 3; | 687 | priv->rx_diversity_mask = 3; |
499 | if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) | 688 | if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) |
@@ -533,7 +722,7 @@ int p54_read_eeprom(struct ieee80211_hw *dev) | |||
533 | struct p54_common *priv = dev->priv; | 722 | struct p54_common *priv = dev->priv; |
534 | size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize; | 723 | size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize; |
535 | int ret = -ENOMEM; | 724 | int ret = -ENOMEM; |
536 | void *eeprom = NULL; | 725 | void *eeprom; |
537 | 726 | ||
538 | maxblocksize = EEPROM_READBACK_LEN; | 727 | maxblocksize = EEPROM_READBACK_LEN; |
539 | if (priv->fw_var >= 0x509) | 728 | if (priv->fw_var >= 0x509) |
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index dc4f3f5ee0c8..21f19018fab5 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c | |||
@@ -585,7 +585,8 @@ int p54_set_ps(struct p54_common *priv) | |||
585 | unsigned int i; | 585 | unsigned int i; |
586 | u16 mode; | 586 | u16 mode; |
587 | 587 | ||
588 | if (priv->hw->conf.flags & IEEE80211_CONF_PS) | 588 | if (priv->hw->conf.flags & IEEE80211_CONF_PS && |
589 | !priv->powersave_override) | ||
589 | mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | | 590 | mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | |
590 | P54_PSM_CHECKSUM | P54_PSM_MCBC; | 591 | P54_PSM_CHECKSUM | P54_PSM_MCBC; |
591 | else | 592 | else |
@@ -607,8 +608,8 @@ int p54_set_ps(struct p54_common *priv) | |||
607 | 608 | ||
608 | psm->beacon_rssi_skip_max = 200; | 609 | psm->beacon_rssi_skip_max = 200; |
609 | psm->rssi_delta_threshold = 0; | 610 | psm->rssi_delta_threshold = 0; |
610 | psm->nr = 10; | 611 | psm->nr = 1; |
611 | psm->exclude[0] = 0; | 612 | psm->exclude[0] = WLAN_EID_TIM; |
612 | 613 | ||
613 | p54_tx(priv, skb); | 614 | p54_tx(priv, skb); |
614 | return 0; | 615 | return 0; |
@@ -685,6 +686,8 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, | |||
685 | 686 | ||
686 | int p54_fetch_statistics(struct p54_common *priv) | 687 | int p54_fetch_statistics(struct p54_common *priv) |
687 | { | 688 | { |
689 | struct ieee80211_tx_info *txinfo; | ||
690 | struct p54_tx_info *p54info; | ||
688 | struct sk_buff *skb; | 691 | struct sk_buff *skb; |
689 | 692 | ||
690 | skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, | 693 | skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, |
@@ -693,6 +696,20 @@ int p54_fetch_statistics(struct p54_common *priv) | |||
693 | if (!skb) | 696 | if (!skb) |
694 | return -ENOMEM; | 697 | return -ENOMEM; |
695 | 698 | ||
699 | /* | ||
700 | * The statistic feedback causes some extra headaches here, if it | ||
701 | * is not to crash/corrupt the firmware data structures. | ||
702 | * | ||
703 | * Unlike all other Control Get OIDs we can not use helpers like | ||
704 | * skb_put to reserve the space for the data we're requesting. | ||
705 | * Instead the extra frame length -which will hold the results later- | ||
706 | * will only be told to the p54_assign_address, so that following | ||
707 | * frames won't be placed into the allegedly empty area. | ||
708 | */ | ||
709 | txinfo = IEEE80211_SKB_CB(skb); | ||
710 | p54info = (void *) txinfo->rate_driver_data; | ||
711 | p54info->extra_len = sizeof(struct p54_statistics); | ||
712 | |||
696 | p54_tx(priv, skb); | 713 | p54_tx(priv, skb); |
697 | return 0; | 714 | return 0; |
698 | } | 715 | } |
diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h index 0496cff26b35..04b63ec80fa4 100644 --- a/drivers/net/wireless/p54/lmac.h +++ b/drivers/net/wireless/p54/lmac.h | |||
@@ -98,6 +98,10 @@ struct p54_hdr { | |||
98 | (!((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ | 98 | (!((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ |
99 | flags) & cpu_to_le16(P54_HDR_FLAG_CONTROL))) | 99 | flags) & cpu_to_le16(P54_HDR_FLAG_CONTROL))) |
100 | 100 | ||
101 | #define GET_HW_QUEUE(skb) \ | ||
102 | (((struct p54_tx_data *)((struct p54_hdr *) \ | ||
103 | skb->data)->data)->hw_queue) | ||
104 | |||
101 | /* | 105 | /* |
102 | * shared interface ID definitions | 106 | * shared interface ID definitions |
103 | * The interface ID is a unique identification of a specific interface. | 107 | * The interface ID is a unique identification of a specific interface. |
@@ -548,4 +552,7 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot, | |||
548 | int p54_download_eeprom(struct p54_common *priv, void *buf, | 552 | int p54_download_eeprom(struct p54_common *priv, void *buf, |
549 | u16 offset, u16 len); | 553 | u16 offset, u16 len); |
550 | 554 | ||
555 | /* utility */ | ||
556 | u8 *p54_find_ie(struct sk_buff *skb, u8 ie); | ||
557 | |||
551 | #endif /* LMAC_H */ | 558 | #endif /* LMAC_H */ |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index f9b4f6a238ea..955f6d7ec16a 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -65,51 +65,64 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, | |||
65 | return p54_update_beacon_tim(priv, sta->aid, set); | 65 | return p54_update_beacon_tim(priv, sta->aid, set); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int p54_beacon_format_ie_tim(struct sk_buff *skb) | 68 | u8 *p54_find_ie(struct sk_buff *skb, u8 ie) |
69 | { | 69 | { |
70 | /* | ||
71 | * the good excuse for this mess is ... the firmware. | ||
72 | * The dummy TIM MUST be at the end of the beacon frame, | ||
73 | * because it'll be overwritten! | ||
74 | */ | ||
75 | |||
76 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | 70 | struct ieee80211_mgmt *mgmt = (void *)skb->data; |
77 | u8 *pos, *end; | 71 | u8 *pos, *end; |
78 | 72 | ||
79 | if (skb->len <= sizeof(mgmt)) | 73 | if (skb->len <= sizeof(mgmt)) |
80 | return -EINVAL; | 74 | return NULL; |
81 | 75 | ||
82 | pos = (u8 *)mgmt->u.beacon.variable; | 76 | pos = (u8 *)mgmt->u.beacon.variable; |
83 | end = skb->data + skb->len; | 77 | end = skb->data + skb->len; |
84 | while (pos < end) { | 78 | while (pos < end) { |
85 | if (pos + 2 + pos[1] > end) | 79 | if (pos + 2 + pos[1] > end) |
86 | return -EINVAL; | 80 | return NULL; |
81 | |||
82 | if (pos[0] == ie) | ||
83 | return pos; | ||
84 | |||
85 | pos += 2 + pos[1]; | ||
86 | } | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | static int p54_beacon_format_ie_tim(struct sk_buff *skb) | ||
91 | { | ||
92 | /* | ||
93 | * the good excuse for this mess is ... the firmware. | ||
94 | * The dummy TIM MUST be at the end of the beacon frame, | ||
95 | * because it'll be overwritten! | ||
96 | */ | ||
97 | u8 *tim; | ||
98 | u8 dtim_len; | ||
99 | u8 dtim_period; | ||
100 | u8 *next; | ||
87 | 101 | ||
88 | if (pos[0] == WLAN_EID_TIM) { | 102 | tim = p54_find_ie(skb, WLAN_EID_TIM); |
89 | u8 dtim_len = pos[1]; | 103 | if (!tim) |
90 | u8 dtim_period = pos[3]; | 104 | return 0; |
91 | u8 *next = pos + 2 + dtim_len; | ||
92 | 105 | ||
93 | if (dtim_len < 3) | 106 | dtim_len = tim[1]; |
94 | return -EINVAL; | 107 | dtim_period = tim[3]; |
108 | next = tim + 2 + dtim_len; | ||
95 | 109 | ||
96 | memmove(pos, next, end - next); | 110 | if (dtim_len < 3) |
111 | return -EINVAL; | ||
97 | 112 | ||
98 | if (dtim_len > 3) | 113 | memmove(tim, next, skb_tail_pointer(skb) - next); |
99 | skb_trim(skb, skb->len - (dtim_len - 3)); | 114 | tim = skb_tail_pointer(skb) - (dtim_len + 2); |
100 | 115 | ||
101 | pos = end - (dtim_len + 2); | 116 | /* add the dummy at the end */ |
117 | tim[0] = WLAN_EID_TIM; | ||
118 | tim[1] = 3; | ||
119 | tim[2] = 0; | ||
120 | tim[3] = dtim_period; | ||
121 | tim[4] = 0; | ||
122 | |||
123 | if (dtim_len > 3) | ||
124 | skb_trim(skb, skb->len - (dtim_len - 3)); | ||
102 | 125 | ||
103 | /* add the dummy at the end */ | ||
104 | pos[0] = WLAN_EID_TIM; | ||
105 | pos[1] = 3; | ||
106 | pos[2] = 0; | ||
107 | pos[3] = dtim_period; | ||
108 | pos[4] = 0; | ||
109 | return 0; | ||
110 | } | ||
111 | pos += 2 + pos[1]; | ||
112 | } | ||
113 | return 0; | 126 | return 0; |
114 | } | 127 | } |
115 | 128 | ||
@@ -117,7 +130,6 @@ static int p54_beacon_update(struct p54_common *priv, | |||
117 | struct ieee80211_vif *vif) | 130 | struct ieee80211_vif *vif) |
118 | { | 131 | { |
119 | struct sk_buff *beacon; | 132 | struct sk_buff *beacon; |
120 | __le32 old_beacon_req_id; | ||
121 | int ret; | 133 | int ret; |
122 | 134 | ||
123 | beacon = ieee80211_beacon_get(priv->hw, vif); | 135 | beacon = ieee80211_beacon_get(priv->hw, vif); |
@@ -127,15 +139,16 @@ static int p54_beacon_update(struct p54_common *priv, | |||
127 | if (ret) | 139 | if (ret) |
128 | return ret; | 140 | return ret; |
129 | 141 | ||
130 | old_beacon_req_id = priv->beacon_req_id; | 142 | /* |
131 | priv->beacon_req_id = GET_REQ_ID(beacon); | 143 | * During operation, the firmware takes care of beaconing. |
132 | 144 | * The driver only needs to upload a new beacon template, once | |
133 | ret = p54_tx_80211(priv->hw, beacon); | 145 | * the template was changed by the stack or userspace. |
134 | if (ret) { | 146 | * |
135 | priv->beacon_req_id = old_beacon_req_id; | 147 | * LMAC API 3.2.2 also specifies that the driver does not need |
136 | return -ENOSPC; | 148 | * to cancel the old beacon template by hand, instead the firmware |
137 | } | 149 | * will release the previous one through the feedback mechanism. |
138 | 150 | */ | |
151 | WARN_ON(p54_tx_80211(priv->hw, beacon)); | ||
139 | priv->tsf_high32 = 0; | 152 | priv->tsf_high32 = 0; |
140 | priv->tsf_low32 = 0; | 153 | priv->tsf_low32 = 0; |
141 | 154 | ||
@@ -240,9 +253,14 @@ static void p54_remove_interface(struct ieee80211_hw *dev, | |||
240 | 253 | ||
241 | mutex_lock(&priv->conf_mutex); | 254 | mutex_lock(&priv->conf_mutex); |
242 | priv->vif = NULL; | 255 | priv->vif = NULL; |
243 | if (priv->beacon_req_id) { | 256 | |
257 | /* | ||
258 | * LMAC API 3.2.2 states that any active beacon template must be | ||
259 | * canceled by the driver before attempting a mode transition. | ||
260 | */ | ||
261 | if (le32_to_cpu(priv->beacon_req_id) != 0) { | ||
244 | p54_tx_cancel(priv, priv->beacon_req_id); | 262 | p54_tx_cancel(priv, priv->beacon_req_id); |
245 | priv->beacon_req_id = cpu_to_le32(0); | 263 | wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ); |
246 | } | 264 | } |
247 | priv->mode = NL80211_IFTYPE_MONITOR; | 265 | priv->mode = NL80211_IFTYPE_MONITOR; |
248 | memset(priv->mac_addr, 0, ETH_ALEN); | 266 | memset(priv->mac_addr, 0, ETH_ALEN); |
@@ -384,6 +402,9 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, | |||
384 | priv->wakeup_timer = info->beacon_int * | 402 | priv->wakeup_timer = info->beacon_int * |
385 | info->dtim_period * 5; | 403 | info->dtim_period * 5; |
386 | p54_setup_mac(priv); | 404 | p54_setup_mac(priv); |
405 | } else { | ||
406 | priv->wakeup_timer = 500; | ||
407 | priv->aid = 0; | ||
387 | } | 408 | } |
388 | } | 409 | } |
389 | 410 | ||
@@ -517,6 +538,9 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
517 | skb_queue_head_init(&priv->tx_pending); | 538 | skb_queue_head_init(&priv->tx_pending); |
518 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 539 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
519 | IEEE80211_HW_SIGNAL_DBM | | 540 | IEEE80211_HW_SIGNAL_DBM | |
541 | IEEE80211_HW_SUPPORTS_PS | | ||
542 | IEEE80211_HW_PS_NULLFUNC_STACK | | ||
543 | IEEE80211_HW_BEACON_FILTER | | ||
520 | IEEE80211_HW_NOISE_DBM; | 544 | IEEE80211_HW_NOISE_DBM; |
521 | 545 | ||
522 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 546 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
@@ -525,6 +549,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
525 | BIT(NL80211_IFTYPE_MESH_POINT); | 549 | BIT(NL80211_IFTYPE_MESH_POINT); |
526 | 550 | ||
527 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 551 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
552 | priv->beacon_req_id = cpu_to_le32(0); | ||
528 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; | 553 | priv->tx_stats[P54_QUEUE_BEACON].limit = 1; |
529 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; | 554 | priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; |
530 | priv->tx_stats[P54_QUEUE_MGMT].limit = 3; | 555 | priv->tx_stats[P54_QUEUE_MGMT].limit = 3; |
@@ -548,6 +573,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
548 | mutex_init(&priv->conf_mutex); | 573 | mutex_init(&priv->conf_mutex); |
549 | mutex_init(&priv->eeprom_mutex); | 574 | mutex_init(&priv->eeprom_mutex); |
550 | init_completion(&priv->eeprom_comp); | 575 | init_completion(&priv->eeprom_comp); |
576 | init_completion(&priv->beacon_comp); | ||
551 | INIT_DELAYED_WORK(&priv->work, p54_work); | 577 | INIT_DELAYED_WORK(&priv->work, p54_work); |
552 | 578 | ||
553 | return dev; | 579 | return dev; |
@@ -579,6 +605,10 @@ EXPORT_SYMBOL_GPL(p54_register_common); | |||
579 | void p54_free_common(struct ieee80211_hw *dev) | 605 | void p54_free_common(struct ieee80211_hw *dev) |
580 | { | 606 | { |
581 | struct p54_common *priv = dev->priv; | 607 | struct p54_common *priv = dev->priv; |
608 | unsigned int i; | ||
609 | |||
610 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
611 | kfree(priv->band_table[i]); | ||
582 | 612 | ||
583 | kfree(priv->iq_autocal); | 613 | kfree(priv->iq_autocal); |
584 | kfree(priv->output_limit); | 614 | kfree(priv->output_limit); |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 19d085c73d7d..1afc39410e85 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -198,6 +198,7 @@ struct p54_common { | |||
198 | struct p54_cal_database *curve_data; | 198 | struct p54_cal_database *curve_data; |
199 | struct p54_cal_database *output_limit; | 199 | struct p54_cal_database *output_limit; |
200 | struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; | 200 | struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; |
201 | struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; | ||
201 | 202 | ||
202 | /* BBP/MAC state */ | 203 | /* BBP/MAC state */ |
203 | u8 mac_addr[ETH_ALEN]; | 204 | u8 mac_addr[ETH_ALEN]; |
@@ -208,7 +209,9 @@ struct p54_common { | |||
208 | u32 tsf_low32, tsf_high32; | 209 | u32 tsf_low32, tsf_high32; |
209 | u32 basic_rate_mask; | 210 | u32 basic_rate_mask; |
210 | u16 aid; | 211 | u16 aid; |
212 | bool powersave_override; | ||
211 | __le32 beacon_req_id; | 213 | __le32 beacon_req_id; |
214 | struct completion beacon_comp; | ||
212 | 215 | ||
213 | /* cryptographic engine information */ | 216 | /* cryptographic engine information */ |
214 | u8 privacy_caps; | 217 | u8 privacy_caps; |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 6426d2cae6de..0d589d68e547 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -87,9 +87,6 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) | |||
87 | u32 target_addr = priv->rx_start; | 87 | u32 target_addr = priv->rx_start; |
88 | u16 len = priv->headroom + skb->len + priv->tailroom + 3; | 88 | u16 len = priv->headroom + skb->len + priv->tailroom + 3; |
89 | 89 | ||
90 | if (unlikely(WARN_ON(!skb || !priv))) | ||
91 | return -EINVAL; | ||
92 | |||
93 | info = IEEE80211_SKB_CB(skb); | 90 | info = IEEE80211_SKB_CB(skb); |
94 | range = (void *) info->rate_driver_data; | 91 | range = (void *) info->rate_driver_data; |
95 | len = (range->extra_len + len) & ~0x3; | 92 | len = (range->extra_len + len) & ~0x3; |
@@ -111,11 +108,6 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) | |||
111 | range = (void *) info->rate_driver_data; | 108 | range = (void *) info->rate_driver_data; |
112 | hole_size = range->start_addr - last_addr; | 109 | hole_size = range->start_addr - last_addr; |
113 | 110 | ||
114 | if (!entry->next) { | ||
115 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
116 | return -ENOSPC; | ||
117 | } | ||
118 | |||
119 | if (!target_skb && hole_size >= len) { | 111 | if (!target_skb && hole_size >= len) { |
120 | target_skb = entry->prev; | 112 | target_skb = entry->prev; |
121 | hole_size -= len; | 113 | hole_size -= len; |
@@ -142,9 +134,13 @@ static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) | |||
142 | range = (void *) info->rate_driver_data; | 134 | range = (void *) info->rate_driver_data; |
143 | range->start_addr = target_addr; | 135 | range->start_addr = target_addr; |
144 | range->end_addr = target_addr + len; | 136 | range->end_addr = target_addr + len; |
137 | data->req_id = cpu_to_le32(target_addr + priv->headroom); | ||
138 | if (IS_DATA_FRAME(skb) && | ||
139 | unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) | ||
140 | priv->beacon_req_id = data->req_id; | ||
141 | |||
145 | __skb_queue_after(&priv->tx_queue, target_skb, skb); | 142 | __skb_queue_after(&priv->tx_queue, target_skb, skb); |
146 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 143 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
147 | data->req_id = cpu_to_le32(target_addr + priv->headroom); | ||
148 | return 0; | 144 | return 0; |
149 | } | 145 | } |
150 | 146 | ||
@@ -153,9 +149,6 @@ static void p54_tx_pending(struct p54_common *priv) | |||
153 | struct sk_buff *skb; | 149 | struct sk_buff *skb; |
154 | int ret; | 150 | int ret; |
155 | 151 | ||
156 | if (unlikely(WARN_ON(!priv))) | ||
157 | return ; | ||
158 | |||
159 | skb = skb_dequeue(&priv->tx_pending); | 152 | skb = skb_dequeue(&priv->tx_pending); |
160 | if (unlikely(!skb)) | 153 | if (unlikely(!skb)) |
161 | return ; | 154 | return ; |
@@ -219,14 +212,20 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, | |||
219 | static void p54_tx_qos_accounting_free(struct p54_common *priv, | 212 | static void p54_tx_qos_accounting_free(struct p54_common *priv, |
220 | struct sk_buff *skb) | 213 | struct sk_buff *skb) |
221 | { | 214 | { |
222 | if (skb && IS_DATA_FRAME(skb)) { | 215 | if (IS_DATA_FRAME(skb)) { |
223 | struct p54_hdr *hdr = (void *) skb->data; | ||
224 | struct p54_tx_data *data = (void *) hdr->data; | ||
225 | unsigned long flags; | 216 | unsigned long flags; |
226 | 217 | ||
227 | spin_lock_irqsave(&priv->tx_stats_lock, flags); | 218 | spin_lock_irqsave(&priv->tx_stats_lock, flags); |
228 | priv->tx_stats[data->hw_queue].len--; | 219 | priv->tx_stats[GET_HW_QUEUE(skb)].len--; |
229 | spin_unlock_irqrestore(&priv->tx_stats_lock, flags); | 220 | spin_unlock_irqrestore(&priv->tx_stats_lock, flags); |
221 | |||
222 | if (unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) { | ||
223 | if (priv->beacon_req_id == GET_REQ_ID(skb)) { | ||
224 | /* this is the active beacon set anymore */ | ||
225 | priv->beacon_req_id = 0; | ||
226 | } | ||
227 | complete(&priv->beacon_comp); | ||
228 | } | ||
230 | } | 229 | } |
231 | p54_wake_queues(priv); | 230 | p54_wake_queues(priv); |
232 | } | 231 | } |
@@ -266,9 +265,6 @@ static struct sk_buff *p54_find_and_unlink_skb(struct p54_common *priv, | |||
266 | 265 | ||
267 | void p54_tx(struct p54_common *priv, struct sk_buff *skb) | 266 | void p54_tx(struct p54_common *priv, struct sk_buff *skb) |
268 | { | 267 | { |
269 | if (unlikely(WARN_ON(!priv))) | ||
270 | return ; | ||
271 | |||
272 | skb_queue_tail(&priv->tx_pending, skb); | 268 | skb_queue_tail(&priv->tx_pending, skb); |
273 | p54_tx_pending(priv); | 269 | p54_tx_pending(priv); |
274 | } | 270 | } |
@@ -288,6 +284,45 @@ static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) | |||
288 | priv->rssical_db[band].add) / 4; | 284 | priv->rssical_db[band].add) / 4; |
289 | } | 285 | } |
290 | 286 | ||
287 | /* | ||
288 | * Even if the firmware is capable of dealing with incoming traffic, | ||
289 | * while dozing, we have to prepared in case mac80211 uses PS-POLL | ||
290 | * to retrieve outstanding frames from our AP. | ||
291 | * (see comment in net/mac80211/mlme.c @ line 1993) | ||
292 | */ | ||
293 | static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb) | ||
294 | { | ||
295 | struct ieee80211_hdr *hdr = (void *) skb->data; | ||
296 | struct ieee80211_tim_ie *tim_ie; | ||
297 | u8 *tim; | ||
298 | u8 tim_len; | ||
299 | bool new_psm; | ||
300 | |||
301 | /* only beacons have a TIM IE */ | ||
302 | if (!ieee80211_is_beacon(hdr->frame_control)) | ||
303 | return; | ||
304 | |||
305 | if (!priv->aid) | ||
306 | return; | ||
307 | |||
308 | /* only consider beacons from the associated BSSID */ | ||
309 | if (compare_ether_addr(hdr->addr3, priv->bssid)) | ||
310 | return; | ||
311 | |||
312 | tim = p54_find_ie(skb, WLAN_EID_TIM); | ||
313 | if (!tim) | ||
314 | return; | ||
315 | |||
316 | tim_len = tim[1]; | ||
317 | tim_ie = (struct ieee80211_tim_ie *) &tim[2]; | ||
318 | |||
319 | new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid); | ||
320 | if (new_psm != priv->powersave_override) { | ||
321 | priv->powersave_override = new_psm; | ||
322 | p54_set_ps(priv); | ||
323 | } | ||
324 | } | ||
325 | |||
291 | static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) | 326 | static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) |
292 | { | 327 | { |
293 | struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; | 328 | struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; |
@@ -340,6 +375,9 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) | |||
340 | 375 | ||
341 | skb_pull(skb, header_len); | 376 | skb_pull(skb, header_len); |
342 | skb_trim(skb, le16_to_cpu(hdr->len)); | 377 | skb_trim(skb, le16_to_cpu(hdr->len)); |
378 | if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS)) | ||
379 | p54_pspoll_workaround(priv, skb); | ||
380 | |||
343 | ieee80211_rx_irqsafe(priv->hw, skb); | 381 | ieee80211_rx_irqsafe(priv->hw, skb); |
344 | 382 | ||
345 | queue_delayed_work(priv->hw->workqueue, &priv->work, | 383 | queue_delayed_work(priv->hw->workqueue, &priv->work, |
@@ -375,10 +413,6 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) | |||
375 | * and we don't want to confuse the mac80211 stack. | 413 | * and we don't want to confuse the mac80211 stack. |
376 | */ | 414 | */ |
377 | if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) { | 415 | if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) { |
378 | if (entry_data->hw_queue == P54_QUEUE_BEACON && | ||
379 | hdr->req_id == priv->beacon_req_id) | ||
380 | priv->beacon_req_id = cpu_to_le32(0); | ||
381 | |||
382 | dev_kfree_skb_any(entry); | 416 | dev_kfree_skb_any(entry); |
383 | return ; | 417 | return ; |
384 | } | 418 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d8035e3575e8..30185ad28d93 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1561,6 +1561,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1561 | .remove_interface = rt2x00mac_remove_interface, | 1561 | .remove_interface = rt2x00mac_remove_interface, |
1562 | .config = rt2x00mac_config, | 1562 | .config = rt2x00mac_config, |
1563 | .configure_filter = rt2x00mac_configure_filter, | 1563 | .configure_filter = rt2x00mac_configure_filter, |
1564 | .set_tim = rt2x00mac_set_tim, | ||
1564 | .get_stats = rt2x00mac_get_stats, | 1565 | .get_stats = rt2x00mac_get_stats, |
1565 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1566 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1566 | .conf_tx = rt2400pci_conf_tx, | 1567 | .conf_tx = rt2400pci_conf_tx, |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index ec3b004ddc3c..ccd644104ad1 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h | |||
@@ -928,7 +928,7 @@ | |||
928 | #define RXD_W7_RESERVED FIELD32(0xffffffff) | 928 | #define RXD_W7_RESERVED FIELD32(0xffffffff) |
929 | 929 | ||
930 | /* | 930 | /* |
931 | * Macro's for converting txpower from EEPROM to mac80211 value | 931 | * Macros for converting txpower from EEPROM to mac80211 value |
932 | * and from mac80211 value to register value. | 932 | * and from mac80211 value to register value. |
933 | * NOTE: Logics in rt2400pci for txpower are reversed | 933 | * NOTE: Logics in rt2400pci for txpower are reversed |
934 | * compared to the other rt2x00 drivers. A higher txpower | 934 | * compared to the other rt2x00 drivers. A higher txpower |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index c123e28396d0..3b3171578b14 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1860,6 +1860,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1860 | .remove_interface = rt2x00mac_remove_interface, | 1860 | .remove_interface = rt2x00mac_remove_interface, |
1861 | .config = rt2x00mac_config, | 1861 | .config = rt2x00mac_config, |
1862 | .configure_filter = rt2x00mac_configure_filter, | 1862 | .configure_filter = rt2x00mac_configure_filter, |
1863 | .set_tim = rt2x00mac_set_tim, | ||
1863 | .get_stats = rt2x00mac_get_stats, | 1864 | .get_stats = rt2x00mac_get_stats, |
1864 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1865 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1865 | .conf_tx = rt2x00mac_conf_tx, | 1866 | .conf_tx = rt2x00mac_conf_tx, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index ce2f065c7486..54d37957883c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h | |||
@@ -1218,7 +1218,7 @@ | |||
1218 | #define RXD_W10_DROP FIELD32(0x00000001) | 1218 | #define RXD_W10_DROP FIELD32(0x00000001) |
1219 | 1219 | ||
1220 | /* | 1220 | /* |
1221 | * Macro's for converting txpower from EEPROM to mac80211 value | 1221 | * Macros for converting txpower from EEPROM to mac80211 value |
1222 | * and from mac80211 value to register value. | 1222 | * and from mac80211 value to register value. |
1223 | */ | 1223 | */ |
1224 | #define MIN_TXPOWER 0 | 1224 | #define MIN_TXPOWER 0 |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 00611b32d08b..de48c5c68eff 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1896,6 +1896,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { | |||
1896 | .remove_interface = rt2x00mac_remove_interface, | 1896 | .remove_interface = rt2x00mac_remove_interface, |
1897 | .config = rt2x00mac_config, | 1897 | .config = rt2x00mac_config, |
1898 | .configure_filter = rt2x00mac_configure_filter, | 1898 | .configure_filter = rt2x00mac_configure_filter, |
1899 | .set_tim = rt2x00mac_set_tim, | ||
1899 | .set_key = rt2x00mac_set_key, | 1900 | .set_key = rt2x00mac_set_key, |
1900 | .get_stats = rt2x00mac_get_stats, | 1901 | .get_stats = rt2x00mac_get_stats, |
1901 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1902 | .bss_info_changed = rt2x00mac_bss_info_changed, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 5bc46fe72179..b01edca42583 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h | |||
@@ -831,7 +831,7 @@ | |||
831 | #define RXD_W3_EIV FIELD32(0xffffffff) | 831 | #define RXD_W3_EIV FIELD32(0xffffffff) |
832 | 832 | ||
833 | /* | 833 | /* |
834 | * Macro's for converting txpower from EEPROM to mac80211 value | 834 | * Macros for converting txpower from EEPROM to mac80211 value |
835 | * and from mac80211 value to register value. | 835 | * and from mac80211 value to register value. |
836 | */ | 836 | */ |
837 | #define MIN_TXPOWER 0 | 837 | #define MIN_TXPOWER 0 |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index a204e66753c2..9efb41710508 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1910,7 +1910,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1910 | /* | 1910 | /* |
1911 | * Before the radio can be enabled, the device first has | 1911 | * Before the radio can be enabled, the device first has |
1912 | * to be woken up. After that it needs a bit of time | 1912 | * to be woken up. After that it needs a bit of time |
1913 | * to be fully awake and the radio can be enabled. | 1913 | * to be fully awake and then the radio can be enabled. |
1914 | */ | 1914 | */ |
1915 | rt2800usb_set_state(rt2x00dev, STATE_AWAKE); | 1915 | rt2800usb_set_state(rt2x00dev, STATE_AWAKE); |
1916 | msleep(1); | 1916 | msleep(1); |
@@ -1918,7 +1918,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
1918 | break; | 1918 | break; |
1919 | case STATE_RADIO_OFF: | 1919 | case STATE_RADIO_OFF: |
1920 | /* | 1920 | /* |
1921 | * After the radio has been disablee, the device should | 1921 | * After the radio has been disabled, the device should |
1922 | * be put to sleep for powersaving. | 1922 | * be put to sleep for powersaving. |
1923 | */ | 1923 | */ |
1924 | rt2800usb_disable_radio(rt2x00dev); | 1924 | rt2800usb_disable_radio(rt2x00dev); |
@@ -2220,10 +2220,8 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2220 | */ | 2220 | */ |
2221 | mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); | 2221 | mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); |
2222 | if (!is_valid_ether_addr(mac)) { | 2222 | if (!is_valid_ether_addr(mac)) { |
2223 | DECLARE_MAC_BUF(macbuf); | ||
2224 | |||
2225 | random_ether_addr(mac); | 2223 | random_ether_addr(mac); |
2226 | EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); | 2224 | EEPROM(rt2x00dev, "MAC: %pM\n", mac); |
2227 | } | 2225 | } |
2228 | 2226 | ||
2229 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); | 2227 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); |
@@ -2786,6 +2784,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = { | |||
2786 | .remove_interface = rt2x00mac_remove_interface, | 2784 | .remove_interface = rt2x00mac_remove_interface, |
2787 | .config = rt2x00mac_config, | 2785 | .config = rt2x00mac_config, |
2788 | .configure_filter = rt2x00mac_configure_filter, | 2786 | .configure_filter = rt2x00mac_configure_filter, |
2787 | .set_tim = rt2x00mac_set_tim, | ||
2789 | .set_key = rt2x00mac_set_key, | 2788 | .set_key = rt2x00mac_set_key, |
2790 | .get_stats = rt2x00mac_get_stats, | 2789 | .get_stats = rt2x00mac_get_stats, |
2791 | .get_tkip_seq = rt2800usb_get_tkip_seq, | 2790 | .get_tkip_seq = rt2800usb_get_tkip_seq, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 61a8be61d3f5..2d9dc3783361 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h | |||
@@ -1921,7 +1921,7 @@ struct mac_iveiv_entry { | |||
1921 | #define RXWI_W3_SNR1 FIELD32(0x0000ff00) | 1921 | #define RXWI_W3_SNR1 FIELD32(0x0000ff00) |
1922 | 1922 | ||
1923 | /* | 1923 | /* |
1924 | * Macro's for converting txpower from EEPROM to mac80211 value | 1924 | * Macros for converting txpower from EEPROM to mac80211 value |
1925 | * and from mac80211 value to register value. | 1925 | * and from mac80211 value to register value. |
1926 | */ | 1926 | */ |
1927 | #define MIN_G_TXPOWER 0 | 1927 | #define MIN_G_TXPOWER 0 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 71f37cb476b0..cbec91ef6f76 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -245,7 +245,7 @@ struct link_ant { | |||
245 | struct antenna_setup active; | 245 | struct antenna_setup active; |
246 | 246 | ||
247 | /* | 247 | /* |
248 | * RSSI information for the different antenna's. | 248 | * RSSI information for the different antennas. |
249 | * These statistics are used to determine when | 249 | * These statistics are used to determine when |
250 | * to switch antenna when using software diversity. | 250 | * to switch antenna when using software diversity. |
251 | * | 251 | * |
@@ -594,7 +594,6 @@ enum rt2x00_flags { | |||
594 | DEVICE_STATE_INITIALIZED, | 594 | DEVICE_STATE_INITIALIZED, |
595 | DEVICE_STATE_STARTED, | 595 | DEVICE_STATE_STARTED, |
596 | DEVICE_STATE_ENABLED_RADIO, | 596 | DEVICE_STATE_ENABLED_RADIO, |
597 | DEVICE_STATE_DISABLED_RADIO_HW, | ||
598 | 597 | ||
599 | /* | 598 | /* |
600 | * Driver requirements | 599 | * Driver requirements |
@@ -634,7 +633,7 @@ struct rt2x00_dev { | |||
634 | * The structure stored in here depends on the | 633 | * The structure stored in here depends on the |
635 | * system bus (PCI or USB). | 634 | * system bus (PCI or USB). |
636 | * When accessing this variable, the rt2x00dev_{pci,usb} | 635 | * When accessing this variable, the rt2x00dev_{pci,usb} |
637 | * macro's should be used for correct typecasting. | 636 | * macros should be used for correct typecasting. |
638 | */ | 637 | */ |
639 | struct device *dev; | 638 | struct device *dev; |
640 | 639 | ||
@@ -963,6 +962,8 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
963 | unsigned int changed_flags, | 962 | unsigned int changed_flags, |
964 | unsigned int *total_flags, | 963 | unsigned int *total_flags, |
965 | int mc_count, struct dev_addr_list *mc_list); | 964 | int mc_count, struct dev_addr_list *mc_list); |
965 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
966 | bool set); | ||
966 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 967 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
967 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 968 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
968 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 969 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 3e019a12df2e..c6e0bcf78e9e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -132,7 +132,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
132 | /* | 132 | /* |
133 | * Failsafe: Make sure we are not sending the | 133 | * Failsafe: Make sure we are not sending the |
134 | * ANTENNA_SW_DIVERSITY state to the driver. | 134 | * ANTENNA_SW_DIVERSITY state to the driver. |
135 | * If that happes fallback to hardware default, | 135 | * If that happens, fallback to hardware defaults, |
136 | * or our own default. | 136 | * or our own default. |
137 | * The calls to rt2x00lib_config_antenna_check() | 137 | * The calls to rt2x00lib_config_antenna_check() |
138 | * might have caused that we restore back to the already | 138 | * might have caused that we restore back to the already |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index c54eda3c2db0..30fbd3bbe08b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -129,7 +129,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) | |||
129 | /* Pull buffer to correct size */ | 129 | /* Pull buffer to correct size */ |
130 | skb_pull(skb, txdesc->iv_len); | 130 | skb_pull(skb, txdesc->iv_len); |
131 | 131 | ||
132 | /* IV/EIV data has officially be stripped */ | 132 | /* IV/EIV data has officially been stripped */ |
133 | skbdesc->flags |= SKBDESC_IV_STRIPPED; | 133 | skbdesc->flags |= SKBDESC_IV_STRIPPED; |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 4fff3a83f7df..658a63bfb761 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -40,8 +40,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
40 | * Don't enable the radio twice. | 40 | * Don't enable the radio twice. |
41 | * And check if the hardware button has been disabled. | 41 | * And check if the hardware button has been disabled. |
42 | */ | 42 | */ |
43 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 43 | if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) |
44 | test_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags)) | ||
45 | return 0; | 44 | return 0; |
46 | 45 | ||
47 | /* | 46 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index eb9b981b9139..32570758e67c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c | |||
@@ -158,7 +158,7 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) | |||
158 | 158 | ||
159 | /* | 159 | /* |
160 | * During the last period we have sampled the RSSI | 160 | * During the last period we have sampled the RSSI |
161 | * from both antenna's. It now is time to determine | 161 | * from both antennas. It now is time to determine |
162 | * which antenna demonstrated the best performance. | 162 | * which antenna demonstrated the best performance. |
163 | * When we are already on the antenna with the best | 163 | * When we are already on the antenna with the best |
164 | * performance, then there really is nothing for us | 164 | * performance, then there really is nothing for us |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index b7e0ddda38f5..9d31c23b92fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -341,7 +341,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) | |||
341 | int status; | 341 | int status; |
342 | 342 | ||
343 | /* | 343 | /* |
344 | * Mac80211 might be calling this function while we are trying | 344 | * mac80211 might be calling this function while we are trying |
345 | * to remove the device or perhaps suspending it. | 345 | * to remove the device or perhaps suspending it. |
346 | */ | 346 | */ |
347 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 347 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
@@ -454,6 +454,16 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) | |||
454 | sizeof(crypto->rx_mic)); | 454 | sizeof(crypto->rx_mic)); |
455 | } | 455 | } |
456 | 456 | ||
457 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | ||
458 | bool set) | ||
459 | { | ||
460 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
461 | |||
462 | rt2x00lib_beacondone(rt2x00dev); | ||
463 | return 0; | ||
464 | } | ||
465 | EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); | ||
466 | |||
457 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 467 | int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
458 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 468 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
459 | struct ieee80211_key_conf *key) | 469 | struct ieee80211_key_conf *key) |
@@ -577,7 +587,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
577 | int update_bssid = 0; | 587 | int update_bssid = 0; |
578 | 588 | ||
579 | /* | 589 | /* |
580 | * Mac80211 might be calling this function while we are trying | 590 | * mac80211 might be calling this function while we are trying |
581 | * to remove the device or perhaps suspending it. | 591 | * to remove the device or perhaps suspending it. |
582 | */ | 592 | */ |
583 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | 593 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index b5e06347c8a7..47d175a13790 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/prefetch.h> | 29 | #include <linux/prefetch.h> |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * DOC: Entrie frame size | 32 | * DOC: Entry frame size |
33 | * | 33 | * |
34 | * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, | 34 | * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, |
35 | * for USB devices this restriction does not apply, but the value of | 35 | * for USB devices this restriction does not apply, but the value of |
@@ -45,13 +45,13 @@ | |||
45 | /** | 45 | /** |
46 | * DOC: Number of entries per queue | 46 | * DOC: Number of entries per queue |
47 | * | 47 | * |
48 | * Under normal load without fragmentation 12 entries are sufficient | 48 | * Under normal load without fragmentation, 12 entries are sufficient |
49 | * without the queue being filled up to the maximum. When using fragmentation | 49 | * without the queue being filled up to the maximum. When using fragmentation |
50 | * and the queue threshold code we need to add some additional margins to | 50 | * and the queue threshold code, we need to add some additional margins to |
51 | * make sure the queue will never (or only under extreme load) fill up | 51 | * make sure the queue will never (or only under extreme load) fill up |
52 | * completely. | 52 | * completely. |
53 | * Since we don't use preallocated DMA having a large number of queue entries | 53 | * Since we don't use preallocated DMA, having a large number of queue entries |
54 | * will have only minimal impact on the memory requirements for the queue. | 54 | * will have minimal impact on the memory requirements for the queue. |
55 | */ | 55 | */ |
56 | #define RX_ENTRIES 24 | 56 | #define RX_ENTRIES 24 |
57 | #define TX_ENTRIES 24 | 57 | #define TX_ENTRIES 24 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index 861322d97fce..983e52e127a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h | |||
@@ -176,8 +176,8 @@ struct rt2x00_field32 { | |||
176 | #define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x)) | 176 | #define is_valid_mask(x) is_power_of_two(1LU + (x) + low_bit_mask(x)) |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Macro's to find first set bit in a variable. | 179 | * Macros to find first set bit in a variable. |
180 | * These macro's behaves the same as the __ffs() function with | 180 | * These macros behave the same as the __ffs() functions but |
181 | * the most important difference that this is done during | 181 | * the most important difference that this is done during |
182 | * compile-time rather then run-time. | 182 | * compile-time rather then run-time. |
183 | */ | 183 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 8a49d99df682..fb95b8cc4fe9 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2312,7 +2312,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2312 | } | 2312 | } |
2313 | 2313 | ||
2314 | /* | 2314 | /* |
2315 | * Determine number of antenna's. | 2315 | * Determine number of antennas. |
2316 | */ | 2316 | */ |
2317 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) | 2317 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) |
2318 | __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); | 2318 | __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); |
@@ -2716,6 +2716,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2716 | .remove_interface = rt2x00mac_remove_interface, | 2716 | .remove_interface = rt2x00mac_remove_interface, |
2717 | .config = rt2x00mac_config, | 2717 | .config = rt2x00mac_config, |
2718 | .configure_filter = rt2x00mac_configure_filter, | 2718 | .configure_filter = rt2x00mac_configure_filter, |
2719 | .set_tim = rt2x00mac_set_tim, | ||
2719 | .set_key = rt2x00mac_set_key, | 2720 | .set_key = rt2x00mac_set_key, |
2720 | .get_stats = rt2x00mac_get_stats, | 2721 | .get_stats = rt2x00mac_get_stats, |
2721 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2722 | .bss_info_changed = rt2x00mac_bss_info_changed, |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 6c71f77c8165..93eb699165cc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h | |||
@@ -1476,7 +1476,7 @@ struct hw_pairwise_ta_entry { | |||
1476 | #define RXD_W15_RESERVED FIELD32(0xffffffff) | 1476 | #define RXD_W15_RESERVED FIELD32(0xffffffff) |
1477 | 1477 | ||
1478 | /* | 1478 | /* |
1479 | * Macro's for converting txpower from EEPROM to mac80211 value | 1479 | * Macros for converting txpower from EEPROM to mac80211 value |
1480 | * and from mac80211 value to register value. | 1480 | * and from mac80211 value to register value. |
1481 | */ | 1481 | */ |
1482 | #define MIN_TXPOWER 0 | 1482 | #define MIN_TXPOWER 0 |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ad2898ca8677..4f9b1772e1a1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2241,6 +2241,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
2241 | .remove_interface = rt2x00mac_remove_interface, | 2241 | .remove_interface = rt2x00mac_remove_interface, |
2242 | .config = rt2x00mac_config, | 2242 | .config = rt2x00mac_config, |
2243 | .configure_filter = rt2x00mac_configure_filter, | 2243 | .configure_filter = rt2x00mac_configure_filter, |
2244 | .set_tim = rt2x00mac_set_tim, | ||
2244 | .set_key = rt2x00mac_set_key, | 2245 | .set_key = rt2x00mac_set_key, |
2245 | .get_stats = rt2x00mac_get_stats, | 2246 | .get_stats = rt2x00mac_get_stats, |
2246 | .bss_info_changed = rt2x00mac_bss_info_changed, | 2247 | .bss_info_changed = rt2x00mac_bss_info_changed, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index c8016f65b4bd..81fe0be51c42 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h | |||
@@ -809,7 +809,7 @@ struct hw_pairwise_ta_entry { | |||
809 | 809 | ||
810 | /* | 810 | /* |
811 | * EEPROM antenna. | 811 | * EEPROM antenna. |
812 | * ANTENNA_NUM: Number of antenna's. | 812 | * ANTENNA_NUM: Number of antennas. |
813 | * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. | 813 | * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. |
814 | * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. | 814 | * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. |
815 | * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only. | 815 | * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only. |
@@ -1058,7 +1058,7 @@ struct hw_pairwise_ta_entry { | |||
1058 | #define RXD_W5_RESERVED FIELD32(0xffffffff) | 1058 | #define RXD_W5_RESERVED FIELD32(0xffffffff) |
1059 | 1059 | ||
1060 | /* | 1060 | /* |
1061 | * Macro's for converting txpower from EEPROM to mac80211 value | 1061 | * Macros for converting txpower from EEPROM to mac80211 value |
1062 | * and from mac80211 value to register value. | 1062 | * and from mac80211 value to register value. |
1063 | */ | 1063 | */ |
1064 | #define MIN_TXPOWER 0 | 1064 | #define MIN_TXPOWER 0 |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 5a8d21c3192d..a46c92a29526 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -84,7 +84,7 @@ int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) | |||
84 | ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, | 84 | ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, |
85 | default_key, sizeof(*default_key)); | 85 | default_key, sizeof(*default_key)); |
86 | if (ret < 0) { | 86 | if (ret < 0) { |
87 | wl1251_error("Couldnt set default key"); | 87 | wl1251_error("Couldn't set default key"); |
88 | goto out; | 88 | goto out; |
89 | } | 89 | } |
90 | 90 | ||
@@ -231,7 +231,7 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl) | |||
231 | ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, | 231 | ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, |
232 | feature, sizeof(*feature)); | 232 | feature, sizeof(*feature)); |
233 | if (ret < 0) { | 233 | if (ret < 0) { |
234 | wl1251_error("Couldnt set HW encryption"); | 234 | wl1251_error("Couldn't set HW encryption"); |
235 | goto out; | 235 | goto out; |
236 | } | 236 | } |
237 | 237 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index cf5e0549fa14..da4c688c46af 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -246,60 +246,6 @@ out: | |||
246 | mutex_unlock(&wl->mutex); | 246 | mutex_unlock(&wl->mutex); |
247 | } | 247 | } |
248 | 248 | ||
249 | int wl1251_plt_start(struct wl1251 *wl) | ||
250 | { | ||
251 | int ret; | ||
252 | |||
253 | mutex_lock(&wl->mutex); | ||
254 | |||
255 | wl1251_notice("power up"); | ||
256 | |||
257 | if (wl->state != WL1251_STATE_OFF) { | ||
258 | wl1251_error("cannot go into PLT state because not " | ||
259 | "in off state: %d", wl->state); | ||
260 | return -EBUSY; | ||
261 | } | ||
262 | |||
263 | wl->state = WL1251_STATE_PLT; | ||
264 | |||
265 | ret = wl1251_chip_wakeup(wl); | ||
266 | if (ret < 0) | ||
267 | return ret; | ||
268 | |||
269 | ret = wl->chip.op_boot(wl); | ||
270 | if (ret < 0) | ||
271 | return ret; | ||
272 | |||
273 | wl1251_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
274 | |||
275 | ret = wl->chip.op_plt_init(wl); | ||
276 | if (ret < 0) | ||
277 | return ret; | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | int wl1251_plt_stop(struct wl1251 *wl) | ||
283 | { | ||
284 | mutex_lock(&wl->mutex); | ||
285 | |||
286 | wl1251_notice("power down"); | ||
287 | |||
288 | if (wl->state != WL1251_STATE_PLT) { | ||
289 | wl1251_error("cannot power down because not in PLT " | ||
290 | "state: %d", wl->state); | ||
291 | return -EBUSY; | ||
292 | } | ||
293 | |||
294 | wl1251_disable_interrupts(wl); | ||
295 | wl1251_power_off(wl); | ||
296 | |||
297 | wl->state = WL1251_STATE_OFF; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | |||
303 | static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 249 | static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
304 | { | 250 | { |
305 | struct wl1251 *wl = hw->priv; | 251 | struct wl1251 *wl = hw->priv; |
@@ -349,7 +295,7 @@ static int wl1251_op_start(struct ieee80211_hw *hw) | |||
349 | 295 | ||
350 | ret = wl1251_chip_wakeup(wl); | 296 | ret = wl1251_chip_wakeup(wl); |
351 | if (ret < 0) | 297 | if (ret < 0) |
352 | return ret; | 298 | goto out; |
353 | 299 | ||
354 | ret = wl->chip.op_boot(wl); | 300 | ret = wl->chip.op_boot(wl); |
355 | if (ret < 0) | 301 | if (ret < 0) |
@@ -435,11 +381,10 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
435 | struct ieee80211_if_init_conf *conf) | 381 | struct ieee80211_if_init_conf *conf) |
436 | { | 382 | { |
437 | struct wl1251 *wl = hw->priv; | 383 | struct wl1251 *wl = hw->priv; |
438 | DECLARE_MAC_BUF(mac); | ||
439 | int ret = 0; | 384 | int ret = 0; |
440 | 385 | ||
441 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", | 386 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
442 | conf->type, print_mac(mac, conf->mac_addr)); | 387 | conf->type, conf->mac_addr); |
443 | 388 | ||
444 | mutex_lock(&wl->mutex); | 389 | mutex_lock(&wl->mutex); |
445 | 390 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_netlink.c b/drivers/net/wireless/wl12xx/wl1251_netlink.c deleted file mode 100644 index 67d3d5a3b519..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_netlink.c +++ /dev/null | |||
@@ -1,679 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | #include "wl1251_netlink.h" | ||
24 | |||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/socket.h> | ||
27 | #include <net/net_namespace.h> | ||
28 | #include <net/sock.h> | ||
29 | #include <net/genetlink.h> | ||
30 | #include <net/wireless.h> | ||
31 | #include <net/mac80211.h> | ||
32 | |||
33 | #include "wl1251.h" | ||
34 | #include "wl1251_spi.h" | ||
35 | #include "wl1251_acx.h" | ||
36 | |||
37 | /* FIXME: this should be changed as soon as user space catches up */ | ||
38 | #define WL1251_NL_NAME "wl1251" | ||
39 | #define WL1251_NL_VERSION 1 | ||
40 | |||
41 | #define WL1251_MAX_TEST_LENGTH 1024 | ||
42 | #define WL1251_MAX_NVS_LENGTH 1024 | ||
43 | |||
44 | enum wl1251_nl_commands { | ||
45 | WL1251_NL_CMD_UNSPEC, | ||
46 | WL1251_NL_CMD_TEST, | ||
47 | WL1251_NL_CMD_INTERROGATE, | ||
48 | WL1251_NL_CMD_CONFIGURE, | ||
49 | WL1251_NL_CMD_PHY_REG_READ, | ||
50 | WL1251_NL_CMD_NVS_PUSH, | ||
51 | WL1251_NL_CMD_REG_WRITE, | ||
52 | WL1251_NL_CMD_REG_READ, | ||
53 | WL1251_NL_CMD_SET_PLT_MODE, | ||
54 | |||
55 | __WL1251_NL_CMD_AFTER_LAST | ||
56 | }; | ||
57 | #define WL1251_NL_CMD_MAX (__WL1251_NL_CMD_AFTER_LAST - 1) | ||
58 | |||
59 | enum wl1251_nl_attrs { | ||
60 | WL1251_NL_ATTR_UNSPEC, | ||
61 | WL1251_NL_ATTR_IFNAME, | ||
62 | WL1251_NL_ATTR_CMD_TEST_PARAM, | ||
63 | WL1251_NL_ATTR_CMD_TEST_ANSWER, | ||
64 | WL1251_NL_ATTR_CMD_IE, | ||
65 | WL1251_NL_ATTR_CMD_IE_LEN, | ||
66 | WL1251_NL_ATTR_CMD_IE_BUFFER, | ||
67 | WL1251_NL_ATTR_CMD_IE_ANSWER, | ||
68 | WL1251_NL_ATTR_REG_ADDR, | ||
69 | WL1251_NL_ATTR_REG_VAL, | ||
70 | WL1251_NL_ATTR_NVS_BUFFER, | ||
71 | WL1251_NL_ATTR_NVS_LEN, | ||
72 | WL1251_NL_ATTR_PLT_MODE, | ||
73 | |||
74 | __WL1251_NL_ATTR_AFTER_LAST | ||
75 | }; | ||
76 | #define WL1251_NL_ATTR_MAX (__WL1251_NL_ATTR_AFTER_LAST - 1) | ||
77 | |||
78 | static struct genl_family wl1251_nl_family = { | ||
79 | .id = GENL_ID_GENERATE, | ||
80 | .name = WL1251_NL_NAME, | ||
81 | .hdrsize = 0, | ||
82 | .version = WL1251_NL_VERSION, | ||
83 | .maxattr = WL1251_NL_ATTR_MAX, | ||
84 | }; | ||
85 | |||
86 | static struct net_device *ifname_to_netdev(struct net *net, | ||
87 | struct genl_info *info) | ||
88 | { | ||
89 | char *ifname; | ||
90 | |||
91 | if (!info->attrs[WL1251_NL_ATTR_IFNAME]) | ||
92 | return NULL; | ||
93 | |||
94 | ifname = nla_data(info->attrs[WL1251_NL_ATTR_IFNAME]); | ||
95 | |||
96 | wl1251_debug(DEBUG_NETLINK, "Looking for %s", ifname); | ||
97 | |||
98 | return dev_get_by_name(net, ifname); | ||
99 | } | ||
100 | |||
101 | static struct wl1251 *ifname_to_wl1251(struct net *net, struct genl_info *info) | ||
102 | { | ||
103 | struct net_device *netdev; | ||
104 | struct wireless_dev *wdev; | ||
105 | struct wiphy *wiphy; | ||
106 | struct ieee80211_hw *hw; | ||
107 | |||
108 | netdev = ifname_to_netdev(net, info); | ||
109 | if (netdev == NULL) { | ||
110 | wl1251_error("Wrong interface"); | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | wdev = netdev->ieee80211_ptr; | ||
115 | if (wdev == NULL) { | ||
116 | wl1251_error("ieee80211_ptr is NULL"); | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | wiphy = wdev->wiphy; | ||
121 | if (wiphy == NULL) { | ||
122 | wl1251_error("wiphy is NULL"); | ||
123 | return NULL; | ||
124 | } | ||
125 | |||
126 | hw = wiphy_priv(wiphy); | ||
127 | if (hw == NULL) { | ||
128 | wl1251_error("hw is NULL"); | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | dev_put(netdev); | ||
133 | |||
134 | return hw->priv; | ||
135 | } | ||
136 | |||
137 | static int wl1251_nl_test_cmd(struct sk_buff *skb, struct genl_info *info) | ||
138 | { | ||
139 | struct wl1251 *wl; | ||
140 | struct wl1251_command *cmd; | ||
141 | char *buf; | ||
142 | int buf_len, ret, cmd_len; | ||
143 | u8 answer; | ||
144 | |||
145 | if (!info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]) | ||
146 | return -EINVAL; | ||
147 | |||
148 | wl = ifname_to_wl1251(&init_net, info); | ||
149 | if (wl == NULL) { | ||
150 | wl1251_error("wl1251 not found"); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | |||
154 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
155 | if (!cmd) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | buf = nla_data(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); | ||
159 | buf_len = nla_len(info->attrs[WL1251_NL_ATTR_CMD_TEST_PARAM]); | ||
160 | answer = nla_get_u8(info->attrs[WL1251_NL_ATTR_CMD_TEST_ANSWER]); | ||
161 | |||
162 | cmd->header.id = CMD_TEST; | ||
163 | memcpy(cmd->parameters, buf, buf_len); | ||
164 | cmd_len = sizeof(struct wl1251_cmd_header) + buf_len; | ||
165 | |||
166 | mutex_lock(&wl->mutex); | ||
167 | ret = wl1251_cmd_test(wl, cmd, cmd_len, answer); | ||
168 | mutex_unlock(&wl->mutex); | ||
169 | |||
170 | if (ret < 0) { | ||
171 | wl1251_error("%s() failed", __func__); | ||
172 | goto out; | ||
173 | } | ||
174 | |||
175 | if (answer) { | ||
176 | struct sk_buff *msg; | ||
177 | void *hdr; | ||
178 | |||
179 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
180 | if (!msg) { | ||
181 | ret = -ENOMEM; | ||
182 | goto out; | ||
183 | } | ||
184 | |||
185 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
186 | &wl1251_nl_family, 0, WL1251_NL_CMD_TEST); | ||
187 | if (IS_ERR(hdr)) { | ||
188 | ret = PTR_ERR(hdr); | ||
189 | goto nla_put_failure; | ||
190 | } | ||
191 | |||
192 | NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, | ||
193 | nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); | ||
194 | NLA_PUT(msg, WL1251_NL_ATTR_CMD_TEST_ANSWER, | ||
195 | sizeof(*cmd), cmd); | ||
196 | |||
197 | ret = genlmsg_end(msg, hdr); | ||
198 | if (ret < 0) { | ||
199 | wl1251_error("%s() failed", __func__); | ||
200 | goto nla_put_failure; | ||
201 | } | ||
202 | |||
203 | wl1251_debug(DEBUG_NETLINK, "TEST cmd sent, answer"); | ||
204 | ret = genlmsg_reply(msg, info); | ||
205 | goto out; | ||
206 | |||
207 | nla_put_failure: | ||
208 | nlmsg_free(msg); | ||
209 | } else | ||
210 | wl1251_debug(DEBUG_NETLINK, "TEST cmd sent"); | ||
211 | |||
212 | out: | ||
213 | kfree(cmd); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static int wl1251_nl_interrogate(struct sk_buff *skb, struct genl_info *info) | ||
218 | { | ||
219 | struct wl1251 *wl; | ||
220 | struct sk_buff *msg; | ||
221 | int ret = -ENOBUFS, cmd_ie, cmd_ie_len; | ||
222 | struct wl1251_command *cmd; | ||
223 | void *hdr; | ||
224 | |||
225 | if (!info->attrs[WL1251_NL_ATTR_CMD_IE]) | ||
226 | return -EINVAL; | ||
227 | |||
228 | if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) | ||
229 | return -EINVAL; | ||
230 | |||
231 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
232 | if (!cmd) | ||
233 | return -ENOMEM; | ||
234 | |||
235 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
236 | if (!msg) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | wl = ifname_to_wl1251(&init_net, info); | ||
240 | if (wl == NULL) { | ||
241 | wl1251_error("wl1251 not found"); | ||
242 | ret = -EINVAL; | ||
243 | goto nla_put_failure; | ||
244 | } | ||
245 | |||
246 | /* acx id */ | ||
247 | cmd_ie = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE]); | ||
248 | |||
249 | /* maximum length of acx, including all headers */ | ||
250 | cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); | ||
251 | |||
252 | wl1251_debug(DEBUG_NETLINK, "Getting IE 0x%x (len %d)", | ||
253 | cmd_ie, cmd_ie_len); | ||
254 | |||
255 | mutex_lock(&wl->mutex); | ||
256 | ret = wl1251_cmd_interrogate(wl, cmd_ie, cmd, cmd_ie_len); | ||
257 | mutex_unlock(&wl->mutex); | ||
258 | |||
259 | if (ret < 0) { | ||
260 | wl1251_error("%s() failed", __func__); | ||
261 | goto nla_put_failure; | ||
262 | } | ||
263 | |||
264 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
265 | &wl1251_nl_family, 0, WL1251_NL_CMD_INTERROGATE); | ||
266 | if (IS_ERR(hdr)) { | ||
267 | ret = PTR_ERR(hdr); | ||
268 | goto nla_put_failure; | ||
269 | } | ||
270 | |||
271 | NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, | ||
272 | nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); | ||
273 | NLA_PUT(msg, WL1251_NL_ATTR_CMD_IE_ANSWER, cmd_ie_len, cmd); | ||
274 | |||
275 | ret = genlmsg_end(msg, hdr); | ||
276 | if (ret < 0) { | ||
277 | wl1251_error("%s() failed", __func__); | ||
278 | goto nla_put_failure; | ||
279 | } | ||
280 | |||
281 | kfree(cmd); | ||
282 | return genlmsg_reply(msg, info); | ||
283 | |||
284 | nla_put_failure: | ||
285 | kfree(cmd); | ||
286 | nlmsg_free(msg); | ||
287 | |||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int wl1251_nl_configure(struct sk_buff *skb, struct genl_info *info) | ||
292 | { | ||
293 | int ret = 0, cmd_ie_len, acx_len; | ||
294 | struct acx_header *acx = NULL; | ||
295 | struct sk_buff *msg; | ||
296 | struct wl1251 *wl; | ||
297 | void *cmd_ie; | ||
298 | u16 *id; | ||
299 | |||
300 | if (!info->attrs[WL1251_NL_ATTR_CMD_IE_BUFFER]) | ||
301 | return -EINVAL; | ||
302 | |||
303 | if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) | ||
304 | return -EINVAL; | ||
305 | |||
306 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
307 | if (!msg) | ||
308 | return -ENOMEM; | ||
309 | |||
310 | wl = ifname_to_wl1251(&init_net, info); | ||
311 | if (wl == NULL) { | ||
312 | wl1251_error("wl1251 not found"); | ||
313 | ret = -EINVAL; | ||
314 | goto nla_put_failure; | ||
315 | } | ||
316 | |||
317 | /* contains the acx header but not the cmd header */ | ||
318 | cmd_ie = nla_data(info->attrs[WL1251_NL_ATTR_CMD_IE_BUFFER]); | ||
319 | |||
320 | cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); | ||
321 | |||
322 | /* acx id is in the first two bytes */ | ||
323 | id = cmd_ie; | ||
324 | |||
325 | /* need to add acx_header before cmd_ie, so create a new command */ | ||
326 | acx_len = sizeof(struct acx_header) + cmd_ie_len; | ||
327 | acx = kzalloc(acx_len, GFP_KERNEL); | ||
328 | if (!acx) { | ||
329 | ret = -ENOMEM; | ||
330 | goto nla_put_failure; | ||
331 | } | ||
332 | |||
333 | /* copy the acx header and the payload */ | ||
334 | memcpy(&acx->id, cmd_ie, cmd_ie_len); | ||
335 | |||
336 | mutex_lock(&wl->mutex); | ||
337 | ret = wl1251_cmd_configure(wl, *id, acx, acx_len); | ||
338 | mutex_unlock(&wl->mutex); | ||
339 | |||
340 | if (ret < 0) { | ||
341 | wl1251_error("%s() failed", __func__); | ||
342 | goto nla_put_failure; | ||
343 | } | ||
344 | |||
345 | wl1251_debug(DEBUG_NETLINK, "CONFIGURE cmd sent"); | ||
346 | |||
347 | nla_put_failure: | ||
348 | kfree(acx); | ||
349 | nlmsg_free(msg); | ||
350 | |||
351 | return ret; | ||
352 | } | ||
353 | |||
354 | static int wl1251_nl_phy_reg_read(struct sk_buff *skb, struct genl_info *info) | ||
355 | { | ||
356 | struct wl1251 *wl; | ||
357 | struct sk_buff *msg; | ||
358 | u32 reg_addr, *reg_value = NULL; | ||
359 | int ret = 0; | ||
360 | void *hdr; | ||
361 | |||
362 | if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) | ||
363 | return -EINVAL; | ||
364 | |||
365 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
366 | if (!msg) | ||
367 | return -ENOMEM; | ||
368 | |||
369 | wl = ifname_to_wl1251(&init_net, info); | ||
370 | if (wl == NULL) { | ||
371 | wl1251_error("wl1251 not found"); | ||
372 | ret = -EINVAL; | ||
373 | goto nla_put_failure; | ||
374 | } | ||
375 | |||
376 | reg_value = kmalloc(sizeof(*reg_value), GFP_KERNEL); | ||
377 | if (!reg_value) { | ||
378 | ret = -ENOMEM; | ||
379 | goto nla_put_failure; | ||
380 | } | ||
381 | |||
382 | reg_addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); | ||
383 | |||
384 | wl1251_debug(DEBUG_NETLINK, "Reading PHY reg 0x%x", reg_addr); | ||
385 | |||
386 | mutex_lock(&wl->mutex); | ||
387 | ret = wl1251_cmd_read_memory(wl, reg_addr, reg_value, | ||
388 | sizeof(*reg_value)); | ||
389 | mutex_unlock(&wl->mutex); | ||
390 | |||
391 | if (ret < 0) { | ||
392 | wl1251_error("%s() failed", __func__); | ||
393 | goto nla_put_failure; | ||
394 | } | ||
395 | |||
396 | |||
397 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
398 | &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); | ||
399 | if (IS_ERR(hdr)) { | ||
400 | ret = PTR_ERR(hdr); | ||
401 | goto nla_put_failure; | ||
402 | } | ||
403 | |||
404 | NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, | ||
405 | nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); | ||
406 | |||
407 | NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, *reg_value); | ||
408 | |||
409 | ret = genlmsg_end(msg, hdr); | ||
410 | if (ret < 0) { | ||
411 | wl1251_error("%s() failed", __func__); | ||
412 | goto nla_put_failure; | ||
413 | } | ||
414 | |||
415 | kfree(reg_value); | ||
416 | |||
417 | return genlmsg_reply(msg, info); | ||
418 | |||
419 | nla_put_failure: | ||
420 | nlmsg_free(msg); | ||
421 | kfree(reg_value); | ||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | |||
426 | static int wl1251_nl_nvs_push(struct sk_buff *skb, struct genl_info *info) | ||
427 | { | ||
428 | struct wl1251 *wl; | ||
429 | int ret = 0; | ||
430 | |||
431 | if (!info->attrs[WL1251_NL_ATTR_NVS_BUFFER]) | ||
432 | return -EINVAL; | ||
433 | |||
434 | if (!info->attrs[WL1251_NL_ATTR_NVS_LEN]) | ||
435 | return -EINVAL; | ||
436 | |||
437 | wl = ifname_to_wl1251(&init_net, info); | ||
438 | if (wl == NULL) { | ||
439 | wl1251_error("wl1251 not found"); | ||
440 | return -EINVAL; | ||
441 | } | ||
442 | |||
443 | mutex_lock(&wl->mutex); | ||
444 | wl->nvs_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_NVS_LEN]); | ||
445 | if (wl->nvs_len % 4) { | ||
446 | wl1251_error("NVS size is not multiple of 32: %d", wl->nvs_len); | ||
447 | ret = -EILSEQ; | ||
448 | goto out; | ||
449 | } | ||
450 | |||
451 | /* If we already have an NVS, we should free it */ | ||
452 | kfree(wl->nvs); | ||
453 | |||
454 | wl->nvs = kzalloc(wl->nvs_len, GFP_KERNEL); | ||
455 | if (wl->nvs == NULL) { | ||
456 | wl1251_error("Can't allocate NVS"); | ||
457 | ret = -ENOMEM; | ||
458 | goto out; | ||
459 | } | ||
460 | |||
461 | memcpy(wl->nvs, | ||
462 | nla_data(info->attrs[WL1251_NL_ATTR_NVS_BUFFER]), | ||
463 | wl->nvs_len); | ||
464 | |||
465 | wl1251_debug(DEBUG_NETLINK, "got NVS from userspace, %d bytes", | ||
466 | wl->nvs_len); | ||
467 | |||
468 | out: | ||
469 | mutex_unlock(&wl->mutex); | ||
470 | |||
471 | return ret; | ||
472 | } | ||
473 | |||
474 | static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info) | ||
475 | { | ||
476 | struct wl1251 *wl; | ||
477 | u32 addr, val; | ||
478 | int ret = 0; | ||
479 | struct sk_buff *msg; | ||
480 | void *hdr; | ||
481 | |||
482 | if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) | ||
483 | return -EINVAL; | ||
484 | |||
485 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
486 | if (!msg) | ||
487 | return -ENOMEM; | ||
488 | |||
489 | wl = ifname_to_wl1251(&init_net, info); | ||
490 | if (wl == NULL) { | ||
491 | wl1251_error("wl1251 not found"); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); | ||
496 | |||
497 | mutex_lock(&wl->mutex); | ||
498 | val = wl1251_reg_read32(wl, addr); | ||
499 | mutex_unlock(&wl->mutex); | ||
500 | |||
501 | hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, | ||
502 | &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); | ||
503 | if (IS_ERR(hdr)) { | ||
504 | ret = PTR_ERR(hdr); | ||
505 | goto nla_put_failure; | ||
506 | } | ||
507 | |||
508 | NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, | ||
509 | nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); | ||
510 | |||
511 | NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val); | ||
512 | |||
513 | ret = genlmsg_end(msg, hdr); | ||
514 | if (ret < 0) { | ||
515 | wl1251_error("%s() failed", __func__); | ||
516 | goto nla_put_failure; | ||
517 | } | ||
518 | |||
519 | return genlmsg_reply(msg, info); | ||
520 | |||
521 | nla_put_failure: | ||
522 | nlmsg_free(msg); | ||
523 | |||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | static int wl1251_nl_reg_write(struct sk_buff *skb, struct genl_info *info) | ||
528 | { | ||
529 | struct wl1251 *wl; | ||
530 | u32 addr, val; | ||
531 | |||
532 | if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) | ||
533 | return -EINVAL; | ||
534 | |||
535 | if (!info->attrs[WL1251_NL_ATTR_REG_VAL]) | ||
536 | return -EINVAL; | ||
537 | |||
538 | wl = ifname_to_wl1251(&init_net, info); | ||
539 | if (wl == NULL) { | ||
540 | wl1251_error("wl1251 not found"); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); | ||
545 | val = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_VAL]); | ||
546 | |||
547 | mutex_lock(&wl->mutex); | ||
548 | wl1251_reg_write32(wl, addr, val); | ||
549 | mutex_unlock(&wl->mutex); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static int wl1251_nl_set_plt_mode(struct sk_buff *skb, struct genl_info *info) | ||
555 | { | ||
556 | struct wl1251 *wl; | ||
557 | u32 val; | ||
558 | int ret; | ||
559 | |||
560 | if (!info->attrs[WL1251_NL_ATTR_PLT_MODE]) | ||
561 | return -EINVAL; | ||
562 | |||
563 | wl = ifname_to_wl1251(&init_net, info); | ||
564 | if (wl == NULL) { | ||
565 | wl1251_error("wl1251 not found"); | ||
566 | return -EINVAL; | ||
567 | } | ||
568 | |||
569 | val = nla_get_u32(info->attrs[WL1251_NL_ATTR_PLT_MODE]); | ||
570 | |||
571 | switch (val) { | ||
572 | case 0: | ||
573 | ret = wl1251_plt_stop(wl); | ||
574 | break; | ||
575 | case 1: | ||
576 | ret = wl1251_plt_start(wl); | ||
577 | break; | ||
578 | default: | ||
579 | ret = -EINVAL; | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | return ret; | ||
584 | } | ||
585 | |||
586 | static struct nla_policy wl1251_nl_policy[WL1251_NL_ATTR_MAX + 1] = { | ||
587 | [WL1251_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, | ||
588 | .len = IFNAMSIZ-1 }, | ||
589 | [WL1251_NL_ATTR_CMD_TEST_PARAM] = { .type = NLA_BINARY, | ||
590 | .len = WL1251_MAX_TEST_LENGTH }, | ||
591 | [WL1251_NL_ATTR_CMD_TEST_ANSWER] = { .type = NLA_U8 }, | ||
592 | [WL1251_NL_ATTR_CMD_IE] = { .type = NLA_U32 }, | ||
593 | [WL1251_NL_ATTR_CMD_IE_LEN] = { .type = NLA_U32 }, | ||
594 | [WL1251_NL_ATTR_CMD_IE_BUFFER] = { .type = NLA_BINARY, | ||
595 | .len = WL1251_MAX_TEST_LENGTH }, | ||
596 | [WL1251_NL_ATTR_CMD_IE_ANSWER] = { .type = NLA_BINARY, | ||
597 | .len = WL1251_MAX_TEST_LENGTH }, | ||
598 | [WL1251_NL_ATTR_REG_ADDR] = { .type = NLA_U32 }, | ||
599 | [WL1251_NL_ATTR_REG_VAL] = { .type = NLA_U32 }, | ||
600 | [WL1251_NL_ATTR_NVS_BUFFER] = { .type = NLA_BINARY, | ||
601 | .len = WL1251_MAX_NVS_LENGTH }, | ||
602 | [WL1251_NL_ATTR_NVS_LEN] = { .type = NLA_U32 }, | ||
603 | [WL1251_NL_ATTR_PLT_MODE] = { .type = NLA_U32 }, | ||
604 | }; | ||
605 | |||
606 | static struct genl_ops wl1251_nl_ops[] = { | ||
607 | { | ||
608 | .cmd = WL1251_NL_CMD_TEST, | ||
609 | .doit = wl1251_nl_test_cmd, | ||
610 | .policy = wl1251_nl_policy, | ||
611 | .flags = GENL_ADMIN_PERM, | ||
612 | }, | ||
613 | { | ||
614 | .cmd = WL1251_NL_CMD_INTERROGATE, | ||
615 | .doit = wl1251_nl_interrogate, | ||
616 | .policy = wl1251_nl_policy, | ||
617 | .flags = GENL_ADMIN_PERM, | ||
618 | }, | ||
619 | { | ||
620 | .cmd = WL1251_NL_CMD_CONFIGURE, | ||
621 | .doit = wl1251_nl_configure, | ||
622 | .policy = wl1251_nl_policy, | ||
623 | .flags = GENL_ADMIN_PERM, | ||
624 | }, | ||
625 | { | ||
626 | .cmd = WL1251_NL_CMD_PHY_REG_READ, | ||
627 | .doit = wl1251_nl_phy_reg_read, | ||
628 | .policy = wl1251_nl_policy, | ||
629 | .flags = GENL_ADMIN_PERM, | ||
630 | }, | ||
631 | { | ||
632 | .cmd = WL1251_NL_CMD_NVS_PUSH, | ||
633 | .doit = wl1251_nl_nvs_push, | ||
634 | .policy = wl1251_nl_policy, | ||
635 | .flags = GENL_ADMIN_PERM, | ||
636 | }, | ||
637 | { | ||
638 | .cmd = WL1251_NL_CMD_REG_WRITE, | ||
639 | .doit = wl1251_nl_reg_write, | ||
640 | .policy = wl1251_nl_policy, | ||
641 | .flags = GENL_ADMIN_PERM, | ||
642 | }, | ||
643 | { | ||
644 | .cmd = WL1251_NL_CMD_REG_READ, | ||
645 | .doit = wl1251_nl_reg_read, | ||
646 | .policy = wl1251_nl_policy, | ||
647 | .flags = GENL_ADMIN_PERM, | ||
648 | }, | ||
649 | { | ||
650 | .cmd = WL1251_NL_CMD_SET_PLT_MODE, | ||
651 | .doit = wl1251_nl_set_plt_mode, | ||
652 | .policy = wl1251_nl_policy, | ||
653 | .flags = GENL_ADMIN_PERM, | ||
654 | }, | ||
655 | }; | ||
656 | |||
657 | int wl1251_nl_register(void) | ||
658 | { | ||
659 | int err, i; | ||
660 | |||
661 | err = genl_register_family(&wl1251_nl_family); | ||
662 | if (err) | ||
663 | return err; | ||
664 | |||
665 | for (i = 0; i < ARRAY_SIZE(wl1251_nl_ops); i++) { | ||
666 | err = genl_register_ops(&wl1251_nl_family, &wl1251_nl_ops[i]); | ||
667 | if (err) | ||
668 | goto err_out; | ||
669 | } | ||
670 | return 0; | ||
671 | err_out: | ||
672 | genl_unregister_family(&wl1251_nl_family); | ||
673 | return err; | ||
674 | } | ||
675 | |||
676 | void wl1251_nl_unregister(void) | ||
677 | { | ||
678 | genl_unregister_family(&wl1251_nl_family); | ||
679 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c index 96a45f595297..e7b9aab3682f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ops.c +++ b/drivers/net/wireless/wl12xx/wl1251_ops.c | |||
@@ -423,7 +423,7 @@ static void wl1251_irq_work(struct work_struct *work) | |||
423 | wl->rx_counter = | 423 | wl->rx_counter = |
424 | wl1251_mem_read32(wl, wl->data_path->rx_control_addr); | 424 | wl1251_mem_read32(wl, wl->data_path->rx_control_addr); |
425 | 425 | ||
426 | /* We handle a frmware bug here */ | 426 | /* We handle a firmware bug here */ |
427 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { | 427 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { |
428 | case 0: | 428 | case 0: |
429 | wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); | 429 | wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); |
@@ -575,7 +575,7 @@ static int wl1251_hw_init_data_path_config(struct wl1251 *wl) | |||
575 | wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), | 575 | wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), |
576 | GFP_KERNEL); | 576 | GFP_KERNEL); |
577 | if (!wl->data_path) { | 577 | if (!wl->data_path) { |
578 | wl1251_error("Couldnt allocate data path parameters"); | 578 | wl1251_error("Couldn't allocate data path parameters"); |
579 | return -ENOMEM; | 579 | return -ENOMEM; |
580 | } | 580 | } |
581 | 581 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h index 81156b9c4758..563a3fde40fb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ b/drivers/net/wireless/wl12xx/wl1251_rx.h | |||
@@ -88,7 +88,7 @@ struct wl1251_rx_descriptor { | |||
88 | u8 type; | 88 | u8 type; |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * Recevied Rate: | 91 | * Received Rate: |
92 | * 0x0A - 1MBPS | 92 | * 0x0A - 1MBPS |
93 | * 0x14 - 2MBPS | 93 | * 0x14 - 2MBPS |
94 | * 0x37 - 5_5MBPS | 94 | * 0x37 - 5_5MBPS |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 07d7ab674a0f..38688847d568 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -76,6 +76,7 @@ static struct usb_device_id usb_ids[] = { | |||
76 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, | 76 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, |
77 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, | 77 | { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, |
78 | { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, | 78 | { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, |
79 | { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B }, | ||
79 | { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B }, | 80 | { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B }, |
80 | { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, | 81 | { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, |
81 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | 82 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index e496a2daf7ef..962e2232a074 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -567,6 +567,12 @@ enum nl80211_commands { | |||
567 | * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE | 567 | * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE |
568 | * commands to specify using a reassociate frame | 568 | * commands to specify using a reassociate frame |
569 | * | 569 | * |
570 | * @NL80211_ATTR_KEY: key information in a nested attribute with | ||
571 | * %NL80211_KEY_* sub-attributes | ||
572 | * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() | ||
573 | * and join_ibss(), key information is in a nested attribute each | ||
574 | * with %NL80211_KEY_* sub-attributes | ||
575 | * | ||
570 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 576 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
571 | * @__NL80211_ATTR_AFTER_LAST: internal use | 577 | * @__NL80211_ATTR_AFTER_LAST: internal use |
572 | */ | 578 | */ |
@@ -692,6 +698,9 @@ enum nl80211_attrs { | |||
692 | 698 | ||
693 | NL80211_ATTR_PREV_BSSID, | 699 | NL80211_ATTR_PREV_BSSID, |
694 | 700 | ||
701 | NL80211_ATTR_KEY, | ||
702 | NL80211_ATTR_KEYS, | ||
703 | |||
695 | /* add attributes here, update the policy in nl80211.c */ | 704 | /* add attributes here, update the policy in nl80211.c */ |
696 | 705 | ||
697 | __NL80211_ATTR_AFTER_LAST, | 706 | __NL80211_ATTR_AFTER_LAST, |
@@ -720,6 +729,8 @@ enum nl80211_attrs { | |||
720 | #define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP | 729 | #define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP |
721 | #define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS | 730 | #define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS |
722 | #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES | 731 | #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES |
732 | #define NL80211_ATTR_KEY NL80211_ATTR_KEY | ||
733 | #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS | ||
723 | 734 | ||
724 | #define NL80211_MAX_SUPP_RATES 32 | 735 | #define NL80211_MAX_SUPP_RATES 32 |
725 | #define NL80211_MAX_SUPP_REG_RULES 32 | 736 | #define NL80211_MAX_SUPP_REG_RULES 32 |
@@ -1249,6 +1260,7 @@ enum nl80211_channel_type { | |||
1249 | * in mBm (100 * dBm) (s32) | 1260 | * in mBm (100 * dBm) (s32) |
1250 | * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon | 1261 | * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon |
1251 | * in unspecified units, scaled to 0..100 (u8) | 1262 | * in unspecified units, scaled to 0..100 (u8) |
1263 | * @NL80211_BSS_STATUS: status, if this BSS is "used" | ||
1252 | * @__NL80211_BSS_AFTER_LAST: internal | 1264 | * @__NL80211_BSS_AFTER_LAST: internal |
1253 | * @NL80211_BSS_MAX: highest BSS attribute | 1265 | * @NL80211_BSS_MAX: highest BSS attribute |
1254 | */ | 1266 | */ |
@@ -1262,6 +1274,7 @@ enum nl80211_bss { | |||
1262 | NL80211_BSS_INFORMATION_ELEMENTS, | 1274 | NL80211_BSS_INFORMATION_ELEMENTS, |
1263 | NL80211_BSS_SIGNAL_MBM, | 1275 | NL80211_BSS_SIGNAL_MBM, |
1264 | NL80211_BSS_SIGNAL_UNSPEC, | 1276 | NL80211_BSS_SIGNAL_UNSPEC, |
1277 | NL80211_BSS_STATUS, | ||
1265 | 1278 | ||
1266 | /* keep last */ | 1279 | /* keep last */ |
1267 | __NL80211_BSS_AFTER_LAST, | 1280 | __NL80211_BSS_AFTER_LAST, |
@@ -1269,6 +1282,15 @@ enum nl80211_bss { | |||
1269 | }; | 1282 | }; |
1270 | 1283 | ||
1271 | /** | 1284 | /** |
1285 | * enum nl80211_bss_status - BSS "status" | ||
1286 | */ | ||
1287 | enum nl80211_bss_status { | ||
1288 | NL80211_BSS_STATUS_AUTHENTICATED, | ||
1289 | NL80211_BSS_STATUS_ASSOCIATED, | ||
1290 | NL80211_BSS_STATUS_IBSS_JOINED, | ||
1291 | }; | ||
1292 | |||
1293 | /** | ||
1272 | * enum nl80211_auth_type - AuthenticationType | 1294 | * enum nl80211_auth_type - AuthenticationType |
1273 | * | 1295 | * |
1274 | * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication | 1296 | * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication |
@@ -1320,4 +1342,34 @@ enum nl80211_wpa_versions { | |||
1320 | NL80211_WPA_VERSION_2 = 1 << 1, | 1342 | NL80211_WPA_VERSION_2 = 1 << 1, |
1321 | }; | 1343 | }; |
1322 | 1344 | ||
1345 | /** | ||
1346 | * enum nl80211_key_attributes - key attributes | ||
1347 | * @__NL80211_KEY_INVALID: invalid | ||
1348 | * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of | ||
1349 | * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC | ||
1350 | * keys | ||
1351 | * @NL80211_KEY_IDX: key ID (u8, 0-3) | ||
1352 | * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 | ||
1353 | * section 7.3.2.25.1, e.g. 0x000FAC04) | ||
1354 | * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and | ||
1355 | * CCMP keys, each six bytes in little endian | ||
1356 | * @NL80211_KEY_DEFAULT: flag indicating default key | ||
1357 | * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key | ||
1358 | * @__NL80211_KEY_AFTER_LAST: internal | ||
1359 | * @NL80211_KEY_MAX: highest key attribute | ||
1360 | */ | ||
1361 | enum nl80211_key_attributes { | ||
1362 | __NL80211_KEY_INVALID, | ||
1363 | NL80211_KEY_DATA, | ||
1364 | NL80211_KEY_IDX, | ||
1365 | NL80211_KEY_CIPHER, | ||
1366 | NL80211_KEY_SEQ, | ||
1367 | NL80211_KEY_DEFAULT, | ||
1368 | NL80211_KEY_DEFAULT_MGMT, | ||
1369 | |||
1370 | /* keep last */ | ||
1371 | __NL80211_KEY_AFTER_LAST, | ||
1372 | NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 | ||
1373 | }; | ||
1374 | |||
1323 | #endif /* __LINUX_NL80211_H */ | 1375 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f2c69a2cca17..df7b23ac66e6 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -304,7 +304,6 @@ typedef unsigned char *sk_buff_data_t; | |||
304 | * @tc_index: Traffic control index | 304 | * @tc_index: Traffic control index |
305 | * @tc_verd: traffic control verdict | 305 | * @tc_verd: traffic control verdict |
306 | * @ndisc_nodetype: router type (from link layer) | 306 | * @ndisc_nodetype: router type (from link layer) |
307 | * @do_not_encrypt: set to prevent encryption of this frame | ||
308 | * @dma_cookie: a cookie to one of several possible DMA operations | 307 | * @dma_cookie: a cookie to one of several possible DMA operations |
309 | * done by skb DMA functions | 308 | * done by skb DMA functions |
310 | * @secmark: security marking | 309 | * @secmark: security marking |
@@ -380,12 +379,9 @@ struct sk_buff { | |||
380 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 379 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
381 | __u8 ndisc_nodetype:2; | 380 | __u8 ndisc_nodetype:2; |
382 | #endif | 381 | #endif |
383 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | ||
384 | __u8 do_not_encrypt:1; | ||
385 | #endif | ||
386 | kmemcheck_bitfield_end(flags2); | 382 | kmemcheck_bitfield_end(flags2); |
387 | 383 | ||
388 | /* 0/13/14 bit hole */ | 384 | /* 0/14 bit hole */ |
389 | 385 | ||
390 | #ifdef CONFIG_NET_DMA | 386 | #ifdef CONFIG_NET_DMA |
391 | dma_cookie_t dma_cookie; | 387 | dma_cookie_t dma_cookie; |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 83c2c727d71e..a981ca8a5701 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -538,7 +538,7 @@ struct cfg80211_ssid { | |||
538 | * @ssids: SSIDs to scan for (active scan only) | 538 | * @ssids: SSIDs to scan for (active scan only) |
539 | * @n_ssids: number of SSIDs | 539 | * @n_ssids: number of SSIDs |
540 | * @channels: channels to scan on. | 540 | * @channels: channels to scan on. |
541 | * @n_channels: number of channels for each band | 541 | * @n_channels: total number of channels to scan |
542 | * @ie: optional information element(s) to add into Probe Request or %NULL | 542 | * @ie: optional information element(s) to add into Probe Request or %NULL |
543 | * @ie_len: length of ie in octets | 543 | * @ie_len: length of ie in octets |
544 | * @wiphy: the wiphy this was for | 544 | * @wiphy: the wiphy this was for |
@@ -647,12 +647,17 @@ struct cfg80211_crypto_settings { | |||
647 | * @auth_type: Authentication type (algorithm) | 647 | * @auth_type: Authentication type (algorithm) |
648 | * @ie: Extra IEs to add to Authentication frame or %NULL | 648 | * @ie: Extra IEs to add to Authentication frame or %NULL |
649 | * @ie_len: Length of ie buffer in octets | 649 | * @ie_len: Length of ie buffer in octets |
650 | * @key_len: length of WEP key for shared key authentication | ||
651 | * @key_idx: index of WEP key for shared key authentication | ||
652 | * @key: WEP key for shared key authentication | ||
650 | */ | 653 | */ |
651 | struct cfg80211_auth_request { | 654 | struct cfg80211_auth_request { |
652 | struct cfg80211_bss *bss; | 655 | struct cfg80211_bss *bss; |
653 | const u8 *ie; | 656 | const u8 *ie; |
654 | size_t ie_len; | 657 | size_t ie_len; |
655 | enum nl80211_auth_type auth_type; | 658 | enum nl80211_auth_type auth_type; |
659 | const u8 *key; | ||
660 | u8 key_len, key_idx; | ||
656 | }; | 661 | }; |
657 | 662 | ||
658 | /** | 663 | /** |
@@ -727,6 +732,8 @@ struct cfg80211_disassoc_request { | |||
727 | * @ie: information element(s) to include in the beacon | 732 | * @ie: information element(s) to include in the beacon |
728 | * @ie_len: length of that | 733 | * @ie_len: length of that |
729 | * @beacon_interval: beacon interval to use | 734 | * @beacon_interval: beacon interval to use |
735 | * @privacy: this is a protected network, keys will be configured | ||
736 | * after joining | ||
730 | */ | 737 | */ |
731 | struct cfg80211_ibss_params { | 738 | struct cfg80211_ibss_params { |
732 | u8 *ssid; | 739 | u8 *ssid; |
@@ -736,6 +743,7 @@ struct cfg80211_ibss_params { | |||
736 | u8 ssid_len, ie_len; | 743 | u8 ssid_len, ie_len; |
737 | u16 beacon_interval; | 744 | u16 beacon_interval; |
738 | bool channel_fixed; | 745 | bool channel_fixed; |
746 | bool privacy; | ||
739 | }; | 747 | }; |
740 | 748 | ||
741 | /** | 749 | /** |
@@ -755,6 +763,9 @@ struct cfg80211_ibss_params { | |||
755 | * @assoc_ie_len: Length of assoc_ie in octets | 763 | * @assoc_ie_len: Length of assoc_ie in octets |
756 | * @privacy: indicates whether privacy-enabled APs should be used | 764 | * @privacy: indicates whether privacy-enabled APs should be used |
757 | * @crypto: crypto settings | 765 | * @crypto: crypto settings |
766 | * @key_len: length of WEP key for shared key authentication | ||
767 | * @key_idx: index of WEP key for shared key authentication | ||
768 | * @key: WEP key for shared key authentication | ||
758 | */ | 769 | */ |
759 | struct cfg80211_connect_params { | 770 | struct cfg80211_connect_params { |
760 | struct ieee80211_channel *channel; | 771 | struct ieee80211_channel *channel; |
@@ -766,6 +777,8 @@ struct cfg80211_connect_params { | |||
766 | size_t ie_len; | 777 | size_t ie_len; |
767 | bool privacy; | 778 | bool privacy; |
768 | struct cfg80211_crypto_settings crypto; | 779 | struct cfg80211_crypto_settings crypto; |
780 | const u8 *key; | ||
781 | u8 key_len, key_idx; | ||
769 | }; | 782 | }; |
770 | 783 | ||
771 | /** | 784 | /** |
@@ -1223,9 +1236,10 @@ extern void wiphy_unregister(struct wiphy *wiphy); | |||
1223 | */ | 1236 | */ |
1224 | extern void wiphy_free(struct wiphy *wiphy); | 1237 | extern void wiphy_free(struct wiphy *wiphy); |
1225 | 1238 | ||
1226 | /* internal struct */ | 1239 | /* internal structs */ |
1227 | struct cfg80211_conn; | 1240 | struct cfg80211_conn; |
1228 | struct cfg80211_internal_bss; | 1241 | struct cfg80211_internal_bss; |
1242 | struct cfg80211_cached_keys; | ||
1229 | 1243 | ||
1230 | #define MAX_AUTH_BSSES 4 | 1244 | #define MAX_AUTH_BSSES 4 |
1231 | 1245 | ||
@@ -1267,6 +1281,7 @@ struct wireless_dev { | |||
1267 | CFG80211_SME_CONNECTED, | 1281 | CFG80211_SME_CONNECTED, |
1268 | } sme_state; | 1282 | } sme_state; |
1269 | struct cfg80211_conn *conn; | 1283 | struct cfg80211_conn *conn; |
1284 | struct cfg80211_cached_keys *connect_keys; | ||
1270 | 1285 | ||
1271 | struct list_head event_list; | 1286 | struct list_head event_list; |
1272 | spinlock_t event_lock; | 1287 | spinlock_t event_lock; |
@@ -1280,6 +1295,7 @@ struct wireless_dev { | |||
1280 | struct { | 1295 | struct { |
1281 | struct cfg80211_ibss_params ibss; | 1296 | struct cfg80211_ibss_params ibss; |
1282 | struct cfg80211_connect_params connect; | 1297 | struct cfg80211_connect_params connect; |
1298 | struct cfg80211_cached_keys *keys; | ||
1283 | u8 *ie; | 1299 | u8 *ie; |
1284 | size_t ie_len; | 1300 | size_t ie_len; |
1285 | u8 bssid[ETH_ALEN]; | 1301 | u8 bssid[ETH_ALEN]; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ce7cb1b5d453..7dd67a1ff4d5 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -241,6 +241,8 @@ struct ieee80211_bss_conf { | |||
241 | * it can be sent out. | 241 | * it can be sent out. |
242 | * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, | 242 | * @IEEE80211_TX_INTFL_RETRIED: completely internal to mac80211, |
243 | * used to indicate that a frame was already retried due to PS | 243 | * used to indicate that a frame was already retried due to PS |
244 | * @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211, | ||
245 | * used to indicate frame should not be encrypted | ||
244 | */ | 246 | */ |
245 | enum mac80211_tx_control_flags { | 247 | enum mac80211_tx_control_flags { |
246 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 248 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -259,6 +261,7 @@ enum mac80211_tx_control_flags { | |||
259 | IEEE80211_TX_INTFL_RCALGO = BIT(13), | 261 | IEEE80211_TX_INTFL_RCALGO = BIT(13), |
260 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), | 262 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), |
261 | IEEE80211_TX_INTFL_RETRIED = BIT(15), | 263 | IEEE80211_TX_INTFL_RETRIED = BIT(15), |
264 | IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), | ||
262 | }; | 265 | }; |
263 | 266 | ||
264 | /** | 267 | /** |
@@ -2094,6 +2097,29 @@ static inline int rate_supported(struct ieee80211_sta *sta, | |||
2094 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | 2097 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); |
2095 | } | 2098 | } |
2096 | 2099 | ||
2100 | /** | ||
2101 | * rate_control_send_low - helper for drivers for management/no-ack frames | ||
2102 | * | ||
2103 | * Rate control algorithms that agree to use the lowest rate to | ||
2104 | * send management frames and NO_ACK data with the respective hw | ||
2105 | * retries should use this in the beginning of their mac80211 get_rate | ||
2106 | * callback. If true is returned the rate control can simply return. | ||
2107 | * If false is returned we guarantee that sta and sta and priv_sta is | ||
2108 | * not null. | ||
2109 | * | ||
2110 | * Rate control algorithms wishing to do more intelligent selection of | ||
2111 | * rate for multicast/broadcast frames may choose to not use this. | ||
2112 | * | ||
2113 | * @sta: &struct ieee80211_sta pointer to the target destination. Note | ||
2114 | * that this may be null. | ||
2115 | * @priv_sta: private rate control structure. This may be null. | ||
2116 | * @txrc: rate control information we sholud populate for mac80211. | ||
2117 | */ | ||
2118 | bool rate_control_send_low(struct ieee80211_sta *sta, | ||
2119 | void *priv_sta, | ||
2120 | struct ieee80211_tx_rate_control *txrc); | ||
2121 | |||
2122 | |||
2097 | static inline s8 | 2123 | static inline s8 |
2098 | rate_lowest_index(struct ieee80211_supported_band *sband, | 2124 | rate_lowest_index(struct ieee80211_supported_band *sband, |
2099 | struct ieee80211_sta *sta) | 2125 | struct ieee80211_sta *sta) |
@@ -2110,6 +2136,17 @@ rate_lowest_index(struct ieee80211_supported_band *sband, | |||
2110 | return 0; | 2136 | return 0; |
2111 | } | 2137 | } |
2112 | 2138 | ||
2139 | static inline | ||
2140 | bool rate_usable_index_exists(struct ieee80211_supported_band *sband, | ||
2141 | struct ieee80211_sta *sta) | ||
2142 | { | ||
2143 | unsigned int i; | ||
2144 | |||
2145 | for (i = 0; i < sband->n_bitrates; i++) | ||
2146 | if (rate_supported(sta, sband->band, i)) | ||
2147 | return true; | ||
2148 | return false; | ||
2149 | } | ||
2113 | 2150 | ||
2114 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | 2151 | int ieee80211_rate_control_register(struct rate_control_ops *ops); |
2115 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | 2152 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); |
diff --git a/net/core/dev.c b/net/core/dev.c index dca8b5000d3b..d6c657ee413d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3923,6 +3923,7 @@ int __dev_addr_sync(struct dev_addr_list **to, int *to_count, | |||
3923 | } | 3923 | } |
3924 | return err; | 3924 | return err; |
3925 | } | 3925 | } |
3926 | EXPORT_SYMBOL_GPL(__dev_addr_sync); | ||
3926 | 3927 | ||
3927 | void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | 3928 | void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, |
3928 | struct dev_addr_list **from, int *from_count) | 3929 | struct dev_addr_list **from, int *from_count) |
@@ -3942,6 +3943,7 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | |||
3942 | da = next; | 3943 | da = next; |
3943 | } | 3944 | } |
3944 | } | 3945 | } |
3946 | EXPORT_SYMBOL_GPL(__dev_addr_unsync); | ||
3945 | 3947 | ||
3946 | /** | 3948 | /** |
3947 | * dev_unicast_sync - Synchronize device's unicast list to another device | 3949 | * dev_unicast_sync - Synchronize device's unicast list to another device |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9e0597d189b0..80a96166df39 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -559,9 +559,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
559 | #endif | 559 | #endif |
560 | #endif | 560 | #endif |
561 | new->vlan_tci = old->vlan_tci; | 561 | new->vlan_tci = old->vlan_tci; |
562 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | ||
563 | new->do_not_encrypt = old->do_not_encrypt; | ||
564 | #endif | ||
565 | 562 | ||
566 | skb_copy_secmark(new, old); | 563 | skb_copy_secmark(new, old); |
567 | } | 564 | } |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 182c9c5c6818..19a4c66e143e 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -206,3 +206,15 @@ config MAC80211_DEBUG_COUNTERS | |||
206 | and show them in debugfs. | 206 | and show them in debugfs. |
207 | 207 | ||
208 | If unsure, say N. | 208 | If unsure, say N. |
209 | |||
210 | config MAC80211_DRIVER_API_TRACER | ||
211 | bool "Driver API tracer" | ||
212 | depends on MAC80211_DEBUG_MENU | ||
213 | depends on EVENT_TRACING | ||
214 | help | ||
215 | Say Y here to make mac80211 register with the ftrace | ||
216 | framework for the driver API -- you can see which | ||
217 | driver methods it is calling then by looking at the | ||
218 | trace. | ||
219 | |||
220 | If unsure, say N. | ||
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 0e3ab88bb706..91284a74ff91 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -41,6 +41,9 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
41 | 41 | ||
42 | mac80211-$(CONFIG_PM) += pm.o | 42 | mac80211-$(CONFIG_PM) += pm.o |
43 | 43 | ||
44 | mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o | ||
45 | CFLAGS_driver-trace.o := -I$(src) | ||
46 | |||
44 | # objects for PID algorithm | 47 | # objects for PID algorithm |
45 | rc80211_pid-y := rc80211_pid_algo.o | 48 | rc80211_pid-y := rc80211_pid_algo.o |
46 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 49 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9e5762ad307d..1958c7c42cd9 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -383,9 +383,6 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local, | |||
383 | 383 | ||
384 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { | 384 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { |
385 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 385 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
386 | /* mark queue as pending, it is stopped already */ | ||
387 | __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
388 | &local->queue_stop_reasons[queue]); | ||
389 | /* copy over remaining packets */ | 386 | /* copy over remaining packets */ |
390 | skb_queue_splice_tail_init( | 387 | skb_queue_splice_tail_init( |
391 | &sta->ampdu_mlme.tid_tx[tid]->pending, | 388 | &sta->ampdu_mlme.tid_tx[tid]->pending, |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 36f8f245fa4c..52928ad90570 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1293,7 +1293,7 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy) | |||
1293 | } | 1293 | } |
1294 | 1294 | ||
1295 | #ifdef CONFIG_NL80211_TESTMODE | 1295 | #ifdef CONFIG_NL80211_TESTMODE |
1296 | int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | 1296 | static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) |
1297 | { | 1297 | { |
1298 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1298 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1299 | 1299 | ||
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 6c439cd5ccea..96991b68f048 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -175,7 +175,7 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, | |||
175 | for (q = 0; q < local->hw.queues; q++) | 175 | for (q = 0; q < local->hw.queues; q++) |
176 | res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, | 176 | res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, |
177 | local->queue_stop_reasons[q], | 177 | local->queue_stop_reasons[q], |
178 | __netif_subqueue_stopped(local->mdev, q)); | 178 | skb_queue_len(&local->pending[q])); |
179 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 179 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
180 | 180 | ||
181 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | 181 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index b13446afd48f..4100c361a99d 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <net/mac80211.h> | 4 | #include <net/mac80211.h> |
5 | #include "ieee80211_i.h" | 5 | #include "ieee80211_i.h" |
6 | #include "driver-trace.h" | ||
6 | 7 | ||
7 | static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | 8 | static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) |
8 | { | 9 | { |
@@ -11,29 +12,37 @@ static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | |||
11 | 12 | ||
12 | static inline int drv_start(struct ieee80211_local *local) | 13 | static inline int drv_start(struct ieee80211_local *local) |
13 | { | 14 | { |
14 | return local->ops->start(&local->hw); | 15 | int ret = local->ops->start(&local->hw); |
16 | trace_drv_start(local, ret); | ||
17 | return ret; | ||
15 | } | 18 | } |
16 | 19 | ||
17 | static inline void drv_stop(struct ieee80211_local *local) | 20 | static inline void drv_stop(struct ieee80211_local *local) |
18 | { | 21 | { |
19 | local->ops->stop(&local->hw); | 22 | local->ops->stop(&local->hw); |
23 | trace_drv_stop(local); | ||
20 | } | 24 | } |
21 | 25 | ||
22 | static inline int drv_add_interface(struct ieee80211_local *local, | 26 | static inline int drv_add_interface(struct ieee80211_local *local, |
23 | struct ieee80211_if_init_conf *conf) | 27 | struct ieee80211_if_init_conf *conf) |
24 | { | 28 | { |
25 | return local->ops->add_interface(&local->hw, conf); | 29 | int ret = local->ops->add_interface(&local->hw, conf); |
30 | trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret); | ||
31 | return ret; | ||
26 | } | 32 | } |
27 | 33 | ||
28 | static inline void drv_remove_interface(struct ieee80211_local *local, | 34 | static inline void drv_remove_interface(struct ieee80211_local *local, |
29 | struct ieee80211_if_init_conf *conf) | 35 | struct ieee80211_if_init_conf *conf) |
30 | { | 36 | { |
31 | local->ops->remove_interface(&local->hw, conf); | 37 | local->ops->remove_interface(&local->hw, conf); |
38 | trace_drv_remove_interface(local, conf->mac_addr, conf->vif); | ||
32 | } | 39 | } |
33 | 40 | ||
34 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 41 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
35 | { | 42 | { |
36 | return local->ops->config(&local->hw, changed); | 43 | int ret = local->ops->config(&local->hw, changed); |
44 | trace_drv_config(local, changed, ret); | ||
45 | return ret; | ||
37 | } | 46 | } |
38 | 47 | ||
39 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | 48 | static inline void drv_bss_info_changed(struct ieee80211_local *local, |
@@ -43,6 +52,7 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
43 | { | 52 | { |
44 | if (local->ops->bss_info_changed) | 53 | if (local->ops->bss_info_changed) |
45 | local->ops->bss_info_changed(&local->hw, vif, info, changed); | 54 | local->ops->bss_info_changed(&local->hw, vif, info, changed); |
55 | trace_drv_bss_info_changed(local, vif, info, changed); | ||
46 | } | 56 | } |
47 | 57 | ||
48 | static inline void drv_configure_filter(struct ieee80211_local *local, | 58 | static inline void drv_configure_filter(struct ieee80211_local *local, |
@@ -53,14 +63,18 @@ static inline void drv_configure_filter(struct ieee80211_local *local, | |||
53 | { | 63 | { |
54 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | 64 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, |
55 | mc_count, mc_list); | 65 | mc_count, mc_list); |
66 | trace_drv_configure_filter(local, changed_flags, total_flags, | ||
67 | mc_count); | ||
56 | } | 68 | } |
57 | 69 | ||
58 | static inline int drv_set_tim(struct ieee80211_local *local, | 70 | static inline int drv_set_tim(struct ieee80211_local *local, |
59 | struct ieee80211_sta *sta, bool set) | 71 | struct ieee80211_sta *sta, bool set) |
60 | { | 72 | { |
73 | int ret = 0; | ||
61 | if (local->ops->set_tim) | 74 | if (local->ops->set_tim) |
62 | return local->ops->set_tim(&local->hw, sta, set); | 75 | ret = local->ops->set_tim(&local->hw, sta, set); |
63 | return 0; | 76 | trace_drv_set_tim(local, sta, set, ret); |
77 | return ret; | ||
64 | } | 78 | } |
65 | 79 | ||
66 | static inline int drv_set_key(struct ieee80211_local *local, | 80 | static inline int drv_set_key(struct ieee80211_local *local, |
@@ -68,7 +82,9 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
68 | struct ieee80211_sta *sta, | 82 | struct ieee80211_sta *sta, |
69 | struct ieee80211_key_conf *key) | 83 | struct ieee80211_key_conf *key) |
70 | { | 84 | { |
71 | return local->ops->set_key(&local->hw, cmd, vif, sta, key); | 85 | int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); |
86 | trace_drv_set_key(local, cmd, vif, sta, key, ret); | ||
87 | return ret; | ||
72 | } | 88 | } |
73 | 89 | ||
74 | static inline void drv_update_tkip_key(struct ieee80211_local *local, | 90 | static inline void drv_update_tkip_key(struct ieee80211_local *local, |
@@ -79,32 +95,41 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
79 | if (local->ops->update_tkip_key) | 95 | if (local->ops->update_tkip_key) |
80 | local->ops->update_tkip_key(&local->hw, conf, address, | 96 | local->ops->update_tkip_key(&local->hw, conf, address, |
81 | iv32, phase1key); | 97 | iv32, phase1key); |
98 | trace_drv_update_tkip_key(local, conf, address, iv32); | ||
82 | } | 99 | } |
83 | 100 | ||
84 | static inline int drv_hw_scan(struct ieee80211_local *local, | 101 | static inline int drv_hw_scan(struct ieee80211_local *local, |
85 | struct cfg80211_scan_request *req) | 102 | struct cfg80211_scan_request *req) |
86 | { | 103 | { |
87 | return local->ops->hw_scan(&local->hw, req); | 104 | int ret = local->ops->hw_scan(&local->hw, req); |
105 | trace_drv_hw_scan(local, req, ret); | ||
106 | return ret; | ||
88 | } | 107 | } |
89 | 108 | ||
90 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 109 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
91 | { | 110 | { |
92 | if (local->ops->sw_scan_start) | 111 | if (local->ops->sw_scan_start) |
93 | local->ops->sw_scan_start(&local->hw); | 112 | local->ops->sw_scan_start(&local->hw); |
113 | trace_drv_sw_scan_start(local); | ||
94 | } | 114 | } |
95 | 115 | ||
96 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 116 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) |
97 | { | 117 | { |
98 | if (local->ops->sw_scan_complete) | 118 | if (local->ops->sw_scan_complete) |
99 | local->ops->sw_scan_complete(&local->hw); | 119 | local->ops->sw_scan_complete(&local->hw); |
120 | trace_drv_sw_scan_complete(local); | ||
100 | } | 121 | } |
101 | 122 | ||
102 | static inline int drv_get_stats(struct ieee80211_local *local, | 123 | static inline int drv_get_stats(struct ieee80211_local *local, |
103 | struct ieee80211_low_level_stats *stats) | 124 | struct ieee80211_low_level_stats *stats) |
104 | { | 125 | { |
105 | if (!local->ops->get_stats) | 126 | int ret = -EOPNOTSUPP; |
106 | return -EOPNOTSUPP; | 127 | |
107 | return local->ops->get_stats(&local->hw, stats); | 128 | if (local->ops->get_stats) |
129 | ret = local->ops->get_stats(&local->hw, stats); | ||
130 | trace_drv_get_stats(local, stats, ret); | ||
131 | |||
132 | return ret; | ||
108 | } | 133 | } |
109 | 134 | ||
110 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, | 135 | static inline void drv_get_tkip_seq(struct ieee80211_local *local, |
@@ -112,14 +137,17 @@ static inline void drv_get_tkip_seq(struct ieee80211_local *local, | |||
112 | { | 137 | { |
113 | if (local->ops->get_tkip_seq) | 138 | if (local->ops->get_tkip_seq) |
114 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); | 139 | local->ops->get_tkip_seq(&local->hw, hw_key_idx, iv32, iv16); |
140 | trace_drv_get_tkip_seq(local, hw_key_idx, iv32, iv16); | ||
115 | } | 141 | } |
116 | 142 | ||
117 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, | 143 | static inline int drv_set_rts_threshold(struct ieee80211_local *local, |
118 | u32 value) | 144 | u32 value) |
119 | { | 145 | { |
146 | int ret = 0; | ||
120 | if (local->ops->set_rts_threshold) | 147 | if (local->ops->set_rts_threshold) |
121 | return local->ops->set_rts_threshold(&local->hw, value); | 148 | ret = local->ops->set_rts_threshold(&local->hw, value); |
122 | return 0; | 149 | trace_drv_set_rts_threshold(local, value, ret); |
150 | return ret; | ||
123 | } | 151 | } |
124 | 152 | ||
125 | static inline void drv_sta_notify(struct ieee80211_local *local, | 153 | static inline void drv_sta_notify(struct ieee80211_local *local, |
@@ -129,46 +157,57 @@ static inline void drv_sta_notify(struct ieee80211_local *local, | |||
129 | { | 157 | { |
130 | if (local->ops->sta_notify) | 158 | if (local->ops->sta_notify) |
131 | local->ops->sta_notify(&local->hw, vif, cmd, sta); | 159 | local->ops->sta_notify(&local->hw, vif, cmd, sta); |
160 | trace_drv_sta_notify(local, vif, cmd, sta); | ||
132 | } | 161 | } |
133 | 162 | ||
134 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 163 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
135 | const struct ieee80211_tx_queue_params *params) | 164 | const struct ieee80211_tx_queue_params *params) |
136 | { | 165 | { |
166 | int ret = -EOPNOTSUPP; | ||
137 | if (local->ops->conf_tx) | 167 | if (local->ops->conf_tx) |
138 | return local->ops->conf_tx(&local->hw, queue, params); | 168 | ret = local->ops->conf_tx(&local->hw, queue, params); |
139 | return -EOPNOTSUPP; | 169 | trace_drv_conf_tx(local, queue, params, ret); |
170 | return ret; | ||
140 | } | 171 | } |
141 | 172 | ||
142 | static inline int drv_get_tx_stats(struct ieee80211_local *local, | 173 | static inline int drv_get_tx_stats(struct ieee80211_local *local, |
143 | struct ieee80211_tx_queue_stats *stats) | 174 | struct ieee80211_tx_queue_stats *stats) |
144 | { | 175 | { |
145 | return local->ops->get_tx_stats(&local->hw, stats); | 176 | int ret = local->ops->get_tx_stats(&local->hw, stats); |
177 | trace_drv_get_tx_stats(local, stats, ret); | ||
178 | return ret; | ||
146 | } | 179 | } |
147 | 180 | ||
148 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 181 | static inline u64 drv_get_tsf(struct ieee80211_local *local) |
149 | { | 182 | { |
183 | u64 ret = -1ULL; | ||
150 | if (local->ops->get_tsf) | 184 | if (local->ops->get_tsf) |
151 | return local->ops->get_tsf(&local->hw); | 185 | ret = local->ops->get_tsf(&local->hw); |
152 | return -1ULL; | 186 | trace_drv_get_tsf(local, ret); |
187 | return ret; | ||
153 | } | 188 | } |
154 | 189 | ||
155 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 190 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) |
156 | { | 191 | { |
157 | if (local->ops->set_tsf) | 192 | if (local->ops->set_tsf) |
158 | local->ops->set_tsf(&local->hw, tsf); | 193 | local->ops->set_tsf(&local->hw, tsf); |
194 | trace_drv_set_tsf(local, tsf); | ||
159 | } | 195 | } |
160 | 196 | ||
161 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 197 | static inline void drv_reset_tsf(struct ieee80211_local *local) |
162 | { | 198 | { |
163 | if (local->ops->reset_tsf) | 199 | if (local->ops->reset_tsf) |
164 | local->ops->reset_tsf(&local->hw); | 200 | local->ops->reset_tsf(&local->hw); |
201 | trace_drv_reset_tsf(local); | ||
165 | } | 202 | } |
166 | 203 | ||
167 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 204 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
168 | { | 205 | { |
206 | int ret = 1; | ||
169 | if (local->ops->tx_last_beacon) | 207 | if (local->ops->tx_last_beacon) |
170 | return local->ops->tx_last_beacon(&local->hw); | 208 | ret = local->ops->tx_last_beacon(&local->hw); |
171 | return 1; | 209 | trace_drv_tx_last_beacon(local, ret); |
210 | return ret; | ||
172 | } | 211 | } |
173 | 212 | ||
174 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 213 | static inline int drv_ampdu_action(struct ieee80211_local *local, |
@@ -176,10 +215,12 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
176 | struct ieee80211_sta *sta, u16 tid, | 215 | struct ieee80211_sta *sta, u16 tid, |
177 | u16 *ssn) | 216 | u16 *ssn) |
178 | { | 217 | { |
218 | int ret = -EOPNOTSUPP; | ||
179 | if (local->ops->ampdu_action) | 219 | if (local->ops->ampdu_action) |
180 | return local->ops->ampdu_action(&local->hw, action, | 220 | ret = local->ops->ampdu_action(&local->hw, action, |
181 | sta, tid, ssn); | 221 | sta, tid, ssn); |
182 | return -EOPNOTSUPP; | 222 | trace_drv_ampdu_action(local, action, sta, tid, ssn, ret); |
223 | return ret; | ||
183 | } | 224 | } |
184 | 225 | ||
185 | 226 | ||
diff --git a/net/mac80211/driver-trace.c b/net/mac80211/driver-trace.c new file mode 100644 index 000000000000..6da6f79932fc --- /dev/null +++ b/net/mac80211/driver-trace.c | |||
@@ -0,0 +1,6 @@ | |||
1 | /* bug in tracepoint.h, it should include this */ | ||
2 | #include <linux/module.h> | ||
3 | |||
4 | #include "driver-ops.h" | ||
5 | #define CREATE_TRACE_POINTS | ||
6 | #include "driver-trace.h" | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h new file mode 100644 index 000000000000..5a10da2d70fd --- /dev/null +++ b/net/mac80211/driver-trace.h | |||
@@ -0,0 +1,648 @@ | |||
1 | #if !defined(__MAC80211_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __MAC80211_DRIVER_TRACE | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | #include <net/mac80211.h> | ||
6 | #include "ieee80211_i.h" | ||
7 | |||
8 | #if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__) | ||
9 | #undef TRACE_EVENT | ||
10 | #define TRACE_EVENT(name, proto, ...) \ | ||
11 | static inline void trace_ ## name(proto) {} | ||
12 | #endif | ||
13 | |||
14 | #undef TRACE_SYSTEM | ||
15 | #define TRACE_SYSTEM mac80211 | ||
16 | |||
17 | #define MAXNAME 32 | ||
18 | #define LOCAL_ENTRY __array(char, wiphy_name, 32) | ||
19 | #define LOCAL_ASSIGN strlcpy(__entry->wiphy_name, wiphy_name(local->hw.wiphy), MAXNAME) | ||
20 | #define LOCAL_PR_FMT "%s" | ||
21 | #define LOCAL_PR_ARG __entry->wiphy_name | ||
22 | |||
23 | #define STA_ENTRY __array(char, sta_addr, ETH_ALEN) | ||
24 | #define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN)) | ||
25 | #define STA_PR_FMT " sta:%pM" | ||
26 | #define STA_PR_ARG __entry->sta_addr | ||
27 | |||
28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) | ||
29 | #define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif | ||
30 | #define VIF_PR_FMT " vif:%p(%d)" | ||
31 | #define VIF_PR_ARG __entry->vif, __entry->vif_type | ||
32 | |||
33 | TRACE_EVENT(drv_start, | ||
34 | TP_PROTO(struct ieee80211_local *local, int ret), | ||
35 | |||
36 | TP_ARGS(local, ret), | ||
37 | |||
38 | TP_STRUCT__entry( | ||
39 | LOCAL_ENTRY | ||
40 | __field(int, ret) | ||
41 | ), | ||
42 | |||
43 | TP_fast_assign( | ||
44 | LOCAL_ASSIGN; | ||
45 | __entry->ret = ret; | ||
46 | ), | ||
47 | |||
48 | TP_printk( | ||
49 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
50 | ) | ||
51 | ); | ||
52 | |||
53 | TRACE_EVENT(drv_stop, | ||
54 | TP_PROTO(struct ieee80211_local *local), | ||
55 | |||
56 | TP_ARGS(local), | ||
57 | |||
58 | TP_STRUCT__entry( | ||
59 | LOCAL_ENTRY | ||
60 | ), | ||
61 | |||
62 | TP_fast_assign( | ||
63 | LOCAL_ASSIGN; | ||
64 | ), | ||
65 | |||
66 | TP_printk( | ||
67 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
68 | ) | ||
69 | ); | ||
70 | |||
71 | TRACE_EVENT(drv_add_interface, | ||
72 | TP_PROTO(struct ieee80211_local *local, | ||
73 | const u8 *addr, | ||
74 | struct ieee80211_vif *vif, | ||
75 | int ret), | ||
76 | |||
77 | TP_ARGS(local, addr, vif, ret), | ||
78 | |||
79 | TP_STRUCT__entry( | ||
80 | LOCAL_ENTRY | ||
81 | VIF_ENTRY | ||
82 | __array(char, addr, 6) | ||
83 | __field(int, ret) | ||
84 | ), | ||
85 | |||
86 | TP_fast_assign( | ||
87 | LOCAL_ASSIGN; | ||
88 | VIF_ASSIGN; | ||
89 | memcpy(__entry->addr, addr, 6); | ||
90 | __entry->ret = ret; | ||
91 | ), | ||
92 | |||
93 | TP_printk( | ||
94 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM ret:%d", | ||
95 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr, __entry->ret | ||
96 | ) | ||
97 | ); | ||
98 | |||
99 | TRACE_EVENT(drv_remove_interface, | ||
100 | TP_PROTO(struct ieee80211_local *local, | ||
101 | const u8 *addr, struct ieee80211_vif *vif), | ||
102 | |||
103 | TP_ARGS(local, addr, vif), | ||
104 | |||
105 | TP_STRUCT__entry( | ||
106 | LOCAL_ENTRY | ||
107 | VIF_ENTRY | ||
108 | __array(char, addr, 6) | ||
109 | ), | ||
110 | |||
111 | TP_fast_assign( | ||
112 | LOCAL_ASSIGN; | ||
113 | VIF_ASSIGN; | ||
114 | memcpy(__entry->addr, addr, 6); | ||
115 | ), | ||
116 | |||
117 | TP_printk( | ||
118 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", | ||
119 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr | ||
120 | ) | ||
121 | ); | ||
122 | |||
123 | TRACE_EVENT(drv_config, | ||
124 | TP_PROTO(struct ieee80211_local *local, | ||
125 | u32 changed, | ||
126 | int ret), | ||
127 | |||
128 | TP_ARGS(local, changed, ret), | ||
129 | |||
130 | TP_STRUCT__entry( | ||
131 | LOCAL_ENTRY | ||
132 | __field(u32, changed) | ||
133 | __field(int, ret) | ||
134 | ), | ||
135 | |||
136 | TP_fast_assign( | ||
137 | LOCAL_ASSIGN; | ||
138 | __entry->changed = changed; | ||
139 | __entry->ret = ret; | ||
140 | ), | ||
141 | |||
142 | TP_printk( | ||
143 | LOCAL_PR_FMT " ch:%#x ret:%d", | ||
144 | LOCAL_PR_ARG, __entry->changed, __entry->ret | ||
145 | ) | ||
146 | ); | ||
147 | |||
148 | TRACE_EVENT(drv_bss_info_changed, | ||
149 | TP_PROTO(struct ieee80211_local *local, | ||
150 | struct ieee80211_vif *vif, | ||
151 | struct ieee80211_bss_conf *info, | ||
152 | u32 changed), | ||
153 | |||
154 | TP_ARGS(local, vif, info, changed), | ||
155 | |||
156 | TP_STRUCT__entry( | ||
157 | LOCAL_ENTRY | ||
158 | VIF_ENTRY | ||
159 | __field(bool, assoc) | ||
160 | __field(u16, aid) | ||
161 | __field(bool, cts) | ||
162 | __field(bool, shortpre) | ||
163 | __field(bool, shortslot) | ||
164 | __field(u8, dtimper) | ||
165 | __field(u16, bcnint) | ||
166 | __field(u16, assoc_cap) | ||
167 | __field(u64, timestamp) | ||
168 | __field(u32, basic_rates) | ||
169 | __field(u32, changed) | ||
170 | ), | ||
171 | |||
172 | TP_fast_assign( | ||
173 | LOCAL_ASSIGN; | ||
174 | VIF_ASSIGN; | ||
175 | __entry->changed = changed; | ||
176 | __entry->aid = info->aid; | ||
177 | __entry->assoc = info->assoc; | ||
178 | __entry->shortpre = info->use_short_preamble; | ||
179 | __entry->cts = info->use_cts_prot; | ||
180 | __entry->shortslot = info->use_short_slot; | ||
181 | __entry->dtimper = info->dtim_period; | ||
182 | __entry->bcnint = info->beacon_int; | ||
183 | __entry->assoc_cap = info->assoc_capability; | ||
184 | __entry->timestamp = info->timestamp; | ||
185 | __entry->basic_rates = info->basic_rates; | ||
186 | ), | ||
187 | |||
188 | TP_printk( | ||
189 | LOCAL_PR_FMT VIF_PR_FMT " changed:%#x", | ||
190 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed | ||
191 | ) | ||
192 | ); | ||
193 | |||
194 | TRACE_EVENT(drv_configure_filter, | ||
195 | TP_PROTO(struct ieee80211_local *local, | ||
196 | unsigned int changed_flags, | ||
197 | unsigned int *total_flags, | ||
198 | int mc_count), | ||
199 | |||
200 | TP_ARGS(local, changed_flags, total_flags, mc_count), | ||
201 | |||
202 | TP_STRUCT__entry( | ||
203 | LOCAL_ENTRY | ||
204 | __field(unsigned int, changed) | ||
205 | __field(unsigned int, total) | ||
206 | __field(int, mc) | ||
207 | ), | ||
208 | |||
209 | TP_fast_assign( | ||
210 | LOCAL_ASSIGN; | ||
211 | __entry->changed = changed_flags; | ||
212 | __entry->total = *total_flags; | ||
213 | __entry->mc = mc_count; | ||
214 | ), | ||
215 | |||
216 | TP_printk( | ||
217 | LOCAL_PR_FMT " changed:%#x total:%#x mc:%d", | ||
218 | LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc | ||
219 | ) | ||
220 | ); | ||
221 | |||
222 | TRACE_EVENT(drv_set_tim, | ||
223 | TP_PROTO(struct ieee80211_local *local, | ||
224 | struct ieee80211_sta *sta, bool set, int ret), | ||
225 | |||
226 | TP_ARGS(local, sta, set, ret), | ||
227 | |||
228 | TP_STRUCT__entry( | ||
229 | LOCAL_ENTRY | ||
230 | STA_ENTRY | ||
231 | __field(bool, set) | ||
232 | __field(int, ret) | ||
233 | ), | ||
234 | |||
235 | TP_fast_assign( | ||
236 | LOCAL_ASSIGN; | ||
237 | STA_ASSIGN; | ||
238 | __entry->set = set; | ||
239 | __entry->ret = ret; | ||
240 | ), | ||
241 | |||
242 | TP_printk( | ||
243 | LOCAL_PR_FMT STA_PR_FMT " set:%d ret:%d", | ||
244 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set, __entry->ret | ||
245 | ) | ||
246 | ); | ||
247 | |||
248 | TRACE_EVENT(drv_set_key, | ||
249 | TP_PROTO(struct ieee80211_local *local, | ||
250 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | ||
251 | struct ieee80211_sta *sta, | ||
252 | struct ieee80211_key_conf *key, int ret), | ||
253 | |||
254 | TP_ARGS(local, cmd, vif, sta, key, ret), | ||
255 | |||
256 | TP_STRUCT__entry( | ||
257 | LOCAL_ENTRY | ||
258 | VIF_ENTRY | ||
259 | STA_ENTRY | ||
260 | __field(enum ieee80211_key_alg, alg) | ||
261 | __field(u8, hw_key_idx) | ||
262 | __field(u8, flags) | ||
263 | __field(s8, keyidx) | ||
264 | __field(int, ret) | ||
265 | ), | ||
266 | |||
267 | TP_fast_assign( | ||
268 | LOCAL_ASSIGN; | ||
269 | VIF_ASSIGN; | ||
270 | STA_ASSIGN; | ||
271 | __entry->alg = key->alg; | ||
272 | __entry->flags = key->flags; | ||
273 | __entry->keyidx = key->keyidx; | ||
274 | __entry->hw_key_idx = key->hw_key_idx; | ||
275 | __entry->ret = ret; | ||
276 | ), | ||
277 | |||
278 | TP_printk( | ||
279 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", | ||
280 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret | ||
281 | ) | ||
282 | ); | ||
283 | |||
284 | TRACE_EVENT(drv_update_tkip_key, | ||
285 | TP_PROTO(struct ieee80211_local *local, | ||
286 | struct ieee80211_key_conf *conf, | ||
287 | const u8 *address, u32 iv32), | ||
288 | |||
289 | TP_ARGS(local, conf, address, iv32), | ||
290 | |||
291 | TP_STRUCT__entry( | ||
292 | LOCAL_ENTRY | ||
293 | __array(u8, addr, 6) | ||
294 | __field(u32, iv32) | ||
295 | ), | ||
296 | |||
297 | TP_fast_assign( | ||
298 | LOCAL_ASSIGN; | ||
299 | memcpy(__entry->addr, address, 6); | ||
300 | __entry->iv32 = iv32; | ||
301 | ), | ||
302 | |||
303 | TP_printk( | ||
304 | LOCAL_PR_FMT " addr:%pM iv32:%#x", | ||
305 | LOCAL_PR_ARG, __entry->addr, __entry->iv32 | ||
306 | ) | ||
307 | ); | ||
308 | |||
309 | TRACE_EVENT(drv_hw_scan, | ||
310 | TP_PROTO(struct ieee80211_local *local, | ||
311 | struct cfg80211_scan_request *req, int ret), | ||
312 | |||
313 | TP_ARGS(local, req, ret), | ||
314 | |||
315 | TP_STRUCT__entry( | ||
316 | LOCAL_ENTRY | ||
317 | __field(int, ret) | ||
318 | ), | ||
319 | |||
320 | TP_fast_assign( | ||
321 | LOCAL_ASSIGN; | ||
322 | __entry->ret = ret; | ||
323 | ), | ||
324 | |||
325 | TP_printk( | ||
326 | LOCAL_PR_FMT " ret:%d", | ||
327 | LOCAL_PR_ARG, __entry->ret | ||
328 | ) | ||
329 | ); | ||
330 | |||
331 | TRACE_EVENT(drv_sw_scan_start, | ||
332 | TP_PROTO(struct ieee80211_local *local), | ||
333 | |||
334 | TP_ARGS(local), | ||
335 | |||
336 | TP_STRUCT__entry( | ||
337 | LOCAL_ENTRY | ||
338 | ), | ||
339 | |||
340 | TP_fast_assign( | ||
341 | LOCAL_ASSIGN; | ||
342 | ), | ||
343 | |||
344 | TP_printk( | ||
345 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
346 | ) | ||
347 | ); | ||
348 | |||
349 | TRACE_EVENT(drv_sw_scan_complete, | ||
350 | TP_PROTO(struct ieee80211_local *local), | ||
351 | |||
352 | TP_ARGS(local), | ||
353 | |||
354 | TP_STRUCT__entry( | ||
355 | LOCAL_ENTRY | ||
356 | ), | ||
357 | |||
358 | TP_fast_assign( | ||
359 | LOCAL_ASSIGN; | ||
360 | ), | ||
361 | |||
362 | TP_printk( | ||
363 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
364 | ) | ||
365 | ); | ||
366 | |||
367 | TRACE_EVENT(drv_get_stats, | ||
368 | TP_PROTO(struct ieee80211_local *local, | ||
369 | struct ieee80211_low_level_stats *stats, | ||
370 | int ret), | ||
371 | |||
372 | TP_ARGS(local, stats, ret), | ||
373 | |||
374 | TP_STRUCT__entry( | ||
375 | LOCAL_ENTRY | ||
376 | __field(int, ret) | ||
377 | __field(unsigned int, ackfail) | ||
378 | __field(unsigned int, rtsfail) | ||
379 | __field(unsigned int, fcserr) | ||
380 | __field(unsigned int, rtssucc) | ||
381 | ), | ||
382 | |||
383 | TP_fast_assign( | ||
384 | LOCAL_ASSIGN; | ||
385 | __entry->ret = ret; | ||
386 | __entry->ackfail = stats->dot11ACKFailureCount; | ||
387 | __entry->rtsfail = stats->dot11RTSFailureCount; | ||
388 | __entry->fcserr = stats->dot11FCSErrorCount; | ||
389 | __entry->rtssucc = stats->dot11RTSSuccessCount; | ||
390 | ), | ||
391 | |||
392 | TP_printk( | ||
393 | LOCAL_PR_FMT " ret:%d", | ||
394 | LOCAL_PR_ARG, __entry->ret | ||
395 | ) | ||
396 | ); | ||
397 | |||
398 | TRACE_EVENT(drv_get_tkip_seq, | ||
399 | TP_PROTO(struct ieee80211_local *local, | ||
400 | u8 hw_key_idx, u32 *iv32, u16 *iv16), | ||
401 | |||
402 | TP_ARGS(local, hw_key_idx, iv32, iv16), | ||
403 | |||
404 | TP_STRUCT__entry( | ||
405 | LOCAL_ENTRY | ||
406 | __field(u8, hw_key_idx) | ||
407 | __field(u32, iv32) | ||
408 | __field(u16, iv16) | ||
409 | ), | ||
410 | |||
411 | TP_fast_assign( | ||
412 | LOCAL_ASSIGN; | ||
413 | __entry->hw_key_idx = hw_key_idx; | ||
414 | __entry->iv32 = *iv32; | ||
415 | __entry->iv16 = *iv16; | ||
416 | ), | ||
417 | |||
418 | TP_printk( | ||
419 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
420 | ) | ||
421 | ); | ||
422 | |||
423 | TRACE_EVENT(drv_set_rts_threshold, | ||
424 | TP_PROTO(struct ieee80211_local *local, u32 value, int ret), | ||
425 | |||
426 | TP_ARGS(local, value, ret), | ||
427 | |||
428 | TP_STRUCT__entry( | ||
429 | LOCAL_ENTRY | ||
430 | __field(u32, value) | ||
431 | __field(int, ret) | ||
432 | ), | ||
433 | |||
434 | TP_fast_assign( | ||
435 | LOCAL_ASSIGN; | ||
436 | __entry->ret = ret; | ||
437 | __entry->value = value; | ||
438 | ), | ||
439 | |||
440 | TP_printk( | ||
441 | LOCAL_PR_FMT " value:%d ret:%d", | ||
442 | LOCAL_PR_ARG, __entry->value, __entry->ret | ||
443 | ) | ||
444 | ); | ||
445 | |||
446 | TRACE_EVENT(drv_sta_notify, | ||
447 | TP_PROTO(struct ieee80211_local *local, | ||
448 | struct ieee80211_vif *vif, | ||
449 | enum sta_notify_cmd cmd, | ||
450 | struct ieee80211_sta *sta), | ||
451 | |||
452 | TP_ARGS(local, vif, cmd, sta), | ||
453 | |||
454 | TP_STRUCT__entry( | ||
455 | LOCAL_ENTRY | ||
456 | VIF_ENTRY | ||
457 | STA_ENTRY | ||
458 | __field(u32, cmd) | ||
459 | ), | ||
460 | |||
461 | TP_fast_assign( | ||
462 | LOCAL_ASSIGN; | ||
463 | VIF_ASSIGN; | ||
464 | STA_ASSIGN; | ||
465 | __entry->cmd = cmd; | ||
466 | ), | ||
467 | |||
468 | TP_printk( | ||
469 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " cmd:%d", | ||
470 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->cmd | ||
471 | ) | ||
472 | ); | ||
473 | |||
474 | TRACE_EVENT(drv_conf_tx, | ||
475 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
476 | const struct ieee80211_tx_queue_params *params, | ||
477 | int ret), | ||
478 | |||
479 | TP_ARGS(local, queue, params, ret), | ||
480 | |||
481 | TP_STRUCT__entry( | ||
482 | LOCAL_ENTRY | ||
483 | __field(u16, queue) | ||
484 | __field(u16, txop) | ||
485 | __field(u16, cw_min) | ||
486 | __field(u16, cw_max) | ||
487 | __field(u8, aifs) | ||
488 | __field(int, ret) | ||
489 | ), | ||
490 | |||
491 | TP_fast_assign( | ||
492 | LOCAL_ASSIGN; | ||
493 | __entry->queue = queue; | ||
494 | __entry->ret = ret; | ||
495 | __entry->txop = params->txop; | ||
496 | __entry->cw_max = params->cw_max; | ||
497 | __entry->cw_min = params->cw_min; | ||
498 | __entry->aifs = params->aifs; | ||
499 | ), | ||
500 | |||
501 | TP_printk( | ||
502 | LOCAL_PR_FMT " queue:%d ret:%d", | ||
503 | LOCAL_PR_ARG, __entry->queue, __entry->ret | ||
504 | ) | ||
505 | ); | ||
506 | |||
507 | TRACE_EVENT(drv_get_tx_stats, | ||
508 | TP_PROTO(struct ieee80211_local *local, | ||
509 | struct ieee80211_tx_queue_stats *stats, | ||
510 | int ret), | ||
511 | |||
512 | TP_ARGS(local, stats, ret), | ||
513 | |||
514 | TP_STRUCT__entry( | ||
515 | LOCAL_ENTRY | ||
516 | __field(int, ret) | ||
517 | ), | ||
518 | |||
519 | TP_fast_assign( | ||
520 | LOCAL_ASSIGN; | ||
521 | __entry->ret = ret; | ||
522 | ), | ||
523 | |||
524 | TP_printk( | ||
525 | LOCAL_PR_FMT " ret:%d", | ||
526 | LOCAL_PR_ARG, __entry->ret | ||
527 | ) | ||
528 | ); | ||
529 | |||
530 | TRACE_EVENT(drv_get_tsf, | ||
531 | TP_PROTO(struct ieee80211_local *local, u64 ret), | ||
532 | |||
533 | TP_ARGS(local, ret), | ||
534 | |||
535 | TP_STRUCT__entry( | ||
536 | LOCAL_ENTRY | ||
537 | __field(u64, ret) | ||
538 | ), | ||
539 | |||
540 | TP_fast_assign( | ||
541 | LOCAL_ASSIGN; | ||
542 | __entry->ret = ret; | ||
543 | ), | ||
544 | |||
545 | TP_printk( | ||
546 | LOCAL_PR_FMT " ret:%llu", | ||
547 | LOCAL_PR_ARG, (unsigned long long)__entry->ret | ||
548 | ) | ||
549 | ); | ||
550 | |||
551 | TRACE_EVENT(drv_set_tsf, | ||
552 | TP_PROTO(struct ieee80211_local *local, u64 tsf), | ||
553 | |||
554 | TP_ARGS(local, tsf), | ||
555 | |||
556 | TP_STRUCT__entry( | ||
557 | LOCAL_ENTRY | ||
558 | __field(u64, tsf) | ||
559 | ), | ||
560 | |||
561 | TP_fast_assign( | ||
562 | LOCAL_ASSIGN; | ||
563 | __entry->tsf = tsf; | ||
564 | ), | ||
565 | |||
566 | TP_printk( | ||
567 | LOCAL_PR_FMT " tsf:%llu", | ||
568 | LOCAL_PR_ARG, (unsigned long long)__entry->tsf | ||
569 | ) | ||
570 | ); | ||
571 | |||
572 | TRACE_EVENT(drv_reset_tsf, | ||
573 | TP_PROTO(struct ieee80211_local *local), | ||
574 | |||
575 | TP_ARGS(local), | ||
576 | |||
577 | TP_STRUCT__entry( | ||
578 | LOCAL_ENTRY | ||
579 | ), | ||
580 | |||
581 | TP_fast_assign( | ||
582 | LOCAL_ASSIGN; | ||
583 | ), | ||
584 | |||
585 | TP_printk( | ||
586 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
587 | ) | ||
588 | ); | ||
589 | |||
590 | TRACE_EVENT(drv_tx_last_beacon, | ||
591 | TP_PROTO(struct ieee80211_local *local, int ret), | ||
592 | |||
593 | TP_ARGS(local, ret), | ||
594 | |||
595 | TP_STRUCT__entry( | ||
596 | LOCAL_ENTRY | ||
597 | __field(int, ret) | ||
598 | ), | ||
599 | |||
600 | TP_fast_assign( | ||
601 | LOCAL_ASSIGN; | ||
602 | __entry->ret = ret; | ||
603 | ), | ||
604 | |||
605 | TP_printk( | ||
606 | LOCAL_PR_FMT " ret:%d", | ||
607 | LOCAL_PR_ARG, __entry->ret | ||
608 | ) | ||
609 | ); | ||
610 | |||
611 | TRACE_EVENT(drv_ampdu_action, | ||
612 | TP_PROTO(struct ieee80211_local *local, | ||
613 | enum ieee80211_ampdu_mlme_action action, | ||
614 | struct ieee80211_sta *sta, u16 tid, | ||
615 | u16 *ssn, int ret), | ||
616 | |||
617 | TP_ARGS(local, action, sta, tid, ssn, ret), | ||
618 | |||
619 | TP_STRUCT__entry( | ||
620 | LOCAL_ENTRY | ||
621 | STA_ENTRY | ||
622 | __field(u32, action) | ||
623 | __field(u16, tid) | ||
624 | __field(u16, ssn) | ||
625 | __field(int, ret) | ||
626 | ), | ||
627 | |||
628 | TP_fast_assign( | ||
629 | LOCAL_ASSIGN; | ||
630 | STA_ASSIGN; | ||
631 | __entry->ret = ret; | ||
632 | __entry->action = action; | ||
633 | __entry->tid = tid; | ||
634 | __entry->ssn = *ssn; | ||
635 | ), | ||
636 | |||
637 | TP_printk( | ||
638 | LOCAL_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", | ||
639 | LOCAL_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | ||
640 | ) | ||
641 | ); | ||
642 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | ||
643 | |||
644 | #undef TRACE_INCLUDE_PATH | ||
645 | #define TRACE_INCLUDE_PATH . | ||
646 | #undef TRACE_INCLUDE_FILE | ||
647 | #define TRACE_INCLUDE_FILE driver-trace | ||
648 | #include <trace/define_trace.h> | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 15d5a53b59a8..8e2220000e5c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -57,7 +57,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
57 | */ | 57 | */ |
58 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) | 58 | if (auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) |
59 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, | 59 | ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, NULL, 0, |
60 | sdata->u.ibss.bssid, 0); | 60 | sdata->u.ibss.bssid, NULL, 0, 0); |
61 | } | 61 | } |
62 | 62 | ||
63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 63 | static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
@@ -494,7 +494,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
494 | 494 | ||
495 | capability = WLAN_CAPABILITY_IBSS; | 495 | capability = WLAN_CAPABILITY_IBSS; |
496 | 496 | ||
497 | if (sdata->default_key) | 497 | if (ifibss->privacy) |
498 | capability |= WLAN_CAPABILITY_PRIVACY; | 498 | capability |= WLAN_CAPABILITY_PRIVACY; |
499 | else | 499 | else |
500 | sdata->drop_unencrypted = 0; | 500 | sdata->drop_unencrypted = 0; |
@@ -524,9 +524,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
524 | return; | 524 | return; |
525 | 525 | ||
526 | capability = WLAN_CAPABILITY_IBSS; | 526 | capability = WLAN_CAPABILITY_IBSS; |
527 | if (sdata->default_key) | 527 | if (ifibss->privacy) |
528 | capability |= WLAN_CAPABILITY_PRIVACY; | 528 | capability |= WLAN_CAPABILITY_PRIVACY; |
529 | |||
530 | if (ifibss->fixed_bssid) | 529 | if (ifibss->fixed_bssid) |
531 | bssid = ifibss->bssid; | 530 | bssid = ifibss->bssid; |
532 | if (ifibss->fixed_channel) | 531 | if (ifibss->fixed_channel) |
@@ -872,6 +871,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
872 | } else | 871 | } else |
873 | sdata->u.ibss.fixed_bssid = false; | 872 | sdata->u.ibss.fixed_bssid = false; |
874 | 873 | ||
874 | sdata->u.ibss.privacy = params->privacy; | ||
875 | |||
875 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 876 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
876 | 877 | ||
877 | sdata->u.ibss.channel = params->channel; | 878 | sdata->u.ibss.channel = params->channel; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 327aabc07abe..6a0177137dd5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -247,18 +247,22 @@ struct ieee80211_mgd_work { | |||
247 | 247 | ||
248 | int tries; | 248 | int tries; |
249 | 249 | ||
250 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
251 | u8 key_len, key_idx; | ||
252 | |||
250 | /* must be last */ | 253 | /* must be last */ |
251 | u8 ie[0]; /* for auth or assoc frame, not probe */ | 254 | u8 ie[0]; /* for auth or assoc frame, not probe */ |
252 | }; | 255 | }; |
253 | 256 | ||
254 | /* flags used in struct ieee80211_if_managed.flags */ | 257 | /* flags used in struct ieee80211_if_managed.flags */ |
255 | enum ieee80211_sta_flags { | 258 | enum ieee80211_sta_flags { |
256 | IEEE80211_STA_PROBEREQ_POLL = BIT(3), | 259 | IEEE80211_STA_BEACON_POLL = BIT(0), |
257 | IEEE80211_STA_CONTROL_PORT = BIT(4), | 260 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
258 | IEEE80211_STA_WMM_ENABLED = BIT(5), | 261 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
259 | IEEE80211_STA_DISABLE_11N = BIT(6), | 262 | IEEE80211_STA_WMM_ENABLED = BIT(3), |
260 | IEEE80211_STA_CSA_RECEIVED = BIT(7), | 263 | IEEE80211_STA_DISABLE_11N = BIT(4), |
261 | IEEE80211_STA_MFP_ENABLED = BIT(8), | 264 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
265 | IEEE80211_STA_MFP_ENABLED = BIT(6), | ||
262 | }; | 266 | }; |
263 | 267 | ||
264 | /* flags for MLME request */ | 268 | /* flags for MLME request */ |
@@ -268,11 +272,16 @@ enum ieee80211_sta_request { | |||
268 | 272 | ||
269 | struct ieee80211_if_managed { | 273 | struct ieee80211_if_managed { |
270 | struct timer_list timer; | 274 | struct timer_list timer; |
275 | struct timer_list conn_mon_timer; | ||
276 | struct timer_list bcn_mon_timer; | ||
271 | struct timer_list chswitch_timer; | 277 | struct timer_list chswitch_timer; |
272 | struct work_struct work; | 278 | struct work_struct work; |
279 | struct work_struct monitor_work; | ||
273 | struct work_struct chswitch_work; | 280 | struct work_struct chswitch_work; |
274 | struct work_struct beacon_loss_work; | 281 | struct work_struct beacon_loss_work; |
275 | 282 | ||
283 | unsigned long probe_timeout; | ||
284 | |||
276 | struct mutex mtx; | 285 | struct mutex mtx; |
277 | struct ieee80211_bss *associated; | 286 | struct ieee80211_bss *associated; |
278 | struct list_head work_list; | 287 | struct list_head work_list; |
@@ -289,8 +298,6 @@ struct ieee80211_if_managed { | |||
289 | 298 | ||
290 | unsigned long request; | 299 | unsigned long request; |
291 | 300 | ||
292 | unsigned long last_beacon; | ||
293 | |||
294 | unsigned int flags; | 301 | unsigned int flags; |
295 | 302 | ||
296 | u32 beacon_crc; | 303 | u32 beacon_crc; |
@@ -321,6 +328,7 @@ struct ieee80211_if_ibss { | |||
321 | 328 | ||
322 | bool fixed_bssid; | 329 | bool fixed_bssid; |
323 | bool fixed_channel; | 330 | bool fixed_channel; |
331 | bool privacy; | ||
324 | 332 | ||
325 | u8 bssid[ETH_ALEN]; | 333 | u8 bssid[ETH_ALEN]; |
326 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 334 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
@@ -559,14 +567,9 @@ enum queue_stop_reason { | |||
559 | IEEE80211_QUEUE_STOP_REASON_CSA, | 567 | IEEE80211_QUEUE_STOP_REASON_CSA, |
560 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 568 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
561 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 569 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
562 | IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
563 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 570 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
564 | }; | 571 | }; |
565 | 572 | ||
566 | struct ieee80211_master_priv { | ||
567 | struct ieee80211_local *local; | ||
568 | }; | ||
569 | |||
570 | struct ieee80211_local { | 573 | struct ieee80211_local { |
571 | /* embed the driver visible part. | 574 | /* embed the driver visible part. |
572 | * don't cast (use the static inlines below), but we keep | 575 | * don't cast (use the static inlines below), but we keep |
@@ -579,13 +582,20 @@ struct ieee80211_local { | |||
579 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 582 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
580 | spinlock_t queue_stop_reason_lock; | 583 | spinlock_t queue_stop_reason_lock; |
581 | 584 | ||
582 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ | ||
583 | int open_count; | 585 | int open_count; |
584 | int monitors, cooked_mntrs; | 586 | int monitors, cooked_mntrs; |
585 | /* number of interfaces with corresponding FIF_ flags */ | 587 | /* number of interfaces with corresponding FIF_ flags */ |
586 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; | 588 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss; |
587 | unsigned int filter_flags; /* FIF_* */ | 589 | unsigned int filter_flags; /* FIF_* */ |
588 | struct iw_statistics wstats; | 590 | struct iw_statistics wstats; |
591 | |||
592 | /* protects the aggregated multicast list and filter calls */ | ||
593 | spinlock_t filter_lock; | ||
594 | |||
595 | /* aggregated multicast list */ | ||
596 | struct dev_addr_list *mc_list; | ||
597 | int mc_count; | ||
598 | |||
589 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 599 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
590 | 600 | ||
591 | /* | 601 | /* |
@@ -805,10 +815,6 @@ struct ieee80211_local { | |||
805 | static inline struct ieee80211_sub_if_data * | 815 | static inline struct ieee80211_sub_if_data * |
806 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | 816 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) |
807 | { | 817 | { |
808 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
809 | |||
810 | BUG_ON(!local || local->mdev == dev); | ||
811 | |||
812 | return netdev_priv(dev); | 818 | return netdev_priv(dev); |
813 | } | 819 | } |
814 | 820 | ||
@@ -988,7 +994,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local); | |||
988 | /* tx handling */ | 994 | /* tx handling */ |
989 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 995 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
990 | void ieee80211_tx_pending(unsigned long data); | 996 | void ieee80211_tx_pending(unsigned long data); |
991 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
992 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 997 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
993 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 998 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
994 | 999 | ||
@@ -1093,8 +1098,8 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
1093 | 1098 | ||
1094 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1099 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1095 | u16 transaction, u16 auth_alg, | 1100 | u16 transaction, u16 auth_alg, |
1096 | u8 *extra, size_t extra_len, | 1101 | u8 *extra, size_t extra_len, const u8 *bssid, |
1097 | const u8 *bssid, int encrypt); | 1102 | const u8 *key, u8 key_len, u8 key_idx); |
1098 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1103 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1099 | const u8 *ie, size_t ie_len); | 1104 | const u8 *ie, size_t ie_len); |
1100 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1105 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 4839a2d97a3b..2f797a86ced5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -190,10 +190,6 @@ static int ieee80211_open(struct net_device *dev) | |||
190 | ETH_ALEN); | 190 | ETH_ALEN); |
191 | } | 191 | } |
192 | 192 | ||
193 | if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) | ||
194 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, | ||
195 | ETH_ALEN); | ||
196 | |||
197 | /* | 193 | /* |
198 | * Validate the MAC address for this device. | 194 | * Validate the MAC address for this device. |
199 | */ | 195 | */ |
@@ -229,9 +225,9 @@ static int ieee80211_open(struct net_device *dev) | |||
229 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 225 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
230 | local->fif_other_bss++; | 226 | local->fif_other_bss++; |
231 | 227 | ||
232 | netif_addr_lock_bh(local->mdev); | 228 | spin_lock_bh(&local->filter_lock); |
233 | ieee80211_configure_filter(local); | 229 | ieee80211_configure_filter(local); |
234 | netif_addr_unlock_bh(local->mdev); | 230 | spin_unlock_bh(&local->filter_lock); |
235 | break; | 231 | break; |
236 | default: | 232 | default: |
237 | conf.vif = &sdata->vif; | 233 | conf.vif = &sdata->vif; |
@@ -243,9 +239,9 @@ static int ieee80211_open(struct net_device *dev) | |||
243 | 239 | ||
244 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 240 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
245 | local->fif_other_bss++; | 241 | local->fif_other_bss++; |
246 | netif_addr_lock_bh(local->mdev); | 242 | spin_lock_bh(&local->filter_lock); |
247 | ieee80211_configure_filter(local); | 243 | ieee80211_configure_filter(local); |
248 | netif_addr_unlock_bh(local->mdev); | 244 | spin_unlock_bh(&local->filter_lock); |
249 | 245 | ||
250 | ieee80211_start_mesh(sdata); | 246 | ieee80211_start_mesh(sdata); |
251 | } | 247 | } |
@@ -279,10 +275,6 @@ static int ieee80211_open(struct net_device *dev) | |||
279 | } | 275 | } |
280 | 276 | ||
281 | if (local->open_count == 0) { | 277 | if (local->open_count == 0) { |
282 | res = dev_open(local->mdev); | ||
283 | WARN_ON(res); | ||
284 | if (res) | ||
285 | goto err_del_interface; | ||
286 | tasklet_enable(&local->tx_pending_tasklet); | 278 | tasklet_enable(&local->tx_pending_tasklet); |
287 | tasklet_enable(&local->tasklet); | 279 | tasklet_enable(&local->tasklet); |
288 | } | 280 | } |
@@ -393,7 +385,14 @@ static int ieee80211_stop(struct net_device *dev) | |||
393 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 385 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
394 | atomic_dec(&local->iff_promiscs); | 386 | atomic_dec(&local->iff_promiscs); |
395 | 387 | ||
396 | dev_mc_unsync(local->mdev, dev); | 388 | netif_addr_lock_bh(dev); |
389 | spin_lock_bh(&local->filter_lock); | ||
390 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | ||
391 | &dev->mc_list, &dev->mc_count); | ||
392 | ieee80211_configure_filter(local); | ||
393 | spin_unlock_bh(&local->filter_lock); | ||
394 | netif_addr_unlock_bh(dev); | ||
395 | |||
397 | del_timer_sync(&local->dynamic_ps_timer); | 396 | del_timer_sync(&local->dynamic_ps_timer); |
398 | cancel_work_sync(&local->dynamic_ps_enable_work); | 397 | cancel_work_sync(&local->dynamic_ps_enable_work); |
399 | 398 | ||
@@ -442,23 +441,25 @@ static int ieee80211_stop(struct net_device *dev) | |||
442 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 441 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
443 | local->fif_other_bss--; | 442 | local->fif_other_bss--; |
444 | 443 | ||
445 | netif_addr_lock_bh(local->mdev); | 444 | spin_lock_bh(&local->filter_lock); |
446 | ieee80211_configure_filter(local); | 445 | ieee80211_configure_filter(local); |
447 | netif_addr_unlock_bh(local->mdev); | 446 | spin_unlock_bh(&local->filter_lock); |
448 | break; | 447 | break; |
449 | case NL80211_IFTYPE_STATION: | 448 | case NL80211_IFTYPE_STATION: |
450 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 449 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
451 | del_timer_sync(&sdata->u.mgd.timer); | 450 | del_timer_sync(&sdata->u.mgd.timer); |
451 | del_timer_sync(&sdata->u.mgd.conn_mon_timer); | ||
452 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | ||
452 | /* | 453 | /* |
453 | * If the timer fired while we waited for it, it will have | 454 | * If any of the timers fired while we waited for it, it will |
454 | * requeued the work. Now the work will be running again | 455 | * have queued its work. Now the work will be running again |
455 | * but will not rearm the timer again because it checks | 456 | * but will not rearm the timer again because it checks |
456 | * whether the interface is running, which, at this point, | 457 | * whether the interface is running, which, at this point, |
457 | * it no longer is. | 458 | * it no longer is. |
458 | */ | 459 | */ |
459 | cancel_work_sync(&sdata->u.mgd.work); | 460 | cancel_work_sync(&sdata->u.mgd.work); |
460 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 461 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
461 | 462 | cancel_work_sync(&sdata->u.mgd.monitor_work); | |
462 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); | 463 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); |
463 | 464 | ||
464 | /* | 465 | /* |
@@ -485,9 +486,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
485 | local->fif_other_bss--; | 486 | local->fif_other_bss--; |
486 | atomic_dec(&local->iff_allmultis); | 487 | atomic_dec(&local->iff_allmultis); |
487 | 488 | ||
488 | netif_addr_lock_bh(local->mdev); | 489 | spin_lock_bh(&local->filter_lock); |
489 | ieee80211_configure_filter(local); | 490 | ieee80211_configure_filter(local); |
490 | netif_addr_unlock_bh(local->mdev); | 491 | spin_unlock_bh(&local->filter_lock); |
491 | 492 | ||
492 | ieee80211_stop_mesh(sdata); | 493 | ieee80211_stop_mesh(sdata); |
493 | } | 494 | } |
@@ -533,9 +534,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
533 | ieee80211_recalc_ps(local, -1); | 534 | ieee80211_recalc_ps(local, -1); |
534 | 535 | ||
535 | if (local->open_count == 0) { | 536 | if (local->open_count == 0) { |
536 | if (netif_running(local->mdev)) | ||
537 | dev_close(local->mdev); | ||
538 | |||
539 | drv_stop(local); | 537 | drv_stop(local); |
540 | 538 | ||
541 | ieee80211_led_radio(local, false); | 539 | ieee80211_led_radio(local, false); |
@@ -582,8 +580,11 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
582 | atomic_dec(&local->iff_promiscs); | 580 | atomic_dec(&local->iff_promiscs); |
583 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 581 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
584 | } | 582 | } |
585 | 583 | spin_lock_bh(&local->filter_lock); | |
586 | dev_mc_sync(local->mdev, dev); | 584 | __dev_addr_sync(&local->mc_list, &local->mc_count, |
585 | &dev->mc_list, &dev->mc_count); | ||
586 | ieee80211_configure_filter(local); | ||
587 | spin_unlock_bh(&local->filter_lock); | ||
587 | } | 588 | } |
588 | 589 | ||
589 | /* | 590 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5b69f5f07299..3234f3751d22 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -83,75 +83,14 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
83 | new_flags |= (1<<31); | 83 | new_flags |= (1<<31); |
84 | 84 | ||
85 | drv_configure_filter(local, changed_flags, &new_flags, | 85 | drv_configure_filter(local, changed_flags, &new_flags, |
86 | local->mdev->mc_count, | 86 | local->mc_count, |
87 | local->mdev->mc_list); | 87 | local->mc_list); |
88 | 88 | ||
89 | WARN_ON(new_flags & (1<<31)); | 89 | WARN_ON(new_flags & (1<<31)); |
90 | 90 | ||
91 | local->filter_flags = new_flags & ~(1<<31); | 91 | local->filter_flags = new_flags & ~(1<<31); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* master interface */ | ||
95 | |||
96 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
97 | { | ||
98 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
99 | return ETH_ALEN; | ||
100 | } | ||
101 | |||
102 | static const struct header_ops ieee80211_header_ops = { | ||
103 | .create = eth_header, | ||
104 | .parse = header_parse_80211, | ||
105 | .rebuild = eth_rebuild_header, | ||
106 | .cache = eth_header_cache, | ||
107 | .cache_update = eth_header_cache_update, | ||
108 | }; | ||
109 | |||
110 | static int ieee80211_master_open(struct net_device *dev) | ||
111 | { | ||
112 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
113 | struct ieee80211_local *local = mpriv->local; | ||
114 | struct ieee80211_sub_if_data *sdata; | ||
115 | int res = -EOPNOTSUPP; | ||
116 | |||
117 | /* we hold the RTNL here so can safely walk the list */ | ||
118 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
119 | if (netif_running(sdata->dev)) { | ||
120 | res = 0; | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (res) | ||
126 | return res; | ||
127 | |||
128 | netif_tx_start_all_queues(local->mdev); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int ieee80211_master_stop(struct net_device *dev) | ||
134 | { | ||
135 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
136 | struct ieee80211_local *local = mpriv->local; | ||
137 | struct ieee80211_sub_if_data *sdata; | ||
138 | |||
139 | /* we hold the RTNL here so can safely walk the list */ | ||
140 | list_for_each_entry(sdata, &local->interfaces, list) | ||
141 | if (netif_running(sdata->dev)) | ||
142 | dev_close(sdata->dev); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | ||
148 | { | ||
149 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
150 | struct ieee80211_local *local = mpriv->local; | ||
151 | |||
152 | ieee80211_configure_filter(local); | ||
153 | } | ||
154 | |||
155 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 94 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
156 | { | 95 | { |
157 | struct ieee80211_channel *chan, *scan_chan; | 96 | struct ieee80211_channel *chan, *scan_chan; |
@@ -310,7 +249,6 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | |||
310 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 249 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
311 | int tmp; | 250 | int tmp; |
312 | 251 | ||
313 | skb->dev = local->mdev; | ||
314 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | 252 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; |
315 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? | 253 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? |
316 | &local->skb_queue : &local->skb_queue_unreliable, skb); | 254 | &local->skb_queue : &local->skb_queue_unreliable, skb); |
@@ -716,7 +654,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
716 | mutex_init(&local->scan_mtx); | 654 | mutex_init(&local->scan_mtx); |
717 | 655 | ||
718 | spin_lock_init(&local->key_lock); | 656 | spin_lock_init(&local->key_lock); |
719 | 657 | spin_lock_init(&local->filter_lock); | |
720 | spin_lock_init(&local->queue_stop_reason_lock); | 658 | spin_lock_init(&local->queue_stop_reason_lock); |
721 | 659 | ||
722 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 660 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
@@ -752,30 +690,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
752 | } | 690 | } |
753 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 691 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
754 | 692 | ||
755 | static const struct net_device_ops ieee80211_master_ops = { | ||
756 | .ndo_start_xmit = ieee80211_master_start_xmit, | ||
757 | .ndo_open = ieee80211_master_open, | ||
758 | .ndo_stop = ieee80211_master_stop, | ||
759 | .ndo_set_multicast_list = ieee80211_master_set_multicast_list, | ||
760 | .ndo_select_queue = ieee80211_select_queue, | ||
761 | }; | ||
762 | |||
763 | static void ieee80211_master_setup(struct net_device *mdev) | ||
764 | { | ||
765 | mdev->type = ARPHRD_IEEE80211; | ||
766 | mdev->netdev_ops = &ieee80211_master_ops; | ||
767 | mdev->header_ops = &ieee80211_header_ops; | ||
768 | mdev->tx_queue_len = 1000; | ||
769 | mdev->addr_len = ETH_ALEN; | ||
770 | } | ||
771 | |||
772 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 693 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
773 | { | 694 | { |
774 | struct ieee80211_local *local = hw_to_local(hw); | 695 | struct ieee80211_local *local = hw_to_local(hw); |
775 | int result; | 696 | int result; |
776 | enum ieee80211_band band; | 697 | enum ieee80211_band band; |
777 | struct net_device *mdev; | ||
778 | struct ieee80211_master_priv *mpriv; | ||
779 | int channels, i, j, max_bitrates; | 698 | int channels, i, j, max_bitrates; |
780 | bool supp_ht; | 699 | bool supp_ht; |
781 | static const u32 cipher_suites[] = { | 700 | static const u32 cipher_suites[] = { |
@@ -874,16 +793,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
874 | if (hw->queues > IEEE80211_MAX_QUEUES) | 793 | if (hw->queues > IEEE80211_MAX_QUEUES) |
875 | hw->queues = IEEE80211_MAX_QUEUES; | 794 | hw->queues = IEEE80211_MAX_QUEUES; |
876 | 795 | ||
877 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), | ||
878 | "wmaster%d", ieee80211_master_setup, | ||
879 | hw->queues); | ||
880 | if (!mdev) | ||
881 | goto fail_mdev_alloc; | ||
882 | |||
883 | mpriv = netdev_priv(mdev); | ||
884 | mpriv->local = local; | ||
885 | local->mdev = mdev; | ||
886 | |||
887 | local->hw.workqueue = | 796 | local->hw.workqueue = |
888 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); | 797 | create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); |
889 | if (!local->hw.workqueue) { | 798 | if (!local->hw.workqueue) { |
@@ -918,17 +827,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
918 | } | 827 | } |
919 | 828 | ||
920 | rtnl_lock(); | 829 | rtnl_lock(); |
921 | result = dev_alloc_name(local->mdev, local->mdev->name); | ||
922 | if (result < 0) | ||
923 | goto fail_dev; | ||
924 | |||
925 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
926 | SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); | ||
927 | local->mdev->features |= NETIF_F_NETNS_LOCAL; | ||
928 | |||
929 | result = register_netdevice(local->mdev); | ||
930 | if (result < 0) | ||
931 | goto fail_dev; | ||
932 | 830 | ||
933 | result = ieee80211_init_rate_ctrl_alg(local, | 831 | result = ieee80211_init_rate_ctrl_alg(local, |
934 | hw->rate_control_algorithm); | 832 | hw->rate_control_algorithm); |
@@ -981,9 +879,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
981 | ieee80211_led_exit(local); | 879 | ieee80211_led_exit(local); |
982 | ieee80211_remove_interfaces(local); | 880 | ieee80211_remove_interfaces(local); |
983 | fail_rate: | 881 | fail_rate: |
984 | unregister_netdevice(local->mdev); | ||
985 | local->mdev = NULL; | ||
986 | fail_dev: | ||
987 | rtnl_unlock(); | 882 | rtnl_unlock(); |
988 | ieee80211_wep_free(local); | 883 | ieee80211_wep_free(local); |
989 | fail_wep: | 884 | fail_wep: |
@@ -992,9 +887,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
992 | debugfs_hw_del(local); | 887 | debugfs_hw_del(local); |
993 | destroy_workqueue(local->hw.workqueue); | 888 | destroy_workqueue(local->hw.workqueue); |
994 | fail_workqueue: | 889 | fail_workqueue: |
995 | if (local->mdev) | ||
996 | free_netdev(local->mdev); | ||
997 | fail_mdev_alloc: | ||
998 | wiphy_unregister(local->hw.wiphy); | 890 | wiphy_unregister(local->hw.wiphy); |
999 | fail_wiphy_register: | 891 | fail_wiphy_register: |
1000 | kfree(local->int_scan_req.channels); | 892 | kfree(local->int_scan_req.channels); |
@@ -1019,13 +911,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1019 | * because the driver cannot be handing us frames any | 911 | * because the driver cannot be handing us frames any |
1020 | * more and the tasklet is killed. | 912 | * more and the tasklet is killed. |
1021 | */ | 913 | */ |
1022 | |||
1023 | /* First, we remove all virtual interfaces. */ | ||
1024 | ieee80211_remove_interfaces(local); | 914 | ieee80211_remove_interfaces(local); |
1025 | 915 | ||
1026 | /* then, finally, remove the master interface */ | ||
1027 | unregister_netdevice(local->mdev); | ||
1028 | |||
1029 | rtnl_unlock(); | 916 | rtnl_unlock(); |
1030 | 917 | ||
1031 | ieee80211_clear_tx_pending(local); | 918 | ieee80211_clear_tx_pending(local); |
@@ -1044,7 +931,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1044 | wiphy_unregister(local->hw.wiphy); | 931 | wiphy_unregister(local->hw.wiphy); |
1045 | ieee80211_wep_free(local); | 932 | ieee80211_wep_free(local); |
1046 | ieee80211_led_exit(local); | 933 | ieee80211_led_exit(local); |
1047 | free_netdev(local->mdev); | ||
1048 | kfree(local->int_scan_req.channels); | 934 | kfree(local->int_scan_req.channels); |
1049 | } | 935 | } |
1050 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 936 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 542ea025494e..8a97b1423088 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -685,9 +685,12 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
685 | fc = le16_to_cpu(mgmt->frame_control); | 685 | fc = le16_to_cpu(mgmt->frame_control); |
686 | 686 | ||
687 | switch (fc & IEEE80211_FCTL_STYPE) { | 687 | switch (fc & IEEE80211_FCTL_STYPE) { |
688 | case IEEE80211_STYPE_ACTION: | ||
689 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
690 | return RX_DROP_MONITOR; | ||
691 | /* fall through */ | ||
688 | case IEEE80211_STYPE_PROBE_RESP: | 692 | case IEEE80211_STYPE_PROBE_RESP: |
689 | case IEEE80211_STYPE_BEACON: | 693 | case IEEE80211_STYPE_BEACON: |
690 | case IEEE80211_STYPE_ACTION: | ||
691 | skb_queue_tail(&ifmsh->skb_queue, skb); | 694 | skb_queue_tail(&ifmsh->skb_queue, skb); |
692 | queue_work(local->hw.workqueue, &ifmsh->work); | 695 | queue_work(local->hw.workqueue, &ifmsh->work); |
693 | return RX_QUEUED; | 696 | return RX_QUEUED; |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index f49ef288e2e2..e93c37ef6a48 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -686,11 +686,11 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
686 | u8 ttl, dst_flags; | 686 | u8 ttl, dst_flags; |
687 | u32 lifetime; | 687 | u32 lifetime; |
688 | 688 | ||
689 | spin_lock(&ifmsh->mesh_preq_queue_lock); | 689 | spin_lock_bh(&ifmsh->mesh_preq_queue_lock); |
690 | if (!ifmsh->preq_queue_len || | 690 | if (!ifmsh->preq_queue_len || |
691 | time_before(jiffies, ifmsh->last_preq + | 691 | time_before(jiffies, ifmsh->last_preq + |
692 | min_preq_int_jiff(sdata))) { | 692 | min_preq_int_jiff(sdata))) { |
693 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 693 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
694 | return; | 694 | return; |
695 | } | 695 | } |
696 | 696 | ||
@@ -698,7 +698,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
698 | struct mesh_preq_queue, list); | 698 | struct mesh_preq_queue, list); |
699 | list_del(&preq_node->list); | 699 | list_del(&preq_node->list); |
700 | --ifmsh->preq_queue_len; | 700 | --ifmsh->preq_queue_len; |
701 | spin_unlock(&ifmsh->mesh_preq_queue_lock); | 701 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
702 | 702 | ||
703 | rcu_read_lock(); | 703 | rcu_read_lock(); |
704 | mpath = mesh_path_lookup(preq_node->dst, sdata); | 704 | mpath = mesh_path_lookup(preq_node->dst, sdata); |
@@ -784,7 +784,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
784 | mesh_path_add(dst_addr, sdata); | 784 | mesh_path_add(dst_addr, sdata); |
785 | mpath = mesh_path_lookup(dst_addr, sdata); | 785 | mpath = mesh_path_lookup(dst_addr, sdata); |
786 | if (!mpath) { | 786 | if (!mpath) { |
787 | dev_kfree_skb(skb); | ||
788 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 787 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
789 | err = -ENOSPC; | 788 | err = -ENOSPC; |
790 | goto endlookup; | 789 | goto endlookup; |
@@ -804,6 +803,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
804 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, | 803 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, |
805 | ETH_ALEN); | 804 | ETH_ALEN); |
806 | } else { | 805 | } else { |
806 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
807 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 807 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
808 | /* Start discovery only if it is not running yet */ | 808 | /* Start discovery only if it is not running yet */ |
809 | mesh_queue_preq(mpath, PREQ_Q_F_START); | 809 | mesh_queue_preq(mpath, PREQ_Q_F_START); |
@@ -815,6 +815,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
815 | skb_unlink(skb_to_free, &mpath->frame_queue); | 815 | skb_unlink(skb_to_free, &mpath->frame_queue); |
816 | } | 816 | } |
817 | 817 | ||
818 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
818 | skb_queue_tail(&mpath->frame_queue, skb); | 819 | skb_queue_tail(&mpath->frame_queue, skb); |
819 | if (skb_to_free) | 820 | if (skb_to_free) |
820 | mesh_path_discard_frame(skb_to_free, sdata); | 821 | mesh_path_discard_frame(skb_to_free, sdata); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 479597e88583..04b9e4d61b8e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -55,7 +55,25 @@ static DEFINE_RWLOCK(pathtbl_resize_lock); | |||
55 | */ | 55 | */ |
56 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | 56 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) |
57 | { | 57 | { |
58 | struct sk_buff *skb; | ||
59 | struct ieee80211_hdr *hdr; | ||
60 | struct sk_buff_head tmpq; | ||
61 | unsigned long flags; | ||
62 | |||
58 | rcu_assign_pointer(mpath->next_hop, sta); | 63 | rcu_assign_pointer(mpath->next_hop, sta); |
64 | |||
65 | __skb_queue_head_init(&tmpq); | ||
66 | |||
67 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); | ||
68 | |||
69 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | ||
70 | hdr = (struct ieee80211_hdr *) skb->data; | ||
71 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | ||
72 | __skb_queue_tail(&tmpq, skb); | ||
73 | } | ||
74 | |||
75 | skb_queue_splice(&tmpq, &mpath->frame_queue); | ||
76 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); | ||
59 | } | 77 | } |
60 | 78 | ||
61 | 79 | ||
@@ -481,11 +499,9 @@ enddel: | |||
481 | */ | 499 | */ |
482 | void mesh_path_tx_pending(struct mesh_path *mpath) | 500 | void mesh_path_tx_pending(struct mesh_path *mpath) |
483 | { | 501 | { |
484 | struct sk_buff *skb; | 502 | if (mpath->flags & MESH_PATH_ACTIVE) |
485 | 503 | ieee80211_add_pending_skbs(mpath->sdata->local, | |
486 | while ((skb = skb_dequeue(&mpath->frame_queue)) && | 504 | &mpath->frame_queue); |
487 | (mpath->flags & MESH_PATH_ACTIVE)) | ||
488 | dev_queue_xmit(skb); | ||
489 | } | 505 | } |
490 | 506 | ||
491 | /** | 507 | /** |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c9db9646025b..523c0d994d15 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -31,8 +31,23 @@ | |||
31 | #define IEEE80211_AUTH_MAX_TRIES 3 | 31 | #define IEEE80211_AUTH_MAX_TRIES 3 |
32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
33 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 33 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
34 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 34 | |
35 | #define IEEE80211_PROBE_WAIT (HZ / 5) | 35 | /* |
36 | * beacon loss detection timeout | ||
37 | * XXX: should depend on beacon interval | ||
38 | */ | ||
39 | #define IEEE80211_BEACON_LOSS_TIME (2 * HZ) | ||
40 | /* | ||
41 | * Time the connection can be idle before we probe | ||
42 | * it to see if we can still talk to the AP. | ||
43 | */ | ||
44 | #define IEEE80211_CONNECTION_IDLE_TIME (2 * HZ) | ||
45 | /* | ||
46 | * Time we wait for a probe response after sending | ||
47 | * a probe request because of beacon loss or for | ||
48 | * checking the connection still works. | ||
49 | */ | ||
50 | #define IEEE80211_PROBE_WAIT (HZ / 5) | ||
36 | 51 | ||
37 | #define TMR_RUNNING_TIMER 0 | 52 | #define TMR_RUNNING_TIMER 0 |
38 | #define TMR_RUNNING_CHANSW 1 | 53 | #define TMR_RUNNING_CHANSW 1 |
@@ -72,6 +87,35 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | |||
72 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); | 87 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); |
73 | } | 88 | } |
74 | 89 | ||
90 | /* | ||
91 | * We can have multiple work items (and connection probing) | ||
92 | * scheduling this timer, but we need to take care to only | ||
93 | * reschedule it when it should fire _earlier_ than it was | ||
94 | * asked for before, or if it's not pending right now. This | ||
95 | * function ensures that. Note that it then is required to | ||
96 | * run this function for all timeouts after the first one | ||
97 | * has happened -- the work that runs from this timer will | ||
98 | * do that. | ||
99 | */ | ||
100 | static void run_again(struct ieee80211_if_managed *ifmgd, | ||
101 | unsigned long timeout) | ||
102 | { | ||
103 | ASSERT_MGD_MTX(ifmgd); | ||
104 | |||
105 | if (!timer_pending(&ifmgd->timer) || | ||
106 | time_before(timeout, ifmgd->timer.expires)) | ||
107 | mod_timer(&ifmgd->timer, timeout); | ||
108 | } | ||
109 | |||
110 | static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | ||
111 | { | ||
112 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | ||
113 | return; | ||
114 | |||
115 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | ||
116 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | ||
117 | } | ||
118 | |||
75 | static int ecw2cw(int ecw) | 119 | static int ecw2cw(int ecw) |
76 | { | 120 | { |
77 | return (1 << ecw) - 1; | 121 | return (1 << ecw) - 1; |
@@ -646,7 +690,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
646 | 690 | ||
647 | if (count == 1 && found->u.mgd.powersave && | 691 | if (count == 1 && found->u.mgd.powersave && |
648 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && | 692 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && |
649 | !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) { | 693 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
694 | IEEE80211_STA_CONNECTION_POLL))) { | ||
650 | s32 beaconint_us; | 695 | s32 beaconint_us; |
651 | 696 | ||
652 | if (latency < 0) | 697 | if (latency < 0) |
@@ -852,6 +897,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
852 | sdata->u.mgd.associated = bss; | 897 | sdata->u.mgd.associated = bss; |
853 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); | 898 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); |
854 | 899 | ||
900 | /* just to be sure */ | ||
901 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
902 | IEEE80211_STA_BEACON_POLL); | ||
903 | |||
855 | ieee80211_led_assoc(local, 1); | 904 | ieee80211_led_assoc(local, 1); |
856 | 905 | ||
857 | sdata->vif.bss_conf.assoc = 1; | 906 | sdata->vif.bss_conf.assoc = 1; |
@@ -916,7 +965,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
916 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); | 965 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); |
917 | 966 | ||
918 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 967 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
919 | mod_timer(&ifmgd->timer, wk->timeout); | 968 | run_again(ifmgd, wk->timeout); |
920 | 969 | ||
921 | return RX_MGMT_NONE; | 970 | return RX_MGMT_NONE; |
922 | } | 971 | } |
@@ -954,25 +1003,30 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
954 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1003 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); |
955 | 1004 | ||
956 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | 1005 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, |
957 | wk->bss->cbss.bssid, 0); | 1006 | wk->bss->cbss.bssid, NULL, 0, 0); |
958 | wk->auth_transaction = 2; | 1007 | wk->auth_transaction = 2; |
959 | 1008 | ||
960 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 1009 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
961 | mod_timer(&ifmgd->timer, wk->timeout); | 1010 | run_again(ifmgd, wk->timeout); |
962 | 1011 | ||
963 | return RX_MGMT_NONE; | 1012 | return RX_MGMT_NONE; |
964 | } | 1013 | } |
965 | 1014 | ||
966 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 1015 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) |
967 | const u8 *bssid, bool deauth) | ||
968 | { | 1016 | { |
969 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1017 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
970 | struct ieee80211_local *local = sdata->local; | 1018 | struct ieee80211_local *local = sdata->local; |
971 | struct sta_info *sta; | 1019 | struct sta_info *sta; |
972 | u32 changed = 0, config_changed = 0; | 1020 | u32 changed = 0, config_changed = 0; |
1021 | u8 bssid[ETH_ALEN]; | ||
973 | 1022 | ||
974 | ASSERT_MGD_MTX(ifmgd); | 1023 | ASSERT_MGD_MTX(ifmgd); |
975 | 1024 | ||
1025 | if (WARN_ON(!ifmgd->associated)) | ||
1026 | return; | ||
1027 | |||
1028 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
1029 | |||
976 | ifmgd->associated = NULL; | 1030 | ifmgd->associated = NULL; |
977 | memset(ifmgd->bssid, 0, ETH_ALEN); | 1031 | memset(ifmgd->bssid, 0, ETH_ALEN); |
978 | 1032 | ||
@@ -1079,7 +1133,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1079 | ieee80211_send_assoc(sdata, wk); | 1133 | ieee80211_send_assoc(sdata, wk); |
1080 | 1134 | ||
1081 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 1135 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
1082 | mod_timer(&ifmgd->timer, wk->timeout); | 1136 | run_again(ifmgd, wk->timeout); |
1083 | 1137 | ||
1084 | return RX_MGMT_NONE; | 1138 | return RX_MGMT_NONE; |
1085 | } | 1139 | } |
@@ -1092,31 +1146,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1092 | * from AP because we know that the connection is working both ways | 1146 | * from AP because we know that the connection is working both ways |
1093 | * at that time. But multicast frames (and hence also beacons) must | 1147 | * at that time. But multicast frames (and hence also beacons) must |
1094 | * be ignored here, because we need to trigger the timer during | 1148 | * be ignored here, because we need to trigger the timer during |
1095 | * data idle periods for sending the periodical probe request to | 1149 | * data idle periods for sending the periodic probe request to the |
1096 | * the AP. | 1150 | * AP we're connected to. |
1097 | */ | 1151 | */ |
1098 | if (!is_multicast_ether_addr(hdr->addr1)) | 1152 | if (is_multicast_ether_addr(hdr->addr1)) |
1099 | mod_timer(&sdata->u.mgd.timer, | 1153 | return; |
1100 | jiffies + IEEE80211_MONITORING_INTERVAL); | 1154 | |
1155 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
1156 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
1101 | } | 1157 | } |
1102 | 1158 | ||
1103 | void ieee80211_beacon_loss_work(struct work_struct *work) | 1159 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
1160 | bool beacon) | ||
1104 | { | 1161 | { |
1105 | struct ieee80211_sub_if_data *sdata = | ||
1106 | container_of(work, struct ieee80211_sub_if_data, | ||
1107 | u.mgd.beacon_loss_work); | ||
1108 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1162 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1109 | const u8 *ssid; | 1163 | const u8 *ssid; |
1164 | bool already = false; | ||
1110 | 1165 | ||
1111 | /* | 1166 | if (!netif_running(sdata->dev)) |
1112 | * The driver has already reported this event and we have | ||
1113 | * already sent a probe request. Maybe the AP died and the | ||
1114 | * driver keeps reporting until we disassociate... We have | ||
1115 | * to ignore that because otherwise we would continually | ||
1116 | * reset the timer and never check whether we received a | ||
1117 | * probe response! | ||
1118 | */ | ||
1119 | if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) | ||
1120 | return; | 1167 | return; |
1121 | 1168 | ||
1122 | mutex_lock(&ifmgd->mtx); | 1169 | mutex_lock(&ifmgd->mtx); |
@@ -1125,12 +1172,35 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1125 | goto out; | 1172 | goto out; |
1126 | 1173 | ||
1127 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1174 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1128 | if (net_ratelimit()) | 1175 | if (beacon && net_ratelimit()) |
1129 | printk(KERN_DEBUG "%s: driver reports beacon loss from AP " | 1176 | printk(KERN_DEBUG "%s: detected beacon loss from AP " |
1130 | "- sending probe request\n", sdata->dev->name); | 1177 | "- sending probe request\n", sdata->dev->name); |
1131 | #endif | 1178 | #endif |
1132 | 1179 | ||
1133 | ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; | 1180 | /* |
1181 | * The driver/our work has already reported this event or the | ||
1182 | * connection monitoring has kicked in and we have already sent | ||
1183 | * a probe request. Or maybe the AP died and the driver keeps | ||
1184 | * reporting until we disassociate... | ||
1185 | * | ||
1186 | * In either case we have to ignore the current call to this | ||
1187 | * function (except for setting the correct probe reason bit) | ||
1188 | * because otherwise we would reset the timer every time and | ||
1189 | * never check whether we received a probe response! | ||
1190 | */ | ||
1191 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
1192 | IEEE80211_STA_CONNECTION_POLL)) | ||
1193 | already = true; | ||
1194 | |||
1195 | if (beacon) | ||
1196 | ifmgd->flags |= IEEE80211_STA_BEACON_POLL; | ||
1197 | else | ||
1198 | ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; | ||
1199 | |||
1200 | if (already) | ||
1201 | goto out; | ||
1202 | |||
1203 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | ||
1134 | 1204 | ||
1135 | mutex_lock(&sdata->local->iflist_mtx); | 1205 | mutex_lock(&sdata->local->iflist_mtx); |
1136 | ieee80211_recalc_ps(sdata->local, -1); | 1206 | ieee80211_recalc_ps(sdata->local, -1); |
@@ -1140,11 +1210,21 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
1140 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 1210 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, |
1141 | ssid + 2, ssid[1], NULL, 0); | 1211 | ssid + 2, ssid[1], NULL, 0); |
1142 | 1212 | ||
1143 | mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); | 1213 | run_again(ifmgd, ifmgd->probe_timeout); |
1214 | |||
1144 | out: | 1215 | out: |
1145 | mutex_unlock(&ifmgd->mtx); | 1216 | mutex_unlock(&ifmgd->mtx); |
1146 | } | 1217 | } |
1147 | 1218 | ||
1219 | void ieee80211_beacon_loss_work(struct work_struct *work) | ||
1220 | { | ||
1221 | struct ieee80211_sub_if_data *sdata = | ||
1222 | container_of(work, struct ieee80211_sub_if_data, | ||
1223 | u.mgd.beacon_loss_work); | ||
1224 | |||
1225 | ieee80211_mgd_probe_ap(sdata, true); | ||
1226 | } | ||
1227 | |||
1148 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1228 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
1149 | { | 1229 | { |
1150 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1230 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
@@ -1176,7 +1256,8 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1176 | return; | 1256 | return; |
1177 | ieee80211_send_auth(sdata, 3, wk->auth_alg, | 1257 | ieee80211_send_auth(sdata, 3, wk->auth_alg, |
1178 | elems.challenge - 2, elems.challenge_len + 2, | 1258 | elems.challenge - 2, elems.challenge_len + 2, |
1179 | wk->bss->cbss.bssid, 1); | 1259 | wk->bss->cbss.bssid, |
1260 | wk->key, wk->key_len, wk->key_idx); | ||
1180 | wk->auth_transaction = 4; | 1261 | wk->auth_transaction = 4; |
1181 | } | 1262 | } |
1182 | 1263 | ||
@@ -1257,7 +1338,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1257 | sdata->dev->name, bssid, reason_code); | 1338 | sdata->dev->name, bssid, reason_code); |
1258 | 1339 | ||
1259 | if (!wk) { | 1340 | if (!wk) { |
1260 | ieee80211_set_disassoc(sdata, bssid, true); | 1341 | ieee80211_set_disassoc(sdata); |
1261 | } else { | 1342 | } else { |
1262 | list_del(&wk->list); | 1343 | list_del(&wk->list); |
1263 | kfree(wk); | 1344 | kfree(wk); |
@@ -1290,7 +1371,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1290 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", | 1371 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", |
1291 | sdata->dev->name, reason_code); | 1372 | sdata->dev->name, reason_code); |
1292 | 1373 | ||
1293 | ieee80211_set_disassoc(sdata, ifmgd->associated->cbss.bssid, false); | 1374 | ieee80211_set_disassoc(sdata); |
1294 | return RX_MGMT_CFG80211_DISASSOC; | 1375 | return RX_MGMT_CFG80211_DISASSOC; |
1295 | } | 1376 | } |
1296 | 1377 | ||
@@ -1349,8 +1430,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1349 | sdata->dev->name, tu, ms); | 1430 | sdata->dev->name, tu, ms); |
1350 | wk->timeout = jiffies + msecs_to_jiffies(ms); | 1431 | wk->timeout = jiffies + msecs_to_jiffies(ms); |
1351 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 1432 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
1352 | mod_timer(&ifmgd->timer, | 1433 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); |
1353 | jiffies + msecs_to_jiffies(ms)); | ||
1354 | return RX_MGMT_NONE; | 1434 | return RX_MGMT_NONE; |
1355 | } | 1435 | } |
1356 | 1436 | ||
@@ -1392,9 +1472,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1392 | return RX_MGMT_NONE; | 1472 | return RX_MGMT_NONE; |
1393 | } | 1473 | } |
1394 | 1474 | ||
1395 | /* update new sta with its last rx activity */ | ||
1396 | sta->last_rx = jiffies; | ||
1397 | |||
1398 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | 1475 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | |
1399 | WLAN_STA_ASSOC_AP); | 1476 | WLAN_STA_ASSOC_AP); |
1400 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 1477 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
@@ -1497,10 +1574,11 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1497 | ieee80211_set_associated(sdata, wk->bss, changed); | 1574 | ieee80211_set_associated(sdata, wk->bss, changed); |
1498 | 1575 | ||
1499 | /* | 1576 | /* |
1500 | * initialise the time of last beacon to be the association time, | 1577 | * Start timer to probe the connection to the AP now. |
1501 | * otherwise beacon loss check will trigger immediately | 1578 | * Also start the timer that will detect beacon loss. |
1502 | */ | 1579 | */ |
1503 | ifmgd->last_beacon = jiffies; | 1580 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1581 | mod_beacon_timer(sdata); | ||
1504 | 1582 | ||
1505 | list_del(&wk->list); | 1583 | list_del(&wk->list); |
1506 | kfree(wk); | 1584 | kfree(wk); |
@@ -1584,11 +1662,22 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1584 | 1662 | ||
1585 | if (ifmgd->associated && | 1663 | if (ifmgd->associated && |
1586 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && | 1664 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && |
1587 | ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { | 1665 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
1588 | ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 1666 | IEEE80211_STA_CONNECTION_POLL)) { |
1667 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
1668 | IEEE80211_STA_BEACON_POLL); | ||
1589 | mutex_lock(&sdata->local->iflist_mtx); | 1669 | mutex_lock(&sdata->local->iflist_mtx); |
1590 | ieee80211_recalc_ps(sdata->local, -1); | 1670 | ieee80211_recalc_ps(sdata->local, -1); |
1591 | mutex_unlock(&sdata->local->iflist_mtx); | 1671 | mutex_unlock(&sdata->local->iflist_mtx); |
1672 | /* | ||
1673 | * We've received a probe response, but are not sure whether | ||
1674 | * we have or will be receiving any beacons or data, so let's | ||
1675 | * schedule the timers again, just in case. | ||
1676 | */ | ||
1677 | mod_beacon_timer(sdata); | ||
1678 | mod_timer(&ifmgd->conn_mon_timer, | ||
1679 | round_jiffies_up(jiffies + | ||
1680 | IEEE80211_CONNECTION_IDLE_TIME)); | ||
1592 | } | 1681 | } |
1593 | } | 1682 | } |
1594 | 1683 | ||
@@ -1638,27 +1727,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1638 | if (rx_status->freq != local->hw.conf.channel->center_freq) | 1727 | if (rx_status->freq != local->hw.conf.channel->center_freq) |
1639 | return; | 1728 | return; |
1640 | 1729 | ||
1641 | if (WARN_ON(!ifmgd->associated)) | 1730 | /* |
1731 | * We might have received a number of frames, among them a | ||
1732 | * disassoc frame and a beacon... | ||
1733 | */ | ||
1734 | if (!ifmgd->associated) | ||
1642 | return; | 1735 | return; |
1643 | 1736 | ||
1644 | bssid = ifmgd->associated->cbss.bssid; | 1737 | bssid = ifmgd->associated->cbss.bssid; |
1645 | 1738 | ||
1646 | if (WARN_ON(memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)) | 1739 | /* |
1740 | * And in theory even frames from a different AP we were just | ||
1741 | * associated to a split-second ago! | ||
1742 | */ | ||
1743 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1647 | return; | 1744 | return; |
1648 | 1745 | ||
1649 | if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) { | 1746 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
1650 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1747 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1651 | if (net_ratelimit()) { | 1748 | if (net_ratelimit()) { |
1652 | printk(KERN_DEBUG "%s: cancelling probereq poll due " | 1749 | printk(KERN_DEBUG "%s: cancelling probereq poll due " |
1653 | "to a received beacon\n", sdata->dev->name); | 1750 | "to a received beacon\n", sdata->dev->name); |
1654 | } | 1751 | } |
1655 | #endif | 1752 | #endif |
1656 | ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 1753 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
1657 | mutex_lock(&local->iflist_mtx); | 1754 | mutex_lock(&local->iflist_mtx); |
1658 | ieee80211_recalc_ps(local, -1); | 1755 | ieee80211_recalc_ps(local, -1); |
1659 | mutex_unlock(&local->iflist_mtx); | 1756 | mutex_unlock(&local->iflist_mtx); |
1660 | } | 1757 | } |
1661 | 1758 | ||
1759 | /* | ||
1760 | * Push the beacon loss detection into the future since | ||
1761 | * we are processing a beacon from the AP just now. | ||
1762 | */ | ||
1763 | mod_beacon_timer(sdata); | ||
1764 | |||
1662 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | 1765 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); |
1663 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, | 1766 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, |
1664 | len - baselen, &elems, | 1767 | len - baselen, &elems, |
@@ -1960,6 +2063,37 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1960 | /* then process the rest of the work */ | 2063 | /* then process the rest of the work */ |
1961 | mutex_lock(&ifmgd->mtx); | 2064 | mutex_lock(&ifmgd->mtx); |
1962 | 2065 | ||
2066 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | ||
2067 | IEEE80211_STA_CONNECTION_POLL) && | ||
2068 | ifmgd->associated) { | ||
2069 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | ||
2070 | run_again(ifmgd, ifmgd->probe_timeout); | ||
2071 | else { | ||
2072 | u8 bssid[ETH_ALEN]; | ||
2073 | /* | ||
2074 | * We actually lost the connection ... or did we? | ||
2075 | * Let's make sure! | ||
2076 | */ | ||
2077 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | ||
2078 | IEEE80211_STA_BEACON_POLL); | ||
2079 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | ||
2080 | printk(KERN_DEBUG "No probe response from AP %pM" | ||
2081 | " after %dms, disconnecting.\n", | ||
2082 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | ||
2083 | ieee80211_set_disassoc(sdata); | ||
2084 | mutex_unlock(&ifmgd->mtx); | ||
2085 | /* | ||
2086 | * must be outside lock due to cfg80211, | ||
2087 | * but that's not a problem. | ||
2088 | */ | ||
2089 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
2090 | IEEE80211_STYPE_DEAUTH, | ||
2091 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
2092 | NULL); | ||
2093 | mutex_lock(&ifmgd->mtx); | ||
2094 | } | ||
2095 | } | ||
2096 | |||
1963 | list_for_each_entry(wk, &ifmgd->work_list, list) { | 2097 | list_for_each_entry(wk, &ifmgd->work_list, list) { |
1964 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { | 2098 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { |
1965 | anybusy = true; | 2099 | anybusy = true; |
@@ -1980,8 +2114,15 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1980 | } | 2114 | } |
1981 | 2115 | ||
1982 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { | 2116 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { |
1983 | if (time_before(jiffies, wk->timeout)) | 2117 | if (time_is_after_jiffies(wk->timeout)) { |
2118 | /* | ||
2119 | * This work item isn't supposed to be worked on | ||
2120 | * right now, but take care to adjust the timer | ||
2121 | * properly. | ||
2122 | */ | ||
2123 | run_again(ifmgd, wk->timeout); | ||
1984 | continue; | 2124 | continue; |
2125 | } | ||
1985 | 2126 | ||
1986 | switch (wk->state) { | 2127 | switch (wk->state) { |
1987 | default: | 2128 | default: |
@@ -2040,15 +2181,54 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2040 | ieee80211_recalc_idle(local); | 2181 | ieee80211_recalc_idle(local); |
2041 | } | 2182 | } |
2042 | 2183 | ||
2184 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | ||
2185 | { | ||
2186 | struct ieee80211_sub_if_data *sdata = | ||
2187 | (struct ieee80211_sub_if_data *) data; | ||
2188 | struct ieee80211_local *local = sdata->local; | ||
2189 | |||
2190 | if (local->quiescing) | ||
2191 | return; | ||
2192 | |||
2193 | queue_work(sdata->local->hw.workqueue, | ||
2194 | &sdata->u.mgd.beacon_loss_work); | ||
2195 | } | ||
2196 | |||
2197 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | ||
2198 | { | ||
2199 | struct ieee80211_sub_if_data *sdata = | ||
2200 | (struct ieee80211_sub_if_data *) data; | ||
2201 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2202 | struct ieee80211_local *local = sdata->local; | ||
2203 | |||
2204 | if (local->quiescing) | ||
2205 | return; | ||
2206 | |||
2207 | queue_work(local->hw.workqueue, &ifmgd->monitor_work); | ||
2208 | } | ||
2209 | |||
2210 | static void ieee80211_sta_monitor_work(struct work_struct *work) | ||
2211 | { | ||
2212 | struct ieee80211_sub_if_data *sdata = | ||
2213 | container_of(work, struct ieee80211_sub_if_data, | ||
2214 | u.mgd.monitor_work); | ||
2215 | |||
2216 | if (sdata->local->sw_scanning || sdata->local->hw_scanning) | ||
2217 | return; | ||
2218 | |||
2219 | ieee80211_mgd_probe_ap(sdata, false); | ||
2220 | } | ||
2221 | |||
2043 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2222 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
2044 | { | 2223 | { |
2045 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 2224 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
2046 | /* | 2225 | sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | |
2047 | * Need to update last_beacon to avoid beacon loss | 2226 | IEEE80211_STA_CONNECTION_POLL); |
2048 | * test to trigger. | ||
2049 | */ | ||
2050 | sdata->u.mgd.last_beacon = jiffies; | ||
2051 | 2227 | ||
2228 | /* let's probe the connection once */ | ||
2229 | queue_work(sdata->local->hw.workqueue, | ||
2230 | &sdata->u.mgd.monitor_work); | ||
2231 | /* and do all the other regular work too */ | ||
2052 | queue_work(sdata->local->hw.workqueue, | 2232 | queue_work(sdata->local->hw.workqueue, |
2053 | &sdata->u.mgd.work); | 2233 | &sdata->u.mgd.work); |
2054 | } | 2234 | } |
@@ -2073,6 +2253,11 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2073 | cancel_work_sync(&ifmgd->chswitch_work); | 2253 | cancel_work_sync(&ifmgd->chswitch_work); |
2074 | if (del_timer_sync(&ifmgd->chswitch_timer)) | 2254 | if (del_timer_sync(&ifmgd->chswitch_timer)) |
2075 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | 2255 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); |
2256 | |||
2257 | cancel_work_sync(&ifmgd->monitor_work); | ||
2258 | /* these will just be re-established on connection */ | ||
2259 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
2260 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
2076 | } | 2261 | } |
2077 | 2262 | ||
2078 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 2263 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
@@ -2093,10 +2278,15 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2093 | 2278 | ||
2094 | ifmgd = &sdata->u.mgd; | 2279 | ifmgd = &sdata->u.mgd; |
2095 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | 2280 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); |
2281 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | ||
2096 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 2282 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
2097 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); | 2283 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); |
2098 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 2284 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
2099 | (unsigned long) sdata); | 2285 | (unsigned long) sdata); |
2286 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | ||
2287 | (unsigned long) sdata); | ||
2288 | setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, | ||
2289 | (unsigned long) sdata); | ||
2100 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, | 2290 | setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, |
2101 | (unsigned long) sdata); | 2291 | (unsigned long) sdata); |
2102 | skb_queue_head_init(&ifmgd->skb_queue); | 2292 | skb_queue_head_init(&ifmgd->skb_queue); |
@@ -2175,6 +2365,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2175 | wk->ie_len = req->ie_len; | 2365 | wk->ie_len = req->ie_len; |
2176 | } | 2366 | } |
2177 | 2367 | ||
2368 | if (req->key && req->key_len) { | ||
2369 | wk->key_len = req->key_len; | ||
2370 | wk->key_idx = req->key_idx; | ||
2371 | memcpy(wk->key, req->key, req->key_len); | ||
2372 | } | ||
2373 | |||
2178 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 2374 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
2179 | memcpy(wk->ssid, ssid + 2, ssid[1]); | 2375 | memcpy(wk->ssid, ssid + 2, ssid[1]); |
2180 | wk->ssid_len = ssid[1]; | 2376 | wk->ssid_len = ssid[1]; |
@@ -2290,7 +2486,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2290 | 2486 | ||
2291 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { | 2487 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { |
2292 | bssid = req->bss->bssid; | 2488 | bssid = req->bss->bssid; |
2293 | ieee80211_set_disassoc(sdata, bssid, true); | 2489 | ieee80211_set_disassoc(sdata); |
2294 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | 2490 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { |
2295 | if (&wk->bss->cbss == req->bss) { | 2491 | if (&wk->bss->cbss == req->bss) { |
2296 | bssid = req->bss->bssid; | 2492 | bssid = req->bss->bssid; |
@@ -2332,7 +2528,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2332 | return -ENOLINK; | 2528 | return -ENOLINK; |
2333 | } | 2529 | } |
2334 | 2530 | ||
2335 | ieee80211_set_disassoc(sdata, req->bss->bssid, false); | 2531 | ieee80211_set_disassoc(sdata); |
2336 | 2532 | ||
2337 | mutex_unlock(&ifmgd->mtx); | 2533 | mutex_unlock(&ifmgd->mtx); |
2338 | 2534 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 4641f00a1e5c..b33efc4fc267 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -198,6 +198,35 @@ static void rate_control_release(struct kref *kref) | |||
198 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
199 | } | 199 | } |
200 | 200 | ||
201 | static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) | ||
202 | { | ||
203 | struct sk_buff *skb = txrc->skb; | ||
204 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
205 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
206 | __le16 fc; | ||
207 | |||
208 | fc = hdr->frame_control; | ||
209 | |||
210 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); | ||
211 | } | ||
212 | |||
213 | bool rate_control_send_low(struct ieee80211_sta *sta, | ||
214 | void *priv_sta, | ||
215 | struct ieee80211_tx_rate_control *txrc) | ||
216 | { | ||
217 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); | ||
218 | |||
219 | if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) { | ||
220 | info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta); | ||
221 | info->control.rates[0].count = | ||
222 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | ||
223 | 1 : txrc->hw->max_rate_tries; | ||
224 | return true; | ||
225 | } | ||
226 | return false; | ||
227 | } | ||
228 | EXPORT_SYMBOL(rate_control_send_low); | ||
229 | |||
201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | 230 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
202 | struct sta_info *sta, | 231 | struct sta_info *sta, |
203 | struct ieee80211_tx_rate_control *txrc) | 232 | struct ieee80211_tx_rate_control *txrc) |
@@ -258,7 +287,7 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
258 | struct rate_control_ref *ref, *old; | 287 | struct rate_control_ref *ref, *old; |
259 | 288 | ||
260 | ASSERT_RTNL(); | 289 | ASSERT_RTNL(); |
261 | if (local->open_count || netif_running(local->mdev)) | 290 | if (local->open_count) |
262 | return -EBUSY; | 291 | return -EBUSY; |
263 | 292 | ||
264 | ref = rate_control_alloc(name, local); | 293 | ref = rate_control_alloc(name, local); |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 37771abd8f5a..7c5142988bbb 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -70,20 +70,6 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
70 | return i; | 70 | return i; |
71 | } | 71 | } |
72 | 72 | ||
73 | static inline bool | ||
74 | use_low_rate(struct sk_buff *skb) | ||
75 | { | ||
76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
78 | u16 fc; | ||
79 | |||
80 | fc = le16_to_cpu(hdr->frame_control); | ||
81 | |||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | ||
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA); | ||
84 | } | ||
85 | |||
86 | |||
87 | static void | 73 | static void |
88 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | 74 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) |
89 | { | 75 | { |
@@ -232,7 +218,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
232 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) | 218 | void *priv_sta, struct ieee80211_tx_rate_control *txrc) |
233 | { | 219 | { |
234 | struct sk_buff *skb = txrc->skb; | 220 | struct sk_buff *skb = txrc->skb; |
235 | struct ieee80211_supported_band *sband = txrc->sband; | ||
236 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 221 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
237 | struct minstrel_sta_info *mi = priv_sta; | 222 | struct minstrel_sta_info *mi = priv_sta; |
238 | struct minstrel_priv *mp = priv; | 223 | struct minstrel_priv *mp = priv; |
@@ -245,14 +230,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
245 | int mrr_ndx[3]; | 230 | int mrr_ndx[3]; |
246 | int sample_rate; | 231 | int sample_rate; |
247 | 232 | ||
248 | if (!sta || !mi || use_low_rate(skb)) { | 233 | if (rate_control_send_low(sta, priv_sta, txrc)) |
249 | ar[0].idx = rate_lowest_index(sband, sta); | ||
250 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
251 | ar[0].count = 1; | ||
252 | else | ||
253 | ar[0].count = mp->max_retry; | ||
254 | return; | 234 | return; |
255 | } | ||
256 | 235 | ||
257 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; | 236 | mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; |
258 | 237 | ||
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a0bef767ceb5..8c053be9dc24 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -276,11 +276,9 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
276 | { | 276 | { |
277 | struct sk_buff *skb = txrc->skb; | 277 | struct sk_buff *skb = txrc->skb; |
278 | struct ieee80211_supported_band *sband = txrc->sband; | 278 | struct ieee80211_supported_band *sband = txrc->sband; |
279 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
280 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 279 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
281 | struct rc_pid_sta_info *spinfo = priv_sta; | 280 | struct rc_pid_sta_info *spinfo = priv_sta; |
282 | int rateidx; | 281 | int rateidx; |
283 | u16 fc; | ||
284 | 282 | ||
285 | if (txrc->rts) | 283 | if (txrc->rts) |
286 | info->control.rates[0].count = | 284 | info->control.rates[0].count = |
@@ -290,16 +288,8 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
290 | txrc->hw->conf.short_frame_max_tx_count; | 288 | txrc->hw->conf.short_frame_max_tx_count; |
291 | 289 | ||
292 | /* Send management frames and NO_ACK data using lowest rate. */ | 290 | /* Send management frames and NO_ACK data using lowest rate. */ |
293 | fc = le16_to_cpu(hdr->frame_control); | 291 | if (rate_control_send_low(sta, priv_sta, txrc)) |
294 | if (!sta || !spinfo || | ||
295 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
296 | info->flags & IEEE80211_TX_CTL_NO_ACK) { | ||
297 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | ||
298 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
299 | info->control.rates[0].count = 1; | ||
300 | |||
301 | return; | 292 | return; |
302 | } | ||
303 | 293 | ||
304 | rateidx = spinfo->txrate_idx; | 294 | rateidx = spinfo->txrate_idx; |
305 | 295 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fe6b99059531..66c797cc85ce 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -833,28 +833,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
833 | if (!sta) | 833 | if (!sta) |
834 | return RX_CONTINUE; | 834 | return RX_CONTINUE; |
835 | 835 | ||
836 | /* Update last_rx only for IBSS packets which are for the current | 836 | /* |
837 | * BSSID to avoid keeping the current IBSS network alive in cases where | 837 | * Update last_rx only for IBSS packets which are for the current |
838 | * other STAs are using different BSSID. */ | 838 | * BSSID to avoid keeping the current IBSS network alive in cases |
839 | * where other STAs start using different BSSID. | ||
840 | */ | ||
839 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 841 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
840 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 842 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
841 | NL80211_IFTYPE_ADHOC); | 843 | NL80211_IFTYPE_ADHOC); |
842 | if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) | 844 | if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) |
843 | sta->last_rx = jiffies; | 845 | sta->last_rx = jiffies; |
844 | } else | 846 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
845 | if (!is_multicast_ether_addr(hdr->addr1) || | 847 | /* |
846 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
847 | /* Update last_rx only for unicast frames in order to prevent | ||
848 | * the Probe Request frames (the only broadcast frames from a | ||
849 | * STA in infrastructure mode) from keeping a connection alive. | ||
850 | * Mesh beacons will update last_rx when if they are found to | 848 | * Mesh beacons will update last_rx when if they are found to |
851 | * match the current local configuration when processed. | 849 | * match the current local configuration when processed. |
852 | */ | 850 | */ |
853 | if (rx->sdata->vif.type == NL80211_IFTYPE_STATION && | 851 | sta->last_rx = jiffies; |
854 | ieee80211_is_beacon(hdr->frame_control)) { | ||
855 | rx->sdata->u.mgd.last_beacon = jiffies; | ||
856 | } else | ||
857 | sta->last_rx = jiffies; | ||
858 | } | 852 | } |
859 | 853 | ||
860 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 854 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
@@ -1484,10 +1478,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1484 | struct ieee80211s_hdr *mesh_hdr; | 1478 | struct ieee80211s_hdr *mesh_hdr; |
1485 | unsigned int hdrlen; | 1479 | unsigned int hdrlen; |
1486 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1480 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1481 | struct ieee80211_local *local = rx->local; | ||
1482 | struct ieee80211_sub_if_data *sdata; | ||
1487 | 1483 | ||
1488 | hdr = (struct ieee80211_hdr *) skb->data; | 1484 | hdr = (struct ieee80211_hdr *) skb->data; |
1489 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1485 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1490 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1486 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1487 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1491 | 1488 | ||
1492 | if (!ieee80211_is_data(hdr->frame_control)) | 1489 | if (!ieee80211_is_data(hdr->frame_control)) |
1493 | return RX_CONTINUE; | 1490 | return RX_CONTINUE; |
@@ -1497,10 +1494,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1497 | return RX_DROP_MONITOR; | 1494 | return RX_DROP_MONITOR; |
1498 | 1495 | ||
1499 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | 1496 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ |
1500 | struct ieee80211_sub_if_data *sdata; | ||
1501 | struct mesh_path *mppath; | 1497 | struct mesh_path *mppath; |
1502 | 1498 | ||
1503 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1504 | rcu_read_lock(); | 1499 | rcu_read_lock(); |
1505 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | 1500 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); |
1506 | if (!mppath) { | 1501 | if (!mppath) { |
@@ -1526,6 +1521,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1526 | dropped_frames_ttl); | 1521 | dropped_frames_ttl); |
1527 | else { | 1522 | else { |
1528 | struct ieee80211_hdr *fwd_hdr; | 1523 | struct ieee80211_hdr *fwd_hdr; |
1524 | struct ieee80211_tx_info *info; | ||
1525 | |||
1529 | fwd_skb = skb_copy(skb, GFP_ATOMIC); | 1526 | fwd_skb = skb_copy(skb, GFP_ATOMIC); |
1530 | 1527 | ||
1531 | if (!fwd_skb && net_ratelimit()) | 1528 | if (!fwd_skb && net_ratelimit()) |
@@ -1539,9 +1536,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1539 | */ | 1536 | */ |
1540 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); | 1537 | memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN); |
1541 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | 1538 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); |
1542 | fwd_skb->dev = rx->local->mdev; | 1539 | info = IEEE80211_SKB_CB(fwd_skb); |
1540 | memset(info, 0, sizeof(*info)); | ||
1541 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | ||
1543 | fwd_skb->iif = rx->dev->ifindex; | 1542 | fwd_skb->iif = rx->dev->ifindex; |
1544 | dev_queue_xmit(fwd_skb); | 1543 | ieee80211_select_queue(local, fwd_skb); |
1544 | if (is_multicast_ether_addr(fwd_hdr->addr3)) | ||
1545 | memcpy(fwd_hdr->addr1, fwd_hdr->addr3, | ||
1546 | ETH_ALEN); | ||
1547 | else { | ||
1548 | int err = mesh_nexthop_lookup(fwd_skb, sdata); | ||
1549 | /* Failed to immediately resolve next hop: | ||
1550 | * fwded frame was dropped or will be added | ||
1551 | * later to the pending skb queue. */ | ||
1552 | if (err) | ||
1553 | return RX_DROP_MONITOR; | ||
1554 | } | ||
1555 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1556 | fwded_frames); | ||
1557 | ieee80211_add_pending_skb(local, fwd_skb); | ||
1545 | } | 1558 | } |
1546 | } | 1559 | } |
1547 | 1560 | ||
@@ -1809,8 +1822,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1809 | return RX_DROP_MONITOR; | 1822 | return RX_DROP_MONITOR; |
1810 | } | 1823 | } |
1811 | 1824 | ||
1812 | static void ieee80211_rx_michael_mic_report(struct net_device *dev, | 1825 | static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, |
1813 | struct ieee80211_hdr *hdr, | ||
1814 | struct ieee80211_rx_data *rx) | 1826 | struct ieee80211_rx_data *rx) |
1815 | { | 1827 | { |
1816 | int keyidx; | 1828 | int keyidx; |
@@ -2120,7 +2132,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2120 | } | 2132 | } |
2121 | 2133 | ||
2122 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { | 2134 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { |
2123 | ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx); | 2135 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2124 | return; | 2136 | return; |
2125 | } | 2137 | } |
2126 | 2138 | ||
@@ -2489,7 +2501,6 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2489 | 2501 | ||
2490 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); | 2502 | BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); |
2491 | 2503 | ||
2492 | skb->dev = local->mdev; | ||
2493 | skb->pkt_type = IEEE80211_RX_MSG; | 2504 | skb->pkt_type = IEEE80211_RX_MSG; |
2494 | skb_queue_tail(&local->skb_queue, skb); | 2505 | skb_queue_tail(&local->skb_queue, skb); |
2495 | tasklet_schedule(&local->tasklet); | 2506 | tasklet_schedule(&local->tasklet); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 5f4f7869d050..74820656dc89 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -294,16 +294,13 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
294 | if (was_hw_scan) | 294 | if (was_hw_scan) |
295 | goto done; | 295 | goto done; |
296 | 296 | ||
297 | netif_tx_lock_bh(local->mdev); | 297 | spin_lock_bh(&local->filter_lock); |
298 | netif_addr_lock(local->mdev); | ||
299 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | 298 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; |
300 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | 299 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, |
301 | &local->filter_flags, | 300 | &local->filter_flags, |
302 | local->mdev->mc_count, | 301 | local->mc_count, |
303 | local->mdev->mc_list); | 302 | local->mc_list); |
304 | 303 | spin_unlock_bh(&local->filter_lock); | |
305 | netif_addr_unlock(local->mdev); | ||
306 | netif_tx_unlock_bh(local->mdev); | ||
307 | 304 | ||
308 | drv_sw_scan_complete(local); | 305 | drv_sw_scan_complete(local); |
309 | 306 | ||
@@ -382,13 +379,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
382 | local->scan_state = SCAN_SET_CHANNEL; | 379 | local->scan_state = SCAN_SET_CHANNEL; |
383 | local->scan_channel_idx = 0; | 380 | local->scan_channel_idx = 0; |
384 | 381 | ||
385 | netif_addr_lock_bh(local->mdev); | 382 | spin_lock_bh(&local->filter_lock); |
386 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | 383 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; |
387 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | 384 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, |
388 | &local->filter_flags, | 385 | &local->filter_flags, |
389 | local->mdev->mc_count, | 386 | local->mc_count, |
390 | local->mdev->mc_list); | 387 | local->mc_list); |
391 | netif_addr_unlock_bh(local->mdev); | 388 | spin_unlock_bh(&local->filter_lock); |
392 | 389 | ||
393 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 390 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
394 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 391 | queue_delayed_work(local->hw.workqueue, &local->scan_work, |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 60ae086995b1..2572509d5568 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -451,7 +451,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
451 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 451 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 452 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
453 | 453 | ||
454 | if (unlikely(tx->skb->do_not_encrypt)) | 454 | if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) |
455 | tx->key = NULL; | 455 | tx->key = NULL; |
456 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 456 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
457 | tx->key = key; | 457 | tx->key = key; |
@@ -497,7 +497,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
497 | } | 497 | } |
498 | 498 | ||
499 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 499 | if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
500 | tx->skb->do_not_encrypt = 1; | 500 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
501 | 501 | ||
502 | return TX_CONTINUE; | 502 | return TX_CONTINUE; |
503 | } | 503 | } |
@@ -512,6 +512,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
512 | int i, len; | 512 | int i, len; |
513 | bool inval = false, rts = false, short_preamble = false; | 513 | bool inval = false, rts = false, short_preamble = false; |
514 | struct ieee80211_tx_rate_control txrc; | 514 | struct ieee80211_tx_rate_control txrc; |
515 | u32 sta_flags; | ||
515 | 516 | ||
516 | memset(&txrc, 0, sizeof(txrc)); | 517 | memset(&txrc, 0, sizeof(txrc)); |
517 | 518 | ||
@@ -544,7 +545,26 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
544 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) | 545 | (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) |
545 | txrc.short_preamble = short_preamble = true; | 546 | txrc.short_preamble = short_preamble = true; |
546 | 547 | ||
548 | sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0; | ||
549 | |||
550 | /* | ||
551 | * Lets not bother rate control if we're associated and cannot | ||
552 | * talk to the sta. This should not happen. | ||
553 | */ | ||
554 | if (WARN((tx->local->sw_scanning) && | ||
555 | (sta_flags & WLAN_STA_ASSOC) && | ||
556 | !rate_usable_index_exists(sband, &tx->sta->sta), | ||
557 | "%s: Dropped data frame as no usable bitrate found while " | ||
558 | "scanning and associated. Target station: " | ||
559 | "%pM on %d GHz band\n", | ||
560 | tx->dev->name, hdr->addr1, | ||
561 | tx->channel->band ? 5 : 2)) | ||
562 | return TX_DROP; | ||
547 | 563 | ||
564 | /* | ||
565 | * If we're associated with the sta at this point we know we can at | ||
566 | * least send the frame at the lowest bit rate. | ||
567 | */ | ||
548 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); | 568 | rate_control_get_rate(tx->sdata, tx->sta, &txrc); |
549 | 569 | ||
550 | if (unlikely(info->control.rates[0].idx < 0)) | 570 | if (unlikely(info->control.rates[0].idx < 0)) |
@@ -754,9 +774,7 @@ static int ieee80211_fragment(struct ieee80211_local *local, | |||
754 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); | 774 | memcpy(tmp->cb, skb->cb, sizeof(tmp->cb)); |
755 | skb_copy_queue_mapping(tmp, skb); | 775 | skb_copy_queue_mapping(tmp, skb); |
756 | tmp->priority = skb->priority; | 776 | tmp->priority = skb->priority; |
757 | tmp->do_not_encrypt = skb->do_not_encrypt; | ||
758 | tmp->dev = skb->dev; | 777 | tmp->dev = skb->dev; |
759 | tmp->iif = skb->iif; | ||
760 | 778 | ||
761 | /* copy header and data */ | 779 | /* copy header and data */ |
762 | memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); | 780 | memcpy(skb_put(tmp, hdrlen), skb->data, hdrlen); |
@@ -784,7 +802,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
784 | 802 | ||
785 | /* | 803 | /* |
786 | * Warn when submitting a fragmented A-MPDU frame and drop it. | 804 | * Warn when submitting a fragmented A-MPDU frame and drop it. |
787 | * This scenario is handled in __ieee80211_tx_prepare but extra | 805 | * This scenario is handled in ieee80211_tx_prepare but extra |
788 | * caution taken here as fragmented ampdu may cause Tx stop. | 806 | * caution taken here as fragmented ampdu may cause Tx stop. |
789 | */ | 807 | */ |
790 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) | 808 | if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) |
@@ -923,11 +941,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
923 | struct ieee80211_radiotap_header *rthdr = | 941 | struct ieee80211_radiotap_header *rthdr = |
924 | (struct ieee80211_radiotap_header *) skb->data; | 942 | (struct ieee80211_radiotap_header *) skb->data; |
925 | struct ieee80211_supported_band *sband; | 943 | struct ieee80211_supported_band *sband; |
944 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
926 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); | 945 | int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); |
927 | 946 | ||
928 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 947 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
929 | 948 | ||
930 | skb->do_not_encrypt = 1; | 949 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
931 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 950 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
932 | 951 | ||
933 | /* | 952 | /* |
@@ -965,7 +984,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
965 | skb_trim(skb, skb->len - FCS_LEN); | 984 | skb_trim(skb, skb->len - FCS_LEN); |
966 | } | 985 | } |
967 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) | 986 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) |
968 | tx->skb->do_not_encrypt = 0; | 987 | info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; |
969 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) | 988 | if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) |
970 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 989 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
971 | break; | 990 | break; |
@@ -998,13 +1017,12 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
998 | * initialises @tx | 1017 | * initialises @tx |
999 | */ | 1018 | */ |
1000 | static ieee80211_tx_result | 1019 | static ieee80211_tx_result |
1001 | __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1020 | ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, |
1002 | struct sk_buff *skb, | 1021 | struct ieee80211_tx_data *tx, |
1003 | struct net_device *dev) | 1022 | struct sk_buff *skb) |
1004 | { | 1023 | { |
1005 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1024 | struct ieee80211_local *local = sdata->local; |
1006 | struct ieee80211_hdr *hdr; | 1025 | struct ieee80211_hdr *hdr; |
1007 | struct ieee80211_sub_if_data *sdata; | ||
1008 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1026 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1009 | int hdrlen, tid; | 1027 | int hdrlen, tid; |
1010 | u8 *qc, *state; | 1028 | u8 *qc, *state; |
@@ -1012,9 +1030,9 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1012 | 1030 | ||
1013 | memset(tx, 0, sizeof(*tx)); | 1031 | memset(tx, 0, sizeof(*tx)); |
1014 | tx->skb = skb; | 1032 | tx->skb = skb; |
1015 | tx->dev = dev; /* use original interface */ | 1033 | tx->dev = sdata->dev; /* use original interface */ |
1016 | tx->local = local; | 1034 | tx->local = local; |
1017 | tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1035 | tx->sdata = sdata; |
1018 | tx->channel = local->hw.conf.channel; | 1036 | tx->channel = local->hw.conf.channel; |
1019 | /* | 1037 | /* |
1020 | * Set this flag (used below to indicate "automatic fragmentation"), | 1038 | * Set this flag (used below to indicate "automatic fragmentation"), |
@@ -1023,7 +1041,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1023 | tx->flags |= IEEE80211_TX_FRAGMENTED; | 1041 | tx->flags |= IEEE80211_TX_FRAGMENTED; |
1024 | 1042 | ||
1025 | /* process and remove the injection radiotap header */ | 1043 | /* process and remove the injection radiotap header */ |
1026 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1027 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { | 1044 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
1028 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) | 1045 | if (!__ieee80211_parse_tx_radiotap(tx, skb)) |
1029 | return TX_DROP; | 1046 | return TX_DROP; |
@@ -1119,50 +1136,28 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1119 | return TX_CONTINUE; | 1136 | return TX_CONTINUE; |
1120 | } | 1137 | } |
1121 | 1138 | ||
1122 | /* | ||
1123 | * NB: @tx is uninitialised when passed in here | ||
1124 | */ | ||
1125 | static int ieee80211_tx_prepare(struct ieee80211_local *local, | ||
1126 | struct ieee80211_tx_data *tx, | ||
1127 | struct sk_buff *skb) | ||
1128 | { | ||
1129 | struct net_device *dev; | ||
1130 | |||
1131 | dev = dev_get_by_index(&init_net, skb->iif); | ||
1132 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { | ||
1133 | dev_put(dev); | ||
1134 | dev = NULL; | ||
1135 | } | ||
1136 | if (unlikely(!dev)) | ||
1137 | return -ENODEV; | ||
1138 | /* | ||
1139 | * initialises tx with control | ||
1140 | * | ||
1141 | * return value is safe to ignore here because this function | ||
1142 | * can only be invoked for multicast frames | ||
1143 | * | ||
1144 | * XXX: clean up | ||
1145 | */ | ||
1146 | __ieee80211_tx_prepare(tx, skb, dev); | ||
1147 | dev_put(dev); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static int __ieee80211_tx(struct ieee80211_local *local, | 1139 | static int __ieee80211_tx(struct ieee80211_local *local, |
1152 | struct sk_buff **skbp, | 1140 | struct sk_buff **skbp, |
1153 | struct sta_info *sta) | 1141 | struct sta_info *sta, |
1142 | bool txpending) | ||
1154 | { | 1143 | { |
1155 | struct sk_buff *skb = *skbp, *next; | 1144 | struct sk_buff *skb = *skbp, *next; |
1156 | struct ieee80211_tx_info *info; | 1145 | struct ieee80211_tx_info *info; |
1146 | unsigned long flags; | ||
1157 | int ret, len; | 1147 | int ret, len; |
1158 | bool fragm = false; | 1148 | bool fragm = false; |
1159 | 1149 | ||
1160 | local->mdev->trans_start = jiffies; | ||
1161 | |||
1162 | while (skb) { | 1150 | while (skb) { |
1163 | if (ieee80211_queue_stopped(&local->hw, | 1151 | int q = skb_get_queue_mapping(skb); |
1164 | skb_get_queue_mapping(skb))) | 1152 | |
1165 | return IEEE80211_TX_PENDING; | 1153 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1154 | ret = IEEE80211_TX_OK; | ||
1155 | if (local->queue_stop_reasons[q] || | ||
1156 | (!txpending && !skb_queue_empty(&local->pending[q]))) | ||
1157 | ret = IEEE80211_TX_PENDING; | ||
1158 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1159 | if (ret != IEEE80211_TX_OK) | ||
1160 | return ret; | ||
1166 | 1161 | ||
1167 | info = IEEE80211_SKB_CB(skb); | 1162 | info = IEEE80211_SKB_CB(skb); |
1168 | 1163 | ||
@@ -1234,10 +1229,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1234 | return 0; | 1229 | return 0; |
1235 | } | 1230 | } |
1236 | 1231 | ||
1237 | static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | 1232 | static void ieee80211_tx(struct ieee80211_sub_if_data *sdata, |
1238 | bool txpending) | 1233 | struct sk_buff *skb, bool txpending) |
1239 | { | 1234 | { |
1240 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1235 | struct ieee80211_local *local = sdata->local; |
1241 | struct ieee80211_tx_data tx; | 1236 | struct ieee80211_tx_data tx; |
1242 | ieee80211_tx_result res_prepare; | 1237 | ieee80211_tx_result res_prepare; |
1243 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1238 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1248,8 +1243,6 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1248 | 1243 | ||
1249 | queue = skb_get_queue_mapping(skb); | 1244 | queue = skb_get_queue_mapping(skb); |
1250 | 1245 | ||
1251 | WARN_ON(!txpending && !skb_queue_empty(&local->pending[queue])); | ||
1252 | |||
1253 | if (unlikely(skb->len < 10)) { | 1246 | if (unlikely(skb->len < 10)) { |
1254 | dev_kfree_skb(skb); | 1247 | dev_kfree_skb(skb); |
1255 | return; | 1248 | return; |
@@ -1258,7 +1251,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1258 | rcu_read_lock(); | 1251 | rcu_read_lock(); |
1259 | 1252 | ||
1260 | /* initialises tx */ | 1253 | /* initialises tx */ |
1261 | res_prepare = __ieee80211_tx_prepare(&tx, skb, dev); | 1254 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); |
1262 | 1255 | ||
1263 | if (unlikely(res_prepare == TX_DROP)) { | 1256 | if (unlikely(res_prepare == TX_DROP)) { |
1264 | dev_kfree_skb(skb); | 1257 | dev_kfree_skb(skb); |
@@ -1277,7 +1270,7 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1277 | 1270 | ||
1278 | retries = 0; | 1271 | retries = 0; |
1279 | retry: | 1272 | retry: |
1280 | ret = __ieee80211_tx(local, &tx.skb, tx.sta); | 1273 | ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending); |
1281 | switch (ret) { | 1274 | switch (ret) { |
1282 | case IEEE80211_TX_OK: | 1275 | case IEEE80211_TX_OK: |
1283 | break; | 1276 | break; |
@@ -1295,34 +1288,35 @@ static void ieee80211_tx(struct net_device *dev, struct sk_buff *skb, | |||
1295 | 1288 | ||
1296 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1289 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1297 | 1290 | ||
1298 | if (__netif_subqueue_stopped(local->mdev, queue)) { | 1291 | if (local->queue_stop_reasons[queue] || |
1292 | !skb_queue_empty(&local->pending[queue])) { | ||
1293 | /* | ||
1294 | * if queue is stopped, queue up frames for later | ||
1295 | * transmission from the tasklet | ||
1296 | */ | ||
1299 | do { | 1297 | do { |
1300 | next = skb->next; | 1298 | next = skb->next; |
1301 | skb->next = NULL; | 1299 | skb->next = NULL; |
1302 | if (unlikely(txpending)) | 1300 | if (unlikely(txpending)) |
1303 | skb_queue_head(&local->pending[queue], | 1301 | __skb_queue_head(&local->pending[queue], |
1304 | skb); | 1302 | skb); |
1305 | else | 1303 | else |
1306 | skb_queue_tail(&local->pending[queue], | 1304 | __skb_queue_tail(&local->pending[queue], |
1307 | skb); | 1305 | skb); |
1308 | } while ((skb = next)); | 1306 | } while ((skb = next)); |
1309 | 1307 | ||
1310 | /* | ||
1311 | * Make sure nobody will enable the queue on us | ||
1312 | * (without going through the tasklet) nor disable the | ||
1313 | * netdev queue underneath the pending handling code. | ||
1314 | */ | ||
1315 | __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING, | ||
1316 | &local->queue_stop_reasons[queue]); | ||
1317 | |||
1318 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1308 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1319 | flags); | 1309 | flags); |
1320 | } else { | 1310 | } else { |
1311 | /* | ||
1312 | * otherwise retry, but this is a race condition or | ||
1313 | * a driver bug (which we warn about if it persists) | ||
1314 | */ | ||
1321 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1315 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1322 | flags); | 1316 | flags); |
1323 | 1317 | ||
1324 | retries++; | 1318 | retries++; |
1325 | if (WARN(retries > 10, "tx refused but queue active")) | 1319 | if (WARN(retries > 10, "tx refused but queue active\n")) |
1326 | goto drop; | 1320 | goto drop; |
1327 | goto retry; | 1321 | goto retry; |
1328 | } | 1322 | } |
@@ -1383,14 +1377,13 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1383 | return 0; | 1377 | return 0; |
1384 | } | 1378 | } |
1385 | 1379 | ||
1386 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1380 | static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, |
1381 | struct sk_buff *skb) | ||
1387 | { | 1382 | { |
1388 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | 1383 | struct ieee80211_local *local = sdata->local; |
1389 | struct ieee80211_local *local = mpriv->local; | ||
1390 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1384 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1391 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1385 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1392 | struct net_device *odev = NULL; | 1386 | struct ieee80211_sub_if_data *tmp_sdata; |
1393 | struct ieee80211_sub_if_data *osdata; | ||
1394 | int headroom; | 1387 | int headroom; |
1395 | bool may_encrypt; | 1388 | bool may_encrypt; |
1396 | enum { | 1389 | enum { |
@@ -1399,20 +1392,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1399 | UNKNOWN_ADDRESS, | 1392 | UNKNOWN_ADDRESS, |
1400 | } monitor_iface = NOT_MONITOR; | 1393 | } monitor_iface = NOT_MONITOR; |
1401 | 1394 | ||
1402 | if (skb->iif) | 1395 | dev_hold(sdata->dev); |
1403 | odev = dev_get_by_index(&init_net, skb->iif); | ||
1404 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { | ||
1405 | dev_put(odev); | ||
1406 | odev = NULL; | ||
1407 | } | ||
1408 | if (unlikely(!odev)) { | ||
1409 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1410 | printk(KERN_DEBUG "%s: Discarded packet with nonexistent " | ||
1411 | "originating device\n", dev->name); | ||
1412 | #endif | ||
1413 | dev_kfree_skb(skb); | ||
1414 | return NETDEV_TX_OK; | ||
1415 | } | ||
1416 | 1396 | ||
1417 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 1397 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
1418 | local->hw.conf.dynamic_ps_timeout > 0 && | 1398 | local->hw.conf.dynamic_ps_timeout > 0 && |
@@ -1428,26 +1408,18 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1428 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1408 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1429 | } | 1409 | } |
1430 | 1410 | ||
1431 | memset(info, 0, sizeof(*info)); | ||
1432 | |||
1433 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1411 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
1434 | 1412 | ||
1435 | osdata = IEEE80211_DEV_TO_SUB_IF(odev); | 1413 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1436 | |||
1437 | if (ieee80211_vif_is_mesh(&osdata->vif) && | ||
1438 | ieee80211_is_data(hdr->frame_control)) { | 1414 | ieee80211_is_data(hdr->frame_control)) { |
1439 | if (is_multicast_ether_addr(hdr->addr3)) | 1415 | if (is_multicast_ether_addr(hdr->addr3)) |
1440 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1416 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1441 | else | 1417 | else |
1442 | if (mesh_nexthop_lookup(skb, osdata)) { | 1418 | if (mesh_nexthop_lookup(skb, sdata)) { |
1443 | dev_put(odev); | 1419 | dev_put(sdata->dev); |
1444 | return NETDEV_TX_OK; | 1420 | return; |
1445 | } | 1421 | } |
1446 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1422 | } else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1447 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, | ||
1448 | fwded_frames); | ||
1449 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { | ||
1450 | struct ieee80211_sub_if_data *sdata; | ||
1451 | int hdrlen; | 1423 | int hdrlen; |
1452 | u16 len_rthdr; | 1424 | u16 len_rthdr; |
1453 | 1425 | ||
@@ -1471,19 +1443,17 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1471 | */ | 1443 | */ |
1472 | 1444 | ||
1473 | rcu_read_lock(); | 1445 | rcu_read_lock(); |
1474 | list_for_each_entry_rcu(sdata, &local->interfaces, | 1446 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, |
1475 | list) { | 1447 | list) { |
1476 | if (!netif_running(sdata->dev)) | 1448 | if (!netif_running(tmp_sdata->dev)) |
1477 | continue; | 1449 | continue; |
1478 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1450 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) |
1479 | continue; | 1451 | continue; |
1480 | if (compare_ether_addr(sdata->dev->dev_addr, | 1452 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, |
1481 | hdr->addr2)) { | 1453 | hdr->addr2)) { |
1482 | dev_hold(sdata->dev); | 1454 | dev_hold(tmp_sdata->dev); |
1483 | dev_put(odev); | 1455 | dev_put(sdata->dev); |
1484 | osdata = sdata; | 1456 | sdata = tmp_sdata; |
1485 | odev = osdata->dev; | ||
1486 | skb->iif = sdata->dev->ifindex; | ||
1487 | monitor_iface = FOUND_SDATA; | 1457 | monitor_iface = FOUND_SDATA; |
1488 | break; | 1458 | break; |
1489 | } | 1459 | } |
@@ -1492,31 +1462,31 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1492 | } | 1462 | } |
1493 | } | 1463 | } |
1494 | 1464 | ||
1495 | may_encrypt = !skb->do_not_encrypt; | 1465 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); |
1496 | 1466 | ||
1497 | headroom = osdata->local->tx_headroom; | 1467 | headroom = local->tx_headroom; |
1498 | if (may_encrypt) | 1468 | if (may_encrypt) |
1499 | headroom += IEEE80211_ENCRYPT_HEADROOM; | 1469 | headroom += IEEE80211_ENCRYPT_HEADROOM; |
1500 | headroom -= skb_headroom(skb); | 1470 | headroom -= skb_headroom(skb); |
1501 | headroom = max_t(int, 0, headroom); | 1471 | headroom = max_t(int, 0, headroom); |
1502 | 1472 | ||
1503 | if (ieee80211_skb_resize(osdata->local, skb, headroom, may_encrypt)) { | 1473 | if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { |
1504 | dev_kfree_skb(skb); | 1474 | dev_kfree_skb(skb); |
1505 | dev_put(odev); | 1475 | dev_put(sdata->dev); |
1506 | return NETDEV_TX_OK; | 1476 | return; |
1507 | } | 1477 | } |
1508 | 1478 | ||
1509 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1479 | tmp_sdata = sdata; |
1510 | osdata = container_of(osdata->bss, | 1480 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1511 | struct ieee80211_sub_if_data, | 1481 | tmp_sdata = container_of(sdata->bss, |
1512 | u.ap); | 1482 | struct ieee80211_sub_if_data, |
1483 | u.ap); | ||
1513 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | 1484 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) |
1514 | info->control.vif = &osdata->vif; | 1485 | info->control.vif = &tmp_sdata->vif; |
1515 | |||
1516 | ieee80211_tx(odev, skb, false); | ||
1517 | dev_put(odev); | ||
1518 | 1486 | ||
1519 | return NETDEV_TX_OK; | 1487 | ieee80211_select_queue(local, skb); |
1488 | ieee80211_tx(sdata, skb, false); | ||
1489 | dev_put(sdata->dev); | ||
1520 | } | 1490 | } |
1521 | 1491 | ||
1522 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1492 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, |
@@ -1526,6 +1496,7 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1526 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1496 | struct ieee80211_channel *chan = local->hw.conf.channel; |
1527 | struct ieee80211_radiotap_header *prthdr = | 1497 | struct ieee80211_radiotap_header *prthdr = |
1528 | (struct ieee80211_radiotap_header *)skb->data; | 1498 | (struct ieee80211_radiotap_header *)skb->data; |
1499 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1529 | u16 len_rthdr; | 1500 | u16 len_rthdr; |
1530 | 1501 | ||
1531 | /* | 1502 | /* |
@@ -1563,15 +1534,9 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1563 | if (unlikely(skb->len < len_rthdr)) | 1534 | if (unlikely(skb->len < len_rthdr)) |
1564 | goto fail; /* skb too short for claimed rt header extent */ | 1535 | goto fail; /* skb too short for claimed rt header extent */ |
1565 | 1536 | ||
1566 | skb->dev = local->mdev; | ||
1567 | |||
1568 | /* needed because we set skb device to master */ | 1537 | /* needed because we set skb device to master */ |
1569 | skb->iif = dev->ifindex; | 1538 | skb->iif = dev->ifindex; |
1570 | 1539 | ||
1571 | /* sometimes we do encrypt injected frames, will be fixed | ||
1572 | * up in radiotap parser if not wanted */ | ||
1573 | skb->do_not_encrypt = 0; | ||
1574 | |||
1575 | /* | 1540 | /* |
1576 | * fix up the pointers accounting for the radiotap | 1541 | * fix up the pointers accounting for the radiotap |
1577 | * header still being in there. We are being given | 1542 | * header still being in there. We are being given |
@@ -1586,8 +1551,10 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1586 | skb_set_network_header(skb, len_rthdr); | 1551 | skb_set_network_header(skb, len_rthdr); |
1587 | skb_set_transport_header(skb, len_rthdr); | 1552 | skb_set_transport_header(skb, len_rthdr); |
1588 | 1553 | ||
1589 | /* pass the radiotap header up to the next stage intact */ | 1554 | memset(info, 0, sizeof(*info)); |
1590 | dev_queue_xmit(skb); | 1555 | |
1556 | /* pass the radiotap header up to xmit */ | ||
1557 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | ||
1591 | return NETDEV_TX_OK; | 1558 | return NETDEV_TX_OK; |
1592 | 1559 | ||
1593 | fail: | 1560 | fail: |
@@ -1615,6 +1582,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1615 | { | 1582 | { |
1616 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1583 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1617 | struct ieee80211_local *local = sdata->local; | 1584 | struct ieee80211_local *local = sdata->local; |
1585 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1618 | int ret = NETDEV_TX_BUSY, head_need; | 1586 | int ret = NETDEV_TX_BUSY, head_need; |
1619 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1587 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1620 | __le16 fc; | 1588 | __le16 fc; |
@@ -1844,7 +1812,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1844 | 1812 | ||
1845 | skb->iif = dev->ifindex; | 1813 | skb->iif = dev->ifindex; |
1846 | 1814 | ||
1847 | skb->dev = local->mdev; | ||
1848 | dev->stats.tx_packets++; | 1815 | dev->stats.tx_packets++; |
1849 | dev->stats.tx_bytes += skb->len; | 1816 | dev->stats.tx_bytes += skb->len; |
1850 | 1817 | ||
@@ -1855,8 +1822,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1855 | skb_set_network_header(skb, nh_pos); | 1822 | skb_set_network_header(skb, nh_pos); |
1856 | skb_set_transport_header(skb, h_pos); | 1823 | skb_set_transport_header(skb, h_pos); |
1857 | 1824 | ||
1825 | memset(info, 0, sizeof(*info)); | ||
1826 | |||
1858 | dev->trans_start = jiffies; | 1827 | dev->trans_start = jiffies; |
1859 | dev_queue_xmit(skb); | 1828 | ieee80211_xmit(sdata, skb); |
1860 | 1829 | ||
1861 | return NETDEV_TX_OK; | 1830 | return NETDEV_TX_OK; |
1862 | 1831 | ||
@@ -1898,7 +1867,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1898 | return true; | 1867 | return true; |
1899 | } | 1868 | } |
1900 | 1869 | ||
1901 | /* validate info->control.vif against skb->iif */ | ||
1902 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1870 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1903 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1871 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1904 | sdata = container_of(sdata->bss, | 1872 | sdata = container_of(sdata->bss, |
@@ -1912,12 +1880,13 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1912 | } | 1880 | } |
1913 | 1881 | ||
1914 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { | 1882 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
1915 | ieee80211_tx(dev, skb, true); | 1883 | /* do not use sdata, it may have been changed above */ |
1884 | ieee80211_tx(IEEE80211_DEV_TO_SUB_IF(dev), skb, true); | ||
1916 | } else { | 1885 | } else { |
1917 | hdr = (struct ieee80211_hdr *)skb->data; | 1886 | hdr = (struct ieee80211_hdr *)skb->data; |
1918 | sta = sta_info_get(local, hdr->addr1); | 1887 | sta = sta_info_get(local, hdr->addr1); |
1919 | 1888 | ||
1920 | ret = __ieee80211_tx(local, &skb, sta); | 1889 | ret = __ieee80211_tx(local, &skb, sta, true); |
1921 | if (ret != IEEE80211_TX_OK) | 1890 | if (ret != IEEE80211_TX_OK) |
1922 | result = false; | 1891 | result = false; |
1923 | } | 1892 | } |
@@ -1929,59 +1898,43 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1929 | } | 1898 | } |
1930 | 1899 | ||
1931 | /* | 1900 | /* |
1932 | * Transmit all pending packets. Called from tasklet, locks master device | 1901 | * Transmit all pending packets. Called from tasklet. |
1933 | * TX lock so that no new packets can come in. | ||
1934 | */ | 1902 | */ |
1935 | void ieee80211_tx_pending(unsigned long data) | 1903 | void ieee80211_tx_pending(unsigned long data) |
1936 | { | 1904 | { |
1937 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1905 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
1938 | struct net_device *dev = local->mdev; | ||
1939 | unsigned long flags; | 1906 | unsigned long flags; |
1940 | int i; | 1907 | int i; |
1941 | bool next; | 1908 | bool txok; |
1942 | 1909 | ||
1943 | rcu_read_lock(); | 1910 | rcu_read_lock(); |
1944 | netif_tx_lock_bh(dev); | ||
1945 | 1911 | ||
1912 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
1946 | for (i = 0; i < local->hw.queues; i++) { | 1913 | for (i = 0; i < local->hw.queues; i++) { |
1947 | /* | 1914 | /* |
1948 | * If queue is stopped by something other than due to pending | 1915 | * If queue is stopped by something other than due to pending |
1949 | * frames, or we have no pending frames, proceed to next queue. | 1916 | * frames, or we have no pending frames, proceed to next queue. |
1950 | */ | 1917 | */ |
1951 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1918 | if (local->queue_stop_reasons[i] || |
1952 | next = false; | ||
1953 | if (local->queue_stop_reasons[i] != | ||
1954 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) || | ||
1955 | skb_queue_empty(&local->pending[i])) | 1919 | skb_queue_empty(&local->pending[i])) |
1956 | next = true; | ||
1957 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1958 | |||
1959 | if (next) | ||
1960 | continue; | 1920 | continue; |
1961 | 1921 | ||
1962 | /* | ||
1963 | * start the queue now to allow processing our packets, | ||
1964 | * we're under the tx lock here anyway so nothing will | ||
1965 | * happen as a result of this | ||
1966 | */ | ||
1967 | netif_start_subqueue(local->mdev, i); | ||
1968 | |||
1969 | while (!skb_queue_empty(&local->pending[i])) { | 1922 | while (!skb_queue_empty(&local->pending[i])) { |
1970 | struct sk_buff *skb = skb_dequeue(&local->pending[i]); | 1923 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
1971 | 1924 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | |
1972 | if (!ieee80211_tx_pending_skb(local, skb)) { | 1925 | flags); |
1973 | skb_queue_head(&local->pending[i], skb); | 1926 | |
1927 | txok = ieee80211_tx_pending_skb(local, skb); | ||
1928 | if (!txok) | ||
1929 | __skb_queue_head(&local->pending[i], skb); | ||
1930 | spin_lock_irqsave(&local->queue_stop_reason_lock, | ||
1931 | flags); | ||
1932 | if (!txok) | ||
1974 | break; | 1933 | break; |
1975 | } | ||
1976 | } | 1934 | } |
1977 | |||
1978 | /* Start regular packet processing again. */ | ||
1979 | if (skb_queue_empty(&local->pending[i])) | ||
1980 | ieee80211_wake_queue_by_reason(&local->hw, i, | ||
1981 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
1982 | } | 1935 | } |
1936 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
1983 | 1937 | ||
1984 | netif_tx_unlock_bh(dev); | ||
1985 | rcu_read_unlock(); | 1938 | rcu_read_unlock(); |
1986 | } | 1939 | } |
1987 | 1940 | ||
@@ -2156,8 +2109,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2156 | 2109 | ||
2157 | info = IEEE80211_SKB_CB(skb); | 2110 | info = IEEE80211_SKB_CB(skb); |
2158 | 2111 | ||
2159 | skb->do_not_encrypt = 1; | 2112 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
2160 | |||
2161 | info->band = band; | 2113 | info->band = band; |
2162 | /* | 2114 | /* |
2163 | * XXX: For now, always use the lowest rate | 2115 | * XXX: For now, always use the lowest rate |
@@ -2228,9 +2180,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2228 | sdata = vif_to_sdata(vif); | 2180 | sdata = vif_to_sdata(vif); |
2229 | bss = &sdata->u.ap; | 2181 | bss = &sdata->u.ap; |
2230 | 2182 | ||
2231 | if (!bss) | ||
2232 | return NULL; | ||
2233 | |||
2234 | rcu_read_lock(); | 2183 | rcu_read_lock(); |
2235 | beacon = rcu_dereference(bss->beacon); | 2184 | beacon = rcu_dereference(bss->beacon); |
2236 | 2185 | ||
@@ -2256,7 +2205,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2256 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2205 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2257 | } | 2206 | } |
2258 | 2207 | ||
2259 | if (!ieee80211_tx_prepare(local, &tx, skb)) | 2208 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) |
2260 | break; | 2209 | break; |
2261 | dev_kfree_skb_any(skb); | 2210 | dev_kfree_skb_any(skb); |
2262 | } | 2211 | } |
@@ -2276,3 +2225,25 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2276 | return skb; | 2225 | return skb; |
2277 | } | 2226 | } |
2278 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2227 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2228 | |||
2229 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
2230 | int encrypt) | ||
2231 | { | ||
2232 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2233 | skb_set_mac_header(skb, 0); | ||
2234 | skb_set_network_header(skb, 0); | ||
2235 | skb_set_transport_header(skb, 0); | ||
2236 | |||
2237 | skb->iif = sdata->dev->ifindex; | ||
2238 | if (!encrypt) | ||
2239 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2240 | |||
2241 | /* | ||
2242 | * The other path calling ieee80211_xmit is from the tasklet, | ||
2243 | * and while we can handle concurrent transmissions locking | ||
2244 | * requirements are that we do not come into tx with bhs on. | ||
2245 | */ | ||
2246 | local_bh_disable(); | ||
2247 | ieee80211_xmit(sdata, skb); | ||
2248 | local_bh_enable(); | ||
2249 | } | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 915e77769312..7fc55846d601 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "mesh.h" | 31 | #include "mesh.h" |
32 | #include "wme.h" | 32 | #include "wme.h" |
33 | #include "led.h" | 33 | #include "led.h" |
34 | #include "wep.h" | ||
34 | 35 | ||
35 | /* privid for wiphys to determine whether they belong to us or not */ | 36 | /* privid for wiphys to determine whether they belong to us or not */ |
36 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 37 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; |
@@ -274,16 +275,12 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
274 | 275 | ||
275 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 276 | __clear_bit(reason, &local->queue_stop_reasons[queue]); |
276 | 277 | ||
277 | if (!skb_queue_empty(&local->pending[queue]) && | ||
278 | local->queue_stop_reasons[queue] == | ||
279 | BIT(IEEE80211_QUEUE_STOP_REASON_PENDING)) | ||
280 | tasklet_schedule(&local->tx_pending_tasklet); | ||
281 | |||
282 | if (local->queue_stop_reasons[queue] != 0) | 278 | if (local->queue_stop_reasons[queue] != 0) |
283 | /* someone still has this queue stopped */ | 279 | /* someone still has this queue stopped */ |
284 | return; | 280 | return; |
285 | 281 | ||
286 | netif_wake_subqueue(local->mdev, queue); | 282 | if (!skb_queue_empty(&local->pending[queue])) |
283 | tasklet_schedule(&local->tx_pending_tasklet); | ||
287 | } | 284 | } |
288 | 285 | ||
289 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 286 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
@@ -312,14 +309,6 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
312 | if (WARN_ON(queue >= hw->queues)) | 309 | if (WARN_ON(queue >= hw->queues)) |
313 | return; | 310 | return; |
314 | 311 | ||
315 | /* | ||
316 | * Only stop if it was previously running, this is necessary | ||
317 | * for correct pending packets handling because there we may | ||
318 | * start (but not wake) the queue and rely on that. | ||
319 | */ | ||
320 | if (!local->queue_stop_reasons[queue]) | ||
321 | netif_stop_subqueue(local->mdev, queue); | ||
322 | |||
323 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 312 | __set_bit(reason, &local->queue_stop_reasons[queue]); |
324 | } | 313 | } |
325 | 314 | ||
@@ -350,8 +339,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
350 | 339 | ||
351 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 340 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
352 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 341 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
353 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING); | 342 | __skb_queue_tail(&local->pending[queue], skb); |
354 | skb_queue_tail(&local->pending[queue], skb); | ||
355 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 343 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
356 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 344 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
357 | } | 345 | } |
@@ -372,16 +360,12 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
372 | while ((skb = skb_dequeue(skbs))) { | 360 | while ((skb = skb_dequeue(skbs))) { |
373 | ret++; | 361 | ret++; |
374 | queue = skb_get_queue_mapping(skb); | 362 | queue = skb_get_queue_mapping(skb); |
375 | skb_queue_tail(&local->pending[queue], skb); | 363 | __skb_queue_tail(&local->pending[queue], skb); |
376 | } | 364 | } |
377 | 365 | ||
378 | for (i = 0; i < hw->queues; i++) { | 366 | for (i = 0; i < hw->queues; i++) |
379 | if (ret) | ||
380 | __ieee80211_stop_queue(hw, i, | ||
381 | IEEE80211_QUEUE_STOP_REASON_PENDING); | ||
382 | __ieee80211_wake_queue(hw, i, | 367 | __ieee80211_wake_queue(hw, i, |
383 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 368 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); |
384 | } | ||
385 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 369 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
386 | 370 | ||
387 | return ret; | 371 | return ret; |
@@ -412,11 +396,16 @@ EXPORT_SYMBOL(ieee80211_stop_queues); | |||
412 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | 396 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) |
413 | { | 397 | { |
414 | struct ieee80211_local *local = hw_to_local(hw); | 398 | struct ieee80211_local *local = hw_to_local(hw); |
399 | unsigned long flags; | ||
400 | int ret; | ||
415 | 401 | ||
416 | if (WARN_ON(queue >= hw->queues)) | 402 | if (WARN_ON(queue >= hw->queues)) |
417 | return true; | 403 | return true; |
418 | 404 | ||
419 | return __netif_subqueue_stopped(local->mdev, queue); | 405 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
406 | ret = !!local->queue_stop_reasons[queue]; | ||
407 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
408 | return ret; | ||
420 | } | 409 | } |
421 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 410 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
422 | 411 | ||
@@ -760,20 +749,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
760 | ieee80211_set_wmm_default(sdata); | 749 | ieee80211_set_wmm_default(sdata); |
761 | } | 750 | } |
762 | 751 | ||
763 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
764 | int encrypt) | ||
765 | { | ||
766 | skb->dev = sdata->local->mdev; | ||
767 | skb_set_mac_header(skb, 0); | ||
768 | skb_set_network_header(skb, 0); | ||
769 | skb_set_transport_header(skb, 0); | ||
770 | |||
771 | skb->iif = sdata->dev->ifindex; | ||
772 | skb->do_not_encrypt = !encrypt; | ||
773 | |||
774 | dev_queue_xmit(skb); | ||
775 | } | ||
776 | |||
777 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 752 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
778 | enum ieee80211_band band) | 753 | enum ieee80211_band band) |
779 | { | 754 | { |
@@ -804,12 +779,13 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | |||
804 | 779 | ||
805 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 780 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
806 | u16 transaction, u16 auth_alg, | 781 | u16 transaction, u16 auth_alg, |
807 | u8 *extra, size_t extra_len, | 782 | u8 *extra, size_t extra_len, const u8 *bssid, |
808 | const u8 *bssid, int encrypt) | 783 | const u8 *key, u8 key_len, u8 key_idx) |
809 | { | 784 | { |
810 | struct ieee80211_local *local = sdata->local; | 785 | struct ieee80211_local *local = sdata->local; |
811 | struct sk_buff *skb; | 786 | struct sk_buff *skb; |
812 | struct ieee80211_mgmt *mgmt; | 787 | struct ieee80211_mgmt *mgmt; |
788 | int err; | ||
813 | 789 | ||
814 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 790 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
815 | sizeof(*mgmt) + 6 + extra_len); | 791 | sizeof(*mgmt) + 6 + extra_len); |
@@ -824,8 +800,6 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
824 | memset(mgmt, 0, 24 + 6); | 800 | memset(mgmt, 0, 24 + 6); |
825 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 801 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
826 | IEEE80211_STYPE_AUTH); | 802 | IEEE80211_STYPE_AUTH); |
827 | if (encrypt) | ||
828 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
829 | memcpy(mgmt->da, bssid, ETH_ALEN); | 803 | memcpy(mgmt->da, bssid, ETH_ALEN); |
830 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 804 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
831 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 805 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
@@ -835,7 +809,13 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
835 | if (extra) | 809 | if (extra) |
836 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 810 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
837 | 811 | ||
838 | ieee80211_tx_skb(sdata, skb, encrypt); | 812 | if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { |
813 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | ||
814 | err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx); | ||
815 | WARN_ON(err); | ||
816 | } | ||
817 | |||
818 | ieee80211_tx_skb(sdata, skb, 0); | ||
839 | } | 819 | } |
840 | 820 | ||
841 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 821 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
@@ -1043,9 +1023,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1043 | /* reconfigure hardware */ | 1023 | /* reconfigure hardware */ |
1044 | ieee80211_hw_config(local, ~0); | 1024 | ieee80211_hw_config(local, ~0); |
1045 | 1025 | ||
1046 | netif_addr_lock_bh(local->mdev); | 1026 | spin_lock_bh(&local->filter_lock); |
1047 | ieee80211_configure_filter(local); | 1027 | ieee80211_configure_filter(local); |
1048 | netif_addr_unlock_bh(local->mdev); | 1028 | spin_unlock_bh(&local->filter_lock); |
1049 | 1029 | ||
1050 | /* Finally also reconfigure all the BSS information */ | 1030 | /* Finally also reconfigure all the BSS information */ |
1051 | list_for_each_entry(sdata, &local->interfaces, list) { | 1031 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 4fafb2d27c84..8a980f136941 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -144,9 +144,9 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
144 | * | 144 | * |
145 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) | 145 | * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) |
146 | */ | 146 | */ |
147 | static int ieee80211_wep_encrypt(struct ieee80211_local *local, | 147 | int ieee80211_wep_encrypt(struct ieee80211_local *local, |
148 | struct sk_buff *skb, | 148 | struct sk_buff *skb, |
149 | const u8 *key, int keylen, int keyidx) | 149 | const u8 *key, int keylen, int keyidx) |
150 | { | 150 | { |
151 | u8 *iv; | 151 | u8 *iv; |
152 | size_t len; | 152 | size_t len; |
diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 85219ded8703..fe29d7e5759f 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h | |||
@@ -20,6 +20,9 @@ int ieee80211_wep_init(struct ieee80211_local *local); | |||
20 | void ieee80211_wep_free(struct ieee80211_local *local); | 20 | void ieee80211_wep_free(struct ieee80211_local *local); |
21 | void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 21 | void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, |
22 | size_t klen, u8 *data, size_t data_len); | 22 | size_t klen, u8 *data, size_t data_len); |
23 | int ieee80211_wep_encrypt(struct ieee80211_local *local, | ||
24 | struct sk_buff *skb, | ||
25 | const u8 *key, int keylen, int keyidx); | ||
23 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | 26 | int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, |
24 | size_t klen, u8 *data, size_t data_len); | 27 | size_t klen, u8 *data, size_t data_len); |
25 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); | 28 | bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 116a923b14d6..b19b7696f3a2 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -85,10 +85,8 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) | |||
85 | return ieee802_1d_to_ac[skb->priority]; | 85 | return ieee802_1d_to_ac[skb->priority]; |
86 | } | 86 | } |
87 | 87 | ||
88 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | 88 | void ieee80211_select_queue(struct ieee80211_local *local, struct sk_buff *skb) |
89 | { | 89 | { |
90 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
91 | struct ieee80211_local *local = mpriv->local; | ||
92 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 90 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
93 | u16 queue; | 91 | u16 queue; |
94 | u8 tid; | 92 | u8 tid; |
@@ -113,5 +111,5 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | |||
113 | *p = 0; | 111 | *p = 0; |
114 | } | 112 | } |
115 | 113 | ||
116 | return queue; | 114 | skb_set_queue_mapping(skb, queue); |
117 | } | 115 | } |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 7520d2e014dc..d4fd87ca5118 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | extern const int ieee802_1d_to_ac[8]; | 21 | extern const int ieee802_1d_to_ac[8]; |
22 | 22 | ||
23 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb); | 23 | void ieee80211_select_queue(struct ieee80211_local *local, |
24 | struct sk_buff *skb); | ||
24 | 25 | ||
25 | #endif /* _WME_H */ | 26 | #endif /* _WME_H */ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 1a78b3c70cf2..6891cd0e38d5 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -548,11 +548,6 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
548 | /* unlock again before freeing */ | 548 | /* unlock again before freeing */ |
549 | mutex_unlock(&rdev->mtx); | 549 | mutex_unlock(&rdev->mtx); |
550 | 550 | ||
551 | cancel_work_sync(&rdev->conn_work); | ||
552 | cancel_work_sync(&rdev->scan_done_wk); | ||
553 | kfree(rdev->scan_req); | ||
554 | flush_work(&rdev->event_work); | ||
555 | |||
556 | cfg80211_debugfs_rdev_del(rdev); | 551 | cfg80211_debugfs_rdev_del(rdev); |
557 | 552 | ||
558 | /* If this device got a regulatory hint tell core its | 553 | /* If this device got a regulatory hint tell core its |
@@ -564,6 +559,11 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
564 | debugfs_remove(rdev->wiphy.debugfsdir); | 559 | debugfs_remove(rdev->wiphy.debugfsdir); |
565 | 560 | ||
566 | mutex_unlock(&cfg80211_mutex); | 561 | mutex_unlock(&cfg80211_mutex); |
562 | |||
563 | cancel_work_sync(&rdev->conn_work); | ||
564 | cancel_work_sync(&rdev->scan_done_wk); | ||
565 | kfree(rdev->scan_req); | ||
566 | flush_work(&rdev->event_work); | ||
567 | } | 567 | } |
568 | EXPORT_SYMBOL(wiphy_unregister); | 568 | EXPORT_SYMBOL(wiphy_unregister); |
569 | 569 | ||
@@ -666,14 +666,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
666 | wdev_lock(wdev); | 666 | wdev_lock(wdev); |
667 | switch (wdev->iftype) { | 667 | switch (wdev->iftype) { |
668 | case NL80211_IFTYPE_ADHOC: | 668 | case NL80211_IFTYPE_ADHOC: |
669 | if (wdev->wext.ibss.ssid_len) | 669 | cfg80211_ibss_wext_join(rdev, wdev); |
670 | __cfg80211_join_ibss(rdev, dev, | ||
671 | &wdev->wext.ibss); | ||
672 | break; | 670 | break; |
673 | case NL80211_IFTYPE_STATION: | 671 | case NL80211_IFTYPE_STATION: |
674 | if (wdev->wext.connect.ssid_len) | 672 | cfg80211_mgd_wext_connect(rdev, wdev); |
675 | __cfg80211_connect(rdev, dev, | ||
676 | &wdev->wext.connect); | ||
677 | break; | 673 | break; |
678 | default: | 674 | default: |
679 | break; | 675 | break; |
@@ -690,6 +686,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
690 | } | 686 | } |
691 | mutex_unlock(&rdev->devlist_mtx); | 687 | mutex_unlock(&rdev->devlist_mtx); |
692 | mutex_destroy(&wdev->mtx); | 688 | mutex_destroy(&wdev->mtx); |
689 | #ifdef CONFIG_WIRELESS_EXT | ||
690 | kfree(wdev->wext.keys); | ||
691 | #endif | ||
693 | break; | 692 | break; |
694 | case NETDEV_PRE_UP: | 693 | case NETDEV_PRE_UP: |
695 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 694 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
diff --git a/net/wireless/core.h b/net/wireless/core.h index e46cd6eb61d7..2ec8ddbe57de 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -238,6 +238,12 @@ struct cfg80211_event { | |||
238 | }; | 238 | }; |
239 | }; | 239 | }; |
240 | 240 | ||
241 | struct cfg80211_cached_keys { | ||
242 | struct key_params params[6]; | ||
243 | u8 data[6][WLAN_MAX_KEY_LEN]; | ||
244 | int def, defmgmt; | ||
245 | }; | ||
246 | |||
241 | 247 | ||
242 | /* free object */ | 248 | /* free object */ |
243 | extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); | 249 | extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev); |
@@ -256,14 +262,18 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
256 | /* IBSS */ | 262 | /* IBSS */ |
257 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 263 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
258 | struct net_device *dev, | 264 | struct net_device *dev, |
259 | struct cfg80211_ibss_params *params); | 265 | struct cfg80211_ibss_params *params, |
266 | struct cfg80211_cached_keys *connkeys); | ||
260 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 267 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
261 | struct net_device *dev, | 268 | struct net_device *dev, |
262 | struct cfg80211_ibss_params *params); | 269 | struct cfg80211_ibss_params *params, |
270 | struct cfg80211_cached_keys *connkeys); | ||
263 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | 271 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); |
264 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 272 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
265 | struct net_device *dev, bool nowext); | 273 | struct net_device *dev, bool nowext); |
266 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | 274 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); |
275 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | ||
276 | struct wireless_dev *wdev); | ||
267 | 277 | ||
268 | /* MLME */ | 278 | /* MLME */ |
269 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 279 | int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
@@ -272,12 +282,14 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
272 | enum nl80211_auth_type auth_type, | 282 | enum nl80211_auth_type auth_type, |
273 | const u8 *bssid, | 283 | const u8 *bssid, |
274 | const u8 *ssid, int ssid_len, | 284 | const u8 *ssid, int ssid_len, |
275 | const u8 *ie, int ie_len); | 285 | const u8 *ie, int ie_len, |
286 | const u8 *key, int key_len, int key_idx); | ||
276 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 287 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
277 | struct net_device *dev, struct ieee80211_channel *chan, | 288 | struct net_device *dev, struct ieee80211_channel *chan, |
278 | enum nl80211_auth_type auth_type, const u8 *bssid, | 289 | enum nl80211_auth_type auth_type, const u8 *bssid, |
279 | const u8 *ssid, int ssid_len, | 290 | const u8 *ssid, int ssid_len, |
280 | const u8 *ie, int ie_len); | 291 | const u8 *ie, int ie_len, |
292 | const u8 *key, int key_len, int key_idx); | ||
281 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 293 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
282 | struct net_device *dev, | 294 | struct net_device *dev, |
283 | struct ieee80211_channel *chan, | 295 | struct ieee80211_channel *chan, |
@@ -310,10 +322,12 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
310 | /* SME */ | 322 | /* SME */ |
311 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 323 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
312 | struct net_device *dev, | 324 | struct net_device *dev, |
313 | struct cfg80211_connect_params *connect); | 325 | struct cfg80211_connect_params *connect, |
326 | struct cfg80211_cached_keys *connkeys); | ||
314 | int cfg80211_connect(struct cfg80211_registered_device *rdev, | 327 | int cfg80211_connect(struct cfg80211_registered_device *rdev, |
315 | struct net_device *dev, | 328 | struct net_device *dev, |
316 | struct cfg80211_connect_params *connect); | 329 | struct cfg80211_connect_params *connect, |
330 | struct cfg80211_cached_keys *connkeys); | ||
317 | int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 331 | int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
318 | struct net_device *dev, u16 reason, | 332 | struct net_device *dev, u16 reason, |
319 | bool wextev); | 333 | bool wextev); |
@@ -323,11 +337,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
323 | void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | 337 | void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, |
324 | const u8 *req_ie, size_t req_ie_len, | 338 | const u8 *req_ie, size_t req_ie_len, |
325 | const u8 *resp_ie, size_t resp_ie_len); | 339 | const u8 *resp_ie, size_t resp_ie_len); |
340 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | ||
341 | struct wireless_dev *wdev); | ||
326 | 342 | ||
327 | void cfg80211_conn_work(struct work_struct *work); | 343 | void cfg80211_conn_work(struct work_struct *work); |
328 | 344 | ||
329 | /* internal helpers */ | 345 | /* internal helpers */ |
330 | int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | 346 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
347 | struct key_params *params, int key_idx, | ||
331 | const u8 *mac_addr); | 348 | const u8 *mac_addr); |
332 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 349 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
333 | size_t ie_len, u16 reason, bool from_ap); | 350 | size_t ie_len, u16 reason, bool from_ap); |
@@ -335,5 +352,6 @@ void cfg80211_sme_scan_done(struct net_device *dev); | |||
335 | void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | 352 | void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); |
336 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); | 353 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); |
337 | void __cfg80211_scan_done(struct work_struct *wk); | 354 | void __cfg80211_scan_done(struct work_struct *wk); |
355 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); | ||
338 | 356 | ||
339 | #endif /* __NET_WIRELESS_CORE_H */ | 357 | #endif /* __NET_WIRELESS_CORE_H */ |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 99ef9364b7e8..8b65e212ae49 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -39,6 +39,8 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
39 | cfg80211_hold_bss(bss_from_pub(bss)); | 39 | cfg80211_hold_bss(bss_from_pub(bss)); |
40 | wdev->current_bss = bss_from_pub(bss); | 40 | wdev->current_bss = bss_from_pub(bss); |
41 | 41 | ||
42 | cfg80211_upload_connect_keys(wdev); | ||
43 | |||
42 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, | 44 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, |
43 | GFP_KERNEL); | 45 | GFP_KERNEL); |
44 | #ifdef CONFIG_WIRELESS_EXT | 46 | #ifdef CONFIG_WIRELESS_EXT |
@@ -71,7 +73,8 @@ EXPORT_SYMBOL(cfg80211_ibss_joined); | |||
71 | 73 | ||
72 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 74 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
73 | struct net_device *dev, | 75 | struct net_device *dev, |
74 | struct cfg80211_ibss_params *params) | 76 | struct cfg80211_ibss_params *params, |
77 | struct cfg80211_cached_keys *connkeys) | ||
75 | { | 78 | { |
76 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 79 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
77 | int err; | 80 | int err; |
@@ -81,13 +84,18 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
81 | if (wdev->ssid_len) | 84 | if (wdev->ssid_len) |
82 | return -EALREADY; | 85 | return -EALREADY; |
83 | 86 | ||
87 | if (WARN_ON(wdev->connect_keys)) | ||
88 | kfree(wdev->connect_keys); | ||
89 | wdev->connect_keys = connkeys; | ||
90 | |||
84 | #ifdef CONFIG_WIRELESS_EXT | 91 | #ifdef CONFIG_WIRELESS_EXT |
85 | wdev->wext.ibss.channel = params->channel; | 92 | wdev->wext.ibss.channel = params->channel; |
86 | #endif | 93 | #endif |
87 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 94 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
88 | 95 | if (err) { | |
89 | if (err) | 96 | wdev->connect_keys = NULL; |
90 | return err; | 97 | return err; |
98 | } | ||
91 | 99 | ||
92 | memcpy(wdev->ssid, params->ssid, params->ssid_len); | 100 | memcpy(wdev->ssid, params->ssid, params->ssid_len); |
93 | wdev->ssid_len = params->ssid_len; | 101 | wdev->ssid_len = params->ssid_len; |
@@ -97,13 +105,14 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
97 | 105 | ||
98 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 106 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
99 | struct net_device *dev, | 107 | struct net_device *dev, |
100 | struct cfg80211_ibss_params *params) | 108 | struct cfg80211_ibss_params *params, |
109 | struct cfg80211_cached_keys *connkeys) | ||
101 | { | 110 | { |
102 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 111 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
103 | int err; | 112 | int err; |
104 | 113 | ||
105 | wdev_lock(wdev); | 114 | wdev_lock(wdev); |
106 | err = __cfg80211_join_ibss(rdev, dev, params); | 115 | err = __cfg80211_join_ibss(rdev, dev, params, connkeys); |
107 | wdev_unlock(wdev); | 116 | wdev_unlock(wdev); |
108 | 117 | ||
109 | return err; | 118 | return err; |
@@ -112,9 +121,22 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
112 | static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | 121 | static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) |
113 | { | 122 | { |
114 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 123 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
124 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
125 | int i; | ||
115 | 126 | ||
116 | ASSERT_WDEV_LOCK(wdev); | 127 | ASSERT_WDEV_LOCK(wdev); |
117 | 128 | ||
129 | kfree(wdev->connect_keys); | ||
130 | wdev->connect_keys = NULL; | ||
131 | |||
132 | /* | ||
133 | * Delete all the keys ... pairwise keys can't really | ||
134 | * exist any more anyway, but default keys might. | ||
135 | */ | ||
136 | if (rdev->ops->del_key) | ||
137 | for (i = 0; i < 6; i++) | ||
138 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); | ||
139 | |||
118 | if (wdev->current_bss) { | 140 | if (wdev->current_bss) { |
119 | cfg80211_unhold_bss(wdev->current_bss); | 141 | cfg80211_unhold_bss(wdev->current_bss); |
120 | cfg80211_put_bss(&wdev->current_bss->pub); | 142 | cfg80211_put_bss(&wdev->current_bss->pub); |
@@ -172,11 +194,14 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | |||
172 | } | 194 | } |
173 | 195 | ||
174 | #ifdef CONFIG_WIRELESS_EXT | 196 | #ifdef CONFIG_WIRELESS_EXT |
175 | static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | 197 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, |
176 | struct wireless_dev *wdev) | 198 | struct wireless_dev *wdev) |
177 | { | 199 | { |
200 | struct cfg80211_cached_keys *ck = NULL; | ||
178 | enum ieee80211_band band; | 201 | enum ieee80211_band band; |
179 | int i; | 202 | int i, err; |
203 | |||
204 | ASSERT_WDEV_LOCK(wdev); | ||
180 | 205 | ||
181 | if (!wdev->wext.ibss.beacon_interval) | 206 | if (!wdev->wext.ibss.beacon_interval) |
182 | wdev->wext.ibss.beacon_interval = 100; | 207 | wdev->wext.ibss.beacon_interval = 100; |
@@ -216,8 +241,24 @@ static int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | |||
216 | if (!netif_running(wdev->netdev)) | 241 | if (!netif_running(wdev->netdev)) |
217 | return 0; | 242 | return 0; |
218 | 243 | ||
219 | return cfg80211_join_ibss(wiphy_to_dev(wdev->wiphy), | 244 | if (wdev->wext.keys) |
220 | wdev->netdev, &wdev->wext.ibss); | 245 | wdev->wext.keys->def = wdev->wext.default_key; |
246 | |||
247 | wdev->wext.ibss.privacy = wdev->wext.default_key != -1; | ||
248 | |||
249 | if (wdev->wext.keys) { | ||
250 | ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL); | ||
251 | if (!ck) | ||
252 | return -ENOMEM; | ||
253 | for (i = 0; i < 6; i++) | ||
254 | ck->params[i].key = ck->data[i]; | ||
255 | } | ||
256 | err = __cfg80211_join_ibss(rdev, wdev->netdev, | ||
257 | &wdev->wext.ibss, ck); | ||
258 | if (err) | ||
259 | kfree(ck); | ||
260 | |||
261 | return err; | ||
221 | } | 262 | } |
222 | 263 | ||
223 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | 264 | int cfg80211_ibss_wext_siwfreq(struct net_device *dev, |
@@ -265,7 +306,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, | |||
265 | wdev->wext.ibss.channel_fixed = false; | 306 | wdev->wext.ibss.channel_fixed = false; |
266 | } | 307 | } |
267 | 308 | ||
268 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 309 | wdev_lock(wdev); |
310 | err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | ||
311 | wdev_unlock(wdev); | ||
312 | |||
313 | return err; | ||
269 | } | 314 | } |
270 | /* temporary symbol - mark GPL - in the future the handler won't be */ | 315 | /* temporary symbol - mark GPL - in the future the handler won't be */ |
271 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); | 316 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); |
@@ -333,7 +378,11 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, | |||
333 | memcpy(wdev->wext.ibss.ssid, ssid, len); | 378 | memcpy(wdev->wext.ibss.ssid, ssid, len); |
334 | wdev->wext.ibss.ssid_len = len; | 379 | wdev->wext.ibss.ssid_len = len; |
335 | 380 | ||
336 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 381 | wdev_lock(wdev); |
382 | err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | ||
383 | wdev_unlock(wdev); | ||
384 | |||
385 | return err; | ||
337 | } | 386 | } |
338 | /* temporary symbol - mark GPL - in the future the handler won't be */ | 387 | /* temporary symbol - mark GPL - in the future the handler won't be */ |
339 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); | 388 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); |
@@ -414,7 +463,11 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, | |||
414 | } else | 463 | } else |
415 | wdev->wext.ibss.bssid = NULL; | 464 | wdev->wext.ibss.bssid = NULL; |
416 | 465 | ||
417 | return cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | 466 | wdev_lock(wdev); |
467 | err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); | ||
468 | wdev_unlock(wdev); | ||
469 | |||
470 | return err; | ||
418 | } | 471 | } |
419 | /* temporary symbol - mark GPL - in the future the handler won't be */ | 472 | /* temporary symbol - mark GPL - in the future the handler won't be */ |
420 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); | 473 | EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); |
@@ -434,8 +487,11 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, | |||
434 | wdev_lock(wdev); | 487 | wdev_lock(wdev); |
435 | if (wdev->current_bss) | 488 | if (wdev->current_bss) |
436 | memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); | 489 | memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN); |
437 | else | 490 | else if (wdev->wext.ibss.bssid) |
438 | memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); | 491 | memcpy(ap_addr->sa_data, wdev->wext.ibss.bssid, ETH_ALEN); |
492 | else | ||
493 | memset(ap_addr->sa_data, 0, ETH_ALEN); | ||
494 | |||
439 | wdev_unlock(wdev); | 495 | wdev_unlock(wdev); |
440 | 496 | ||
441 | return 0; | 497 | return 0; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1b2ca1fea7a1..5b9b22120824 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -178,12 +178,12 @@ static void __cfg80211_send_disassoc(struct net_device *dev, | |||
178 | bool from_ap; | 178 | bool from_ap; |
179 | bool done = false; | 179 | bool done = false; |
180 | 180 | ||
181 | wdev_lock(wdev); | 181 | ASSERT_WDEV_LOCK(wdev); |
182 | 182 | ||
183 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); | 183 | nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); |
184 | 184 | ||
185 | if (!wdev->sme_state == CFG80211_SME_CONNECTED) | 185 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
186 | goto out; | 186 | return; |
187 | 187 | ||
188 | if (wdev->current_bss && | 188 | if (wdev->current_bss && |
189 | memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { | 189 | memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { |
@@ -205,8 +205,6 @@ static void __cfg80211_send_disassoc(struct net_device *dev, | |||
205 | 205 | ||
206 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; | 206 | from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; |
207 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); | 207 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
208 | out: | ||
209 | wdev_unlock(wdev); | ||
210 | } | 208 | } |
211 | 209 | ||
212 | void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, | 210 | void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len, |
@@ -328,7 +326,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
328 | enum nl80211_auth_type auth_type, | 326 | enum nl80211_auth_type auth_type, |
329 | const u8 *bssid, | 327 | const u8 *bssid, |
330 | const u8 *ssid, int ssid_len, | 328 | const u8 *ssid, int ssid_len, |
331 | const u8 *ie, int ie_len) | 329 | const u8 *ie, int ie_len, |
330 | const u8 *key, int key_len, int key_idx) | ||
332 | { | 331 | { |
333 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 332 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
334 | struct cfg80211_auth_request req; | 333 | struct cfg80211_auth_request req; |
@@ -337,6 +336,10 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
337 | 336 | ||
338 | ASSERT_WDEV_LOCK(wdev); | 337 | ASSERT_WDEV_LOCK(wdev); |
339 | 338 | ||
339 | if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) | ||
340 | if (!key || !key_len || key_idx < 0 || key_idx > 4) | ||
341 | return -EINVAL; | ||
342 | |||
340 | if (wdev->current_bss && | 343 | if (wdev->current_bss && |
341 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) | 344 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) |
342 | return -EALREADY; | 345 | return -EALREADY; |
@@ -359,6 +362,9 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
359 | req.auth_type = auth_type; | 362 | req.auth_type = auth_type; |
360 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 363 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
361 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 364 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
365 | req.key = key; | ||
366 | req.key_len = key_len; | ||
367 | req.key_idx = key_idx; | ||
362 | if (!req.bss) | 368 | if (!req.bss) |
363 | return -ENOENT; | 369 | return -ENOENT; |
364 | 370 | ||
@@ -396,13 +402,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
396 | struct net_device *dev, struct ieee80211_channel *chan, | 402 | struct net_device *dev, struct ieee80211_channel *chan, |
397 | enum nl80211_auth_type auth_type, const u8 *bssid, | 403 | enum nl80211_auth_type auth_type, const u8 *bssid, |
398 | const u8 *ssid, int ssid_len, | 404 | const u8 *ssid, int ssid_len, |
399 | const u8 *ie, int ie_len) | 405 | const u8 *ie, int ie_len, |
406 | const u8 *key, int key_len, int key_idx) | ||
400 | { | 407 | { |
401 | int err; | 408 | int err; |
402 | 409 | ||
403 | wdev_lock(dev->ieee80211_ptr); | 410 | wdev_lock(dev->ieee80211_ptr); |
404 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 411 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
405 | ssid, ssid_len, ie, ie_len); | 412 | ssid, ssid_len, ie, ie_len, |
413 | key, key_len, key_idx); | ||
406 | wdev_unlock(dev->ieee80211_ptr); | 414 | wdev_unlock(dev->ieee80211_ptr); |
407 | 415 | ||
408 | return err; | 416 | return err; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4478760b7dc3..da450ef1fc7e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -73,6 +73,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
73 | [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, | 73 | [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, |
74 | [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, | 74 | [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN }, |
75 | 75 | ||
76 | [NL80211_ATTR_KEY] = { .type = NLA_NESTED, }, | ||
76 | [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, | 77 | [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, |
77 | .len = WLAN_MAX_KEY_LEN }, | 78 | .len = WLAN_MAX_KEY_LEN }, |
78 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, | 79 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, |
@@ -134,6 +135,17 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
134 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, | 135 | [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, |
135 | }; | 136 | }; |
136 | 137 | ||
138 | /* policy for the attributes */ | ||
139 | static struct nla_policy | ||
140 | nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = { | ||
141 | [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, | ||
142 | [NL80211_KEY_IDX] = { .type = NLA_U8 }, | ||
143 | [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, | ||
144 | [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, | ||
145 | [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, | ||
146 | [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, | ||
147 | }; | ||
148 | |||
137 | /* IE validation */ | 149 | /* IE validation */ |
138 | static bool is_valid_ie_attr(const struct nlattr *attr) | 150 | static bool is_valid_ie_attr(const struct nlattr *attr) |
139 | { | 151 | { |
@@ -198,6 +210,177 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
198 | 210 | ||
199 | /* netlink command implementations */ | 211 | /* netlink command implementations */ |
200 | 212 | ||
213 | struct key_parse { | ||
214 | struct key_params p; | ||
215 | int idx; | ||
216 | bool def, defmgmt; | ||
217 | }; | ||
218 | |||
219 | static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k) | ||
220 | { | ||
221 | struct nlattr *tb[NL80211_KEY_MAX + 1]; | ||
222 | int err = nla_parse_nested(tb, NL80211_KEY_MAX, key, | ||
223 | nl80211_key_policy); | ||
224 | if (err) | ||
225 | return err; | ||
226 | |||
227 | k->def = !!tb[NL80211_KEY_DEFAULT]; | ||
228 | k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT]; | ||
229 | |||
230 | if (tb[NL80211_KEY_IDX]) | ||
231 | k->idx = nla_get_u8(tb[NL80211_KEY_IDX]); | ||
232 | |||
233 | if (tb[NL80211_KEY_DATA]) { | ||
234 | k->p.key = nla_data(tb[NL80211_KEY_DATA]); | ||
235 | k->p.key_len = nla_len(tb[NL80211_KEY_DATA]); | ||
236 | } | ||
237 | |||
238 | if (tb[NL80211_KEY_SEQ]) { | ||
239 | k->p.seq = nla_data(tb[NL80211_KEY_SEQ]); | ||
240 | k->p.seq_len = nla_len(tb[NL80211_KEY_SEQ]); | ||
241 | } | ||
242 | |||
243 | if (tb[NL80211_KEY_CIPHER]) | ||
244 | k->p.cipher = nla_get_u32(tb[NL80211_KEY_CIPHER]); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k) | ||
250 | { | ||
251 | if (info->attrs[NL80211_ATTR_KEY_DATA]) { | ||
252 | k->p.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); | ||
253 | k->p.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); | ||
254 | } | ||
255 | |||
256 | if (info->attrs[NL80211_ATTR_KEY_SEQ]) { | ||
257 | k->p.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
258 | k->p.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
259 | } | ||
260 | |||
261 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | ||
262 | k->idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | ||
263 | |||
264 | if (info->attrs[NL80211_ATTR_KEY_CIPHER]) | ||
265 | k->p.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); | ||
266 | |||
267 | k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT]; | ||
268 | k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]; | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int nl80211_parse_key(struct genl_info *info, struct key_parse *k) | ||
274 | { | ||
275 | int err; | ||
276 | |||
277 | memset(k, 0, sizeof(*k)); | ||
278 | k->idx = -1; | ||
279 | |||
280 | if (info->attrs[NL80211_ATTR_KEY]) | ||
281 | err = nl80211_parse_key_new(info->attrs[NL80211_ATTR_KEY], k); | ||
282 | else | ||
283 | err = nl80211_parse_key_old(info, k); | ||
284 | |||
285 | if (err) | ||
286 | return err; | ||
287 | |||
288 | if (k->def && k->defmgmt) | ||
289 | return -EINVAL; | ||
290 | |||
291 | if (k->idx != -1) { | ||
292 | if (k->defmgmt) { | ||
293 | if (k->idx < 4 || k->idx > 5) | ||
294 | return -EINVAL; | ||
295 | } else if (k->def) { | ||
296 | if (k->idx < 0 || k->idx > 3) | ||
297 | return -EINVAL; | ||
298 | } else { | ||
299 | if (k->idx < 0 || k->idx > 5) | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static struct cfg80211_cached_keys * | ||
308 | nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, | ||
309 | struct nlattr *keys) | ||
310 | { | ||
311 | struct key_parse parse; | ||
312 | struct nlattr *key; | ||
313 | struct cfg80211_cached_keys *result; | ||
314 | int rem, err, def = 0; | ||
315 | |||
316 | result = kzalloc(sizeof(*result), GFP_KERNEL); | ||
317 | if (!result) | ||
318 | return ERR_PTR(-ENOMEM); | ||
319 | |||
320 | result->def = -1; | ||
321 | result->defmgmt = -1; | ||
322 | |||
323 | nla_for_each_nested(key, keys, rem) { | ||
324 | memset(&parse, 0, sizeof(parse)); | ||
325 | parse.idx = -1; | ||
326 | |||
327 | err = nl80211_parse_key_new(key, &parse); | ||
328 | if (err) | ||
329 | goto error; | ||
330 | err = -EINVAL; | ||
331 | if (!parse.p.key) | ||
332 | goto error; | ||
333 | if (parse.idx < 0 || parse.idx > 4) | ||
334 | goto error; | ||
335 | if (parse.def) { | ||
336 | if (def) | ||
337 | goto error; | ||
338 | def = 1; | ||
339 | result->def = parse.idx; | ||
340 | } else if (parse.defmgmt) | ||
341 | goto error; | ||
342 | err = cfg80211_validate_key_settings(rdev, &parse.p, | ||
343 | parse.idx, NULL); | ||
344 | if (err) | ||
345 | goto error; | ||
346 | result->params[parse.idx].cipher = parse.p.cipher; | ||
347 | result->params[parse.idx].key_len = parse.p.key_len; | ||
348 | result->params[parse.idx].key = result->data[parse.idx]; | ||
349 | memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len); | ||
350 | } | ||
351 | |||
352 | return result; | ||
353 | error: | ||
354 | kfree(result); | ||
355 | return ERR_PTR(err); | ||
356 | } | ||
357 | |||
358 | static int nl80211_key_allowed(struct wireless_dev *wdev) | ||
359 | { | ||
360 | ASSERT_WDEV_LOCK(wdev); | ||
361 | |||
362 | if (!netif_running(wdev->netdev)) | ||
363 | return -ENETDOWN; | ||
364 | |||
365 | switch (wdev->iftype) { | ||
366 | case NL80211_IFTYPE_AP: | ||
367 | case NL80211_IFTYPE_AP_VLAN: | ||
368 | break; | ||
369 | case NL80211_IFTYPE_ADHOC: | ||
370 | if (!wdev->current_bss) | ||
371 | return -ENOLINK; | ||
372 | break; | ||
373 | case NL80211_IFTYPE_STATION: | ||
374 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | ||
375 | return -ENOLINK; | ||
376 | break; | ||
377 | default: | ||
378 | return -EINVAL; | ||
379 | } | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
201 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 384 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
202 | struct cfg80211_registered_device *dev) | 385 | struct cfg80211_registered_device *dev) |
203 | { | 386 | { |
@@ -943,10 +1126,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
943 | struct get_key_cookie { | 1126 | struct get_key_cookie { |
944 | struct sk_buff *msg; | 1127 | struct sk_buff *msg; |
945 | int error; | 1128 | int error; |
1129 | int idx; | ||
946 | }; | 1130 | }; |
947 | 1131 | ||
948 | static void get_key_callback(void *c, struct key_params *params) | 1132 | static void get_key_callback(void *c, struct key_params *params) |
949 | { | 1133 | { |
1134 | struct nlattr *key; | ||
950 | struct get_key_cookie *cookie = c; | 1135 | struct get_key_cookie *cookie = c; |
951 | 1136 | ||
952 | if (params->key) | 1137 | if (params->key) |
@@ -961,6 +1146,26 @@ static void get_key_callback(void *c, struct key_params *params) | |||
961 | NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, | 1146 | NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, |
962 | params->cipher); | 1147 | params->cipher); |
963 | 1148 | ||
1149 | key = nla_nest_start(cookie->msg, NL80211_ATTR_KEY); | ||
1150 | if (!key) | ||
1151 | goto nla_put_failure; | ||
1152 | |||
1153 | if (params->key) | ||
1154 | NLA_PUT(cookie->msg, NL80211_KEY_DATA, | ||
1155 | params->key_len, params->key); | ||
1156 | |||
1157 | if (params->seq) | ||
1158 | NLA_PUT(cookie->msg, NL80211_KEY_SEQ, | ||
1159 | params->seq_len, params->seq); | ||
1160 | |||
1161 | if (params->cipher) | ||
1162 | NLA_PUT_U32(cookie->msg, NL80211_KEY_CIPHER, | ||
1163 | params->cipher); | ||
1164 | |||
1165 | NLA_PUT_U8(cookie->msg, NL80211_ATTR_KEY_IDX, cookie->idx); | ||
1166 | |||
1167 | nla_nest_end(cookie->msg, key); | ||
1168 | |||
964 | return; | 1169 | return; |
965 | nla_put_failure: | 1170 | nla_put_failure: |
966 | cookie->error = 1; | 1171 | cookie->error = 1; |
@@ -1014,6 +1219,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1014 | } | 1219 | } |
1015 | 1220 | ||
1016 | cookie.msg = msg; | 1221 | cookie.msg = msg; |
1222 | cookie.idx = key_idx; | ||
1017 | 1223 | ||
1018 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 1224 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
1019 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); | 1225 | NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); |
@@ -1049,26 +1255,21 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1049 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | 1255 | static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) |
1050 | { | 1256 | { |
1051 | struct cfg80211_registered_device *rdev; | 1257 | struct cfg80211_registered_device *rdev; |
1258 | struct key_parse key; | ||
1052 | int err; | 1259 | int err; |
1053 | struct net_device *dev; | 1260 | struct net_device *dev; |
1054 | u8 key_idx; | ||
1055 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, | 1261 | int (*func)(struct wiphy *wiphy, struct net_device *netdev, |
1056 | u8 key_index); | 1262 | u8 key_index); |
1057 | 1263 | ||
1058 | if (!info->attrs[NL80211_ATTR_KEY_IDX]) | 1264 | err = nl80211_parse_key(info, &key); |
1059 | return -EINVAL; | 1265 | if (err) |
1060 | 1266 | return err; | |
1061 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | ||
1062 | 1267 | ||
1063 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) { | 1268 | if (key.idx < 0) |
1064 | if (key_idx < 4 || key_idx > 5) | ||
1065 | return -EINVAL; | ||
1066 | } else if (key_idx > 3) | ||
1067 | return -EINVAL; | 1269 | return -EINVAL; |
1068 | 1270 | ||
1069 | /* currently only support setting default key */ | 1271 | /* only support setting default key */ |
1070 | if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] && | 1272 | if (!key.def && !key.defmgmt) |
1071 | !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) | ||
1072 | return -EINVAL; | 1273 | return -EINVAL; |
1073 | 1274 | ||
1074 | rtnl_lock(); | 1275 | rtnl_lock(); |
@@ -1077,7 +1278,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1077 | if (err) | 1278 | if (err) |
1078 | goto unlock_rtnl; | 1279 | goto unlock_rtnl; |
1079 | 1280 | ||
1080 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) | 1281 | if (key.def) |
1081 | func = rdev->ops->set_default_key; | 1282 | func = rdev->ops->set_default_key; |
1082 | else | 1283 | else |
1083 | func = rdev->ops->set_default_mgmt_key; | 1284 | func = rdev->ops->set_default_mgmt_key; |
@@ -1087,15 +1288,20 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1087 | goto out; | 1288 | goto out; |
1088 | } | 1289 | } |
1089 | 1290 | ||
1090 | err = func(&rdev->wiphy, dev, key_idx); | 1291 | wdev_lock(dev->ieee80211_ptr); |
1292 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1293 | if (!err) | ||
1294 | err = func(&rdev->wiphy, dev, key.idx); | ||
1295 | |||
1091 | #ifdef CONFIG_WIRELESS_EXT | 1296 | #ifdef CONFIG_WIRELESS_EXT |
1092 | if (!err) { | 1297 | if (!err) { |
1093 | if (func == rdev->ops->set_default_key) | 1298 | if (func == rdev->ops->set_default_key) |
1094 | dev->ieee80211_ptr->wext.default_key = key_idx; | 1299 | dev->ieee80211_ptr->wext.default_key = key.idx; |
1095 | else | 1300 | else |
1096 | dev->ieee80211_ptr->wext.default_mgmt_key = key_idx; | 1301 | dev->ieee80211_ptr->wext.default_mgmt_key = key.idx; |
1097 | } | 1302 | } |
1098 | #endif | 1303 | #endif |
1304 | wdev_unlock(dev->ieee80211_ptr); | ||
1099 | 1305 | ||
1100 | out: | 1306 | out: |
1101 | cfg80211_unlock_rdev(rdev); | 1307 | cfg80211_unlock_rdev(rdev); |
@@ -1110,58 +1316,43 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1110 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | 1316 | static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) |
1111 | { | 1317 | { |
1112 | struct cfg80211_registered_device *rdev; | 1318 | struct cfg80211_registered_device *rdev; |
1113 | int err, i; | 1319 | int err; |
1114 | struct net_device *dev; | 1320 | struct net_device *dev; |
1115 | struct key_params params; | 1321 | struct key_parse key; |
1116 | u8 key_idx = 0; | ||
1117 | u8 *mac_addr = NULL; | 1322 | u8 *mac_addr = NULL; |
1118 | 1323 | ||
1119 | memset(¶ms, 0, sizeof(params)); | 1324 | err = nl80211_parse_key(info, &key); |
1325 | if (err) | ||
1326 | return err; | ||
1120 | 1327 | ||
1121 | if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) | 1328 | if (!key.p.key) |
1122 | return -EINVAL; | 1329 | return -EINVAL; |
1123 | 1330 | ||
1124 | if (info->attrs[NL80211_ATTR_KEY_DATA]) { | ||
1125 | params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); | ||
1126 | params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); | ||
1127 | } | ||
1128 | |||
1129 | if (info->attrs[NL80211_ATTR_KEY_SEQ]) { | ||
1130 | params.seq = nla_data(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1131 | params.seq_len = nla_len(info->attrs[NL80211_ATTR_KEY_SEQ]); | ||
1132 | } | ||
1133 | |||
1134 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | ||
1135 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | ||
1136 | |||
1137 | params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); | ||
1138 | |||
1139 | if (info->attrs[NL80211_ATTR_MAC]) | 1331 | if (info->attrs[NL80211_ATTR_MAC]) |
1140 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1332 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1141 | 1333 | ||
1142 | if (cfg80211_validate_key_settings(¶ms, key_idx, mac_addr)) | ||
1143 | return -EINVAL; | ||
1144 | |||
1145 | rtnl_lock(); | 1334 | rtnl_lock(); |
1146 | 1335 | ||
1147 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 1336 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); |
1148 | if (err) | 1337 | if (err) |
1149 | goto unlock_rtnl; | 1338 | goto unlock_rtnl; |
1150 | 1339 | ||
1151 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) | 1340 | if (!rdev->ops->add_key) { |
1152 | if (params.cipher == rdev->wiphy.cipher_suites[i]) | 1341 | err = -EOPNOTSUPP; |
1153 | break; | ||
1154 | if (i == rdev->wiphy.n_cipher_suites) { | ||
1155 | err = -EINVAL; | ||
1156 | goto out; | 1342 | goto out; |
1157 | } | 1343 | } |
1158 | 1344 | ||
1159 | if (!rdev->ops->add_key) { | 1345 | if (cfg80211_validate_key_settings(rdev, &key.p, key.idx, mac_addr)) { |
1160 | err = -EOPNOTSUPP; | 1346 | err = -EINVAL; |
1161 | goto out; | 1347 | goto out; |
1162 | } | 1348 | } |
1163 | 1349 | ||
1164 | err = rdev->ops->add_key(&rdev->wiphy, dev, key_idx, mac_addr, ¶ms); | 1350 | wdev_lock(dev->ieee80211_ptr); |
1351 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1352 | if (!err) | ||
1353 | err = rdev->ops->add_key(&rdev->wiphy, dev, key.idx, | ||
1354 | mac_addr, &key.p); | ||
1355 | wdev_unlock(dev->ieee80211_ptr); | ||
1165 | 1356 | ||
1166 | out: | 1357 | out: |
1167 | cfg80211_unlock_rdev(rdev); | 1358 | cfg80211_unlock_rdev(rdev); |
@@ -1177,14 +1368,12 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1177 | struct cfg80211_registered_device *rdev; | 1368 | struct cfg80211_registered_device *rdev; |
1178 | int err; | 1369 | int err; |
1179 | struct net_device *dev; | 1370 | struct net_device *dev; |
1180 | u8 key_idx = 0; | ||
1181 | u8 *mac_addr = NULL; | 1371 | u8 *mac_addr = NULL; |
1372 | struct key_parse key; | ||
1182 | 1373 | ||
1183 | if (info->attrs[NL80211_ATTR_KEY_IDX]) | 1374 | err = nl80211_parse_key(info, &key); |
1184 | key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); | 1375 | if (err) |
1185 | 1376 | return err; | |
1186 | if (key_idx > 5) | ||
1187 | return -EINVAL; | ||
1188 | 1377 | ||
1189 | if (info->attrs[NL80211_ATTR_MAC]) | 1378 | if (info->attrs[NL80211_ATTR_MAC]) |
1190 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1379 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
@@ -1200,16 +1389,20 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1200 | goto out; | 1389 | goto out; |
1201 | } | 1390 | } |
1202 | 1391 | ||
1203 | err = rdev->ops->del_key(&rdev->wiphy, dev, key_idx, mac_addr); | 1392 | wdev_lock(dev->ieee80211_ptr); |
1393 | err = nl80211_key_allowed(dev->ieee80211_ptr); | ||
1394 | if (!err) | ||
1395 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); | ||
1204 | 1396 | ||
1205 | #ifdef CONFIG_WIRELESS_EXT | 1397 | #ifdef CONFIG_WIRELESS_EXT |
1206 | if (!err) { | 1398 | if (!err) { |
1207 | if (key_idx == dev->ieee80211_ptr->wext.default_key) | 1399 | if (key.idx == dev->ieee80211_ptr->wext.default_key) |
1208 | dev->ieee80211_ptr->wext.default_key = -1; | 1400 | dev->ieee80211_ptr->wext.default_key = -1; |
1209 | else if (key_idx == dev->ieee80211_ptr->wext.default_mgmt_key) | 1401 | else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key) |
1210 | dev->ieee80211_ptr->wext.default_mgmt_key = -1; | 1402 | dev->ieee80211_ptr->wext.default_mgmt_key = -1; |
1211 | } | 1403 | } |
1212 | #endif | 1404 | #endif |
1405 | wdev_unlock(dev->ieee80211_ptr); | ||
1213 | 1406 | ||
1214 | out: | 1407 | out: |
1215 | cfg80211_unlock_rdev(rdev); | 1408 | cfg80211_unlock_rdev(rdev); |
@@ -2901,11 +3094,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2901 | 3094 | ||
2902 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 3095 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
2903 | struct cfg80211_registered_device *rdev, | 3096 | struct cfg80211_registered_device *rdev, |
2904 | struct net_device *dev, | 3097 | struct wireless_dev *wdev, |
2905 | struct cfg80211_bss *res) | 3098 | struct cfg80211_internal_bss *intbss) |
2906 | { | 3099 | { |
3100 | struct cfg80211_bss *res = &intbss->pub; | ||
2907 | void *hdr; | 3101 | void *hdr; |
2908 | struct nlattr *bss; | 3102 | struct nlattr *bss; |
3103 | int i; | ||
3104 | |||
3105 | ASSERT_WDEV_LOCK(wdev); | ||
2909 | 3106 | ||
2910 | hdr = nl80211hdr_put(msg, pid, seq, flags, | 3107 | hdr = nl80211hdr_put(msg, pid, seq, flags, |
2911 | NL80211_CMD_NEW_SCAN_RESULTS); | 3108 | NL80211_CMD_NEW_SCAN_RESULTS); |
@@ -2914,7 +3111,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
2914 | 3111 | ||
2915 | NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, | 3112 | NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, |
2916 | rdev->bss_generation); | 3113 | rdev->bss_generation); |
2917 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 3114 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); |
2918 | 3115 | ||
2919 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); | 3116 | bss = nla_nest_start(msg, NL80211_ATTR_BSS); |
2920 | if (!bss) | 3117 | if (!bss) |
@@ -2943,6 +3140,28 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
2943 | break; | 3140 | break; |
2944 | } | 3141 | } |
2945 | 3142 | ||
3143 | switch (wdev->iftype) { | ||
3144 | case NL80211_IFTYPE_STATION: | ||
3145 | if (intbss == wdev->current_bss) | ||
3146 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3147 | NL80211_BSS_STATUS_ASSOCIATED); | ||
3148 | else for (i = 0; i < MAX_AUTH_BSSES; i++) { | ||
3149 | if (intbss != wdev->auth_bsses[i]) | ||
3150 | continue; | ||
3151 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3152 | NL80211_BSS_STATUS_AUTHENTICATED); | ||
3153 | break; | ||
3154 | } | ||
3155 | break; | ||
3156 | case NL80211_IFTYPE_ADHOC: | ||
3157 | if (intbss == wdev->current_bss) | ||
3158 | NLA_PUT_U32(msg, NL80211_BSS_STATUS, | ||
3159 | NL80211_BSS_STATUS_IBSS_JOINED); | ||
3160 | break; | ||
3161 | default: | ||
3162 | break; | ||
3163 | } | ||
3164 | |||
2946 | nla_nest_end(msg, bss); | 3165 | nla_nest_end(msg, bss); |
2947 | 3166 | ||
2948 | return genlmsg_end(msg, hdr); | 3167 | return genlmsg_end(msg, hdr); |
@@ -2955,9 +3174,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
2955 | static int nl80211_dump_scan(struct sk_buff *skb, | 3174 | static int nl80211_dump_scan(struct sk_buff *skb, |
2956 | struct netlink_callback *cb) | 3175 | struct netlink_callback *cb) |
2957 | { | 3176 | { |
2958 | struct cfg80211_registered_device *dev; | 3177 | struct cfg80211_registered_device *rdev; |
2959 | struct net_device *netdev; | 3178 | struct net_device *dev; |
2960 | struct cfg80211_internal_bss *scan; | 3179 | struct cfg80211_internal_bss *scan; |
3180 | struct wireless_dev *wdev; | ||
2961 | int ifidx = cb->args[0]; | 3181 | int ifidx = cb->args[0]; |
2962 | int start = cb->args[1], idx = 0; | 3182 | int start = cb->args[1], idx = 0; |
2963 | int err; | 3183 | int err; |
@@ -2978,39 +3198,43 @@ static int nl80211_dump_scan(struct sk_buff *skb, | |||
2978 | cb->args[0] = ifidx; | 3198 | cb->args[0] = ifidx; |
2979 | } | 3199 | } |
2980 | 3200 | ||
2981 | netdev = dev_get_by_index(&init_net, ifidx); | 3201 | dev = dev_get_by_index(&init_net, ifidx); |
2982 | if (!netdev) | 3202 | if (!dev) |
2983 | return -ENODEV; | 3203 | return -ENODEV; |
2984 | 3204 | ||
2985 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 3205 | rdev = cfg80211_get_dev_from_ifindex(ifidx); |
2986 | if (IS_ERR(dev)) { | 3206 | if (IS_ERR(rdev)) { |
2987 | err = PTR_ERR(dev); | 3207 | err = PTR_ERR(rdev); |
2988 | goto out_put_netdev; | 3208 | goto out_put_netdev; |
2989 | } | 3209 | } |
2990 | 3210 | ||
2991 | spin_lock_bh(&dev->bss_lock); | 3211 | wdev = dev->ieee80211_ptr; |
2992 | cfg80211_bss_expire(dev); | 3212 | |
3213 | wdev_lock(wdev); | ||
3214 | spin_lock_bh(&rdev->bss_lock); | ||
3215 | cfg80211_bss_expire(rdev); | ||
2993 | 3216 | ||
2994 | list_for_each_entry(scan, &dev->bss_list, list) { | 3217 | list_for_each_entry(scan, &rdev->bss_list, list) { |
2995 | if (++idx <= start) | 3218 | if (++idx <= start) |
2996 | continue; | 3219 | continue; |
2997 | if (nl80211_send_bss(skb, | 3220 | if (nl80211_send_bss(skb, |
2998 | NETLINK_CB(cb->skb).pid, | 3221 | NETLINK_CB(cb->skb).pid, |
2999 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3222 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
3000 | dev, netdev, &scan->pub) < 0) { | 3223 | rdev, wdev, scan) < 0) { |
3001 | idx--; | 3224 | idx--; |
3002 | goto out; | 3225 | goto out; |
3003 | } | 3226 | } |
3004 | } | 3227 | } |
3005 | 3228 | ||
3006 | out: | 3229 | out: |
3007 | spin_unlock_bh(&dev->bss_lock); | 3230 | spin_unlock_bh(&rdev->bss_lock); |
3231 | wdev_unlock(wdev); | ||
3008 | 3232 | ||
3009 | cb->args[1] = idx; | 3233 | cb->args[1] = idx; |
3010 | err = skb->len; | 3234 | err = skb->len; |
3011 | cfg80211_unlock_rdev(dev); | 3235 | cfg80211_unlock_rdev(rdev); |
3012 | out_put_netdev: | 3236 | out_put_netdev: |
3013 | dev_put(netdev); | 3237 | dev_put(dev); |
3014 | 3238 | ||
3015 | return err; | 3239 | return err; |
3016 | } | 3240 | } |
@@ -3050,6 +3274,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3050 | const u8 *bssid, *ssid, *ie = NULL; | 3274 | const u8 *bssid, *ssid, *ie = NULL; |
3051 | int err, ssid_len, ie_len = 0; | 3275 | int err, ssid_len, ie_len = 0; |
3052 | enum nl80211_auth_type auth_type; | 3276 | enum nl80211_auth_type auth_type; |
3277 | struct key_parse key; | ||
3053 | 3278 | ||
3054 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3279 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3055 | return -EINVAL; | 3280 | return -EINVAL; |
@@ -3066,6 +3291,25 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3066 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 3291 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
3067 | return -EINVAL; | 3292 | return -EINVAL; |
3068 | 3293 | ||
3294 | err = nl80211_parse_key(info, &key); | ||
3295 | if (err) | ||
3296 | return err; | ||
3297 | |||
3298 | if (key.idx >= 0) { | ||
3299 | if (!key.p.key || !key.p.key_len) | ||
3300 | return -EINVAL; | ||
3301 | if ((key.p.cipher != WLAN_CIPHER_SUITE_WEP40 || | ||
3302 | key.p.key_len != WLAN_KEY_LEN_WEP40) && | ||
3303 | (key.p.cipher != WLAN_CIPHER_SUITE_WEP104 || | ||
3304 | key.p.key_len != WLAN_KEY_LEN_WEP104)) | ||
3305 | return -EINVAL; | ||
3306 | if (key.idx > 4) | ||
3307 | return -EINVAL; | ||
3308 | } else { | ||
3309 | key.p.key_len = 0; | ||
3310 | key.p.key = NULL; | ||
3311 | } | ||
3312 | |||
3069 | rtnl_lock(); | 3313 | rtnl_lock(); |
3070 | 3314 | ||
3071 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); | 3315 | err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev); |
@@ -3110,7 +3354,8 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3110 | } | 3354 | } |
3111 | 3355 | ||
3112 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 3356 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
3113 | ssid, ssid_len, ie, ie_len); | 3357 | ssid, ssid_len, ie, ie_len, |
3358 | key.p.key, key.p.key_len, key.idx); | ||
3114 | 3359 | ||
3115 | out: | 3360 | out: |
3116 | cfg80211_unlock_rdev(rdev); | 3361 | cfg80211_unlock_rdev(rdev); |
@@ -3397,6 +3642,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
3397 | struct net_device *dev; | 3642 | struct net_device *dev; |
3398 | struct cfg80211_ibss_params ibss; | 3643 | struct cfg80211_ibss_params ibss; |
3399 | struct wiphy *wiphy; | 3644 | struct wiphy *wiphy; |
3645 | struct cfg80211_cached_keys *connkeys = NULL; | ||
3400 | int err; | 3646 | int err; |
3401 | 3647 | ||
3402 | memset(&ibss, 0, sizeof(ibss)); | 3648 | memset(&ibss, 0, sizeof(ibss)); |
@@ -3461,13 +3707,26 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
3461 | } | 3707 | } |
3462 | 3708 | ||
3463 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; | 3709 | ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; |
3710 | ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; | ||
3711 | |||
3712 | if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) { | ||
3713 | connkeys = nl80211_parse_connkeys(rdev, | ||
3714 | info->attrs[NL80211_ATTR_KEYS]); | ||
3715 | if (IS_ERR(connkeys)) { | ||
3716 | err = PTR_ERR(connkeys); | ||
3717 | connkeys = NULL; | ||
3718 | goto out; | ||
3719 | } | ||
3720 | } | ||
3464 | 3721 | ||
3465 | err = cfg80211_join_ibss(rdev, dev, &ibss); | 3722 | err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); |
3466 | 3723 | ||
3467 | out: | 3724 | out: |
3468 | cfg80211_unlock_rdev(rdev); | 3725 | cfg80211_unlock_rdev(rdev); |
3469 | dev_put(dev); | 3726 | dev_put(dev); |
3470 | unlock_rtnl: | 3727 | unlock_rtnl: |
3728 | if (err) | ||
3729 | kfree(connkeys); | ||
3471 | rtnl_unlock(); | 3730 | rtnl_unlock(); |
3472 | return err; | 3731 | return err; |
3473 | } | 3732 | } |
@@ -3637,6 +3896,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
3637 | struct net_device *dev; | 3896 | struct net_device *dev; |
3638 | struct cfg80211_connect_params connect; | 3897 | struct cfg80211_connect_params connect; |
3639 | struct wiphy *wiphy; | 3898 | struct wiphy *wiphy; |
3899 | struct cfg80211_cached_keys *connkeys = NULL; | ||
3640 | int err; | 3900 | int err; |
3641 | 3901 | ||
3642 | memset(&connect, 0, sizeof(connect)); | 3902 | memset(&connect, 0, sizeof(connect)); |
@@ -3680,10 +3940,6 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
3680 | 3940 | ||
3681 | wiphy = &rdev->wiphy; | 3941 | wiphy = &rdev->wiphy; |
3682 | 3942 | ||
3683 | connect.bssid = NULL; | ||
3684 | connect.channel = NULL; | ||
3685 | connect.auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
3686 | |||
3687 | if (info->attrs[NL80211_ATTR_MAC]) | 3943 | if (info->attrs[NL80211_ATTR_MAC]) |
3688 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 3944 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
3689 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 3945 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
@@ -3705,12 +3961,24 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
3705 | } | 3961 | } |
3706 | } | 3962 | } |
3707 | 3963 | ||
3708 | err = cfg80211_connect(rdev, dev, &connect); | 3964 | if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) { |
3965 | connkeys = nl80211_parse_connkeys(rdev, | ||
3966 | info->attrs[NL80211_ATTR_KEYS]); | ||
3967 | if (IS_ERR(connkeys)) { | ||
3968 | err = PTR_ERR(connkeys); | ||
3969 | connkeys = NULL; | ||
3970 | goto out; | ||
3971 | } | ||
3972 | } | ||
3973 | |||
3974 | err = cfg80211_connect(rdev, dev, &connect, connkeys); | ||
3709 | 3975 | ||
3710 | out: | 3976 | out: |
3711 | cfg80211_unlock_rdev(rdev); | 3977 | cfg80211_unlock_rdev(rdev); |
3712 | dev_put(dev); | 3978 | dev_put(dev); |
3713 | unlock_rtnl: | 3979 | unlock_rtnl: |
3980 | if (err) | ||
3981 | kfree(connkeys); | ||
3714 | rtnl_unlock(); | 3982 | rtnl_unlock(); |
3715 | return err; | 3983 | return err; |
3716 | } | 3984 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2b4a6c66f5ae..fb40428a5946 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -113,11 +113,7 @@ static const struct ieee80211_regdomain world_regdom = { | |||
113 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | 113 | static const struct ieee80211_regdomain *cfg80211_world_regdom = |
114 | &world_regdom; | 114 | &world_regdom; |
115 | 115 | ||
116 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
117 | static char *ieee80211_regdom = "US"; | ||
118 | #else | ||
119 | static char *ieee80211_regdom = "00"; | 116 | static char *ieee80211_regdom = "00"; |
120 | #endif | ||
121 | 117 | ||
122 | module_param(ieee80211_regdom, charp, 0444); | 118 | module_param(ieee80211_regdom, charp, 0444); |
123 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 119 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
@@ -2287,22 +2283,12 @@ int regulatory_init(void) | |||
2287 | 2283 | ||
2288 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | 2284 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); |
2289 | print_regdomain_info(cfg80211_regdomain); | 2285 | print_regdomain_info(cfg80211_regdomain); |
2290 | /* | ||
2291 | * The old code still requests for a new regdomain and if | ||
2292 | * you have CRDA you get it updated, otherwise you get | ||
2293 | * stuck with the static values. Since "EU" is not a valid | ||
2294 | * ISO / IEC 3166 alpha2 code we can't expect userpace to | ||
2295 | * give us a regulatory domain for it. We need last_request | ||
2296 | * iniitalized though so lets just send a request which we | ||
2297 | * know will be ignored... this crap will be removed once | ||
2298 | * OLD_REG dies. | ||
2299 | */ | ||
2300 | err = regulatory_hint_core(ieee80211_regdom); | ||
2301 | #else | 2286 | #else |
2302 | cfg80211_regdomain = cfg80211_world_regdom; | 2287 | cfg80211_regdomain = cfg80211_world_regdom; |
2303 | 2288 | ||
2304 | err = regulatory_hint_core(ieee80211_regdom); | ||
2305 | #endif | 2289 | #endif |
2290 | /* We always try to get an update for the static regdomain */ | ||
2291 | err = regulatory_hint_core(cfg80211_regdomain->alpha2); | ||
2306 | if (err) { | 2292 | if (err) { |
2307 | if (err == -ENOMEM) | 2293 | if (err == -ENOMEM) |
2308 | return err; | 2294 | return err; |
@@ -2321,6 +2307,13 @@ int regulatory_init(void) | |||
2321 | #endif | 2307 | #endif |
2322 | } | 2308 | } |
2323 | 2309 | ||
2310 | /* | ||
2311 | * Finally, if the user set the module parameter treat it | ||
2312 | * as a user hint. | ||
2313 | */ | ||
2314 | if (!is_world_regdom(ieee80211_regdom)) | ||
2315 | regulatory_hint_user(ieee80211_regdom); | ||
2316 | |||
2324 | return 0; | 2317 | return 0; |
2325 | } | 2318 | } |
2326 | 2319 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index df9173f73604..82de2d9795f4 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -125,7 +125,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
125 | params->channel, params->auth_type, | 125 | params->channel, params->auth_type, |
126 | params->bssid, | 126 | params->bssid, |
127 | params->ssid, params->ssid_len, | 127 | params->ssid, params->ssid_len, |
128 | NULL, 0); | 128 | NULL, 0, |
129 | params->key, params->key_len, | ||
130 | params->key_idx); | ||
129 | case CFG80211_CONN_ASSOCIATE_NEXT: | 131 | case CFG80211_CONN_ASSOCIATE_NEXT: |
130 | BUG_ON(!rdev->ops->assoc); | 132 | BUG_ON(!rdev->ops->assoc); |
131 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 133 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -225,7 +227,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) | |||
225 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | 227 | if (wdev->sme_state != CFG80211_SME_CONNECTING) |
226 | return; | 228 | return; |
227 | 229 | ||
228 | if (WARN_ON(!wdev->conn)) | 230 | if (!wdev->conn) |
229 | return; | 231 | return; |
230 | 232 | ||
231 | if (wdev->conn->state != CFG80211_CONN_SCANNING && | 233 | if (wdev->conn->state != CFG80211_CONN_SCANNING && |
@@ -279,8 +281,12 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
279 | /* select automatically between only open, shared, leap */ | 281 | /* select automatically between only open, shared, leap */ |
280 | switch (wdev->conn->params.auth_type) { | 282 | switch (wdev->conn->params.auth_type) { |
281 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 283 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
282 | wdev->conn->params.auth_type = | 284 | if (wdev->connect_keys) |
283 | NL80211_AUTHTYPE_SHARED_KEY; | 285 | wdev->conn->params.auth_type = |
286 | NL80211_AUTHTYPE_SHARED_KEY; | ||
287 | else | ||
288 | wdev->conn->params.auth_type = | ||
289 | NL80211_AUTHTYPE_NETWORK_EAP; | ||
284 | break; | 290 | break; |
285 | case NL80211_AUTHTYPE_SHARED_KEY: | 291 | case NL80211_AUTHTYPE_SHARED_KEY: |
286 | wdev->conn->params.auth_type = | 292 | wdev->conn->params.auth_type = |
@@ -295,9 +301,8 @@ void cfg80211_sme_rx_auth(struct net_device *dev, | |||
295 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; | 301 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; |
296 | schedule_work(&rdev->conn_work); | 302 | schedule_work(&rdev->conn_work); |
297 | } else if (status_code != WLAN_STATUS_SUCCESS) { | 303 | } else if (status_code != WLAN_STATUS_SUCCESS) { |
298 | wdev->sme_state = CFG80211_SME_IDLE; | 304 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
299 | kfree(wdev->conn); | 305 | status_code, false); |
300 | wdev->conn = NULL; | ||
301 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && | 306 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING && |
302 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { | 307 | wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { |
303 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; | 308 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; |
@@ -336,7 +341,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
336 | if (req_ie && status == WLAN_STATUS_SUCCESS) { | 341 | if (req_ie && status == WLAN_STATUS_SUCCESS) { |
337 | memset(&wrqu, 0, sizeof(wrqu)); | 342 | memset(&wrqu, 0, sizeof(wrqu)); |
338 | wrqu.data.length = req_ie_len; | 343 | wrqu.data.length = req_ie_len; |
339 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie); | 344 | wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie); |
340 | } | 345 | } |
341 | 346 | ||
342 | if (resp_ie && status == WLAN_STATUS_SUCCESS) { | 347 | if (resp_ie && status == WLAN_STATUS_SUCCESS) { |
@@ -354,10 +359,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
354 | #endif | 359 | #endif |
355 | 360 | ||
356 | if (status == WLAN_STATUS_SUCCESS && | 361 | if (status == WLAN_STATUS_SUCCESS && |
357 | wdev->sme_state == CFG80211_SME_IDLE) { | 362 | wdev->sme_state == CFG80211_SME_IDLE) |
358 | wdev->sme_state = CFG80211_SME_CONNECTED; | 363 | goto success; |
359 | return; | ||
360 | } | ||
361 | 364 | ||
362 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | 365 | if (wdev->sme_state != CFG80211_SME_CONNECTING) |
363 | return; | 366 | return; |
@@ -371,24 +374,29 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
371 | if (wdev->conn) | 374 | if (wdev->conn) |
372 | wdev->conn->state = CFG80211_CONN_IDLE; | 375 | wdev->conn->state = CFG80211_CONN_IDLE; |
373 | 376 | ||
374 | if (status == WLAN_STATUS_SUCCESS) { | 377 | if (status != WLAN_STATUS_SUCCESS) { |
375 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | ||
376 | wdev->ssid, wdev->ssid_len, | ||
377 | WLAN_CAPABILITY_ESS, | ||
378 | WLAN_CAPABILITY_ESS); | ||
379 | |||
380 | if (WARN_ON(!bss)) | ||
381 | return; | ||
382 | |||
383 | cfg80211_hold_bss(bss_from_pub(bss)); | ||
384 | wdev->current_bss = bss_from_pub(bss); | ||
385 | |||
386 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
387 | } else { | ||
388 | wdev->sme_state = CFG80211_SME_IDLE; | 378 | wdev->sme_state = CFG80211_SME_IDLE; |
389 | kfree(wdev->conn); | 379 | kfree(wdev->conn); |
390 | wdev->conn = NULL; | 380 | wdev->conn = NULL; |
381 | kfree(wdev->connect_keys); | ||
382 | wdev->connect_keys = NULL; | ||
383 | return; | ||
391 | } | 384 | } |
385 | |||
386 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | ||
387 | wdev->ssid, wdev->ssid_len, | ||
388 | WLAN_CAPABILITY_ESS, | ||
389 | WLAN_CAPABILITY_ESS); | ||
390 | |||
391 | if (WARN_ON(!bss)) | ||
392 | return; | ||
393 | |||
394 | cfg80211_hold_bss(bss_from_pub(bss)); | ||
395 | wdev->current_bss = bss_from_pub(bss); | ||
396 | |||
397 | success: | ||
398 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
399 | cfg80211_upload_connect_keys(wdev); | ||
392 | } | 400 | } |
393 | 401 | ||
394 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 402 | void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
@@ -466,7 +474,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | |||
466 | if (req_ie) { | 474 | if (req_ie) { |
467 | memset(&wrqu, 0, sizeof(wrqu)); | 475 | memset(&wrqu, 0, sizeof(wrqu)); |
468 | wrqu.data.length = req_ie_len; | 476 | wrqu.data.length = req_ie_len; |
469 | wireless_send_event(wdev->netdev, IWEVASSOCRESPIE, | 477 | wireless_send_event(wdev->netdev, IWEVASSOCREQIE, |
470 | &wrqu, req_ie); | 478 | &wrqu, req_ie); |
471 | } | 479 | } |
472 | 480 | ||
@@ -517,6 +525,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
517 | size_t ie_len, u16 reason, bool from_ap) | 525 | size_t ie_len, u16 reason, bool from_ap) |
518 | { | 526 | { |
519 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 527 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
528 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
529 | int i; | ||
520 | #ifdef CONFIG_WIRELESS_EXT | 530 | #ifdef CONFIG_WIRELESS_EXT |
521 | union iwreq_data wrqu; | 531 | union iwreq_data wrqu; |
522 | #endif | 532 | #endif |
@@ -544,8 +554,15 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
544 | wdev->conn = NULL; | 554 | wdev->conn = NULL; |
545 | } | 555 | } |
546 | 556 | ||
547 | nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev, | 557 | nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); |
548 | reason, ie, ie_len, from_ap); | 558 | |
559 | /* | ||
560 | * Delete all the keys ... pairwise keys can't really | ||
561 | * exist any more anyway, but default keys might. | ||
562 | */ | ||
563 | if (rdev->ops->del_key) | ||
564 | for (i = 0; i < 6; i++) | ||
565 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); | ||
549 | 566 | ||
550 | #ifdef CONFIG_WIRELESS_EXT | 567 | #ifdef CONFIG_WIRELESS_EXT |
551 | memset(&wrqu, 0, sizeof(wrqu)); | 568 | memset(&wrqu, 0, sizeof(wrqu)); |
@@ -581,7 +598,8 @@ EXPORT_SYMBOL(cfg80211_disconnected); | |||
581 | 598 | ||
582 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 599 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
583 | struct net_device *dev, | 600 | struct net_device *dev, |
584 | struct cfg80211_connect_params *connect) | 601 | struct cfg80211_connect_params *connect, |
602 | struct cfg80211_cached_keys *connkeys) | ||
585 | { | 603 | { |
586 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 604 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
587 | int err; | 605 | int err; |
@@ -591,6 +609,24 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
591 | if (wdev->sme_state != CFG80211_SME_IDLE) | 609 | if (wdev->sme_state != CFG80211_SME_IDLE) |
592 | return -EALREADY; | 610 | return -EALREADY; |
593 | 611 | ||
612 | if (WARN_ON(wdev->connect_keys)) { | ||
613 | kfree(wdev->connect_keys); | ||
614 | wdev->connect_keys = NULL; | ||
615 | } | ||
616 | |||
617 | if (connkeys && connkeys->def >= 0) { | ||
618 | int idx; | ||
619 | |||
620 | idx = connkeys->def; | ||
621 | /* If given a WEP key we may need it for shared key auth */ | ||
622 | if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
623 | connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) { | ||
624 | connect->key_idx = idx; | ||
625 | connect->key = connkeys->params[idx].key; | ||
626 | connect->key_len = connkeys->params[idx].key_len; | ||
627 | } | ||
628 | } | ||
629 | |||
594 | if (!rdev->ops->connect) { | 630 | if (!rdev->ops->connect) { |
595 | if (!rdev->ops->auth || !rdev->ops->assoc) | 631 | if (!rdev->ops->auth || !rdev->ops->assoc) |
596 | return -EOPNOTSUPP; | 632 | return -EOPNOTSUPP; |
@@ -641,6 +677,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
641 | cfg80211_get_conn_bss(wdev); | 677 | cfg80211_get_conn_bss(wdev); |
642 | 678 | ||
643 | wdev->sme_state = CFG80211_SME_CONNECTING; | 679 | wdev->sme_state = CFG80211_SME_CONNECTING; |
680 | wdev->connect_keys = connkeys; | ||
644 | 681 | ||
645 | /* we're good if we have both BSSID and channel */ | 682 | /* we're good if we have both BSSID and channel */ |
646 | if (wdev->conn->params.bssid && wdev->conn->params.channel) { | 683 | if (wdev->conn->params.bssid && wdev->conn->params.channel) { |
@@ -663,13 +700,16 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
663 | kfree(wdev->conn); | 700 | kfree(wdev->conn); |
664 | wdev->conn = NULL; | 701 | wdev->conn = NULL; |
665 | wdev->sme_state = CFG80211_SME_IDLE; | 702 | wdev->sme_state = CFG80211_SME_IDLE; |
703 | wdev->connect_keys = NULL; | ||
666 | } | 704 | } |
667 | 705 | ||
668 | return err; | 706 | return err; |
669 | } else { | 707 | } else { |
670 | wdev->sme_state = CFG80211_SME_CONNECTING; | 708 | wdev->sme_state = CFG80211_SME_CONNECTING; |
709 | wdev->connect_keys = connkeys; | ||
671 | err = rdev->ops->connect(&rdev->wiphy, dev, connect); | 710 | err = rdev->ops->connect(&rdev->wiphy, dev, connect); |
672 | if (err) { | 711 | if (err) { |
712 | wdev->connect_keys = NULL; | ||
673 | wdev->sme_state = CFG80211_SME_IDLE; | 713 | wdev->sme_state = CFG80211_SME_IDLE; |
674 | return err; | 714 | return err; |
675 | } | 715 | } |
@@ -683,12 +723,13 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
683 | 723 | ||
684 | int cfg80211_connect(struct cfg80211_registered_device *rdev, | 724 | int cfg80211_connect(struct cfg80211_registered_device *rdev, |
685 | struct net_device *dev, | 725 | struct net_device *dev, |
686 | struct cfg80211_connect_params *connect) | 726 | struct cfg80211_connect_params *connect, |
727 | struct cfg80211_cached_keys *connkeys) | ||
687 | { | 728 | { |
688 | int err; | 729 | int err; |
689 | 730 | ||
690 | wdev_lock(dev->ieee80211_ptr); | 731 | wdev_lock(dev->ieee80211_ptr); |
691 | err = __cfg80211_connect(rdev, dev, connect); | 732 | err = __cfg80211_connect(rdev, dev, connect, connkeys); |
692 | wdev_unlock(dev->ieee80211_ptr); | 733 | wdev_unlock(dev->ieee80211_ptr); |
693 | 734 | ||
694 | return err; | 735 | return err; |
@@ -705,6 +746,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
705 | if (wdev->sme_state == CFG80211_SME_IDLE) | 746 | if (wdev->sme_state == CFG80211_SME_IDLE) |
706 | return -EINVAL; | 747 | return -EINVAL; |
707 | 748 | ||
749 | kfree(wdev->connect_keys); | ||
750 | wdev->connect_keys = NULL; | ||
751 | |||
708 | if (!rdev->ops->disconnect) { | 752 | if (!rdev->ops->disconnect) { |
709 | if (!rdev->ops->deauth) | 753 | if (!rdev->ops->deauth) |
710 | return -EOPNOTSUPP; | 754 | return -EOPNOTSUPP; |
@@ -782,8 +826,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) | |||
782 | return; | 826 | return; |
783 | 827 | ||
784 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); | 828 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); |
785 | if (cfg80211_mlme_deauth(rdev, dev, bssid, | 829 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, |
786 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { | 830 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { |
787 | /* whatever -- assume gone anyway */ | 831 | /* whatever -- assume gone anyway */ |
788 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); | 832 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); |
789 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); | 833 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 28f8f96801d4..ba387d85dcfd 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -141,9 +141,12 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) | |||
141 | set_mandatory_flags_band(wiphy->bands[band], band); | 141 | set_mandatory_flags_band(wiphy->bands[band], band); |
142 | } | 142 | } |
143 | 143 | ||
144 | int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | 144 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, |
145 | struct key_params *params, int key_idx, | ||
145 | const u8 *mac_addr) | 146 | const u8 *mac_addr) |
146 | { | 147 | { |
148 | int i; | ||
149 | |||
147 | if (key_idx > 5) | 150 | if (key_idx > 5) |
148 | return -EINVAL; | 151 | return -EINVAL; |
149 | 152 | ||
@@ -197,6 +200,12 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx, | |||
197 | } | 200 | } |
198 | } | 201 | } |
199 | 202 | ||
203 | for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) | ||
204 | if (params->cipher == rdev->wiphy.cipher_suites[i]) | ||
205 | break; | ||
206 | if (i == rdev->wiphy.n_cipher_suites) | ||
207 | return -EINVAL; | ||
208 | |||
200 | return 0; | 209 | return 0; |
201 | } | 210 | } |
202 | 211 | ||
@@ -523,3 +532,37 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) | |||
523 | return NULL; | 532 | return NULL; |
524 | } | 533 | } |
525 | EXPORT_SYMBOL(ieee80211_bss_get_ie); | 534 | EXPORT_SYMBOL(ieee80211_bss_get_ie); |
535 | |||
536 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | ||
537 | { | ||
538 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
539 | struct net_device *dev = wdev->netdev; | ||
540 | int i; | ||
541 | |||
542 | if (!wdev->connect_keys) | ||
543 | return; | ||
544 | |||
545 | for (i = 0; i < 6; i++) { | ||
546 | if (!wdev->connect_keys->params[i].cipher) | ||
547 | continue; | ||
548 | if (rdev->ops->add_key(wdev->wiphy, dev, i, NULL, | ||
549 | &wdev->connect_keys->params[i])) { | ||
550 | printk(KERN_ERR "%s: failed to set key %d\n", | ||
551 | dev->name, i); | ||
552 | continue; | ||
553 | } | ||
554 | if (wdev->connect_keys->def == i) | ||
555 | if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) { | ||
556 | printk(KERN_ERR "%s: failed to set defkey %d\n", | ||
557 | dev->name, i); | ||
558 | continue; | ||
559 | } | ||
560 | if (wdev->connect_keys->defmgmt == i) | ||
561 | if (rdev->ops->set_default_mgmt_key(wdev->wiphy, dev, i)) | ||
562 | printk(KERN_ERR "%s: failed to set mgtdef %d\n", | ||
563 | dev->name, i); | ||
564 | } | ||
565 | |||
566 | kfree(wdev->connect_keys); | ||
567 | wdev->connect_keys = NULL; | ||
568 | } | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 9d101d566bb1..c7351a98e660 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -453,15 +453,32 @@ int cfg80211_wext_giwretry(struct net_device *dev, | |||
453 | } | 453 | } |
454 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); | 454 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwretry); |
455 | 455 | ||
456 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | 456 | static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, |
457 | struct net_device *dev, const u8 *addr, | 457 | struct net_device *dev, const u8 *addr, |
458 | bool remove, bool tx_key, int idx, | 458 | bool remove, bool tx_key, int idx, |
459 | struct key_params *params) | 459 | struct key_params *params) |
460 | { | 460 | { |
461 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 461 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
462 | int err; | 462 | int err, i; |
463 | |||
464 | if (!wdev->wext.keys) { | ||
465 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), | ||
466 | GFP_KERNEL); | ||
467 | if (!wdev->wext.keys) | ||
468 | return -ENOMEM; | ||
469 | for (i = 0; i < 6; i++) | ||
470 | wdev->wext.keys->params[i].key = | ||
471 | wdev->wext.keys->data[i]; | ||
472 | } | ||
473 | |||
474 | if (wdev->iftype != NL80211_IFTYPE_ADHOC && | ||
475 | wdev->iftype != NL80211_IFTYPE_STATION) | ||
476 | return -EOPNOTSUPP; | ||
463 | 477 | ||
464 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { | 478 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { |
479 | if (!wdev->current_bss) | ||
480 | return -ENOLINK; | ||
481 | |||
465 | if (!rdev->ops->set_default_mgmt_key) | 482 | if (!rdev->ops->set_default_mgmt_key) |
466 | return -EOPNOTSUPP; | 483 | return -EOPNOTSUPP; |
467 | 484 | ||
@@ -471,8 +488,14 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
471 | return -EINVAL; | 488 | return -EINVAL; |
472 | 489 | ||
473 | if (remove) { | 490 | if (remove) { |
474 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | 491 | err = 0; |
492 | if (wdev->current_bss) | ||
493 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | ||
475 | if (!err) { | 494 | if (!err) { |
495 | if (!addr) { | ||
496 | wdev->wext.keys->params[idx].key_len = 0; | ||
497 | wdev->wext.keys->params[idx].cipher = 0; | ||
498 | } | ||
476 | if (idx == wdev->wext.default_key) | 499 | if (idx == wdev->wext.default_key) |
477 | wdev->wext.default_key = -1; | 500 | wdev->wext.default_key = -1; |
478 | else if (idx == wdev->wext.default_mgmt_key) | 501 | else if (idx == wdev->wext.default_mgmt_key) |
@@ -486,36 +509,65 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
486 | return 0; | 509 | return 0; |
487 | 510 | ||
488 | return err; | 511 | return err; |
489 | } else { | 512 | } |
490 | if (addr) | ||
491 | tx_key = false; | ||
492 | 513 | ||
493 | if (cfg80211_validate_key_settings(params, idx, addr)) | 514 | if (addr) |
494 | return -EINVAL; | 515 | tx_key = false; |
495 | 516 | ||
517 | if (cfg80211_validate_key_settings(rdev, params, idx, addr)) | ||
518 | return -EINVAL; | ||
519 | |||
520 | err = 0; | ||
521 | if (wdev->current_bss) | ||
496 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); | 522 | err = rdev->ops->add_key(&rdev->wiphy, dev, idx, addr, params); |
497 | if (err) | 523 | if (err) |
498 | return err; | 524 | return err; |
499 | 525 | ||
500 | if (tx_key || (!addr && wdev->wext.default_key == -1)) { | 526 | if (!addr) { |
527 | wdev->wext.keys->params[idx] = *params; | ||
528 | memcpy(wdev->wext.keys->data[idx], | ||
529 | params->key, params->key_len); | ||
530 | wdev->wext.keys->params[idx].key = | ||
531 | wdev->wext.keys->data[idx]; | ||
532 | } | ||
533 | |||
534 | if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
535 | params->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
536 | (tx_key || (!addr && wdev->wext.default_key == -1))) { | ||
537 | if (wdev->current_bss) | ||
501 | err = rdev->ops->set_default_key(&rdev->wiphy, | 538 | err = rdev->ops->set_default_key(&rdev->wiphy, |
502 | dev, idx); | 539 | dev, idx); |
503 | if (!err) | 540 | if (!err) |
504 | wdev->wext.default_key = idx; | 541 | wdev->wext.default_key = idx; |
505 | return err; | 542 | return err; |
506 | } | 543 | } |
507 | 544 | ||
508 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && | 545 | if (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC && |
509 | (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { | 546 | (tx_key || (!addr && wdev->wext.default_mgmt_key == -1))) { |
547 | if (wdev->current_bss) | ||
510 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, | 548 | err = rdev->ops->set_default_mgmt_key(&rdev->wiphy, |
511 | dev, idx); | 549 | dev, idx); |
512 | if (!err) | 550 | if (!err) |
513 | wdev->wext.default_mgmt_key = idx; | 551 | wdev->wext.default_mgmt_key = idx; |
514 | return err; | 552 | return err; |
515 | } | ||
516 | |||
517 | return 0; | ||
518 | } | 553 | } |
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | ||
559 | struct net_device *dev, const u8 *addr, | ||
560 | bool remove, bool tx_key, int idx, | ||
561 | struct key_params *params) | ||
562 | { | ||
563 | int err; | ||
564 | |||
565 | wdev_lock(dev->ieee80211_ptr); | ||
566 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, | ||
567 | tx_key, idx, params); | ||
568 | wdev_unlock(dev->ieee80211_ptr); | ||
569 | |||
570 | return err; | ||
519 | } | 571 | } |
520 | 572 | ||
521 | int cfg80211_wext_siwencode(struct net_device *dev, | 573 | int cfg80211_wext_siwencode(struct net_device *dev, |
@@ -528,6 +580,10 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
528 | bool remove = false; | 580 | bool remove = false; |
529 | struct key_params params; | 581 | struct key_params params; |
530 | 582 | ||
583 | if (wdev->iftype != NL80211_IFTYPE_STATION && | ||
584 | wdev->iftype != NL80211_IFTYPE_ADHOC) | ||
585 | return -EOPNOTSUPP; | ||
586 | |||
531 | /* no use -- only MFP (set_default_mgmt_key) is optional */ | 587 | /* no use -- only MFP (set_default_mgmt_key) is optional */ |
532 | if (!rdev->ops->del_key || | 588 | if (!rdev->ops->del_key || |
533 | !rdev->ops->add_key || | 589 | !rdev->ops->add_key || |
@@ -548,9 +604,14 @@ int cfg80211_wext_siwencode(struct net_device *dev, | |||
548 | remove = true; | 604 | remove = true; |
549 | else if (erq->length == 0) { | 605 | else if (erq->length == 0) { |
550 | /* No key data - just set the default TX key index */ | 606 | /* No key data - just set the default TX key index */ |
551 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, idx); | 607 | err = 0; |
608 | wdev_lock(wdev); | ||
609 | if (wdev->current_bss) | ||
610 | err = rdev->ops->set_default_key(&rdev->wiphy, | ||
611 | dev, idx); | ||
552 | if (!err) | 612 | if (!err) |
553 | wdev->wext.default_key = idx; | 613 | wdev->wext.default_key = idx; |
614 | wdev_unlock(wdev); | ||
554 | return err; | 615 | return err; |
555 | } | 616 | } |
556 | 617 | ||
@@ -583,6 +644,10 @@ int cfg80211_wext_siwencodeext(struct net_device *dev, | |||
583 | struct key_params params; | 644 | struct key_params params; |
584 | u32 cipher; | 645 | u32 cipher; |
585 | 646 | ||
647 | if (wdev->iftype != NL80211_IFTYPE_STATION && | ||
648 | wdev->iftype != NL80211_IFTYPE_ADHOC) | ||
649 | return -EOPNOTSUPP; | ||
650 | |||
586 | /* no use -- only MFP (set_default_mgmt_key) is optional */ | 651 | /* no use -- only MFP (set_default_mgmt_key) is optional */ |
587 | if (!rdev->ops->del_key || | 652 | if (!rdev->ops->del_key || |
588 | !rdev->ops->add_key || | 653 | !rdev->ops->add_key || |
@@ -656,37 +721,15 @@ int cfg80211_wext_siwencodeext(struct net_device *dev, | |||
656 | } | 721 | } |
657 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); | 722 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwencodeext); |
658 | 723 | ||
659 | struct giwencode_cookie { | ||
660 | size_t buflen; | ||
661 | char *keybuf; | ||
662 | }; | ||
663 | |||
664 | static void giwencode_get_key_cb(void *cookie, struct key_params *params) | ||
665 | { | ||
666 | struct giwencode_cookie *data = cookie; | ||
667 | |||
668 | if (!params->key) { | ||
669 | data->buflen = 0; | ||
670 | return; | ||
671 | } | ||
672 | |||
673 | data->buflen = min_t(size_t, data->buflen, params->key_len); | ||
674 | memcpy(data->keybuf, params->key, data->buflen); | ||
675 | } | ||
676 | |||
677 | int cfg80211_wext_giwencode(struct net_device *dev, | 724 | int cfg80211_wext_giwencode(struct net_device *dev, |
678 | struct iw_request_info *info, | 725 | struct iw_request_info *info, |
679 | struct iw_point *erq, char *keybuf) | 726 | struct iw_point *erq, char *keybuf) |
680 | { | 727 | { |
681 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 728 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
682 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 729 | int idx; |
683 | int idx, err; | ||
684 | struct giwencode_cookie data = { | ||
685 | .keybuf = keybuf, | ||
686 | .buflen = erq->length, | ||
687 | }; | ||
688 | 730 | ||
689 | if (!rdev->ops->get_key) | 731 | if (wdev->iftype != NL80211_IFTYPE_STATION && |
732 | wdev->iftype != NL80211_IFTYPE_ADHOC) | ||
690 | return -EOPNOTSUPP; | 733 | return -EOPNOTSUPP; |
691 | 734 | ||
692 | idx = erq->flags & IW_ENCODE_INDEX; | 735 | idx = erq->flags & IW_ENCODE_INDEX; |
@@ -701,21 +744,18 @@ int cfg80211_wext_giwencode(struct net_device *dev, | |||
701 | 744 | ||
702 | erq->flags = idx + 1; | 745 | erq->flags = idx + 1; |
703 | 746 | ||
704 | err = rdev->ops->get_key(&rdev->wiphy, dev, idx, NULL, &data, | 747 | if (!wdev->wext.keys || !wdev->wext.keys->params[idx].cipher) { |
705 | giwencode_get_key_cb); | ||
706 | if (!err) { | ||
707 | erq->length = data.buflen; | ||
708 | erq->flags |= IW_ENCODE_ENABLED; | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | if (err == -ENOENT) { | ||
713 | erq->flags |= IW_ENCODE_DISABLED; | 748 | erq->flags |= IW_ENCODE_DISABLED; |
714 | erq->length = 0; | 749 | erq->length = 0; |
715 | return 0; | 750 | return 0; |
716 | } | 751 | } |
717 | 752 | ||
718 | return err; | 753 | erq->length = min_t(size_t, erq->length, |
754 | wdev->wext.keys->params[idx].key_len); | ||
755 | memcpy(keybuf, wdev->wext.keys->params[idx].key, erq->length); | ||
756 | erq->flags |= IW_ENCODE_ENABLED; | ||
757 | |||
758 | return 0; | ||
719 | } | 759 | } |
720 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); | 760 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); |
721 | 761 | ||
@@ -841,9 +881,19 @@ static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) | |||
841 | wdev->wext.connect.crypto.wpa_versions = 0; | 881 | wdev->wext.connect.crypto.wpa_versions = 0; |
842 | 882 | ||
843 | if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | | 883 | if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | |
844 | IW_AUTH_WPA_VERSION_WPA2)) | 884 | IW_AUTH_WPA_VERSION_WPA2| |
885 | IW_AUTH_WPA_VERSION_DISABLED)) | ||
845 | return -EINVAL; | 886 | return -EINVAL; |
846 | 887 | ||
888 | if ((wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) && | ||
889 | (wpa_versions & (IW_AUTH_WPA_VERSION_WPA| | ||
890 | IW_AUTH_WPA_VERSION_WPA2))) | ||
891 | return -EINVAL; | ||
892 | |||
893 | if (wpa_versions & IW_AUTH_WPA_VERSION_DISABLED) | ||
894 | wdev->wext.connect.crypto.wpa_versions &= | ||
895 | ~(NL80211_WPA_VERSION_1|NL80211_WPA_VERSION_2); | ||
896 | |||
847 | if (wpa_versions & IW_AUTH_WPA_VERSION_WPA) | 897 | if (wpa_versions & IW_AUTH_WPA_VERSION_WPA) |
848 | wdev->wext.connect.crypto.wpa_versions |= | 898 | wdev->wext.connect.crypto.wpa_versions |= |
849 | NL80211_WPA_VERSION_1; | 899 | NL80211_WPA_VERSION_1; |
@@ -1127,7 +1177,7 @@ int cfg80211_wext_giwrate(struct net_device *dev, | |||
1127 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1177 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
1128 | /* we are under RTNL - globally locked - so can use a static struct */ | 1178 | /* we are under RTNL - globally locked - so can use a static struct */ |
1129 | static struct station_info sinfo; | 1179 | static struct station_info sinfo; |
1130 | u8 *addr; | 1180 | u8 addr[ETH_ALEN]; |
1131 | int err; | 1181 | int err; |
1132 | 1182 | ||
1133 | if (wdev->iftype != NL80211_IFTYPE_STATION) | 1183 | if (wdev->iftype != NL80211_IFTYPE_STATION) |
@@ -1136,12 +1186,15 @@ int cfg80211_wext_giwrate(struct net_device *dev, | |||
1136 | if (!rdev->ops->get_station) | 1186 | if (!rdev->ops->get_station) |
1137 | return -EOPNOTSUPP; | 1187 | return -EOPNOTSUPP; |
1138 | 1188 | ||
1189 | err = 0; | ||
1190 | wdev_lock(wdev); | ||
1139 | if (wdev->current_bss) | 1191 | if (wdev->current_bss) |
1140 | addr = wdev->current_bss->pub.bssid; | 1192 | memcpy(addr, wdev->current_bss->pub.bssid, ETH_ALEN); |
1141 | else if (wdev->wext.connect.bssid) | ||
1142 | addr = wdev->wext.connect.bssid; | ||
1143 | else | 1193 | else |
1144 | return -EOPNOTSUPP; | 1194 | err = -EOPNOTSUPP; |
1195 | wdev_unlock(wdev); | ||
1196 | if (err) | ||
1197 | return err; | ||
1145 | 1198 | ||
1146 | err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo); | 1199 | err = rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo); |
1147 | if (err) | 1200 | if (err) |
@@ -1167,7 +1220,7 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1167 | /* we are under RTNL - globally locked - so can use static structs */ | 1220 | /* we are under RTNL - globally locked - so can use static structs */ |
1168 | static struct iw_statistics wstats; | 1221 | static struct iw_statistics wstats; |
1169 | static struct station_info sinfo; | 1222 | static struct station_info sinfo; |
1170 | u8 *addr; | 1223 | u8 bssid[ETH_ALEN]; |
1171 | 1224 | ||
1172 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) | 1225 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) |
1173 | return NULL; | 1226 | return NULL; |
@@ -1175,11 +1228,16 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) | |||
1175 | if (!rdev->ops->get_station) | 1228 | if (!rdev->ops->get_station) |
1176 | return NULL; | 1229 | return NULL; |
1177 | 1230 | ||
1178 | addr = wdev->wext.connect.bssid; | 1231 | /* Grab BSSID of current BSS, if any */ |
1179 | if (!addr) | 1232 | wdev_lock(wdev); |
1233 | if (!wdev->current_bss) { | ||
1234 | wdev_unlock(wdev); | ||
1180 | return NULL; | 1235 | return NULL; |
1236 | } | ||
1237 | memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); | ||
1238 | wdev_unlock(wdev); | ||
1181 | 1239 | ||
1182 | if (rdev->ops->get_station(&rdev->wiphy, dev, addr, &sinfo)) | 1240 | if (rdev->ops->get_station(&rdev->wiphy, dev, bssid, &sinfo)) |
1183 | return NULL; | 1241 | return NULL; |
1184 | 1242 | ||
1185 | memset(&wstats, 0, sizeof(wstats)); | 1243 | memset(&wstats, 0, sizeof(wstats)); |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 6f75aaa7f795..4c689fd865b0 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
@@ -10,10 +10,11 @@ | |||
10 | #include <net/cfg80211.h> | 10 | #include <net/cfg80211.h> |
11 | #include "nl80211.h" | 11 | #include "nl80211.h" |
12 | 12 | ||
13 | static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | 13 | int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, |
14 | struct wireless_dev *wdev) | 14 | struct wireless_dev *wdev) |
15 | { | 15 | { |
16 | int err; | 16 | struct cfg80211_cached_keys *ck = NULL; |
17 | int err, i; | ||
17 | 18 | ||
18 | ASSERT_RDEV_LOCK(rdev); | 19 | ASSERT_RDEV_LOCK(rdev); |
19 | ASSERT_WDEV_LOCK(wdev); | 20 | ASSERT_WDEV_LOCK(wdev); |
@@ -25,10 +26,25 @@ static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
25 | wdev->wext.connect.ie_len = wdev->wext.ie_len; | 26 | wdev->wext.connect.ie_len = wdev->wext.ie_len; |
26 | wdev->wext.connect.privacy = wdev->wext.default_key != -1; | 27 | wdev->wext.connect.privacy = wdev->wext.default_key != -1; |
27 | 28 | ||
28 | err = 0; | 29 | if (wdev->wext.keys) { |
29 | if (wdev->wext.connect.ssid_len != 0) | 30 | wdev->wext.keys->def = wdev->wext.default_key; |
30 | err = __cfg80211_connect(rdev, wdev->netdev, | 31 | wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key; |
31 | &wdev->wext.connect); | 32 | } |
33 | |||
34 | if (!wdev->wext.connect.ssid_len) | ||
35 | return 0; | ||
36 | |||
37 | if (wdev->wext.keys) { | ||
38 | ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL); | ||
39 | if (!ck) | ||
40 | return -ENOMEM; | ||
41 | for (i = 0; i < 6; i++) | ||
42 | ck->params[i].key = ck->data[i]; | ||
43 | } | ||
44 | err = __cfg80211_connect(rdev, wdev->netdev, | ||
45 | &wdev->wext.connect, ck); | ||
46 | if (err) | ||
47 | kfree(ck); | ||
32 | 48 | ||
33 | return err; | 49 | return err; |
34 | } | 50 | } |
@@ -56,13 +72,14 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | |||
56 | cfg80211_lock_rdev(rdev); | 72 | cfg80211_lock_rdev(rdev); |
57 | wdev_lock(wdev); | 73 | wdev_lock(wdev); |
58 | 74 | ||
59 | if (wdev->wext.connect.channel == chan) { | ||
60 | err = 0; | ||
61 | goto out; | ||
62 | } | ||
63 | |||
64 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 75 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
65 | bool event = true; | 76 | bool event = true; |
77 | |||
78 | if (wdev->wext.connect.channel == chan) { | ||
79 | err = 0; | ||
80 | goto out; | ||
81 | } | ||
82 | |||
66 | /* if SSID set, we'll try right again, avoid event */ | 83 | /* if SSID set, we'll try right again, avoid event */ |
67 | if (wdev->wext.connect.ssid_len) | 84 | if (wdev->wext.connect.ssid_len) |
68 | event = false; | 85 | event = false; |
@@ -148,13 +165,14 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | |||
148 | 165 | ||
149 | err = 0; | 166 | err = 0; |
150 | 167 | ||
151 | if (wdev->wext.connect.ssid && len && | ||
152 | len == wdev->wext.connect.ssid_len && | ||
153 | memcmp(wdev->wext.connect.ssid, ssid, len)) | ||
154 | goto out; | ||
155 | |||
156 | if (wdev->sme_state != CFG80211_SME_IDLE) { | 168 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
157 | bool event = true; | 169 | bool event = true; |
170 | |||
171 | if (wdev->wext.connect.ssid && len && | ||
172 | len == wdev->wext.connect.ssid_len && | ||
173 | memcmp(wdev->wext.connect.ssid, ssid, len) == 0) | ||
174 | goto out; | ||
175 | |||
158 | /* if SSID set now, we'll try to connect, avoid event */ | 176 | /* if SSID set now, we'll try to connect, avoid event */ |
159 | if (len) | 177 | if (len) |
160 | event = false; | 178 | event = false; |
@@ -193,11 +211,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, | |||
193 | data->flags = 0; | 211 | data->flags = 0; |
194 | 212 | ||
195 | wdev_lock(wdev); | 213 | wdev_lock(wdev); |
196 | if (wdev->ssid_len) { | 214 | if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { |
197 | data->flags = 1; | ||
198 | data->length = wdev->ssid_len; | ||
199 | memcpy(ssid, wdev->ssid, data->length); | ||
200 | } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { | ||
201 | data->flags = 1; | 215 | data->flags = 1; |
202 | data->length = wdev->wext.connect.ssid_len; | 216 | data->length = wdev->wext.connect.ssid_len; |
203 | memcpy(ssid, wdev->wext.connect.ssid, data->length); | 217 | memcpy(ssid, wdev->wext.connect.ssid, data->length); |
@@ -232,17 +246,17 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | |||
232 | cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); | 246 | cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); |
233 | wdev_lock(wdev); | 247 | wdev_lock(wdev); |
234 | 248 | ||
235 | err = 0; | 249 | if (wdev->sme_state != CFG80211_SME_IDLE) { |
236 | /* both automatic */ | 250 | err = 0; |
237 | if (!bssid && !wdev->wext.connect.bssid) | 251 | /* both automatic */ |
238 | goto out; | 252 | if (!bssid && !wdev->wext.connect.bssid) |
253 | goto out; | ||
239 | 254 | ||
240 | /* fixed already - and no change */ | 255 | /* fixed already - and no change */ |
241 | if (wdev->wext.connect.bssid && bssid && | 256 | if (wdev->wext.connect.bssid && bssid && |
242 | compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) | 257 | compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) |
243 | goto out; | 258 | goto out; |
244 | 259 | ||
245 | if (wdev->sme_state != CFG80211_SME_IDLE) { | ||
246 | err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), | 260 | err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), |
247 | dev, WLAN_REASON_DEAUTH_LEAVING, | 261 | dev, WLAN_REASON_DEAUTH_LEAVING, |
248 | false); | 262 | false); |