OSDN Git Service

cfg80211: make wdev_list accessible to drivers
authorJohannes Berg <johannes.berg@intel.com>
Tue, 3 May 2016 13:52:04 +0000 (16:52 +0300)
committerLior David <liord@codeaurora.org>
Thu, 17 Nov 2016 23:20:15 +0000 (01:20 +0200)
There's no harm in having drivers read the list, since they can
use RCU protection or RTNL locking; allow this to not require
each and every driver to also implement its own bookkeeping.

CRs-Fixed: 1087922
Change-Id: I2f38b8ba1ddbe6041a4189f5d9b72c982f0fb367
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
Git-commit: 53873f134d285191ef6435882d55837093a36c53
[liord@codeaurora.org: fix conflicts]
Signed-off-by: Lior David <liord@codeaurora.org>
include/net/cfg80211.h
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c

index b89c9c2..ab25e88 100644 (file)
@@ -3219,6 +3219,9 @@ struct wiphy_iftype_ext_capab {
  * @vht_capa_mod_mask:  Specify what VHT capabilities can be over-ridden.
  *     If null, then none can be over-ridden.
  *
+ * @wdev_list: the list of associated (virtual) interfaces; this list must
+ *     not be modified by the driver, but can be read with RTNL/RCU protection.
+ *
  * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
  *     supports for ACL.
  *
@@ -3363,6 +3366,8 @@ struct wiphy {
        const struct ieee80211_ht_cap *ht_capa_mod_mask;
        const struct ieee80211_vht_cap *vht_capa_mod_mask;
 
+       struct list_head wdev_list;
+
        /* the network namespace this phy lives in currently */
        possible_net_t _net;
 
index cf14c7e..d5ccaea 100644 (file)
@@ -749,7 +749,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
         * and thus fail the GO instantiation, consider only the interfaces of
         * the current registered device.
         */
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                struct ieee80211_channel *other_chan = NULL;
                int r1, r2;
 
index 6d34024..16043fa 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright 2006-2010         Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright 2015      Intel Deutschland GmbH
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -157,7 +158,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
        if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
                return -EOPNOTSUPP;
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (!wdev->netdev)
                        continue;
                wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
@@ -171,7 +172,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
                /* failed -- clean up to old netns */
                net = wiphy_net(&rdev->wiphy);
 
-               list_for_each_entry_continue_reverse(wdev, &rdev->wdev_list,
+               list_for_each_entry_continue_reverse(wdev,
+                                                    &rdev->wiphy.wdev_list,
                                                     list) {
                        if (!wdev->netdev)
                                continue;
@@ -230,7 +232,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
 
        ASSERT_RTNL();
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (wdev->netdev) {
                        dev_close(wdev->netdev);
                        continue;
@@ -298,7 +300,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
                kfree(item);
                spin_unlock_irq(&rdev->destroy_list_lock);
 
-               list_for_each_entry_safe(wdev, tmp, &rdev->wdev_list, list) {
+               list_for_each_entry_safe(wdev, tmp,
+                                        &rdev->wiphy.wdev_list, list) {
                        if (nlportid == wdev->owner_nlportid)
                                rdev_del_virtual_intf(rdev, wdev);
                }
@@ -400,7 +403,7 @@ use_default_name:
                dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
        }
 
-       INIT_LIST_HEAD(&rdev->wdev_list);
+       INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
        INIT_LIST_HEAD(&rdev->beacon_registrations);
        spin_lock_init(&rdev->beacon_registrations_lock);
        spin_lock_init(&rdev->bss_lock);
@@ -812,7 +815,7 @@ void wiphy_unregister(struct wiphy *wiphy)
        nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY);
        rdev->wiphy.registered = false;
 
-       WARN_ON(!list_empty(&rdev->wdev_list));
+       WARN_ON(!list_empty(&rdev->wiphy.wdev_list));
 
        /*
         * First remove the hardware from everywhere, this makes
@@ -949,7 +952,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
                wdev->identifier = ++rdev->wdev_id;
-               list_add_rcu(&wdev->list, &rdev->wdev_list);
+               list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
                rdev->devlist_generation++;
                /* can only change netns with wiphy */
                dev->features |= NETIF_F_NETNS_LOCAL;
index fcd59e7..a06a105 100644 (file)
@@ -50,8 +50,7 @@ struct cfg80211_registered_device {
        /* wiphy index, internal only */
        int wiphy_idx;
 
-       /* associated wireless interfaces, protected by rtnl or RCU */
-       struct list_head wdev_list;
+       /* protected by RTNL */
        int devlist_generation, wdev_id;
        int opencount; /* also protected by devlist_mtx */
        wait_queue_head_t dev_wait;
index 40299f1..862c26b 100644 (file)
@@ -103,7 +103,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
                if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
                        continue;
 
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        if (have_ifidx && wdev->netdev &&
                            wdev->netdev->ifindex == ifidx) {
                                result = wdev;
@@ -149,7 +149,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
                tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
                if (tmp) {
                        /* make sure wdev exists */
-                       list_for_each_entry(wdev, &tmp->wdev_list, list) {
+                       list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
                                if (wdev->identifier != (u32)wdev_id)
                                        continue;
                                found = true;
@@ -524,7 +524,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                *rdev = wiphy_to_rdev(wiphy);
                *wdev = NULL;
 
-               list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+               list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
                        if (tmp->identifier == cb->args[1]) {
                                *wdev = tmp;
                                break;
@@ -2504,7 +2504,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
                }
                if_idx = 0;
 
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        if (if_idx < if_start) {
                                if_idx++;
                                continue;
@@ -2776,7 +2776,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
                wdev->identifier = ++rdev->wdev_id;
-               list_add_rcu(&wdev->list, &rdev->wdev_list);
+               list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
                rdev->devlist_generation++;
                break;
        default:
@@ -3585,7 +3585,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
        struct wireless_dev *wdev;
        bool ret = false;
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO)
                        continue;
@@ -10328,7 +10328,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
                *wdev = NULL;
 
                if (cb->args[1]) {
-                       list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+                       list_for_each_entry(tmp, &wiphy->wdev_list, list) {
                                if (tmp->identifier == cb->args[1] - 1) {
                                        *wdev = tmp;
                                        break;
@@ -13339,7 +13339,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
                    sched_scan_req->owner_nlportid == notify->portid)
                        schedule_scan_stop = true;
 
-               list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
                        cfg80211_mlme_unregister_socket(wdev, notify->portid);
 
                        if (wdev->owner_nlportid == notify->portid)
index 2fed05f..050d794 100644 (file)
@@ -1685,7 +1685,7 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy)
        struct cfg80211_sched_scan_request *sched_scan_req;
        ASSERT_RTNL();
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list)
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
                if (!reg_wdev_chan_valid(wiphy, wdev)) {
                        dev = wdev->netdev;
                        switch (wdev->iftype) {
index 37d8ab3..e5b962d 100644 (file)
@@ -54,7 +54,7 @@ static bool cfg80211_is_all_countryie_ignore(void)
        bool is_all_countryie_ignore = true;
 
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        wdev_lock(wdev);
                        if (!(wdev->wiphy->regulatory_flags &
                                REGULATORY_COUNTRY_IE_IGNORE)) {
@@ -246,7 +246,7 @@ void cfg80211_conn_work(struct work_struct *work)
 
        rtnl_lock();
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (!wdev->netdev)
                        continue;
 
@@ -630,7 +630,7 @@ static bool cfg80211_is_all_idle(void)
         * count as new regulatory hints.
         */
        list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        wdev_lock(wdev);
                        if (wdev->conn || wdev->current_bss)
                                is_all_idle = false;
index acff02f..71fcbcb 100644 (file)
@@ -910,7 +910,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
 
        ASSERT_RTNL();
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list)
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
                cfg80211_process_wdev_events(wdev);
 }
 
@@ -1494,14 +1494,14 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
                return -EINVAL;
 
        params.iftype_num[iftype] = 1;
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (!wdev->beacon_interval)
                        continue;
 
                params.iftype_num[wdev->iftype]++;
        }
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                u32 bi_prev = wdev->beacon_interval;
 
                if (!wdev->beacon_interval)
@@ -1701,7 +1701,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
                break;
        }
 
-       list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev_iter, &rdev->wiphy.wdev_list, list) {
                if (wdev_iter == wdev)
                        continue;
                if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {