summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h12
-rw-r--r--net/wireless/nl80211.c14
-rw-r--r--net/wireless/rdev-ops.h26
-rw-r--r--net/wireless/trace.h20
4 files changed, 70 insertions, 2 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a4f9e6094118..5706f96b819a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3858,6 +3858,11 @@ struct mgmt_frame_regs {
* keep the struct wireless_dev's iftype updated.
* This additionally holds the RTNL to be able to do netdev changes.
*
+ * @add_intf_link: Add a new MLO link to the given interface. Note that
+ * the wdev->link[] data structure has been updated, so the new link
+ * address is available.
+ * @del_intf_link: Remove an MLO link from the given interface.
+ *
* @add_key: add a key with the given parameters. @mac_addr will be %NULL
* when adding a group key.
*
@@ -4212,6 +4217,13 @@ struct cfg80211_ops {
enum nl80211_iftype type,
struct vif_params *params);
+ int (*add_intf_link)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ unsigned int link_id);
+ void (*del_intf_link)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ unsigned int link_id);
+
int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool pairwise, const u8 *mac_addr,
struct key_params *params);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9bc66a21ac3a..0a69a5a6b74d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15556,9 +15556,11 @@ static int nl80211_set_fils_aad(struct sk_buff *skb,
static int nl80211_add_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;
+ int ret;
if (!(wdev->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
return -EINVAL;
@@ -15578,13 +15580,20 @@ static int nl80211_add_link(struct sk_buff *skb, struct genl_info *info)
wdev->valid_links |= BIT(link_id);
ether_addr_copy(wdev->links[link_id].addr,
nla_data(info->attrs[NL80211_ATTR_MAC]));
+
+ ret = rdev_add_intf_link(rdev, wdev, link_id);
+ if (ret) {
+ wdev->valid_links &= ~BIT(link_id);
+ eth_zero_addr(wdev->links[link_id].addr);
+ }
wdev_unlock(wdev);
- return 0;
+ return ret;
}
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;
@@ -15604,6 +15613,9 @@ static int nl80211_remove_link(struct sk_buff *skb, struct genl_info *info)
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);
wdev_unlock(wdev);
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d2300eff03ae..a329ba036989 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1422,4 +1422,30 @@ rdev_set_radar_background(struct cfg80211_registered_device *rdev,
return ret;
}
+static inline int
+rdev_add_intf_link(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ unsigned int link_id)
+{
+ int ret = 0;
+
+ trace_rdev_add_intf_link(&rdev->wiphy, wdev, link_id);
+ if (rdev->ops->add_intf_link)
+ ret = rdev->ops->add_intf_link(&rdev->wiphy, wdev, link_id);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+
+ return ret;
+}
+
+static inline void
+rdev_del_intf_link(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ unsigned int link_id)
+{
+ trace_rdev_del_intf_link(&rdev->wiphy, wdev, link_id);
+ if (rdev->ops->add_intf_link)
+ rdev->ops->add_intf_link(&rdev->wiphy, wdev, link_id);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 92742430958e..65f8b814ecd0 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2064,7 +2064,7 @@ TRACE_EVENT(rdev_set_noack_map,
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
);
-TRACE_EVENT(rdev_get_channel,
+DECLARE_EVENT_CLASS(wiphy_wdev_link_evt,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
unsigned int link_id),
TP_ARGS(wiphy, wdev, link_id),
@@ -2082,6 +2082,12 @@ TRACE_EVENT(rdev_get_channel,
WIPHY_PR_ARG, WDEV_PR_ARG, __entry->link_id)
);
+DEFINE_EVENT(wiphy_wdev_link_evt, rdev_get_channel,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, wdev, link_id)
+);
+
TRACE_EVENT(rdev_return_chandef,
TP_PROTO(struct wiphy *wiphy, int ret,
struct cfg80211_chan_def *chandef),
@@ -2823,6 +2829,18 @@ TRACE_EVENT(rdev_set_radar_background,
WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
);
+DEFINE_EVENT(wiphy_wdev_link_evt, rdev_add_intf_link,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, wdev, link_id)
+);
+
+DEFINE_EVENT(wiphy_wdev_link_evt, rdev_del_intf_link,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, wdev, link_id)
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/