mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
wifi: nl80211: allow device lookup under RCU
We already modify our wiphy/wdev lists in RCU-safe ways, so we can do lookups in RCU critical sections. Prepare more of the code to be able to do that. Link: https://patch.msgid.link/20261006120655.86d9cf36d8bb.I07b7ce5a69391d5168dc31c598b5079917a29bff@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
bf49114633
commit
57b1607464
|
|
@ -57,13 +57,13 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
|
|||
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
|
||||
"Disable 40MHz support in the 2.4GHz band");
|
||||
|
||||
/* requires RCU or rtnl */
|
||||
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
|
||||
{
|
||||
struct cfg80211_registered_device *result = NULL, *rdev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
for_each_rdev(rdev) {
|
||||
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list,
|
||||
lockdep_rtnl_is_held()) {
|
||||
if (rdev->wiphy_idx == wiphy_idx) {
|
||||
result = rdev;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
/* returns ERR_PTR values */
|
||||
/* returns ERR_PTR values, requires RCU or rtnl if rdev is %NULL */
|
||||
static struct wireless_dev *
|
||||
__cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
|
||||
struct net *netns, struct nlattr **attrs)
|
||||
|
|
@ -105,9 +105,8 @@ __cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
|
|||
return result ?: ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
for_each_rdev(rdev) {
|
||||
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list,
|
||||
lockdep_rtnl_is_held()) {
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
if (wiphy_net(&rdev->wiphy) != netns)
|
||||
|
|
@ -116,7 +115,8 @@ __cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
|
|||
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list,
|
||||
lockdep_rtnl_is_held()) {
|
||||
if (have_ifidx && wdev->netdev &&
|
||||
wdev->netdev->ifindex == ifidx) {
|
||||
result = wdev;
|
||||
|
|
@ -137,14 +137,13 @@ __cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev,
|
|||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
/* requires RCU or rtnl */
|
||||
static struct cfg80211_registered_device *
|
||||
__cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = NULL, *tmp;
|
||||
struct net_device *netdev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (!attrs[NL80211_ATTR_WIPHY] &&
|
||||
!attrs[NL80211_ATTR_IFINDEX] &&
|
||||
!attrs[NL80211_ATTR_WDEV])
|
||||
|
|
@ -162,7 +161,8 @@ __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->wiphy.wdev_list, list) {
|
||||
list_for_each_entry_rcu(wdev, &tmp->wiphy.wdev_list,
|
||||
list, lockdep_rtnl_is_held()) {
|
||||
if (wdev->identifier != (u32)wdev_id)
|
||||
continue;
|
||||
found = true;
|
||||
|
|
@ -181,14 +181,16 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
if (attrs[NL80211_ATTR_IFINDEX]) {
|
||||
int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
|
||||
|
||||
netdev = __dev_get_by_index(netns, ifindex);
|
||||
if (netdev) {
|
||||
if (netdev->ieee80211_ptr)
|
||||
tmp = wiphy_to_rdev(
|
||||
netdev->ieee80211_ptr->wiphy);
|
||||
else
|
||||
tmp = NULL;
|
||||
/* RCU required for dev_get_by_index_rcu() if we have RTNL */
|
||||
rcu_read_lock();
|
||||
netdev = dev_get_by_index_rcu(netns, ifindex);
|
||||
if (netdev && netdev->ieee80211_ptr)
|
||||
tmp = wiphy_to_rdev(netdev->ieee80211_ptr->wiphy);
|
||||
else
|
||||
tmp = NULL;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (netdev) {
|
||||
/* not wireless device -- return error */
|
||||
if (!tmp)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user