* [PATCH wireless-next 1/2] wifi: mac80211: notify driver on airtime weight changes
2026-10-04 11:14 [PATCH wireless-next 0/2] wifi: mac80211: airtime weight op, BSS color during a color change Andrei-Alexandru Bleortu
@ 2026-10-04 11:14 ` Andrei-Alexandru Bleortu
2026-10-04 11:14 ` [PATCH wireless-next 2/2] wifi: mac80211: keep the BSS color while a color change is pending Andrei-Alexandru Bleortu
1 sibling, 0 replies; 3+ messages in thread
From: Andrei-Alexandru Bleortu @ 2026-10-04 11:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-kernel, linux-wireless, Felix Fietkau
From: Felix Fietkau <nbd@nbd.name>
Add a new sta_set_airtime_weight driver op so drivers can program the
airtime fairness weight into hardware. The op is called when the weight
is updated via sta_apply_parameters, and on station upload if a
non-default weight is already set.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Andrei-Alexandru Bleortu <me@andrei-z.com>
---
include/net/mac80211.h | 5 +++++
net/mac80211/cfg.c | 6 +++++-
net/mac80211/driver-ops.c | 4 ++++
net/mac80211/driver-ops.h | 19 +++++++++++++++++++
net/mac80211/sta_info.c | 7 ++++++-
net/mac80211/trace.h | 27 +++++++++++++++++++++++++++
6 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cb9f8e14b3..aab98d92ee 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4694,6 +4694,8 @@ struct ieee80211_prep_tx_info {
* @set_sar_specs: Update the SAR (TX power) settings.
* @sta_set_decap_offload: Called to notify the driver when a station is allowed
* to use rx decapsulation offload
+ * @sta_set_airtime_weight: Called to notify the driver of a change to a
+ * station's airtime fairness weight, so it can be programmed in hardware.
* @add_twt_setup: Update hw with TWT agreement parameters received from the peer.
* This callback allows the hw to check if requested parameters
* are supported and if there is enough room for a new agreement.
@@ -5108,6 +5110,9 @@ struct ieee80211_ops {
void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enabled);
+ void (*sta_set_airtime_weight)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, u16 weight);
void (*add_twt_setup)(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct ieee80211_twt_setup *twt);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bd1a857c81..28f99a8f8a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2616,8 +2616,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,
if (ieee80211_vif_is_mesh(&sdata->vif))
sta_apply_mesh_params(local, sta, params);
- if (params->airtime_weight)
+ if (params->airtime_weight) {
sta->airtime_weight = params->airtime_weight;
+ if (sta->uploaded)
+ drv_sta_set_airtime_weight(local, sdata, &sta->sta,
+ sta->airtime_weight);
+ }
if (params->nmi_mac) {
struct ieee80211_sub_if_data *nmi =
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 49753b73ab..083c265175 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -157,6 +157,10 @@ int drv_sta_state(struct ieee80211_local *local,
sta->uploaded = true;
if (rcu_access_pointer(sta->sta.rates))
drv_sta_rate_tbl_update(local, sdata, &sta->sta);
+ if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+ drv_sta_set_airtime_weight(local, sdata,
+ &sta->sta,
+ sta->airtime_weight);
}
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f1c0b87fdd..bd5c9d1edc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1633,6 +1633,25 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ u16 weight)
+{
+ sdata = get_bss_sdata(sdata);
+
+ might_sleep();
+ lockdep_assert_wiphy(local->hw.wiphy);
+ if (!check_sdata_in_driver(sdata))
+ return;
+
+ trace_drv_sta_set_airtime_weight(local, sdata, sta, weight);
+ if (local->ops->sta_set_airtime_weight)
+ local->ops->sta_set_airtime_weight(&local->hw, &sdata->vif, sta,
+ weight);
+ trace_drv_return_void(local);
+}
+
static inline void drv_add_twt_setup(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index e81cd15519..2ce3ef905f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -872,8 +872,13 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
* Drivers using legacy sta_add/sta_remove callbacks only
* get uploaded set to true after sta_add is called.
*/
- if (!local->ops->sta_add)
+ if (!local->ops->sta_add) {
sta->uploaded = true;
+ if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+ drv_sta_set_airtime_weight(local, sdata,
+ &sta->sta,
+ sta->airtime_weight);
+ }
return 0;
}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 562a4964af..3ae7e78de7 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2462,6 +2462,33 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,
TP_ARGS(local, sdata, sta, enabled)
);
+TRACE_EVENT(drv_sta_set_airtime_weight,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta, u16 weight),
+
+ TP_ARGS(local, sdata, sta, weight),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ STA_ENTRY
+ __field(u16, weight)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ STA_ASSIGN;
+ __entry->weight = weight;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " weight:%u",
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->weight
+ )
+);
+
TRACE_EVENT(drv_add_twt_setup,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sta *sta,
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH wireless-next 2/2] wifi: mac80211: keep the BSS color while a color change is pending
2026-10-04 11:14 [PATCH wireless-next 0/2] wifi: mac80211: airtime weight op, BSS color during a color change Andrei-Alexandru Bleortu
2026-10-04 11:14 ` [PATCH wireless-next 1/2] wifi: mac80211: notify driver on airtime weight changes Andrei-Alexandru Bleortu
@ 2026-10-04 11:14 ` Andrei-Alexandru Bleortu
1 sibling, 0 replies; 3+ messages in thread
From: Andrei-Alexandru Bleortu @ 2026-10-04 11:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-kernel, linux-wireless, Felix Fietkau
When a BSS color change starts, mac80211 tells the driver that the BSS
color is disabled, as the Beacon frames say during the countdown, but it
also sets the color to 0. While the BSS Color Disabled subfield is 1, an
HE STA shall keep using its nonzero color, the one it used before, in the
BSS_COLOR of the HE PPDUs it transmits (IEEE Std 802.11-2024, 26.11.4),
and a driver can only do so if it still knows the color.
Keep the current color and only clear enabled.
Assisted-by: LLM
Signed-off-by: Andrei-Alexandru Bleortu <me@andrei-z.com>
---
net/mac80211/cfg.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 28f99a8f8a..e68edf833f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -5807,8 +5807,13 @@ ieee80211_color_change(struct wiphy *wiphy, struct net_device *dev,
cfg80211_color_change_started_notify(sdata->dev, params->count, link_id);
+ /* While the color is disabled, the BSS keeps using its current color
+ * (IEEE Std 802.11-2024, 26.11.4)
+ */
if (changed)
- ieee80211_color_change_bss_config_notify(link, 0, 0, changed);
+ ieee80211_color_change_bss_config_notify(link,
+ link_conf->he_bss_color.color,
+ 0, changed);
else
/* if the beacon didn't change, we can finalize immediately */
ieee80211_color_change_finalize(link);
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread