cfg80211: make wdev_list accessible to drivers
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>
This commit is contained in:
parent
1e17007652
commit
ed8559eaeb
8 changed files with 33 additions and 26 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue