cfg80211 supports NL80211_CMD_SET_SMD_CTX on the target AP MLD for
userspace to program the station's dynamic context on the TX and RX
queues.

Add mac80211 support to handle this command in driver and lower layers
so that the context is installed and the target AP MLD is ready to
continue data transfer with the non-AP MLD from where it may have left
off at the current AP MLD. This facilitates the seamless roaming benefit
of the SMD BSS Transition procedure.

Signed-off-by: Pooventhiran G <[email protected]>
---
 include/net/mac80211.h    |  5 +++++
 net/mac80211/cfg.c        | 26 +++++++++++++++++++++++++
 net/mac80211/driver-ops.h | 24 +++++++++++++++++++++++
 net/mac80211/trace.h      | 49 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 104 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a377a16da5c4..9b451628f248 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4786,6 +4786,8 @@ enum ieee80211_sta_smd_state {
  * @sta_smd_state: Notifies low level driver about IEEE 802.11bn SMD substate
  *     transition of a station. It must not fail while transitioning down.
  *     The callback can sleep.
+ * @set_smd_ctx: Set the UHR SMD context for the non-AP MLD. This is used on
+ *     the target AP MLD side to program dynamic context.
  */
 struct ieee80211_ops {
        void (*tx)(struct ieee80211_hw *hw,
@@ -5192,6 +5194,9 @@ struct ieee80211_ops {
                             struct ieee80211_sta *sta,
                             enum ieee80211_sta_smd_state old_state,
                             enum ieee80211_sta_smd_state new_state);
+       int (*set_smd_ctx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
+                          struct cfg80211_smd_transition_info *st_info);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0ea8b610a771..2cf0e80137a7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -6081,6 +6081,31 @@ ieee80211_set_peer_nan_sched(struct wiphy *wiphy,
        return ieee80211_nan_set_peer_sched(sdata, sched);
 }
 
+static int ieee80211_set_smd_ctx(struct wiphy *wiphy, struct wireless_dev 
*wdev,
+                                const u8 *addr,
+                                struct cfg80211_smd_transition_info *st_info)
+{
+       struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct ieee80211_sub_if_data *sdata;
+       struct sta_info *sta;
+
+       lockdep_assert_wiphy(wiphy);
+
+       sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+       if (sdata->vif.type != NL80211_IFTYPE_AP &&
+           sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
+               return -EOPNOTSUPP;
+
+       sta = sta_info_get_bss(sdata, addr);
+       if (!sta)
+               return -ENOENT;
+       if (!sta->sta.smd_params.smd_sta)
+               return -EINVAL;
+
+       return drv_set_smd_ctx(local, sdata, &sta->sta, st_info);
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
        .add_virtual_intf = ieee80211_add_iface,
        .del_virtual_intf = ieee80211_del_iface,
@@ -6199,4 +6224,5 @@ const struct cfg80211_ops mac80211_config_ops = {
        .set_epcs = ieee80211_set_epcs,
        .nan_set_local_sched = ieee80211_set_local_nan_sched,
        .nan_set_peer_sched = ieee80211_set_peer_nan_sched,
+       .set_smd_ctx = ieee80211_set_smd_ctx,
 };
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index ce11a723ec36..e764dd394de2 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1820,4 +1820,28 @@ int drv_sta_smd_state(struct ieee80211_local *local,
                      enum ieee80211_sta_smd_state old_state,
                      enum ieee80211_sta_smd_state new_state);
 
+static inline int drv_set_smd_ctx(struct ieee80211_local *local,
+                                 struct ieee80211_sub_if_data *sdata,
+                                 struct ieee80211_sta *sta,
+                                 struct cfg80211_smd_transition_info *st_info)
+{
+       int ret;
+
+       if (!local->ops->set_smd_ctx)
+               return -EOPNOTSUPP;
+
+       sdata = get_bss_sdata(sdata);
+
+       lockdep_assert_wiphy(local->hw.wiphy);
+
+       if (!check_sdata_in_driver(sdata))
+               return -EIO;
+
+       trace_drv_set_smd_ctx(local, sdata, sta, st_info);
+       ret = local->ops->set_smd_ctx(&local->hw, &sdata->vif, sta, st_info);
+       trace_drv_return_int(local, ret);
+
+       return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 63838a6d5d07..7aba79e441cf 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -3438,6 +3438,55 @@ TRACE_EVENT(drv_sta_smd_state,
        )
 );
 
+TRACE_EVENT(drv_set_smd_ctx,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                struct ieee80211_sta *sta,
+                struct cfg80211_smd_transition_info *st_info),
+
+       TP_ARGS(local, sdata, sta, st_info),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               STA_ENTRY
+               __field(u8, st_type)
+               __field(unsigned int, num_tids)
+               __dynamic_array(unsigned long, dl_tid_bitmap,
+                               BITS_TO_LONGS(IEEE80211_SMD_CTX_NUM_TIDS))
+               __dynamic_array(unsigned long, ul_tid_bitmap,
+                               BITS_TO_LONGS(IEEE80211_SMD_CTX_NUM_TIDS))
+       ),
+
+       TP_fast_assign(
+               struct ieee80211_smd_ctx *ctx = st_info->ctx;
+               unsigned long sz;
+
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               STA_ASSIGN;
+               __entry->st_type = st_info->type;
+
+               __entry->num_tids = IEEE80211_SMD_CTX_NUM_TIDS;
+               sz = BITS_TO_LONGS(__entry->num_tids) * sizeof(unsigned long);
+
+               memcpy(__get_dynamic_array(dl_tid_bitmap),
+                      ctx->dl.valid_tid_bmap, sz);
+               memcpy(__get_dynamic_array(ul_tid_bitmap),
+                      ctx->ul.valid_tid_bmap, sz);
+       ),
+
+       TP_printk(LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT
+                 ", ST type=%u DL TIDs: %*pb, UL TIDs: %*pb",
+                 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG,
+                 __entry->st_type,
+                 __entry->num_tids,
+                 (unsigned long *)__get_dynamic_array(dl_tid_bitmap),
+                 __entry->num_tids,
+                 (unsigned long *)__get_dynamic_array(ul_tid_bitmap)
+       )
+);
+
 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH

-- 
2.34.1


Reply via email to