Commit cdf0a0a8 authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: cfg80211: clean up links appropriately



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: default avatarJohannes Berg <johannes.berg@intel.com>
parent a95fe067
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);
		}
	}
@@ -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:
+5 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −9
Original line number Diff line number Diff line
@@ -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)
@@ -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;
@@ -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;
+43 −0
Original line number Diff line number Diff line
@@ -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);
}