]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: cfg80211: handle DFS per link
authorAditya Kumar Singh <quic_adisi@quicinc.com>
Fri, 6 Sep 2024 06:44:23 +0000 (12:14 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 6 Sep 2024 11:01:05 +0000 (13:01 +0200)
Currently, during starting a radar detection, no link id information is
parsed and passed down. In order to support starting radar detection
during Multi Link Operation, it is required to pass link id as well.

Add changes to first parse and then pass link id in the start radar
detection path.

Additionally, update notification APIs to allow drivers/mac80211 to
pass the link ID.

However, everything is handled at link 0 only until all API's are ready to
handle it per link.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-6-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
14 files changed:
drivers/net/wireless/marvell/mwifiex/11h.c
drivers/net/wireless/marvell/mwifiex/cfg80211.c
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
drivers/net/wireless/quantenna/qtnfmac/event.c
include/net/cfg80211.h
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/util.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/trace.h

index fb2cad0967580fc44ca19fcc5a1ab81056195303..032b93a41d995692216b9f4c93ef49d353e9d367 100644 (file)
@@ -122,7 +122,7 @@ void mwifiex_dfs_cac_work_queue(struct work_struct *work)
                            "CAC timer finished; No radar detected\n");
                cfg80211_cac_event(priv->netdev, &chandef,
                                   NL80211_RADAR_CAC_FINISHED,
-                                  GFP_KERNEL);
+                                  GFP_KERNEL, 0);
        }
 }
 
@@ -182,7 +182,8 @@ void mwifiex_abort_cac(struct mwifiex_private *priv)
                            "Aborting delayed work for CAC.\n");
                cancel_delayed_work_sync(&priv->dfs_cac_work);
                cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
-                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL,
+                                  0);
        }
 }
 
@@ -221,7 +222,7 @@ int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv,
                                cfg80211_cac_event(priv->netdev,
                                                   &priv->dfs_chandef,
                                                   NL80211_RADAR_DETECTED,
-                                                  GFP_KERNEL);
+                                                  GFP_KERNEL, 0);
                        }
                        break;
                default:
index 9d154c42465e910ea47126fb06513213be4b608a..fca3eea7ee842150e438181da7a060314a53c516 100644 (file)
@@ -4205,7 +4205,7 @@ static int
 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       struct cfg80211_chan_def *chandef,
-                                      u32 cac_time_ms)
+                                      u32 cac_time_ms, int link_id)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        struct mwifiex_radar_params radar_params;
index 663d77770fce70d63935743ed23727be5eeae1b6..8b97accf6638fc93791ea8cd394fa3b1c6c757f5 100644 (file)
@@ -837,7 +837,7 @@ static int qtnf_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 static int qtnf_start_radar_detection(struct wiphy *wiphy,
                                      struct net_device *ndev,
                                      struct cfg80211_chan_def *chandef,
-                                     u32 cac_time_ms)
+                                     u32 cac_time_ms, int link_id)
 {
        struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
        int ret;
index 8bd1e14e5de9ddd16348333192b09f9e67aa0dff..71840f41b73ce1c9b077b19d8d1d9b873e639c8e 100644 (file)
@@ -524,14 +524,14 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
                        break;
 
                cfg80211_cac_event(vif->netdev, &chandef,
-                                  NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+                                  NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
                break;
        case QLINK_RADAR_CAC_ABORTED:
                if (!vif->wdev.links[0].cac_started)
                        break;
 
                cfg80211_cac_event(vif->netdev, &chandef,
-                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+                                  NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
                break;
        case QLINK_RADAR_CAC_STARTED:
                if (vif->wdev.links[0].cac_started)
@@ -542,7 +542,7 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif,
                        break;
 
                cfg80211_cac_event(vif->netdev, &chandef,
-                                  NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
+                                  NL80211_RADAR_CAC_STARTED, GFP_KERNEL, 0);
                break;
        default:
                pr_warn("%s: unhandled radar event %u\n",
index 727a94a6b7c3e98229aa0c21ea191eecca316aa7..efdea667cb923950a45a280c6300fb351473e31e 100644 (file)
@@ -4837,9 +4837,9 @@ struct cfg80211_ops {
        int     (*start_radar_detection)(struct wiphy *wiphy,
                                         struct net_device *dev,
                                         struct cfg80211_chan_def *chandef,
-                                        u32 cac_time_ms);
+                                        u32 cac_time_ms, int link_id);
        void    (*end_cac)(struct wiphy *wiphy,
-                               struct net_device *dev);
+                          struct net_device *dev, unsigned int link_id);
        int     (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
                                 struct cfg80211_update_ft_ies_params *ftie);
        int     (*crit_proto_start)(struct wiphy *wiphy,
@@ -8741,6 +8741,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
  * @chandef: chandef for the current channel
  * @event: type of event
  * @gfp: context flags
+ * @link_id: valid link_id for MLO operation or 0 otherwise.
  *
  * This function is called when a Channel availability check (CAC) is finished
  * or aborted. This must be called to notify the completion of a CAC process,
@@ -8748,7 +8749,8 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
  */
 void cfg80211_cac_event(struct net_device *netdev,
                        const struct cfg80211_chan_def *chandef,
-                       enum nl80211_radar_event event, gfp_t gfp);
+                       enum nl80211_radar_event event, gfp_t gfp,
+                       unsigned int link_id);
 
 /**
  * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
index 5725ab6f495f2e18c3bd378f9cf6139d4fb8ef4f..67dd780530fbe620520115fbaa0374a3da229a66 100644 (file)
@@ -1667,7 +1667,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
                wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
                cfg80211_cac_event(sdata->dev, &chandef,
                                   NL80211_RADAR_CAC_ABORTED,
-                                  GFP_KERNEL);
+                                  GFP_KERNEL, 0);
        }
 
        drv_stop_ap(sdata->local, sdata, link_conf);
@@ -3462,7 +3462,7 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
 static int ieee80211_start_radar_detection(struct wiphy *wiphy,
                                           struct net_device *dev,
                                           struct cfg80211_chan_def *chandef,
-                                          u32 cac_time_ms)
+                                          u32 cac_time_ms, int link_id)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_chan_req chanreq = { .oper = *chandef };
@@ -3490,7 +3490,7 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
 }
 
 static void ieee80211_end_cac(struct wiphy *wiphy,
-                             struct net_device *dev)
+                             struct net_device *dev, unsigned int link_id)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
index bdaf8e215965f60d578888eda1002abd67259e98..e074de893ed6c1c77fe84ee22f5bb5bab551821e 100644 (file)
@@ -558,7 +558,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
                ieee80211_link_release_channel(&sdata->deflink);
                cfg80211_cac_event(sdata->dev, &chandef,
                                   NL80211_RADAR_CAC_ABORTED,
-                                  GFP_KERNEL);
+                                  GFP_KERNEL, 0);
        }
 
        if (sdata->vif.type == NL80211_IFTYPE_AP) {
index 79579c89e281a1908abd23f9415bf242e3fc3012..715709860fdd37db744df3b526230689943f506d 100644 (file)
@@ -3043,7 +3043,7 @@ void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work)
                ieee80211_link_release_channel(link);
                cfg80211_cac_event(sdata->dev, &chandef,
                                   NL80211_RADAR_CAC_FINISHED,
-                                  GFP_KERNEL);
+                                  GFP_KERNEL, 0);
        }
 }
 
index ab17361dba970bde1182f8fc23c2a77d1d386013..c4fd60fbcfd41d5ce86ab55def42bfc991d1afa5 100644 (file)
@@ -3484,7 +3484,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
                        cfg80211_cac_event(sdata->dev,
                                           &chandef,
                                           NL80211_RADAR_CAC_ABORTED,
-                                          GFP_KERNEL);
+                                          GFP_KERNEL, 0);
                }
        }
 }
index fddd6a62b94200b1b8604d58394cf4ed107ac6ce..115c8cd28aafaa835b6d9dbe408e1708b71f769a 100644 (file)
@@ -1110,18 +1110,19 @@ EXPORT_SYMBOL(__cfg80211_radar_event);
 
 void cfg80211_cac_event(struct net_device *netdev,
                        const struct cfg80211_chan_def *chandef,
-                       enum nl80211_radar_event event, gfp_t gfp)
+                       enum nl80211_radar_event event, gfp_t gfp,
+                       unsigned int link_id)
 {
        struct wireless_dev *wdev = netdev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
        unsigned long timeout;
 
-       /* not yet supported */
-       if (wdev->valid_links)
+       if (WARN_ON(wdev->valid_links &&
+                   !(wdev->valid_links & BIT(link_id))))
                return;
 
-       trace_cfg80211_cac_event(netdev, event);
+       trace_cfg80211_cac_event(netdev, event, link_id);
 
        if (WARN_ON(!wdev->links[0].cac_started &&
                    event != NL80211_RADAR_CAC_STARTED))
index f4fdf32d5d07ce3bc35a99773610d81dd85e46ef..7d9264304a8afcba4a5f6490ecaa53c8c3c4e958 100644 (file)
@@ -10121,7 +10121,20 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
                goto unlock;
        }
 
-       if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
+       if (cfg80211_beaconing_iface_active(wdev)) {
+               /* During MLO other link(s) can beacon, only the current link
+                * can not already beacon
+                */
+               if (wdev->valid_links &&
+                   !wdev->links[0].ap.beacon_interval) {
+                       /* nothing */
+               } else {
+                       err = -EBUSY;
+                       goto unlock;
+               }
+       }
+
+       if (wdev->links[0].cac_started) {
                err = -EBUSY;
                goto unlock;
        }
@@ -10141,7 +10154,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        if (WARN_ON(!cac_time_ms))
                cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
 
-       err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
+       err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
+                                        0);
        if (!err) {
                switch (wdev->iftype) {
                case NL80211_IFTYPE_AP:
@@ -16515,10 +16529,10 @@ nl80211_set_ttlm(struct sk_buff *skb, struct genl_info *info)
        SELECTOR(__sel, NETDEV_UP_NOTMX,                \
                 NL80211_FLAG_NEED_NETDEV_UP |          \
                 NL80211_FLAG_NO_WIPHY_MTX)             \
-       SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO,          \
+       SELECTOR(__sel, NETDEV_UP_NOTMX_MLO,            \
                 NL80211_FLAG_NEED_NETDEV_UP |          \
                 NL80211_FLAG_NO_WIPHY_MTX |            \
-                NL80211_FLAG_MLO_UNSUPPORTED)          \
+                NL80211_FLAG_MLO_VALID_LINK_ID)        \
        SELECTOR(__sel, NETDEV_UP_CLEAR,                \
                 NL80211_FLAG_NEED_NETDEV_UP |          \
                 NL80211_FLAG_CLEAR_SKB)                \
@@ -17413,7 +17427,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
                .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
                                         NL80211_FLAG_NO_WIPHY_MTX |
-                                        NL80211_FLAG_MLO_UNSUPPORTED),
+                                        NL80211_FLAG_MLO_VALID_LINK_ID),
        },
        {
                .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
index ec3f4aa1c807b95dff39d6573fc4074a5180cdfe..f5adbf6b5c846c1f8e565837abd71033c7b47097 100644 (file)
@@ -1200,26 +1200,27 @@ static inline int
 rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
                           struct net_device *dev,
                           struct cfg80211_chan_def *chandef,
-                          u32 cac_time_ms)
+                          u32 cac_time_ms, int link_id)
 {
        int ret = -EOPNOTSUPP;
 
        trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef,
-                                        cac_time_ms);
+                                        cac_time_ms, link_id);
        if (rdev->ops->start_radar_detection)
                ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev,
-                                                      chandef, cac_time_ms);
+                                                      chandef, cac_time_ms,
+                                                      link_id);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
 
 static inline void
 rdev_end_cac(struct cfg80211_registered_device *rdev,
-            struct net_device *dev)
+            struct net_device *dev, unsigned int link_id)
 {
-       trace_rdev_end_cac(&rdev->wiphy, dev);
+       trace_rdev_end_cac(&rdev->wiphy, dev, link_id);
        if (rdev->ops->end_cac)
-               rdev->ops->end_cac(&rdev->wiphy, dev);
+               rdev->ops->end_cac(&rdev->wiphy, dev, link_id);
        trace_rdev_return_void(&rdev->wiphy);
 }
 
index 898abc6d0609b1025a11f7e383c678799fb6cd23..6489ba943a633dd43a023f15b4dfc512d3975c7f 100644 (file)
@@ -4229,6 +4229,8 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed);
 static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
 {
        struct wireless_dev *wdev;
+       unsigned int link_id;
+
        /* If we finished CAC or received radar, we should end any
         * CAC running on the same channels.
         * the check !cfg80211_chandef_dfs_usable contain 2 options:
@@ -4241,16 +4243,17 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
        list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                struct cfg80211_chan_def *chandef;
 
-               if (!wdev->links[0].cac_started)
-                       continue;
+               for_each_valid_link(wdev, link_id) {
+                       if (!wdev->links[link_id].cac_started)
+                               continue;
 
-               /* FIXME: radar detection is tied to link 0 for now */
-               chandef = wdev_chandef(wdev, 0);
-               if (!chandef)
-                       continue;
+                       chandef = wdev_chandef(wdev, link_id);
+                       if (!chandef)
+                               continue;
 
-               if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
-                       rdev_end_cac(rdev, wdev->netdev);
+                       if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
+                               rdev_end_cac(rdev, wdev->netdev, link_id);
+               }
        }
 }
 
index 7fc7de9bcc3490be54dc48fb5dbc1162230573e6..97c21b627791a385349b7b689b9127b6a423b530 100644 (file)
@@ -806,17 +806,21 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
 );
 
 TRACE_EVENT(rdev_end_cac,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
-       TP_ARGS(wiphy, netdev),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                unsigned int link_id),
+       TP_ARGS(wiphy, netdev, link_id),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
+               __field(unsigned int, link_id)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
+               __entry->link_id = link_id;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id)
 );
 
 DECLARE_EVENT_CLASS(station_add_change,
@@ -2661,24 +2665,26 @@ TRACE_EVENT(rdev_external_auth,
 TRACE_EVENT(rdev_start_radar_detection,
        TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
                 struct cfg80211_chan_def *chandef,
-                u32 cac_time_ms),
-       TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
+                u32 cac_time_ms, int link_id),
+       TP_ARGS(wiphy, netdev, chandef, cac_time_ms, link_id),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
                CHAN_DEF_ENTRY
                __field(u32, cac_time_ms)
+               __field(int, link_id)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
                CHAN_DEF_ASSIGN(chandef);
                __entry->cac_time_ms = cac_time_ms;
+               __entry->link_id = link_id;
        ),
        TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
-                 ", cac_time_ms=%u",
+                 ", cac_time_ms=%u, link_id=%d",
                  WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
-                 __entry->cac_time_ms)
+                 __entry->cac_time_ms, __entry->link_id)
 );
 
 TRACE_EVENT(rdev_set_mcast_rate,
@@ -3492,18 +3498,21 @@ TRACE_EVENT(cfg80211_radar_event,
 );
 
 TRACE_EVENT(cfg80211_cac_event,
-       TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt),
-       TP_ARGS(netdev, evt),
+       TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt,
+                unsigned int link_id),
+       TP_ARGS(netdev, evt, link_id),
        TP_STRUCT__entry(
                NETDEV_ENTRY
                __field(enum nl80211_radar_event, evt)
+               __field(unsigned int, link_id)
        ),
        TP_fast_assign(
                NETDEV_ASSIGN;
                __entry->evt = evt;
+               __entry->link_id = link_id;
        ),
-       TP_printk(NETDEV_PR_FMT ",  event: %d",
-                 NETDEV_PR_ARG, __entry->evt)
+       TP_printk(NETDEV_PR_FMT ",  event: %d, link_id=%u",
+                 NETDEV_PR_ARG, __entry->evt, __entry->link_id)
 );
 
 DECLARE_EVENT_CLASS(cfg80211_rx_evt,