Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>
Link: https://patch.msgid.link/20240906064426.2101315-6-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Aditya Kumar Singh and committed by
Johannes Berg
81f67d60 62c16f21

+82 -51
+4 -3
drivers/net/wireless/marvell/mwifiex/11h.c
··· 122 122 "CAC timer finished; No radar detected\n"); 123 123 cfg80211_cac_event(priv->netdev, &chandef, 124 124 NL80211_RADAR_CAC_FINISHED, 125 - GFP_KERNEL); 125 + GFP_KERNEL, 0); 126 126 } 127 127 } 128 128 ··· 182 182 "Aborting delayed work for CAC.\n"); 183 183 cancel_delayed_work_sync(&priv->dfs_cac_work); 184 184 cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, 185 - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); 185 + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 186 + 0); 186 187 } 187 188 } 188 189 ··· 222 221 cfg80211_cac_event(priv->netdev, 223 222 &priv->dfs_chandef, 224 223 NL80211_RADAR_DETECTED, 225 - GFP_KERNEL); 224 + GFP_KERNEL, 0); 226 225 } 227 226 break; 228 227 default:
+1 -1
drivers/net/wireless/marvell/mwifiex/cfg80211.c
··· 4205 4205 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, 4206 4206 struct net_device *dev, 4207 4207 struct cfg80211_chan_def *chandef, 4208 - u32 cac_time_ms) 4208 + u32 cac_time_ms, int link_id) 4209 4209 { 4210 4210 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 4211 4211 struct mwifiex_radar_params radar_params;
+1 -1
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
··· 837 837 static int qtnf_start_radar_detection(struct wiphy *wiphy, 838 838 struct net_device *ndev, 839 839 struct cfg80211_chan_def *chandef, 840 - u32 cac_time_ms) 840 + u32 cac_time_ms, int link_id) 841 841 { 842 842 struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev); 843 843 int ret;
+3 -3
drivers/net/wireless/quantenna/qtnfmac/event.c
··· 524 524 break; 525 525 526 526 cfg80211_cac_event(vif->netdev, &chandef, 527 - NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); 527 + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0); 528 528 break; 529 529 case QLINK_RADAR_CAC_ABORTED: 530 530 if (!vif->wdev.links[0].cac_started) 531 531 break; 532 532 533 533 cfg80211_cac_event(vif->netdev, &chandef, 534 - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); 534 + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); 535 535 break; 536 536 case QLINK_RADAR_CAC_STARTED: 537 537 if (vif->wdev.links[0].cac_started) ··· 542 542 break; 543 543 544 544 cfg80211_cac_event(vif->netdev, &chandef, 545 - NL80211_RADAR_CAC_STARTED, GFP_KERNEL); 545 + NL80211_RADAR_CAC_STARTED, GFP_KERNEL, 0); 546 546 break; 547 547 default: 548 548 pr_warn("%s: unhandled radar event %u\n",
+5 -3
include/net/cfg80211.h
··· 4837 4837 int (*start_radar_detection)(struct wiphy *wiphy, 4838 4838 struct net_device *dev, 4839 4839 struct cfg80211_chan_def *chandef, 4840 - u32 cac_time_ms); 4840 + u32 cac_time_ms, int link_id); 4841 4841 void (*end_cac)(struct wiphy *wiphy, 4842 - struct net_device *dev); 4842 + struct net_device *dev, unsigned int link_id); 4843 4843 int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, 4844 4844 struct cfg80211_update_ft_ies_params *ftie); 4845 4845 int (*crit_proto_start)(struct wiphy *wiphy, ··· 8741 8741 * @chandef: chandef for the current channel 8742 8742 * @event: type of event 8743 8743 * @gfp: context flags 8744 + * @link_id: valid link_id for MLO operation or 0 otherwise. 8744 8745 * 8745 8746 * This function is called when a Channel availability check (CAC) is finished 8746 8747 * or aborted. This must be called to notify the completion of a CAC process, ··· 8749 8748 */ 8750 8749 void cfg80211_cac_event(struct net_device *netdev, 8751 8750 const struct cfg80211_chan_def *chandef, 8752 - enum nl80211_radar_event event, gfp_t gfp); 8751 + enum nl80211_radar_event event, gfp_t gfp, 8752 + unsigned int link_id); 8753 8753 8754 8754 /** 8755 8755 * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
+3 -3
net/mac80211/cfg.c
··· 1667 1667 wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work); 1668 1668 cfg80211_cac_event(sdata->dev, &chandef, 1669 1669 NL80211_RADAR_CAC_ABORTED, 1670 - GFP_KERNEL); 1670 + GFP_KERNEL, 0); 1671 1671 } 1672 1672 1673 1673 drv_stop_ap(sdata->local, sdata, link_conf); ··· 3462 3462 static int ieee80211_start_radar_detection(struct wiphy *wiphy, 3463 3463 struct net_device *dev, 3464 3464 struct cfg80211_chan_def *chandef, 3465 - u32 cac_time_ms) 3465 + u32 cac_time_ms, int link_id) 3466 3466 { 3467 3467 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3468 3468 struct ieee80211_chan_req chanreq = { .oper = *chandef }; ··· 3490 3490 } 3491 3491 3492 3492 static void ieee80211_end_cac(struct wiphy *wiphy, 3493 - struct net_device *dev) 3493 + struct net_device *dev, unsigned int link_id) 3494 3494 { 3495 3495 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3496 3496 struct ieee80211_local *local = sdata->local;
+1 -1
net/mac80211/iface.c
··· 558 558 ieee80211_link_release_channel(&sdata->deflink); 559 559 cfg80211_cac_event(sdata->dev, &chandef, 560 560 NL80211_RADAR_CAC_ABORTED, 561 - GFP_KERNEL); 561 + GFP_KERNEL, 0); 562 562 } 563 563 564 564 if (sdata->vif.type == NL80211_IFTYPE_AP) {
+1 -1
net/mac80211/mlme.c
··· 3043 3043 ieee80211_link_release_channel(link); 3044 3044 cfg80211_cac_event(sdata->dev, &chandef, 3045 3045 NL80211_RADAR_CAC_FINISHED, 3046 - GFP_KERNEL); 3046 + GFP_KERNEL, 0); 3047 3047 } 3048 3048 } 3049 3049
+1 -1
net/mac80211/util.c
··· 3484 3484 cfg80211_cac_event(sdata->dev, 3485 3485 &chandef, 3486 3486 NL80211_RADAR_CAC_ABORTED, 3487 - GFP_KERNEL); 3487 + GFP_KERNEL, 0); 3488 3488 } 3489 3489 } 3490 3490 }
+5 -4
net/wireless/mlme.c
··· 1110 1110 1111 1111 void cfg80211_cac_event(struct net_device *netdev, 1112 1112 const struct cfg80211_chan_def *chandef, 1113 - enum nl80211_radar_event event, gfp_t gfp) 1113 + enum nl80211_radar_event event, gfp_t gfp, 1114 + unsigned int link_id) 1114 1115 { 1115 1116 struct wireless_dev *wdev = netdev->ieee80211_ptr; 1116 1117 struct wiphy *wiphy = wdev->wiphy; 1117 1118 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); 1118 1119 unsigned long timeout; 1119 1120 1120 - /* not yet supported */ 1121 - if (wdev->valid_links) 1121 + if (WARN_ON(wdev->valid_links && 1122 + !(wdev->valid_links & BIT(link_id)))) 1122 1123 return; 1123 1124 1124 - trace_cfg80211_cac_event(netdev, event); 1125 + trace_cfg80211_cac_event(netdev, event, link_id); 1125 1126 1126 1127 if (WARN_ON(!wdev->links[0].cac_started && 1127 1128 event != NL80211_RADAR_CAC_STARTED))
+19 -5
net/wireless/nl80211.c
··· 10121 10121 goto unlock; 10122 10122 } 10123 10123 10124 - if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) { 10124 + if (cfg80211_beaconing_iface_active(wdev)) { 10125 + /* During MLO other link(s) can beacon, only the current link 10126 + * can not already beacon 10127 + */ 10128 + if (wdev->valid_links && 10129 + !wdev->links[0].ap.beacon_interval) { 10130 + /* nothing */ 10131 + } else { 10132 + err = -EBUSY; 10133 + goto unlock; 10134 + } 10135 + } 10136 + 10137 + if (wdev->links[0].cac_started) { 10125 10138 err = -EBUSY; 10126 10139 goto unlock; 10127 10140 } ··· 10154 10141 if (WARN_ON(!cac_time_ms)) 10155 10142 cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; 10156 10143 10157 - err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms); 10144 + err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms, 10145 + 0); 10158 10146 if (!err) { 10159 10147 switch (wdev->iftype) { 10160 10148 case NL80211_IFTYPE_AP: ··· 16529 16515 SELECTOR(__sel, NETDEV_UP_NOTMX, \ 16530 16516 NL80211_FLAG_NEED_NETDEV_UP | \ 16531 16517 NL80211_FLAG_NO_WIPHY_MTX) \ 16532 - SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \ 16518 + SELECTOR(__sel, NETDEV_UP_NOTMX_MLO, \ 16533 16519 NL80211_FLAG_NEED_NETDEV_UP | \ 16534 16520 NL80211_FLAG_NO_WIPHY_MTX | \ 16535 - NL80211_FLAG_MLO_UNSUPPORTED) \ 16521 + NL80211_FLAG_MLO_VALID_LINK_ID) \ 16536 16522 SELECTOR(__sel, NETDEV_UP_CLEAR, \ 16537 16523 NL80211_FLAG_NEED_NETDEV_UP | \ 16538 16524 NL80211_FLAG_CLEAR_SKB) \ ··· 17427 17413 .flags = GENL_UNS_ADMIN_PERM, 17428 17414 .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP | 17429 17415 NL80211_FLAG_NO_WIPHY_MTX | 17430 - NL80211_FLAG_MLO_UNSUPPORTED), 17416 + NL80211_FLAG_MLO_VALID_LINK_ID), 17431 17417 }, 17432 17418 { 17433 17419 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
+7 -6
net/wireless/rdev-ops.h
··· 1200 1200 rdev_start_radar_detection(struct cfg80211_registered_device *rdev, 1201 1201 struct net_device *dev, 1202 1202 struct cfg80211_chan_def *chandef, 1203 - u32 cac_time_ms) 1203 + u32 cac_time_ms, int link_id) 1204 1204 { 1205 1205 int ret = -EOPNOTSUPP; 1206 1206 1207 1207 trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef, 1208 - cac_time_ms); 1208 + cac_time_ms, link_id); 1209 1209 if (rdev->ops->start_radar_detection) 1210 1210 ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev, 1211 - chandef, cac_time_ms); 1211 + chandef, cac_time_ms, 1212 + link_id); 1212 1213 trace_rdev_return_int(&rdev->wiphy, ret); 1213 1214 return ret; 1214 1215 } 1215 1216 1216 1217 static inline void 1217 1218 rdev_end_cac(struct cfg80211_registered_device *rdev, 1218 - struct net_device *dev) 1219 + struct net_device *dev, unsigned int link_id) 1219 1220 { 1220 - trace_rdev_end_cac(&rdev->wiphy, dev); 1221 + trace_rdev_end_cac(&rdev->wiphy, dev, link_id); 1221 1222 if (rdev->ops->end_cac) 1222 - rdev->ops->end_cac(&rdev->wiphy, dev); 1223 + rdev->ops->end_cac(&rdev->wiphy, dev, link_id); 1223 1224 trace_rdev_return_void(&rdev->wiphy); 1224 1225 } 1225 1226
+11 -8
net/wireless/reg.c
··· 4229 4229 static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev) 4230 4230 { 4231 4231 struct wireless_dev *wdev; 4232 + unsigned int link_id; 4233 + 4232 4234 /* If we finished CAC or received radar, we should end any 4233 4235 * CAC running on the same channels. 4234 4236 * the check !cfg80211_chandef_dfs_usable contain 2 options: ··· 4243 4241 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { 4244 4242 struct cfg80211_chan_def *chandef; 4245 4243 4246 - if (!wdev->links[0].cac_started) 4247 - continue; 4244 + for_each_valid_link(wdev, link_id) { 4245 + if (!wdev->links[link_id].cac_started) 4246 + continue; 4248 4247 4249 - /* FIXME: radar detection is tied to link 0 for now */ 4250 - chandef = wdev_chandef(wdev, 0); 4251 - if (!chandef) 4252 - continue; 4248 + chandef = wdev_chandef(wdev, link_id); 4249 + if (!chandef) 4250 + continue; 4253 4251 4254 - if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef)) 4255 - rdev_end_cac(rdev, wdev->netdev); 4252 + if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef)) 4253 + rdev_end_cac(rdev, wdev->netdev, link_id); 4254 + } 4256 4255 } 4257 4256 } 4258 4257
+20 -11
net/wireless/trace.h
··· 806 806 ); 807 807 808 808 TRACE_EVENT(rdev_end_cac, 809 - TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), 810 - TP_ARGS(wiphy, netdev), 809 + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, 810 + unsigned int link_id), 811 + TP_ARGS(wiphy, netdev, link_id), 811 812 TP_STRUCT__entry( 812 813 WIPHY_ENTRY 813 814 NETDEV_ENTRY 815 + __field(unsigned int, link_id) 814 816 ), 815 817 TP_fast_assign( 816 818 WIPHY_ASSIGN; 817 819 NETDEV_ASSIGN; 820 + __entry->link_id = link_id; 818 821 ), 819 - TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG) 822 + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d", 823 + WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id) 820 824 ); 821 825 822 826 DECLARE_EVENT_CLASS(station_add_change, ··· 2665 2661 TRACE_EVENT(rdev_start_radar_detection, 2666 2662 TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, 2667 2663 struct cfg80211_chan_def *chandef, 2668 - u32 cac_time_ms), 2669 - TP_ARGS(wiphy, netdev, chandef, cac_time_ms), 2664 + u32 cac_time_ms, int link_id), 2665 + TP_ARGS(wiphy, netdev, chandef, cac_time_ms, link_id), 2670 2666 TP_STRUCT__entry( 2671 2667 WIPHY_ENTRY 2672 2668 NETDEV_ENTRY 2673 2669 CHAN_DEF_ENTRY 2674 2670 __field(u32, cac_time_ms) 2671 + __field(int, link_id) 2675 2672 ), 2676 2673 TP_fast_assign( 2677 2674 WIPHY_ASSIGN; 2678 2675 NETDEV_ASSIGN; 2679 2676 CHAN_DEF_ASSIGN(chandef); 2680 2677 __entry->cac_time_ms = cac_time_ms; 2678 + __entry->link_id = link_id; 2681 2679 ), 2682 2680 TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT 2683 - ", cac_time_ms=%u", 2681 + ", cac_time_ms=%u, link_id=%d", 2684 2682 WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG, 2685 - __entry->cac_time_ms) 2683 + __entry->cac_time_ms, __entry->link_id) 2686 2684 ); 2687 2685 2688 2686 TRACE_EVENT(rdev_set_mcast_rate, ··· 3498 3492 ); 3499 3493 3500 3494 TRACE_EVENT(cfg80211_cac_event, 3501 - TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt), 3502 - TP_ARGS(netdev, evt), 3495 + TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt, 3496 + unsigned int link_id), 3497 + TP_ARGS(netdev, evt, link_id), 3503 3498 TP_STRUCT__entry( 3504 3499 NETDEV_ENTRY 3505 3500 __field(enum nl80211_radar_event, evt) 3501 + __field(unsigned int, link_id) 3506 3502 ), 3507 3503 TP_fast_assign( 3508 3504 NETDEV_ASSIGN; 3509 3505 __entry->evt = evt; 3506 + __entry->link_id = link_id; 3510 3507 ), 3511 - TP_printk(NETDEV_PR_FMT ", event: %d", 3512 - NETDEV_PR_ARG, __entry->evt) 3508 + TP_printk(NETDEV_PR_FMT ", event: %d, link_id=%u", 3509 + NETDEV_PR_ARG, __entry->evt, __entry->link_id) 3513 3510 ); 3514 3511 3515 3512 DECLARE_EVENT_CLASS(cfg80211_rx_evt,