diff options
-rw-r--r-- | net/mac80211/cfg.c | 18 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/iface.c | 231 | ||||
-rw-r--r-- | net/mac80211/main.c | 9 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 6 | ||||
-rw-r--r-- | net/mac80211/rx.c | 14 | ||||
-rw-r--r-- | net/mac80211/status.c | 22 | ||||
-rw-r--r-- | net/mac80211/trace.h | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 14 |
10 files changed, 226 insertions, 96 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8052a7ad03a6..69b322f6ca2e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -102,6 +102,18 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int ieee80211_start_p2p_device(struct wiphy *wiphy, | ||
106 | struct wireless_dev *wdev) | ||
107 | { | ||
108 | return ieee80211_do_open(wdev, true); | ||
109 | } | ||
110 | |||
111 | static void ieee80211_stop_p2p_device(struct wiphy *wiphy, | ||
112 | struct wireless_dev *wdev) | ||
113 | { | ||
114 | ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev)); | ||
115 | } | ||
116 | |||
105 | static int ieee80211_set_noack_map(struct wiphy *wiphy, | 117 | static int ieee80211_set_noack_map(struct wiphy *wiphy, |
106 | struct net_device *dev, | 118 | struct net_device *dev, |
107 | u16 noack_map) | 119 | u16 noack_map) |
@@ -1774,6 +1786,7 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1774 | case NL80211_IFTYPE_ADHOC: | 1786 | case NL80211_IFTYPE_ADHOC: |
1775 | case NL80211_IFTYPE_MESH_POINT: | 1787 | case NL80211_IFTYPE_MESH_POINT: |
1776 | case NL80211_IFTYPE_P2P_CLIENT: | 1788 | case NL80211_IFTYPE_P2P_CLIENT: |
1789 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1777 | break; | 1790 | break; |
1778 | case NL80211_IFTYPE_P2P_GO: | 1791 | case NL80211_IFTYPE_P2P_GO: |
1779 | if (sdata->local->ops->hw_scan) | 1792 | if (sdata->local->ops->hw_scan) |
@@ -2461,6 +2474,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2461 | if (!sdata->u.mgd.associated) | 2474 | if (!sdata->u.mgd.associated) |
2462 | need_offchan = true; | 2475 | need_offchan = true; |
2463 | break; | 2476 | break; |
2477 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2478 | need_offchan = true; | ||
2479 | break; | ||
2464 | default: | 2480 | default: |
2465 | return -EOPNOTSUPP; | 2481 | return -EOPNOTSUPP; |
2466 | } | 2482 | } |
@@ -3013,6 +3029,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3013 | .add_virtual_intf = ieee80211_add_iface, | 3029 | .add_virtual_intf = ieee80211_add_iface, |
3014 | .del_virtual_intf = ieee80211_del_iface, | 3030 | .del_virtual_intf = ieee80211_del_iface, |
3015 | .change_virtual_intf = ieee80211_change_iface, | 3031 | .change_virtual_intf = ieee80211_change_iface, |
3032 | .start_p2p_device = ieee80211_start_p2p_device, | ||
3033 | .stop_p2p_device = ieee80211_stop_p2p_device, | ||
3016 | .add_key = ieee80211_add_key, | 3034 | .add_key = ieee80211_add_key, |
3017 | .del_key = ieee80211_del_key, | 3035 | .del_key = ieee80211_del_key, |
3018 | .get_key = ieee80211_get_key, | 3036 | .get_key = ieee80211_get_key, |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index a81154d27291..da9003b20004 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -9,7 +9,7 @@ static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | |||
9 | { | 9 | { |
10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), | 10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), |
11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", | 11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", |
12 | sdata->dev->name, sdata->flags); | 12 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); |
13 | } | 13 | } |
14 | 14 | ||
15 | static inline struct ieee80211_sub_if_data * | 15 | static inline struct ieee80211_sub_if_data * |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2a80698b6324..0b81fa807179 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1080,6 +1080,8 @@ struct ieee80211_local { | |||
1080 | struct idr ack_status_frames; | 1080 | struct idr ack_status_frames; |
1081 | spinlock_t ack_status_lock; | 1081 | spinlock_t ack_status_lock; |
1082 | 1082 | ||
1083 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | ||
1084 | |||
1083 | /* dummy netdev for use w/ NAPI */ | 1085 | /* dummy netdev for use w/ NAPI */ |
1084 | struct net_device napi_dev; | 1086 | struct net_device napi_dev; |
1085 | 1087 | ||
@@ -1296,6 +1298,8 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); | |||
1296 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1298 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1297 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1299 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1298 | const int offset); | 1300 | const int offset); |
1301 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); | ||
1302 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); | ||
1299 | 1303 | ||
1300 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1304 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1301 | { | 1305 | { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 366d9d3e84c4..152aeea14c85 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -100,6 +100,10 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
100 | sdata->vif.bss_conf.idle = true; | 100 | sdata->vif.bss_conf.idle = true; |
101 | continue; | 101 | continue; |
102 | } | 102 | } |
103 | |||
104 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
105 | continue; | ||
106 | |||
103 | /* count everything else */ | 107 | /* count everything else */ |
104 | sdata->vif.bss_conf.idle = false; | 108 | sdata->vif.bss_conf.idle = false; |
105 | count++; | 109 | count++; |
@@ -121,7 +125,8 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
121 | 125 | ||
122 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
123 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 127 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
124 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 128 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
129 | sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
125 | continue; | 130 | continue; |
126 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | 131 | if (sdata->old_idle == sdata->vif.bss_conf.idle) |
127 | continue; | 132 | continue; |
@@ -204,6 +209,8 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
204 | { | 209 | { |
205 | return type1 == NL80211_IFTYPE_MONITOR || | 210 | return type1 == NL80211_IFTYPE_MONITOR || |
206 | type2 == NL80211_IFTYPE_MONITOR || | 211 | type2 == NL80211_IFTYPE_MONITOR || |
212 | type1 == NL80211_IFTYPE_P2P_DEVICE || | ||
213 | type2 == NL80211_IFTYPE_P2P_DEVICE || | ||
207 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || | 214 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || |
208 | (type1 == NL80211_IFTYPE_WDS && | 215 | (type1 == NL80211_IFTYPE_WDS && |
209 | (type2 == NL80211_IFTYPE_WDS || | 216 | (type2 == NL80211_IFTYPE_WDS || |
@@ -406,9 +413,10 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
406 | * an error on interface type changes that have been pre-checked, so most | 413 | * an error on interface type changes that have been pre-checked, so most |
407 | * checks should be in ieee80211_check_concurrent_iface. | 414 | * checks should be in ieee80211_check_concurrent_iface. |
408 | */ | 415 | */ |
409 | static int ieee80211_do_open(struct net_device *dev, bool coming_up) | 416 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) |
410 | { | 417 | { |
411 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 418 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
419 | struct net_device *dev = wdev->netdev; | ||
412 | struct ieee80211_local *local = sdata->local; | 420 | struct ieee80211_local *local = sdata->local; |
413 | struct sta_info *sta; | 421 | struct sta_info *sta; |
414 | u32 changed = 0; | 422 | u32 changed = 0; |
@@ -443,13 +451,13 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
443 | case NL80211_IFTYPE_STATION: | 451 | case NL80211_IFTYPE_STATION: |
444 | case NL80211_IFTYPE_MONITOR: | 452 | case NL80211_IFTYPE_MONITOR: |
445 | case NL80211_IFTYPE_ADHOC: | 453 | case NL80211_IFTYPE_ADHOC: |
454 | case NL80211_IFTYPE_P2P_DEVICE: | ||
446 | /* no special treatment */ | 455 | /* no special treatment */ |
447 | break; | 456 | break; |
448 | case NL80211_IFTYPE_UNSPECIFIED: | 457 | case NL80211_IFTYPE_UNSPECIFIED: |
449 | case NUM_NL80211_IFTYPES: | 458 | case NUM_NL80211_IFTYPES: |
450 | case NL80211_IFTYPE_P2P_CLIENT: | 459 | case NL80211_IFTYPE_P2P_CLIENT: |
451 | case NL80211_IFTYPE_P2P_GO: | 460 | case NL80211_IFTYPE_P2P_GO: |
452 | case NL80211_IFTYPE_P2P_DEVICE: | ||
453 | /* cannot happen */ | 461 | /* cannot happen */ |
454 | WARN_ON(1); | 462 | WARN_ON(1); |
455 | break; | 463 | break; |
@@ -472,7 +480,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
472 | * Copy the hopefully now-present MAC address to | 480 | * Copy the hopefully now-present MAC address to |
473 | * this interface, if it has the special null one. | 481 | * this interface, if it has the special null one. |
474 | */ | 482 | */ |
475 | if (is_zero_ether_addr(dev->dev_addr)) { | 483 | if (dev && is_zero_ether_addr(dev->dev_addr)) { |
476 | memcpy(dev->dev_addr, | 484 | memcpy(dev->dev_addr, |
477 | local->hw.wiphy->perm_addr, | 485 | local->hw.wiphy->perm_addr, |
478 | ETH_ALEN); | 486 | ETH_ALEN); |
@@ -537,7 +545,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
537 | local->fif_probe_req++; | 545 | local->fif_probe_req++; |
538 | } | 546 | } |
539 | 547 | ||
540 | changed |= ieee80211_reset_erp_info(sdata); | 548 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) |
549 | changed |= ieee80211_reset_erp_info(sdata); | ||
541 | ieee80211_bss_info_change_notify(sdata, changed); | 550 | ieee80211_bss_info_change_notify(sdata, changed); |
542 | 551 | ||
543 | switch (sdata->vif.type) { | 552 | switch (sdata->vif.type) { |
@@ -548,6 +557,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
548 | netif_carrier_off(dev); | 557 | netif_carrier_off(dev); |
549 | break; | 558 | break; |
550 | case NL80211_IFTYPE_WDS: | 559 | case NL80211_IFTYPE_WDS: |
560 | case NL80211_IFTYPE_P2P_DEVICE: | ||
551 | break; | 561 | break; |
552 | default: | 562 | default: |
553 | netif_carrier_on(dev); | 563 | netif_carrier_on(dev); |
@@ -584,6 +594,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
584 | 594 | ||
585 | rate_control_rate_init(sta); | 595 | rate_control_rate_init(sta); |
586 | netif_carrier_on(dev); | 596 | netif_carrier_on(dev); |
597 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
598 | rcu_assign_pointer(local->p2p_sdata, sdata); | ||
587 | } | 599 | } |
588 | 600 | ||
589 | /* | 601 | /* |
@@ -609,7 +621,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
609 | 621 | ||
610 | ieee80211_recalc_ps(local, -1); | 622 | ieee80211_recalc_ps(local, -1); |
611 | 623 | ||
612 | netif_tx_start_all_queues(dev); | 624 | if (dev) |
625 | netif_tx_start_all_queues(dev); | ||
613 | 626 | ||
614 | return 0; | 627 | return 0; |
615 | err_del_interface: | 628 | err_del_interface: |
@@ -639,7 +652,7 @@ static int ieee80211_open(struct net_device *dev) | |||
639 | if (err) | 652 | if (err) |
640 | return err; | 653 | return err; |
641 | 654 | ||
642 | return ieee80211_do_open(dev, true); | 655 | return ieee80211_do_open(&sdata->wdev, true); |
643 | } | 656 | } |
644 | 657 | ||
645 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | 658 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, |
@@ -660,7 +673,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
660 | /* | 673 | /* |
661 | * Stop TX on this interface first. | 674 | * Stop TX on this interface first. |
662 | */ | 675 | */ |
663 | netif_tx_stop_all_queues(sdata->dev); | 676 | if (sdata->dev) |
677 | netif_tx_stop_all_queues(sdata->dev); | ||
664 | 678 | ||
665 | ieee80211_roc_purge(sdata); | 679 | ieee80211_roc_purge(sdata); |
666 | 680 | ||
@@ -699,14 +713,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
699 | local->fif_probe_req--; | 713 | local->fif_probe_req--; |
700 | } | 714 | } |
701 | 715 | ||
702 | netif_addr_lock_bh(sdata->dev); | 716 | if (sdata->dev) { |
703 | spin_lock_bh(&local->filter_lock); | 717 | netif_addr_lock_bh(sdata->dev); |
704 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, | 718 | spin_lock_bh(&local->filter_lock); |
705 | sdata->dev->addr_len); | 719 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, |
706 | spin_unlock_bh(&local->filter_lock); | 720 | sdata->dev->addr_len); |
707 | netif_addr_unlock_bh(sdata->dev); | 721 | spin_unlock_bh(&local->filter_lock); |
722 | netif_addr_unlock_bh(sdata->dev); | ||
708 | 723 | ||
709 | ieee80211_configure_filter(local); | 724 | ieee80211_configure_filter(local); |
725 | } | ||
710 | 726 | ||
711 | del_timer_sync(&local->dynamic_ps_timer); | 727 | del_timer_sync(&local->dynamic_ps_timer); |
712 | cancel_work_sync(&local->dynamic_ps_enable_work); | 728 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -767,6 +783,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
767 | ieee80211_adjust_monitor_flags(sdata, -1); | 783 | ieee80211_adjust_monitor_flags(sdata, -1); |
768 | ieee80211_configure_filter(local); | 784 | ieee80211_configure_filter(local); |
769 | break; | 785 | break; |
786 | case NL80211_IFTYPE_P2P_DEVICE: | ||
787 | /* relies on synchronize_rcu() below */ | ||
788 | rcu_assign_pointer(local->p2p_sdata, NULL); | ||
789 | /* fall through */ | ||
770 | default: | 790 | default: |
771 | flush_work(&sdata->work); | 791 | flush_work(&sdata->work); |
772 | /* | 792 | /* |
@@ -877,9 +897,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
877 | * Called when the netdev is removed or, by the code below, before | 897 | * Called when the netdev is removed or, by the code below, before |
878 | * the interface type changes. | 898 | * the interface type changes. |
879 | */ | 899 | */ |
880 | static void ieee80211_teardown_sdata(struct net_device *dev) | 900 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
881 | { | 901 | { |
882 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
883 | struct ieee80211_local *local = sdata->local; | 902 | struct ieee80211_local *local = sdata->local; |
884 | int flushed; | 903 | int flushed; |
885 | int i; | 904 | int i; |
@@ -900,6 +919,11 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
900 | WARN_ON(flushed); | 919 | WARN_ON(flushed); |
901 | } | 920 | } |
902 | 921 | ||
922 | static void ieee80211_uninit(struct net_device *dev) | ||
923 | { | ||
924 | ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); | ||
925 | } | ||
926 | |||
903 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 927 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
904 | struct sk_buff *skb) | 928 | struct sk_buff *skb) |
905 | { | 929 | { |
@@ -909,7 +933,7 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev, | |||
909 | static const struct net_device_ops ieee80211_dataif_ops = { | 933 | static const struct net_device_ops ieee80211_dataif_ops = { |
910 | .ndo_open = ieee80211_open, | 934 | .ndo_open = ieee80211_open, |
911 | .ndo_stop = ieee80211_stop, | 935 | .ndo_stop = ieee80211_stop, |
912 | .ndo_uninit = ieee80211_teardown_sdata, | 936 | .ndo_uninit = ieee80211_uninit, |
913 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 937 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
914 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 938 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
915 | .ndo_change_mtu = ieee80211_change_mtu, | 939 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -940,7 +964,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
940 | static const struct net_device_ops ieee80211_monitorif_ops = { | 964 | static const struct net_device_ops ieee80211_monitorif_ops = { |
941 | .ndo_open = ieee80211_open, | 965 | .ndo_open = ieee80211_open, |
942 | .ndo_stop = ieee80211_stop, | 966 | .ndo_stop = ieee80211_stop, |
943 | .ndo_uninit = ieee80211_teardown_sdata, | 967 | .ndo_uninit = ieee80211_uninit, |
944 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | 968 | .ndo_start_xmit = ieee80211_monitor_start_xmit, |
945 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 969 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
946 | .ndo_change_mtu = ieee80211_change_mtu, | 970 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -1099,7 +1123,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1099 | /* and set some type-dependent values */ | 1123 | /* and set some type-dependent values */ |
1100 | sdata->vif.type = type; | 1124 | sdata->vif.type = type; |
1101 | sdata->vif.p2p = false; | 1125 | sdata->vif.p2p = false; |
1102 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1103 | sdata->wdev.iftype = type; | 1126 | sdata->wdev.iftype = type; |
1104 | 1127 | ||
1105 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 1128 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
@@ -1107,8 +1130,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1107 | 1130 | ||
1108 | sdata->noack_map = 0; | 1131 | sdata->noack_map = 0; |
1109 | 1132 | ||
1110 | /* only monitor differs */ | 1133 | /* only monitor/p2p-device differ */ |
1111 | sdata->dev->type = ARPHRD_ETHER; | 1134 | if (sdata->dev) { |
1135 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1136 | sdata->dev->type = ARPHRD_ETHER; | ||
1137 | } | ||
1112 | 1138 | ||
1113 | skb_queue_head_init(&sdata->skb_queue); | 1139 | skb_queue_head_init(&sdata->skb_queue); |
1114 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 1140 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
@@ -1146,9 +1172,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1146 | break; | 1172 | break; |
1147 | case NL80211_IFTYPE_WDS: | 1173 | case NL80211_IFTYPE_WDS: |
1148 | case NL80211_IFTYPE_AP_VLAN: | 1174 | case NL80211_IFTYPE_AP_VLAN: |
1149 | break; | ||
1150 | case NL80211_IFTYPE_P2P_DEVICE: | 1175 | case NL80211_IFTYPE_P2P_DEVICE: |
1151 | /* not yet supported */ | 1176 | break; |
1152 | case NL80211_IFTYPE_UNSPECIFIED: | 1177 | case NL80211_IFTYPE_UNSPECIFIED: |
1153 | case NUM_NL80211_IFTYPES: | 1178 | case NUM_NL80211_IFTYPES: |
1154 | BUG(); | 1179 | BUG(); |
@@ -1215,7 +1240,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1215 | 1240 | ||
1216 | ieee80211_do_stop(sdata, false); | 1241 | ieee80211_do_stop(sdata, false); |
1217 | 1242 | ||
1218 | ieee80211_teardown_sdata(sdata->dev); | 1243 | ieee80211_teardown_sdata(sdata); |
1219 | 1244 | ||
1220 | ret = drv_change_interface(local, sdata, internal_type, p2p); | 1245 | ret = drv_change_interface(local, sdata, internal_type, p2p); |
1221 | if (ret) | 1246 | if (ret) |
@@ -1230,7 +1255,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1230 | 1255 | ||
1231 | ieee80211_setup_sdata(sdata, type); | 1256 | ieee80211_setup_sdata(sdata, type); |
1232 | 1257 | ||
1233 | err = ieee80211_do_open(sdata->dev, false); | 1258 | err = ieee80211_do_open(&sdata->wdev, false); |
1234 | WARN(err, "type change: do_open returned %d", err); | 1259 | WARN(err, "type change: do_open returned %d", err); |
1235 | 1260 | ||
1236 | return ret; | 1261 | return ret; |
@@ -1257,7 +1282,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1257 | return ret; | 1282 | return ret; |
1258 | } else { | 1283 | } else { |
1259 | /* Purge and reset type-dependent state. */ | 1284 | /* Purge and reset type-dependent state. */ |
1260 | ieee80211_teardown_sdata(sdata->dev); | 1285 | ieee80211_teardown_sdata(sdata); |
1261 | ieee80211_setup_sdata(sdata, type); | 1286 | ieee80211_setup_sdata(sdata, type); |
1262 | } | 1287 | } |
1263 | 1288 | ||
@@ -1273,8 +1298,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1273 | } | 1298 | } |
1274 | 1299 | ||
1275 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | 1300 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, |
1276 | struct net_device *dev, | 1301 | u8 *perm_addr, enum nl80211_iftype type) |
1277 | enum nl80211_iftype type) | ||
1278 | { | 1302 | { |
1279 | struct ieee80211_sub_if_data *sdata; | 1303 | struct ieee80211_sub_if_data *sdata; |
1280 | u64 mask, start, addr, val, inc; | 1304 | u64 mask, start, addr, val, inc; |
@@ -1283,7 +1307,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1283 | int i; | 1307 | int i; |
1284 | 1308 | ||
1285 | /* default ... something at least */ | 1309 | /* default ... something at least */ |
1286 | memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 1310 | memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
1287 | 1311 | ||
1288 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && | 1312 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && |
1289 | local->hw.wiphy->n_addresses <= 1) | 1313 | local->hw.wiphy->n_addresses <= 1) |
@@ -1302,7 +1326,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1302 | list_for_each_entry(sdata, &local->interfaces, list) { | 1326 | list_for_each_entry(sdata, &local->interfaces, list) { |
1303 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1327 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
1304 | continue; | 1328 | continue; |
1305 | memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); | 1329 | memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); |
1306 | break; | 1330 | break; |
1307 | } | 1331 | } |
1308 | /* keep default if no AP interface present */ | 1332 | /* keep default if no AP interface present */ |
@@ -1321,7 +1345,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1321 | } | 1345 | } |
1322 | 1346 | ||
1323 | if (!used) { | 1347 | if (!used) { |
1324 | memcpy(dev->perm_addr, | 1348 | memcpy(perm_addr, |
1325 | local->hw.wiphy->addresses[i].addr, | 1349 | local->hw.wiphy->addresses[i].addr, |
1326 | ETH_ALEN); | 1350 | ETH_ALEN); |
1327 | break; | 1351 | break; |
@@ -1372,7 +1396,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1372 | } | 1396 | } |
1373 | 1397 | ||
1374 | if (!used) { | 1398 | if (!used) { |
1375 | memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); | 1399 | memcpy(perm_addr, tmp_addr, ETH_ALEN); |
1376 | break; | 1400 | break; |
1377 | } | 1401 | } |
1378 | addr = (start & ~mask) | (val & mask); | 1402 | addr = (start & ~mask) | (val & mask); |
@@ -1388,49 +1412,68 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1388 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1412 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1389 | struct vif_params *params) | 1413 | struct vif_params *params) |
1390 | { | 1414 | { |
1391 | struct net_device *ndev; | 1415 | struct net_device *ndev = NULL; |
1392 | struct ieee80211_sub_if_data *sdata = NULL; | 1416 | struct ieee80211_sub_if_data *sdata = NULL; |
1393 | int ret, i; | 1417 | int ret, i; |
1394 | int txqs = 1; | 1418 | int txqs = 1; |
1395 | 1419 | ||
1396 | ASSERT_RTNL(); | 1420 | ASSERT_RTNL(); |
1397 | 1421 | ||
1398 | if (local->hw.queues >= IEEE80211_NUM_ACS) | 1422 | if (type == NL80211_IFTYPE_P2P_DEVICE) { |
1399 | txqs = IEEE80211_NUM_ACS; | 1423 | struct wireless_dev *wdev; |
1400 | 1424 | ||
1401 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, | 1425 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, |
1402 | name, ieee80211_if_setup, txqs, 1); | 1426 | GFP_KERNEL); |
1403 | if (!ndev) | 1427 | if (!sdata) |
1404 | return -ENOMEM; | 1428 | return -ENOMEM; |
1405 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1429 | wdev = &sdata->wdev; |
1406 | 1430 | ||
1407 | ndev->needed_headroom = local->tx_headroom + | 1431 | sdata->dev = NULL; |
1408 | 4*6 /* four MAC addresses */ | 1432 | strlcpy(sdata->name, name, IFNAMSIZ); |
1409 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 1433 | ieee80211_assign_perm_addr(local, wdev->address, type); |
1410 | + 6 /* mesh */ | 1434 | memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); |
1411 | + 8 /* rfc1042/bridge tunnel */ | 1435 | } else { |
1412 | - ETH_HLEN /* ethernet hard_header_len */ | 1436 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
1413 | + IEEE80211_ENCRYPT_HEADROOM; | 1437 | txqs = IEEE80211_NUM_ACS; |
1414 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | 1438 | |
1415 | 1439 | ndev = alloc_netdev_mqs(sizeof(*sdata) + | |
1416 | ret = dev_alloc_name(ndev, ndev->name); | 1440 | local->hw.vif_data_size, |
1417 | if (ret < 0) | 1441 | name, ieee80211_if_setup, txqs, 1); |
1418 | goto fail; | 1442 | if (!ndev) |
1419 | 1443 | return -ENOMEM; | |
1420 | ieee80211_assign_perm_addr(local, ndev, type); | 1444 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
1421 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | 1445 | |
1422 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 1446 | ndev->needed_headroom = local->tx_headroom + |
1423 | 1447 | 4*6 /* four MAC addresses */ | |
1424 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 1448 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ |
1425 | sdata = netdev_priv(ndev); | 1449 | + 6 /* mesh */ |
1426 | ndev->ieee80211_ptr = &sdata->wdev; | 1450 | + 8 /* rfc1042/bridge tunnel */ |
1427 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | 1451 | - ETH_HLEN /* ethernet hard_header_len */ |
1428 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | 1452 | + IEEE80211_ENCRYPT_HEADROOM; |
1453 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
1454 | |||
1455 | ret = dev_alloc_name(ndev, ndev->name); | ||
1456 | if (ret < 0) { | ||
1457 | free_netdev(ndev); | ||
1458 | return ret; | ||
1459 | } | ||
1460 | |||
1461 | ieee80211_assign_perm_addr(local, ndev->perm_addr, type); | ||
1462 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | ||
1463 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | ||
1464 | |||
1465 | /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ | ||
1466 | sdata = netdev_priv(ndev); | ||
1467 | ndev->ieee80211_ptr = &sdata->wdev; | ||
1468 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
1469 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
1470 | |||
1471 | sdata->dev = ndev; | ||
1472 | } | ||
1429 | 1473 | ||
1430 | /* initialise type-independent data */ | 1474 | /* initialise type-independent data */ |
1431 | sdata->wdev.wiphy = local->hw.wiphy; | 1475 | sdata->wdev.wiphy = local->hw.wiphy; |
1432 | sdata->local = local; | 1476 | sdata->local = local; |
1433 | sdata->dev = ndev; | ||
1434 | #ifdef CONFIG_INET | 1477 | #ifdef CONFIG_INET |
1435 | sdata->arp_filter_state = true; | 1478 | sdata->arp_filter_state = true; |
1436 | #endif | 1479 | #endif |
@@ -1459,17 +1502,21 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1459 | /* setup type-dependent data */ | 1502 | /* setup type-dependent data */ |
1460 | ieee80211_setup_sdata(sdata, type); | 1503 | ieee80211_setup_sdata(sdata, type); |
1461 | 1504 | ||
1462 | if (params) { | 1505 | if (ndev) { |
1463 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; | 1506 | if (params) { |
1464 | if (type == NL80211_IFTYPE_STATION) | 1507 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; |
1465 | sdata->u.mgd.use_4addr = params->use_4addr; | 1508 | if (type == NL80211_IFTYPE_STATION) |
1466 | } | 1509 | sdata->u.mgd.use_4addr = params->use_4addr; |
1510 | } | ||
1467 | 1511 | ||
1468 | ndev->features |= local->hw.netdev_features; | 1512 | ndev->features |= local->hw.netdev_features; |
1469 | 1513 | ||
1470 | ret = register_netdevice(ndev); | 1514 | ret = register_netdevice(ndev); |
1471 | if (ret) | 1515 | if (ret) { |
1472 | goto fail; | 1516 | free_netdev(ndev); |
1517 | return ret; | ||
1518 | } | ||
1519 | } | ||
1473 | 1520 | ||
1474 | mutex_lock(&local->iflist_mtx); | 1521 | mutex_lock(&local->iflist_mtx); |
1475 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1522 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
@@ -1479,10 +1526,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1479 | *new_wdev = &sdata->wdev; | 1526 | *new_wdev = &sdata->wdev; |
1480 | 1527 | ||
1481 | return 0; | 1528 | return 0; |
1482 | |||
1483 | fail: | ||
1484 | free_netdev(ndev); | ||
1485 | return ret; | ||
1486 | } | 1529 | } |
1487 | 1530 | ||
1488 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | 1531 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
@@ -1494,7 +1537,21 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1494 | mutex_unlock(&sdata->local->iflist_mtx); | 1537 | mutex_unlock(&sdata->local->iflist_mtx); |
1495 | 1538 | ||
1496 | synchronize_rcu(); | 1539 | synchronize_rcu(); |
1497 | unregister_netdevice(sdata->dev); | 1540 | |
1541 | if (sdata->dev) { | ||
1542 | unregister_netdevice(sdata->dev); | ||
1543 | } else { | ||
1544 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1545 | kfree(sdata); | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | ||
1550 | { | ||
1551 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) | ||
1552 | return; | ||
1553 | ieee80211_do_stop(sdata, true); | ||
1554 | ieee80211_teardown_sdata(sdata); | ||
1498 | } | 1555 | } |
1499 | 1556 | ||
1500 | /* | 1557 | /* |
@@ -1505,6 +1562,7 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1505 | { | 1562 | { |
1506 | struct ieee80211_sub_if_data *sdata, *tmp; | 1563 | struct ieee80211_sub_if_data *sdata, *tmp; |
1507 | LIST_HEAD(unreg_list); | 1564 | LIST_HEAD(unreg_list); |
1565 | LIST_HEAD(wdev_list); | ||
1508 | 1566 | ||
1509 | ASSERT_RTNL(); | 1567 | ASSERT_RTNL(); |
1510 | 1568 | ||
@@ -1512,11 +1570,20 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1512 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1570 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1513 | list_del(&sdata->list); | 1571 | list_del(&sdata->list); |
1514 | 1572 | ||
1515 | unregister_netdevice_queue(sdata->dev, &unreg_list); | 1573 | if (sdata->dev) |
1574 | unregister_netdevice_queue(sdata->dev, &unreg_list); | ||
1575 | else | ||
1576 | list_add(&sdata->list, &wdev_list); | ||
1516 | } | 1577 | } |
1517 | mutex_unlock(&local->iflist_mtx); | 1578 | mutex_unlock(&local->iflist_mtx); |
1518 | unregister_netdevice_many(&unreg_list); | 1579 | unregister_netdevice_many(&unreg_list); |
1519 | list_del(&unreg_list); | 1580 | list_del(&unreg_list); |
1581 | |||
1582 | list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { | ||
1583 | list_del(&sdata->list); | ||
1584 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1585 | kfree(sdata); | ||
1586 | } | ||
1520 | } | 1587 | } |
1521 | 1588 | ||
1522 | static int netdev_notify(struct notifier_block *nb, | 1589 | static int netdev_notify(struct notifier_block *nb, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c26e231c733a..e706f9e5b051 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -207,6 +207,10 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
207 | sdata->vif.bss_conf.bssid = NULL; | 207 | sdata->vif.bss_conf.bssid = NULL; |
208 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 208 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
209 | sdata->vif.bss_conf.bssid = zero; | 209 | sdata->vif.bss_conf.bssid = zero; |
210 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
211 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
212 | WARN_ONCE(changed & ~(BSS_CHANGED_IDLE), | ||
213 | "P2P Device BSS changed %#x", changed); | ||
210 | } else { | 214 | } else { |
211 | WARN_ON(1); | 215 | WARN_ON(1); |
212 | return; | 216 | return; |
@@ -514,6 +518,11 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
514 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 518 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
515 | BIT(IEEE80211_STYPE_DEAUTH >> 4), | 519 | BIT(IEEE80211_STYPE_DEAUTH >> 4), |
516 | }, | 520 | }, |
521 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
522 | .tx = 0xffff, | ||
523 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
524 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
525 | }, | ||
517 | }; | 526 | }; |
518 | 527 | ||
519 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | 528 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 635c3250c668..507121dad082 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -116,6 +116,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
116 | if (!ieee80211_sdata_running(sdata)) | 116 | if (!ieee80211_sdata_running(sdata)) |
117 | continue; | 117 | continue; |
118 | 118 | ||
119 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
120 | continue; | ||
121 | |||
119 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 122 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
120 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 123 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
121 | 124 | ||
@@ -144,6 +147,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
144 | 147 | ||
145 | mutex_lock(&local->iflist_mtx); | 148 | mutex_lock(&local->iflist_mtx); |
146 | list_for_each_entry(sdata, &local->interfaces, list) { | 149 | list_for_each_entry(sdata, &local->interfaces, list) { |
150 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
151 | continue; | ||
152 | |||
147 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 153 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
148 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 154 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
149 | 155 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 78bf6c7e80c8..f5258ebc15be 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2812,8 +2812,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2812 | if (!bssid) { | 2812 | if (!bssid) { |
2813 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | 2813 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) |
2814 | return 0; | 2814 | return 0; |
2815 | } else if (!ieee80211_bssid_match(bssid, | 2815 | } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { |
2816 | sdata->vif.addr)) { | ||
2817 | /* | 2816 | /* |
2818 | * Accept public action frames even when the | 2817 | * Accept public action frames even when the |
2819 | * BSSID doesn't match, this is used for P2P | 2818 | * BSSID doesn't match, this is used for P2P |
@@ -2833,9 +2832,18 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2833 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) | 2832 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) |
2834 | return 0; | 2833 | return 0; |
2835 | break; | 2834 | break; |
2835 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2836 | if (!ieee80211_is_public_action(hdr, skb->len) && | ||
2837 | !ieee80211_is_probe_req(hdr->frame_control) && | ||
2838 | !ieee80211_is_probe_resp(hdr->frame_control) && | ||
2839 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2840 | return 0; | ||
2841 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
2842 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
2843 | break; | ||
2836 | default: | 2844 | default: |
2837 | /* should never get here */ | 2845 | /* should never get here */ |
2838 | WARN_ON(1); | 2846 | WARN_ON_ONCE(1); |
2839 | break; | 2847 | break; |
2840 | } | 2848 | } |
2841 | 2849 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8cd72914cdaf..b0801b7d572d 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -519,19 +519,27 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
519 | u64 cookie = (unsigned long)skb; | 519 | u64 cookie = (unsigned long)skb; |
520 | acked = info->flags & IEEE80211_TX_STAT_ACK; | 520 | acked = info->flags & IEEE80211_TX_STAT_ACK; |
521 | 521 | ||
522 | /* | ||
523 | * TODO: When we have non-netdev frame TX, | ||
524 | * we cannot use skb->dev->ieee80211_ptr | ||
525 | */ | ||
526 | |||
527 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 522 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
528 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 523 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
529 | cfg80211_probe_status(skb->dev, hdr->addr1, | 524 | cfg80211_probe_status(skb->dev, hdr->addr1, |
530 | cookie, acked, GFP_ATOMIC); | 525 | cookie, acked, GFP_ATOMIC); |
531 | else | 526 | } else if (skb->dev) { |
532 | cfg80211_mgmt_tx_status( | 527 | cfg80211_mgmt_tx_status( |
533 | skb->dev->ieee80211_ptr, cookie, skb->data, | 528 | skb->dev->ieee80211_ptr, cookie, skb->data, |
534 | skb->len, acked, GFP_ATOMIC); | 529 | skb->len, acked, GFP_ATOMIC); |
530 | } else { | ||
531 | struct ieee80211_sub_if_data *p2p_sdata; | ||
532 | |||
533 | rcu_read_lock(); | ||
534 | |||
535 | p2p_sdata = rcu_dereference(local->p2p_sdata); | ||
536 | if (p2p_sdata) { | ||
537 | cfg80211_mgmt_tx_status( | ||
538 | &p2p_sdata->wdev, cookie, skb->data, | ||
539 | skb->len, acked, GFP_ATOMIC); | ||
540 | } | ||
541 | rcu_read_unlock(); | ||
542 | } | ||
535 | } | 543 | } |
536 | 544 | ||
537 | if (unlikely(info->ack_frame_id)) { | 545 | if (unlikely(info->ack_frame_id)) { |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index c6d33b55b2df..65e9a2a1a3e1 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -24,7 +24,7 @@ | |||
24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
26 | __entry->p2p = sdata->vif.p2p; \ | 26 | __entry->p2p = sdata->vif.p2p; \ |
27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) |
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9a4e4e30ea6c..79bce870ad78 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -276,6 +276,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
277 | int ac; | 277 | int ac; |
278 | 278 | ||
279 | if (!sdata->dev) | ||
280 | continue; | ||
281 | |||
279 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | 282 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) |
280 | continue; | 283 | continue; |
281 | 284 | ||
@@ -364,6 +367,9 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
364 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 367 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
365 | int ac; | 368 | int ac; |
366 | 369 | ||
370 | if (!sdata->dev) | ||
371 | continue; | ||
372 | |||
367 | for (ac = 0; ac < n_acs; ac++) { | 373 | for (ac = 0; ac < n_acs; ac++) { |
368 | if (sdata->vif.hw_queue[ac] == queue || | 374 | if (sdata->vif.hw_queue[ac] == queue || |
369 | sdata->vif.cab_queue == queue) | 375 | sdata->vif.cab_queue == queue) |
@@ -902,7 +908,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
902 | drv_conf_tx(local, sdata, ac, &qparam); | 908 | drv_conf_tx(local, sdata, ac, &qparam); |
903 | } | 909 | } |
904 | 910 | ||
905 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 911 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && |
912 | sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { | ||
906 | sdata->vif.bss_conf.qos = enable_qos; | 913 | sdata->vif.bss_conf.qos = enable_qos; |
907 | if (bss_notify) | 914 | if (bss_notify) |
908 | ieee80211_bss_info_change_notify(sdata, | 915 | ieee80211_bss_info_change_notify(sdata, |
@@ -1391,7 +1398,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1391 | /* ignore virtual */ | 1398 | /* ignore virtual */ |
1392 | break; | 1399 | break; |
1393 | case NL80211_IFTYPE_P2P_DEVICE: | 1400 | case NL80211_IFTYPE_P2P_DEVICE: |
1394 | /* not yet supported */ | 1401 | changed = BSS_CHANGED_IDLE; |
1402 | break; | ||
1395 | case NL80211_IFTYPE_UNSPECIFIED: | 1403 | case NL80211_IFTYPE_UNSPECIFIED: |
1396 | case NUM_NL80211_IFTYPES: | 1404 | case NUM_NL80211_IFTYPES: |
1397 | case NL80211_IFTYPE_P2P_CLIENT: | 1405 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -1578,6 +1586,8 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) | |||
1578 | list_for_each_entry(sdata, &local->interfaces, list) { | 1586 | list_for_each_entry(sdata, &local->interfaces, list) { |
1579 | if (!ieee80211_sdata_running(sdata)) | 1587 | if (!ieee80211_sdata_running(sdata)) |
1580 | continue; | 1588 | continue; |
1589 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
1590 | continue; | ||
1581 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1591 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1582 | goto set; | 1592 | goto set; |
1583 | 1593 | ||