Message ID | 20250207071003.162576-1-quic_lingbok@quicinc.com |
---|---|
State | Superseded |
Headers | show |
Series | wifi: ath12k: report station mode per-chain signal strength | expand |
Hi Lingbo,
kernel test robot noticed the following build warnings:
[auto build test WARNING on d132a72d768bae74d10e6539fcf6522dfdbd1115]
url: https://github.com/intel-lab-lkp/linux/commits/Lingbo-Kong/wifi-ath12k-report-station-mode-per-chain-signal-strength/20250207-151239
base: d132a72d768bae74d10e6539fcf6522dfdbd1115
patch link: https://lore.kernel.org/r/20250207071003.162576-1-quic_lingbok%40quicinc.com
patch subject: [PATCH] wifi: ath12k: report station mode per-chain signal strength
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20250208/202502081250.6rZZ2s6H-lkp@intel.com/config)
compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250208/202502081250.6rZZ2s6H-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502081250.6rZZ2s6H-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from drivers/net/wireless/ath/ath12k/wmi.c:6:
In file included from include/linux/skbuff.h:17:
In file included from include/linux/bvec.h:10:
In file included from include/linux/highmem.h:8:
In file included from include/linux/cacheflush.h:5:
In file included from arch/x86/include/asm/cacheflush.h:5:
In file included from include/linux/mm.h:2224:
include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
504 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
505 | item];
| ~~~~
include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
511 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
512 | NR_VM_NUMA_EVENT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~~
include/linux/vmstat.h:524:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
524 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
525 | NR_VM_NUMA_EVENT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/ath/ath12k/wmi.c:7550:2: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
7550 | default:
| ^
drivers/net/wireless/ath/ath12k/wmi.c:7550:2: note: insert 'break;' to avoid fall-through
7550 | default:
| ^
| break;
4 warnings generated.
vim +7550 drivers/net/wireless/ath/ath12k/wmi.c
1715fcabad1648 Lingbo Kong 2025-02-07 7520
79e7b04b5388c1 Lingbo Kong 2025-01-15 7521 static int ath12k_wmi_tlv_fw_stats_parse(struct ath12k_base *ab,
79e7b04b5388c1 Lingbo Kong 2025-01-15 7522 u16 tag, u16 len,
79e7b04b5388c1 Lingbo Kong 2025-01-15 7523 const void *ptr, void *data)
79e7b04b5388c1 Lingbo Kong 2025-01-15 7524 {
79e7b04b5388c1 Lingbo Kong 2025-01-15 7525 struct wmi_tlv_fw_stats_parse *parse = data;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7526 int ret = 0;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7527
79e7b04b5388c1 Lingbo Kong 2025-01-15 7528 switch (tag) {
79e7b04b5388c1 Lingbo Kong 2025-01-15 7529 case WMI_TAG_STATS_EVENT:
79e7b04b5388c1 Lingbo Kong 2025-01-15 7530 parse->ev = ptr;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7531 break;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7532 case WMI_TAG_ARRAY_BYTE:
79e7b04b5388c1 Lingbo Kong 2025-01-15 7533 ret = ath12k_wmi_tlv_fw_stats_data_parse(ab, parse, ptr, len);
79e7b04b5388c1 Lingbo Kong 2025-01-15 7534 break;
1715fcabad1648 Lingbo Kong 2025-02-07 7535 case WMI_TAG_PER_CHAIN_RSSI_STATS:
1715fcabad1648 Lingbo Kong 2025-02-07 7536 parse->rssi = ptr;
1715fcabad1648 Lingbo Kong 2025-02-07 7537 if (le32_to_cpu(parse->ev->stats_id) & WMI_REQUEST_RSSI_PER_CHAIN_STAT)
1715fcabad1648 Lingbo Kong 2025-02-07 7538 parse->rssi_num = le32_to_cpu(parse->rssi->num_per_chain_rssi);
1715fcabad1648 Lingbo Kong 2025-02-07 7539 break;
1715fcabad1648 Lingbo Kong 2025-02-07 7540 case WMI_TAG_ARRAY_STRUCT:
1715fcabad1648 Lingbo Kong 2025-02-07 7541 if (parse->rssi_num && !parse->chain_rssi_done) {
1715fcabad1648 Lingbo Kong 2025-02-07 7542 ret = ath12k_wmi_tlv_iter(ab, ptr, len,
1715fcabad1648 Lingbo Kong 2025-02-07 7543 ath12k_wmi_tlv_rssi_chain_parse,
1715fcabad1648 Lingbo Kong 2025-02-07 7544 parse);
1715fcabad1648 Lingbo Kong 2025-02-07 7545 if (ret)
1715fcabad1648 Lingbo Kong 2025-02-07 7546 return ret;
1715fcabad1648 Lingbo Kong 2025-02-07 7547
1715fcabad1648 Lingbo Kong 2025-02-07 7548 parse->chain_rssi_done = true;
1715fcabad1648 Lingbo Kong 2025-02-07 7549 }
79e7b04b5388c1 Lingbo Kong 2025-01-15 @7550 default:
79e7b04b5388c1 Lingbo Kong 2025-01-15 7551 break;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7552 }
79e7b04b5388c1 Lingbo Kong 2025-01-15 7553 return ret;
79e7b04b5388c1 Lingbo Kong 2025-01-15 7554 }
79e7b04b5388c1 Lingbo Kong 2025-01-15 7555
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 57e71ccbbb67..967e3cad3bca 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -508,6 +508,7 @@ struct ath12k_link_sta { u32 bw_prev; u32 peer_nss; s8 rssi_beacon; + s8 chain_signal[IEEE80211_MAX_CHAINS]; /* For now the assoc link will be considered primary */ bool is_assoc_link; @@ -530,6 +531,9 @@ struct ath12k_sta { enum ieee80211_sta_state state; }; +#define ATH12K_INVALID_RSSI_FULL -1 +#define ATH12K_INVALID_RSSI_EMPTY -128 + #define ATH12K_MIN_5G_FREQ 4150 #define ATH12K_MIN_6G_FREQ 5925 #define ATH12K_MAX_6G_FREQ 7115 @@ -738,6 +742,7 @@ struct ath12k { u32 mlo_setup_status; u8 ftm_msgref; struct ath12k_fw_stats fw_stats; + unsigned long last_signal_update; }; struct ath12k_hw { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 16e6f2fae943..2c72a83e6aaf 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -10140,6 +10140,27 @@ static int ath12k_mac_get_fw_stats(struct ath12k *ar, u32 pdev_id, return ret; } +static void ath12k_mac_put_chain_rssi(struct station_info *sinfo, + struct ath12k_link_sta *arsta) +{ + s8 rssi; + int i; + + for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { + sinfo->chains &= ~BIT(i); + rssi = arsta->chain_signal[i]; + + if (rssi != ATH12K_DEFAULT_NOISE_FLOOR && + rssi != ATH12K_INVALID_RSSI_FULL && + rssi != ATH12K_INVALID_RSSI_EMPTY && + rssi != 0) { + sinfo->chain_signal[i] = rssi; + sinfo->chains |= BIT(i); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); + } + } +} + static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -10187,12 +10208,22 @@ static void ath12k_mac_op_sta_statistics(struct ieee80211_hw *hw, /* TODO: Use real NF instead of default one. */ signal = arsta->rssi_comb; - if (!signal && - ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA && - !(ath12k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, - WMI_REQUEST_VDEV_STAT))) + /* Limit the requests to Firmware for fetching the signal strength */ + if (time_after(jiffies, msecs_to_jiffies(ATH12K_PDEV_SIGNAL_UPDATE_TIME_MSECS) + + ar->last_signal_update)) { + ath12k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, WMI_REQUEST_VDEV_STAT); + ath12k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_RSSI_PER_CHAIN_STAT); + ar->last_signal_update = jiffies; + } + + if (!signal && ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA) signal = arsta->rssi_beacon; + if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && + ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA) + ath12k_mac_put_chain_rssi(sinfo, arsta); + if (signal) { sinfo->signal = db2dbm ? signal : signal + ATH12K_DEFAULT_NOISE_FLOOR; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 5a6e3c3316be..df7e35886668 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -51,6 +51,8 @@ struct ath12k_generic_iter { #define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS #define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1) +#define ATH12K_PDEV_SIGNAL_UPDATE_TIME_MSECS 2000 + enum ath12k_supported_bw { ATH12K_BW_20 = 0, ATH12K_BW_40 = 1, diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index f934d49acee6..b6df2bb3b88e 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -29,6 +29,9 @@ struct ath12k_wmi_svc_ready_parse { struct wmi_tlv_fw_stats_parse { const struct wmi_stats_event *ev; + const struct wmi_per_chain_rssi_stat_params *rssi; + int rssi_num; + bool chain_rssi_done; }; struct ath12k_wmi_dma_ring_caps_parse { @@ -177,6 +180,8 @@ static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = { .min_len = sizeof(struct ath12k_wmi_p2p_noa_info) }, [WMI_TAG_P2P_NOA_EVENT] = { .min_len = sizeof(struct wmi_p2p_noa_event) }, + [WMI_TAG_PER_CHAIN_RSSI_STATS] = { + .min_len = sizeof(struct wmi_per_chain_rssi_stat_params) }, }; __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len) @@ -7452,6 +7457,67 @@ static int ath12k_wmi_tlv_fw_stats_data_parse(struct ath12k_base *ab, return ret; } +static int ath12k_wmi_tlv_rssi_chain_parse(struct ath12k_base *ab, + u16 tag, u16 len, + const void *ptr, void *data) +{ + const struct wmi_rssi_stat_params *stats_rssi = ptr; + struct wmi_tlv_fw_stats_parse *parse = data; + const struct wmi_stats_event *ev = parse->ev; + struct ath12k_link_vif *arvif; + struct ath12k_link_sta *arsta; + struct ieee80211_sta *sta; + struct ath12k_sta *ahsta; + struct ath12k *ar; + int pdev_id; + int vdev_id; + int j; + + if (tag != WMI_TAG_RSSI_STATS) + return -EPROTO; + + pdev_id = le32_to_cpu(ev->pdev_id); + vdev_id = le32_to_cpu(stats_rssi->vdev_id); + guard(rcu)(); + ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id); + if (!ar) { + ath12k_warn(ab, "invalid pdev id %d in rssi chain parse\n", + pdev_id); + return -EPROTO; + } + + arvif = ath12k_mac_get_arvif(ar, vdev_id); + if (!arvif) { + ath12k_warn(ab, "not found vif for vdev id %d\n", vdev_id); + return -EPROTO; + } + + ath12k_dbg(ab, ATH12K_DBG_WMI, + "stats bssid %pM vif %p\n", + arvif->bssid, arvif->ahvif->vif); + + sta = ieee80211_find_sta_by_ifaddr(ath12k_ar_to_hw(ar), + arvif->bssid, + NULL); + if (!sta) { + ath12k_dbg(ab, ATH12K_DBG_WMI, + "not found station of bssid %pM for rssi chain\n", + arvif->bssid); + return -EPROTO; + } + + ahsta = ath12k_sta_to_ahsta(sta); + arsta = &ahsta->deflink; + + BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) > + ARRAY_SIZE(stats_rssi->rssi_avg_beacon)); + + for (j = 0; j < ARRAY_SIZE(arsta->chain_signal); j++) + arsta->chain_signal[j] = le32_to_cpu(stats_rssi->rssi_avg_beacon[j]); + + return 0; +} + static int ath12k_wmi_tlv_fw_stats_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) @@ -7466,6 +7532,21 @@ static int ath12k_wmi_tlv_fw_stats_parse(struct ath12k_base *ab, case WMI_TAG_ARRAY_BYTE: ret = ath12k_wmi_tlv_fw_stats_data_parse(ab, parse, ptr, len); break; + case WMI_TAG_PER_CHAIN_RSSI_STATS: + parse->rssi = ptr; + if (le32_to_cpu(parse->ev->stats_id) & WMI_REQUEST_RSSI_PER_CHAIN_STAT) + parse->rssi_num = le32_to_cpu(parse->rssi->num_per_chain_rssi); + break; + case WMI_TAG_ARRAY_STRUCT: + if (parse->rssi_num && !parse->chain_rssi_done) { + ret = ath12k_wmi_tlv_iter(ab, ptr, len, + ath12k_wmi_tlv_rssi_chain_parse, + parse); + if (ret) + return ret; + + parse->chain_rssi_done = true; + } default: break; } diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 1ba33e30ddd2..be03616e7c88 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -5680,9 +5680,10 @@ struct wmi_stats_event { } __packed; enum wmi_stats_id { - WMI_REQUEST_PDEV_STAT = BIT(2), - WMI_REQUEST_VDEV_STAT = BIT(3), - WMI_REQUEST_BCN_STAT = BIT(11), + WMI_REQUEST_PDEV_STAT = BIT(2), + WMI_REQUEST_VDEV_STAT = BIT(3), + WMI_REQUEST_RSSI_PER_CHAIN_STAT = BIT(8), + WMI_REQUEST_BCN_STAT = BIT(11), }; struct wmi_request_stats_cmd { @@ -5693,6 +5694,17 @@ struct wmi_request_stats_cmd { __le32 pdev_id; } __packed; +struct wmi_rssi_stat_params { + __le32 vdev_id; + __le32 rssi_avg_beacon[WMI_MAX_CHAINS]; + __le32 rssi_avg_data[WMI_MAX_CHAINS]; + struct ath12k_wmi_mac_addr_params peer_macaddr; +} __packed; + +struct wmi_per_chain_rssi_stat_params { + __le32 num_per_chain_rssi; +} __packed; + #define WLAN_MAX_AC 4 #define MAX_TX_RATE_VALUES 10
Currently, command “iw wlan0 station dump” does not show per-chain signal strength. This is because ath12k does not handle the num_per_chain_rssi and rssi_avg_beacon reported by firmware to ath12k. To address this, update ath12k to send WMI_REQUEST_STATS_CMDID with the flag WMI_REQUEST_RSSI_PER_CHAIN_STAT to the firmware. Then, add logic to handle num_per_chain_rssi and rssi_avg_beacon in the ath12k_wmi_tlv_fw_stats_parse(), and assign the resulting per-chain signal strength to the chain_signal of struct station_info. After that, "iw dev xxx station dump" shows the correct per-chain signal strength. Such as: Station AA:BB:CC:DD:EE:FF (on wlan0) inactive time: 212 ms rx bytes: 10398 rx packets: 64 tx bytes: 4362 tx packets: 33 tx retries: 49 tx failed: 0 beacon loss: 0 beacon rx: 14 rx drop misc: 16 signal: -45 [-51, -46] dBm beacon signal avg: -44 dBm Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219751 Signed-off-by: Lingbo Kong <quic_lingbok@quicinc.com> --- drivers/net/wireless/ath/ath12k/core.h | 5 ++ drivers/net/wireless/ath/ath12k/mac.c | 39 +++++++++++-- drivers/net/wireless/ath/ath12k/mac.h | 2 + drivers/net/wireless/ath/ath12k/wmi.c | 81 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 18 +++++- 5 files changed, 138 insertions(+), 7 deletions(-) base-commit: d132a72d768bae74d10e6539fcf6522dfdbd1115