Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git patches for v6.6. Major changes:

ath12k

* Extremely High Throughput (EHT) PHY support for Wi-Fi 7
This commit is contained in:
Kalle Valo
2023-08-03 21:16:27 +03:00
27 changed files with 991 additions and 190 deletions
+2 -27
View File
@@ -14,6 +14,7 @@
#include "ahb.h"
#include "debug.h"
#include "hif.h"
#include "qmi.h"
#include <linux/remoteproc.h>
#include "pcic.h"
#include <linux/soc/qcom/smem.h>
@@ -419,32 +420,6 @@ static void ath11k_ahb_power_down(struct ath11k_base *ab)
rproc_shutdown(ab_ahb->tgt_rproc);
}
static int ath11k_ahb_fwreset_from_cold_boot(struct ath11k_base *ab)
{
int timeout;
if (ath11k_cold_boot_cal == 0 || ab->qmi.cal_done ||
ab->hw_params.cold_boot_calib == 0 ||
ab->hw_params.cbcal_restart_fw == 0)
return 0;
ath11k_dbg(ab, ATH11K_DBG_AHB, "wait for cold boot done\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
ath11k_cold_boot_cal = 0;
ath11k_warn(ab, "Coldboot Calibration failed timed out\n");
}
/* reset the firmware */
ath11k_ahb_power_down(ab);
ath11k_ahb_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_AHB, "exited from cold boot mode\n");
return 0;
}
static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
{
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
@@ -1227,7 +1202,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
goto err_ce_free;
}
ath11k_ahb_fwreset_from_cold_boot(ab);
ath11k_qmi_fwreset_from_cold_boot(ab);
return 0;
+29 -9
View File
@@ -86,7 +86,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -167,7 +168,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -248,7 +250,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -332,8 +335,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = false,
.cbcal_restart_fw = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 2,
.num_vdevs = 8,
.num_peers = 128,
@@ -413,7 +417,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -495,7 +500,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -578,7 +584,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@@ -667,7 +674,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = false,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.single_pdev_only = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fix_l1ss = true,
.supports_dynamic_smps_6ghz = false,
@@ -749,6 +757,18 @@ void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
ath11k_fw_stats_bcn_free(&stats->bcn);
}
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab)
{
if (!ath11k_cold_boot_cal)
return false;
if (ath11k_ftm_mode)
return ab->hw_params.coldboot_cal_ftm;
else
return ab->hw_params.coldboot_cal_mm;
}
int ath11k_core_suspend(struct ath11k_base *ab)
{
int ret;
+1
View File
@@ -1186,6 +1186,7 @@ void ath11k_core_halt(struct ath11k *ar);
int ath11k_core_resume(struct ath11k_base *ab);
int ath11k_core_suspend(struct ath11k_base *ab);
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *filename);
+1 -1
View File
@@ -2408,7 +2408,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_status->freq = center_freq;
} else if (channel_num >= 1 && channel_num <= 14) {
rx_status->band = NL80211_BAND_2GHZ;
} else if (channel_num >= 36 && channel_num <= 173) {
} else if (channel_num >= 36 && channel_num <= 177) {
rx_status->band = NL80211_BAND_5GHZ;
} else {
spin_lock_bh(&ar->data_lock);
+2 -1
View File
@@ -187,7 +187,8 @@ struct ath11k_hw_params {
bool supports_shadow_regs;
bool idle_ps;
bool supports_sta_ps;
bool cold_boot_calib;
bool coldboot_cal_mm;
bool coldboot_cal_ftm;
bool cbcal_restart_fw;
int fw_mem_mode;
u32 num_vdevs;
+2 -2
View File
@@ -8255,7 +8255,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
const struct cfg80211_bitrate_mask *mask)
{
bool he_fixed_rate = false, vht_fixed_rate = false;
struct ath11k_peer *peer, *tmp;
struct ath11k_peer *peer;
const u16 *vht_mcs_mask, *he_mcs_mask;
struct ieee80211_link_sta *deflink;
u8 vht_nss, he_nss;
@@ -8278,7 +8278,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
rcu_read_lock();
spin_lock_bh(&ar->ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
list_for_each_entry(peer, &ar->ab->peers, list) {
if (peer->sta) {
deflink = &peer->sta->deflink;
+2
View File
@@ -15,6 +15,7 @@
#include "mhi.h"
#include "debug.h"
#include "pcic.h"
#include "qmi.h"
#define ATH11K_PCI_BAR_NUM 0
#define ATH11K_PCI_DMA_MASK 32
@@ -897,6 +898,7 @@ unsupported_wcn6855_soc:
ath11k_err(ab, "failed to init core: %d\n", ret);
goto err_irq_affinity_cleanup;
}
ath11k_qmi_fwreset_from_cold_boot(ab);
return 0;
err_irq_affinity_cleanup:
+31 -3
View File
@@ -9,6 +9,7 @@
#include "qmi.h"
#include "core.h"
#include "debug.h"
#include "hif.h"
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/ioport.h>
@@ -2078,7 +2079,7 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
return -EINVAL;
}
if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) {
if (ath11k_core_coldboot_cal_support(ab)) {
if (hremote_node) {
ab->qmi.target_mem[idx].paddr =
res.start + host_ddr_sz;
@@ -2838,6 +2839,33 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,
return 0;
}
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
{
int timeout;
if (!ath11k_core_coldboot_cal_support(ab) ||
ab->hw_params.cbcal_restart_fw == 0)
return 0;
ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
ath11k_warn(ab, "Coldboot Calibration timed out\n");
return -ETIMEDOUT;
}
/* reset the firmware */
ath11k_hif_power_down(ab);
ath11k_hif_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
return 0;
}
EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot);
static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
{
int timeout;
@@ -3208,8 +3236,8 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
break;
}
if (ath11k_cold_boot_cal && ab->qmi.cal_done == 0 &&
ab->hw_params.cold_boot_calib) {
if (ab->qmi.cal_done == 0 &&
ath11k_core_coldboot_cal_support(ab)) {
ath11k_qmi_process_coldboot_calibration(ab);
} else {
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
+2 -1
View File
@@ -37,7 +37,7 @@
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
#define ATH11K_FIRMWARE_MODE_OFF 4
#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ)
#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ)
#define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000
@@ -519,5 +519,6 @@ void ath11k_qmi_msg_recv_work(struct work_struct *work);
void ath11k_qmi_deinit_service(struct ath11k_base *ab);
int ath11k_qmi_init_service(struct ath11k_base *ab);
void ath11k_qmi_free_resource(struct ath11k_base *ab);
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab);
#endif
+34
View File
@@ -238,6 +238,7 @@ struct ath12k_vif {
u32 key_cipher;
u8 tx_encap_type;
u8 vdev_stats_id;
u32 punct_bitmap;
};
struct ath12k_vif_iter {
@@ -580,6 +581,14 @@ struct ath12k_band_cap {
u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE];
struct ath12k_wmi_ppe_threshold_arg he_ppet;
u16 he_6ghz_capa;
u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
u32 eht_cap_phy_info[WMI_MAX_EHTCAP_PHY_SIZE];
u32 eht_mcs_20_only;
u32 eht_mcs_80;
u32 eht_mcs_160;
u32 eht_mcs_320;
struct ath12k_wmi_ppe_threshold_arg eht_ppet;
u32 eht_cap_info_internal;
};
struct ath12k_pdev_cap {
@@ -614,6 +623,12 @@ struct ath12k_pdev {
struct mlo_timestamp timestamp;
};
struct ath12k_fw_pdev {
u32 pdev_id;
u32 phy_id;
u32 supported_bands;
};
struct ath12k_board_data {
const struct firmware *fw;
const void *data;
@@ -669,7 +684,26 @@ struct ath12k_base {
struct mutex core_lock;
/* Protects data like peers */
spinlock_t base_lock;
/* Single pdev device (struct ath12k_hw_params::single_pdev_only):
*
* Firmware maintains data for all bands but advertises a single
* phy to the host which is stored as a single element in this
* array.
*
* Other devices:
*
* This array will contain as many elements as the number of
* radios.
*/
struct ath12k_pdev pdevs[MAX_RADIOS];
/* struct ath12k_hw_params::single_pdev_only devices use this to
* store phy specific data
*/
struct ath12k_fw_pdev fw_pdev[MAX_RADIOS];
u8 fw_pdev_count;
struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS];
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map;
+7 -4
View File
@@ -2539,7 +2539,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
struct ath12k_skb_rxcb *rxcb;
struct sk_buff *msdu;
struct ath12k *ar;
u8 mac_id;
u8 mac_id, pdev_id;
int ret;
if (skb_queue_empty(msdu_list))
@@ -2550,8 +2550,9 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
while ((msdu = __skb_dequeue(msdu_list))) {
rxcb = ATH12K_SKB_RXCB(msdu);
mac_id = rxcb->mac_id;
ar = ab->pdevs[mac_id].ar;
if (!rcu_dereference(ab->pdevs_active[mac_id])) {
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!rcu_dereference(ab->pdevs_active[pdev_id])) {
dev_kfree_skb_any(msdu);
continue;
}
@@ -3385,6 +3386,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
dma_addr_t paddr;
bool is_frag;
bool drop = false;
int pdev_id;
tot_n_bufs_reaped = 0;
quota = budget;
@@ -3440,7 +3442,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
mac_id = le32_get_bits(reo_desc->info0,
HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
ar = ab->pdevs[mac_id].ar;
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, drop,
msdu_cookies[i]))
+5 -3
View File
@@ -347,6 +347,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
{
struct ath12k *ar;
struct ath12k_skb_cb *skb_cb;
u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
skb_cb = ATH12K_SKB_CB(msdu);
@@ -357,7 +358,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
dev_kfree_skb_any(msdu);
ar = ab->pdevs[mac_id].ar;
ar = ab->pdevs[pdev_id].ar;
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
}
@@ -536,7 +537,7 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
struct hal_tx_status ts = { 0 };
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
struct hal_wbm_release_ring *desc;
u8 mac_id;
u8 mac_id, pdev_id;
u64 desc_va;
spin_lock_bh(&status_ring->lock);
@@ -605,7 +606,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
continue;
}
ar = ab->pdevs[mac_id].ar;
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
+478 -111
View File
@@ -182,32 +182,35 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
[NL80211_BAND_2GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20_2G,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20_2G,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40_2G,
[NL80211_CHAN_WIDTH_80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_320] = MODE_UNKNOWN,
},
[NL80211_BAND_5GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
[NL80211_BAND_6GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
};
@@ -292,6 +295,24 @@ static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
return "11ax-he40-2g";
case MODE_11AX_HE80_2G:
return "11ax-he80-2g";
case MODE_11BE_EHT20:
return "11be-eht20";
case MODE_11BE_EHT40:
return "11be-eht40";
case MODE_11BE_EHT80:
return "11be-eht80";
case MODE_11BE_EHT80_80:
return "11be-eht80+80";
case MODE_11BE_EHT160:
return "11be-eht160";
case MODE_11BE_EHT160_160:
return "11be-eht160+160";
case MODE_11BE_EHT320:
return "11be-eht320";
case MODE_11BE_EHT20_2G:
return "11be-eht20-2g";
case MODE_11BE_EHT40_2G:
return "11be-eht40-2g";
case MODE_UNKNOWN:
/* skip */
break;
@@ -821,6 +842,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
arg.pref_tx_streams = ar->num_tx_chains;
arg.pref_rx_streams = ar->num_rx_chains;
arg.punct_bitmap = 0xFFFFFFFF;
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
@@ -1637,9 +1659,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
sizeof(arg->peer_he_cap_macinfo));
sizeof(he_cap->he_cap_elem.mac_cap_info));
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
sizeof(arg->peer_he_cap_phyinfo));
sizeof(he_cap->he_cap_elem.phy_cap_info));
arg->peer_he_ops = vif->bss_conf.he_oper.params;
/* the top most byte is used to indicate BSS color info */
@@ -1929,6 +1951,41 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
return MODE_UNKNOWN;
}
static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
struct ieee80211_sta *sta)
{
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)
if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
return MODE_11BE_EHT320;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11BE_EHT160;
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
return MODE_11BE_EHT80_80;
ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]);
return MODE_11BE_EHT160;
}
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
return MODE_11BE_EHT80;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
return MODE_11BE_EHT40;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
return MODE_11BE_EHT20;
return MODE_UNKNOWN;
}
static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -1950,7 +2007,12 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
switch (band) {
case NL80211_BAND_2GHZ:
if (sta->deflink.he_cap.has_he) {
if (sta->deflink.eht_cap.has_eht) {
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11BE_EHT40_2G;
else
phymode = MODE_11BE_EHT20_2G;
} else if (sta->deflink.he_cap.has_he) {
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
phymode = MODE_11AX_HE80_2G;
else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
@@ -1977,8 +2039,10 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
break;
case NL80211_BAND_5GHZ:
case NL80211_BAND_6GHZ:
/* Check HE first */
if (sta->deflink.he_cap.has_he) {
/* Check EHT first */
if (sta->deflink.eht_cap.has_eht) {
phymode = ath12k_mac_get_phymode_eht(ar, sta);
} else if (sta->deflink.he_cap.has_he) {
phymode = ath12k_mac_get_phymode_he(ar, sta);
} else if (sta->deflink.vht_cap.vht_supported &&
!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
@@ -2004,6 +2068,152 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
WARN_ON(phymode == MODE_UNKNOWN);
}
static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9,
u8 rx_tx_mcs11, u8 rx_tx_mcs13,
u32 *rx_mcs, u32 *tx_mcs)
{
*rx_mcs = 0;
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_0_7);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_8_9);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_10_11);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_12_13);
*tx_mcs = 0;
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_0_7);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_8_9);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_10_11);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_12_13);
}
static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
struct ath12k_wmi_ppe_threshold_arg *ppet)
{
u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE, val;
u8 nss, ru, i;
u8 ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK);
ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres),
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
for (nss = 0; nss <= ppet->numss_m1; nss++) {
for (ru = 0;
ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
ru++) {
if ((ppet->ru_bit_mask & BIT(ru)) == 0)
continue;
val = 0;
for (i = 0; i < ppet_bit_len_per_ru; i++) {
val |= (((ppe_thres[bit_pos / 8] >>
(bit_pos % 8)) & 0x1) << i);
bit_pos++;
}
ppet->ppet16_ppet8_ru3_ru0[nss] |=
(val << (ru * ppet_bit_len_per_ru));
}
}
}
static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
u32 *rx_mcs, *tx_mcs;
if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
return;
arg->eht_flag = true;
if ((eht_cap->eht_cap_elem.phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) &&
eht_cap->eht_ppe_thres[0] != 0)
ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres,
&arg->peer_eht_ppet);
memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info,
sizeof(eht_cap->eht_cap_elem.mac_cap_info));
memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info,
sizeof(eht_cap->eht_cap_elem.phy_cap_info));
rx_mcs = arg->peer_eht_rx_mcs_set;
tx_mcs = arg->peer_eht_tx_mcs_set;
switch (sta->deflink.bandwidth) {
case IEEE80211_STA_RX_BW_320:
bw = &eht_cap->eht_mcs_nss_supp.bw._320;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]);
arg->peer_eht_mcs_count++;
fallthrough;
case IEEE80211_STA_RX_BW_160:
bw = &eht_cap->eht_mcs_nss_supp.bw._160;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]);
arg->peer_eht_mcs_count++;
fallthrough;
default:
if ((he_cap->he_cap_elem.phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) {
bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;
ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
bw_20->rx_tx_mcs9_max_nss,
bw_20->rx_tx_mcs11_max_nss,
bw_20->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
} else {
bw = &eht_cap->eht_mcs_nss_supp.bw._80;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
}
arg->peer_eht_mcs_count++;
break;
}
arg->punct_bitmap = ~arvif->punct_bitmap;
}
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -2023,6 +2233,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
ath12k_peer_assoc_h_he(ar, vif, sta, arg);
ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
ath12k_peer_assoc_h_smps(sta, arg);
@@ -2554,6 +2765,9 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
ath12k_mac_fils_discovery(arvif, info);
if (changed & BSS_CHANGED_EHT_PUNCTURING)
arvif->punct_bitmap = info->eht_puncturing;
mutex_unlock(&ar->conf_mutex);
}
@@ -2755,9 +2969,12 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg.scan_id = ATH12K_SCAN_ID;
if (req->ie_len) {
arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
if (!arg.extraie.ptr) {
ret = -ENOMEM;
goto exit;
}
arg.extraie.len = req->ie_len;
arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
memcpy(arg.extraie.ptr, req->ie, req->ie_len);
}
if (req->n_ssids) {
@@ -2770,6 +2987,14 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels) {
arg.num_chan = req->n_channels;
arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
GFP_KERNEL);
if (!arg.chan_list) {
ret = -ENOMEM;
goto exit;
}
for (i = 0; i < arg.num_chan; i++)
arg.chan_list[i] = req->channels[i]->center_freq;
}
@@ -2788,6 +3013,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
ATH12K_MAC_SCAN_TIMEOUT_MSECS));
exit:
kfree(arg.chan_list);
if (req->ie_len)
kfree(arg.extraie.ptr);
@@ -4209,18 +4436,178 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
return cpu_to_le16(bcap->he_6ghz_capa);
}
static int ath12k_mac_copy_he_cap(struct ath12k *ar,
struct ath12k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
int band)
static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
int iftype, u8 num_tx_chains,
struct ieee80211_sta_he_cap *he_cap)
{
struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
he_cap->has_he = true;
memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
sizeof(he_cap_elem->mac_cap_info));
memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
sizeof(he_cap_elem->phy_cap_info));
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;
switch (iftype) {
case NL80211_IFTYPE_AP:
he_cap_elem->phy_cap_info[3] &=
~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES;
he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_MESH_POINT:
ath12k_mac_filter_he_cap_mesh(he_cap_elem);
break;
}
mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres);
}
static void
ath12k_mac_copy_eht_mcs_nss(struct ath12k_band_cap *band_cap,
struct ieee80211_eht_mcs_nss_supp *mcs_nss,
const struct ieee80211_he_cap_elem *he_cap,
const struct ieee80211_eht_cap_elem_fixed *eht_cap)
{
if ((he_cap->phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0)
memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only,
sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only));
if (he_cap->phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
if (he_cap->phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
}
static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,
struct ieee80211_sta_eht_cap *cap)
{
u16 bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
u8 i, nss, ru, ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
u8p_replace_bits(&cap->eht_ppe_thres[0], fw_ppet->numss_m1,
IEEE80211_EHT_PPE_THRES_NSS_MASK);
u16p_replace_bits((u16 *)&cap->eht_ppe_thres[0], fw_ppet->ru_bit_mask,
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
for (ru = 0;
ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
ru++) {
u32 val = 0;
if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
continue;
u32p_replace_bits(&val, fw_ppet->ppet16_ppet8_ru3_ru0[nss] >>
(ru * ppet_bit_len_per_ru),
GENMASK(ppet_bit_len_per_ru - 1, 0));
for (i = 0; i < ppet_bit_len_per_ru; i++) {
cap->eht_ppe_thres[bit / 8] |=
(((val >> i) & 0x1) << ((bit % 8)));
bit++;
}
}
}
}
static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
struct ieee80211_he_cap_elem *he_cap_elem,
int iftype,
struct ieee80211_sta_eht_cap *eht_cap)
{
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
eht_cap->has_eht = true;
memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
sizeof(eht_cap_elem->mac_cap_info));
memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info,
sizeof(eht_cap_elem->phy_cap_info));
switch (iftype) {
case NL80211_IFTYPE_AP:
eht_cap_elem->phy_cap_info[0] &=
~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ;
eht_cap_elem->phy_cap_info[4] &=
~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO;
eht_cap_elem->phy_cap_info[5] &=
~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP;
break;
case NL80211_IFTYPE_STATION:
eht_cap_elem->phy_cap_info[7] &=
~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
eht_cap_elem->phy_cap_info[7] &=
~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
break;
default:
break;
}
ath12k_mac_copy_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp,
he_cap_elem, eht_cap_elem);
if (eht_cap_elem->phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)
ath12k_mac_copy_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap);
}
static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
struct ath12k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
int band)
{
struct ath12k_band_cap *band_cap = &cap->band[band];
int i, idx = 0;
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
struct ath12k_band_cap *band_cap = &cap->band[band];
struct ieee80211_he_cap_elem *he_cap_elem =
&he_cap->he_cap_elem;
switch (i) {
case NL80211_IFTYPE_STATION:
@@ -4233,102 +4620,56 @@ static int ath12k_mac_copy_he_cap(struct ath12k *ar,
}
data[idx].types_mask = BIT(i);
he_cap->has_he = true;
memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
sizeof(he_cap_elem->mac_cap_info));
memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
sizeof(he_cap_elem->phy_cap_info));
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
switch (i) {
case NL80211_IFTYPE_AP:
he_cap_elem->phy_cap_info[3] &=
~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[0] &=
~IEEE80211_HE_MAC_CAP0_TWT_RES;
he_cap_elem->mac_cap_info[0] |=
IEEE80211_HE_MAC_CAP0_TWT_REQ;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_MESH_POINT:
ath12k_mac_filter_he_cap_mesh(he_cap_elem);
break;
}
he_cap->he_mcs_nss_supp.rx_mcs_80 =
cpu_to_le16(band_cap->he_mcs & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_80 =
cpu_to_le16(band_cap->he_mcs & 0xffff);
he_cap->he_mcs_nss_supp.rx_mcs_160 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_160 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
ath12k_gen_ppe_thresh(&band_cap->he_ppet,
he_cap->ppe_thres);
ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
if (band == NL80211_BAND_6GHZ) {
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
}
ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
&data[idx].eht_cap);
idx++;
}
return idx;
}
static void ath12k_mac_setup_he_cap(struct ath12k *ar,
struct ath12k_pdev_cap *cap)
static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
struct ath12k_pdev_cap *cap)
{
struct ieee80211_supported_band *band;
struct ieee80211_supported_band *sband;
enum nl80211_band band;
int count;
if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_2GHZ],
NL80211_BAND_2GHZ);
band = &ar->mac.sbands[NL80211_BAND_2GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_2GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_5GHZ],
NL80211_BAND_5GHZ);
band = &ar->mac.sbands[NL80211_BAND_5GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_5GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
ar->supports_6ghz) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_6GHZ],
NL80211_BAND_6GHZ);
band = &ar->mac.sbands[NL80211_BAND_6GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_6GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
}
@@ -4373,7 +4714,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
/* Reload HT/VHT/HE capability */
ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
ath12k_mac_setup_he_cap(ar, &ar->pdev->cap);
ath12k_mac_setup_sband_iftype_data(ar, &ar->pdev->cap);
return 0;
}
@@ -5201,7 +5542,7 @@ err:
static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)
{
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
struct ath12k_tx_desc_info *tx_desc_info;
struct ath12k_skb_cb *skb_cb;
struct sk_buff *skb;
int i;
@@ -5209,8 +5550,8 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif
for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {
spin_lock_bh(&dp->tx_desc_lock[i]);
list_for_each_entry_safe(tx_desc_info, tmp1, &dp->tx_desc_used_list[i],
list) {
list_for_each_entry(tx_desc_info, &dp->tx_desc_used_list[i],
list) {
skb = tx_desc_info->skb;
if (!skb)
continue;
@@ -5466,6 +5807,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.vdev_id = arvif->vdev_id;
arg.dtim_period = arvif->dtim_period;
arg.bcn_intval = arvif->beacon_interval;
arg.punct_bitmap = ~arvif->punct_bitmap;
arg.freq = chandef->chan->center_freq;
arg.band_center_freq1 = chandef->center_freq1;
@@ -5508,9 +5850,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac vdev %d start center_freq %d phymode %s\n",
"mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n",
arg.vdev_id, arg.freq,
ath12k_mac_phymode_str(arg.mode));
ath12k_mac_phymode_str(arg.mode), arg.punct_bitmap);
ret = ath12k_wmi_vdev_start(ar, &arg, restart);
if (ret) {
@@ -5837,6 +6179,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
"mac chanctx assign ptr %pK vdev_id %i\n",
ctx, arvif->vdev_id);
arvif->punct_bitmap = link_conf->eht_puncturing;
/* for some targets bss peer must be created before vdev_start */
if (ab->hw_params->vdev_start_delay &&
arvif->vdev_type != WMI_VDEV_TYPE_AP &&
@@ -6388,6 +6732,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
{
struct ath12k *ar = hw->priv;
struct ath12k_base *ab = ar->ab;
struct ath12k_vif *arvif;
int recovery_count;
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
@@ -6416,6 +6761,26 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
}
}
list_for_each_entry(arvif, &ar->arvifs, list) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"reconfig cipher %d up %d vdev type %d\n",
arvif->key_cipher,
arvif->is_up,
arvif->vdev_type);
/* After trigger disconnect, then upper layer will
* trigger connect again, then the PN number of
* upper layer will be reset to keep up with AP
* side, hence PN number mis-match will not happened.
*/
if (arvif->is_up &&
arvif->vdev_type == WMI_VDEV_TYPE_STA &&
arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
ieee80211_hw_restart_disconnect(arvif->vif);
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"restart disconnect\n");
}
}
}
mutex_unlock(&ar->conf_mutex);
@@ -6854,7 +7219,7 @@ static int __ath12k_mac_register(struct ath12k *ar)
goto err;
ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
ath12k_mac_setup_he_cap(ar, cap);
ath12k_mac_setup_sband_iftype_data(ar, cap);
ret = ath12k_mac_setup_iface_combinations(ar);
if (ret) {
@@ -6943,6 +7308,8 @@ static int __ath12k_mac_register(struct ath12k *ar)
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
}
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_PUNCT);
ath12k_reg_init(ar);
if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {
+1 -1
View File
@@ -33,7 +33,7 @@ struct ath12k_generic_iter {
#define IEEE80211_VHT_MCS_SUPPORT_0_11_MASK GENMASK(23, 16)
#define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24)
#define ATH12K_CHAN_WIDTH_NUM 8
#define ATH12K_CHAN_WIDTH_NUM 14
#define ATH12K_TX_POWER_MAX_VAL 70
#define ATH12K_TX_POWER_MIN_VAL 0
+1 -1
View File
@@ -387,7 +387,7 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
mlo_capable_valid),
},
{
.data_type = QMI_OPT_FLAG,
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
+256 -4
View File
@@ -62,9 +62,27 @@ struct ath12k_wmi_svc_rdy_ext_parse {
bool dma_ring_cap_done;
};
struct ath12k_wmi_svc_rdy_ext2_arg {
u32 reg_db_version;
u32 hw_min_max_tx_power_2ghz;
u32 hw_min_max_tx_power_5ghz;
u32 chwidth_num_peer_caps;
u32 preamble_puncture_bw;
u32 max_user_per_ppdu_ofdma;
u32 max_user_per_ppdu_mumimo;
u32 target_cap_flags;
u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
u32 max_num_linkview_peers;
u32 max_num_msduq_supported_per_tid;
u32 default_num_msduq_supported_per_tid;
};
struct ath12k_wmi_svc_rdy_ext2_parse {
struct ath12k_wmi_svc_rdy_ext2_arg arg;
struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse;
bool dma_ring_cap_done;
bool spectral_bin_scaling_done;
bool mac_phy_caps_ext_done;
};
struct ath12k_wmi_rdy_parse {
@@ -445,8 +463,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps;
const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps;
const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps;
struct ath12k_base *ab = wmi_handle->wmi_ab->ab;
struct ath12k_band_cap *cap_band;
struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
struct ath12k_fw_pdev *fw_pdev;
u32 phy_map;
u32 hw_idx, phy_idx = 0;
int i;
@@ -475,6 +495,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);
pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);
fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];
fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);
fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id);
fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);
ab->fw_pdev_count++;
/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from
* band to band for a single radio, need to see how this should be
* handled.
@@ -995,6 +1021,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms);
cmd->regdomain = cpu_to_le32(arg->regdomain);
cmd->he_ops = cpu_to_le32(arg->he_ops);
cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);
if (!restart) {
if (arg->ssid) {
@@ -1791,6 +1818,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
bool hw_crypto_disabled)
{
cmd->peer_flags = 0;
cmd->peer_flags_ext = 0;
if (arg->is_wme_set) {
if (arg->qos_flag)
@@ -1805,6 +1833,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
cmd->peer_flags |= cpu_to_le32(WMI_PEER_80MHZ);
if (arg->bw_160)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);
if (arg->bw_320)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
/* Typically if STBC is enabled for VHT it should be enabled
* for HT as well
@@ -1832,6 +1862,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_REQ);
if (arg->twt_responder)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_RESP);
if (arg->eht_flag)
cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_EHT);
}
/* Suppress authorization for all AUTH modes that need 4-way handshake
@@ -1876,6 +1908,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
struct wmi_peer_assoc_complete_cmd *cmd;
struct ath12k_wmi_vht_rate_set_params *mcs;
struct ath12k_wmi_he_rate_set_params *he_mcs;
struct ath12k_wmi_eht_rate_set_params *eht_mcs;
struct sk_buff *skb;
struct wmi_tlv *tlv;
void *ptr;
@@ -1892,7 +1925,9 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) +
TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) +
sizeof(*mcs) + TLV_HDR_SIZE +
(sizeof(*he_mcs) * arg->peer_he_mcs_count);
(sizeof(*he_mcs) * arg->peer_he_mcs_count) +
TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count) +
TLV_HDR_SIZE + TLV_HDR_SIZE;
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@@ -1908,6 +1943,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_new_assoc = cpu_to_le32(arg->peer_new_assoc);
cmd->peer_associd = cpu_to_le32(arg->peer_associd);
cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);
ath12k_wmi_copy_peer_flags(cmd, arg,
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED,
@@ -1939,6 +1975,16 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_ppet.ppet16_ppet8_ru3_ru0[i] =
cpu_to_le32(arg->peer_ppet.ppet16_ppet8_ru3_ru0[i]);
/* Update 11be capabilities */
memcpy_and_pad(cmd->peer_eht_cap_mac, sizeof(cmd->peer_eht_cap_mac),
arg->peer_eht_cap_mac, sizeof(arg->peer_eht_cap_mac),
0);
memcpy_and_pad(cmd->peer_eht_cap_phy, sizeof(cmd->peer_eht_cap_phy),
arg->peer_eht_cap_phy, sizeof(arg->peer_eht_cap_phy),
0);
memcpy_and_pad(&cmd->peer_eht_ppet, sizeof(cmd->peer_eht_ppet),
&arg->peer_eht_ppet, sizeof(arg->peer_eht_ppet), 0);
/* Update peer legacy rate information */
ptr += sizeof(*cmd);
@@ -2005,8 +2051,36 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ptr += sizeof(*he_mcs);
}
/* MLO header tag with 0 length */
len = 0;
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
/* Loop through the EHT rate set */
len = arg->peer_eht_mcs_count * sizeof(*eht_mcs);
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
for (i = 0; i < arg->peer_eht_mcs_count; i++) {
eht_mcs = ptr;
eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,
sizeof(*eht_mcs));
eht_mcs->rx_mcs_set = cpu_to_le32(arg->peer_eht_rx_mcs_set[i]);
eht_mcs->tx_mcs_set = cpu_to_le32(arg->peer_eht_tx_mcs_set[i]);
ptr += sizeof(*eht_mcs);
}
/* ML partner links tag with 0 length */
len = 0;
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n",
cmd->vdev_id, cmd->peer_associd, arg->peer_mac,
cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,
cmd->peer_listen_intval, cmd->peer_ht_caps,
@@ -2016,7 +2090,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_he_ops, cmd->peer_he_cap_info_ext,
cmd->peer_he_cap_phy[0], cmd->peer_he_cap_phy[1],
cmd->peer_he_cap_phy[2],
cmd->peer_bw_rxnss_override);
cmd->peer_bw_rxnss_override, cmd->peer_flags_ext,
cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1],
cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1],
cmd->peer_eht_cap_phy[2]);
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID);
if (ret) {
@@ -3705,6 +3782,10 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) {
hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
mode = le32_to_cpu(hw_mode_caps->hw_mode_id);
if (mode >= WMI_HOST_HW_MODE_MAX)
continue;
pref = soc->wmi_ab.preferred_hw_mode;
if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
@@ -3811,6 +3892,7 @@ static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc,
soc->num_radios = 0;
phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map);
soc->fw_pdev_count = 0;
while (phy_id_map && soc->num_radios < MAX_RADIOS) {
ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle,
@@ -4038,14 +4120,165 @@ err:
return ret;
}
static int ath12k_pull_svc_ready_ext2(struct ath12k_wmi_pdev *wmi_handle,
const void *ptr,
struct ath12k_wmi_svc_rdy_ext2_arg *arg)
{
const struct wmi_service_ready_ext2_event *ev = ptr;
if (!ev)
return -EINVAL;
arg->reg_db_version = le32_to_cpu(ev->reg_db_version);
arg->hw_min_max_tx_power_2ghz = le32_to_cpu(ev->hw_min_max_tx_power_2ghz);
arg->hw_min_max_tx_power_5ghz = le32_to_cpu(ev->hw_min_max_tx_power_5ghz);
arg->chwidth_num_peer_caps = le32_to_cpu(ev->chwidth_num_peer_caps);
arg->preamble_puncture_bw = le32_to_cpu(ev->preamble_puncture_bw);
arg->max_user_per_ppdu_ofdma = le32_to_cpu(ev->max_user_per_ppdu_ofdma);
arg->max_user_per_ppdu_mumimo = le32_to_cpu(ev->max_user_per_ppdu_mumimo);
arg->target_cap_flags = le32_to_cpu(ev->target_cap_flags);
return 0;
}
static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
const __le32 cap_mac_info[],
const __le32 cap_phy_info[],
const __le32 supp_mcs[],
const struct ath12k_wmi_ppe_threshold_params *ppet,
__le32 cap_info_internal)
{
struct ath12k_band_cap *cap_band = &pdev->cap.band[band];
u8 i;
for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++)
cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]);
for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++)
cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]);
cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]);
cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]);
if (band != NL80211_BAND_2GHZ) {
cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]);
cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]);
}
cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1);
cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info);
for (i = 0; i < WMI_MAX_NUM_SS; i++)
cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] =
le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]);
cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal);
}
static int
ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
const struct ath12k_wmi_caps_ext_params *caps,
struct ath12k_pdev *pdev)
{
u32 bands;
int i;
if (ab->hw_params->single_pdev_only) {
for (i = 0; i < ab->fw_pdev_count; i++) {
struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];
if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) &&
fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) {
bands = fw_pdev->supported_bands;
break;
}
}
if (i == ab->fw_pdev_count)
return -EINVAL;
} else {
bands = pdev->cap.supported_bands;
}
if (bands & WMI_HOST_WLAN_2G_CAP) {
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ,
caps->eht_cap_mac_info_2ghz,
caps->eht_cap_phy_info_2ghz,
caps->eht_supp_mcs_ext_2ghz,
&caps->eht_ppet_2ghz,
caps->eht_cap_info_internal);
}
if (bands & WMI_HOST_WLAN_5G_CAP) {
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ,
caps->eht_cap_mac_info_5ghz,
caps->eht_cap_phy_info_5ghz,
caps->eht_supp_mcs_ext_5ghz,
&caps->eht_ppet_5ghz,
caps->eht_cap_info_internal);
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ,
caps->eht_cap_mac_info_5ghz,
caps->eht_cap_phy_info_5ghz,
caps->eht_supp_mcs_ext_5ghz,
&caps->eht_ppet_5ghz,
caps->eht_cap_info_internal);
}
return 0;
}
static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,
u16 len, const void *ptr,
void *data)
{
const struct ath12k_wmi_caps_ext_params *caps = ptr;
int i = 0, ret;
if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT)
return -EPROTO;
if (ab->hw_params->single_pdev_only) {
if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id))
return 0;
} else {
for (i = 0; i < ab->num_radios; i++) {
if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id))
break;
}
if (i == ab->num_radios)
return -EINVAL;
}
ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]);
if (ret) {
ath12k_warn(ab,
"failed to parse extended MAC PHY capabilities for pdev %d: %d\n",
ret, ab->pdevs[i].pdev_id);
return ret;
}
return 0;
}
static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
{
struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];
struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;
int ret;
switch (tag) {
case WMI_TAG_SERVICE_READY_EXT2_EVENT:
ret = ath12k_pull_svc_ready_ext2(wmi_handle, ptr,
&parse->arg);
if (ret) {
ath12k_warn(ab,
"failed to extract wmi service ready ext2 parameters: %d\n",
ret);
return ret;
}
break;
case WMI_TAG_ARRAY_STRUCT:
if (!parse->dma_ring_cap_done) {
ret = ath12k_wmi_dma_ring_caps(ab, len, ptr,
@@ -4054,6 +4287,23 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
return ret;
parse->dma_ring_cap_done = true;
} else if (!parse->spectral_bin_scaling_done) {
/* TODO: This is a place-holder as WMI tag for
* spectral scaling is before
* WMI_TAG_MAC_PHY_CAPABILITIES_EXT
*/
parse->spectral_bin_scaling_done = true;
} else if (!parse->mac_phy_caps_ext_done) {
ret = ath12k_wmi_tlv_iter(ab, ptr, len,
ath12k_wmi_tlv_mac_phy_caps_ext,
parse);
if (ret) {
ath12k_warn(ab, "failed to parse extended MAC PHY capabilities WMI TLV: %d\n",
ret);
return ret;
}
parse->mac_phy_caps_ext_done = true;
}
break;
default:
@@ -5223,7 +5473,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
ieee80211_queue_work(ar->hw, &ar->regd_update_work);
queue_work(ab->workqueue, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we
@@ -5698,6 +5948,8 @@ static void ath12k_scan_event(struct ath12k_base *ab, struct sk_buff *skb)
ath12k_wmi_event_scan_start_failed(ar);
break;
case WMI_SCAN_EVENT_DEQUEUED:
__ath12k_mac_scan_finish(ar);
break;
case WMI_SCAN_EVENT_PREEMPTED:
case WMI_SCAN_EVENT_RESTARTED:
case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT:
+115 -4
View File
@@ -1167,6 +1167,11 @@ enum wmi_tlv_peer_flags {
};
enum wmi_tlv_peer_flags_ext {
WMI_PEER_EXT_EHT = BIT(0),
WMI_PEER_EXT_320MHZ = BIT(1),
};
/** Enum list of TLV Tags for each parameter structure type. */
enum wmi_tlv_tag {
WMI_TAG_LAST_RESERVED = 15,
@@ -1920,10 +1925,12 @@ enum wmi_tlv_tag {
/* TODO add all the missing cmds */
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
WMI_TAG_EHT_RATE_SET = 0x3C4,
WMI_TAG_MAX
};
@@ -2581,6 +2588,69 @@ struct ath12k_wmi_soc_hal_reg_caps_params {
__le32 num_phy;
} __packed;
#define WMI_MAX_EHTCAP_MAC_SIZE 2
#define WMI_MAX_EHTCAP_PHY_SIZE 3
#define WMI_MAX_EHTCAP_RATE_SET 3
/* Used for EHT MCS-NSS array. Data at each array index follows the format given
* in IEEE P802.11be/D2.0, May 20229.4.2.313.4.
*
* Index interpretation:
* 0 - 20 MHz only sta, all 4 bytes valid
* 1 - index for bandwidths <= 80 MHz except 20 MHz-only, first 3 bytes valid
* 2 - index for 160 MHz, first 3 bytes valid
* 3 - index for 320 MHz, first 3 bytes valid
*/
#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2
#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_80 0
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_160 1
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_320 2
#define WMI_EHT_MCS_NSS_0_7 GENMASK(3, 0)
#define WMI_EHT_MCS_NSS_8_9 GENMASK(7, 4)
#define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8)
#define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12)
struct wmi_service_ready_ext2_event {
__le32 reg_db_version;
__le32 hw_min_max_tx_power_2ghz;
__le32 hw_min_max_tx_power_5ghz;
__le32 chwidth_num_peer_caps;
__le32 preamble_puncture_bw;
__le32 max_user_per_ppdu_ofdma;
__le32 max_user_per_ppdu_mumimo;
__le32 target_cap_flags;
__le32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 max_num_linkview_peers;
__le32 max_num_msduq_supported_per_tid;
__le32 default_num_msduq_supported_per_tid;
} __packed;
struct ath12k_wmi_caps_ext_params {
__le32 hw_mode_id;
union {
struct {
__le16 pdev_id;
__le16 hw_link_id;
} __packed ath12k_wmi_pdev_to_link_map;
__le32 pdev_id;
};
__le32 phy_id;
__le32 wireless_modes_ext;
__le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 eht_cap_mac_info_5ghz[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 rsvd0[2];
__le32 eht_cap_phy_info_2ghz[WMI_MAX_EHTCAP_PHY_SIZE];
__le32 eht_cap_phy_info_5ghz[WMI_MAX_EHTCAP_PHY_SIZE];
struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz;
struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz;
__le32 eht_cap_info_internal;
__le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE];
__le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE];
} __packed;
/* 2 word representation of MAC addr */
struct ath12k_wmi_mac_addr_params {
u8 addr[ETH_ALEN];
@@ -2705,6 +2775,11 @@ struct wmi_vdev_start_request_cmd {
__le32 he_ops;
__le32 cac_duration_ms;
__le32 regdomain;
__le32 min_data_rate;
__le32 mbssid_flags;
__le32 mbssid_tx_vdev_id;
__le32 eht_ops;
__le32 punct_bitmap;
} __packed;
#define MGMT_TX_DL_FRM_LEN 64
@@ -2758,8 +2833,17 @@ enum wmi_phy_mode {
MODE_11AX_HE20_2G = 21,
MODE_11AX_HE40_2G = 22,
MODE_11AX_HE80_2G = 23,
MODE_UNKNOWN = 24,
MODE_MAX = 24
MODE_11BE_EHT20 = 24,
MODE_11BE_EHT40 = 25,
MODE_11BE_EHT80 = 26,
MODE_11BE_EHT80_80 = 27,
MODE_11BE_EHT160 = 28,
MODE_11BE_EHT160_160 = 29,
MODE_11BE_EHT320 = 30,
MODE_11BE_EHT20_2G = 31,
MODE_11BE_EHT40_2G = 32,
MODE_UNKNOWN = 33,
MODE_MAX = 33,
};
struct wmi_vdev_start_req_arg {
@@ -2795,6 +2879,10 @@ struct wmi_vdev_start_req_arg {
u32 pref_rx_streams;
u32 pref_tx_streams;
u32 num_noa_descriptors;
u32 min_data_rate;
u32 mbssid_flags;
u32 mbssid_tx_vdev_id;
u32 punct_bitmap;
};
struct ath12k_wmi_peer_create_arg {
@@ -3034,7 +3122,6 @@ enum scan_dwelltime_adaptive_mode {
#define WLAN_SCAN_MAX_NUM_SSID 10
#define WLAN_SCAN_MAX_NUM_BSSID 10
#define WLAN_SCAN_MAX_NUM_CHANNELS 40
struct ath12k_wmi_element_info_arg {
u32 len;
@@ -3243,7 +3330,7 @@ struct ath12k_wmi_scan_req_arg {
u32 num_bssid;
u32 num_ssids;
u32 n_probes;
u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS];
u32 *chan_list;
u32 notify_scan_events;
struct cfg80211_ssid ssid[WLAN_SCAN_MAX_NUM_SSID];
struct ath12k_wmi_mac_addr_params bssid_list[WLAN_SCAN_MAX_NUM_BSSID];
@@ -3491,6 +3578,7 @@ struct ath12k_wmi_peer_assoc_arg {
bool bw_40;
bool bw_80;
bool bw_160;
bool bw_320;
bool stbc_flag;
bool ldpc_flag;
bool static_mimops_flag;
@@ -3518,6 +3606,14 @@ struct ath12k_wmi_peer_assoc_arg {
bool twt_responder;
bool twt_requester;
struct ath12k_wmi_ppe_threshold_arg peer_ppet;
bool eht_flag;
u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE];
u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE];
u32 peer_eht_mcs_count;
u32 peer_eht_rx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet;
u32 punct_bitmap;
};
struct wmi_peer_assoc_complete_cmd {
@@ -3549,6 +3645,15 @@ struct wmi_peer_assoc_complete_cmd {
__le32 peer_he_cap_info_internal;
__le32 min_data_rate;
__le32 peer_he_caps_6ghz;
__le32 sta_type;
__le32 bss_max_idle_option;
__le32 auth_mode;
__le32 peer_flags_ext;
__le32 punct_bitmap;
__le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE];
__le32 peer_eht_ops;
struct ath12k_wmi_ppe_threshold_params peer_eht_ppet;
} __packed;
struct wmi_stop_scan_cmd {
@@ -3776,6 +3881,12 @@ struct ath12k_wmi_he_rate_set_params {
__le32 tx_mcs_set;
} __packed;
struct ath12k_wmi_eht_rate_set_params {
__le32 tlv_header;
__le32 rx_mcs_set;
__le32 tx_mcs_set;
} __packed;
#define MAX_REG_RULES 10
#define REG_ALPHA2_LEN 2
#define MAX_6G_REG_RULES 5
-2
View File
@@ -982,8 +982,6 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
ah->debug.level = ath5k_debug;
phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
if (!phydir)
return;
debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
debugfs_create_file("registers", 0400, phydir, ah, &registers_fops);
-2
View File
@@ -1793,8 +1793,6 @@ int ath6kl_debug_init_fs(struct ath6kl *ar)
{
ar->debugfs_phy = debugfs_create_dir("ath6kl",
ar->wiphy->debugfsdir);
if (!ar->debugfs_phy)
return -ENOMEM;
debugfs_create_file("tgt_stats", 0400, ar->debugfs_phy, ar,
&fops_tgt_stats);
+2 -2
View File
@@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)mem, irq);
wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
hw_name, mem, irq);
return 0;
+4 -2
View File
@@ -115,8 +115,10 @@ struct ath_tx_status {
u8 qid;
u16 desc_id;
u8 tid;
u32 ba_low;
u32 ba_high;
struct_group(ba,
u32 ba_low;
u32 ba_high;
);
u32 evm0;
u32 evm1;
u32 evm2;
+2 -2
View File
@@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->sc_ah->msi_reg = 0;
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)sc->mem, pdev->irq);
wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
hw_name, sc->mem, pdev->irq);
return 0;
+4 -2
View File
@@ -466,9 +466,11 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
*nframes = 0;
isaggr = bf_isaggr(bf);
memset(ba, 0, WME_BA_BMP_SIZE >> 3);
if (isaggr) {
seq_st = ts->ts_seqnum;
memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
}
while (bf) {
@@ -551,7 +553,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (isaggr && txok) {
if (ts->ts_flags & ATH9K_TX_BA) {
seq_st = ts->ts_seqnum;
memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
} else {
/*
* AR5416 can become deaf/mute when BA
+1 -1
View File
@@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
&s->tid_crypto_rx[tid];
struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
const u8 *pn = (u8 *)&d->mac.pn_15_0;
const u8 *pn = (u8 *)&d->mac.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,
+4 -2
View File
@@ -343,8 +343,10 @@ struct vring_rx_mac {
u32 d0;
u32 d1;
u16 w4;
u16 pn_15_0;
u32 pn_47_16;
struct_group_attr(pn, __packed,
u16 pn_15_0;
u32 pn_47_16;
);
} __packed;
/* Rx descriptor - DMA part
+1 -1
View File
@@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil,
s = &wil->sta[cid];
c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid];
cc = &c->key_id[key_id];
pn = (u8 *)&st->ext.pn_15_0;
pn = (u8 *)&st->ext.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,
+4 -2
View File
@@ -330,8 +330,10 @@ struct wil_rx_status_extension {
u32 d0;
u32 d1;
__le16 seq_num; /* only lower 12 bits */
u16 pn_15_0;
u32 pn_47_16;
struct_group_attr(pn, __packed,
u16 pn_15_0;
u32 pn_47_16;
);
} __packed;
struct wil_rx_status_extended {