aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c7
-rw-r--r--net/wireless/core.c53
-rw-r--r--net/wireless/mlme.c10
-rw-r--r--net/wireless/nl80211.c122
-rw-r--r--net/wireless/radiotap.c2
-rw-r--r--net/wireless/util.c36
6 files changed, 201 insertions, 29 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index d355f67d0cdd..2f876b9ee344 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -105,7 +105,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
105 105
106 ASSERT_WDEV_LOCK(wdev); 106 ASSERT_WDEV_LOCK(wdev);
107 107
108 if (!netif_running(wdev->netdev)) 108 if (wdev->netdev && !netif_running(wdev->netdev))
109 return; 109 return;
110 110
111 switch (wdev->iftype) { 111 switch (wdev->iftype) {
@@ -143,6 +143,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
143 case NL80211_IFTYPE_WDS: 143 case NL80211_IFTYPE_WDS:
144 /* these interface types don't really have a channel */ 144 /* these interface types don't really have a channel */
145 return; 145 return;
146 case NL80211_IFTYPE_P2P_DEVICE:
147 if (wdev->wiphy->features &
148 NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL)
149 *chanmode = CHAN_MODE_EXCLUSIVE;
150 return;
146 case NL80211_IFTYPE_UNSPECIFIED: 151 case NL80211_IFTYPE_UNSPECIFIED:
147 case NUM_NL80211_IFTYPES: 152 case NUM_NL80211_IFTYPES:
148 WARN_ON(1); 153 WARN_ON(1);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index dcd64d5b07aa..443d4d7deea2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -230,9 +230,24 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
230 rtnl_lock(); 230 rtnl_lock();
231 mutex_lock(&rdev->devlist_mtx); 231 mutex_lock(&rdev->devlist_mtx);
232 232
233 list_for_each_entry(wdev, &rdev->wdev_list, list) 233 list_for_each_entry(wdev, &rdev->wdev_list, list) {
234 if (wdev->netdev) 234 if (wdev->netdev) {
235 dev_close(wdev->netdev); 235 dev_close(wdev->netdev);
236 continue;
237 }
238 /* otherwise, check iftype */
239 switch (wdev->iftype) {
240 case NL80211_IFTYPE_P2P_DEVICE:
241 if (!wdev->p2p_started)
242 break;
243 rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
244 wdev->p2p_started = false;
245 rdev->opencount--;
246 break;
247 default:
248 break;
249 }
250 }
236 251
237 mutex_unlock(&rdev->devlist_mtx); 252 mutex_unlock(&rdev->devlist_mtx);
238 rtnl_unlock(); 253 rtnl_unlock();
@@ -407,6 +422,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
407 if (WARN_ON(wiphy->software_iftypes & types)) 422 if (WARN_ON(wiphy->software_iftypes & types))
408 return -EINVAL; 423 return -EINVAL;
409 424
425 /* Only a single P2P_DEVICE can be allowed */
426 if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
427 c->limits[j].max > 1))
428 return -EINVAL;
429
410 cnt += c->limits[j].max; 430 cnt += c->limits[j].max;
411 /* 431 /*
412 * Don't advertise an unsupported type 432 * Don't advertise an unsupported type
@@ -734,6 +754,35 @@ static void wdev_cleanup_work(struct work_struct *work)
734 dev_put(wdev->netdev); 754 dev_put(wdev->netdev);
735} 755}
736 756
757void cfg80211_unregister_wdev(struct wireless_dev *wdev)
758{
759 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
760
761 ASSERT_RTNL();
762
763 if (WARN_ON(wdev->netdev))
764 return;
765
766 mutex_lock(&rdev->devlist_mtx);
767 list_del_rcu(&wdev->list);
768 rdev->devlist_generation++;
769
770 switch (wdev->iftype) {
771 case NL80211_IFTYPE_P2P_DEVICE:
772 if (!wdev->p2p_started)
773 break;
774 rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
775 wdev->p2p_started = false;
776 rdev->opencount--;
777 break;
778 default:
779 WARN_ON_ONCE(1);
780 break;
781 }
782 mutex_unlock(&rdev->devlist_mtx);
783}
784EXPORT_SYMBOL(cfg80211_unregister_wdev);
785
737static struct device_type wiphy_type = { 786static struct device_type wiphy_type = {
738 .name = "wlan", 787 .name = "wlan",
739}; 788};
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 1cdb1d5e6b0f..8fd0242ee169 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -736,7 +736,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
736 const u8 *buf, size_t len, bool no_cck, 736 const u8 *buf, size_t len, bool no_cck,
737 bool dont_wait_for_ack, u64 *cookie) 737 bool dont_wait_for_ack, u64 *cookie)
738{ 738{
739 struct net_device *dev = wdev->netdev;
740 const struct ieee80211_mgmt *mgmt; 739 const struct ieee80211_mgmt *mgmt;
741 u16 stype; 740 u16 stype;
742 741
@@ -796,7 +795,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
796 case NL80211_IFTYPE_AP: 795 case NL80211_IFTYPE_AP:
797 case NL80211_IFTYPE_P2P_GO: 796 case NL80211_IFTYPE_P2P_GO:
798 case NL80211_IFTYPE_AP_VLAN: 797 case NL80211_IFTYPE_AP_VLAN:
799 if (!ether_addr_equal(mgmt->bssid, dev->dev_addr)) 798 if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev)))
800 err = -EINVAL; 799 err = -EINVAL;
801 break; 800 break;
802 case NL80211_IFTYPE_MESH_POINT: 801 case NL80211_IFTYPE_MESH_POINT:
@@ -809,6 +808,11 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
809 * cfg80211 doesn't track the stations 808 * cfg80211 doesn't track the stations
810 */ 809 */
811 break; 810 break;
811 case NL80211_IFTYPE_P2P_DEVICE:
812 /*
813 * fall through, P2P device only supports
814 * public action frames
815 */
812 default: 816 default:
813 err = -EOPNOTSUPP; 817 err = -EOPNOTSUPP;
814 break; 818 break;
@@ -819,7 +823,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
819 return err; 823 return err;
820 } 824 }
821 825
822 if (!ether_addr_equal(mgmt->sa, dev->dev_addr)) 826 if (!ether_addr_equal(mgmt->sa, wdev_address(wdev)))
823 return -EINVAL; 827 return -EINVAL;
824 828
825 /* Transmit the Action frame as requested by user space */ 829 /* Transmit the Action frame as requested by user space */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 97026f3b215a..787aeaa902fe 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1100,6 +1100,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1100 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) 1100 if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS))
1101 goto nla_put_failure; 1101 goto nla_put_failure;
1102 } 1102 }
1103 CMD(start_p2p_device, START_P2P_DEVICE);
1103 1104
1104#ifdef CONFIG_NL80211_TESTMODE 1105#ifdef CONFIG_NL80211_TESTMODE
1105 CMD(testmode_cmd, TESTMODE); 1106 CMD(testmode_cmd, TESTMODE);
@@ -1748,13 +1749,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1748 1749
1749 if (dev && 1750 if (dev &&
1750 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || 1751 (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
1751 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) || 1752 nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name)))
1752 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dev->dev_addr)))
1753 goto nla_put_failure; 1753 goto nla_put_failure;
1754 1754
1755 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || 1755 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
1756 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || 1756 nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
1757 nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || 1757 nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
1758 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
1758 nla_put_u32(msg, NL80211_ATTR_GENERATION, 1759 nla_put_u32(msg, NL80211_ATTR_GENERATION,
1759 rdev->devlist_generation ^ 1760 rdev->devlist_generation ^
1760 (cfg80211_rdev_list_generation << 2))) 1761 (cfg80211_rdev_list_generation << 2)))
@@ -2021,8 +2022,10 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
2021 return PTR_ERR(wdev); 2022 return PTR_ERR(wdev);
2022 } 2023 }
2023 2024
2024 if (type == NL80211_IFTYPE_MESH_POINT && 2025 switch (type) {
2025 info->attrs[NL80211_ATTR_MESH_ID]) { 2026 case NL80211_IFTYPE_MESH_POINT:
2027 if (!info->attrs[NL80211_ATTR_MESH_ID])
2028 break;
2026 wdev_lock(wdev); 2029 wdev_lock(wdev);
2027 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != 2030 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
2028 IEEE80211_MAX_MESH_ID_LEN); 2031 IEEE80211_MAX_MESH_ID_LEN);
@@ -2031,6 +2034,26 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
2031 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), 2034 memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
2032 wdev->mesh_id_up_len); 2035 wdev->mesh_id_up_len);
2033 wdev_unlock(wdev); 2036 wdev_unlock(wdev);
2037 break;
2038 case NL80211_IFTYPE_P2P_DEVICE:
2039 /*
2040 * P2P Device doesn't have a netdev, so doesn't go
2041 * through the netdev notifier and must be added here
2042 */
2043 mutex_init(&wdev->mtx);
2044 INIT_LIST_HEAD(&wdev->event_list);
2045 spin_lock_init(&wdev->event_lock);
2046 INIT_LIST_HEAD(&wdev->mgmt_registrations);
2047 spin_lock_init(&wdev->mgmt_registrations_lock);
2048
2049 mutex_lock(&rdev->devlist_mtx);
2050 wdev->identifier = ++rdev->wdev_id;
2051 list_add_rcu(&wdev->list, &rdev->wdev_list);
2052 rdev->devlist_generation++;
2053 mutex_unlock(&rdev->devlist_mtx);
2054 break;
2055 default:
2056 break;
2034 } 2057 }
2035 2058
2036 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, 2059 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0,
@@ -6053,6 +6076,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
6053 case NL80211_IFTYPE_AP_VLAN: 6076 case NL80211_IFTYPE_AP_VLAN:
6054 case NL80211_IFTYPE_MESH_POINT: 6077 case NL80211_IFTYPE_MESH_POINT:
6055 case NL80211_IFTYPE_P2P_GO: 6078 case NL80211_IFTYPE_P2P_GO:
6079 case NL80211_IFTYPE_P2P_DEVICE:
6056 break; 6080 break;
6057 default: 6081 default:
6058 return -EOPNOTSUPP; 6082 return -EOPNOTSUPP;
@@ -6099,6 +6123,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
6099 case NL80211_IFTYPE_AP_VLAN: 6123 case NL80211_IFTYPE_AP_VLAN:
6100 case NL80211_IFTYPE_MESH_POINT: 6124 case NL80211_IFTYPE_MESH_POINT:
6101 case NL80211_IFTYPE_P2P_GO: 6125 case NL80211_IFTYPE_P2P_GO:
6126 case NL80211_IFTYPE_P2P_DEVICE:
6102 break; 6127 break;
6103 default: 6128 default:
6104 return -EOPNOTSUPP; 6129 return -EOPNOTSUPP;
@@ -6195,6 +6220,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
6195 case NL80211_IFTYPE_AP: 6220 case NL80211_IFTYPE_AP:
6196 case NL80211_IFTYPE_AP_VLAN: 6221 case NL80211_IFTYPE_AP_VLAN:
6197 case NL80211_IFTYPE_P2P_GO: 6222 case NL80211_IFTYPE_P2P_GO:
6223 case NL80211_IFTYPE_P2P_DEVICE:
6198 break; 6224 break;
6199 default: 6225 default:
6200 return -EOPNOTSUPP; 6226 return -EOPNOTSUPP;
@@ -6810,6 +6836,68 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
6810 return 0; 6836 return 0;
6811} 6837}
6812 6838
6839static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
6840{
6841 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6842 struct wireless_dev *wdev = info->user_ptr[1];
6843 int err;
6844
6845 if (!rdev->ops->start_p2p_device)
6846 return -EOPNOTSUPP;
6847
6848 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
6849 return -EOPNOTSUPP;
6850
6851 if (wdev->p2p_started)
6852 return 0;
6853
6854 mutex_lock(&rdev->devlist_mtx);
6855 err = cfg80211_can_add_interface(rdev, wdev->iftype);
6856 mutex_unlock(&rdev->devlist_mtx);
6857 if (err)
6858 return err;
6859
6860 err = rdev->ops->start_p2p_device(&rdev->wiphy, wdev);
6861 if (err)
6862 return err;
6863
6864 wdev->p2p_started = true;
6865 mutex_lock(&rdev->devlist_mtx);
6866 rdev->opencount++;
6867 mutex_unlock(&rdev->devlist_mtx);
6868
6869 return 0;
6870}
6871
6872static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
6873{
6874 struct cfg80211_registered_device *rdev = info->user_ptr[0];
6875 struct wireless_dev *wdev = info->user_ptr[1];
6876
6877 if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
6878 return -EOPNOTSUPP;
6879
6880 if (!rdev->ops->stop_p2p_device)
6881 return -EOPNOTSUPP;
6882
6883 if (!wdev->p2p_started)
6884 return 0;
6885
6886 rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
6887 wdev->p2p_started = false;
6888
6889 mutex_lock(&rdev->devlist_mtx);
6890 rdev->opencount--;
6891 mutex_unlock(&rdev->devlist_mtx);
6892
6893 if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
6894 rdev->scan_req->aborted = true;
6895 ___cfg80211_scan_done(rdev, true);
6896 }
6897
6898 return 0;
6899}
6900
6813#define NL80211_FLAG_NEED_WIPHY 0x01 6901#define NL80211_FLAG_NEED_WIPHY 0x01
6814#define NL80211_FLAG_NEED_NETDEV 0x02 6902#define NL80211_FLAG_NEED_NETDEV 0x02
6815#define NL80211_FLAG_NEED_RTNL 0x04 6903#define NL80211_FLAG_NEED_RTNL 0x04
@@ -6817,7 +6905,7 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
6817#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ 6905#define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\
6818 NL80211_FLAG_CHECK_NETDEV_UP) 6906 NL80211_FLAG_CHECK_NETDEV_UP)
6819#define NL80211_FLAG_NEED_WDEV 0x10 6907#define NL80211_FLAG_NEED_WDEV 0x10
6820/* If a netdev is associated, it must be UP */ 6908/* If a netdev is associated, it must be UP, P2P must be started */
6821#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ 6909#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
6822 NL80211_FLAG_CHECK_NETDEV_UP) 6910 NL80211_FLAG_CHECK_NETDEV_UP)
6823 6911
@@ -6878,6 +6966,13 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
6878 } 6966 }
6879 6967
6880 dev_hold(dev); 6968 dev_hold(dev);
6969 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
6970 if (!wdev->p2p_started) {
6971 mutex_unlock(&cfg80211_mutex);
6972 if (rtnl)
6973 rtnl_unlock();
6974 return -ENETDOWN;
6975 }
6881 } 6976 }
6882 6977
6883 cfg80211_lock_rdev(rdev); 6978 cfg80211_lock_rdev(rdev);
@@ -7439,7 +7534,22 @@ static struct genl_ops nl80211_ops[] = {
7439 .internal_flags = NL80211_FLAG_NEED_NETDEV | 7534 .internal_flags = NL80211_FLAG_NEED_NETDEV |
7440 NL80211_FLAG_NEED_RTNL, 7535 NL80211_FLAG_NEED_RTNL,
7441 }, 7536 },
7442 7537 {
7538 .cmd = NL80211_CMD_START_P2P_DEVICE,
7539 .doit = nl80211_start_p2p_device,
7540 .policy = nl80211_policy,
7541 .flags = GENL_ADMIN_PERM,
7542 .internal_flags = NL80211_FLAG_NEED_WDEV |
7543 NL80211_FLAG_NEED_RTNL,
7544 },
7545 {
7546 .cmd = NL80211_CMD_STOP_P2P_DEVICE,
7547 .doit = nl80211_stop_p2p_device,
7548 .policy = nl80211_policy,
7549 .flags = GENL_ADMIN_PERM,
7550 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
7551 NL80211_FLAG_NEED_RTNL,
7552 },
7443}; 7553};
7444 7554
7445static struct genl_multicast_group nl80211_mlme_mcgrp = { 7555static struct genl_multicast_group nl80211_mlme_mcgrp = {
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index c4ad7958af52..7d604c06c3dc 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -41,6 +41,8 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = {
41 [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, 41 [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
42 [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, 42 [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
43 [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, 43 [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
44 [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
45 [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
44 /* 46 /*
45 * add more here as they are defined in radiotap.h 47 * add more here as they are defined in radiotap.h
46 */ 48 */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 994e2f0cc7a8..ef35f4ef2aa6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -684,22 +684,10 @@ EXPORT_SYMBOL(cfg80211_classify8021d);
684 684
685const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) 685const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie)
686{ 686{
687 u8 *end, *pos; 687 if (bss->information_elements == NULL)
688
689 pos = bss->information_elements;
690 if (pos == NULL)
691 return NULL; 688 return NULL;
692 end = pos + bss->len_information_elements; 689 return cfg80211_find_ie(ie, bss->information_elements,
693 690 bss->len_information_elements);
694 while (pos + 1 < end) {
695 if (pos + 2 + pos[1] > end)
696 break;
697 if (pos[0] == ie)
698 return pos;
699 pos += 2 + pos[1];
700 }
701
702 return NULL;
703} 691}
704EXPORT_SYMBOL(ieee80211_bss_get_ie); 692EXPORT_SYMBOL(ieee80211_bss_get_ie);
705 693
@@ -812,6 +800,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
812 if (otype == NL80211_IFTYPE_AP_VLAN) 800 if (otype == NL80211_IFTYPE_AP_VLAN)
813 return -EOPNOTSUPP; 801 return -EOPNOTSUPP;
814 802
803 /* cannot change into P2P device type */
804 if (ntype == NL80211_IFTYPE_P2P_DEVICE)
805 return -EOPNOTSUPP;
806
815 if (!rdev->ops->change_virtual_intf || 807 if (!rdev->ops->change_virtual_intf ||
816 !(rdev->wiphy.interface_modes & (1 << ntype))) 808 !(rdev->wiphy.interface_modes & (1 << ntype)))
817 return -EOPNOTSUPP; 809 return -EOPNOTSUPP;
@@ -889,6 +881,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
889 case NUM_NL80211_IFTYPES: 881 case NUM_NL80211_IFTYPES:
890 /* not happening */ 882 /* not happening */
891 break; 883 break;
884 case NL80211_IFTYPE_P2P_DEVICE:
885 WARN_ON(1);
886 break;
892 } 887 }
893 } 888 }
894 889
@@ -1053,8 +1048,15 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1053 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { 1048 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
1054 if (wdev_iter == wdev) 1049 if (wdev_iter == wdev)
1055 continue; 1050 continue;
1056 if (!netif_running(wdev_iter->netdev)) 1051 if (wdev_iter->netdev) {
1057 continue; 1052 if (!netif_running(wdev_iter->netdev))
1053 continue;
1054 } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1055 if (!wdev_iter->p2p_started)
1056 continue;
1057 } else {
1058 WARN_ON(1);
1059 }
1058 1060
1059 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) 1061 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
1060 continue; 1062 continue;