aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c124
1 files changed, 101 insertions, 23 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 22a384dfab6..7cc4f913a43 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -20,6 +20,7 @@
20#include <linux/rtnetlink.h> 20#include <linux/rtnetlink.h>
21#include <linux/bitmap.h> 21#include <linux/bitmap.h>
22#include <linux/pm_qos_params.h> 22#include <linux/pm_qos_params.h>
23#include <linux/inetdevice.h>
23#include <net/net_namespace.h> 24#include <net/net_namespace.h>
24#include <net/cfg80211.h> 25#include <net/cfg80211.h>
25 26
@@ -106,12 +107,15 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
106 if (scan_chan) { 107 if (scan_chan) {
107 chan = scan_chan; 108 chan = scan_chan;
108 channel_type = NL80211_CHAN_NO_HT; 109 channel_type = NL80211_CHAN_NO_HT;
110 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
109 } else if (local->tmp_channel) { 111 } else if (local->tmp_channel) {
110 chan = scan_chan = local->tmp_channel; 112 chan = scan_chan = local->tmp_channel;
111 channel_type = local->tmp_channel_type; 113 channel_type = local->tmp_channel_type;
114 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
112 } else { 115 } else {
113 chan = local->oper_channel; 116 chan = local->oper_channel;
114 channel_type = local->_oper_channel_type; 117 channel_type = local->_oper_channel_type;
118 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
115 } 119 }
116 120
117 if (chan != local->hw.conf.channel || 121 if (chan != local->hw.conf.channel ||
@@ -259,7 +263,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
259{ 263{
260 struct ieee80211_local *local = (struct ieee80211_local *) data; 264 struct ieee80211_local *local = (struct ieee80211_local *) data;
261 struct sk_buff *skb; 265 struct sk_buff *skb;
262 struct ieee80211_ra_tid *ra_tid;
263 266
264 while ((skb = skb_dequeue(&local->skb_queue)) || 267 while ((skb = skb_dequeue(&local->skb_queue)) ||
265 (skb = skb_dequeue(&local->skb_queue_unreliable))) { 268 (skb = skb_dequeue(&local->skb_queue_unreliable))) {
@@ -274,18 +277,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
274 skb->pkt_type = 0; 277 skb->pkt_type = 0;
275 ieee80211_tx_status(local_to_hw(local), skb); 278 ieee80211_tx_status(local_to_hw(local), skb);
276 break; 279 break;
277 case IEEE80211_DELBA_MSG:
278 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
279 ieee80211_stop_tx_ba_cb(ra_tid->vif, ra_tid->ra,
280 ra_tid->tid);
281 dev_kfree_skb(skb);
282 break;
283 case IEEE80211_ADDBA_MSG:
284 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
285 ieee80211_start_tx_ba_cb(ra_tid->vif, ra_tid->ra,
286 ra_tid->tid);
287 dev_kfree_skb(skb);
288 break ;
289 default: 280 default:
290 WARN(1, "mac80211: Packet is of unknown type %d\n", 281 WARN(1, "mac80211: Packet is of unknown type %d\n",
291 skb->pkt_type); 282 skb->pkt_type);
@@ -329,6 +320,76 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
329 mutex_unlock(&local->iflist_mtx); 320 mutex_unlock(&local->iflist_mtx);
330} 321}
331 322
323#ifdef CONFIG_INET
324static int ieee80211_ifa_changed(struct notifier_block *nb,
325 unsigned long data, void *arg)
326{
327 struct in_ifaddr *ifa = arg;
328 struct ieee80211_local *local =
329 container_of(nb, struct ieee80211_local,
330 ifa_notifier);
331 struct net_device *ndev = ifa->ifa_dev->dev;
332 struct wireless_dev *wdev = ndev->ieee80211_ptr;
333 struct in_device *idev;
334 struct ieee80211_sub_if_data *sdata;
335 struct ieee80211_bss_conf *bss_conf;
336 struct ieee80211_if_managed *ifmgd;
337 int c = 0;
338
339 if (!netif_running(ndev))
340 return NOTIFY_DONE;
341
342 /* Make sure it's our interface that got changed */
343 if (!wdev)
344 return NOTIFY_DONE;
345
346 if (wdev->wiphy != local->hw.wiphy)
347 return NOTIFY_DONE;
348
349 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
350 bss_conf = &sdata->vif.bss_conf;
351
352 /* ARP filtering is only supported in managed mode */
353 if (sdata->vif.type != NL80211_IFTYPE_STATION)
354 return NOTIFY_DONE;
355
356 idev = sdata->dev->ip_ptr;
357 if (!idev)
358 return NOTIFY_DONE;
359
360 ifmgd = &sdata->u.mgd;
361 mutex_lock(&ifmgd->mtx);
362
363 /* Copy the addresses to the bss_conf list */
364 ifa = idev->ifa_list;
365 while (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN && ifa) {
366 bss_conf->arp_addr_list[c] = ifa->ifa_address;
367 ifa = ifa->ifa_next;
368 c++;
369 }
370
371 /* If not all addresses fit the list, disable filtering */
372 if (ifa) {
373 sdata->arp_filter_state = false;
374 c = 0;
375 } else {
376 sdata->arp_filter_state = true;
377 }
378 bss_conf->arp_addr_cnt = c;
379
380 /* Configure driver only if associated */
381 if (ifmgd->associated) {
382 bss_conf->arp_filter_enabled = sdata->arp_filter_state;
383 ieee80211_bss_info_change_notify(sdata,
384 BSS_CHANGED_ARP_FILTER);
385 }
386
387 mutex_unlock(&ifmgd->mtx);
388
389 return NOTIFY_DONE;
390}
391#endif
392
332struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 393struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
333 const struct ieee80211_ops *ops) 394 const struct ieee80211_ops *ops)
334{ 395{
@@ -396,7 +457,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
396 mutex_init(&local->iflist_mtx); 457 mutex_init(&local->iflist_mtx);
397 mutex_init(&local->scan_mtx); 458 mutex_init(&local->scan_mtx);
398 459
399 spin_lock_init(&local->key_lock); 460 mutex_init(&local->key_mtx);
400 spin_lock_init(&local->filter_lock); 461 spin_lock_init(&local->filter_lock);
401 spin_lock_init(&local->queue_stop_reason_lock); 462 spin_lock_init(&local->queue_stop_reason_lock);
402 463
@@ -419,8 +480,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
419 480
420 sta_info_init(local); 481 sta_info_init(local);
421 482
422 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) 483 for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
423 skb_queue_head_init(&local->pending[i]); 484 skb_queue_head_init(&local->pending[i]);
485 atomic_set(&local->agg_queue_stop[i], 0);
486 }
424 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, 487 tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
425 (unsigned long)local); 488 (unsigned long)local);
426 489
@@ -431,8 +494,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
431 skb_queue_head_init(&local->skb_queue); 494 skb_queue_head_init(&local->skb_queue);
432 skb_queue_head_init(&local->skb_queue_unreliable); 495 skb_queue_head_init(&local->skb_queue_unreliable);
433 496
434 spin_lock_init(&local->ampdu_lock);
435
436 return local_to_hw(local); 497 return local_to_hw(local);
437} 498}
438EXPORT_SYMBOL(ieee80211_alloc_hw); 499EXPORT_SYMBOL(ieee80211_alloc_hw);
@@ -572,18 +633,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
572 633
573 local->hw.conf.listen_interval = local->hw.max_listen_interval; 634 local->hw.conf.listen_interval = local->hw.max_listen_interval;
574 635
575 local->hw.conf.dynamic_ps_forced_timeout = -1; 636 local->dynamic_ps_forced_timeout = -1;
576 637
577 result = sta_info_start(local); 638 result = sta_info_start(local);
578 if (result < 0) 639 if (result < 0)
579 goto fail_sta_info; 640 goto fail_sta_info;
580 641
581 result = ieee80211_wep_init(local); 642 result = ieee80211_wep_init(local);
582 if (result < 0) { 643 if (result < 0)
583 printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", 644 printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
584 wiphy_name(local->hw.wiphy), result); 645 wiphy_name(local->hw.wiphy), result);
585 goto fail_wep;
586 }
587 646
588 rtnl_lock(); 647 rtnl_lock();
589 648
@@ -612,21 +671,30 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
612 ieee80211_max_network_latency; 671 ieee80211_max_network_latency;
613 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, 672 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
614 &local->network_latency_notifier); 673 &local->network_latency_notifier);
615
616 if (result) { 674 if (result) {
617 rtnl_lock(); 675 rtnl_lock();
618 goto fail_pm_qos; 676 goto fail_pm_qos;
619 } 677 }
620 678
679#ifdef CONFIG_INET
680 local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
681 result = register_inetaddr_notifier(&local->ifa_notifier);
682 if (result)
683 goto fail_ifa;
684#endif
685
621 return 0; 686 return 0;
622 687
688 fail_ifa:
689 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
690 &local->network_latency_notifier);
691 rtnl_lock();
623 fail_pm_qos: 692 fail_pm_qos:
624 ieee80211_led_exit(local); 693 ieee80211_led_exit(local);
625 ieee80211_remove_interfaces(local); 694 ieee80211_remove_interfaces(local);
626 fail_rate: 695 fail_rate:
627 rtnl_unlock(); 696 rtnl_unlock();
628 ieee80211_wep_free(local); 697 ieee80211_wep_free(local);
629 fail_wep:
630 sta_info_stop(local); 698 sta_info_stop(local);
631 fail_sta_info: 699 fail_sta_info:
632 destroy_workqueue(local->workqueue); 700 destroy_workqueue(local->workqueue);
@@ -647,6 +715,9 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
647 715
648 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, 716 pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
649 &local->network_latency_notifier); 717 &local->network_latency_notifier);
718#ifdef CONFIG_INET
719 unregister_inetaddr_notifier(&local->ifa_notifier);
720#endif
650 721
651 rtnl_lock(); 722 rtnl_lock();
652 723
@@ -704,6 +775,10 @@ static int __init ieee80211_init(void)
704 if (ret) 775 if (ret)
705 return ret; 776 return ret;
706 777
778 ret = rc80211_minstrel_ht_init();
779 if (ret)
780 goto err_minstrel;
781
707 ret = rc80211_pid_init(); 782 ret = rc80211_pid_init();
708 if (ret) 783 if (ret)
709 goto err_pid; 784 goto err_pid;
@@ -716,6 +791,8 @@ static int __init ieee80211_init(void)
716 err_netdev: 791 err_netdev:
717 rc80211_pid_exit(); 792 rc80211_pid_exit();
718 err_pid: 793 err_pid:
794 rc80211_minstrel_ht_exit();
795 err_minstrel:
719 rc80211_minstrel_exit(); 796 rc80211_minstrel_exit();
720 797
721 return ret; 798 return ret;
@@ -724,6 +801,7 @@ static int __init ieee80211_init(void)
724static void __exit ieee80211_exit(void) 801static void __exit ieee80211_exit(void)
725{ 802{
726 rc80211_pid_exit(); 803 rc80211_pid_exit();
804 rc80211_minstrel_ht_exit();
727 rc80211_minstrel_exit(); 805 rc80211_minstrel_exit();
728 806
729 /* 807 /*