[PATCH RFC wireless-next 4/7] wifi: mac80211: forward QoS Management configuration to drivers

Aishwarya R aishwarya.r at oss.qualcomm.com
Wed Oct 14 22:54:38 PDT 2026


Add a mac80211 QoS Management driver operation and connect it to the
cfg80211 set_qos_mgmt_cfg() callback.

Pass the parsed SCS/MSCS request, including any QoS Characteristics, to
the driver together with the response descriptor array. The driver is
expected to apply the protocol-specific configuration and update each
response descriptor with the status for its corresponding request.

The accepted configuration is then retained by mac80211 for use by
subsequent data-path handling.

Co-developed-by: Arun Vikas T <arun.t at oss.qualcomm.com>
Signed-off-by: Arun Vikas T <arun.t at oss.qualcomm.com>
Signed-off-by: Aishwarya R <aishwarya.r at oss.qualcomm.com>
---
 include/net/mac80211.h     |  7 +++++++
 net/mac80211/cfg.c         | 13 +++++++++++++
 net/mac80211/driver-ops.h  | 28 ++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h |  4 ++++
 net/mac80211/mlme.c        | 17 +++++++++++++++++
 net/mac80211/trace.h       | 24 ++++++++++++++++++++++++
 6 files changed, 93 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a1a6409b44c1..a610d6eb92b4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4760,6 +4760,9 @@ struct ieee80211_prep_tx_info {
  * @set_eml_op_mode: Configure eMLSR/eMLMR operation mode in the underlay
  *	driver according to the parameter received in the EML Operating mode
  *	notification frame.
+ * @qos_mgmt_cfg: Configure QoS Management (QM) for a station. The request
+ *	contains SCS or MSCS parameters, and the driver populates the
+ *	per-descriptor response status.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw,
@@ -5173,6 +5176,10 @@ struct ieee80211_ops {
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta,
 			       struct ieee80211_eml_params *eml_params);
+	int (*qos_mgmt_cfg)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			    struct ieee80211_sta *sta,
+			    struct cfg80211_qm_req_data *qm_req,
+			    struct cfg80211_qm_resp_data *qm_resp);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9608c07bcea7..f66f736adb92 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -6309,6 +6309,18 @@ ieee80211_set_nan_non_evac_channels(struct wiphy *wiphy,
 	return ieee80211_nan_set_non_evac_channels(sdata, channels);
 }
 
+static int
+ieee80211_set_qos_mgmt_cfg(struct wiphy *wiphy, struct net_device *dev,
+			   struct cfg80211_qm_req_data *qm_req,
+			   struct cfg80211_qm_resp_data *qm_resp)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	lockdep_assert_wiphy(wiphy);
+
+	return ieee80211_qos_mgmt_cfg(sdata, qm_req, qm_resp);
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -6432,4 +6444,5 @@ const struct cfg80211_ops mac80211_config_ops = {
 	.nan_set_local_sched = ieee80211_set_local_nan_sched,
 	.nan_set_peer_sched = ieee80211_set_peer_nan_sched,
 	.nan_set_non_evac_channels = ieee80211_set_nan_non_evac_channels,
+	.set_qos_mgmt_cfg = ieee80211_set_qos_mgmt_cfg,
 };
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 83dd15f2daf6..f1dc9ca9f8f7 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1804,4 +1804,32 @@ drv_nan_peer_sched_changed(struct ieee80211_local *local,
 	return ret;
 }
 
+static inline int
+drv_qos_mgmt_cfg(struct ieee80211_sub_if_data *sdata,
+		 struct ieee80211_local *local, struct ieee80211_sta *sta,
+		 struct cfg80211_qm_req_data *qm_req,
+		 struct cfg80211_qm_resp_data *qm_resp)
+{
+	int ret = -EOPNOTSUPP;
+
+	might_sleep();
+	lockdep_assert_wiphy(local->hw.wiphy);
+
+	if (!check_sdata_in_driver(sdata))
+		return ret;
+
+	/*
+	 * Called only for SCS descriptors carrying a QoS Characteristics
+	 * element (9.4.2.326, IEEE Std 802.11be-2024).  Legacy SCS and MSCS
+	 * are handled in mac80211.
+	 */
+	trace_drv_qos_mgmt_cfg(local, sdata, sta, qm_req);
+	if (local->ops->qos_mgmt_cfg)
+		ret = local->ops->qos_mgmt_cfg(&local->hw, &sdata->vif,
+						sta, qm_req, qm_resp);
+	trace_drv_return_int(local, ret);
+
+	return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1a6cbbb5a17d..63391a1fd9c6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -3020,6 +3020,10 @@ ieee80211_uhr_cap_ie_to_sta_uhr_cap(struct ieee80211_sub_if_data *sdata,
 				    u8 uhr_cap_len,
 				    struct link_sta_info *link_sta);
 
+int ieee80211_qos_mgmt_cfg(struct ieee80211_sub_if_data *sdata,
+			   struct cfg80211_qm_req_data *qm_req,
+			   struct cfg80211_qm_resp_data *qm_resp);
+
 #if IS_ENABLED(CONFIG_MAC80211_KUNIT_TEST)
 #define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
 #define VISIBLE_IF_MAC80211_KUNIT
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6ec45a9f7221..e476c6b9cb14 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -12036,3 +12036,20 @@ void ieee80211_sta_rx_queued_frame(struct ieee80211_sub_if_data *sdata,
 		break;
 	}
 }
+
+int ieee80211_qos_mgmt_cfg(struct ieee80211_sub_if_data *sdata,
+			   struct cfg80211_qm_req_data *qm_req,
+			   struct cfg80211_qm_resp_data *qm_resp)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta;
+
+	if (sdata->vif.type != NL80211_IFTYPE_AP)
+		return -EOPNOTSUPP;
+
+	sta = sta_info_get_bss(sdata, qm_req->peer_mac);
+	if (!sta)
+		return -ENOENT;
+
+	return drv_qos_mgmt_cfg(sdata, local, &sta->sta, qm_req, qm_resp);
+}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index ea46c3cca21a..ce69e5edd03f 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -3431,6 +3431,30 @@ TRACE_EVENT(drv_nan_peer_sched_changed,
 	)
 );
 
+TRACE_EVENT(drv_qos_mgmt_cfg,
+	    TP_PROTO(struct ieee80211_local *local,
+		     struct ieee80211_sub_if_data *sdata,
+		     struct ieee80211_sta *sta,
+		     struct cfg80211_qm_req_data *qm_req),
+	    TP_ARGS(local, sdata, sta, qm_req),
+	    TP_STRUCT__entry(LOCAL_ENTRY
+			     VIF_ENTRY
+			     STA_ENTRY
+			     __field(u8, qm_type)
+			     __field(unsigned int, num_qm_desc)
+	),
+	    TP_fast_assign(LOCAL_ASSIGN;
+			   VIF_ASSIGN;
+			   STA_NAMED_ASSIGN(sta);
+			   __entry->qm_type = qm_req->qm_type;
+			   __entry->num_qm_desc = qm_req->num_qm_desc;
+	),
+	    TP_printk(LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT
+		      " qm_type:%u num_qm_desc:%u",
+		      LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG,
+		      __entry->qm_type, __entry->num_qm_desc)
+);
+
 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
2.34.1




More information about the ath12k mailing list