| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/22 14:54 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"MAC80211"
],
"FocusSymbols": [
"ieee80211_sta_update_pending_airtime",
"ieee80211_txq_airtime_check",
"ieee80211_txq_aql_pending",
"ieee80211_rate_expected_tx_airtime",
"sta_estimate_expected_throughput"
],
"Reasoning": "The patch introduces Airtime Queue Limit (AQL) support for multicast traffic and modifies the expected throughput calculation for stations in mac80211. This is reachable core logic for 802.11 networking and can be triggered via mac80211_hwsim.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/22 14:54 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 79d58539beb740bc57b632f178745cc5ca82fca2\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Jul 22 14:54:29 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/include/net/cfg80211.h b/include/net/cfg80211.h\nindex f5abf1db7558bc..7354ba079363a5 100644\n--- a/include/net/cfg80211.h\n+++ b/include/net/cfg80211.h\n@@ -3722,6 +3722,7 @@ enum wiphy_params_flags {\n /* The per TXQ device queue limit in airtime */\n #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L\t5000\n #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H\t12000\n+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_MC\t50000\n \n /* The per interface airtime threshold to switch to lower queue limit */\n #define IEEE80211_AQL_THRESHOLD\t\t\t24000\ndiff --git a/include/net/mac80211.h b/include/net/mac80211.h\nindex 4f95da023746f9..23d8d4639cdd6d 100644\n--- a/include/net/mac80211.h\n+++ b/include/net/mac80211.h\n@@ -1354,8 +1354,8 @@ struct ieee80211_tx_info {\n \t status_data_idr:1,\n \t status_data:13,\n \t hw_queue:4,\n+\t tx_time_mc:1,\n \t tx_time_est:10;\n-\t/* 1 free bit */\n \n \tunion {\n \t\tstruct {\n@@ -6876,6 +6876,17 @@ void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,\n bool\n ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);\n \n+/**\n+ * ieee80211_txq_aql_pending - get pending AQL airtime for a txq\n+ *\n+ * @hw: pointer obtained from ieee80211_alloc_hw()\n+ * @txq: pointer obtained from station or virtual interface\n+ *\n+ * Return: pending airtime (in usec) for the given txq.\n+ */\n+u32 ieee80211_txq_aql_pending(struct ieee80211_hw *hw,\n+\t\t\t struct ieee80211_txq *txq);\n+\n /**\n * ieee80211_iter_keys - iterate keys programmed into the device\n * @hw: pointer obtained from ieee80211_alloc_hw()\ndiff --git a/net/mac80211/airtime.c b/net/mac80211/airtime.c\nindex c61df637232a9b..0c54cdbd753cd7 100644\n--- a/net/mac80211/airtime.c\n+++ b/net/mac80211/airtime.c\n@@ -685,7 +685,7 @@ static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,\n \tif (ieee80211_fill_rate_info(hw, stat, band, ri))\n \t\treturn 0;\n \n-\tif (!ieee80211_rate_valid(rate))\n+\tif (!rate || !ieee80211_rate_valid(rate))\n \t\treturn -1;\n \n \tif (rate-\u003eflags \u0026 IEEE80211_TX_RC_160_MHZ_WIDTH)\n@@ -753,6 +753,53 @@ u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,\n }\n EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);\n \n+u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,\n+\t\t\t\t struct ieee80211_tx_rate *tx_rate,\n+\t\t\t\t struct rate_info *ri,\n+\t\t\t\t enum nl80211_band band,\n+\t\t\t\t bool ampdu, int len)\n+{\n+\tstruct ieee80211_rx_status stat;\n+\tu32 duration, overhead;\n+\tu8 agg_shift;\n+\n+\tif (ieee80211_fill_rx_status(\u0026stat, hw, tx_rate, ri, band, len))\n+\t\treturn 0;\n+\n+\tif (stat.encoding == RX_ENC_LEGACY || !ampdu)\n+\t\treturn ieee80211_calc_rx_airtime(hw, \u0026stat, len) * 1024;\n+\n+\tduration = ieee80211_get_rate_duration(hw, \u0026stat, \u0026overhead);\n+\n+\t/*\n+\t * Assume that HT/VHT transmission on any AC except VO will\n+\t * use aggregation. Since we don't have reliable reporting\n+\t * of aggregation length, assume an average size based on the\n+\t * tx rate.\n+\t * This will not be very accurate, but much better than simply\n+\t * assuming un-aggregated tx in all cases.\n+\t */\n+\tif (duration \u003e 400 * 1024) /* \u003c= VHT20 MCS2 1S */\n+\t\tagg_shift = 1;\n+\telse if (duration \u003e 250 * 1024) /* \u003c= VHT20 MCS3 1S or MCS1 2S */\n+\t\tagg_shift = 2;\n+\telse if (duration \u003e 150 * 1024) /* \u003c= VHT20 MCS5 1S or MCS2 2S */\n+\t\tagg_shift = 3;\n+\telse if (duration \u003e 70 * 1024) /* \u003c= VHT20 MCS5 2S */\n+\t\tagg_shift = 4;\n+\telse if (stat.encoding != RX_ENC_HE ||\n+\t\t duration \u003e 20 * 1024) /* \u003c= HE40 MCS6 2S */\n+\t\tagg_shift = 5;\n+\telse\n+\t\tagg_shift = 6;\n+\n+\tduration *= len;\n+\tduration /= AVG_PKT_SIZE;\n+\tduration += (overhead * 1024 \u003e\u003e agg_shift);\n+\n+\treturn duration;\n+}\n+\n u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,\n \t\t\t\t struct ieee80211_vif *vif,\n \t\t\t\t struct ieee80211_sta *pubsta,\n@@ -775,45 +822,13 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,\n \tif (pubsta) {\n \t\tstruct sta_info *sta = container_of(pubsta, struct sta_info,\n \t\t\t\t\t\t sta);\n-\t\tstruct ieee80211_rx_status stat;\n \t\tstruct ieee80211_tx_rate *tx_rate = \u0026sta-\u003edeflink.tx_stats.last_rate;\n \t\tstruct rate_info *ri = \u0026sta-\u003edeflink.tx_stats.last_rate_info;\n-\t\tu32 duration, overhead;\n-\t\tu8 agg_shift;\n-\n-\t\tif (ieee80211_fill_rx_status(\u0026stat, hw, tx_rate, ri, band, len))\n-\t\t\treturn 0;\n+\t\tu32 duration;\n \n-\t\tif (stat.encoding == RX_ENC_LEGACY || !ampdu)\n-\t\t\treturn ieee80211_calc_rx_airtime(hw, \u0026stat, len);\n-\n-\t\tduration = ieee80211_get_rate_duration(hw, \u0026stat, \u0026overhead);\n-\t\t/*\n-\t\t * Assume that HT/VHT transmission on any AC except VO will\n-\t\t * use aggregation. Since we don't have reliable reporting\n-\t\t * of aggregation length, assume an average size based on the\n-\t\t * tx rate.\n-\t\t * This will not be very accurate, but much better than simply\n-\t\t * assuming un-aggregated tx in all cases.\n-\t\t */\n-\t\tif (duration \u003e 400 * 1024) /* \u003c= VHT20 MCS2 1S */\n-\t\t\tagg_shift = 1;\n-\t\telse if (duration \u003e 250 * 1024) /* \u003c= VHT20 MCS3 1S or MCS1 2S */\n-\t\t\tagg_shift = 2;\n-\t\telse if (duration \u003e 150 * 1024) /* \u003c= VHT20 MCS5 1S or MCS2 2S */\n-\t\t\tagg_shift = 3;\n-\t\telse if (duration \u003e 70 * 1024) /* \u003c= VHT20 MCS5 2S */\n-\t\t\tagg_shift = 4;\n-\t\telse if (stat.encoding != RX_ENC_HE ||\n-\t\t\t duration \u003e 20 * 1024) /* \u003c= HE40 MCS6 2S */\n-\t\t\tagg_shift = 5;\n-\t\telse\n-\t\t\tagg_shift = 6;\n-\n-\t\tduration *= len;\n-\t\tduration /= AVG_PKT_SIZE;\n+\t\tduration = ieee80211_rate_expected_tx_airtime(hw, tx_rate, ri,\n+\t\t\t\t\t\t\t band, true, len);\n \t\tduration /= 1024;\n-\t\tduration += (overhead \u003e\u003e agg_shift);\n \n \t\treturn max_t(u32, duration, 4);\n \t}\ndiff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c\nindex a4d5461f6480f0..8ebf5bcf3c0ec1 100644\n--- a/net/mac80211/debugfs.c\n+++ b/net/mac80211/debugfs.c\n@@ -210,11 +210,13 @@ static ssize_t aql_pending_read(struct file *file,\n \t\t\t\"VI %u us\\n\"\n \t\t\t\"BE %u us\\n\"\n \t\t\t\"BK %u us\\n\"\n+\t\t\t\"MC %u us\\n\"\n \t\t\t\"total %u us\\n\",\n \t\t\tatomic_read(\u0026local-\u003eaql_ac_pending_airtime[IEEE80211_AC_VO]),\n \t\t\tatomic_read(\u0026local-\u003eaql_ac_pending_airtime[IEEE80211_AC_VI]),\n \t\t\tatomic_read(\u0026local-\u003eaql_ac_pending_airtime[IEEE80211_AC_BE]),\n \t\t\tatomic_read(\u0026local-\u003eaql_ac_pending_airtime[IEEE80211_AC_BK]),\n+\t\t\tatomic_read(\u0026local-\u003eaql_mc_pending_airtime),\n \t\t\tatomic_read(\u0026local-\u003eaql_total_pending_airtime));\n \treturn simple_read_from_buffer(user_buf, count, ppos,\n \t\t\t\t buf, len);\n@@ -239,7 +241,8 @@ static ssize_t aql_txq_limit_read(struct file *file,\n \t\t\t\"VO\t%u\t\t%u\\n\"\n \t\t\t\"VI\t%u\t\t%u\\n\"\n \t\t\t\"BE\t%u\t\t%u\\n\"\n-\t\t\t\"BK\t%u\t\t%u\\n\",\n+\t\t\t\"BK\t%u\t\t%u\\n\"\n+\t\t\t\"MC\t%u\\n\",\n \t\t\tlocal-\u003eaql_txq_limit_low[IEEE80211_AC_VO],\n \t\t\tlocal-\u003eaql_txq_limit_high[IEEE80211_AC_VO],\n \t\t\tlocal-\u003eaql_txq_limit_low[IEEE80211_AC_VI],\n@@ -247,7 +250,8 @@ static ssize_t aql_txq_limit_read(struct file *file,\n \t\t\tlocal-\u003eaql_txq_limit_low[IEEE80211_AC_BE],\n \t\t\tlocal-\u003eaql_txq_limit_high[IEEE80211_AC_BE],\n \t\t\tlocal-\u003eaql_txq_limit_low[IEEE80211_AC_BK],\n-\t\t\tlocal-\u003eaql_txq_limit_high[IEEE80211_AC_BK]);\n+\t\t\tlocal-\u003eaql_txq_limit_high[IEEE80211_AC_BK],\n+\t\t\tlocal-\u003eaql_txq_limit_mc);\n \treturn simple_read_from_buffer(user_buf, count, ppos,\n \t\t\t\t buf, len);\n }\n@@ -273,6 +277,11 @@ static ssize_t aql_txq_limit_write(struct file *file,\n \telse\n \t\tbuf[count] = '\\0';\n \n+\tif (sscanf(buf, \"mcast %u\", \u0026q_limit_low) == 1) {\n+\t\tlocal-\u003eaql_txq_limit_mc = q_limit_low;\n+\t\treturn count;\n+\t}\n+\n \tif (sscanf(buf, \"%u %u %u\", \u0026ac, \u0026q_limit_low, \u0026q_limit_high) != 3)\n \t\treturn -EINVAL;\n \ndiff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h\nindex 34a9ea8b6f857e..78fea7a17ae766 100644\n--- a/net/mac80211/ieee80211_i.h\n+++ b/net/mac80211/ieee80211_i.h\n@@ -1464,10 +1464,12 @@ struct ieee80211_local {\n \tspinlock_t handle_wake_tx_queue_lock;\n \n \tu16 airtime_flags;\n+\tu32 aql_txq_limit_mc;\n \tu32 aql_txq_limit_low[IEEE80211_NUM_ACS];\n \tu32 aql_txq_limit_high[IEEE80211_NUM_ACS];\n \tu32 aql_threshold;\n \tatomic_t aql_total_pending_airtime;\n+\tatomic_t aql_mc_pending_airtime;\n \tatomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];\n \n \tconst struct ieee80211_ops *ops;\n@@ -2939,6 +2941,11 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,\n \n extern const struct ethtool_ops ieee80211_ethtool_ops;\n \n+u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,\n+\t\t\t\t struct ieee80211_tx_rate *tx_rate,\n+\t\t\t\t struct rate_info *ri,\n+\t\t\t\t enum nl80211_band band,\n+\t\t\t\t bool ampdu, int len);\n u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,\n \t\t\t\t struct ieee80211_vif *vif,\n \t\t\t\t struct ieee80211_sta *pubsta,\ndiff --git a/net/mac80211/main.c b/net/mac80211/main.c\nindex eb1eaaf34612e1..b5dc7f659b5de5 100644\n--- a/net/mac80211/main.c\n+++ b/net/mac80211/main.c\n@@ -988,6 +988,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,\n \tspin_lock_init(\u0026local-\u003erx_path_lock);\n \tspin_lock_init(\u0026local-\u003equeue_stop_reason_lock);\n \n+\tlocal-\u003eaql_txq_limit_mc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_MC;\n \tfor (i = 0; i \u003c IEEE80211_NUM_ACS; i++) {\n \t\tINIT_LIST_HEAD(\u0026local-\u003eactive_txqs[i]);\n \t\tspin_lock_init(\u0026local-\u003eactive_txq_lock[i]);\ndiff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c\nindex 22eba0e6e54c5b..d12aed9c175617 100644\n--- a/net/mac80211/sta_info.c\n+++ b/net/mac80211/sta_info.c\n@@ -2491,13 +2491,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);\n \n void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,\n \t\t\t\t\t struct sta_info *sta, u8 ac,\n-\t\t\t\t\t u16 tx_airtime, bool tx_completed)\n+\t\t\t\t\t u16 tx_airtime, bool tx_completed,\n+\t\t\t\t\t bool mcast)\n {\n \tint tx_pending;\n \n \tif (!wiphy_ext_feature_isset(local-\u003ehw.wiphy, NL80211_EXT_FEATURE_AQL))\n \t\treturn;\n \n+\tif (mcast) {\n+\t\tif (!tx_completed) {\n+\t\t\tatomic_add(tx_airtime, \u0026local-\u003eaql_mc_pending_airtime);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\ttx_pending = atomic_sub_return(tx_airtime,\n+\t\t\t\t\t \u0026local-\u003eaql_mc_pending_airtime);\n+\t\tif (tx_pending \u003c 0)\n+\t\t\tatomic_cmpxchg(\u0026local-\u003eaql_mc_pending_airtime,\n+\t\t\t\t tx_pending, 0);\n+\t\treturn;\n+\t}\n+\n \tif (!tx_completed) {\n \t\tif (sta)\n \t\t\tatomic_add(tx_airtime,\n@@ -2797,6 +2812,28 @@ void sta_set_accumulated_removed_links_sinfo(struct sta_info *sta,\n \t}\n }\n \n+static u32 sta_estimate_expected_throughput(struct sta_info *sta,\n+\t\t\t\t\t struct rate_info *ri,\n+\t\t\t\t\t struct ieee80211_bss_conf *bss_conf)\n+{\n+\tstruct ieee80211_hw *hw = \u0026sta-\u003esdata-\u003elocal-\u003ehw;\n+\tstruct ieee80211_chanctx_conf *conf;\n+\tu32 duration;\n+\tu8 band;\n+\n+\tconf = rcu_dereference(bss_conf-\u003echanctx_conf);\n+\tif (!conf)\n+\t\treturn 0;\n+\tband = conf-\u003edef.chan-\u003eband;\n+\n+\tduration = ieee80211_rate_expected_tx_airtime(hw, NULL, ri, band, true, 1024);\n+\tduration += duration \u003e\u003e 4; /* add assumed packet error rate of ~6% */\n+\tif (!duration)\n+\t\treturn 0;\n+\n+\treturn ((1024 * USEC_PER_SEC) / duration) * 8;\n+}\n+\n static void sta_set_link_sinfo(struct sta_info *sta,\n \t\t\t struct link_station_info *link_sinfo,\n \t\t\t struct ieee80211_link_data *link,\n@@ -3011,6 +3048,10 @@ static void sta_set_link_sinfo(struct sta_info *sta,\n \tlink_sinfo-\u003ebss_param.beacon_interval = link-\u003econf-\u003ebeacon_int;\n \n \tthr = sta_get_expected_throughput(sta);\n+\tif (!thr \u0026\u0026 (link_sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_TX_BITRATE)))\n+\t\tthr = sta_estimate_expected_throughput(sta,\n+\t\t\t\t\t\t \u0026link_sinfo-\u003etxrate,\n+\t\t\t\t\t\t link-\u003econf);\n \n \tif (thr != 0) {\n \t\tlink_sinfo-\u003efilled |=\n@@ -3264,6 +3305,14 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,\n \tif (thr != 0) {\n \t\tsinfo-\u003efilled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);\n \t\tsinfo-\u003eexpected_throughput = thr;\n+\t} else if (!sta-\u003esta.valid_links \u0026\u0026\n+\t\t (sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {\n+\t\tthr = sta_estimate_expected_throughput(sta, \u0026sinfo-\u003etxrate,\n+\t\t\t\t\t\t \u0026sdata-\u003evif.bss_conf);\n+\t\tif (thr) {\n+\t\t\tsinfo-\u003efilled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);\n+\t\t\tsinfo-\u003eexpected_throughput = thr;\n+\t\t}\n \t}\n \n \tif (!(sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL)) \u0026\u0026\n@@ -3284,6 +3333,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,\n \tif (sta-\u003esta.valid_links) {\n \t\tstruct ieee80211_link_data *link;\n \t\tstruct link_sta_info *link_sta;\n+\t\tu32 est_thr = 0;\n \t\tint link_id;\n \n \t\tsinfo-\u003emlo_params_valid = true;\n@@ -3295,17 +3345,25 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,\n \t\tsinfo-\u003evalid_links = sta-\u003esta.valid_links;\n \n \t\tfor_each_valid_link(sinfo, link_id) {\n+\t\t\tstruct link_station_info *link_sinfo = sinfo-\u003elinks[link_id];\n+\n \t\t\tlink_sta = wiphy_dereference(sta-\u003elocal-\u003ehw.wiphy,\n \t\t\t\t\t\t sta-\u003elink[link_id]);\n \t\t\tlink = wiphy_dereference(sdata-\u003elocal-\u003ehw.wiphy,\n \t\t\t\t\t\t sdata-\u003elink[link_id]);\n \n-\t\t\tif (!link_sta || !sinfo-\u003elinks[link_id] || !link) {\n+\t\t\tif (!link_sta || !link_sinfo || !link) {\n \t\t\t\tsinfo-\u003evalid_links \u0026= ~BIT(link_id);\n \t\t\t\tcontinue;\n \t\t\t}\n-\t\t\tsta_set_link_sinfo(sta, sinfo-\u003elinks[link_id],\n-\t\t\t\t\t link, tidstats);\n+\t\t\tsta_set_link_sinfo(sta, link_sinfo, link, tidstats);\n+\t\t\tif (!thr \u0026\u0026\n+\t\t\t (link_sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT)))\n+\t\t\t\test_thr += link_sinfo-\u003eexpected_throughput;\n+\t\t}\n+\t\tif (est_thr) {\n+\t\t\tsinfo-\u003efilled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);\n+\t\t\tsinfo-\u003eexpected_throughput = est_thr;\n \t\t}\n \t}\n }\ndiff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h\nindex 5da3142d8516ef..ee0d32877c5b47 100644\n--- a/net/mac80211/sta_info.h\n+++ b/net/mac80211/sta_info.h\n@@ -147,7 +147,8 @@ struct airtime_info {\n \n void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,\n \t\t\t\t\t struct sta_info *sta, u8 ac,\n-\t\t\t\t\t u16 tx_airtime, bool tx_completed);\n+\t\t\t\t\t u16 tx_airtime, bool tx_completed,\n+\t\t\t\t\t bool mcast);\n \n struct sta_info;\n \ndiff --git a/net/mac80211/status.c b/net/mac80211/status.c\nindex dd1dbba06838e5..c764e1a9548696 100644\n--- a/net/mac80211/status.c\n+++ b/net/mac80211/status.c\n@@ -774,7 +774,7 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,\n \t\tieee80211_sta_update_pending_airtime(local, sta,\n \t\t\t\t\t\t skb_get_queue_mapping(skb),\n \t\t\t\t\t\t tx_time_est,\n-\t\t\t\t\t\t true);\n+\t\t\t\t\t\t true, info-\u003etx_time_mc);\n \t\trcu_read_unlock();\n \t}\n \n@@ -1186,10 +1186,11 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,\n \t\t/* Do this here to avoid the expensive lookup of the sta\n \t\t * in ieee80211_report_used_skb().\n \t\t */\n+\t\tbool mcast = IEEE80211_SKB_CB(skb)-\u003etx_time_mc;\n \t\tieee80211_sta_update_pending_airtime(local, sta,\n \t\t\t\t\t\t skb_get_queue_mapping(skb),\n \t\t\t\t\t\t tx_time_est,\n-\t\t\t\t\t\t true);\n+\t\t\t\t\t\t true, mcast);\n \t\tieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);\n \t}\n \ndiff --git a/net/mac80211/tx.c b/net/mac80211/tx.c\nindex 91b14112e24f08..85aff37819242a 100644\n--- a/net/mac80211/tx.c\n+++ b/net/mac80211/tx.c\n@@ -4054,20 +4054,20 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,\n encap_out:\n \tinfo-\u003econtrol.vif = vif;\n \n-\tif (tx.sta \u0026\u0026\n-\t wiphy_ext_feature_isset(local-\u003ehw.wiphy, NL80211_EXT_FEATURE_AQL)) {\n-\t\tbool ampdu = txq-\u003eac != IEEE80211_AC_VO;\n+\tif (wiphy_ext_feature_isset(local-\u003ehw.wiphy, NL80211_EXT_FEATURE_AQL)) {\n+\t\tbool ampdu = txq-\u003esta \u0026\u0026 txq-\u003eac != IEEE80211_AC_VO;\n \t\tu32 airtime;\n \n \t\tairtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq-\u003esta,\n \t\t\t\t\t\t\t skb-\u003elen, ampdu);\n-\t\tif (airtime) {\n-\t\t\tairtime = ieee80211_info_set_tx_time_est(info, airtime);\n-\t\t\tieee80211_sta_update_pending_airtime(local, tx.sta,\n-\t\t\t\t\t\t\t txq-\u003eac,\n-\t\t\t\t\t\t\t airtime,\n-\t\t\t\t\t\t\t false);\n-\t\t}\n+\t\tif (!airtime)\n+\t\t\treturn skb;\n+\n+\t\tairtime = ieee80211_info_set_tx_time_est(info, airtime);\n+\t\tinfo-\u003etx_time_mc = !tx.sta;\n+\t\tieee80211_sta_update_pending_airtime(local, tx.sta, txq-\u003eac,\n+\t\t\t\t\t\t airtime, false,\n+\t\t\t\t\t\t info-\u003etx_time_mc);\n \t}\n \n \treturn skb;\n@@ -4119,6 +4119,7 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)\n \tstruct ieee80211_txq *ret = NULL;\n \tstruct txq_info *txqi = NULL, *head = NULL;\n \tbool found_eligible_txq = false;\n+\tbool aql_check;\n \n \tspin_lock_bh(\u0026local-\u003eactive_txq_lock[ac]);\n \n@@ -4142,26 +4143,28 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)\n \tif (!head)\n \t\thead = txqi;\n \n+\taql_check = ieee80211_txq_airtime_check(hw, \u0026txqi-\u003etxq);\n+\tif (aql_check)\n+\t\tfound_eligible_txq = true;\n+\n \tif (txqi-\u003etxq.sta) {\n \t\tstruct sta_info *sta = container_of(txqi-\u003etxq.sta,\n \t\t\t\t\t\t struct sta_info, sta);\n-\t\tbool aql_check = ieee80211_txq_airtime_check(hw, \u0026txqi-\u003etxq);\n-\t\ts32 deficit = ieee80211_sta_deficit(sta, txqi-\u003etxq.ac);\n \n-\t\tif (aql_check)\n-\t\t\tfound_eligible_txq = true;\n-\n-\t\tif (deficit \u003c 0)\n+\t\tif (ieee80211_sta_deficit(sta, txqi-\u003etxq.ac) \u003c 0) {\n \t\t\tsta-\u003eairtime[txqi-\u003etxq.ac].deficit +=\n \t\t\t\tsta-\u003eairtime_weight;\n \n-\t\tif (deficit \u003c 0 || !aql_check) {\n-\t\t\tlist_move_tail(\u0026txqi-\u003eschedule_order,\n-\t\t\t\t \u0026local-\u003eactive_txqs[txqi-\u003etxq.ac]);\n-\t\t\tgoto begin;\n+\t\t\taql_check = false;\n \t\t}\n \t}\n \n+\tif (!aql_check) {\n+\t\tlist_move_tail(\u0026txqi-\u003eschedule_order,\n+\t\t\t\t \u0026local-\u003eactive_txqs[txqi-\u003etxq.ac]);\n+\t\tgoto begin;\n+\t}\n+\n \tif (txqi-\u003eschedule_round == local-\u003eschedule_round[ac])\n \t\tgoto out;\n \n@@ -4228,7 +4231,8 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,\n \t\treturn true;\n \n \tif (!txq-\u003esta)\n-\t\treturn true;\n+\t\treturn atomic_read(\u0026local-\u003eaql_mc_pending_airtime) \u003c\n+\t\t local-\u003eaql_txq_limit_mc;\n \n \tif (unlikely(txq-\u003etid == IEEE80211_NUM_TIDS))\n \t\treturn true;\n@@ -4248,6 +4252,24 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,\n }\n EXPORT_SYMBOL(ieee80211_txq_airtime_check);\n \n+u32 ieee80211_txq_aql_pending(struct ieee80211_hw *hw,\n+\t\t\t struct ieee80211_txq *txq)\n+{\n+\tstruct ieee80211_local *local = hw_to_local(hw);\n+\tstruct sta_info *sta;\n+\n+\tif (unlikely(txq-\u003etid == IEEE80211_NUM_TIDS))\n+\t\treturn 0;\n+\n+\tif (!txq-\u003esta)\n+\t\treturn atomic_read(\u0026local-\u003eaql_mc_pending_airtime);\n+\n+\tsta = container_of(txq-\u003esta, struct sta_info, sta);\n+\n+\treturn atomic_read(\u0026sta-\u003eairtime[txq-\u003eac].aql_tx_pending);\n+}\n+EXPORT_SYMBOL(ieee80211_txq_aql_pending);\n+\n static bool\n ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)\n {\n@@ -4277,15 +4299,15 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,\n \n \tspin_lock_bh(\u0026local-\u003eactive_txq_lock[ac]);\n \n-\tif (!txqi-\u003etxq.sta)\n-\t\tgoto out;\n-\n \tif (list_empty(\u0026txqi-\u003eschedule_order))\n \t\tgoto out;\n \n \tif (!ieee80211_txq_schedule_airtime_check(local, ac))\n \t\tgoto out;\n \n+\tif (!txqi-\u003etxq.sta)\n+\t\tgoto out;\n+\n \tlist_for_each_entry_safe(iter, tmp, \u0026local-\u003eactive_txqs[ac],\n \t\t\t\t schedule_order) {\n \t\tif (iter == txqi)\n"
} |
| 2/1 | 2026/07/22 14:54 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"MAC80211"
],
"FocusSymbols": [
"ieee80211_sta_update_pending_airtime",
"ieee80211_txq_airtime_check",
"ieee80211_txq_aql_pending",
"ieee80211_rate_expected_tx_airtime",
"sta_estimate_expected_throughput"
],
"Reasoning": "The patch introduces Airtime Queue Limit (AQL) support for multicast traffic and modifies the expected throughput calculation for stations in mac80211. This is reachable core logic for 802.11 networking and can be triggered via mac80211_hwsim.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 79d58539beb740bc57b632f178745cc5ca82fca2
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Jul 22 14:54:29 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f5abf1db7558bc..7354ba079363a5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3722,6 +3722,7 @@ enum wiphy_params_flags {
/* The per TXQ device queue limit in airtime */
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_MC 50000
/* The per interface airtime threshold to switch to lower queue limit */
#define IEEE80211_AQL_THRESHOLD 24000
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4f95da023746f9..23d8d4639cdd6d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1354,8 +1354,8 @@ struct ieee80211_tx_info {
status_data_idr:1,
status_data:13,
hw_queue:4,
+ tx_time_mc:1,
tx_time_est:10;
- /* 1 free bit */
union {
struct {
@@ -6876,6 +6876,17 @@ void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,
bool
ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
+/**
+ * ieee80211_txq_aql_pending - get pending AQL airtime for a txq
+ *
+ * @hw: pointer obtained from ieee80211_alloc_hw()
+ * @txq: pointer obtained from station or virtual interface
+ *
+ * Return: pending airtime (in usec) for the given txq.
+ */
+u32 ieee80211_txq_aql_pending(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq);
+
/**
* ieee80211_iter_keys - iterate keys programmed into the device
* @hw: pointer obtained from ieee80211_alloc_hw()
diff --git a/net/mac80211/airtime.c b/net/mac80211/airtime.c
index c61df637232a9b..0c54cdbd753cd7 100644
--- a/net/mac80211/airtime.c
+++ b/net/mac80211/airtime.c
@@ -685,7 +685,7 @@ static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,
if (ieee80211_fill_rate_info(hw, stat, band, ri))
return 0;
- if (!ieee80211_rate_valid(rate))
+ if (!rate || !ieee80211_rate_valid(rate))
return -1;
if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
@@ -753,6 +753,53 @@ u32 ieee80211_calc_tx_airtime(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);
+u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,
+ struct ieee80211_tx_rate *tx_rate,
+ struct rate_info *ri,
+ enum nl80211_band band,
+ bool ampdu, int len)
+{
+ struct ieee80211_rx_status stat;
+ u32 duration, overhead;
+ u8 agg_shift;
+
+ if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len))
+ return 0;
+
+ if (stat.encoding == RX_ENC_LEGACY || !ampdu)
+ return ieee80211_calc_rx_airtime(hw, &stat, len) * 1024;
+
+ duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
+
+ /*
+ * Assume that HT/VHT transmission on any AC except VO will
+ * use aggregation. Since we don't have reliable reporting
+ * of aggregation length, assume an average size based on the
+ * tx rate.
+ * This will not be very accurate, but much better than simply
+ * assuming un-aggregated tx in all cases.
+ */
+ if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
+ agg_shift = 1;
+ else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
+ agg_shift = 2;
+ else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
+ agg_shift = 3;
+ else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
+ agg_shift = 4;
+ else if (stat.encoding != RX_ENC_HE ||
+ duration > 20 * 1024) /* <= HE40 MCS6 2S */
+ agg_shift = 5;
+ else
+ agg_shift = 6;
+
+ duration *= len;
+ duration /= AVG_PKT_SIZE;
+ duration += (overhead * 1024 >> agg_shift);
+
+ return duration;
+}
+
u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *pubsta,
@@ -775,45 +822,13 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
if (pubsta) {
struct sta_info *sta = container_of(pubsta, struct sta_info,
sta);
- struct ieee80211_rx_status stat;
struct ieee80211_tx_rate *tx_rate = &sta->deflink.tx_stats.last_rate;
struct rate_info *ri = &sta->deflink.tx_stats.last_rate_info;
- u32 duration, overhead;
- u8 agg_shift;
-
- if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len))
- return 0;
+ u32 duration;
- if (stat.encoding == RX_ENC_LEGACY || !ampdu)
- return ieee80211_calc_rx_airtime(hw, &stat, len);
-
- duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
- /*
- * Assume that HT/VHT transmission on any AC except VO will
- * use aggregation. Since we don't have reliable reporting
- * of aggregation length, assume an average size based on the
- * tx rate.
- * This will not be very accurate, but much better than simply
- * assuming un-aggregated tx in all cases.
- */
- if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
- agg_shift = 1;
- else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
- agg_shift = 2;
- else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
- agg_shift = 3;
- else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
- agg_shift = 4;
- else if (stat.encoding != RX_ENC_HE ||
- duration > 20 * 1024) /* <= HE40 MCS6 2S */
- agg_shift = 5;
- else
- agg_shift = 6;
-
- duration *= len;
- duration /= AVG_PKT_SIZE;
+ duration = ieee80211_rate_expected_tx_airtime(hw, tx_rate, ri,
+ band, true, len);
duration /= 1024;
- duration += (overhead >> agg_shift);
return max_t(u32, duration, 4);
}
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index a4d5461f6480f0..8ebf5bcf3c0ec1 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -210,11 +210,13 @@ static ssize_t aql_pending_read(struct file *file,
"VI %u us\n"
"BE %u us\n"
"BK %u us\n"
+ "MC %u us\n"
"total %u us\n",
atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
+ atomic_read(&local->aql_mc_pending_airtime),
atomic_read(&local->aql_total_pending_airtime));
return simple_read_from_buffer(user_buf, count, ppos,
buf, len);
@@ -239,7 +241,8 @@ static ssize_t aql_txq_limit_read(struct file *file,
"VO %u %u\n"
"VI %u %u\n"
"BE %u %u\n"
- "BK %u %u\n",
+ "BK %u %u\n"
+ "MC %u\n",
local->aql_txq_limit_low[IEEE80211_AC_VO],
local->aql_txq_limit_high[IEEE80211_AC_VO],
local->aql_txq_limit_low[IEEE80211_AC_VI],
@@ -247,7 +250,8 @@ static ssize_t aql_txq_limit_read(struct file *file,
local->aql_txq_limit_low[IEEE80211_AC_BE],
local->aql_txq_limit_high[IEEE80211_AC_BE],
local->aql_txq_limit_low[IEEE80211_AC_BK],
- local->aql_txq_limit_high[IEEE80211_AC_BK]);
+ local->aql_txq_limit_high[IEEE80211_AC_BK],
+ local->aql_txq_limit_mc);
return simple_read_from_buffer(user_buf, count, ppos,
buf, len);
}
@@ -273,6 +277,11 @@ static ssize_t aql_txq_limit_write(struct file *file,
else
buf[count] = '\0';
+ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) {
+ local->aql_txq_limit_mc = q_limit_low;
+ return count;
+ }
+
if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
return -EINVAL;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34a9ea8b6f857e..78fea7a17ae766 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1464,10 +1464,12 @@ struct ieee80211_local {
spinlock_t handle_wake_tx_queue_lock;
u16 airtime_flags;
+ u32 aql_txq_limit_mc;
u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
u32 aql_threshold;
atomic_t aql_total_pending_airtime;
+ atomic_t aql_mc_pending_airtime;
atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
const struct ieee80211_ops *ops;
@@ -2939,6 +2941,11 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
extern const struct ethtool_ops ieee80211_ethtool_ops;
+u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,
+ struct ieee80211_tx_rate *tx_rate,
+ struct rate_info *ri,
+ enum nl80211_band band,
+ bool ampdu, int len);
u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *pubsta,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index eb1eaaf34612e1..b5dc7f659b5de5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -988,6 +988,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
spin_lock_init(&local->rx_path_lock);
spin_lock_init(&local->queue_stop_reason_lock);
+ local->aql_txq_limit_mc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_MC;
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
INIT_LIST_HEAD(&local->active_txqs[i]);
spin_lock_init(&local->active_txq_lock[i]);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 22eba0e6e54c5b..d12aed9c175617 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2491,13 +2491,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
struct sta_info *sta, u8 ac,
- u16 tx_airtime, bool tx_completed)
+ u16 tx_airtime, bool tx_completed,
+ bool mcast)
{
int tx_pending;
if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
return;
+ if (mcast) {
+ if (!tx_completed) {
+ atomic_add(tx_airtime, &local->aql_mc_pending_airtime);
+ return;
+ }
+
+ tx_pending = atomic_sub_return(tx_airtime,
+ &local->aql_mc_pending_airtime);
+ if (tx_pending < 0)
+ atomic_cmpxchg(&local->aql_mc_pending_airtime,
+ tx_pending, 0);
+ return;
+ }
+
if (!tx_completed) {
if (sta)
atomic_add(tx_airtime,
@@ -2797,6 +2812,28 @@ void sta_set_accumulated_removed_links_sinfo(struct sta_info *sta,
}
}
+static u32 sta_estimate_expected_throughput(struct sta_info *sta,
+ struct rate_info *ri,
+ struct ieee80211_bss_conf *bss_conf)
+{
+ struct ieee80211_hw *hw = &sta->sdata->local->hw;
+ struct ieee80211_chanctx_conf *conf;
+ u32 duration;
+ u8 band;
+
+ conf = rcu_dereference(bss_conf->chanctx_conf);
+ if (!conf)
+ return 0;
+ band = conf->def.chan->band;
+
+ duration = ieee80211_rate_expected_tx_airtime(hw, NULL, ri, band, true, 1024);
+ duration += duration >> 4; /* add assumed packet error rate of ~6% */
+ if (!duration)
+ return 0;
+
+ return ((1024 * USEC_PER_SEC) / duration) * 8;
+}
+
static void sta_set_link_sinfo(struct sta_info *sta,
struct link_station_info *link_sinfo,
struct ieee80211_link_data *link,
@@ -3011,6 +3048,10 @@ static void sta_set_link_sinfo(struct sta_info *sta,
link_sinfo->bss_param.beacon_interval = link->conf->beacon_int;
thr = sta_get_expected_throughput(sta);
+ if (!thr && (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)))
+ thr = sta_estimate_expected_throughput(sta,
+ &link_sinfo->txrate,
+ link->conf);
if (thr != 0) {
link_sinfo->filled |=
@@ -3264,6 +3305,14 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
if (thr != 0) {
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
sinfo->expected_throughput = thr;
+ } else if (!sta->sta.valid_links &&
+ (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {
+ thr = sta_estimate_expected_throughput(sta, &sinfo->txrate,
+ &sdata->vif.bss_conf);
+ if (thr) {
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+ sinfo->expected_throughput = thr;
+ }
}
if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL)) &&
@@ -3284,6 +3333,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
if (sta->sta.valid_links) {
struct ieee80211_link_data *link;
struct link_sta_info *link_sta;
+ u32 est_thr = 0;
int link_id;
sinfo->mlo_params_valid = true;
@@ -3295,17 +3345,25 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sinfo->valid_links = sta->sta.valid_links;
for_each_valid_link(sinfo, link_id) {
+ struct link_station_info *link_sinfo = sinfo->links[link_id];
+
link_sta = wiphy_dereference(sta->local->hw.wiphy,
sta->link[link_id]);
link = wiphy_dereference(sdata->local->hw.wiphy,
sdata->link[link_id]);
- if (!link_sta || !sinfo->links[link_id] || !link) {
+ if (!link_sta || !link_sinfo || !link) {
sinfo->valid_links &= ~BIT(link_id);
continue;
}
- sta_set_link_sinfo(sta, sinfo->links[link_id],
- link, tidstats);
+ sta_set_link_sinfo(sta, link_sinfo, link, tidstats);
+ if (!thr &&
+ (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT)))
+ est_thr += link_sinfo->expected_throughput;
+ }
+ if (est_thr) {
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+ sinfo->expected_throughput = est_thr;
}
}
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5da3142d8516ef..ee0d32877c5b47 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -147,7 +147,8 @@ struct airtime_info {
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
struct sta_info *sta, u8 ac,
- u16 tx_airtime, bool tx_completed);
+ u16 tx_airtime, bool tx_completed,
+ bool mcast);
struct sta_info;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index dd1dbba06838e5..c764e1a9548696 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -774,7 +774,7 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
ieee80211_sta_update_pending_airtime(local, sta,
skb_get_queue_mapping(skb),
tx_time_est,
- true);
+ true, info->tx_time_mc);
rcu_read_unlock();
}
@@ -1186,10 +1186,11 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
/* Do this here to avoid the expensive lookup of the sta
* in ieee80211_report_used_skb().
*/
+ bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc;
ieee80211_sta_update_pending_airtime(local, sta,
skb_get_queue_mapping(skb),
tx_time_est,
- true);
+ true, mcast);
ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 91b14112e24f08..85aff37819242a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4054,20 +4054,20 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
encap_out:
info->control.vif = vif;
- if (tx.sta &&
- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
- bool ampdu = txq->ac != IEEE80211_AC_VO;
+ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
+ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO;
u32 airtime;
airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
skb->len, ampdu);
- if (airtime) {
- airtime = ieee80211_info_set_tx_time_est(info, airtime);
- ieee80211_sta_update_pending_airtime(local, tx.sta,
- txq->ac,
- airtime,
- false);
- }
+ if (!airtime)
+ return skb;
+
+ airtime = ieee80211_info_set_tx_time_est(info, airtime);
+ info->tx_time_mc = !tx.sta;
+ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac,
+ airtime, false,
+ info->tx_time_mc);
}
return skb;
@@ -4119,6 +4119,7 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
struct ieee80211_txq *ret = NULL;
struct txq_info *txqi = NULL, *head = NULL;
bool found_eligible_txq = false;
+ bool aql_check;
spin_lock_bh(&local->active_txq_lock[ac]);
@@ -4142,26 +4143,28 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
if (!head)
head = txqi;
+ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
+ if (aql_check)
+ found_eligible_txq = true;
+
if (txqi->txq.sta) {
struct sta_info *sta = container_of(txqi->txq.sta,
struct sta_info, sta);
- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac);
- if (aql_check)
- found_eligible_txq = true;
-
- if (deficit < 0)
+ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) {
sta->airtime[txqi->txq.ac].deficit +=
sta->airtime_weight;
- if (deficit < 0 || !aql_check) {
- list_move_tail(&txqi->schedule_order,
- &local->active_txqs[txqi->txq.ac]);
- goto begin;
+ aql_check = false;
}
}
+ if (!aql_check) {
+ list_move_tail(&txqi->schedule_order,
+ &local->active_txqs[txqi->txq.ac]);
+ goto begin;
+ }
+
if (txqi->schedule_round == local->schedule_round[ac])
goto out;
@@ -4228,7 +4231,8 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
return true;
if (!txq->sta)
- return true;
+ return atomic_read(&local->aql_mc_pending_airtime) <
+ local->aql_txq_limit_mc;
if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
return true;
@@ -4248,6 +4252,24 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_txq_airtime_check);
+u32 ieee80211_txq_aql_pending(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct sta_info *sta;
+
+ if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
+ return 0;
+
+ if (!txq->sta)
+ return atomic_read(&local->aql_mc_pending_airtime);
+
+ sta = container_of(txq->sta, struct sta_info, sta);
+
+ return atomic_read(&sta->airtime[txq->ac].aql_tx_pending);
+}
+EXPORT_SYMBOL(ieee80211_txq_aql_pending);
+
static bool
ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)
{
@@ -4277,15 +4299,15 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock[ac]);
- if (!txqi->txq.sta)
- goto out;
-
if (list_empty(&txqi->schedule_order))
goto out;
if (!ieee80211_txq_schedule_airtime_check(local, ac))
goto out;
+ if (!txqi->txq.sta)
+ goto out;
+
list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
schedule_order) {
if (iter == txqi)
|
| 3/2 | 2026/07/22 14:54 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10511 output: 33 thoughts: 316 Thoughts: **Analyzing the mac80211 Patch for AQL and Throughput Modifications** Okay, so I've got a patch here that's making some interesting changes to the `mac80211` wireless stack. Looks like it's adding Airtime Queue Limit (AQL) support, specifically for multicast traffic – that's a key area to optimize. It's also modifying how the expected throughput for stations is calculated. That's intriguing; getting those throughput estimations right is crucial for airtime fairness and overall performance. I see it touches quite a few core files: `cfg80211.h`, `mac80211.h`, the airtime implementation (`airtime.c`), debug facilities, internal IEEE80211 structures, the main module (`main.c`), station information management (`sta_info.c`, `sta_info.h`), status updates, and the transmit path (`tx.c`). That indicates it’s really getting into the heart of the stack. Now, I need to verify its reachability and functionality. Since it's modifying the core logic related to airtime calculations, transmission queue (txq) airtime checks, and station throughput, I need to know how to test this. I think I can use `mac80211_hwsim` to reach it, which is ideal for this kind of low-level modification. Before I go further, I need to check the required configurations. Naturally, `MAC80211` itself is a given. I should search the Kconfig files for any dependencies related to AQL specifically, particularly `NL80211_EXT_FEATURE_AQL` or just `AQL` to make sure the feature is properly enabled. That's a good starting point. |
| 4/2 | 2026/07/22 14:54 | tool | grepper |
0mError:no matches Args: {
"Expression": "AQL",
"PathPrefix": "net/mac80211/Kconfig"
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/07/22 14:54 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11258 output: 38 thoughts: 18 Thoughts: Okay, here's my interpretation of those thoughts, tailored for an expert audience, and delivered as a first-person summary: **Digging into mac80211 Configuration** Alright, before I dive too deep into this problem, I want to make sure I'm not overlooking something obvious. The first thing I'm going to do is quickly scan my mental database. There's a good chance I already know this, but let's just make absolutely certain. My initial thought is to specifically check for anything related to *mac80211* configuration. I need to be methodical here. Are there any custom directives, module parameters, or quirks that might be influencing the behavior I'm seeing? I'm talking about anything that could be a specific, targeted setting for that subsystem, before I start looking at more generic kernel or system-wide settings. It's often the case that some subtle configuration is just overlooked in the noise. I would hate to spend more than a minute on a complex solution only to realise that a simple config was missed. Let's make sure I'm not missing something basic that's specific to the mac80211 driver. |
| 6/2 | 2026/07/22 14:54 | tool | grepper |
0mArgs:{
"Expression": "config MAC80211",
"PathPrefix": "net/mac80211/Kconfig"
}Results: {
"Output": "net/mac80211/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\nnet/mac80211/Kconfig:2:config MAC80211\nnet/mac80211/Kconfig-3-\ttristate \"Generic IEEE 802.11 Networking Stack (mac80211)\"\n--\nnet/mac80211/Kconfig=19=if MAC80211 != n\nnet/mac80211/Kconfig-20-\nnet/mac80211/Kconfig:21:config MAC80211_HAS_RC\nnet/mac80211/Kconfig-22-\tbool\nnet/mac80211/Kconfig-23-\nnet/mac80211/Kconfig:24:config MAC80211_RC_MINSTREL\nnet/mac80211/Kconfig-25-\tbool \"Minstrel\" if EXPERT\n--\nnet/mac80211/Kconfig=31=choice\n--\nnet/mac80211/Kconfig-40-\nnet/mac80211/Kconfig:41:config MAC80211_RC_DEFAULT_MINSTREL\nnet/mac80211/Kconfig-42-\tbool \"Minstrel\"\n--\nnet/mac80211/Kconfig=48=endchoice\nnet/mac80211/Kconfig-49-\nnet/mac80211/Kconfig:50:config MAC80211_RC_DEFAULT\nnet/mac80211/Kconfig-51-\tstring\n--\nnet/mac80211/Kconfig=57=comment \"Some wireless drivers require a rate control algorithm\"\n--\nnet/mac80211/Kconfig-59-\nnet/mac80211/Kconfig:60:config MAC80211_KUNIT_TEST\nnet/mac80211/Kconfig-61-\ttristate \"KUnit tests for mac80211\" if !KUNIT_ALL_TESTS\n--\nnet/mac80211/Kconfig-69-\nnet/mac80211/Kconfig:70:config MAC80211_MESH\nnet/mac80211/Kconfig-71-\tbool \"Enable mac80211 mesh networking support\"\n--\nnet/mac80211/Kconfig-78-\nnet/mac80211/Kconfig:79:config MAC80211_LEDS\nnet/mac80211/Kconfig-80-\tbool \"Enable LED triggers\"\n--\nnet/mac80211/Kconfig-87-\nnet/mac80211/Kconfig:88:config MAC80211_DEBUGFS\nnet/mac80211/Kconfig-89-\tbool \"Export mac80211 internals in DebugFS\"\n--\nnet/mac80211/Kconfig-96-\nnet/mac80211/Kconfig:97:config MAC80211_MESSAGE_TRACING\nnet/mac80211/Kconfig-98-\tbool \"Trace all mac80211 debug messages\"\n--\nnet/mac80211/Kconfig-109-\nnet/mac80211/Kconfig:110:menuconfig MAC80211_DEBUG_MENU\nnet/mac80211/Kconfig-111-\tbool \"Select mac80211 debugging features\"\n--\nnet/mac80211/Kconfig-115-\nnet/mac80211/Kconfig:116:config MAC80211_NOINLINE\nnet/mac80211/Kconfig-117-\tbool \"Do not inline TX/RX handlers\"\n--\nnet/mac80211/Kconfig-131-\nnet/mac80211/Kconfig:132:config MAC80211_VERBOSE_DEBUG\nnet/mac80211/Kconfig-133-\tbool \"Verbose debugging output\"\n--\nnet/mac80211/Kconfig-142-\nnet/mac80211/Kconfig:143:config MAC80211_MLME_DEBUG\nnet/mac80211/Kconfig-144-\tbool \"Verbose managed MLME output\"\n--\nnet/mac80211/Kconfig-153-\nnet/mac80211/Kconfig:154:config MAC80211_STA_DEBUG\nnet/mac80211/Kconfig-155-\tbool \"Verbose station debugging\"\n--\nnet/mac80211/Kconfig-162-\nnet/mac80211/Kconfig:163:config MAC80211_HT_DEBUG\nnet/mac80211/Kconfig-164-\tbool \"Verbose HT debugging\"\n--\nnet/mac80211/Kconfig-174-\nnet/mac80211/Kconfig:175:config MAC80211_OCB_DEBUG\nnet/mac80211/Kconfig-176-\tbool \"Verbose OCB debugging\"\n--\nnet/mac80211/Kconfig-185-\nnet/mac80211/Kconfig:186:config MAC80211_IBSS_DEBUG\nnet/mac80211/Kconfig-187-\tbool \"Verbose IBSS debugging\"\n--\nnet/mac80211/Kconfig-196-\nnet/mac80211/Kconfig:197:config MAC80211_PS_DEBUG\nnet/mac80211/Kconfig-198-\tbool \"Verbose powersave mode debugging\"\n--\nnet/mac80211/Kconfig-208-\nnet/mac80211/Kconfig:209:config MAC80211_MPL_DEBUG\nnet/mac80211/Kconfig-210-\tbool \"Verbose mesh peer link debugging\"\n--\nnet/mac80211/Kconfig-221-\nnet/mac80211/Kconfig:222:config MAC80211_MPATH_DEBUG\nnet/mac80211/Kconfig-223-\tbool \"Verbose mesh path debugging\"\n--\nnet/mac80211/Kconfig-234-\nnet/mac80211/Kconfig:235:config MAC80211_MHWMP_DEBUG\nnet/mac80211/Kconfig-236-\tbool \"Verbose mesh HWMP routing debugging\"\n--\nnet/mac80211/Kconfig-247-\nnet/mac80211/Kconfig:248:config MAC80211_MESH_SYNC_DEBUG\nnet/mac80211/Kconfig-249-\tbool \"Verbose mesh synchronization debugging\"\n--\nnet/mac80211/Kconfig-258-\nnet/mac80211/Kconfig:259:config MAC80211_MESH_CSA_DEBUG\nnet/mac80211/Kconfig-260-\tbool \"Verbose mesh channel switch debugging\"\n--\nnet/mac80211/Kconfig-269-\nnet/mac80211/Kconfig:270:config MAC80211_MESH_PS_DEBUG\nnet/mac80211/Kconfig-271-\tbool \"Verbose mesh powersave debugging\"\n--\nnet/mac80211/Kconfig-280-\nnet/mac80211/Kconfig:281:config MAC80211_TDLS_DEBUG\nnet/mac80211/Kconfig-282-\tbool \"Verbose TDLS debugging\"\n--\nnet/mac80211/Kconfig-292-\nnet/mac80211/Kconfig:293:config MAC80211_DEBUG_COUNTERS\nnet/mac80211/Kconfig-294-\tbool \"Extra statistics for TX/RX debugging\"\n--\nnet/mac80211/Kconfig-307-\nnet/mac80211/Kconfig:308:config MAC80211_STA_HASH_MAX_SIZE\nnet/mac80211/Kconfig-309-\tint \"Station hash table maximum size\" if MAC80211_DEBUG_MENU\n"
} |
| 7/2 | 2026/07/22 14:54 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13745 output: 45 thoughts: 115 Thoughts: **Analyzing the Mac80211 Airtime Management Patch** Okay, so I'm looking at this patch and immediately, I can see it's touching some critical parts of the mac80211 airtime management system. Specifically, it's modifying `ieee80211_rate_expected_tx_airtime`, `ieee80211_calc_expected_tx_airtime`, `ieee80211_sta_update_pending_airtime`, `ieee80211_txq_airtime_check`, and `ieee80211_txq_aql_pending`. These are all core functions – fundamental building blocks, really – within the framework, especially as they relate to calculating and managing transmission airtime for 802.11 frames. The changes here could be pretty impactful, affecting scheduling, fairness, and overall performance. Time to dig in and understand *why* these specific functions are being targeted. I need to get a handle on the key functions so I can properly assess the implication of the patch. |
| 8/2 | 2026/07/22 14:54 | tool | grepper |
0mArgs:{
"Expression": "ieee80211_rate_expected_tx_airtime",
"PathPrefix": "net/mac80211/"
}Results: {
"Output": "net/mac80211/airtime.c=754=EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);\nnet/mac80211/airtime.c-755-\nnet/mac80211/airtime.c:756:u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,\nnet/mac80211/airtime.c-757-\t\t\t\t struct ieee80211_tx_rate *tx_rate,\n--\nnet/mac80211/airtime.c=803=u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,\n--\nnet/mac80211/airtime.c-828-\nnet/mac80211/airtime.c:829:\t\tduration = ieee80211_rate_expected_tx_airtime(hw, tx_rate, ri,\nnet/mac80211/airtime.c-830-\t\t\t\t\t\t\t band, true, len);\n--\nnet/mac80211/ieee80211_i.h=2942=extern const struct ethtool_ops ieee80211_ethtool_ops;\nnet/mac80211/ieee80211_i.h-2943-\nnet/mac80211/ieee80211_i.h:2944:u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,\nnet/mac80211/ieee80211_i.h-2945-\t\t\t\t struct ieee80211_tx_rate *tx_rate,\n--\nnet/mac80211/sta_info.c=2815=static u32 sta_estimate_expected_throughput(struct sta_info *sta,\n--\nnet/mac80211/sta_info.c-2828-\nnet/mac80211/sta_info.c:2829:\tduration = ieee80211_rate_expected_tx_airtime(hw, NULL, ri, band, true, 1024);\nnet/mac80211/sta_info.c-2830-\tduration += duration \u003e\u003e 4; /* add assumed packet error rate of ~6% */\n"
} |
| 9/2 | 2026/07/22 14:54 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14800 output: 44 thoughts: 21 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, and delivered as if they were my own: **Analyzing `ieee80211_txq_aql_pending`** Alright, time to dig into `ieee80211_txq_aql_pending`. That function name itself is a pretty big clue. It's obviously related to the 802.11 transmit queue and likely connected to Active Queue Management (AQM). I'm assuming we're looking at pending packets, the ones waiting to be sent, right? Given the context of AQM, I'd bet we're trying to figure out if there's back pressure or congestion within the queue. We need to understand how this function reports the state of things; does it return a simple count, a boolean indicating if *any* packets are pending, or something more nuanced like a per-AC (Access Category) breakdown or even some kind of estimate of the queued bytes? Are we talking about packets *enqueued* but not yet *transmitted*, or do we include packets in flight to a degree? This will affect how it's used within a larger AQM control loop. I'd need to confirm what the function does with its parameters - are they the TX queue itself, specific ACs, or something else entirely? A quick peek at the surrounding code to determine its intended use will be useful. |
| 10/2 | 2026/07/22 14:54 | tool | grepper |
0mArgs:{
"Expression": "ieee80211_txq_aql_pending",
"PathPrefix": "net/mac80211/"
}Results: {
"Output": "net/mac80211/tx.c=4253=EXPORT_SYMBOL(ieee80211_txq_airtime_check);\nnet/mac80211/tx.c-4254-\nnet/mac80211/tx.c:4255:u32 ieee80211_txq_aql_pending(struct ieee80211_hw *hw,\nnet/mac80211/tx.c-4256-\t\t\t struct ieee80211_txq *txq)\n--\nnet/mac80211/tx.c-4270-}\nnet/mac80211/tx.c:4271:EXPORT_SYMBOL(ieee80211_txq_aql_pending);\nnet/mac80211/tx.c-4272-\n"
} |
| 11/2 | 2026/07/22 14:54 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15405 output: 44 thoughts: 21 Thoughts: Okay, here's my attempt at summarizing the thought process, as if it were my own, assuming I'm an expert in the field: **Diving into `ieee80211_txq_airtime_check`** Alright, time to get to it. Let's dig into `ieee80211_txq_airtime_check`. I know this function is critical. It's the gatekeeper, the arbiter of fairness in our wireless stack. This is where we decide if a frame gets airtime or gets held back, and I need to understand it cold. We're talking about the guts of how we manage contention and prioritize traffic in this interface. I want to see how it's making its determinations: what factors are being considered, what the thresholds are, and what the overall logic flow is. Knowing this function's logic is absolutely key to understanding the performance characteristics of our wireless network under load. I need to refresh my understanding of the interactions between airtime fairness and any other admission control mechanisms we've implemented. Is there a potential bottleneck? Are there any hidden bugs lurking that could be causing unfair distribution or unexpected drops? I want to make sure the algorithm is robust, that it accounts for our various traffic types, and that it's optimized as best as can be. This is a critical building block, so let's get down to brass tacks and understand this function. |
| 12/2 | 2026/07/22 14:55 | tool | grepper |
0mArgs:{
"Expression": "ieee80211_txq_airtime_check",
"PathPrefix": "net/mac80211/"
}Results: {
"Output": "net/mac80211/tx.c=3875=struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,\n--\nnet/mac80211/tx.c-3893-\nnet/mac80211/tx.c:3894:\tif (!ieee80211_txq_airtime_check(hw, txq))\nnet/mac80211/tx.c-3895-\t\treturn NULL;\n--\nnet/mac80211/tx.c=4116=struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)\n--\nnet/mac80211/tx.c-4145-\nnet/mac80211/tx.c:4146:\taql_check = ieee80211_txq_airtime_check(hw, \u0026txqi-\u003etxq);\nnet/mac80211/tx.c-4147-\tif (aql_check)\n--\nnet/mac80211/tx.c=4219=DEFINE_STATIC_KEY_FALSE(aql_disable);\nnet/mac80211/tx.c-4220-\nnet/mac80211/tx.c:4221:bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,\nnet/mac80211/tx.c-4222-\t\t\t\t struct ieee80211_txq *txq)\n--\nnet/mac80211/tx.c-4252-}\nnet/mac80211/tx.c:4253:EXPORT_SYMBOL(ieee80211_txq_airtime_check);\nnet/mac80211/tx.c-4254-\n"
} |
| 13/2 | 2026/07/22 14:55 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 16298 output: 45 thoughts: 22 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Analyzing `ieee80211_sta_update_pending_airtime`** Okay, let's dive into `ieee80211_sta_update_pending_airtime`. I need to understand how this function handles pending airtime updates for a station. My initial focus is likely to be on the function's core logic. What triggers this update? Is it related to QoS, admission control, or some form of rate adaptation? I expect to see conditionals and possibly loops related to checking various airtime calculation parameters. I need to understand what data structures are being modified within this function. I'll need to examine the `ieee80211_sta` structure and any related structs – probably something containing airtime usage or granted time. Specifically, I need to see how the pending airtime is integrated into the overall airtime accounting for a station. Is this a simple increment, or does it involve more sophisticated calculations, perhaps taking into account channel conditions and packet characteristics? Beyond the direct modification of data structures, I'm going to look for potential side effects. Does this function interact with other parts of the scheduler, such as packet queuing or transmission scheduling? I want to see if any locks are taken, and where the function is called. What interrupt context does it run in? Are there any potential race conditions I need to be aware of? Are there any obvious areas for optimization, or common pitfalls that could lead to airtime starvation or unfair allocation? I also need to see any other related update functions. This could give me a more complete picture of how the airtime allocation system works. I'm expecting to find a delicate balance between accuracy, overhead, and fairness in this implementation. I need to figure out what trade-offs the developers made. |
| 14/2 | 2026/07/22 14:55 | tool | grepper |
0mArgs:{
"Expression": "ieee80211_sta_update_pending_airtime",
"PathPrefix": "net/mac80211/"
}Results: {
"Output": "net/mac80211/sta_info.c=2490=EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);\nnet/mac80211/sta_info.c-2491-\nnet/mac80211/sta_info.c:2492:void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,\nnet/mac80211/sta_info.c-2493-\t\t\t\t\t struct sta_info *sta, u8 ac,\n--\nnet/mac80211/sta_info.h=138=struct airtime_info {\n--\nnet/mac80211/sta_info.h-147-\nnet/mac80211/sta_info.h:148:void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,\nnet/mac80211/sta_info.h-149-\t\t\t\t\t struct sta_info *sta, u8 ac,\n--\nnet/mac80211/status.c=756=static void ieee80211_report_used_skb(struct ieee80211_local *local,\n--\nnet/mac80211/status.c-773-\t\tsta = sta_info_get_by_addrs(local, hdr-\u003eaddr1, hdr-\u003eaddr2);\nnet/mac80211/status.c:774:\t\tieee80211_sta_update_pending_airtime(local, sta,\nnet/mac80211/status.c-775-\t\t\t\t\t\t skb_get_queue_mapping(skb),\n--\nnet/mac80211/status.c=1164=void ieee80211_tx_status_ext(struct ieee80211_hw *hw,\n--\nnet/mac80211/status.c-1189-\t\tbool mcast = IEEE80211_SKB_CB(skb)-\u003etx_time_mc;\nnet/mac80211/status.c:1190:\t\tieee80211_sta_update_pending_airtime(local, sta,\nnet/mac80211/status.c-1191-\t\t\t\t\t\t skb_get_queue_mapping(skb),\n--\nnet/mac80211/tx.c=3875=struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,\n--\nnet/mac80211/tx.c-4067-\t\tinfo-\u003etx_time_mc = !tx.sta;\nnet/mac80211/tx.c:4068:\t\tieee80211_sta_update_pending_airtime(local, tx.sta, txq-\u003eac,\nnet/mac80211/tx.c-4069-\t\t\t\t\t\t airtime, false,\n"
} |
| 15/2 | 2026/07/22 14:55 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17549 output: 36 thoughts: 236 Thoughts: **My Assessment of the Multicast AQL Patch** Okay, so this patch introduces AQL (Airtime Fairness Queueing) functionality for multicast traffic. My primary concern right now is ensuring the correct integration and that we haven't overlooked any crucial components. My focus should be on verifying the usage of these symbols within the relevant code paths, specifically: `ieee80211_sta_update_pending_airtime`, `ieee80211_txq_airtime_check`, `ieee80211_txq_aql_pending`, `ieee80211_rate_expected_tx_airtime`, and `sta_estimate_expected_throughput`. First, I need to confirm that `MAC80211` is the correct config to enable this. The code's located within `net/mac80211/`, so I believe `MAC80211` is the relevant config item. But let's be absolutely certain – is there anything else? The code uses `wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)`, which indicates a runtime feature flag is used. I need to quickly scan to confirm there are no other configurations needed. From my initial assessment, `MAC80211` alone should suffice. Just to be absolutely certain, I'll perform a quick double-check on how `sta_estimate_expected_throughput` is used in this context. It's a key element, and I want to ensure my initial assessment is correct. |
| 16/2 | 2026/07/22 14:55 | tool | grepper |
0mArgs:{
"Expression": "sta_estimate_expected_throughput",
"PathPrefix": "net/mac80211/"
}Results: {
"Output": "net/mac80211/sta_info.c=2789=void sta_set_accumulated_removed_links_sinfo(struct sta_info *sta,\n--\nnet/mac80211/sta_info.c-2814-\nnet/mac80211/sta_info.c:2815:static u32 sta_estimate_expected_throughput(struct sta_info *sta,\nnet/mac80211/sta_info.c-2816-\t\t\t\t\t struct rate_info *ri,\n--\nnet/mac80211/sta_info.c=2837=static void sta_set_link_sinfo(struct sta_info *sta,\n--\nnet/mac80211/sta_info.c-3051-\tif (!thr \u0026\u0026 (link_sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_TX_BITRATE)))\nnet/mac80211/sta_info.c:3052:\t\tthr = sta_estimate_expected_throughput(sta,\nnet/mac80211/sta_info.c-3053-\t\t\t\t\t\t \u0026link_sinfo-\u003etxrate,\n--\nnet/mac80211/sta_info.c=3079=void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,\n--\nnet/mac80211/sta_info.c-3309-\t\t (sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_TX_BITRATE))) {\nnet/mac80211/sta_info.c:3310:\t\tthr = sta_estimate_expected_throughput(sta, \u0026sinfo-\u003etxrate,\nnet/mac80211/sta_info.c-3311-\t\t\t\t\t\t \u0026sdata-\u003evif.bss_conf);\n"
} |
| 17/2 | 2026/07/22 14:55 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 18655 output: 182 thoughts: 187 Thoughts: Here's my summary, as I understand it: **Airtime Queue Limit for Multicast and Throughput Calculation** Alright, so the patch looks good – functional and definitely reachable within the existing 802.11 stack. My focus here is on the addition of Airtime Queue Limit (AQL) support for multicast traffic, alongside modifications to how we estimate expected throughput for stations within mac80211. This is solid, core logic. Seems like the developers have been digging into: `ieee80211_sta_update_pending_airtime`, `ieee80211_txq_airtime_check`, `ieee80211_txq_aql_pending`, `ieee80211_rate_expected_tx_airtime` and `sta_estimate_expected_throughput`. These functions are directly involved in the critical path. The fact that `MAC80211` is the relevant config confirms it’s within the heart of the mac80211 framework. We can trigger this through `mac80211_hwsim` which is great for testing this new functionality. Seems like the correct approach and direction. Let's call set-results. |
| 18/2 | 2026/07/22 14:55 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"MAC80211"
],
"FocusSymbols": [
"ieee80211_sta_update_pending_airtime",
"ieee80211_txq_airtime_check",
"ieee80211_txq_aql_pending",
"ieee80211_rate_expected_tx_airtime",
"sta_estimate_expected_throughput"
],
"Reasoning": "The patch introduces Airtime Queue Limit (AQL) support for multicast traffic and modifies the expected throughput calculation for stations in mac80211. This is reachable core logic for 802.11 networking and can be triggered via mac80211_hwsim.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"MAC80211"
],
"FocusSymbols": [
"ieee80211_sta_update_pending_airtime",
"ieee80211_txq_airtime_check",
"ieee80211_txq_aql_pending",
"ieee80211_rate_expected_tx_airtime",
"sta_estimate_expected_throughput"
],
"Reasoning": "The patch introduces Airtime Queue Limit (AQL) support for multicast traffic and modifies the expected throughput calculation for stations in mac80211. This is reachable core logic for 802.11 networking and can be triggered via mac80211_hwsim.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|