Skip to content

Commit

Permalink
wifi: cfg80211: clean up links appropriately
Browse files Browse the repository at this point in the history
This was missing earlier, we need to remove links when
interfaces are being destroyed, and we also need to
stop (AP) operations when a link is being destroyed.
Address these issues to remove many warnings that will
otherwise appear in mac80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
jmberg-intel committed Jul 15, 2022
1 parent a95fe06 commit cdf0a0a
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 10 deletions.
3 changes: 2 additions & 1 deletion net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)

wiphy_lock(&rdev->wiphy);
cfg80211_leave(rdev, wdev);
rdev_del_virtual_intf(rdev, wdev);
cfg80211_remove_virtual_intf(rdev, wdev);
wiphy_unlock(&rdev->wiphy);
}
}
Expand Down Expand Up @@ -1437,6 +1437,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
case NETDEV_GOING_DOWN:
wiphy_lock(&rdev->wiphy);
cfg80211_leave(rdev, wdev);
cfg80211_remove_links(wdev);
wiphy_unlock(&rdev->wiphy);
break;
case NETDEV_DOWN:
Expand Down
5 changes: 5 additions & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,4 +562,9 @@ void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
void cfg80211_pmsr_free_wk(struct work_struct *work);

void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id);
void cfg80211_remove_links(struct wireless_dev *wdev);
int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);

#endif /* __NET_WIRELESS_CORE_H */
11 changes: 2 additions & 9 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -4279,7 +4279,7 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)

mutex_lock(&rdev->wiphy.mtx);

return rdev_del_virtual_intf(rdev, wdev);
return cfg80211_remove_virtual_intf(rdev, wdev);
}

static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
Expand Down Expand Up @@ -15707,7 +15707,6 @@ static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)

static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
unsigned int link_id = nl80211_link_id(info->attrs);
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
Expand All @@ -15723,14 +15722,8 @@ static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}

/* FIXME: stop the link operations first */

wdev_lock(wdev);
wdev->valid_links &= ~BIT(link_id);

rdev_del_intf_link(rdev, wdev, link_id);

eth_zero_addr(wdev->links[link_id].addr);
cfg80211_remove_link(wdev, link_id);
wdev_unlock(wdev);

return 0;
Expand Down
43 changes: 43 additions & 0 deletions net/wireless/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2447,3 +2447,46 @@ bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
return false;
}
EXPORT_SYMBOL(cfg80211_iftype_allowed);

void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);

ASSERT_WDEV_LOCK(wdev);

switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
__cfg80211_stop_ap(rdev, wdev->netdev, link_id, true);
break;
default:
/* per-link not relevant */
break;
}

wdev->valid_links &= ~BIT(link_id);

rdev_del_intf_link(rdev, wdev, link_id);

eth_zero_addr(wdev->links[link_id].addr);
}

void cfg80211_remove_links(struct wireless_dev *wdev)
{
unsigned int link_id;

wdev_lock(wdev);
if (wdev->valid_links) {
for_each_valid_link(wdev, link_id)
cfg80211_remove_link(wdev, link_id);
}
wdev_unlock(wdev);
}

int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
{
cfg80211_remove_links(wdev);

return rdev_del_virtual_intf(rdev, wdev);
}

0 comments on commit cdf0a0a

Please sign in to comment.