aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-15 18:19:54 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-08-20 07:58:21 -0400
commit98104fdeda63d57631c9f89e90a7b83b58fcee40 (patch)
tree22d0f75c2f369fd02695ea8051ddc68e6f8b8390
parentcc74c0c7d6d623d0d3f13ef64895937edb7b3177 (diff)
cfg80211: add P2P Device abstraction
In order to support using a different MAC address for the P2P Device address we must first have a P2P Device abstraction that can be assigned a MAC address. This abstraction will also be useful to support offloading P2P operations to the device, e.g. periodic listen for discoverability. Currently, the driver is responsible for assigning a MAC address to the P2P Device, but this could be changed by allowing a MAC address to be given to the NEW_INTERFACE command. As it has no associated netdev, a P2P Device can only be identified by its wdev identifier but the previous patches allowed using the wdev identifier in various APIs, e.g. remain-on-channel. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/linux/nl80211.h30
-rw-r--r--include/net/cfg80211.h40
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/util.c2
-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/util.c18
9 files changed, 265 insertions, 20 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2f3878806403..458416279347 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -565,6 +565,14 @@
565 * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with 565 * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
566 * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. 566 * %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
567 * 567 *
568 * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
569 * its %NL80211_ATTR_WDEV identifier. It must have been created with
570 * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
571 * P2P Device can be used for P2P operations, e.g. remain-on-channel and
572 * public action frame TX.
573 * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by
574 * its %NL80211_ATTR_WDEV identifier.
575 *
568 * @NL80211_CMD_MAX: highest used command number 576 * @NL80211_CMD_MAX: highest used command number
569 * @__NL80211_CMD_AFTER_LAST: internal use 577 * @__NL80211_CMD_AFTER_LAST: internal use
570 */ 578 */
@@ -708,6 +716,9 @@ enum nl80211_commands {
708 716
709 NL80211_CMD_CH_SWITCH_NOTIFY, 717 NL80211_CMD_CH_SWITCH_NOTIFY,
710 718
719 NL80211_CMD_START_P2P_DEVICE,
720 NL80211_CMD_STOP_P2P_DEVICE,
721
711 /* add new commands above here */ 722 /* add new commands above here */
712 723
713 /* used to define NL80211_CMD_MAX below */ 724 /* used to define NL80211_CMD_MAX below */
@@ -1575,6 +1586,10 @@ enum nl80211_attrs {
1575 * @NL80211_IFTYPE_MESH_POINT: mesh point 1586 * @NL80211_IFTYPE_MESH_POINT: mesh point
1576 * @NL80211_IFTYPE_P2P_CLIENT: P2P client 1587 * @NL80211_IFTYPE_P2P_CLIENT: P2P client
1577 * @NL80211_IFTYPE_P2P_GO: P2P group owner 1588 * @NL80211_IFTYPE_P2P_GO: P2P group owner
1589 * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev
1590 * and therefore can't be created in the normal ways, use the
1591 * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
1592 * commands to create and destroy one
1578 * @NL80211_IFTYPE_MAX: highest interface type number currently defined 1593 * @NL80211_IFTYPE_MAX: highest interface type number currently defined
1579 * @NUM_NL80211_IFTYPES: number of defined interface types 1594 * @NUM_NL80211_IFTYPES: number of defined interface types
1580 * 1595 *
@@ -1593,6 +1608,7 @@ enum nl80211_iftype {
1593 NL80211_IFTYPE_MESH_POINT, 1608 NL80211_IFTYPE_MESH_POINT,
1594 NL80211_IFTYPE_P2P_CLIENT, 1609 NL80211_IFTYPE_P2P_CLIENT,
1595 NL80211_IFTYPE_P2P_GO, 1610 NL80211_IFTYPE_P2P_GO,
1611 NL80211_IFTYPE_P2P_DEVICE,
1596 1612
1597 /* keep last */ 1613 /* keep last */
1598 NUM_NL80211_IFTYPES, 1614 NUM_NL80211_IFTYPES,
@@ -2994,12 +3010,18 @@ enum nl80211_ap_sme_features {
2994 * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested 3010 * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
2995 * to work properly to suppport receiving regulatory hints from 3011 * to work properly to suppport receiving regulatory hints from
2996 * cellular base stations. 3012 * cellular base stations.
3013 * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active
3014 * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel
3015 * in the interface combinations, even when it's only used for scan
3016 * and remain-on-channel. This could be due to, for example, the
3017 * remain-on-channel implementation requiring a channel context.
2997 */ 3018 */
2998enum nl80211_feature_flags { 3019enum nl80211_feature_flags {
2999 NL80211_FEATURE_SK_TX_STATUS = 1 << 0, 3020 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
3000 NL80211_FEATURE_HT_IBSS = 1 << 1, 3021 NL80211_FEATURE_HT_IBSS = 1 << 1,
3001 NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, 3022 NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
3002 NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, 3023 NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
3024 NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
3003}; 3025};
3004 3026
3005/** 3027/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 493fa0c79005..4c518f1f1aca 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1437,7 +1437,8 @@ struct cfg80211_gtk_rekey_data {
1437 * @add_virtual_intf: create a new virtual interface with the given name, 1437 * @add_virtual_intf: create a new virtual interface with the given name,
1438 * must set the struct wireless_dev's iftype. Beware: You must create 1438 * must set the struct wireless_dev's iftype. Beware: You must create
1439 * the new netdev in the wiphy's network namespace! Returns the struct 1439 * the new netdev in the wiphy's network namespace! Returns the struct
1440 * wireless_dev, or an ERR_PTR. 1440 * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must
1441 * also set the address member in the wdev.
1441 * 1442 *
1442 * @del_virtual_intf: remove the virtual interface 1443 * @del_virtual_intf: remove the virtual interface
1443 * 1444 *
@@ -1616,6 +1617,9 @@ struct cfg80211_gtk_rekey_data {
1616 * @get_channel: Get the current operating channel for the virtual interface. 1617 * @get_channel: Get the current operating channel for the virtual interface.
1617 * For monitor interfaces, it should return %NULL unless there's a single 1618 * For monitor interfaces, it should return %NULL unless there's a single
1618 * current monitoring channel. 1619 * current monitoring channel.
1620 *
1621 * @start_p2p_device: Start the given P2P device.
1622 * @stop_p2p_device: Stop the given P2P device.
1619 */ 1623 */
1620struct cfg80211_ops { 1624struct cfg80211_ops {
1621 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); 1625 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1832,6 +1836,11 @@ struct cfg80211_ops {
1832 (*get_channel)(struct wiphy *wiphy, 1836 (*get_channel)(struct wiphy *wiphy,
1833 struct wireless_dev *wdev, 1837 struct wireless_dev *wdev,
1834 enum nl80211_channel_type *type); 1838 enum nl80211_channel_type *type);
1839
1840 int (*start_p2p_device)(struct wiphy *wiphy,
1841 struct wireless_dev *wdev);
1842 void (*stop_p2p_device)(struct wiphy *wiphy,
1843 struct wireless_dev *wdev);
1835}; 1844};
1836 1845
1837/* 1846/*
@@ -2395,6 +2404,8 @@ struct cfg80211_cached_keys;
2395 * @cleanup_work: work struct used for cleanup that can't be done directly 2404 * @cleanup_work: work struct used for cleanup that can't be done directly
2396 * @beacon_interval: beacon interval used on this device for transmitting 2405 * @beacon_interval: beacon interval used on this device for transmitting
2397 * beacons, 0 when not valid 2406 * beacons, 0 when not valid
2407 * @address: The address for this device, valid only if @netdev is %NULL
2408 * @p2p_started: true if this is a P2P Device that has been started
2398 */ 2409 */
2399struct wireless_dev { 2410struct wireless_dev {
2400 struct wiphy *wiphy; 2411 struct wiphy *wiphy;
@@ -2413,7 +2424,9 @@ struct wireless_dev {
2413 2424
2414 struct work_struct cleanup_work; 2425 struct work_struct cleanup_work;
2415 2426
2416 bool use_4addr; 2427 bool use_4addr, p2p_started;
2428
2429 u8 address[ETH_ALEN] __aligned(sizeof(u16));
2417 2430
2418 /* currently used for IBSS and SME - might be rearranged later */ 2431 /* currently used for IBSS and SME - might be rearranged later */
2419 u8 ssid[IEEE80211_MAX_SSID_LEN]; 2432 u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -2461,6 +2474,13 @@ struct wireless_dev {
2461#endif 2474#endif
2462}; 2475};
2463 2476
2477static inline u8 *wdev_address(struct wireless_dev *wdev)
2478{
2479 if (wdev->netdev)
2480 return wdev->netdev->dev_addr;
2481 return wdev->address;
2482}
2483
2464/** 2484/**
2465 * wdev_priv - return wiphy priv from wireless_dev 2485 * wdev_priv - return wiphy priv from wireless_dev
2466 * 2486 *
@@ -3528,6 +3548,22 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
3528 */ 3548 */
3529u32 cfg80211_calculate_bitrate(struct rate_info *rate); 3549u32 cfg80211_calculate_bitrate(struct rate_info *rate);
3530 3550
3551/**
3552 * cfg80211_unregister_wdev - remove the given wdev
3553 * @wdev: struct wireless_dev to remove
3554 *
3555 * Call this function only for wdevs that have no netdev assigned,
3556 * e.g. P2P Devices. It removes the device from the list so that
3557 * it can no longer be used. It is necessary to call this function
3558 * even when cfg80211 requests the removal of the interface by
3559 * calling the del_virtual_intf() callback. The function must also
3560 * be called when the driver wishes to unregister the wdev, e.g.
3561 * when the device is unbound from the driver.
3562 *
3563 * Requires the RTNL to be held.
3564 */
3565void cfg80211_unregister_wdev(struct wireless_dev *wdev);
3566
3531/* Logging, debugging and troubleshooting/diagnostic helpers. */ 3567/* Logging, debugging and troubleshooting/diagnostic helpers. */
3532 3568
3533/* wiphy_printk helpers, similar to dev_printk */ 3569/* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index fbab7a84ca21..366d9d3e84c4 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -449,6 +449,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
449 case NUM_NL80211_IFTYPES: 449 case NUM_NL80211_IFTYPES:
450 case NL80211_IFTYPE_P2P_CLIENT: 450 case NL80211_IFTYPE_P2P_CLIENT:
451 case NL80211_IFTYPE_P2P_GO: 451 case NL80211_IFTYPE_P2P_GO:
452 case NL80211_IFTYPE_P2P_DEVICE:
452 /* cannot happen */ 453 /* cannot happen */
453 WARN_ON(1); 454 WARN_ON(1);
454 break; 455 break;
@@ -1146,6 +1147,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
1146 case NL80211_IFTYPE_WDS: 1147 case NL80211_IFTYPE_WDS:
1147 case NL80211_IFTYPE_AP_VLAN: 1148 case NL80211_IFTYPE_AP_VLAN:
1148 break; 1149 break;
1150 case NL80211_IFTYPE_P2P_DEVICE:
1151 /* not yet supported */
1149 case NL80211_IFTYPE_UNSPECIFIED: 1152 case NL80211_IFTYPE_UNSPECIFIED:
1150 case NUM_NL80211_IFTYPES: 1153 case NUM_NL80211_IFTYPES:
1151 BUG(); 1154 BUG();
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 7dff94e43a0c..9a4e4e30ea6c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1390,6 +1390,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1390 case NL80211_IFTYPE_MONITOR: 1390 case NL80211_IFTYPE_MONITOR:
1391 /* ignore virtual */ 1391 /* ignore virtual */
1392 break; 1392 break;
1393 case NL80211_IFTYPE_P2P_DEVICE:
1394 /* not yet supported */
1393 case NL80211_IFTYPE_UNSPECIFIED: 1395 case NL80211_IFTYPE_UNSPECIFIED:
1394 case NUM_NL80211_IFTYPES: 1396 case NUM_NL80211_IFTYPES:
1395 case NL80211_IFTYPE_P2P_CLIENT: 1397 case NL80211_IFTYPE_P2P_CLIENT:
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 31b40cc4a9c3..91b300443f4b 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/util.c b/net/wireless/util.c
index ce393dd8c928..d7b672262b5f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -800,6 +800,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
800 if (otype == NL80211_IFTYPE_AP_VLAN) 800 if (otype == NL80211_IFTYPE_AP_VLAN)
801 return -EOPNOTSUPP; 801 return -EOPNOTSUPP;
802 802
803 /* cannot change into P2P device type */
804 if (ntype == NL80211_IFTYPE_P2P_DEVICE)
805 return -EOPNOTSUPP;
806
803 if (!rdev->ops->change_virtual_intf || 807 if (!rdev->ops->change_virtual_intf ||
804 !(rdev->wiphy.interface_modes & (1 << ntype))) 808 !(rdev->wiphy.interface_modes & (1 << ntype)))
805 return -EOPNOTSUPP; 809 return -EOPNOTSUPP;
@@ -877,6 +881,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
877 case NUM_NL80211_IFTYPES: 881 case NUM_NL80211_IFTYPES:
878 /* not happening */ 882 /* not happening */
879 break; 883 break;
884 case NL80211_IFTYPE_P2P_DEVICE:
885 WARN_ON(1);
886 break;
880 } 887 }
881 } 888 }
882 889
@@ -1041,8 +1048,15 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1041 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { 1048 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
1042 if (wdev_iter == wdev) 1049 if (wdev_iter == wdev)
1043 continue; 1050 continue;
1044 if (!netif_running(wdev_iter->netdev)) 1051 if (wdev_iter->netdev) {
1045 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 }
1046 1060
1047 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) 1061 if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
1048 continue; 1062 continue;