wifi: ath11k: WMI services debugfs and HE AP fixes
cover wifi: ath11k: WMI services debugfs and HE AP fixes
A debugfs file listing the firmware's WMI services, and fixes for an ath11k HE AP found by checking it against IEEE Std 802.11-2024, each tested on a QCN9074:
1. debugfs: wmi_services lists the services the firmware advertises. Earlier posted in the airtime fairness series, now split by tree; since v2 the commit message no longer claims to match ath10k's output.
2. Probe Responses during a channel switch carried the initial count:
ath11k never counted down mac80211's CSA counter (as ath12k does).
3. Without spatial reuse parameters, an AP enabled non-SRG OBSS PD at -62 dBm; it now stays off, as in ath12k.
4. A 6 GHz AP never sent its per-20 MHz power limits to firmware (the TPC command was station only); it now does as an LPI AP, as in ath12k.
5. The hardware DSCP-TID tables used the class selector bits, while cfg80211 maps DSCP to UP per RFC 8325 section 4; checked on air through the firmware's per-TID peer statistics (CS1->1, AF21->3, EF->6, CS6->7).
None of them depends on the mac80211 series sent alongside.
The patches by me were written with an AI coding assistant (Claude Code), which also drafted the changelogs; the testing described was done on the hardware.
v2 of patch 1: https://lore.kernel.org/all/[email protected]/
Andrei-Alexandru Bleortu (5):
wifi: ath11k: add a debugfs file listing the firmware WMI services
wifi: ath11k: count down channel switch announcements in mac80211
wifi: ath11k: leave OBSS PD off when spatial reuse is not configured
wifi: ath11k: set the 6 GHz transmit power limits of an AP
wifi: ath11k: map DSCP to TID as cfg80211 does by default
drivers/net/wireless/ath/ath11k/core.h | 2 ++ drivers/net/wireless/ath/ath11k/debugfs.c | 15 +++++++++++ drivers/net/wireless/ath/ath11k/hal_tx.c | 30 +++++++++++----------- drivers/net/wireless/ath/ath11k/mac.c | 31 +++++++++++++++-------- drivers/net/wireless/ath/ath11k/wmi.c | 23 +++++++++++++---- 5 files changed, 71 insertions(+), 30 deletions(-)
base-commit: f49defea7668d8c68ec19fa085ef3da6075561c7
Signature · 1 line
2.47.3
PATCH 1/5 wifi: ath11k: add a debugfs file listing the firmware WMI services
Whether a feature is available often comes down to a WMI service bit the firmware reports at boot, and ath11k only logs the ext services, at debug level. List the number of every set bit of the service map in <soc>/wmi_services, so that the capabilities of a given firmware build can be read directly.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/debugfs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/net/wireless/ath/ath11k/debugfs.c +15 -0
@@ -851,6 +851,18 @@ static const struct file_operations fops_sram_dump = { .llseek = default_llseek, }; +static int ath11k_wmi_services_show (struct seq_file *m,void *v) +{ +struct ath11k_base *ab = m->private; +unsigned int i; + +for_each_set_bit (i, ab->wmi_ab.svc_map,WMI_MAX_EXT2_SERVICE ) +seq_printf (m,"%u\n" , i); + +return 0 ; +} +DEFINE_SHOW_ATTRIBUTE (ath11k_wmi_services); +int ath11k_debugfs_pdev_create (struct ath11k_base *ab) {if (test_bit (ATH11K_FLAG_REGISTERED , &ab->dev_flags))
@@ -862,6 +874,9 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)debugfs_create_file ("soc_dp_stats" ,0400 , ab->debugfs_soc, ab, &fops_soc_dp_stats); +debugfs_create_file ("wmi_services" ,0400 , ab->debugfs_soc, ab, + &ath11k_wmi_services_fops); +if (ab->hw_params.sram_dump.start !=0 )debugfs_create_file ("sram" ,0400 , ab->debugfs_soc, ab, &fops_sram_dump);
Signature · 1 line
2.47.3
PATCH 2/5 wifi: ath11k: count down channel switch announcements in mac80211
In reply to Andrei-Alexandru Bleortuath11k handled the CSA switch count event only once the count reached zero, to finish the switch, and did not ask the firmware for an event at any other count. mac80211's countdown therefore never moved: Probe Response frames, which mac80211 fills from it, and every beacon template uploaded during the switch carried the initial Channel Switch Count, although IEEE Std 802.11-2024, 9.4.2.17 has it give the number of TBTTs left until the switch.
Request an event for every count in the beacon template command and decrement mac80211's countdown on each one that matches the expected count; a beacon that failed to go out repeats the previous count, which is then skipped. This is how ath12k handles the same event.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/core.h | 2 ++ drivers/net/wireless/ath/ath11k/wmi.c | 23 ++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath11k/core.h +2 -0
@@ -395,6 +395,8 @@ struct ath11k_vif {bool is_started;bool is_up; +/* CSA countdown value the firmware is expected to report next */ +u8 current_cntdown_counter;bool ftm_responder;bool spectral_enabled;bool ps;
drivers/net/wireless/ath/ath11k/wmi.c +18 -5
@@ -1806,6 +1806,9 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,if (vif->bss_conf.csa_active) { cmd->csa_switch_count_offset = offs->cntdwn_counter_offs[0 ]; cmd->ext_csa_switch_count_offset = offs->cntdwn_counter_offs[1 ]; +/* a switch count event for every count, not just the last */ + cmd->csa_event_bitmap =0xffffffff ; + arvif->current_cntdown_counter = bcn->data[offs->cntdwn_counter_offs[0 ]]; } cmd->buf_len = bcn->len;
@@ -8385,10 +8388,6 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab,struct ath11k_vif *arvif;int i; -/* Finish CSA once the switch count becomes NULL */ -if (ev->current_switch_count) -return ; -if (num_vdevs > vdev_ids_len /sizeof (*vdev_ids)) {ath11k_warn (ab,"csa switch count num_vdevs %u exceeds tlv array length %u\n" , num_vdevs, vdev_ids_len);
@@ -8405,8 +8404,22 @@ ath11k_wmi_process_csa_switch_count_event(struct ath11k_base *ab,continue ; } -if (arvif->is_up && arvif->vif->bss_conf.csa_active) +if (!arvif->is_up || !arvif->vif->bss_conf.csa_active) +continue ; + +if (!ev->current_switch_count) {ieee80211_csa_finish (arvif->vif,0 ); + arvif->current_cntdown_counter =0 ; + }else if (ev->current_switch_count >1 ) { +/* A beacon that failed to go out repeats the previous +* count; mac80211 counts down once per beacon sent. +*/ +if (ev->current_switch_count != arvif->current_cntdown_counter) +continue ; + + arvif->current_cntdown_counter = +ieee80211_beacon_update_cntdwn (arvif->vif,0 ); + } }rcu_read_unlock (); }
Signature · 1 line
2.47.3
PATCH 3/5 wifi: ath11k: leave OBSS PD off when spatial reuse is not configured
In reply to Andrei-Alexandru Bleortumac80211 reports BSS_CHANGED_HE_OBSS_PD when an HE AP starts even if user space configured no spatial reuse parameters, with he_obss_pd .enable false. ath11k ignored the flag and, with an empty SR Control, enabled non-SRG OBSS PD at its default maximum threshold of -62 dBm, where IEEE Std 802.11-2024, 26.10.2.4 puts the non-SRG OBSS PD maximum at -82 dBm plus an offset that the AP did not advertise.
Disable OBSS PD unless it is enabled, as ath12k does.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/ath/ath11k/mac.c +2 -1
@@ -3373,7 +3373,8 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,/* Set and enable SRG/non-SRG OBSS PD Threshold */ param_id =WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD ; -if (test_bit (ATH11K_FLAG_MONITOR_STARTED , &ar->monitor_flags)) { +if (test_bit (ATH11K_FLAG_MONITOR_STARTED , &ar->monitor_flags) || + !he_obss_pd->enable) { ret =ath11k_wmi_pdev_set_param (ar, param_id,0 , pdev_id);if (ret) ath11k_warn(ar->ab,
Signature · 1 line
2.47.3
PATCH 4/5 wifi: ath11k: set the 6 GHz transmit power limits of an AP
In reply to Andrei-Alexandru BleortuA 6 GHz AP has to keep within the regulatory power limits of its channel, which for low power indoor operation are given per MHz (IEEE Std 802.11-2024, 11.7.6, E.2.7). ath11k sends the per-20 MHz limits to firmware with WMI_VDEV_SET_TPC_POWER_CMDID only for station vdevs; an AP got just one transmit power limit for the whole channel, and the firmware, as the driver's own comment says, is not aware of the EIRP limits unless the driver sets them with that command.
Send them for AP vdevs too, as ath12k does, with the low power indoor AP type, the only AP power mode supported for now. An AP builds its limits from the regulatory rules alone: power levels kept from an earlier start are not a received Transmit Power Envelope.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/mac.c | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
drivers/net/wireless/ath/ath11k/mac.c +19 -9
@@ -3515,13 +3515,14 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,return 0 ; } -static bool ath11k_mac_supports_station_tpc (struct ath11k *ar, -struct ath11k_vif *arvif, -const struct cfg80211_chan_def *chandef) +static bool ath11k_mac_supports_tpc (struct ath11k *ar, +struct ath11k_vif *arvif, +const struct cfg80211_chan_def *chandef) {return ath11k_wmi_supports_6ghz_cc_ext (ar) &&test_bit (WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT , ar->ab->wmi_ab.svc_map) && - arvif->vdev_type ==WMI_VDEV_TYPE_STA && + (arvif->vdev_type ==WMI_VDEV_TYPE_STA || + arvif->vdev_type ==WMI_VDEV_TYPE_AP ) && arvif->vdev_subtype ==WMI_VDEV_SUBTYPE_NONE && chandef->chan && chandef->chan->band ==NL80211_BAND_6GHZ ;
@@ -7655,8 +7656,8 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,/* TODO: For now we only set TPC power here. However when * channel changes, say CSA, it should be updated again. */ -if (ath11k_mac_supports_station_tpc (ar, arvif, chandef)) { -ath11k_mac_fill_reg_tpc_info (ar, arvif->vif, &arvif->chanctx); +if (ath11k_mac_supports_tpc (ar, arvif, chandef)) { +ath11k_mac_fill_reg_tpc_info (ar, arvif->vif, ctx);ath11k_wmi_send_vdev_set_tpc_power (ar, arvif->vdev_id, &arvif->reg_tpc_info); }
@@ -8168,7 +8169,11 @@ void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, start_freq =ath11k_mac_get_6ghz_start_frequency (&ctx->def); pwr_reduction = bss_conf->pwr_reduction; -if (arvif->reg_tpc_info.num_pwr_levels) { +/* Only a station takes power levels from its AP's TPE; an AP's own +* levels from an earlier start are not a TPE. +*/ +if (arvif->vdev_type ==WMI_VDEV_TYPE_STA && + arvif->reg_tpc_info.num_pwr_levels) { is_tpe_present = true; num_pwr_levels = arvif->reg_tpc_info.num_pwr_levels; }else {
@@ -8319,8 +8324,13 @@ void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, reg_tpc_info->num_pwr_levels = num_pwr_levels; reg_tpc_info->is_psd_power = is_psd_power; reg_tpc_info->eirp_power = eirp_power; - reg_tpc_info->ap_power_type = -ath11k_reg_ap_pwr_convert (vif->bss_conf.power_type); +if (arvif->vdev_type ==WMI_VDEV_TYPE_STA ) + reg_tpc_info->ap_power_type = +ath11k_reg_ap_pwr_convert (vif->bss_conf.power_type); +else +/* LPI is the only AP power mode supported for now */ + reg_tpc_info->ap_power_type = +ath11k_reg_ap_pwr_convert (IEEE80211_REG_LPI_AP ); } static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
Signature · 1 line
2.47.3
PATCH 5/5 wifi: ath11k: map DSCP to TID as cfg80211 does by default
In reply to Andrei-Alexandru BleortuWhere the hardware classifies frames by their DSCP, it takes the TID from the DSCP-TID tables ath11k programs, all of them with the DSCP's class selector bits. cfg80211, which classifies the frames mac80211 queues, follows RFC 8325 section 4 instead (commit 6fdb8b8781d5 ("wifi: cfg80211: Update the default DSCP-to-UP mapping")), as does Wi-Fi QoS Management. The two disagree for AF1x and CS2 (UP 0, not 1 and 2), AF2x (UP 3, best effort, not 2, background), CS3 and AF3x (UP 4, not 3), VA and EF (UP 6, voice, not 5, video) and CS6 (UP 7, not 6).
Program the tables with cfg80211's default mapping.
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-02146-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/hal_tx.c | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-)
drivers/net/wireless/ath/ath11k/hal_tx.c +15 -15
@@ -11,26 +11,26 @@#define DSCP_TID_MAP_TBL_ENTRY_SIZE 64 -/* dscp_tid_map - Default DSCP-TID mapping +/* dscp_tid_map - Default DSCP-TID mapping, the one cfg80211_classify8021d() +* uses without a QoS map: the DSCP's class selector bits, except where RFC 8325 +* section 4 maps the DiffServ service class differently. * -* DSCP TID -* 000000 0 -* 001000 1 -* 010000 2 -* 011000 3 -* 100000 4 -* 101000 5 -* 110000 6 -* 111000 7 +* DSCP TID +* AF11-13, CS2 0 +* AF21-23 3 +* CS3, AF31-33 4 +* VA, EF 6 +* CS6 7 +* any other DSCP >> 3 */ static const u8 dscp_tid_map[DSCP_TID_MAP_TBL_ENTRY_SIZE ] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , -1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 , -2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 , -3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 , +1 ,1 ,0 ,1 ,0 ,1 ,0 ,1 , +0 ,2 ,3 ,2 ,3 ,2 ,3 ,2 , +4 ,3 ,4 ,3 ,4 ,3 ,4 ,3 ,4 ,4 ,4 ,4 ,4 ,4 ,4 ,4 , -5 ,5 ,5 ,5 ,5 ,5 ,5 ,5 , -6 ,6 ,6 ,6 ,6 ,6 ,6 ,6 , +5 ,5 ,5 ,5 ,6 ,5 ,6 ,5 , +7 ,6 ,6 ,6 ,6 ,6 ,6 ,6 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 , };
Signature · 1 line
2.47.3