| From f08e9c0b36a76033554c0fc89b6e3cfbf8019d8c Mon Sep 17 00:00:00 2001 |
| From: Aditya Kumar Singh <quic_adisi@quicinc.com> |
| Date: Thu, 11 Jul 2024 09:21:44 +0530 |
| Subject: [PATCH 13/89] bp: wifi: cfg80211: handle DFS per link |
| |
| 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> |
| --- |
| drivers/net/wireless/marvell/mwifiex/11h.c | 7 +++-- |
| .../net/wireless/marvell/mwifiex/cfg80211.c | 2 +- |
| .../net/wireless/quantenna/qtnfmac/cfg80211.c | 2 +- |
| .../net/wireless/quantenna/qtnfmac/event.c | 6 ++-- |
| include/net/cfg80211.h | 8 +++-- |
| net/mac80211/cfg.c | 6 ++-- |
| net/mac80211/iface.c | 2 +- |
| net/mac80211/mlme.c | 2 +- |
| net/mac80211/util.c | 2 +- |
| net/wireless/mlme.c | 9 +++--- |
| net/wireless/nl80211.c | 24 +++++++++++--- |
| net/wireless/rdev-ops.h | 13 ++++---- |
| net/wireless/reg.c | 19 +++++++----- |
| net/wireless/trace.h | 31 ++++++++++++------- |
| 14 files changed, 82 insertions(+), 51 deletions(-) |
| |
| diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c |
| index fb2cad0..032b93a 100644 |
| --- a/drivers/net/wireless/marvell/mwifiex/11h.c |
| +++ b/drivers/net/wireless/marvell/mwifiex/11h.c |
| @@ -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: |
| diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c |
| index 436d391..18fe850 100644 |
| --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c |
| +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c |
| @@ -4145,7 +4145,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; |
| diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |
| index 663d777..8b97acc 100644 |
| --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |
| +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c |
| @@ -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; |
| diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c |
| index 8bd1e14..71840f4 100644 |
| --- a/drivers/net/wireless/quantenna/qtnfmac/event.c |
| +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c |
| @@ -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", |
| diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h |
| index 86634cc..906e48b 100644 |
| --- a/include/net/cfg80211.h |
| +++ b/include/net/cfg80211.h |
| @@ -4846,9 +4846,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, |
| @@ -8762,6 +8762,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, |
| @@ -8769,7 +8770,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 |
| diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c |
| index 4d5eb60..cf60420 100644 |
| --- a/net/mac80211/cfg.c |
| +++ b/net/mac80211/cfg.c |
| @@ -1661,7 +1661,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); |
| @@ -3455,7 +3455,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 }; |
| @@ -3483,7 +3483,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; |
| diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c |
| index f0d9024..71e8b0d 100644 |
| --- a/net/mac80211/iface.c |
| +++ b/net/mac80211/iface.c |
| @@ -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) { |
| diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c |
| index 2258858..2c7a3dc 100644 |
| --- a/net/mac80211/mlme.c |
| +++ b/net/mac80211/mlme.c |
| @@ -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); |
| } |
| } |
| |
| diff --git a/net/mac80211/util.c b/net/mac80211/util.c |
| index 424d8d6..5996ea7 100644 |
| --- a/net/mac80211/util.c |
| +++ b/net/mac80211/util.c |
| @@ -3468,7 +3468,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); |
| } |
| } |
| } |
| diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c |
| index eda999d..7d52222 100644 |
| --- a/net/wireless/mlme.c |
| +++ b/net/wireless/mlme.c |
| @@ -1111,18 +1111,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)) |
| diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c |
| index 3e87f5a..6893256 100644 |
| --- a/net/wireless/nl80211.c |
| +++ b/net/wireless/nl80211.c |
| @@ -10154,7 +10154,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; |
| } |
| @@ -10174,7 +10187,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) { |
| wdev->links[0].ap.chandef = chandef; |
| wdev->links[0].cac_started = true; |
| @@ -16531,10 +16545,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) \ |
| @@ -17441,7 +17455,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, |
| diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h |
| index 951ca95..4e8c895 100644 |
| --- a/net/wireless/rdev-ops.h |
| +++ b/net/wireless/rdev-ops.h |
| @@ -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); |
| } |
| |
| diff --git a/net/wireless/reg.c b/net/wireless/reg.c |
| index 0040862..1a393f3 100644 |
| --- a/net/wireless/reg.c |
| +++ b/net/wireless/reg.c |
| @@ -4233,6 +4233,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: |
| @@ -4245,16 +4247,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); |
| + } |
| } |
| } |
| |
| diff --git a/net/wireless/trace.h b/net/wireless/trace.h |
| index 881c01d..a831f94 100644 |
| --- a/net/wireless/trace.h |
| +++ b/net/wireless/trace.h |
| @@ -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, |
| -- |
| 2.18.0 |
| |