From 1d7f514577f0ccf3e5f5736247138868fb62896a Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Mon, 9 May 2022 14:57:32 +0300 Subject: [PATCH] ath11k: Designating channel frequency when sending management frames In case of Passpoint, the WLAN interface may be requested to remain on a specific channel and then to send some management frames on that channel. Now chanfreq of wmi_mgmt_send_cmd is set as 0, as a result firmware may choose a default but wrong channel. Fix it by assigning chanfreq field with the designated channel. This change only applies to WCN6855 and QCA6390, other chips are not affected. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220506013614.1580274-4-quic_bqiang@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 7 +++++++ drivers/net/wireless/ath/ath11k/hw.h | 1 + drivers/net/wireless/ath/ath11k/wmi.c | 17 ++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 6b65354..26f7bdd 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -110,6 +110,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, @@ -185,6 +186,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .name = "qca6390 hw2.0", @@ -259,6 +261,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "qcn9074 hw1.0", @@ -333,6 +336,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 3, .ce_window_idx = 2, .fixed_fw_mem = false, + .support_off_channel_tx = false, }, { .name = "wcn6855 hw2.0", @@ -407,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "wcn6855 hw2.1", @@ -480,6 +485,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 0, .ce_window_idx = 0, .fixed_fw_mem = false, + .support_off_channel_tx = true, }, { .name = "wcn6750 hw1.0", @@ -553,6 +559,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .dp_window_idx = 1, .ce_window_idx = 2, .fixed_fw_mem = true, + .support_off_channel_tx = false, }, }; diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 3a2abde..77dc5c8 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -204,6 +204,7 @@ struct ath11k_hw_params { u8 dp_window_idx; u8 ce_window_idx; bool fixed_fw_mem; + bool support_off_channel_tx; }; struct ath11k_hw_ops { diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 0eb2e5e..84d1c70 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -625,10 +625,25 @@ struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len) return skb; } +static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar, + struct ieee80211_tx_info *info) +{ + struct ath11k_base *ab = ar->ab; + u32 freq = 0; + + if (ab->hw_params.support_off_channel_tx && + ar->scan.is_roc && + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) + freq = ar->scan.roc_freq; + + return freq; +} + int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame) { struct ath11k_pdev_wmi *wmi = ar->wmi; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame); struct wmi_mgmt_send_cmd *cmd; struct wmi_tlv *frame_tlv; struct sk_buff *skb; @@ -649,7 +664,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->vdev_id = vdev_id; cmd->desc_id = buf_id; - cmd->chanfreq = 0; + cmd->chanfreq = ath11k_wmi_mgmt_get_freq(ar, info); cmd->paddr_lo = lower_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr); cmd->frame_len = frame->len; -- 2.7.4