To give an indication of what this does. I built a small nuc computer with 13 USB wifi cards and 1 pci-e wifi card. I used kismet to channel hop every card twice per second while in monitor mode. Before this patch, the load average of my 4 core nuc was 11-12 (fairly stable, with actual cpu use fairly low, 2-10%) After this patch, the load average is 3.5-4 under the same usage conditions. Quick math suggest this is a very worthwhile improvement. Interestingly, with the patch I bumped it back up to the default hop speed of 5 per second and the load average only hit 5-6 I'll leave the code review to those who are much better at this than I, but hopefully this demonstrates at least some of the need. I have another computer with ~15 wifi clients connecting and disconnecting once per minute and it hits D state long enough to time out connections. I look forward to testing this patch on that system as well. Thanks Johannes! -Zero On Wed, Jul 31, 2019 at 6:21 PM Johannes Berg <johannes@xxxxxxxxxxxxxxxx> wrote: > > From: Johannes Berg <johannes.berg@xxxxxxxxx> > > Currently, _everything_ in cfg80211 holds the RTNL, and if you > have a slow USB device (or a few) you can get some bad lock > contention on that. > > Fix that by re-adding a mutex to each wiphy/rdev as we had at > some point, so we have locking for the wireless_dev lists and > all the other things in there, and also so that drivers still > don't have to worry too much about it (they still won't get > parallel calls for a single device). > > Then, we can restrict the RTNL to a few cases where we add or > remove interfaces and really need the added protection. Some > of the global list management still also uses the RTNL, since > we need to have it anyway for netdev management. > > TODO: > - re-read everything a few times to make sure it seems right > - use wiphy_lock()/wiphy_unlock() in all drivers as the code > changed in mac80211 does > - address the FIXME > > Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> > --- > include/net/cfg80211.h | 24 +- > net/mac80211/main.c | 2 + > net/wireless/chan.c | 5 +- > net/wireless/core.c | 45 +++- > net/wireless/core.h | 4 +- > net/wireless/ibss.c | 2 +- > net/wireless/mlme.c | 6 +- > net/wireless/nl80211.c | 547 +++++++++++++++++++++-------------------- > net/wireless/sme.c | 1 - > net/wireless/util.c | 2 +- > 10 files changed, 353 insertions(+), 285 deletions(-) > > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h > index 35ec1f0a2bf9..2ac6cb79f67d 100644 > --- a/include/net/cfg80211.h > +++ b/include/net/cfg80211.h > @@ -4726,6 +4726,25 @@ struct cfg80211_internal_bss; > struct cfg80211_cached_keys; > struct cfg80211_cqm_config; > > +/** > + * wiphy_lock - lock the wiphy > + * @wiphy: the wiphy to lock > + * > + * This is mostly exposed so it can be done around registering and > + * unregistering netdevs that aren't created through cfg80211 calls, > + * since that requires locking in cfg80211 when the notifiers is > + * called, but that cannot differentiate which way it's called. > + * > + * When cfg80211 ops are called, the wiphy is already locked. > + */ > +void wiphy_lock(struct wiphy *wiphy); > + > +/** > + * wiphy_unlock - unlock the wiphy again > + * @wiphy: the wiphy to unlock > + */ > +void wiphy_unlock(struct wiphy *wiphy); > + > /** > * struct wireless_dev - wireless device state > * > @@ -4733,7 +4752,10 @@ struct cfg80211_cqm_config; > * that uses the ieee80211_ptr field in struct net_device (this > * is intentional so it can be allocated along with the netdev.) > * It need not be registered then as netdev registration will > - * be intercepted by cfg80211 to see the new wireless device. > + * be intercepted by cfg80211 to see the new wireless device, > + * however, drivers must lock the wiphy before registering or > + * unregistering netdevs if they pre-create any netdevs (in ops > + * called from cfg80211, the wiphy is already locked.) > * > * For non-netdev uses, it must also be allocated by the driver > * in response to the cfg80211 callbacks that require it, as > diff --git a/net/mac80211/main.c b/net/mac80211/main.c > index 29b9d57df1a3..03fc52587bff 100644 > --- a/net/mac80211/main.c > +++ b/net/mac80211/main.c > @@ -1252,8 +1252,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) > !ieee80211_hw_check(hw, NO_AUTO_VIF)) { > struct vif_params params = {0}; > > + wiphy_lock(hw->wiphy); > result = ieee80211_if_add(local, "wlan%d", NET_NAME_ENUM, NULL, > NL80211_IFTYPE_STATION, ¶ms); > + wiphy_unlock(hw->wiphy); > if (result) > wiphy_warn(local->hw.wiphy, > "Failed to add default virtual iface\n"); > diff --git a/net/wireless/chan.c b/net/wireless/chan.c > index 7dc1bbd0888f..ac83c9030c17 100644 > --- a/net/wireless/chan.c > +++ b/net/wireless/chan.c > @@ -839,7 +839,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy, > struct wireless_dev *wdev; > struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) || > !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)) > @@ -961,9 +961,10 @@ bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, > struct cfg80211_chan_def *chandef, > enum nl80211_iftype iftype) > { > + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > bool check_no_ir; > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > /* > * Under certain conditions suggested by some regulatory bodies a > diff --git a/net/wireless/core.c b/net/wireless/core.c > index 742986c73490..2d5bd07ae11f 100644 > --- a/net/wireless/core.c > +++ b/net/wireless/core.c > @@ -39,7 +39,7 @@ MODULE_LICENSE("GPL"); > MODULE_DESCRIPTION("wireless configuration support"); > MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME); > > -/* RCU-protected (and RTNL for writers) */ > +/* RTNL-protected for writing, RCU-based lookup */ > LIST_HEAD(cfg80211_rdev_list); > int cfg80211_rdev_list_generation; > > @@ -222,7 +222,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) > void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, > struct wireless_dev *wdev) > { > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) > return; > @@ -245,7 +245,7 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, > void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, > struct wireless_dev *wdev) > { > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN)) > return; > @@ -472,6 +472,7 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, > } > } > > + mutex_init(&rdev->mtx); > INIT_LIST_HEAD(&rdev->wiphy.wdev_list); > INIT_LIST_HEAD(&rdev->beacon_registrations); > spin_lock_init(&rdev->beacon_registrations_lock); > @@ -978,21 +979,38 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy) > } > EXPORT_SYMBOL(wiphy_rfkill_stop_polling); > > +void wiphy_lock(struct wiphy *wiphy) > +{ > + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > + > + mutex_lock(&rdev->mtx); > +} > +EXPORT_SYMBOL(wiphy_lock); > + > +void wiphy_unlock(struct wiphy *wiphy) > +{ > + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > + > + mutex_unlock(&rdev->mtx); > +} > +EXPORT_SYMBOL(wiphy_unlock); > + > void wiphy_unregister(struct wiphy *wiphy) > { > struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); > > wait_event(rdev->dev_wait, ({ > int __count; > - rtnl_lock(); > + mutex_lock(&rdev->mtx); > __count = rdev->opencount; > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > __count == 0; })); > > if (rdev->rfkill) > rfkill_unregister(rdev->rfkill); > > rtnl_lock(); > + mutex_lock(&rdev->mtx); > nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); > rdev->wiphy.registered = false; > > @@ -1015,6 +1033,7 @@ void wiphy_unregister(struct wiphy *wiphy) > cfg80211_rdev_list_generation++; > device_del(&rdev->wiphy.dev); > > + mutex_unlock(&rdev->mtx); > rtnl_unlock(); > > flush_work(&rdev->scan_done_wk); > @@ -1047,6 +1066,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) > } > list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) > cfg80211_put_bss(&rdev->wiphy, &scan->pub); > + mutex_destroy(&rdev->mtx); > kfree(rdev); > } > > @@ -1125,7 +1145,7 @@ static const struct device_type wiphy_type = { > void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, > enum nl80211_iftype iftype, int num) > { > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > rdev->num_running_ifaces += num; > if (iftype == NL80211_IFTYPE_MONITOR) > @@ -1138,7 +1158,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev, > struct net_device *dev = wdev->netdev; > struct cfg80211_sched_scan_request *pos, *tmp; > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > ASSERT_WDEV_LOCK(wdev); > > cfg80211_pmsr_wdev_down(wdev); > @@ -1234,6 +1254,9 @@ void cfg80211_init_wdev(struct cfg80211_registered_device *rdev, > spin_lock_init(&wdev->pmsr_lock); > INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk); > > + ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > + > /* > * We get here also when the interface changes network namespaces, > * as it's registered into the new one, but we don't want it to > @@ -1269,6 +1292,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, > SET_NETDEV_DEVTYPE(dev, &wiphy_type); > break; > case NETDEV_REGISTER: > + lockdep_assert_held(&rdev->mtx); > /* > * NB: cannot take rdev->mtx here because this may be > * called within code protected by it when interfaces > @@ -1305,9 +1329,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, > cfg80211_init_wdev(rdev, wdev); > break; > case NETDEV_GOING_DOWN: > + mutex_lock(&rdev->mtx); > cfg80211_leave(rdev, wdev); > + mutex_unlock(&rdev->mtx); > break; > case NETDEV_DOWN: > + mutex_lock(&rdev->mtx); > cfg80211_update_iface_num(rdev, wdev->iftype, -1); > if (rdev->scan_req && rdev->scan_req->wdev == wdev) { > if (WARN_ON(!rdev->scan_req->notified)) > @@ -1322,9 +1349,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, > } > > rdev->opencount--; > + mutex_unlock(&rdev->mtx); > wake_up(&rdev->dev_wait); > break; > case NETDEV_UP: > + mutex_lock(&rdev->mtx); > cfg80211_update_iface_num(rdev, wdev->iftype, 1); > wdev_lock(wdev); > switch (wdev->iftype) { > @@ -1371,8 +1400,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, > /* assume this means it's off */ > wdev->ps = false; > } > + mutex_unlock(&rdev->mtx); > break; > case NETDEV_UNREGISTER: > + lockdep_assert_held(&rdev->mtx); > /* > * It is possible to get NETDEV_UNREGISTER > * multiple times. To detect that, check > diff --git a/net/wireless/core.h b/net/wireless/core.h > index 77556c58d9ac..9ad586fd7939 100644 > --- a/net/wireless/core.h > +++ b/net/wireless/core.h > @@ -25,6 +25,8 @@ struct cfg80211_registered_device { > const struct cfg80211_ops *ops; > struct list_head list; > > + struct mutex mtx; > + > /* rfkill support */ > struct rfkill_ops rfkill_ops; > struct rfkill *rfkill; > @@ -231,7 +233,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev) > > static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) > { > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces && > rdev->num_running_ifaces > 0; > diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c > index d1743e6abc34..e8d9162f9010 100644 > --- a/net/wireless/ibss.c > +++ b/net/wireless/ibss.c > @@ -92,7 +92,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, > struct wireless_dev *wdev = dev->ieee80211_ptr; > int err; > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > ASSERT_WDEV_LOCK(wdev); > > if (wdev->ssid_len) > diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c > index f9462010575f..808821d521f9 100644 > --- a/net/wireless/mlme.c > +++ b/net/wireless/mlme.c > @@ -433,7 +433,7 @@ cfg80211_process_mlme_unregistrations(struct cfg80211_registered_device *rdev) > { > struct cfg80211_mgmt_registration *reg; > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > spin_lock_bh(&rdev->mlme_unreg_lock); > while ((reg = list_first_entry_or_null(&rdev->mlme_unreg, > @@ -463,9 +463,9 @@ void cfg80211_mlme_unreg_wk(struct work_struct *wk) > rdev = container_of(wk, struct cfg80211_registered_device, > mlme_unreg_wk); > > - rtnl_lock(); > + mutex_lock(&rdev->mtx); > cfg80211_process_mlme_unregistrations(rdev); > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > } > > int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid, > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c > index 1a107f29016b..b79ab55f1f53 100644 > --- a/net/wireless/nl80211.c > +++ b/net/wireless/nl80211.c > @@ -63,9 +63,9 @@ static const struct genl_multicast_group nl80211_mcgrps[] = { > > /* returns ERR_PTR values */ > static struct wireless_dev * > -__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) > +__cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev, > + struct net *netns, struct nlattr **attrs) > { > - struct cfg80211_registered_device *rdev; > struct wireless_dev *result = NULL; > bool have_ifidx = attrs[NL80211_ATTR_IFINDEX]; > bool have_wdev_id = attrs[NL80211_ATTR_WDEV]; > @@ -73,8 +73,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) > int wiphy_idx = -1; > int ifidx = -1; > > - ASSERT_RTNL(); > - > if (!have_ifidx && !have_wdev_id) > return ERR_PTR(-EINVAL); > > @@ -85,6 +83,28 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) > wiphy_idx = wdev_id >> 32; > } > > + if (rdev) { > + struct wireless_dev *wdev; > + > + lockdep_assert_held(&rdev->mtx); > + > + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { > + if (have_ifidx && wdev->netdev && > + wdev->netdev->ifindex == ifidx) { > + result = wdev; > + break; > + } > + if (have_wdev_id && wdev->identifier == (u32)wdev_id) { > + result = wdev; > + break; > + } > + } > + > + return result ?: ERR_PTR(-ENODEV); > + } > + > + ASSERT_RTNL(); > + > list_for_each_entry(rdev, &cfg80211_rdev_list, list) { > struct wireless_dev *wdev; > > @@ -775,22 +795,31 @@ int nl80211_prepare_wdev_dump(struct netlink_callback *cb, > return err; > } > > - *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk), > + rtnl_lock(); > + *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk), > attrbuf); > kfree(attrbuf); > - if (IS_ERR(*wdev)) > + if (IS_ERR(*wdev)) { > + rtnl_unlock(); > return PTR_ERR(*wdev); > + } > *rdev = wiphy_to_rdev((*wdev)->wiphy); > + mutex_lock(&(*rdev)->mtx); > + rtnl_unlock(); > /* 0 is the first index - add 1 to parse only once */ > cb->args[0] = (*rdev)->wiphy_idx + 1; > cb->args[1] = (*wdev)->identifier; > } else { > /* subtract the 1 again here */ > - struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); > + struct wiphy *wiphy; > struct wireless_dev *tmp; > > - if (!wiphy) > + rtnl_lock(); > + wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); > + if (!wiphy) { > + rtnl_unlock(); > return -ENODEV; > + } > *rdev = wiphy_to_rdev(wiphy); > *wdev = NULL; > > @@ -801,8 +830,12 @@ int nl80211_prepare_wdev_dump(struct netlink_callback *cb, > } > } > > - if (!*wdev) > + if (!*wdev) { > + rtnl_unlock(); > return -ENODEV; > + } > + mutex_lock(&(*rdev)->mtx); > + rtnl_unlock(); > } > > return 0; > @@ -2791,7 +2824,7 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) > > static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) > { > - struct cfg80211_registered_device *rdev; > + struct cfg80211_registered_device *rdev = NULL; > struct net_device *netdev = NULL; > struct wireless_dev *wdev; > int result = 0, rem_txq_params = 0; > @@ -2802,8 +2835,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) > u8 coverage_class = 0; > u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0; > > - ASSERT_RTNL(); > - > + rtnl_lock(); > /* > * Try to find the wiphy and netdev. Normally this > * function shouldn't need the netdev, but this is > @@ -2827,14 +2859,20 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) > if (!netdev) { > rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), > info->attrs); > - if (IS_ERR(rdev)) > + if (IS_ERR(rdev)) { > + rtnl_unlock(); > return PTR_ERR(rdev); > + } > wdev = NULL; > netdev = NULL; > result = 0; > } else > wdev = netdev->ieee80211_ptr; > > + if (rdev) > + mutex_lock(&rdev->mtx); > + rtnl_unlock(); > + > /* > * end workaround code, by now the rdev is available > * and locked, and wdev may or may not be NULL. > @@ -2844,6 +2882,10 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) > result = cfg80211_dev_rename( > rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); > > + // FIXME - push this through to all the error paths below > + if (rdev) > + mutex_unlock(&rdev->mtx); > + > if (result) > return result; > > @@ -3607,6 +3649,17 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) > if (!rdev->ops->del_virtual_intf) > return -EOPNOTSUPP; > > + /* > + * We hold RTNL, so this is safe, without RTNL opencount cannot > + * reach 0, and thus the rdev cannot be deleted. > + * > + * We need to do it for the dev_close(), since that will call > + * the netdev notifiers, and we need to acquire the mutex there > + * but don't know if we get there from here or from some other > + * place (e.g. "ip link set ... down"). > + */ > + mutex_unlock(&rdev->mtx); > + > /* > * If we remove a wireless device without a netdev then clear > * user_ptr[1] so that nl80211_post_doit won't dereference it > @@ -3616,6 +3669,10 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) > */ > if (!wdev->netdev) > info->user_ptr[1] = NULL; > + else > + dev_close(wdev->netdev); > + > + mutex_lock(&rdev->mtx); > > return rdev_del_virtual_intf(rdev, wdev); > } > @@ -5216,10 +5273,9 @@ static int nl80211_dump_station(struct sk_buff *skb, > int sta_idx = cb->args[2]; > int err; > > - rtnl_lock(); > err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); > if (err) > - goto out_err; > + return err; > > if (!wdev->netdev) { > err = -EINVAL; > @@ -5254,7 +5310,7 @@ static int nl80211_dump_station(struct sk_buff *skb, > cb->args[2] = sta_idx; > err = skb->len; > out_err: > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > > return err; > } > @@ -6099,10 +6155,9 @@ static int nl80211_dump_mpath(struct sk_buff *skb, > int path_idx = cb->args[2]; > int err; > > - rtnl_lock(); > err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); > if (err) > - goto out_err; > + return err; > > if (!rdev->ops->dump_mpath) { > err = -EOPNOTSUPP; > @@ -6135,7 +6190,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb, > cb->args[2] = path_idx; > err = skb->len; > out_err: > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > return err; > } > > @@ -6295,10 +6350,9 @@ static int nl80211_dump_mpp(struct sk_buff *skb, > int path_idx = cb->args[2]; > int err; > > - rtnl_lock(); > err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); > if (err) > - goto out_err; > + return err; > > if (!rdev->ops->dump_mpp) { > err = -EOPNOTSUPP; > @@ -6331,7 +6385,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb, > cb->args[2] = path_idx; > err = skb->len; > out_err: > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > return err; > } > > @@ -6939,12 +6993,15 @@ static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) > if (!hdr) > goto put_failure; > > + rtnl_lock(); > + > if (info->attrs[NL80211_ATTR_WIPHY]) { > bool self_managed; > > rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); > if (IS_ERR(rdev)) { > nlmsg_free(msg); > + rtnl_unlock(); > return PTR_ERR(rdev); > } > > @@ -6953,9 +7010,11 @@ static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) > REGULATORY_WIPHY_SELF_MANAGED; > regdom = get_wiphy_regdom(wiphy); > > + > /* a self-managed-reg device must have a private regdom */ > if (WARN_ON(!regdom && self_managed)) { > nlmsg_free(msg); > + rtnl_unlock(); > return -EINVAL; > } > > @@ -6980,11 +7039,13 @@ static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info) > rcu_read_unlock(); > > genlmsg_end(msg, hdr); > + rtnl_unlock(); > return genlmsg_reply(msg, info); > > nla_put_failure_rcu: > rcu_read_unlock(); > nla_put_failure: > + rtnl_unlock(); > put_failure: > nlmsg_free(msg); > return -EMSGSIZE; > @@ -7147,12 +7208,17 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) > return -EINVAL; > } > > - if (!reg_is_valid_request(alpha2)) > - return -EINVAL; > + rtnl_lock(); > + if (!reg_is_valid_request(alpha2)) { > + r = -EINVAL; > + goto out; > + } > > rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL); > - if (!rd) > - return -ENOMEM; > + if (!rd) { > + r = -ENOMEM; > + goto out; > + } > > rd->n_reg_rules = num_rules; > rd->alpha2[0] = alpha2[0]; > @@ -7184,10 +7250,13 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) > } > } > > + r = set_regdom(rd, REGD_SOURCE_CRDA); > /* set_regdom takes ownership of rd */ > - return set_regdom(rd, REGD_SOURCE_CRDA); > + rd = NULL; > bad_reg: > kfree(rd); > + out: > + rtnl_unlock(); > return r; > } > #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ > @@ -8367,10 +8436,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) > struct net_device *dev = info->user_ptr[1]; > struct wireless_dev *wdev = dev->ieee80211_ptr; > struct cfg80211_csa_settings params; > - /* csa_attrs is defined static to avoid waste of stack size - this > - * function is called under RTNL lock, so this should not be a problem. > - */ > - static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; > + struct nlattr **csa_attrs; > int err; > bool need_new_beacon = false; > bool need_handle_dfs_flag = true; > @@ -8435,28 +8501,39 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) > if (err) > return err; > > + csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs), > + GFP_KERNEL); > + if (!csa_attrs) > + return -ENOMEM; > + > err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX, > info->attrs[NL80211_ATTR_CSA_IES], > nl80211_policy, info->extack); > if (err) > - return err; > + goto free; > > err = nl80211_parse_beacon(rdev, csa_attrs, ¶ms.beacon_csa); > if (err) > - return err; > + goto free; > > - if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) > - return -EINVAL; > + if (!csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]) { > + err = -EINVAL; > + goto free; > + } > > len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); > - if (!len || (len % sizeof(u16))) > - return -EINVAL; > + if (!len || (len % sizeof(u16))) { > + err = -EINVAL; > + goto free; > + } > > params.n_counter_offsets_beacon = len / sizeof(u16); > if (rdev->wiphy.max_num_csa_counters && > (params.n_counter_offsets_beacon > > - rdev->wiphy.max_num_csa_counters)) > - return -EINVAL; > + rdev->wiphy.max_num_csa_counters)) { > + err = -EINVAL; > + goto free; > + } > > params.counter_offsets_beacon = > nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_BEACON]); > @@ -8465,23 +8542,31 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) > for (i = 0; i < params.n_counter_offsets_beacon; i++) { > u16 offset = params.counter_offsets_beacon[i]; > > - if (offset >= params.beacon_csa.tail_len) > - return -EINVAL; > + if (offset >= params.beacon_csa.tail_len) { > + err = -EINVAL; > + goto free; > + } > > - if (params.beacon_csa.tail[offset] != params.count) > - return -EINVAL; > + if (params.beacon_csa.tail[offset] != params.count) { > + err = -EINVAL; > + goto free; > + } > } > > if (csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]) { > len = nla_len(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); > - if (!len || (len % sizeof(u16))) > - return -EINVAL; > + if (!len || (len % sizeof(u16))) { > + err = -EINVAL; > + goto free; > + } > > params.n_counter_offsets_presp = len / sizeof(u16); > if (rdev->wiphy.max_num_csa_counters && > (params.n_counter_offsets_presp > > - rdev->wiphy.max_num_csa_counters)) > - return -EINVAL; > + rdev->wiphy.max_num_csa_counters)) { > + err = -EINVAL; > + goto free; > + } > > params.counter_offsets_presp = > nla_data(csa_attrs[NL80211_ATTR_CSA_C_OFF_PRESP]); > @@ -8490,35 +8575,42 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) > for (i = 0; i < params.n_counter_offsets_presp; i++) { > u16 offset = params.counter_offsets_presp[i]; > > - if (offset >= params.beacon_csa.probe_resp_len) > - return -EINVAL; > + if (offset >= params.beacon_csa.probe_resp_len) { > + err = -EINVAL; > + goto free; > + } > > if (params.beacon_csa.probe_resp[offset] != > - params.count) > - return -EINVAL; > + params.count) { > + err = -EINVAL; > + goto free; > + } > } > } > > skip_beacons: > err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); > if (err) > - return err; > + goto free; > > if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, > - wdev->iftype)) > - return -EINVAL; > + wdev->iftype)) { > + err = -EINVAL; > + goto free; > + } > > err = cfg80211_chandef_dfs_required(wdev->wiphy, > ¶ms.chandef, > wdev->iftype); > if (err < 0) > - return err; > + goto free; > > if (err > 0) { > params.radar_required = true; > if (need_handle_dfs_flag && > !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) { > - return -EINVAL; > + err = -EINVAL; > + goto free; > } > } > > @@ -8529,6 +8621,8 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) > err = rdev_channel_switch(rdev, dev, ¶ms); > wdev_unlock(wdev); > > +free: > + kfree(csa_attrs); > return err; > } > > @@ -8677,12 +8771,9 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) > int start = cb->args[2], idx = 0; > int err; > > - rtnl_lock(); > err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); > - if (err) { > - rtnl_unlock(); > + if (err) > return err; > - } > > wdev_lock(wdev); > spin_lock_bh(&rdev->bss_lock); > @@ -8713,7 +8804,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb) > wdev_unlock(wdev); > > cb->args[2] = idx; > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > > return skb->len; > } > @@ -8802,10 +8893,11 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) > if (!attrbuf) > return -ENOMEM; > > - rtnl_lock(); > res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); > - if (res) > - goto out_err; > + if (res) { > + kfree(attrbuf); > + return res; > + } > > /* prepare_wdev_dump parsed the attributes */ > radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; > @@ -8847,7 +8939,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb) > res = skb->len; > out_err: > kfree(attrbuf); > - rtnl_unlock(); > + mutex_unlock(&rdev->mtx); > return res; > } > > @@ -9674,10 +9766,14 @@ EXPORT_SYMBOL(__cfg80211_send_event_skb); > static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) > { > struct cfg80211_registered_device *rdev = info->user_ptr[0]; > - struct wireless_dev *wdev = > - __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); > + struct wireless_dev *wdev; > int err; > > + lockdep_assert_held(&rdev->mtx); > + > + wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info), > + info->attrs); > + > if (!rdev->ops->testmode_cmd) > return -EOPNOTSUPP; > > @@ -12817,7 +12913,8 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) > { > struct cfg80211_registered_device *rdev = info->user_ptr[0]; > struct wireless_dev *wdev = > - __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); > + __cfg80211_wdev_from_attrs(rdev, genl_info_net(info), > + info->attrs); > int i, err; > u32 vid, subcmd; > > @@ -12941,7 +13038,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb, > goto out; > } > > - *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf); > + *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf); > if (IS_ERR(*wdev)) > *wdev = NULL; > > @@ -13723,31 +13820,24 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info) > static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > struct genl_info *info) > { > - struct cfg80211_registered_device *rdev; > + struct cfg80211_registered_device *rdev = NULL; > struct wireless_dev *wdev; > struct net_device *dev; > - bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; > - > - if (rtnl) > - rtnl_lock(); > > + rtnl_lock(); > if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { > rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); > if (IS_ERR(rdev)) { > - if (rtnl) > - rtnl_unlock(); > + rtnl_unlock(); > return PTR_ERR(rdev); > } > info->user_ptr[0] = rdev; > } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || > ops->internal_flags & NL80211_FLAG_NEED_WDEV) { > - ASSERT_RTNL(); > - > - wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), > + wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info), > info->attrs); > if (IS_ERR(wdev)) { > - if (rtnl) > - rtnl_unlock(); > + rtnl_unlock(); > return PTR_ERR(wdev); > } > > @@ -13756,8 +13846,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > > if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { > if (!dev) { > - if (rtnl) > - rtnl_unlock(); > + rtnl_unlock(); > return -EINVAL; > } > > @@ -13768,8 +13857,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > > if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && > !wdev_running(wdev)) { > - if (rtnl) > - rtnl_unlock(); > + rtnl_unlock(); > return -ENETDOWN; > } > > @@ -13779,6 +13867,11 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, > info->user_ptr[0] = rdev; > } > > + if (rdev) > + mutex_lock(&rdev->mtx); > + if (!(ops->internal_flags & NL80211_FLAG_NEED_RTNL)) > + rtnl_unlock(); > + > return 0; > } > > @@ -13796,6 +13889,12 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, > } > } > > + if (info->user_ptr[0]) { > + struct cfg80211_registered_device *rdev = info->user_ptr[0]; > + > + mutex_unlock(&rdev->mtx); > + } > + > if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) > rtnl_unlock(); > > @@ -13819,15 +13918,13 @@ static const struct genl_ops nl80211_ops[] = { > .dumpit = nl80211_dump_wiphy, > .done = nl80211_dump_wiphy_done, > /* can be retrieved by unprivileged users */ > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_SET_WIPHY, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_wiphy, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_RTNL, > }, > { > .cmd = NL80211_CMD_GET_INTERFACE, > @@ -13835,8 +13932,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_get_interface, > .dumpit = nl80211_dump_interface, > /* can be retrieved by unprivileged users */ > - .internal_flags = NL80211_FLAG_NEED_WDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV, > }, > { > .cmd = NL80211_CMD_SET_INTERFACE, > @@ -13867,8 +13963,7 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_key, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_KEY, > @@ -13876,7 +13971,6 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_set_key, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -13885,7 +13979,6 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_new_key, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -13893,64 +13986,56 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_del_key, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_BEACON, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .flags = GENL_UNS_ADMIN_PERM, > .doit = nl80211_set_beacon, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_START_AP, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .flags = GENL_UNS_ADMIN_PERM, > .doit = nl80211_start_ap, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_STOP_AP, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .flags = GENL_UNS_ADMIN_PERM, > .doit = nl80211_stop_ap, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_STATION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_station, > .dumpit = nl80211_dump_station, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_STATION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_station, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_NEW_STATION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_new_station, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_DEL_STATION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_del_station, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_MPATH, > @@ -13958,8 +14043,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_get_mpath, > .dumpit = nl80211_dump_mpath, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_MPP, > @@ -13967,47 +14051,42 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_get_mpp, > .dumpit = nl80211_dump_mpp, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_MPATH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_mpath, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_NEW_MPATH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_new_mpath, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_DEL_MPATH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_del_mpath, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_BSS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_bss, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_REG, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_reg_do, > .dumpit = nl80211_get_reg_dump, > - .internal_flags = NL80211_FLAG_NEED_RTNL, > + .internal_flags = 0, > /* can be retrieved by unprivileged users */ > }, > #ifdef CONFIG_CFG80211_CRDA_SUPPORT > @@ -14016,7 +14095,7 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_reg, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_RTNL, > + .internal_flags = 0, > }, > #endif > { > @@ -14036,32 +14115,28 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_mesh_config, > /* can be retrieved by unprivileged users */ > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_MESH_CONFIG, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_update_mesh_config, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_TRIGGER_SCAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_trigger_scan, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_ABORT_SCAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_abort_scan, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_SCAN, > @@ -14073,16 +14148,14 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_start_sched_scan, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_STOP_SCHED_SCAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_stop_sched_scan, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_AUTHENTICATE, > @@ -14090,7 +14163,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_authenticate, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14099,7 +14172,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_associate, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14107,32 +14180,28 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_deauthenticate, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_DISASSOCIATE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_disassociate, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_JOIN_IBSS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_join_ibss, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_LEAVE_IBSS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_leave_ibss, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > #ifdef CONFIG_NL80211_TESTMODE > { > @@ -14141,8 +14210,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_testmode_do, > .dumpit = nl80211_testmode_dump, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > #endif > { > @@ -14151,7 +14219,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_connect, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14160,7 +14228,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_update_connect_params, > .flags = GENL_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14168,16 +14236,14 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_disconnect, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_WIPHY_NETNS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_wiphy_netns, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_GET_SURVEY, > @@ -14190,7 +14256,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_setdel_pmksa, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14198,136 +14264,119 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_setdel_pmksa, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_FLUSH_PMKSA, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_flush_pmksa, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_remain_on_channel, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_cancel_remain_on_channel, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_tx_bitrate_mask, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_REGISTER_FRAME, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_register_mgmt, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV, > }, > { > .cmd = NL80211_CMD_FRAME, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tx_mgmt, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_FRAME_WAIT_CANCEL, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tx_mgmt_cancel_wait, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_POWER_SAVE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_power_save, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_GET_POWER_SAVE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_power_save, > /* can be retrieved by unprivileged users */ > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_CQM, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_cqm, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_CHANNEL, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_channel, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_WDS_PEER, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_wds_peer, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_JOIN_MESH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_join_mesh, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_LEAVE_MESH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_leave_mesh, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_JOIN_OCB, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_join_ocb, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_LEAVE_OCB, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_leave_ocb, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > #ifdef CONFIG_PM > { > @@ -14335,16 +14384,14 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_wowlan, > /* can be retrieved by unprivileged users */ > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_SET_WOWLAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_wowlan, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > #endif > { > @@ -14353,7 +14400,7 @@ static const struct genl_ops nl80211_ops[] = { > .doit = nl80211_set_rekey_data, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14361,128 +14408,112 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tdls_mgmt, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_TDLS_OPER, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tdls_oper, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_UNEXPECTED_FRAME, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_register_unexpected_frame, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_PROBE_CLIENT, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_probe_client, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_REGISTER_BEACONS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_register_beacons, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_SET_NOACK_MAP, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_noack_map, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_START_P2P_DEVICE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_start_p2p_device, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV, > }, > { > .cmd = NL80211_CMD_STOP_P2P_DEVICE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_stop_p2p_device, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_START_NAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_start_nan, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV, > }, > { > .cmd = NL80211_CMD_STOP_NAN, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_stop_nan, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_ADD_NAN_FUNCTION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_nan_add_func, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_DEL_NAN_FUNCTION, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_nan_del_func, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_CHANGE_NAN_CONFIG, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_nan_change_config, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_MCAST_RATE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_mcast_rate, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_MAC_ACL, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_mac_acl, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_RADAR_DETECT, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_start_radar_detection, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, > @@ -14494,47 +14525,41 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_update_ft_ies, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_CRIT_PROTOCOL_START, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_crit_protocol_start, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_crit_protocol_stop, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_COALESCE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_coalesce, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_SET_COALESCE, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_coalesce, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WIPHY, > }, > { > .cmd = NL80211_CMD_CHANNEL_SWITCH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_channel_switch, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_VENDOR, > @@ -14543,7 +14568,7 @@ static const struct genl_ops nl80211_ops[] = { > .dumpit = nl80211_vendor_cmd_dump, > .flags = GENL_UNS_ADMIN_PERM, > .internal_flags = NL80211_FLAG_NEED_WIPHY | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > @@ -14551,116 +14576,102 @@ static const struct genl_ops nl80211_ops[] = { > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_qos_map, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_ADD_TX_TS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_add_tx_ts, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_DEL_TX_TS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_del_tx_ts, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tdls_channel_switch, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tdls_cancel_channel_switch, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_multicast_to_unicast, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_SET_PMK, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_set_pmk, > .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL | > + 0 | > NL80211_FLAG_CLEAR_SKB, > }, > { > .cmd = NL80211_CMD_DEL_PMK, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_del_pmk, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_EXTERNAL_AUTH, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_external_auth, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_CONTROL_PORT_FRAME, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_tx_control_port, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_get_ftm_responder_stats, > - .internal_flags = NL80211_FLAG_NEED_NETDEV | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV, > }, > { > .cmd = NL80211_CMD_PEER_MEASUREMENT_START, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_pmsr_start, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, > }, > { > .cmd = NL80211_CMD_NOTIFY_RADAR, > .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, > .doit = nl80211_notify_radar_detection, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_UPDATE_OWE_INFO, > .doit = nl80211_update_owe_info, > .flags = GENL_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > { > .cmd = NL80211_CMD_PROBE_MESH_LINK, > .doit = nl80211_probe_mesh_link, > .flags = GENL_UNS_ADMIN_PERM, > - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | > - NL80211_FLAG_NEED_RTNL, > + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, > }, > }; > > diff --git a/net/wireless/sme.c b/net/wireless/sme.c > index 7a6c38ddc65a..f6b68685189f 100644 > --- a/net/wireless/sme.c > +++ b/net/wireless/sme.c > @@ -67,7 +67,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) > struct cfg80211_scan_request *request; > int n_channels, err; > > - ASSERT_RTNL(); > ASSERT_WDEV_LOCK(wdev); > > if (rdev->scan_req || rdev->scan_msg) > diff --git a/net/wireless/util.c b/net/wireless/util.c > index 1c39d6a2e850..39587ad2fb48 100644 > --- a/net/wireless/util.c > +++ b/net/wireless/util.c > @@ -891,7 +891,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) > { > struct wireless_dev *wdev; > > - ASSERT_RTNL(); > + lockdep_assert_held(&rdev->mtx); > > list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) > cfg80211_process_wdev_events(wdev); > -- > 2.20.1 >