diff options
Diffstat (limited to 'drivers')
90 files changed, 2774 insertions, 2397 deletions
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 }, |