diff options
| author | Johannes Berg <johannes.berg@intel.com> | 2026-02-02 17:55:04 +0100 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2026-02-02 17:55:23 +0100 |
| commit | 19dd0cc36a52d0d121d7854cbb9b00d6d4dcad0a (patch) | |
| tree | bfe56948d666520168e3ad78cd4640ea32cf6c7e /drivers/net/wireless | |
| parent | 0d95280a2d54ebd3d38adc4ff67808009798978c (diff) | |
| parent | 2c1ba9c2adf0fda96eaaebd8799268a7506a8fc9 (diff) | |
| download | lwn-19dd0cc36a52d0d121d7854cbb9b00d6d4dcad0a.tar.gz lwn-19dd0cc36a52d0d121d7854cbb9b00d6d4dcad0a.zip | |
Merge tag 'ath-next-20260202' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath
Jeff Johnson says:
==================
ath.git patches for v6.20/v7.0 (#3)
A set of small features and cleanups for the next merge window.
==================
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless')
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/sdio.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.c | 53 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/core.c | 27 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/core.h | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c | 197 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h | 81 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 174 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.c | 142 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.h | 47 |
12 files changed, 729 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index c06d50db40b8..00d0556dafef 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -2487,7 +2487,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) if (fast_dump) ath10k_bmi_start(ar); + mutex_lock(&ar->dump_mutex); + + spin_lock_bh(&ar->data_lock); ar->stats.fw_crash_counter++; + spin_unlock_bh(&ar->data_lock); ath10k_sdio_disable_intrs(ar); @@ -2505,6 +2509,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar) ath10k_sdio_enable_intrs(ar); + mutex_unlock(&ar->dump_mutex); + ath10k_core_start_recovery(ar); } diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index b3f6424c17d3..f72f236fb9eb 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: ISC /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <linux/bits.h> @@ -11,6 +12,7 @@ #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/property.h> +#include <linux/pwrseq/consumer.h> #include <linux/regulator/consumer.h> #include <linux/remoteproc/qcom_rproc.h> #include <linux/of_reserved_mem.h> @@ -1023,10 +1025,14 @@ static int ath10k_hw_power_on(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n"); - ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs); + ret = pwrseq_power_on(ar_snoc->pwrseq); if (ret) return ret; + ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs); + if (ret) + goto pwrseq_off; + ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks); if (ret) goto vreg_off; @@ -1035,18 +1041,28 @@ static int ath10k_hw_power_on(struct ath10k *ar) vreg_off: regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs); +pwrseq_off: + pwrseq_power_off(ar_snoc->pwrseq); + return ret; } static int ath10k_hw_power_off(struct ath10k *ar) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int ret_seq = 0; + int ret_vreg; ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n"); clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks); - return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs); + ret_vreg = regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs); + + if (ar_snoc->pwrseq) + ret_seq = pwrseq_power_off(ar_snoc->pwrseq); + + return ret_vreg ? : ret_seq; } static void ath10k_snoc_wlan_disable(struct ath10k *ar) @@ -1762,7 +1778,38 @@ static int ath10k_snoc_probe(struct platform_device *pdev) goto err_release_resource; } - ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators); + /* + * devm_pwrseq_get() can return -EPROBE_DEFER in two cases: + * - it is not supposed to be used + * - it is supposed to be used, but the driver hasn't probed yet. + * + * There is no simple way to distinguish between these two cases, but: + * - if it is not supposed to be used, then regulator_bulk_get() will + * return all regulators as expected, continuing the probe + * - if it is supposed to be used, but wasn't probed yet, we will get + * -EPROBE_DEFER from regulator_bulk_get() too. + * + * For backwards compatibility with DTs specifying regulators directly + * rather than using the PMU device, ignore the defer error from + * pwrseq. + */ + ar_snoc->pwrseq = devm_pwrseq_get(&pdev->dev, "wlan"); + if (IS_ERR(ar_snoc->pwrseq)) { + ret = PTR_ERR(ar_snoc->pwrseq); + ar_snoc->pwrseq = NULL; + if (ret != -EPROBE_DEFER) + goto err_free_irq; + + ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators); + } else { + /* + * The first regulator (vdd-0.8-cx-mx) is used to power on part + * of the SoC rather than the PMU on WCN399x, the rest are + * handled via pwrseq. + */ + ar_snoc->num_vregs = 1; + } + ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs, sizeof(*ar_snoc->vregs), GFP_KERNEL); if (!ar_snoc->vregs) { diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index d4bce1707696..1ecae34687c2 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #ifndef _SNOC_H_ @@ -53,6 +54,7 @@ enum ath10k_snoc_flags { }; struct clk_bulk_data; +struct pwrseq_desc; struct regulator_bulk_data; struct ath10k_snoc { @@ -73,6 +75,7 @@ struct ath10k_snoc { struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX]; struct ath10k_ce ce; struct timer_list rx_post_retry; + struct pwrseq_desc *pwrseq; struct regulator_bulk_data *vregs; size_t num_vregs; struct clk_bulk_data *clks; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index b4aad6604d6d..ce22141e5efd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5289,8 +5289,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb) struct ath10k_sta *arsta; u8 peer_addr[ETH_ALEN]; - lockdep_assert_held(&ar->data_lock); - ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data; ether_addr_copy(peer_addr, ev->peer_macaddr.addr); @@ -5305,7 +5303,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb) } arsta = (struct ath10k_sta *)sta->drv_priv; + spin_lock_bh(&ar->data_lock); arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state); + spin_unlock_bh(&ar->data_lock); exit: rcu_read_unlock(); diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index de84906d1b27..3f6f4db5b7ee 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1044,6 +1044,33 @@ static const struct dmi_system_id ath11k_pm_quirk_table[] = { {} }; +static const struct __ath11k_core_usecase_firmware_table { + u32 hw_rev; + const char *compatible; + const char *firmware_name; +} ath11k_core_usecase_firmware_table[] = { + { ATH11K_HW_WCN6855_HW21, "qcom,lemans-evk", "nfa765"}, + { ATH11K_HW_WCN6855_HW21, "qcom,monaco-evk", "nfa765"}, + { ATH11K_HW_WCN6855_HW21, "qcom,hamoa-iot-evk", "nfa765"}, + { /* Sentinel */ } +}; + +const char *ath11k_core_get_usecase_firmware(struct ath11k_base *ab) +{ + const struct __ath11k_core_usecase_firmware_table *entry = NULL; + + entry = ath11k_core_usecase_firmware_table; + while (entry->compatible) { + if (ab->hw_rev == entry->hw_rev && + of_machine_is_compatible(entry->compatible)) + return entry->firmware_name; + entry++; + } + + return NULL; +} +EXPORT_SYMBOL(ath11k_core_get_usecase_firmware); + void ath11k_fw_stats_pdevs_free(struct list_head *head) { struct ath11k_fw_stats_pdev *i, *tmp; diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 3f41e6569a78..a0d725923ef2 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -1292,6 +1292,7 @@ bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab); const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, const char *filename); +const char *ath11k_core_get_usecase_firmware(struct ath11k_base *ab); static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state) { @@ -1346,6 +1347,9 @@ static inline void ath11k_core_create_firmware_path(struct ath11k_base *ab, of_property_read_string(ab->dev->of_node, "firmware-name", &fw_name); + if (!fw_name) + fw_name = ath11k_core_get_usecase_firmware(ab); + if (fw_name && strncmp(filename, "board", 5)) snprintf(buf, buf_len, "%s/%s/%s/%s", ATH11K_FW_DIR, ab->hw_params.fw.dir, fw_name, filename); diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c index 48b010a1b756..7f6ca07fb335 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <linux/vmalloc.h> @@ -29,8 +29,10 @@ print_array_to_buf_index(u8 *buf, u32 offset, const char *header, u32 stats_inde " %u:%u,", stats_index++, le32_to_cpu(array[i])); } /* To overwrite the last trailing comma */ - index--; - *(buf + offset + index) = '\0'; + if (array_len > 0) { + index--; + *(buf + offset + index) = '\0'; + } if (footer) { index += scnprintf(buf + offset + index, @@ -5537,6 +5539,189 @@ ath12k_htt_print_pdev_rtt_tbr_cmd_res_stats_tlv(const void *tag_buf, u16 tag_len stats_req->buf_len = len; } +static void +ath12k_htt_print_rx_pdev_fw_stats_tlv(const void *tag_buf, u16 tag_len, + struct debug_htt_stats_req *stats_req) +{ + const struct htt_rx_pdev_fw_stats_tlv *htt_stats_buf = tag_buf; + u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; + u32 len = stats_req->buf_len; + u8 *buf = stats_req->buf; + + if (tag_len < sizeof(*htt_stats_buf)) + return; + + len += scnprintf(buf + len, buf_len - len, "HTT_RX_PDEV_FW_STATS_TLV:\n"); + len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", + le32_to_cpu(htt_stats_buf->mac_id__word) & 0xFF); + len += scnprintf(buf + len, buf_len - len, "ppdu_recvd = %u\n", + le32_to_cpu(htt_stats_buf->ppdu_recvd)); + len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_ok = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_cnt_fcs_ok)); + len += scnprintf(buf + len, buf_len - len, "mpdu_cnt_fcs_err = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_cnt_fcs_err)); + len += scnprintf(buf + len, buf_len - len, "tcp_msdu_cnt = %u\n", + le32_to_cpu(htt_stats_buf->tcp_msdu_cnt)); + len += scnprintf(buf + len, buf_len - len, "tcp_ack_msdu_cnt = %u\n", + le32_to_cpu(htt_stats_buf->tcp_ack_msdu_cnt)); + len += scnprintf(buf + len, buf_len - len, "udp_msdu_cnt = %u\n", + le32_to_cpu(htt_stats_buf->udp_msdu_cnt)); + len += scnprintf(buf + len, buf_len - len, "other_msdu_cnt = %u\n", + le32_to_cpu(htt_stats_buf->other_msdu_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_ring_mpdu_ind = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_mpdu_ind)); + len += print_array_to_buf(buf, len, "fw_ring_mgmt_subtype", + htt_stats_buf->fw_ring_mgmt_subtype, + ATH12K_HTT_STATS_SUBTYPE_MAX, "\n"); + len += print_array_to_buf(buf, len, "fw_ring_ctrl_subtype", + htt_stats_buf->fw_ring_ctrl_subtype, + ATH12K_HTT_STATS_SUBTYPE_MAX, "\n"); + len += scnprintf(buf + len, buf_len - len, "fw_ring_mcast_data_msdu = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_mcast_data_msdu)); + len += scnprintf(buf + len, buf_len - len, "fw_ring_bcast_data_msdu = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_bcast_data_msdu)); + len += scnprintf(buf + len, buf_len - len, "fw_ring_ucast_data_msdu = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_ucast_data_msdu)); + len += scnprintf(buf + len, buf_len - len, "fw_ring_null_data_msdu = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_null_data_msdu)); + len += scnprintf(buf + len, buf_len - len, "fw_ring_mpdu_drop = %u\n", + le32_to_cpu(htt_stats_buf->fw_ring_mpdu_drop)); + len += scnprintf(buf + len, buf_len - len, "ofld_local_data_ind_cnt = %u\n", + le32_to_cpu(htt_stats_buf->ofld_local_data_ind_cnt)); + len += scnprintf(buf + len, buf_len - len, + "ofld_local_data_buf_recycle_cnt = %u\n", + le32_to_cpu(htt_stats_buf->ofld_local_data_buf_recycle_cnt)); + len += scnprintf(buf + len, buf_len - len, "drx_local_data_ind_cnt = %u\n", + le32_to_cpu(htt_stats_buf->drx_local_data_ind_cnt)); + len += scnprintf(buf + len, buf_len - len, + "drx_local_data_buf_recycle_cnt = %u\n", + le32_to_cpu(htt_stats_buf->drx_local_data_buf_recycle_cnt)); + len += scnprintf(buf + len, buf_len - len, "local_nondata_ind_cnt = %u\n", + le32_to_cpu(htt_stats_buf->local_nondata_ind_cnt)); + len += scnprintf(buf + len, buf_len - len, "local_nondata_buf_recycle_cnt = %u\n", + le32_to_cpu(htt_stats_buf->local_nondata_buf_recycle_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_status_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_status_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_status_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_status_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_pkt_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_pkt_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_pkt_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_pkt_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_link_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_link_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "fw_link_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->fw_link_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "host_pkt_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->host_pkt_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "host_pkt_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->host_pkt_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_pkt_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_pkt_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_pkt_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_pkt_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, + "mon_status_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_status_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_status_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_status_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_desc_buf_ring_refill_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_desc_buf_ring_refill_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_desc_buf_ring_empty_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_desc_buf_ring_empty_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_dest_ring_update_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_dest_ring_update_cnt)); + len += scnprintf(buf + len, buf_len - len, "mon_dest_ring_full_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mon_dest_ring_full_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_suspend_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_suspend_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_suspend_fail_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_suspend_fail_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_resume_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_resume_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_resume_fail_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_resume_fail_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_ring_switch_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_ring_switch_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_ring_restore_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_ring_restore_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_flush_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_flush_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_recovery_reset_cnt = %u\n", + le32_to_cpu(htt_stats_buf->rx_recovery_reset_cnt)); + len += scnprintf(buf + len, buf_len - len, "rx_lwm_prom_filter_dis = %u\n", + le32_to_cpu(htt_stats_buf->rx_lwm_prom_filter_dis)); + len += scnprintf(buf + len, buf_len - len, "rx_hwm_prom_filter_en = %u\n", + le32_to_cpu(htt_stats_buf->rx_hwm_prom_filter_en)); + len += scnprintf(buf + len, buf_len - len, "bytes_received_low_32 = %u\n", + le32_to_cpu(htt_stats_buf->bytes_received_low_32)); + len += scnprintf(buf + len, buf_len - len, "bytes_received_high_32 = %u\n", + le32_to_cpu(htt_stats_buf->bytes_received_high_32)); + + stats_req->buf_len = len; +} + +static void +ath12k_htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, u16 tag_len, + struct debug_htt_stats_req *stats_req) +{ + const struct htt_tx_hwq_stats_cmn_tlv *htt_stats_buf = tag_buf; + u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE; + u32 len = stats_req->buf_len; + u8 *buf = stats_req->buf; + + if (tag_len < sizeof(*htt_stats_buf)) + return; + + len += scnprintf(buf + len, buf_len - len, "HTT_TX_HWQ_STATS_CMN_TLV:\n"); + len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n", + le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF); + len += scnprintf(buf + len, buf_len - len, "hwq_id = %u\n", + (le32_to_cpu(htt_stats_buf->mac_id__hwq_id__word) & 0xFF00) >> 8); + len += scnprintf(buf + len, buf_len - len, "xretry = %u\n", + le32_to_cpu(htt_stats_buf->xretry)); + len += scnprintf(buf + len, buf_len - len, "underrun_cnt = %u\n", + le32_to_cpu(htt_stats_buf->underrun_cnt)); + len += scnprintf(buf + len, buf_len - len, "flush_cnt = %u\n", + le32_to_cpu(htt_stats_buf->flush_cnt)); + len += scnprintf(buf + len, buf_len - len, "filt_cnt = %u\n", + le32_to_cpu(htt_stats_buf->filt_cnt)); + len += scnprintf(buf + len, buf_len - len, "null_mpdu_bmap = %u\n", + le32_to_cpu(htt_stats_buf->null_mpdu_bmap)); + len += scnprintf(buf + len, buf_len - len, "user_ack_failure = %u\n", + le32_to_cpu(htt_stats_buf->user_ack_failure)); + len += scnprintf(buf + len, buf_len - len, "ack_tlv_proc = %u\n", + le32_to_cpu(htt_stats_buf->ack_tlv_proc)); + len += scnprintf(buf + len, buf_len - len, "sched_id_proc = %u\n", + le32_to_cpu(htt_stats_buf->sched_id_proc)); + len += scnprintf(buf + len, buf_len - len, "null_mpdu_tx_count = %u\n", + le32_to_cpu(htt_stats_buf->null_mpdu_tx_count)); + len += scnprintf(buf + len, buf_len - len, "mpdu_bmap_not_recvd = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_bmap_not_recvd)); + len += scnprintf(buf + len, buf_len - len, "num_bar = %u\n", + le32_to_cpu(htt_stats_buf->num_bar)); + len += scnprintf(buf + len, buf_len - len, "rts = %u\n", + le32_to_cpu(htt_stats_buf->rts)); + len += scnprintf(buf + len, buf_len - len, "cts2self = %u\n", + le32_to_cpu(htt_stats_buf->cts2self)); + len += scnprintf(buf + len, buf_len - len, "qos_null = %u\n", + le32_to_cpu(htt_stats_buf->qos_null)); + len += scnprintf(buf + len, buf_len - len, "mpdu_tried_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_tried_cnt)); + len += scnprintf(buf + len, buf_len - len, "mpdu_queued_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_queued_cnt)); + len += scnprintf(buf + len, buf_len - len, "mpdu_ack_fail_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_ack_fail_cnt)); + len += scnprintf(buf + len, buf_len - len, "mpdu_filt_cnt = %u\n", + le32_to_cpu(htt_stats_buf->mpdu_filt_cnt)); + len += scnprintf(buf + len, buf_len - len, "false_mpdu_ack_count = %u\n", + le32_to_cpu(htt_stats_buf->false_mpdu_ack_count)); + len += scnprintf(buf + len, buf_len - len, "txq_timeout = %u\n", + le32_to_cpu(htt_stats_buf->txq_timeout)); + + stats_req->buf_len = len; +} + static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *tag_buf, void *user_data) @@ -5690,6 +5875,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, case HTT_STATS_SFM_CLIENT_USER_TAG: ath12k_htt_print_sfm_client_user_tlv(tag_buf, len, stats_req); break; + case HTT_STATS_RX_PDEV_FW_STATS_TAG: + ath12k_htt_print_rx_pdev_fw_stats_tlv(tag_buf, len, stats_req); + break; case HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG: ath12k_htt_print_tx_pdev_mu_mimo_sch_stats_tlv(tag_buf, len, stats_req); break; @@ -5833,6 +6021,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab, case HTT_STATS_PDEV_RTT_TBR_CMD_RESULT_STATS_TAG: ath12k_htt_print_pdev_rtt_tbr_cmd_res_stats_tlv(tag_buf, len, stats_req); break; + case HTT_STATS_TX_HWQ_CMN_TAG: + ath12k_htt_print_tx_hwq_stats_cmn_tlv(tag_buf, len, stats_req); + break; default: break; } diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h index 8008658371aa..bfabe6500d44 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h +++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h @@ -127,6 +127,8 @@ struct ath12k_htt_extd_stats_msg { enum ath12k_dbg_htt_ext_stats_type { ATH12K_DBG_HTT_EXT_STATS_RESET = 0, ATH12K_DBG_HTT_EXT_STATS_PDEV_TX = 1, + ATH12K_DBG_HTT_EXT_STATS_PDEV_RX = 2, + ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_HWQ = 3, ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_SCHED = 4, ATH12K_DBG_HTT_EXT_STATS_PDEV_ERROR = 5, ATH12K_DBG_HTT_EXT_STATS_PDEV_TQM = 6, @@ -173,6 +175,7 @@ enum ath12k_dbg_htt_tlv_tag { HTT_STATS_TX_PDEV_SIFS_TAG = 2, HTT_STATS_TX_PDEV_FLUSH_TAG = 3, HTT_STATS_STRING_TAG = 5, + HTT_STATS_TX_HWQ_CMN_TAG = 6, HTT_STATS_TX_TQM_GEN_MPDU_TAG = 11, HTT_STATS_TX_TQM_LIST_MPDU_TAG = 12, HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG = 13, @@ -188,6 +191,7 @@ enum ath12k_dbg_htt_tlv_tag { HTT_STATS_TX_PDEV_MU_MIMO_STATS_TAG = 25, HTT_STATS_SFM_CMN_TAG = 26, HTT_STATS_SRING_STATS_TAG = 27, + HTT_STATS_RX_PDEV_FW_STATS_TAG = 28, HTT_STATS_TX_PDEV_RATE_STATS_TAG = 34, HTT_STATS_RX_PDEV_RATE_STATS_TAG = 35, HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG = 36, @@ -2075,4 +2079,81 @@ struct ath12k_htt_stats_pdev_rtt_tbr_cmd_result_stats_tlv { __le32 mu_res[ATH12K_HTT_FTYPE_MAX][ATH12K_HTT_MAX_SCH_CMD_RESULT]; } __packed; +struct htt_rx_pdev_fw_stats_tlv { + __le32 mac_id__word; + __le32 ppdu_recvd; + __le32 mpdu_cnt_fcs_ok; + __le32 mpdu_cnt_fcs_err; + __le32 tcp_msdu_cnt; + __le32 tcp_ack_msdu_cnt; + __le32 udp_msdu_cnt; + __le32 other_msdu_cnt; + __le32 fw_ring_mpdu_ind; + __le32 fw_ring_mgmt_subtype[ATH12K_HTT_STATS_SUBTYPE_MAX]; + __le32 fw_ring_ctrl_subtype[ATH12K_HTT_STATS_SUBTYPE_MAX]; + __le32 fw_ring_mcast_data_msdu; + __le32 fw_ring_bcast_data_msdu; + __le32 fw_ring_ucast_data_msdu; + __le32 fw_ring_null_data_msdu; + __le32 fw_ring_mpdu_drop; + __le32 ofld_local_data_ind_cnt; + __le32 ofld_local_data_buf_recycle_cnt; + __le32 drx_local_data_ind_cnt; + __le32 drx_local_data_buf_recycle_cnt; + __le32 local_nondata_ind_cnt; + __le32 local_nondata_buf_recycle_cnt; + __le32 fw_status_buf_ring_refill_cnt; + __le32 fw_status_buf_ring_empty_cnt; + __le32 fw_pkt_buf_ring_refill_cnt; + __le32 fw_pkt_buf_ring_empty_cnt; + __le32 fw_link_buf_ring_refill_cnt; + __le32 fw_link_buf_ring_empty_cnt; + __le32 host_pkt_buf_ring_refill_cnt; + __le32 host_pkt_buf_ring_empty_cnt; + __le32 mon_pkt_buf_ring_refill_cnt; + __le32 mon_pkt_buf_ring_empty_cnt; + __le32 mon_status_buf_ring_refill_cnt; + __le32 mon_status_buf_ring_empty_cnt; + __le32 mon_desc_buf_ring_refill_cnt; + __le32 mon_desc_buf_ring_empty_cnt; + __le32 mon_dest_ring_update_cnt; + __le32 mon_dest_ring_full_cnt; + __le32 rx_suspend_cnt; + __le32 rx_suspend_fail_cnt; + __le32 rx_resume_cnt; + __le32 rx_resume_fail_cnt; + __le32 rx_ring_switch_cnt; + __le32 rx_ring_restore_cnt; + __le32 rx_flush_cnt; + __le32 rx_recovery_reset_cnt; + __le32 rx_lwm_prom_filter_dis; + __le32 rx_hwm_prom_filter_en; + __le32 bytes_received_low_32; + __le32 bytes_received_high_32; +} __packed; + +struct htt_tx_hwq_stats_cmn_tlv { + __le32 mac_id__hwq_id__word; + __le32 xretry; + __le32 underrun_cnt; + __le32 flush_cnt; + __le32 filt_cnt; + __le32 null_mpdu_bmap; + __le32 user_ack_failure; + __le32 ack_tlv_proc; + __le32 sched_id_proc; + __le32 null_mpdu_tx_count; + __le32 mpdu_bmap_not_recvd; + __le32 num_bar; + __le32 rts; + __le32 cts2self; + __le32 qos_null; + __le32 mpdu_tried_cnt; + __le32 mpdu_queued_cnt; + __le32 mpdu_ack_fail_cnt; + __le32 mpdu_filt_cnt; + __le32 false_mpdu_ack_count; + __le32 txq_timeout; +} __packed; + #endif diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index cdb72439dcf4..68431a0e128e 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -4281,8 +4281,10 @@ ath12k_mac_op_change_vif_links(struct ieee80211_hw *hw, if (WARN_ON(!arvif)) return -EINVAL; - if (!arvif->is_created) + if (!arvif->is_created) { + ath12k_mac_unassign_link_vif(arvif); continue; + } if (WARN_ON(!arvif->ar)) return -EINVAL; @@ -4505,6 +4507,166 @@ static void ath12k_wmi_vdev_params_up(struct ath12k *ar, arvif->vdev_id, ret); } +static int ath12k_mac_config_obss_pd(struct ath12k_link_vif *arvif, + const struct ieee80211_he_obss_pd *he_obss_pd) +{ + struct ath12k_wmi_obss_pd_arg obss_pd_arg = {}; + u32 srg_bitmap[2], non_srg_bitmap[2]; + struct ath12k *ar = arvif->ar; + u32 param_id, pdev_id; + u32 param_val; + int ret; + + if (ar->ab->hw_params->single_pdev_only) + pdev_id = ath12k_mac_get_target_pdev_id_from_vif(arvif); + else + pdev_id = ar->pdev->pdev_id; + + /* Set and enable SRG/non-SRG OBSS PD threshold */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD; + if (ar->monitor_started || !he_obss_pd->enable) { + ret = ath12k_wmi_pdev_set_param(ar, param_id, 0, pdev_id); + if (ret) + ath12k_warn(ar->ab, + "failed to set OBSS PD threshold for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* + * This service flag indicates firmware support for SRG/SRP-based + * spatial reuse. It also specifies whether OBSS PD threshold values + * should be interpreted as dB (offset) or dBm (absolute) units. + */ + obss_pd_arg.srp_support = test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT, + ar->ab->wmi_ab.svc_map); + + if (!(he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_NON_SRG_OBSS_PD_SR_DISALLOWED)) { + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) + obss_pd_arg.non_srg_th = ATH12K_OBSS_PD_MAX_THRESHOLD + + he_obss_pd->non_srg_max_offset; + else + obss_pd_arg.non_srg_th = ATH12K_OBSS_PD_NON_SRG_MAX_THRESHOLD; + + if (!obss_pd_arg.srp_support) + obss_pd_arg.non_srg_th -= ATH12K_DEFAULT_NOISE_FLOOR; + + obss_pd_arg.non_srg_enabled = true; + } + + if (he_obss_pd->sr_ctrl & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) { + obss_pd_arg.srg_th = ATH12K_OBSS_PD_MAX_THRESHOLD + + he_obss_pd->max_offset; + obss_pd_arg.srg_enabled = true; + } + + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, + "pdev %u OBSS PD sr_ctrl 0x%x srg_th %d dBm non_srg_th %d dBm\n", + pdev_id, he_obss_pd->sr_ctrl, + obss_pd_arg.srg_th, obss_pd_arg.non_srg_th); + + param_val = ath12k_wmi_build_obss_pd(&obss_pd_arg); + ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath12k_warn(ar->ab, + "failed to set OBSS PD threshold for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* Enable OBSS PD for all access category */ + param_id = WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC; + param_val = 0xf; + ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath12k_warn(ar->ab, + "failed to set OBSS PD per ac for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* Set SR prohibit */ + param_id = WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT; + param_val = !!(he_obss_pd->sr_ctrl & + IEEE80211_HE_SPR_HESIGA_SR_VAL15_ALLOWED); + ret = ath12k_wmi_pdev_set_param(ar, param_id, param_val, pdev_id); + if (ret) { + ath12k_warn(ar->ab, "failed to set SR prohibit for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + if (!obss_pd_arg.srp_support) + return 0; + + memcpy(srg_bitmap, he_obss_pd->bss_color_bitmap, sizeof(srg_bitmap)); + /* Set SRG BSS color bitmap */ + ret = ath12k_wmi_pdev_set_srg_bss_color_bitmap(ar, pdev_id, srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to set SRG bss color bitmap for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* Enable BSS colors for SRG */ + ret = ath12k_wmi_pdev_srg_obss_color_enable_bitmap(ar, pdev_id, srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to enable SRG bss color bitmap pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + memcpy(srg_bitmap, he_obss_pd->partial_bssid_bitmap, sizeof(srg_bitmap)); + /* Set SRG partial bssid bitmap */ + ret = ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(ar, pdev_id, srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to set SRG partial bssid bitmap for pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* Enable partial bssid mask for SRG */ + ret = ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(ar, pdev_id, srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to enable SRG bssid bitmap pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* + * No explicit non-SRG bitmap from mac80211; enable all colors/bssids + * as non-SRG candidates. Actual SRG members are filtered by SRG bitmaps. + */ + memset(non_srg_bitmap, 0xff, sizeof(non_srg_bitmap)); + + /* Enable BSS colors for non-SRG */ + ret = ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(ar, pdev_id, + non_srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to enable non SRG color bitmap pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + /* Enable partial bssid mask for non-SRG */ + ret = ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(ar, pdev_id, + non_srg_bitmap); + if (ret) { + ath12k_warn(ar->ab, + "failed to enable non SRG bssid bitmap pdev %u: %d\n", + pdev_id, ret); + return ret; + } + + return 0; +} + static void ath12k_mac_bss_info_changed(struct ath12k *ar, struct ath12k_link_vif *arvif, struct ieee80211_bss_conf *info, @@ -4796,9 +4958,13 @@ skip_vdev_up: ath12k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id); } - if (changed & BSS_CHANGED_HE_OBSS_PD) - ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id, - &info->he_obss_pd); + if (changed & BSS_CHANGED_HE_OBSS_PD) { + if (vif->type == NL80211_IFTYPE_AP) + ath12k_mac_config_obss_pd(arvif, &info->he_obss_pd); + else + ath12k_wmi_send_obss_spr_cmd(ar, arvif->vdev_id, + &info->he_obss_pd); + } if (changed & BSS_CHANGED_HE_BSS_COLOR) { if (vif->type == NL80211_IFTYPE_AP) { diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 422bd3b095cd..7b50c5976384 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -138,6 +138,9 @@ struct ath12k_reg_tpc_power_info { struct ath12k_chan_power_info chan_power_info[ATH12K_NUM_PWR_LEVELS]; }; +#define ATH12K_OBSS_PD_MAX_THRESHOLD -82 +#define ATH12K_OBSS_PD_NON_SRG_MAX_THRESHOLD -62 + extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default; #define ATH12K_SCAN_11D_INTERVAL 600000 diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index cce3d699112d..7617fc3a2479 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -126,6 +126,14 @@ struct wmi_tlv_mgmt_rx_parse { bool frame_buf_done; }; +struct wmi_pdev_set_obss_bitmap_arg { + u32 tlv_tag; + u32 pdev_id; + u32 cmd_id; + const u32 *bitmap; + const char *label; +}; + static const struct ath12k_wmi_tlv_policy ath12k_wmi_tlv_policies[] = { [WMI_TAG_ARRAY_BYTE] = { .min_len = 0 }, [WMI_TAG_ARRAY_UINT32] = { .min_len = 0 }, @@ -3560,6 +3568,140 @@ ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id, return ret; } +u32 ath12k_wmi_build_obss_pd(const struct ath12k_wmi_obss_pd_arg *arg) +{ + u32 param_val = 0; + + param_val |= u32_encode_bits((u8)arg->srg_th, GENMASK(15, 8)); + param_val |= u32_encode_bits((u8)arg->non_srg_th, GENMASK(7, 0)); + + if (arg->srp_support) + param_val |= ATH12K_OBSS_PD_THRESHOLD_IN_DBM; + + if (arg->srg_enabled && arg->srp_support) + param_val |= ATH12K_OBSS_PD_SRG_EN; + + if (arg->non_srg_enabled) + param_val |= ATH12K_OBSS_PD_NON_SRG_EN; + + return param_val; +} + +static int ath12k_wmi_pdev_set_obss_bitmap(struct ath12k *ar, + const struct wmi_pdev_set_obss_bitmap_arg *arg) +{ + struct wmi_pdev_obss_pd_bitmap_cmd *cmd; + struct ath12k_wmi_pdev *wmi = ar->wmi; + const int len = sizeof(*cmd); + struct sk_buff *skb; + int ret; + + skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_obss_pd_bitmap_cmd *)skb->data; + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(arg->tlv_tag, len); + cmd->pdev_id = cpu_to_le32(arg->pdev_id); + memcpy(cmd->bitmap, arg->bitmap, sizeof(cmd->bitmap)); + + ath12k_dbg(ar->ab, ATH12K_DBG_WMI, + "wmi set pdev %u %s %08x %08x\n", + arg->pdev_id, arg->label, arg->bitmap[0], arg->bitmap[1]); + + ret = ath12k_wmi_cmd_send(wmi, skb, arg->cmd_id); + if (ret) { + ath12k_warn(ar->ab, "failed to send %s: %d\n", arg->label, ret); + dev_kfree_skb(skb); + } + + return ret; +} + +int ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID, + .bitmap = bitmap, + .label = "SRG bss color bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + +int ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID, + .bitmap = bitmap, + .label = "SRG partial bssid bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + +int ath12k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + .bitmap = bitmap, + .label = "SRG obss color enable bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + +int ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, + .bitmap = bitmap, + .label = "SRG obss bssid enable bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + +int ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + .bitmap = bitmap, + .label = "non SRG obss color enable bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + +int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar, + u32 pdev_id, const u32 *bitmap) +{ + struct wmi_pdev_set_obss_bitmap_arg arg = { + .tlv_tag = WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + .pdev_id = pdev_id, + .cmd_id = WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, + .bitmap = bitmap, + .label = "non SRG obss bssid enable bitmap", + }; + + return ath12k_wmi_pdev_set_obss_bitmap(ar, &arg); +} + int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id, u8 bss_color, u32 period, bool enable) diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index fdc203fdba0a..0bf0a7941cd3 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -374,6 +374,12 @@ enum wmi_tlv_cmd_id { WMI_PDEV_DMA_RING_CFG_REQ_CMDID, WMI_PDEV_HE_TB_ACTION_FRM_CMDID, WMI_PDEV_PKTLOG_FILTER_CMDID, + WMI_PDEV_SET_SRG_BSS_COLOR_BITMAP_CMDID = 0x403b, + WMI_PDEV_SET_SRG_PARTIAL_BSSID_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMDID, + WMI_PDEV_SET_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMDID, WMI_PDEV_SET_BIOS_SAR_TABLE_CMDID = 0x4044, WMI_PDEV_SET_BIOS_GEO_TABLE_CMDID = 0x4045, WMI_PDEV_SET_BIOS_INTERFACE_CMDID = 0x404A, @@ -1076,6 +1082,9 @@ enum wmi_tlv_pdev_param { WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE, WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE, WMI_PDEV_PARAM_MESH_MCAST_ENABLE, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc, + WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe, + WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6, }; enum wmi_tlv_vdev_param { @@ -1987,6 +1996,12 @@ enum wmi_tlv_tag { WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334, WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344, WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F, + WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b, + WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD, + WMI_TAG_PDEV_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD = 0x381, + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, WMI_TAG_TPC_STATS_GET_CMD = 0x38B, @@ -2244,6 +2259,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219, WMI_TLV_SERVICE_EXT2_MSG = 220, WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT = 244, + WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, WMI_MAX_EXT_SERVICE = 256, @@ -4925,6 +4941,12 @@ struct wmi_obss_spatial_reuse_params_cmd { __le32 vdev_id; } __packed; +struct wmi_pdev_obss_pd_bitmap_cmd { + __le32 tlv_header; + __le32 pdev_id; + __le32 bitmap[2]; +} __packed; + #define ATH12K_BSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 #define ATH12K_OBSS_COLOR_COLLISION_DETECTION_DISABLE 0 #define ATH12K_OBSS_COLOR_COLLISION_DETECTION 1 @@ -6329,6 +6351,18 @@ struct ath12k_wmi_rssi_dbm_conv_info_arg { /* each WMI cmd can hold 58 channel entries at most */ #define ATH12K_WMI_MAX_NUM_CHAN_PER_CMD 58 +#define ATH12K_OBSS_PD_THRESHOLD_IN_DBM BIT(29) +#define ATH12K_OBSS_PD_SRG_EN BIT(30) +#define ATH12K_OBSS_PD_NON_SRG_EN BIT(31) + +struct ath12k_wmi_obss_pd_arg { + bool srp_support; + bool srg_enabled; + bool non_srg_enabled; + s8 srg_th; + s8 non_srg_th; +}; + int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len); @@ -6432,6 +6466,19 @@ int ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_twt_disable_cmd(struct ath12k *ar, u32 pdev_id); int ath12k_wmi_send_obss_spr_cmd(struct ath12k *ar, u32 vdev_id, struct ieee80211_he_obss_pd *he_obss_pd); +u32 ath12k_wmi_build_obss_pd(const struct ath12k_wmi_obss_pd_arg *arg); +int ath12k_wmi_pdev_set_srg_bss_color_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); +int ath12k_wmi_pdev_set_srg_partial_bssid_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); +int ath12k_wmi_pdev_srg_obss_color_enable_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); +int ath12k_wmi_pdev_srg_obss_bssid_enable_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); +int ath12k_wmi_pdev_non_srg_obss_color_enable_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); +int ath12k_wmi_pdev_non_srg_obss_bssid_enable_bitmap(struct ath12k *ar, u32 pdev_id, + const u32 *bitmap); int ath12k_wmi_obss_color_cfg_cmd(struct ath12k *ar, u32 vdev_id, u8 bss_color, u32 period, bool enable); |
