diff options
Diffstat (limited to 'drivers/net/wireless')
164 files changed, 8214 insertions, 5709 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 4a006fb4d424..76efea2f1138 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -5,7 +5,7 @@ */ #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/clk.h> #include <linux/reset.h> #include "core.h" diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 139da578831a..ceb3ccbb1827 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -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> @@ -418,32 +419,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; @@ -1226,7 +1201,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; diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index bebfd342e28b..fc7c4564a715 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -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; diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 9d15b4390b9c..b04447762483 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -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); diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 5c76664ba0dd..1e488eed282b 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -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); diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index f5533630a7f9..d51a99669dd6 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -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; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 8c77ade49437..2aadf2c387b6 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -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; diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 79e2cbe82638..5fd08ffc2a9f 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -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: diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index d4eaf7d2ba84..41fad03a3025 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -9,11 +9,11 @@ #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> #include <linux/firmware.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 @@ -2079,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; @@ -2839,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; @@ -3209,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, diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h index 0909d53cefeb..b0407abf90cd 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -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 diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 2f93296db792..4389ff40b49d 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -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; diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index ffd9a2018610..67f8c140840f 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -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])) diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index d3c7c76d6b75..d661fe586651 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -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); diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 1bb9802ef569..0f2af2f14ef7 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -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)) { diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index 57f4295420bb..7b16b70df4fa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -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 diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index b510c2de1bd4..b2db0436bdde 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -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, diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 4928e4e91660..cc9a377c06fd 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -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) { @@ -3704,6 +3781,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]) { @@ -3810,6 +3891,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, @@ -4037,14 +4119,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, @@ -4053,6 +4286,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: @@ -5222,7 +5472,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 @@ -5697,6 +5947,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: diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index d89c12bfb009..8c047a9623f9 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -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 diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4b41160e5d38..ec130510aeb2 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -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, ®isters_fops); diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 433a047f3747..b837d31416df 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -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); diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9cd12b20b18d..9bfaadfa6c00 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index af44b33814dd..f03d792732da 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index a09f9d223f3d..0633589b85c2 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -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; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f6f2ab7a63ff..4e939dcac1c9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -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 diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 8dbd115a393c..2bd1163177f0 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -19,9 +19,8 @@ #include <linux/module.h> #include <linux/firmware.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/rpmsg.h> #include <linux/soc/qcom/smem_state.h> #include <linux/soc/qcom/wcnss_ctrl.h> diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 237cbd5c5060..f29ac6de7139 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -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, diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 1ae1bec1b97f..689f68d89a44 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -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 diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 201c8c35e0c9..1ba1f21ebea2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -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, diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h index c736f7413a35..ee90e225bb05 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.h +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h @@ -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 { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h index 2d08c155c23b..90b6e3982d2c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h @@ -145,14 +145,6 @@ struct si_pub { struct pci_dev; -struct gpioh_item { - void *arg; - bool level; - void (*handler) (u32 stat, void *arg); - u32 event; - struct gpioh_item *next; -}; - /* misc si info needed by some of the routines */ struct si_info { struct si_pub pub; /* back plane public state (must be first) */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c index e24228e60027..e859075db716 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c @@ -476,11 +476,9 @@ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, - u8 ba_wsize, /* negotiated ba window size (in pdu) */ uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ { struct scb_ampdu *scb_ampdu; - struct scb_ampdu_tid_ini *ini; struct ampdu_info *ampdu = wlc->ampdu; struct scb *scb = &wlc->pri_scb; scb_ampdu = &scb->scb_ampdu; @@ -491,10 +489,6 @@ brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, return; } - ini = &scb_ampdu->ini[tid]; - ini->tid = tid; - ini->scb = scb_ampdu->scb; - ini->ba_wsize = ba_wsize; scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 0bd4e679a359..543e93ec49d2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -810,7 +810,6 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, brcms_c_init_scb(scb); wl->pub->global_ampdu = &(scb->scb_ampdu); - wl->pub->global_ampdu->scb = scb; wl->pub->global_ampdu->max_pdu = 16; /* @@ -831,7 +830,6 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; - u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; @@ -863,11 +861,11 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, /* * BA window size from ADDBA response ('buf_size') defines how * many outstanding MPDUs are allowed for the BA stream by - * recipient and traffic class. 'ampdu_factor' gives maximum - * AMPDU size. + * recipient and traffic class (this is actually unused by the + * rest of the driver). 'ampdu_factor' gives maximum AMPDU size. */ spin_lock_bh(&wl->lock); - brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size, + brcms_c_ampdu_tx_operational(wl->wlc, tid, (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->deflink.ht_cap.ampdu_factor)) - 1); spin_unlock_bh(&wl->lock); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c index 11b33e78127c..b3663c5ef382 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c @@ -3147,10 +3147,8 @@ void brcms_c_init_scb(struct scb *scb) scb->flags = SCB_WMECAP | SCB_HTCAP; for (i = 0; i < NUMPRIO; i++) { scb->seqnum[i] = 0; - scb->seqctl[i] = 0xFFFF; } - scb->seqctl_nonqos = 0xFFFF; scb->magic = SCB_MAGIC; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h index 2e6a3d454ee8..1efc92fd1671 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h @@ -141,11 +141,6 @@ struct tx_power { u8 target[WL_TX_POWER_RATES]; }; -struct tx_inst_power { - u8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ - u8 txpwr_est_Pout_gofdm; /* Pwr estimate for 2.4 OFDM */ -}; - struct brcms_chanvec { u8 vec[MAXCHANNEL / NBBY]; }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h index 4da38cb4f318..bfc63b2f0537 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h @@ -297,7 +297,7 @@ struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc); void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, u16 tid); void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, - u8 ba_wsize, uint max_rx_ampdu_bytes); + uint max_rx_ampdu_bytes); int brcms_c_module_register(struct brcms_pub *pub, const char *name, struct brcms_info *hdl, int (*down_fn)(void *handle)); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h index 3a3d73699f83..d65561227da0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h @@ -36,19 +36,13 @@ /* structure to store per-tid state for the ampdu initiator */ struct scb_ampdu_tid_ini { - u8 tid; /* initiator tid for easy lookup */ /* tx retry count; indexed by seq modulo */ u8 txretry[AMPDU_TX_BA_MAX_WSIZE]; - struct scb *scb; /* backptr for easy lookup */ - u8 ba_wsize; /* negotiated ba window size (in pdu) */ }; struct scb_ampdu { - struct scb *scb; /* back pointer for easy reference */ - u8 mpdu_density; /* mpdu density */ u8 max_pdu; /* max pdus allowed in ampdu */ u8 release; /* # of mpdus released at a time */ - u16 min_len; /* min mpdu len to support the density */ u32 max_rx_ampdu_bytes; /* max ampdu rcv length; 8k, 16k, 32k, 64k */ /* @@ -64,15 +58,7 @@ struct scb_ampdu { struct scb { u32 magic; u32 flags; /* various bit flags as defined below */ - u32 flags2; /* various bit flags2 as defined below */ - u8 state; /* current state bitfield of auth/assoc process */ - u8 ea[ETH_ALEN]; /* station address */ - uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */ - u16 seqctl[NUMPRIO]; /* seqctl of last received frame (for dups) */ - /* seqctl of last received frame (for dups) for non-QoS data and - * management */ - u16 seqctl_nonqos; u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */ struct scb_ampdu scb_ampdu; /* AMPDU state including per tid info */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h index 2b0df07ced74..12a0df5b4e98 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h @@ -288,15 +288,6 @@ struct tx_status; struct d11rxhdr; struct txpwr_limits; -/* iovar structure */ -struct brcmu_iovar { - const char *name; /* name for lookup and display */ - u16 varid; /* id for switch */ - u16 flags; /* driver-specific flag bits */ - u16 type; /* base type of argument */ - u16 minlen; /* min length for buffer vars */ -}; - /* brcm_msg_level is a bit vector with defs in defs.h */ extern u32 brcm_msg_level; diff --git a/drivers/net/wireless/intersil/orinoco/airport.c b/drivers/net/wireless/intersil/orinoco/airport.c index a890bfa0d5cc..45ac00fdafa5 100644 --- a/drivers/net/wireless/intersil/orinoco/airport.c +++ b/drivers/net/wireless/intersil/orinoco/airport.c @@ -18,7 +18,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <asm/pmac_feature.h> #include "orinoco.h" diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index a63c5e622ee3..524034699972 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -101,7 +101,7 @@ MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); struct if_sdio_packet { - struct if_sdio_packet *next; + struct list_head list; u16 nb; u8 buffer[] __aligned(4); }; @@ -119,10 +119,11 @@ struct if_sdio_card { u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; - struct if_sdio_packet *packets; + struct list_head packets; struct workqueue_struct *workqueue; struct work_struct packet_worker; + struct work_struct reset_worker; u8 rx_unit; }; @@ -404,9 +405,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) while (1) { spin_lock_irqsave(&card->lock, flags); - packet = card->packets; + packet = list_first_entry_or_null(&card->packets, + struct if_sdio_packet, list); if (packet) - card->packets = packet->next; + list_del(&packet->list); spin_unlock_irqrestore(&card->lock, flags); if (!packet) @@ -909,7 +911,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, { int ret; struct if_sdio_card *card; - struct if_sdio_packet *packet, *cur; + struct if_sdio_packet *packet; u16 size; unsigned long flags; @@ -934,7 +936,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv, goto out; } - packet->next = NULL; packet->nb = size; /* @@ -949,14 +950,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, spin_lock_irqsave(&card->lock, flags); - if (!card->packets) - card->packets = packet; - else { - cur = card->packets; - while (cur->next) - cur = cur->next; - cur->next = packet; - } + list_add_tail(&packet->list, &card->packets); switch (type) { case MVMS_CMD: @@ -1029,10 +1023,19 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) } -static struct mmc_host *reset_host; - static void if_sdio_reset_card_worker(struct work_struct *work) { + int ret; + const char *name; + struct device *dev; + struct if_sdio_card *card; + struct mmc_host *reset_host; + + card = container_of(work, struct if_sdio_card, reset_worker); + reset_host = card->func->card->host; + name = card->priv->dev->name; + dev = &card->func->dev; + /* * The actual reset operation must be run outside of lbs_thread. This * is because mmc_remove_host() will cause the device to be instantly @@ -1043,21 +1046,19 @@ static void if_sdio_reset_card_worker(struct work_struct *work) * instance for that reason. */ - pr_info("Resetting card..."); + dev_info(dev, "resetting card %s...", name); mmc_remove_host(reset_host); - mmc_add_host(reset_host); + ret = mmc_add_host(reset_host); + if (ret) + dev_err(dev, "%s: can't add mmc host, error %d\n", name, ret); } -static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker); static void if_sdio_reset_card(struct lbs_private *priv) { struct if_sdio_card *card = priv->card; - if (work_pending(&card_reset_work)) - return; - - reset_host = card->func->card->host; - schedule_work(&card_reset_work); + if (!work_pending(&card->reset_worker)) + schedule_work(&card->reset_worker); } static int if_sdio_power_save(struct lbs_private *priv) @@ -1137,7 +1138,7 @@ static int if_sdio_probe(struct sdio_func *func, struct lbs_private *priv; int ret, i; unsigned int model; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; for (i = 0;i < func->card->num_info;i++) { if (sscanf(func->card->info[i], @@ -1178,11 +1179,15 @@ static int if_sdio_probe(struct sdio_func *func, } spin_lock_init(&card->lock); + INIT_LIST_HEAD(&card->packets); + card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0); if (unlikely(!card->workqueue)) { ret = -ENOMEM; goto err_queue; } + + INIT_WORK(&card->reset_worker, if_sdio_reset_card_worker); INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); init_waitqueue_head(&card->pwron_waitq); @@ -1233,13 +1238,12 @@ err_activate_card: flush_workqueue(card->workqueue); lbs_remove_card(priv); free: + cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); err_queue: - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); @@ -1249,7 +1253,7 @@ err_queue: static void if_sdio_remove(struct sdio_func *func) { struct if_sdio_card *card; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; card = sdio_get_drvdata(func); @@ -1277,13 +1281,12 @@ static void if_sdio_remove(struct sdio_func *func) lbs_stop_card(card->priv); lbs_remove_card(card->priv); + cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); } @@ -1403,8 +1406,6 @@ static void __exit if_sdio_exit_module(void) /* Set the flag as user is removing this module. */ user_rmmod = 1; - cancel_work_sync(&card_reset_work); - sdio_unregister_driver(&if_sdio_driver); } diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index 1225fc0e3352..8690b0114e23 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -76,16 +76,13 @@ struct if_spi_card { static void free_if_spi_card(struct if_spi_card *card) { - struct list_head *cursor, *next; - struct if_spi_packet *packet; + struct if_spi_packet *packet, *tmp; - list_for_each_safe(cursor, next, &card->cmd_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); + list_for_each_entry_safe(packet, tmp, &card->cmd_packet_list, list) { list_del(&packet->list); kfree(packet); } - list_for_each_safe(cursor, next, &card->data_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); + list_for_each_entry_safe(packet, tmp, &card->data_packet_list, list) { list_del(&packet->list); kfree(packet); } @@ -829,11 +826,16 @@ static void if_spi_e2h(struct if_spi_card *card) goto out; /* re-enable the card event interrupt */ - spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, - ~IF_SPI_HICU_CARD_EVENT); + err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, + ~IF_SPI_HICU_CARD_EVENT); + if (err) + goto out; /* generate a card interrupt */ - spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT); + err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, + IF_SPI_CIC_HOST_EVENT); + if (err) + goto out; lbs_queue_event(priv, cause & 0xff); out: diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c index 90ffe8d1e0e8..2dd635935448 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.c +++ b/drivers/net/wireless/marvell/libertas/mesh.c @@ -188,8 +188,11 @@ static ssize_t anycast_mask_store(struct device *dev, uint32_t datum; int ret; + ret = kstrtouint(buf, 16, &datum); + if (ret) + return ret; + memset(&mesh_access, 0, sizeof(mesh_access)); - sscanf(buf, "%x", &datum); mesh_access.data[0] = cpu_to_le32(datum); ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); @@ -241,15 +244,14 @@ static ssize_t prb_rsp_limit_store(struct device *dev, int ret; unsigned long retry_limit; - memset(&mesh_access, 0, sizeof(mesh_access)); - mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); - ret = kstrtoul(buf, 10, &retry_limit); if (ret) return ret; if (retry_limit > 15) return -ENOTSUPP; + memset(&mesh_access, 0, sizeof(mesh_access)); + mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); mesh_access.data[1] = cpu_to_le32(retry_limit); ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, @@ -285,9 +287,12 @@ static ssize_t lbs_mesh_store(struct device *dev, const char *buf, size_t count) { struct lbs_private *priv = to_net_dev(dev)->ml_priv; - int enable; + int ret, enable; + + ret = kstrtoint(buf, 16, &enable); + if (ret) + return ret; - sscanf(buf, "%x", &enable); enable = !!enable; if (enable == !!priv->mesh_dev) return count; @@ -387,11 +392,13 @@ static ssize_t bootflag_store(struct device *dev, struct device_attribute *attr, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 1)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 1) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); cmd.length = cpu_to_le16(sizeof(uint32_t)); ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, @@ -438,11 +445,14 @@ static ssize_t boottime_store(struct device *dev, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 255) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); + /* A too small boot time will result in the device booting into * standalone (no-host) mode before the host can take control of it, * so the change will be hard to revert. This may be a desired @@ -497,11 +507,13 @@ static ssize_t channel_store(struct device *dev, struct device_attribute *attr, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if (ret != 1 || datum < 1 || datum > 11) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum < 1 || datum > 11) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); cmd.length = cpu_to_le16(sizeof(uint16_t)); ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, @@ -626,11 +638,14 @@ static ssize_t protocol_id_store(struct device *dev, uint32_t datum; int ret; - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) + ret = kstrtouint(buf, 10, &datum); + if (ret) + return ret; + if (datum > 255) return -EINVAL; + memset(&cmd, 0, sizeof(cmd)); + /* fetch all other Information Element parameters */ ret = mesh_get_default_parameters(dev, &defs); diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 813d1cbebe19..ba4e29713a8c 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4395,6 +4395,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) WIPHY_FLAG_AP_UAPSD | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_NETNS_OK | WIPHY_FLAG_PS_ON_BY_DEFAULT; if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 1cd9d20cca16..d99127dc466e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -724,14 +724,9 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter, /* Override default firmware with manufacturing one if * manufacturing mode is enabled */ - if (mfg_mode) { - if (strlcpy(adapter->fw_name, MFG_FIRMWARE, - sizeof(adapter->fw_name)) >= - sizeof(adapter->fw_name)) { - pr_err("%s: fw_name too long!\n", __func__); - return -1; - } - } + if (mfg_mode) + strscpy(adapter->fw_name, MFG_FIRMWARE, + sizeof(adapter->fw_name)); if (req_fw_nowait) { ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name, diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 9a698a16a8f3..6697132ecc97 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -189,6 +189,8 @@ static int mwifiex_pcie_probe_of(struct device *dev) } static void mwifiex_pcie_work(struct work_struct *work); +static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter); +static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter); static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, @@ -792,14 +794,15 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) if (!skb) { mwifiex_dbg(adapter, ERROR, "Unable to allocate skb for RX ring.\n"); - kfree(card->rxbd_ring_vbase); return -ENOMEM; } if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_RX_DATA_BUF_SIZE, - DMA_FROM_DEVICE)) - return -1; + DMA_FROM_DEVICE)) { + kfree_skb(skb); + return -ENOMEM; + } buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); @@ -849,7 +852,6 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) if (!skb) { mwifiex_dbg(adapter, ERROR, "Unable to allocate skb for EVENT buf.\n"); - kfree(card->evtbd_ring_vbase); return -ENOMEM; } skb_put(skb, MAX_EVENT_SIZE); @@ -857,8 +859,7 @@ static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, DMA_FROM_DEVICE)) { kfree_skb(skb); - kfree(card->evtbd_ring_vbase); - return -1; + return -ENOMEM; } buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); @@ -1058,6 +1059,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) */ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) { + int ret; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -1096,7 +1098,10 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->rxbd_ring_pbase >> 32), card->rxbd_ring_size); - return mwifiex_init_rxq_ring(adapter); + ret = mwifiex_init_rxq_ring(adapter); + if (ret) + mwifiex_pcie_delete_rxbd_ring(adapter); + return ret; } /* @@ -1127,6 +1132,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) */ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) { + int ret; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; @@ -1161,7 +1167,10 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->evtbd_ring_pbase >> 32), card->evtbd_ring_size); - return mwifiex_pcie_init_evt_ring(adapter); + ret = mwifiex_pcie_init_evt_ring(adapter); + if (ret) + mwifiex_pcie_delete_evtbd_ring(adapter); + return ret; } /* diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index 13659b02ba88..f2899d53a43f 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -86,6 +86,14 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; + if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { + mwifiex_dbg(priv->adapter, ERROR, + "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", + skb->len, rx_pkt_off); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, sizeof(bridge_tunnel_header))) || (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, @@ -194,7 +202,8 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; - if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { + if ((rx_pkt_offset + rx_pkt_length) > skb->len || + sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) { mwifiex_dbg(adapter, ERROR, "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len, rx_pkt_offset, rx_pkt_length); diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c index 97bb87c3676b..6c60621b6ccc 100644 --- a/drivers/net/wireless/marvell/mwifiex/tdls.c +++ b/drivers/net/wireless/marvell/mwifiex/tdls.c @@ -735,6 +735,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, int ret; u16 capab; struct ieee80211_ht_cap *ht_cap; + unsigned int extra; u8 radio, *pos; capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; @@ -753,7 +754,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, switch (action_code) { case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1); + /* See the layout of 'struct ieee80211_mgmt'. */ + extra = sizeof(mgmt->u.action.u.tdls_discover_resp) + + sizeof(mgmt->u.action.category); + skb_put(skb, extra); mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES; @@ -762,8 +766,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, mgmt->u.action.u.tdls_discover_resp.capability = cpu_to_le16(capab); /* move back for addr4 */ - memmove(pos + ETH_ALEN, &mgmt->u.action.category, - sizeof(mgmt->u.action.u.tdls_discover_resp)); + memmove(pos + ETH_ALEN, &mgmt->u.action, extra); /* init address 4 */ eth_broadcast_addr(pos); diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c index e495f7eaea03..04ff051f5d18 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c @@ -103,6 +103,15 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, return; } + if (sizeof(*rx_pkt_hdr) + + le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) { + mwifiex_dbg(adapter, ERROR, + "wrong rx packet offset: len=%d,rx_pkt_offset=%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + } + if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, sizeof(bridge_tunnel_header))) || (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, @@ -367,6 +376,16 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); + if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) + + sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) { + mwifiex_dbg(adapter, ERROR, + "wrong rx packet for struct ethhdr: len=%d, offset=%d\n", + skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset)); + priv->stats.rx_dropped++; + dev_kfree_skb_any(skb); + return 0; + } + ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source); if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wireless/marvell/mwifiex/util.c index 94c2d219835d..745b1d925b21 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -393,11 +393,15 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, } rx_pd = (struct rxpd *)skb->data; + pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) { + mwifiex_dbg(priv->adapter, ERROR, "invalid rx_pkt_length"); + return -1; + } skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); skb_pull(skb, sizeof(pkt_len)); - - pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + pkt_len -= sizeof(pkt_len); ieee_hdr = (void *)skb->data; if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { @@ -410,7 +414,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, skb->data + sizeof(struct ieee80211_hdr), pkt_len - sizeof(struct ieee80211_hdr)); - pkt_len -= ETH_ALEN + sizeof(pkt_len); + pkt_len -= ETH_ALEN; rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 18152c16c36f..7eb1b0b63d11 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -29,6 +29,14 @@ config MT76_CONNAC_LIB tristate select MT76_CORE +config MT792x_LIB + tristate + select MT76_CONNAC_LIB + +config MT792x_USB + tristate + select MT76_USB + source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 84c99b7e57f9..85c4799be954 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -5,6 +5,8 @@ obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o +obj-$(CONFIG_MT792x_LIB) += mt792x-lib.o +obj-$(CONFIG_MT792x_USB) += mt792x-usb.o mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ @@ -19,6 +21,7 @@ mt76-sdio-y := sdio.o sdio_txrx.o CFLAGS_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src) CFLAGS_mt76x02_trace.o := -I$(src) +CFLAGS_mt792x_trace.o := -I$(src) mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \ @@ -27,7 +30,12 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o + +mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \ + mt792x_debugfs.o mt792x_dma.o +mt792x-lib-$(CONFIG_ACPI) += mt792x_acpi_sar.o +mt792x-usb-y := mt792x_usb.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 465190ebaf1c..05d9ab3ce819 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -466,6 +466,9 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf buf = {}; dma_addr_t addr; + if (test_bit(MT76_MCU_RESET, &dev->phy.state)) + goto error; + if (q->queued + 1 >= q->ndesc - 1) goto error; @@ -507,6 +510,9 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, dma_addr_t addr; u8 *txwi; + if (test_bit(MT76_RESET, &dev->phy.state)) + goto free_skb; + t = mt76_get_txwi(dev); if (!t) goto free_skb; diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index dce851d42e08..36564930aef1 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -6,34 +6,39 @@ #include <linux/of_net.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> +#include <linux/nvmem-consumer.h> #include <linux/etherdevice.h> #include "mt76.h" -int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) +static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len) { -#if defined(CONFIG_OF) && defined(CONFIG_MTD) struct device_node *np = dev->dev->of_node; - struct mtd_info *mtd; - const __be32 *list; const void *data; - const char *part; - phandle phandle; int size; - size_t retlen; - int ret; - if (!np) + data = of_get_property(np, "mediatek,eeprom-data", &size); + if (!data) return -ENOENT; - data = of_get_property(np, "mediatek,eeprom-data", &size); - if (data) { - if (size > len) - return -EINVAL; + if (size > len) + return -EINVAL; - memcpy(eep, data, size); + memcpy(eep, data, size); - return 0; - } + return 0; +} + +static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len) +{ +#ifdef CONFIG_MTD + struct device_node *np = dev->dev->of_node; + struct mtd_info *mtd; + const __be32 *list; + const char *part; + phandle phandle; + size_t retlen; + int size; + int ret; list = of_get_property(np, "mediatek,mtd-eeprom", &size); if (!list) @@ -100,6 +105,56 @@ out_put_node: return -ENOENT; #endif } + +static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int len) +{ + struct device_node *np = dev->dev->of_node; + struct nvmem_cell *cell; + const void *data; + size_t retlen; + int ret = 0; + + cell = of_nvmem_cell_get(np, "eeprom"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + data = nvmem_cell_read(cell, &retlen); + nvmem_cell_put(cell); + + if (IS_ERR(data)) + return PTR_ERR(data); + + if (retlen < len) { + ret = -EINVAL; + goto exit; + } + + memcpy(eep, data, len); + +exit: + kfree(data); + + return ret; +} + +int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len) +{ + struct device_node *np = dev->dev->of_node; + int ret; + + if (!np) + return -ENOENT; + + ret = mt76_get_of_eeprom_data(dev, eep, len); + if (!ret) + return 0; + + ret = mt76_get_of_epprom_from_mtd(dev, eep, offset, len); + if (!ret) + return 0; + + return mt76_get_of_epprom_from_nvmem(dev, eep, len); +} EXPORT_SYMBOL_GPL(mt76_get_of_eeprom); void diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 467afef98ba2..d158320bc15d 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -4,7 +4,6 @@ */ #include <linux/sched.h> #include <linux/of.h> -#include <net/page_pool.h> #include "mt76.h" #define CHAN2G(_idx, _freq) { \ @@ -76,6 +75,7 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = { CHAN5G(165, 5825), CHAN5G(169, 5845), CHAN5G(173, 5865), + CHAN5G(177, 5885), }; static const struct ieee80211_channel mt76_channels_6ghz[] = { @@ -660,6 +660,8 @@ mt76_alloc_device(struct device *pdev, unsigned int size, idr_init(&dev->rx_token); INIT_LIST_HEAD(&dev->wcid_list); + INIT_LIST_HEAD(&dev->sta_poll_list); + spin_lock_init(&dev->sta_poll_lock); INIT_LIST_HEAD(&dev->txwi_cache); INIT_LIST_HEAD(&dev->rxwi_cache); @@ -1743,6 +1745,9 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi, for (i = 0; i < (eht ? 14 : 12); i++) data[ei++] += stats->tx_mcs[i]; + for (i = 0; i < 4; i++) + data[ei++] += stats->tx_nss[i]; + wi->worker_stat_count = ei - wi->initial_stat_idx; } EXPORT_SYMBOL_GPL(mt76_ethtool_worker); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6b07b8fafec2..e8757865a3d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -15,6 +15,7 @@ #include <linux/average.h> #include <linux/soc/mediatek/mtk_wed.h> #include <net/mac80211.h> +#include <net/page_pool/helpers.h> #include "util.h" #include "testmode.h" @@ -277,7 +278,7 @@ struct mt76_sta_stats { u64 tx_mcs[16]; /* mcs idx */ u64 tx_bytes; /* WED TX */ - u32 tx_packets; + u32 tx_packets; /* unit: MSDU */ u32 tx_retries; u32 tx_failed; /* WED RX */ @@ -316,6 +317,7 @@ struct mt76_wcid { int inactive_count; struct rate_info rate; + unsigned long ampdu_state; u16 idx; u8 hw_key_idx; @@ -336,6 +338,8 @@ struct mt76_wcid { struct idr pktid; struct mt76_sta_stats stats; + + struct list_head poll_list; }; struct mt76_txq { @@ -702,6 +706,9 @@ struct mt76_vif { u8 wmm_idx; u8 scan_seq_num; u8 cipher; + u8 basic_rates_idx; + u8 mcast_rates_idx; + u8 beacon_rates_idx; }; struct mt76_phy { @@ -823,6 +830,9 @@ struct mt76_dev { struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; struct list_head wcid_list; + struct list_head sta_poll_list; + spinlock_t sta_poll_lock; + u32 rev; struct tasklet_struct pre_tbtt_tasklet; @@ -857,6 +867,101 @@ struct mt76_dev { }; }; +/* per-phy stats. */ +struct mt76_mib_stats { + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; + u32 tx_bf_cnt; + u32 tx_mu_bf_cnt; + u32 tx_mu_mpdu_cnt; + u32 tx_mu_acked_mpdu_cnt; + u32 tx_su_acked_mpdu_cnt; + u32 tx_bf_ibf_ppdu_cnt; + u32 tx_bf_ebf_ppdu_cnt; + + u32 tx_bf_rx_fb_all_cnt; + u32 tx_bf_rx_fb_eht_cnt; + u32 tx_bf_rx_fb_he_cnt; + u32 tx_bf_rx_fb_vht_cnt; + u32 tx_bf_rx_fb_ht_cnt; + + u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ + u32 tx_bf_rx_fb_nc_cnt; + u32 tx_bf_rx_fb_nr_cnt; + u32 tx_bf_fb_cpl_cnt; + u32 tx_bf_fb_trig_cnt; + + u32 tx_ampdu_cnt; + u32 tx_stop_q_empty_cnt; + u32 tx_mpdu_attempts_cnt; + u32 tx_mpdu_success_cnt; + u32 tx_pkt_ebf_cnt; + u32 tx_pkt_ibf_cnt; + + u32 tx_rwp_fail_cnt; + u32 tx_rwp_need_cnt; + + /* rx stats */ + u32 rx_fifo_full_cnt; + u32 channel_idle_cnt; + u32 primary_cca_busy_time; + u32 secondary_cca_busy_time; + u32 primary_energy_detect_time; + u32 cck_mdrdy_time; + u32 ofdm_mdrdy_time; + u32 green_mdrdy_time; + u32 rx_vector_mismatch_cnt; + u32 rx_delimiter_fail_cnt; + u32 rx_mrdy_cnt; + u32 rx_len_mismatch_cnt; + u32 rx_mpdu_cnt; + u32 rx_ampdu_cnt; + u32 rx_ampdu_bytes_cnt; + u32 rx_ampdu_valid_subframe_cnt; + u32 rx_ampdu_valid_subframe_bytes_cnt; + u32 rx_pfdrop_cnt; + u32 rx_vec_queue_overflow_drop_cnt; + u32 rx_ba_cnt; + + u32 tx_amsdu[8]; + u32 tx_amsdu_cnt; + + /* mcu_muru_stats */ + u32 dl_cck_cnt; + u32 dl_ofdm_cnt; + u32 dl_htmix_cnt; + u32 dl_htgf_cnt; + u32 dl_vht_su_cnt; + u32 dl_vht_2mu_cnt; + u32 dl_vht_3mu_cnt; + u32 dl_vht_4mu_cnt; + u32 dl_he_su_cnt; + u32 dl_he_ext_su_cnt; + u32 dl_he_2ru_cnt; + u32 dl_he_2mu_cnt; + u32 dl_he_3ru_cnt; + u32 dl_he_3mu_cnt; + u32 dl_he_4ru_cnt; + u32 dl_he_4mu_cnt; + u32 dl_he_5to8ru_cnt; + u32 dl_he_9to16ru_cnt; + u32 dl_he_gtr16ru_cnt; + + u32 ul_hetrig_su_cnt; + u32 ul_hetrig_2ru_cnt; + u32 ul_hetrig_3ru_cnt; + u32 ul_hetrig_4ru_cnt; + u32 ul_hetrig_5to8ru_cnt; + u32 ul_hetrig_9to16ru_cnt; + u32 ul_hetrig_gtr16ru_cnt; + u32 ul_hetrig_2mu_cnt; + u32 ul_hetrig_3mu_cnt; + u32 ul_hetrig_4mu_cnt; +}; + struct mt76_power_limits { s8 cck[4]; s8 ofdm[8]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c index b65b0a88c1de..888678732f29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -161,7 +161,8 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) return; } - dev->mt76.beacon_int = intval; + if (intval) + dev->mt76.beacon_int = intval; mt76_wr(dev, MT_TBTT, FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c index 9a2e632d577a..0762de3ce5ac 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -500,8 +500,6 @@ int mt7603_register_device(struct mt7603_dev *dev) bus_ops->rmw = mt7603_rmw; dev->mt76.bus = bus_ops; - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); spin_lock_init(&dev->ps_lock); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index 12e0af52082a..99ae080502d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -178,8 +178,9 @@ mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled) mt76_wr(dev, addr + 3 * 4, val); } -void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) +void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort) { + u32 flush_mask; int i, port, queue; if (abort) { @@ -195,6 +196,18 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN | FIELD_PREP(MT_TX_ABORT_WCID, idx)); + flush_mask = MT_WF_ARB_TX_FLUSH_AC0 | + MT_WF_ARB_TX_FLUSH_AC1 | + MT_WF_ARB_TX_FLUSH_AC2 | + MT_WF_ARB_TX_FLUSH_AC3; + flush_mask <<= mac_idx; + + mt76_wr(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask); + mt76_poll(dev, MT_WF_ARB_TX_FLUSH_0, flush_mask, 0, 20000); + mt76_wr(dev, MT_WF_ARB_TX_START_0, flush_mask); + + mt76_wr(dev, MT_TX_ABORT, 0); + for (i = 0; i < 4; i++) { mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) | @@ -202,13 +215,11 @@ void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); - mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 15000); + mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000); } WARN_ON_ONCE(mt76_rr(dev, MT_DMA_FQCR0) & MT_DMA_FQCR0_BUSY); - mt76_wr(dev, MT_TX_ABORT, 0); - mt7603_wtbl_set_skip_tx(dev, idx, false); } @@ -245,7 +256,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); if (enabled) - mt7603_filter_tx(dev, idx, false); + mt7603_filter_tx(dev, sta->vif->idx, idx, false); addr = mt7603_wtbl1_addr(idx); mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); @@ -412,16 +423,16 @@ void mt7603_mac_sta_poll(struct mt7603_dev *dev) while (1) { bool clear = false; - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&dev->sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&dev->mt76.sta_poll_list)) { + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } - msta = list_first_entry(&dev->sta_poll_list, struct mt7603_sta, - poll_list); - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + msta = list_first_entry(&dev->mt76.sta_poll_list, + struct mt7603_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7603_wtbl4_addr(msta->wcid.idx); for (i = 0; i < 4; i++) { @@ -1267,10 +1278,10 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) msta = container_of(wcid, struct mt7603_sta, wcid); sta = wcid_to_sta(wcid); - if (list_empty(&msta->poll_list)) { - spin_lock_bh(&dev->sta_poll_lock); - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) { + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 1b1358c6bb46..c213fd2a5216 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -66,9 +66,10 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; dev->mt76.vif_mask |= BIT_ULL(mvif->idx); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.hw_key_idx = -1; + mvif->sta.vif = mvif; mt76_packet_id_init(&mvif->sta.wcid); eth_broadcast_addr(bc_addr); @@ -100,10 +101,10 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mutex_lock(&dev->mt76.mutex); dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx); @@ -351,12 +352,13 @@ mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); __skb_queue_head_init(&msta->psq); msta->ps = ~0; msta->smps = ~0; msta->wcid.sta = 1; msta->wcid.idx = idx; + msta->vif = mvif; mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); mt7603_wtbl_set_ps(dev, msta, false); @@ -380,18 +382,19 @@ mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; spin_lock_bh(&dev->ps_lock); __skb_queue_purge(&msta->psq); - mt7603_filter_tx(dev, wcid->idx, true); + mt7603_filter_tx(dev, mvif->idx, wcid->idx, true); spin_unlock_bh(&dev->ps_lock); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); mt7603_wtbl_clear(dev, wcid->idx); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h index 7c3be596da09..9e58df7042ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -64,7 +64,6 @@ struct mt7603_sta { struct mt7603_vif *vif; - struct list_head poll_list; u32 tx_airtime_ac[4]; struct sk_buff_head psq; @@ -110,9 +109,6 @@ struct mt7603_dev { u32 rxfilter; - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - struct mt7603_sta global_sta; u32 agc0, agc3; @@ -234,7 +230,7 @@ void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, bool enabled); void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, bool enabled); -void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort); +void mt7603_filter_tx(struct mt7603_dev *dev, int mac_idx, int idx, bool abort); int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h index 3b901090b29c..a39c9a0fcb1c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -309,6 +309,13 @@ enum { #define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110) #define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114) +#define MT_WF_ARB_TX_FLUSH_AC0 BIT(0) +#define MT_WF_ARB_TX_FLUSH_AC1 BIT(5) +#define MT_WF_ARB_TX_FLUSH_AC2 BIT(10) +#define MT_WF_ARB_TX_FLUSH_AC3 BIT(16) +#define MT_WF_ARB_TX_FLUSH_AC4 BIT(21) +#define MT_WF_ARB_TX_FLUSH_AC5 BIT(26) + #define MT_WF_ARB_BCN_START MT_WF_ARB(0x118) #define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n)) #define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 621e69f07e3c..18a50ccff106 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -397,6 +397,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + if (!is_mt7622(&phy->dev->mt76)) + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); @@ -626,8 +628,6 @@ void mt7615_init_device(struct mt7615_dev *dev) INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work); skb_queue_head_init(&dev->phy.scan_event_list); skb_queue_head_init(&dev->coredump.msg_list); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); init_waitqueue_head(&dev->phy.roc_wait); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 64002484ccad..7ba789834e8d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -387,10 +387,11 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) struct mt7615_sta *msta; msta = container_of(status->wcid, struct mt7615_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask && @@ -905,19 +906,19 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) int i; INIT_LIST_HEAD(&sta_poll_list); - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); while (!list_empty(&sta_poll_list)) { bool clear = false; msta = list_first_entry(&sta_poll_list, struct mt7615_sta, - poll_list); + wcid.poll_list); - spin_lock_bh(&dev->sta_poll_lock); - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; @@ -1514,10 +1515,10 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) msta = container_of(wcid, struct mt7615_sta, wcid); sta = wcid_to_sta(wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data)) goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index dadb13f2ca09..200b1752ca77 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -222,7 +222,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, idx = MT7615_WTBL_RESERVED - mvif->mt76.idx; - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -274,10 +274,10 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, mt7615_mutex_release(dev); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid); } @@ -552,6 +552,32 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, mt7615_mutex_release(dev); } +static void +mt7615_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + u8 i, band = mvif->mt76.band_idx; + u32 *mu; + + mu = (u32 *)info->mu_group.membership; + for (i = 0; i < WLAN_MEMBERSHIP_LEN / sizeof(*mu); i++) { + if (is_mt7663(&dev->mt76)) + mt76_wr(dev, MT7663_WF_PHY_GID_TAB_VLD(band, i), mu[i]); + else + mt76_wr(dev, MT_WF_PHY_GID_TAB_VLD(band, i), mu[i]); + } + + mu = (u32 *)info->mu_group.position; + for (i = 0; i < WLAN_USER_POSITION_LEN / sizeof(*mu); i++) { + if (is_mt7663(&dev->mt76)) + mt76_wr(dev, MT7663_WF_PHY_GID_TAB_POS(band, i), mu[i]); + else + mt76_wr(dev, MT_WF_PHY_GID_TAB_POS(band, i), mu[i]); + } +} + static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -600,6 +626,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7615_mac_set_beacon_filter(phy, vif, vif->cfg.assoc); + if (changed & BSS_CHANGED_MU_GROUPS) + mt7615_update_mu_group(hw, vif, info); + mt7615_mutex_release(dev); } @@ -628,7 +657,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -676,10 +705,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mt7615_mcu_add_bss_info(phy, vif, sta, false); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); mt76_connac_power_save_sched(phy->mt76, &dev->pm); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 582d1b5b7cb3..a20322aae967 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -125,7 +125,6 @@ struct mt7615_sta { struct mt7615_vif *vif; - struct list_head poll_list; u32 airtime_ac[8]; struct ieee80211_tx_rate rates[4]; @@ -262,9 +261,6 @@ struct mt7615_dev { wait_queue_head_t reset_wait; u32 reset_state; - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - struct { u8 n_pulses; u32 period; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h index d3eb49d83b98..9be5a58a4e6d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 7cecb22c569e..806b3887c541 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -212,6 +212,15 @@ enum mt7615_reg_base { #define MT7663_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0224 + ((_phy) << 12)) +#define MT_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \ + ((_phy) << 9)) +#define MT7663_WF_PHY_GID_TAB_VLD(_phy, i) MT_WF_PHY(0x0254 + (i) * 4 + \ + ((_phy) << 12)) +#define MT_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \ + ((_phy) << 9)) +#define MT7663_WF_PHY_GID_TAB_POS(_phy, i) MT_WF_PHY(0x025c + (i) * 4 + \ + ((_phy) << 12)) + #define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c) #define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \ GENMASK(28, 20)) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h index 15653b274f83..22878f088804 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h @@ -197,11 +197,21 @@ static inline bool is_mt7916(struct mt76_dev *dev) return mt76_chip(dev) == 0x7906; } +static inline bool is_mt7981(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7981; +} + static inline bool is_mt7986(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7986; } +static inline bool is_mt798x(struct mt76_dev *dev) +{ + return is_mt7981(dev) || is_mt7986(dev); +} + static inline bool is_mt7996(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7990; @@ -409,5 +419,13 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, struct mt76_rx_status *status, struct ieee80211_supported_band *sband, __le32 *rxv, u8 *mode); - +void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi); +void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, + struct list_head *free_list); +void mt76_connac2_tx_token_put(struct mt76_dev *dev); + +/* connac3 */ +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode); #endif /* __MT76_CONNAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h index fabf637bdf7f..bd2a92467a97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac2_mac.h @@ -34,7 +34,7 @@ enum { #define MT_TX_FREE_MSDU_CNT GENMASK(9, 0) #define MT_TX_FREE_WLAN_ID GENMASK(23, 14) -#define MT_TX_FREE_LATENCY GENMASK(12, 0) +#define MT_TX_FREE_COUNT GENMASK(12, 0) /* 0: success, others: dropped */ #define MT_TX_FREE_STATUS GENMASK(14, 13) #define MT_TX_FREE_MSDU_ID GENMASK(30, 16) diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c new file mode 100644 index 000000000000..73e9f283d0ae --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt76_connac.h" +#include "mt76_connac3_mac.h" +#include "dma.h" + +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ + IEEE80211_RADIOTAP_HE_##f) + +static void +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, + struct ieee80211_radiotap_he *he, + __le32 *rxv) +{ + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0; + + status->bw = RATE_INFO_BW_HE_RU; + + switch (ru) { + case 0 ... 36: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; + offs = ru; + break; + case 37 ... 52: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; + offs = ru - 37; + break; + case 53 ... 60: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; + offs = ru - 53; + break; + case 61 ... 64: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; + offs = ru - 61; + break; + case 65 ... 66: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; + offs = ru - 65; + break; + case 67: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; + break; + case 68: + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; + break; + } + + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | + le16_encode_bits(offs, + IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); +} + +#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) +static void +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static const struct ieee80211_radiotap_he_mu mu_known = { + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), + }; + struct ieee80211_radiotap_he_mu *he_mu; + + status->flag |= RX_FLAG_RADIOTAP_HE_MU; + + he_mu = skb_push(skb, sizeof(mu_known)); + memcpy(he_mu, &mu_known, sizeof(mu_known)); + + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); + if (status->he_dcm) + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); + + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | + MU_PREP(FLAGS2_SIG_B_SYMS_USERS, + le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); + + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; + + if (status->bw >= RATE_INFO_BW_40) { + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); + he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; + } + + if (status->bw >= RATE_INFO_BW_80) { + u32 ru_h, ru_l; + + he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; + + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); + } +} + +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, + u8 mode) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + static const struct ieee80211_radiotap_he known = { + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | + HE_BITS(DATA1_DATA_DCM_KNOWN) | + HE_BITS(DATA1_STBC_KNOWN) | + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), + .data2 = HE_BITS(DATA2_GI_KNOWN) | + HE_BITS(DATA2_TXBF_KNOWN) | + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN), + }; + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; + struct ieee80211_radiotap_he *he; + + status->flag |= RX_FLAG_RADIOTAP_HE; + + he = skb_push(skb, sizeof(known)); + memcpy(he, &known, sizeof(known)); + + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | + le16_encode_bits(ltf_size, + IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) + he->data5 |= HE_BITS(DATA5_TXBF); + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); + + switch (mode) { + case MT_PHY_TYPE_HE_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + break; + case MT_PHY_TYPE_HE_EXT_SU: + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | + HE_BITS(DATA1_UL_DL_KNOWN) | + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + break; + case MT_PHY_TYPE_HE_MU: + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | + HE_BITS(DATA1_UL_DL_KNOWN); + + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); + + mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv); + break; + case MT_PHY_TYPE_HE_TB: + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); + + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); + + mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); + break; + default: + break; + } +} +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h new file mode 100644 index 000000000000..68ca0844cbbf --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h @@ -0,0 +1,339 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT76_CONNAC3_MAC_H +#define __MT76_CONNAC3_MAC_H + +enum { + MT_CTX0, + MT_HIF0 = 0x0, + + MT_LMAC_AC00 = 0x0, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0, + MT_LMAC_BCN0, + MT_LMAC_PSMP0, +}; + +#define MT_CT_PARSE_LEN 72 +#define MT_CT_DMA_BUF_NUM 2 + +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_FLAG GENMASK(19, 16) +#define MT_RXD0_PKT_TYPE GENMASK(31, 27) + +#define MT_RXD0_MESH BIT(18) +#define MT_RXD0_MHCP BIT(19) +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) + +#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) +#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F +#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801 + +/* RXD DW1 */ +#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0) +#define MT_RXD1_NORMAL_GROUP_1 BIT(16) +#define MT_RXD1_NORMAL_GROUP_2 BIT(17) +#define MT_RXD1_NORMAL_GROUP_3 BIT(18) +#define MT_RXD1_NORMAL_GROUP_4 BIT(19) +#define MT_RXD1_NORMAL_GROUP_5 BIT(20) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) +#define MT_RXD1_NORMAL_CM BIT(23) +#define MT_RXD1_NORMAL_CLM BIT(24) +#define MT_RXD1_NORMAL_ICV_ERR BIT(25) +#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) +#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27) +#define MT_RXD1_NORMAL_SPP_EN BIT(29) +#define MT_RXD1_NORMAL_ADD_OM BIT(30) +#define MT_RXD1_NORMAL_SEC_DONE BIT(31) + +/* RXD DW2 */ +#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) +#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) +#define MT_RXD2_NORMAL_HDR_TRANS BIT(7) +#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13) +#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16) +#define MT_RXD2_NORMAL_MU_BAR BIT(21) +#define MT_RXD2_NORMAL_SW_BIT BIT(22) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) +#define MT_RXD2_NORMAL_INT_FRAME BIT(26) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) +#define MT_RXD2_NORMAL_BF_REPORT BIT(31) + +/* RXD DW3 */ +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) +#define MT_RXD3_NORMAL_U2M BIT(0) +#define MT_RXD3_NORMAL_HTC_VLD BIT(18) +#define MT_RXD3_NORMAL_BEACON_MC BIT(20) +#define MT_RXD3_NORMAL_BEACON_UC BIT(21) +#define MT_RXD3_NORMAL_CO_ANT BIT(22) +#define MT_RXD3_NORMAL_FCS_ERR BIT(24) +#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) + +/* RXD DW4 */ +#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) +#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) +#define MT_RXD4_MID_AMSDU_FRAME BIT(1) +#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) + +#define MT_RXV_HDR_BAND_IDX BIT(24) + +/* RXD GROUP4 */ +#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0) + +#define MT_RXD10_SEQ_CTRL GENMASK(15, 0) +#define MT_RXD10_QOS_CTL GENMASK(31, 16) + +#define MT_RXD11_HT_CONTROL GENMASK(31, 0) + +/* P-RXV */ +#define MT_PRXV_TX_RATE GENMASK(6, 0) +#define MT_PRXV_TX_DCM BIT(4) +#define MT_PRXV_TX_ER_SU_106T BIT(5) +#define MT_PRXV_NSTS GENMASK(10, 7) +#define MT_PRXV_TXBF BIT(11) +#define MT_PRXV_HT_AD_CODE BIT(12) +#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22) +#define MT_PRXV_RCPI3 GENMASK(31, 24) +#define MT_PRXV_RCPI2 GENMASK(23, 16) +#define MT_PRXV_RCPI1 GENMASK(15, 8) +#define MT_PRXV_RCPI0 GENMASK(7, 0) +#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3) +#define MT_PRXV_HT_STBC GENMASK(10, 9) +#define MT_PRXV_TX_MODE GENMASK(14, 11) +#define MT_PRXV_FRAME_MODE GENMASK(2, 0) +#define MT_PRXV_DCM BIT(5) + +/* C-RXV */ +#define MT_CRXV_HE_NUM_USER GENMASK(26, 20) +#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27) +#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30) + +#define MT_CRXV_HE_PE_DISAMBIG BIT(1) +#define MT_CRXV_HE_UPLINK BIT(2) + +#define MT_CRXV_HE_MU_AID GENMASK(27, 17) +#define MT_CRXV_HE_BEAM_CHNG BIT(29) + +#define MT_CRXV_HE_DOPPLER BIT(0) +#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10) +#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17) + +#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) +#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) +#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) +#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) + +#define MT_CRXV_HE_RU0 GENMASK(8, 0) +#define MT_CRXV_HE_RU1 GENMASK(17, 9) +#define MT_CRXV_HE_RU2 GENMASK(26, 18) +#define MT_CRXV_HE_RU3_L GENMASK(31, 27) +#define MT_CRXV_HE_RU3_H GENMASK(3, 0) + +enum tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +enum tx_pkt_type { + MT_TX_TYPE_CT, + MT_TX_TYPE_SF, + MT_TX_TYPE_CMD, + MT_TX_TYPE_FW, +}; + +enum tx_port_idx { + MT_TX_PORT_IDX_LMAC, + MT_TX_PORT_IDX_MCU +}; + +enum tx_mcu_port_q_idx { + MT_TX_MCU_PORT_RX_Q0 = 0x20, + MT_TX_MCU_PORT_RX_Q1, + MT_TX_MCU_PORT_RX_Q2, + MT_TX_MCU_PORT_RX_Q3, + MT_TX_MCU_PORT_RX_FWDL = 0x3e +}; + +enum tx_mgnt_type { + MT_TX_NORMAL, + MT_TX_TIMING, + MT_TX_ADDBA, +}; + +#define MT_CT_INFO_APPLY_TXD BIT(0) +#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) +#define MT_CT_INFO_MGMT_FRAME BIT(2) +#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) +#define MT_CT_INFO_HSR2_TX BIT(4) +#define MT_CT_INFO_FROM_HOST BIT(7) + +#define MT_TXD_SIZE (8 * 4) + +#define MT_TXD0_Q_IDX GENMASK(31, 25) +#define MT_TXD0_PKT_FMT GENMASK(24, 23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_FIXED_RATE BIT(31) +#define MT_TXD1_OWN_MAC GENMASK(30, 25) +#define MT_TXD1_TID GENMASK(24, 21) +#define MT_TXD1_BIP BIT(24) +#define MT_TXD1_ETH_802_3 BIT(20) +#define MT_TXD1_HDR_INFO GENMASK(20, 16) +#define MT_TXD1_HDR_FORMAT GENMASK(15, 14) +#define MT_TXD1_TGID GENMASK(13, 12) +#define MT_TXD1_WLAN_IDX GENMASK(11, 0) + +#define MT_TXD2_POWER_OFFSET GENMASK(31, 26) +#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_HDR_PAD GENMASK(11, 10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_OWN_MAC_MAP BIT(8) +#define MT_TXD2_BF_TYPE GENMASK(6, 7) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SW_POWER_MGMT BIT(29) +#define MT_TXD3_BA_DISABLE BIT(28) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) +#define MT_TXD3_HW_AMSDU BIT(5) +#define MT_TXD3_BCM BIT(4) +#define MT_TXD3_EEOSP BIT(3) +#define MT_TXD3_EMRD BIT(2) +#define MT_TXD3_PROTECT_FRAME BIT(1) +#define MT_TXD3_NO_ACK BIT(0) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_FL BIT(15) +#define MT_TXD5_BYPASS_TBB BIT(14) +#define MT_TXD5_BYPASS_RBB BIT(13) +#define MT_TXD5_BSS_COLOR_ZERO BIT(12) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_TX_SRC GENMASK(31, 30) +#define MT_TXD6_VTA BIT(28) +#define MT_TXD6_BW GENMASK(25, 22) +#define MT_TXD6_TX_RATE GENMASK(21, 16) +#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) +#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) +#define MT_TXD6_MSDU_CNT GENMASK(9, 4) +#define MT_TXD6_DIS_MAT BIT(3) +#define MT_TXD6_DAS BIT(2) +#define MT_TXD6_AMSDU_CAP BIT(1) + +#define MT_TXD7_TXD_LEN GENMASK(31, 30) +#define MT_TXD7_IP_SUM BIT(29) +#define MT_TXD7_DROP_BY_SDO BIT(28) +#define MT_TXD7_MAC_TXD BIT(27) +#define MT_TXD7_CTXD BIT(26) +#define MT_TXD7_CTXD_CNT GENMASK(25, 22) +#define MT_TXD7_UDP_TCP_SUM BIT(15) +#define MT_TXD7_TX_TIME GENMASK(9, 0) + +#define MT_TX_RATE_STBC BIT(14) +#define MT_TX_RATE_NSS GENMASK(13, 10) +#define MT_TX_RATE_MODE GENMASK(9, 6) +#define MT_TX_RATE_SU_EXT_TONE BIT(5) +#define MT_TX_RATE_DCM BIT(4) +/* VHT/HE only use bits 0-3 */ +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27) +#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) +#define MT_TXFREE0_RX_BYTE GENMASK(15, 0) + +#define MT_TXFREE1_VER GENMASK(18, 16) + +#define MT_TXFREE_INFO_PAIR BIT(31) +#define MT_TXFREE_INFO_HEADER BIT(30) +#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12) +#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0) +#define MT_TXFREE_INFO_COUNT GENMASK(27, 24) +#define MT_TXFREE_INFO_STAT GENMASK(29, 28) + +#define MT_TXS0_BW GENMASK(31, 29) +#define MT_TXS0_TID GENMASK(28, 26) +#define MT_TXS0_AMPDU BIT(25) +#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) +#define MT_TXS0_BA_ERROR BIT(22) +#define MT_TXS0_PS_FLAG BIT(21) +#define MT_TXS0_TXOP_TIMEOUT BIT(20) +#define MT_TXS0_BIP_ERROR BIT(19) + +#define MT_TXS0_QUEUE_TIMEOUT BIT(18) +#define MT_TXS0_RTS_TIMEOUT BIT(17) +#define MT_TXS0_ACK_TIMEOUT BIT(16) +#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) + +#define MT_TXS0_TX_STATUS_HOST BIT(15) +#define MT_TXS0_TX_STATUS_MCU BIT(14) +#define MT_TXS0_TX_RATE GENMASK(13, 0) + +#define MT_TXS1_SEQNO GENMASK(31, 20) +#define MT_TXS1_RESP_RATE GENMASK(19, 16) +#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) +#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) + +#define MT_TXS2_BF_STATUS GENMASK(31, 30) +#define MT_TXS2_BAND GENMASK(29, 28) +#define MT_TXS2_WCID GENMASK(27, 16) +#define MT_TXS2_TX_DELAY GENMASK(15, 0) + +#define MT_TXS3_PID GENMASK(31, 24) +#define MT_TXS3_RATE_STBC BIT(7) +#define MT_TXS3_FIXED_RATE BIT(6) +#define MT_TXS3_SRC GENMASK(5, 4) +#define MT_TXS3_SHARED_ANTENNA BIT(3) +#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0) + +#define MT_TXS4_TIMESTAMP GENMASK(31, 0) + +#define MT_TXS5_F0_FINAL_MPDU BIT(31) +#define MT_TXS5_F0_QOS BIT(30) +#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) +#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0) +#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24) +#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0) + +#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24) +#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16) +#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8) +#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0) +#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24) +#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0) + +#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24) +#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16) +#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8) +#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0) +#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24) +#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0) + +#endif /* __MT76_CONNAC3_MAC_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c index d39a3cc5e381..ee5177fd6dde 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c @@ -495,6 +495,7 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, BSS_CHANGED_BEACON_ENABLED)); bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); + bool amsdu_en = wcid->amsdu; if (vif) { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; @@ -521,9 +522,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + mt76_connac_lmac_mapping(skb_get_queue_mapping(skb)); - /* counting non-offloading skbs */ - wcid->stats.tx_bytes += skb->len; - wcid->stats.tx_packets++; + /* mt7915 WA only counts WED path */ + if (is_mt7915(dev) && mtk_wed_device_active(&dev->mmio.wed)) + wcid->stats.tx_packets++; } val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | @@ -554,12 +555,14 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, txwi[4] = 0; val = FIELD_PREP(MT_TXD5_PID, pid); - if (pid >= MT_PACKET_ID_FIRST) + if (pid >= MT_PACKET_ID_FIRST) { val |= MT_TXD5_TX_STATUS_HOST; + amsdu_en = amsdu_en && !is_mt7921(dev); + } txwi[5] = cpu_to_le32(val); txwi[6] = 0; - txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; + txwi[7] = amsdu_en ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0; if (is_8023) mt76_connac2_mac_write_txwi_8023(txwi, skb, wcid); @@ -606,12 +609,11 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid, txs = le32_to_cpu(txs_data[0]); /* PPDU based reporting */ - if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { + if (mtk_wed_device_active(&dev->mmio.wed) && + FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1) { stats->tx_bytes += le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_BYTE) - le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_BYTE); - stats->tx_packets += - le32_get_bits(txs_data[5], MT_TXS5_MPDU_TX_CNT); stats->tx_failed += le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT); stats->tx_retries += @@ -729,17 +731,15 @@ bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid, skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - bool noacked = !(info->flags & IEEE80211_TX_STAT_ACK); if (!(le32_to_cpu(txs_data[0]) & MT_TXS0_ACK_ERROR_MASK)) info->flags |= IEEE80211_TX_STAT_ACK; info->status.ampdu_len = 1; - info->status.ampdu_ack_len = !noacked; + info->status.ampdu_ack_len = + !!(info->flags & IEEE80211_TX_STAT_ACK); info->status.rates[0].idx = -1; - wcid->stats.tx_failed += noacked; - mt76_connac2_mac_fill_txs(dev, wcid, txs_data); mt76_tx_status_skb_done(dev, skb, &list); } @@ -1112,3 +1112,85 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev, return 0; } EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate); + +void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +{ + struct mt76_wcid *wcid; + u16 fc, tid; + u32 val; + + if (!sta || + !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) + return; + + tid = le32_get_bits(txwi[1], MT_TXD1_TID); + if (tid >= 6) /* skip VO queue */ + return; + + val = le32_to_cpu(txwi[2]); + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; + if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) + return; + + wcid = (struct mt76_wcid *)sta->drv_priv; + if (!test_and_set_bit(tid, &wcid->ampdu_state)) + ieee80211_start_tx_ba_session(sta, tid, 0); +} +EXPORT_SYMBOL_GPL(mt76_connac2_tx_check_aggr); + +void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t, + struct ieee80211_sta *sta, + struct list_head *free_list) +{ + struct mt76_wcid *wcid; + __le32 *txwi; + u16 wcid_idx; + + mt76_connac_txp_skb_unmap(dev, t); + if (!t->skb) + goto out; + + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t); + if (sta) { + wcid = (struct mt76_wcid *)sta->drv_priv; + wcid_idx = wcid->idx; + } else { + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); + wcid = rcu_dereference(dev->wcid[wcid_idx]); + + if (wcid && wcid->sta) { + sta = container_of((void *)wcid, struct ieee80211_sta, + drv_priv); + spin_lock_bh(&dev->sta_poll_lock); + if (list_empty(&wcid->poll_list)) + list_add_tail(&wcid->poll_list, + &dev->sta_poll_list); + spin_unlock_bh(&dev->sta_poll_lock); + } + } + + if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) + mt76_connac2_tx_check_aggr(sta, txwi); + + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list); +out: + t->skb = NULL; + mt76_put_txwi(dev, t); +} +EXPORT_SYMBOL_GPL(mt76_connac2_txwi_free); + +void mt76_connac2_tx_token_put(struct mt76_dev *dev) +{ + struct mt76_txwi_cache *txwi; + int id; + + spin_lock_bh(&dev->token_lock); + idr_for_each_entry(&dev->token, txwi, id) { + mt76_connac2_txwi_free(dev, txwi, NULL, NULL); + dev->token_count--; + } + spin_unlock_bh(&dev->token_lock); + idr_destroy(&dev->token); +} +EXPORT_SYMBOL_GPL(mt76_connac2_tx_token_put); diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h index ca1ce97a6d2f..4543e5bf0482 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -22,6 +22,7 @@ #define FW_START_OVERRIDE BIT(0) #define FW_START_WORKING_PDA_CR4 BIT(2) +#define FW_START_WORKING_PDA_DSP BIT(3) #define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0) #define PATCH_SEC_TYPE_MASK GENMASK(15, 0) @@ -518,7 +519,8 @@ struct sta_rec_muru { u8 uo_ra; u8 he_2x996_tone; u8 rx_t_frame_11ac; - u8 rsv[3]; + u8 rx_ctrl_frame_to_mbss; + u8 rsv[2]; } ofdma_ul; struct { @@ -998,6 +1000,7 @@ enum { MCU_EXT_EVENT_ASSERT_DUMP = 0x23, MCU_EXT_EVENT_RDD_REPORT = 0x3a, MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, + MCU_EXT_EVENT_WA_TX_STAT = 0x74, MCU_EXT_EVENT_BCC_NOTIFY = 0x75, MCU_EXT_EVENT_MURU_CTRL = 0x9f, }; @@ -1287,6 +1290,7 @@ enum { UNI_BSS_INFO_UAPSD = 19, UNI_BSS_INFO_PS = 21, UNI_BSS_INFO_BCNFT = 22, + UNI_BSS_INFO_IFS_TIME = 23, UNI_BSS_INFO_OFFLOAD = 25, UNI_BSS_INFO_MLD = 26, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 3e41d809ade3..d5db6ffd6d36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -853,7 +853,8 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, if (WARN_ON_ONCE(len > skb->len)) return -EINVAL; - pskb_trim(skb, len); + if (pskb_trim(skb, len)) + return -EINVAL; status->chains = BIT(0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h index 6a98092e996b..11d119cd0f6f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig index d710726d47bf..896ec38c23d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Kconfig @@ -14,12 +14,12 @@ config MT7915E To compile this driver as a module, choose M here. -config MT7986_WMAC - bool "MT7986 (SoC) WMAC support" +config MT798X_WMAC + bool "MT798x (SoC) WMAC support" depends on MT7915E depends on ARCH_MEDIATEK || COMPILE_TEST select REGMAP help - This adds support for the built-in WMAC on MT7986 SoC device + This adds support for the built-in WMAC on MT7981 and MT7986 SoC device which has the same feature set as a MT7915, but enables 6E support. diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile index 797ae49805c3..e0ca638c91a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7915/Makefile @@ -6,5 +6,5 @@ mt7915e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ debugfs.o mmio.o mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o -mt7915e-$(CONFIG_MT7986_WMAC) += soc.o +mt7915e-$(CONFIG_MT798X_WMAC) += soc.o mt7915e-$(CONFIG_DEV_COREDUMP) += coredump.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c b/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c index d097a56dd33d..5daf2258dfe6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/coredump.c @@ -52,7 +52,7 @@ static const struct mt7915_mem_region mt7916_mem_regions[] = { }, }; -static const struct mt7915_mem_region mt7986_mem_regions[] = { +static const struct mt7915_mem_region mt798x_mem_regions[] = { { .start = 0x00800000, .len = 0x0005ffff, @@ -92,9 +92,10 @@ mt7915_coredump_get_mem_layout(struct mt7915_dev *dev, u32 *num) case 0x7915: *num = ARRAY_SIZE(mt7915_mem_regions); return &mt7915_mem_regions[0]; + case 0x7981: case 0x7986: - *num = ARRAY_SIZE(mt7986_mem_regions); - return &mt7986_mem_regions[0]; + *num = ARRAY_SIZE(mt798x_mem_regions); + return &mt798x_mem_regions[0]; case 0x7916: *num = ARRAY_SIZE(mt7916_mem_regions); return &mt7916_mem_regions[0]; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index 879884ead660..6c3696c8c700 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -251,7 +251,6 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; struct mt7915_dev *dev = phy->dev; - struct mt7915_mcu_muru_stats mu_stats = {}; static const char * const dl_non_he_type[] = { "CCK", "OFDM", "HT MIX", "HT GF", "VHT SU", "VHT 2MU", "VHT 3MU", "VHT 4MU" @@ -275,7 +274,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) mutex_lock(&dev->mt76.mutex); - ret = mt7915_mcu_muru_debug_get(phy, &mu_stats); + ret = mt7915_mcu_muru_debug_get(phy); if (ret) goto exit; @@ -285,14 +284,13 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) for (i = 0; i < 5; i++) seq_printf(file, "%8s | ", dl_non_he_type[i]); -#define __dl_u32(s) le32_to_cpu(mu_stats.dl.s) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %8u | ", - __dl_u32(cck_cnt), - __dl_u32(ofdm_cnt), - __dl_u32(htmix_cnt), - __dl_u32(htgf_cnt), - __dl_u32(vht_su_cnt)); + phy->mib.dl_cck_cnt, + phy->mib.dl_ofdm_cnt, + phy->mib.dl_htmix_cnt, + phy->mib.dl_htgf_cnt, + phy->mib.dl_vht_su_cnt); seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); @@ -301,23 +299,23 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __dl_u32(vht_2mu_cnt), - __dl_u32(vht_3mu_cnt), - __dl_u32(vht_4mu_cnt)); + phy->mib.dl_vht_2mu_cnt, + phy->mib.dl_vht_3mu_cnt, + phy->mib.dl_vht_4mu_cnt); - sub_total_cnt = __dl_u32(vht_2mu_cnt) + - __dl_u32(vht_3mu_cnt) + - __dl_u32(vht_4mu_cnt); + sub_total_cnt = phy->mib.dl_vht_2mu_cnt + + phy->mib.dl_vht_3mu_cnt + + phy->mib.dl_vht_4mu_cnt; seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); total_ppdu_cnt = sub_total_cnt + - __dl_u32(cck_cnt) + - __dl_u32(ofdm_cnt) + - __dl_u32(htmix_cnt) + - __dl_u32(htgf_cnt) + - __dl_u32(vht_su_cnt); + phy->mib.dl_cck_cnt + + phy->mib.dl_ofdm_cnt + + phy->mib.dl_htmix_cnt + + phy->mib.dl_htgf_cnt + + phy->mib.dl_vht_su_cnt; seq_printf(file, "\nAll non-HE DL PPDU count: %lld", total_ppdu_cnt); @@ -329,8 +327,7 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | ", - __dl_u32(he_su_cnt), - __dl_u32(he_ext_su_cnt)); + phy->mib.dl_he_su_cnt, phy->mib.dl_he_ext_su_cnt); seq_puts(file, "\nDownlink MU-MIMO\nData Type: "); @@ -339,9 +336,8 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __dl_u32(he_2mu_cnt), - __dl_u32(he_3mu_cnt), - __dl_u32(he_4mu_cnt)); + phy->mib.dl_he_2mu_cnt, phy->mib.dl_he_3mu_cnt, + phy->mib.dl_he_4mu_cnt); seq_puts(file, "\nDownlink OFDMA\nData Type: "); @@ -350,37 +346,35 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %9u | %8u | ", - __dl_u32(he_2ru_cnt), - __dl_u32(he_3ru_cnt), - __dl_u32(he_4ru_cnt), - __dl_u32(he_5to8ru_cnt), - __dl_u32(he_9to16ru_cnt), - __dl_u32(he_gtr16ru_cnt)); - - sub_total_cnt = __dl_u32(he_2mu_cnt) + - __dl_u32(he_3mu_cnt) + - __dl_u32(he_4mu_cnt); + phy->mib.dl_he_2ru_cnt, + phy->mib.dl_he_3ru_cnt, + phy->mib.dl_he_4ru_cnt, + phy->mib.dl_he_5to8ru_cnt, + phy->mib.dl_he_9to16ru_cnt, + phy->mib.dl_he_gtr16ru_cnt); + + sub_total_cnt = phy->mib.dl_he_2mu_cnt + + phy->mib.dl_he_3mu_cnt + + phy->mib.dl_he_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld", sub_total_cnt); - sub_total_cnt = __dl_u32(he_2ru_cnt) + - __dl_u32(he_3ru_cnt) + - __dl_u32(he_4ru_cnt) + - __dl_u32(he_5to8ru_cnt) + - __dl_u32(he_9to16ru_cnt) + - __dl_u32(he_gtr16ru_cnt); + sub_total_cnt = phy->mib.dl_he_2ru_cnt + + phy->mib.dl_he_3ru_cnt + + phy->mib.dl_he_4ru_cnt + + phy->mib.dl_he_5to8ru_cnt + + phy->mib.dl_he_9to16ru_cnt + + phy->mib.dl_he_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld", sub_total_cnt); - total_ppdu_cnt += __dl_u32(he_su_cnt) + - __dl_u32(he_ext_su_cnt); + total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt; seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt); -#undef __dl_u32 /* HE Uplink */ seq_puts(file, "\n\nUplink"); @@ -389,12 +383,11 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) for (i = 0; i < 3; i++) seq_printf(file, "%8s | ", ul_he_type[i]); -#define __ul_u32(s) le32_to_cpu(mu_stats.ul.s) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | ", - __ul_u32(hetrig_2mu_cnt), - __ul_u32(hetrig_3mu_cnt), - __ul_u32(hetrig_4mu_cnt)); + phy->mib.ul_hetrig_2mu_cnt, + phy->mib.ul_hetrig_3mu_cnt, + phy->mib.ul_hetrig_4mu_cnt); seq_puts(file, "\nTrigger-based Uplink OFDMA\nData Type: "); @@ -403,37 +396,36 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data) seq_puts(file, "\nTotal Count:"); seq_printf(file, "%8u | %8u | %8u | %8u | %8u | %9u | %7u | ", - __ul_u32(hetrig_su_cnt), - __ul_u32(hetrig_2ru_cnt), - __ul_u32(hetrig_3ru_cnt), - __ul_u32(hetrig_4ru_cnt), - __ul_u32(hetrig_5to8ru_cnt), - __ul_u32(hetrig_9to16ru_cnt), - __ul_u32(hetrig_gtr16ru_cnt)); - - sub_total_cnt = __ul_u32(hetrig_2mu_cnt) + - __ul_u32(hetrig_3mu_cnt) + - __ul_u32(hetrig_4mu_cnt); + phy->mib.ul_hetrig_su_cnt, + phy->mib.ul_hetrig_2ru_cnt, + phy->mib.ul_hetrig_3ru_cnt, + phy->mib.ul_hetrig_4ru_cnt, + phy->mib.ul_hetrig_5to8ru_cnt, + phy->mib.ul_hetrig_9to16ru_cnt, + phy->mib.ul_hetrig_gtr16ru_cnt); + + sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt + + phy->mib.ul_hetrig_3mu_cnt + + phy->mib.ul_hetrig_4mu_cnt; total_ppdu_cnt = sub_total_cnt; seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld", sub_total_cnt); - sub_total_cnt = __ul_u32(hetrig_2ru_cnt) + - __ul_u32(hetrig_3ru_cnt) + - __ul_u32(hetrig_4ru_cnt) + - __ul_u32(hetrig_5to8ru_cnt) + - __ul_u32(hetrig_9to16ru_cnt) + - __ul_u32(hetrig_gtr16ru_cnt); + sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt + + phy->mib.ul_hetrig_3ru_cnt + + phy->mib.ul_hetrig_4ru_cnt + + phy->mib.ul_hetrig_5to8ru_cnt + + phy->mib.ul_hetrig_9to16ru_cnt + + phy->mib.ul_hetrig_gtr16ru_cnt; total_ppdu_cnt += sub_total_cnt; seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld", sub_total_cnt); - total_ppdu_cnt += __ul_u32(hetrig_su_cnt); + total_ppdu_cnt += phy->mib.ul_hetrig_su_cnt; seq_printf(file, "\nAll HE UL TB PPDU count: %lld\n", total_ppdu_cnt); -#undef __ul_u32 exit: mutex_unlock(&dev->mt76.mutex); @@ -719,10 +711,10 @@ mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy, static void mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) { + struct mt76_mib_stats *mib = &phy->mib; static const char * const bw[] = { "BW20", "BW40", "BW80", "BW160" }; - struct mib_stats *mib = &phy->mib; /* Tx Beamformer monitor */ seq_puts(s, "\nTx Beamformer applied PPDU counts: "); @@ -768,7 +760,7 @@ mt7915_tx_stats_show(struct seq_file *file, void *data) { struct mt7915_phy *phy = file->private; struct mt7915_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; int i; mutex_lock(&dev->mt76.mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c index 43a5456d4b97..59a44d79aaed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/dma.c @@ -11,7 +11,7 @@ mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base struct mt7915_dev *dev = phy->dev; if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) { - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) ring_base += MT_TXQ_ID(0) * MT_RING_SIZE; else ring_base = MT_WED_TX_RING_BASE; @@ -250,7 +250,7 @@ static void mt7915_dma_disable(struct mt7915_dev *dev, bool rst) } } -static int mt7915_dma_enable(struct mt7915_dev *dev) +int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset) { struct mt76_dev *mdev = &dev->mt76; u32 hif1_ofs = 0; @@ -259,6 +259,84 @@ static int mt7915_dma_enable(struct mt7915_dev *dev) if (dev->hif2) hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + /* enable wpdma tx/rx */ + if (!reset) { + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + + if (dev->hif2) { + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (is_mt7915(mdev)) + mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, + MT_WFDMA1_GLO_CFG_TX_DMA_EN | + MT_WFDMA1_GLO_CFG_RX_DMA_EN | + MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); + + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_PDMA_BAND); + } + } + + /* enable interrupts for TX/RX rings */ + irq_mask = MT_INT_RX_DONE_MCU | + MT_INT_TX_DONE_MCU | + MT_INT_MCU_CMD; + + if (!dev->phy.mt76->band_idx) + irq_mask |= MT_INT_BAND0_RX_DONE; + + if (dev->dbdc_support || dev->phy.mt76->band_idx) + irq_mask |= MT_INT_BAND1_RX_DONE; + + if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wed_reset) { + u32 wed_irq_mask = irq_mask; + int ret; + + wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; + if (!is_mt798x(&dev->mt76)) + mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); + else + mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); + + ret = mt7915_mcu_wed_enable_rx_stats(dev); + if (ret) + return ret; + + mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); + } + + irq_mask = reset ? MT_INT_MCU_CMD : irq_mask; + + mt7915_irq_enable(dev, irq_mask); + mt7915_irq_disable(dev, 0); + + return 0; +} + +static int mt7915_dma_enable(struct mt7915_dev *dev, bool reset) +{ + struct mt76_dev *mdev = &dev->mt76; + u32 hif1_ofs = 0; + + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + /* reset dma idx */ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); if (is_mt7915(mdev)) @@ -322,69 +400,7 @@ static int mt7915_dma_enable(struct mt7915_dev *dev) mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); - /* set WFDMA Tx/Rx */ - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (is_mt7915(mdev)) - mt76_set(dev, MT_WFDMA1_GLO_CFG, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN | - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - - if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (is_mt7915(mdev)) - mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs, - MT_WFDMA1_GLO_CFG_TX_DMA_EN | - MT_WFDMA1_GLO_CFG_RX_DMA_EN | - MT_WFDMA1_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA1_GLO_CFG_OMIT_RX_INFO); - - mt76_set(dev, MT_WFDMA_HOST_CONFIG, - MT_WFDMA_HOST_CONFIG_PDMA_BAND); - } - - /* enable interrupts for TX/RX rings */ - irq_mask = MT_INT_RX_DONE_MCU | - MT_INT_TX_DONE_MCU | - MT_INT_MCU_CMD; - - if (!dev->phy.mt76->band_idx) - irq_mask |= MT_INT_BAND0_RX_DONE; - - if (dev->dbdc_support || dev->phy.mt76->band_idx) - irq_mask |= MT_INT_BAND1_RX_DONE; - - if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { - u32 wed_irq_mask = irq_mask; - int ret; - - wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1; - if (!is_mt7986(&dev->mt76)) - mt76_wr(dev, MT_INT_WED_MASK_CSR, wed_irq_mask); - else - mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask); - - ret = mt7915_mcu_wed_enable_rx_stats(dev); - if (ret) - return ret; - - mtk_wed_device_start(&dev->mt76.mmio.wed, wed_irq_mask); - } - - mt7915_irq_enable(dev, irq_mask); - - return 0; + return mt7915_dma_start(dev, reset, true); } int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) @@ -404,7 +420,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) mt7915_dma_disable(dev, true); if (mtk_wed_device_active(&mdev->mmio.wed)) { - if (!is_mt7986(mdev)) { + if (!is_mt798x(mdev)) { u8 wed_control_rx1 = is_mt7915(mdev) ? 1 : 2; mt76_set(dev, MT_WFDMA_HOST_CONFIG, @@ -560,7 +576,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2) mt7915_poll_tx); napi_enable(&dev->mt76.tx_napi); - mt7915_dma_enable(dev); + mt7915_dma_enable(dev, false); return 0; } @@ -642,7 +658,7 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force) mt76_rmw(dev, MT_WFDMA0_EXT0_CFG, MT_WFDMA0_EXT0_RXWB_KEEP, MT_WFDMA0_EXT0_RXWB_KEEP); - mt7915_dma_enable(dev); + mt7915_dma_enable(dev, !force); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c index a79628933948..76be7308460b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c @@ -39,6 +39,8 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev) return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76)); case 0x7916: return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76)); + case 0x7981: + return CHECK_EEPROM_ERR(is_mt7981(&dev->mt76)); case 0x7986: return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76)); default: @@ -52,6 +54,9 @@ static char *mt7915_eeprom_name(struct mt7915_dev *dev) case 0x7915: return dev->dbdc_support ? MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT; + case 0x7981: + /* mt7981 only supports mt7976 and only in DBDC mode */ + return MT7981_EEPROM_MT7976_DEFAULT_DBDC; case 0x7986: switch (mt7915_check_adie(dev, true)) { case MT7976_ONE_ADIE_DBDC: @@ -215,7 +220,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev, eeprom[MT_EE_WIFI_CONF + 2 + band]); } - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) nss_max = 2; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index ac2049f49bb3..35fdf4f98d80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -4,6 +4,7 @@ #include <linux/etherdevice.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> +#include <linux/of.h> #include <linux/thermal.h> #include "mt7915.h" #include "mac.h" @@ -414,7 +415,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy) if (!dev->dbdc_support) vht_cap->cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1); } else { vht_cap->cap |= @@ -499,6 +499,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band) set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); + + /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than + * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. + */ + if (mtk_wed_device_active(&dev->mt76.mmio.wed)) + mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H); } static void @@ -581,6 +587,8 @@ void mt7915_mac_init(struct mt7915_dev *dev) if (!is_mt7915(&dev->mt76)) mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT); + else + mt76_clear(dev, MT_PLE_HOST_RPT0, MT_PLE_HOST_RPT0_TX_LATENCY); /* enable hardware de-agg */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); @@ -732,7 +740,7 @@ void mt7915_wfsys_reset(struct mt7915_dev *dev) mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE); msleep(100); - } else if (is_mt7986(&dev->mt76)) { + } else if (is_mt798x(&dev->mt76)) { mt7986_wmac_disable(dev); msleep(20); @@ -753,7 +761,7 @@ static bool mt7915_band_config(struct mt7915_dev *dev) dev->phy.mt76->band_idx = 0; - if (is_mt7986(&dev->mt76)) { + if (is_mt798x(&dev->mt76)) { u32 sku = mt7915_check_adie(dev, true); /* @@ -1158,11 +1166,11 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev) static void mt7915_stop_hardware(struct mt7915_dev *dev) { mt7915_mcu_exit(dev); - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); mt7915_dma_cleanup(dev); tasklet_disable(&dev->mt76.irq_tasklet); - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) mt7986_wmac_disable(dev); } @@ -1177,9 +1185,7 @@ int mt7915_register_device(struct mt7915_dev *dev) INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work); INIT_LIST_HEAD(&dev->sta_rc_list); - INIT_LIST_HEAD(&dev->sta_poll_list); INIT_LIST_HEAD(&dev->twt_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7915_mac_reset_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 7df8d95fc3fb..b8b0c0fda752 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -105,9 +105,9 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) LIST_HEAD(sta_poll_list); int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); rcu_read_lock(); @@ -118,15 +118,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev) s8 rssi[4]; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, - struct mt7915_sta, poll_list); - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + struct mt7915_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -326,10 +326,11 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb, if (status->wcid) { msta = container_of(status->wcid, struct mt7915_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } status->freq = mphy->chandef.chan->center_freq; @@ -842,74 +843,6 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id) } static void -mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) -{ - struct mt7915_sta *msta; - u16 fc, tid; - u32 val; - - if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) - return; - - tid = le32_get_bits(txwi[1], MT_TXD1_TID); - if (tid >= 6) /* skip VO queue */ - return; - - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; - if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) - return; - - msta = (struct mt7915_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) - ieee80211_start_tx_ba_session(sta, tid, 0); -} - -static void -mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, struct list_head *free_list) -{ - struct mt76_dev *mdev = &dev->mt76; - struct mt7915_sta *msta; - struct mt76_wcid *wcid; - __le32 *txwi; - u16 wcid_idx; - - mt76_connac_txp_skb_unmap(mdev, t); - if (!t->skb) - goto out; - - txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); - if (sta) { - wcid = (struct mt76_wcid *)sta->drv_priv; - wcid_idx = wcid->idx; - } else { - wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - wcid = rcu_dereference(dev->mt76.wcid[wcid_idx]); - - if (wcid && wcid->sta) { - msta = container_of(wcid, struct mt7915_sta, wcid); - sta = container_of((void *)msta, struct ieee80211_sta, - drv_priv); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); - } - } - - if (sta && likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7915_tx_check_aggr(sta, txwi); - - __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); - -out: - t->skb = NULL; - mt76_put_txwi(mdev, t); -} - -static void mt7915_mac_tx_free_prepare(struct mt7915_dev *dev) { struct mt76_dev *mdev = &dev->mt76; @@ -951,6 +884,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) struct mt76_dev *mdev = &dev->mt76; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + struct mt76_wcid *wcid = NULL; LIST_HEAD(free_list); void *end = data + len; bool v3, wake = false; @@ -977,7 +911,6 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) info = le32_to_cpu(*cur_info); if (info & MT_TX_FREE_PAIR) { struct mt7915_sta *msta; - struct mt76_wcid *wcid; u16 idx; idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); @@ -987,14 +920,33 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7915_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } - if (v3 && (info & MT_TX_FREE_MPDU_HEADER)) + if (!mtk_wed_device_active(&mdev->mmio.wed) && wcid) { + u32 tx_retries = 0, tx_failed = 0; + + if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) { + tx_retries = + FIELD_GET(MT_TX_FREE_COUNT_V3, info) - 1; + tx_failed = tx_retries + + !!FIELD_GET(MT_TX_FREE_STAT_V3, info); + } else if (!v3 && (info & MT_TX_FREE_MPDU_HEADER)) { + tx_retries = + FIELD_GET(MT_TX_FREE_COUNT, info) - 1; + tx_failed = tx_retries + + !!FIELD_GET(MT_TX_FREE_STAT, info); + } + wcid->stats.tx_retries += tx_retries; + wcid->stats.tx_failed += tx_failed; + } + + if (v3 && (info & MT_TX_FREE_MPDU_HEADER_V3)) continue; for (i = 0; i < 1 + v3; i++) { @@ -1010,7 +962,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) if (!txwi) continue; - mt7915_txwi_free(dev, txwi, sta, &free_list); + mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); } } @@ -1042,7 +994,7 @@ mt7915_mac_tx_free_v0(struct mt7915_dev *dev, void *data, int len) if (!txwi) continue; - mt7915_txwi_free(dev, txwi, NULL, &free_list); + mt76_connac2_txwi_free(mdev, txwi, NULL, &free_list); } mt7915_mac_tx_free_done(dev, &free_list, wake); @@ -1081,10 +1033,10 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data) if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); @@ -1357,20 +1309,6 @@ mt7915_update_beacons(struct mt7915_dev *dev) mt7915_update_vif_beacon, mphy_ext->hw); } -void mt7915_tx_token_put(struct mt7915_dev *dev) -{ - struct mt76_txwi_cache *txwi; - int id; - - spin_lock_bh(&dev->mt76.token_lock); - idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7915_txwi_free(dev, txwi, NULL, NULL); - dev->mt76.token_count--; - } - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); -} - static int mt7915_mac_restart(struct mt7915_dev *dev) { @@ -1389,8 +1327,12 @@ mt7915_mac_restart(struct mt7915_dev *dev) if (dev_is_pci(mdev->dev)) { mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); - if (dev->hif2) - mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); + if (dev->hif2) { + if (is_mt7915(mdev)) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0); + else + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0x0); + } } set_bit(MT76_RESET, &dev->mphy.state); @@ -1415,7 +1357,7 @@ mt7915_mac_restart(struct mt7915_dev *dev) napi_disable(&dev->mt76.tx_napi); /* token reinit */ - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); mt7915_dma_reset(dev, true); @@ -1440,8 +1382,12 @@ mt7915_mac_restart(struct mt7915_dev *dev) } if (dev_is_pci(mdev->dev)) { mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - if (dev->hif2) - mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + if (dev->hif2) { + if (is_mt7915(mdev)) + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); + else + mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff); + } } /* load firmware */ @@ -1576,7 +1522,7 @@ void mt7915_mac_reset_work(struct work_struct *work) if (mtk_wed_device_active(&dev->mt76.mmio.wed)) { mtk_wed_device_stop(&dev->mt76.mmio.wed); - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) mt76_wr(dev, MT_INT_WED_MASK_CSR, 0); } @@ -1604,13 +1550,19 @@ void mt7915_mac_reset_work(struct work_struct *work) if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { mt7915_dma_reset(dev, false); - mt7915_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); } + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + /* enable DMA Tx/Rx and interrupt */ + mt7915_dma_start(dev, false, false); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); if (phy2) @@ -1625,9 +1577,6 @@ void mt7915_mac_reset_work(struct work_struct *work) tasklet_schedule(&dev->mt76.irq_tasklet); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7915_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - mt76_worker_enable(&dev->mt76.tx_worker); local_bh_disable(); @@ -1747,8 +1696,8 @@ void mt7915_reset(struct mt7915_dev *dev) void mt7915_mac_update_stats(struct mt7915_phy *phy) { + struct mt76_mib_stats *mib = &phy->mib; struct mt7915_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; int i, aggr0 = 0, aggr1, cnt; u8 band = phy->mt76->band_idx; u32 val; @@ -2010,7 +1959,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) u32 changed; LIST_HEAD(list); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); list_splice_init(&dev->sta_rc_list, &list); while (!list_empty(&list)) { @@ -2018,7 +1967,7 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) list_del_init(&msta->rc_list); changed = msta->changed; msta->changed = 0; - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); @@ -2031,10 +1980,10 @@ void mt7915_mac_sta_rc_work(struct work_struct *work) if (changed & IEEE80211_RC_SMPS_CHANGED) mt7915_mcu_add_smps(dev, vif, sta); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); } - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } void mt7915_mac_work(struct work_struct *work) @@ -2054,6 +2003,9 @@ void mt7915_mac_work(struct work_struct *work) mt7915_mac_update_stats(phy); mt7915_mac_severe_check(phy); + + if (phy->dev->muru_debug) + mt7915_mcu_muru_debug_get(phy); } mutex_unlock(&mphy->dev->mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h index ce94f87e2042..448b1b380190 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.h @@ -9,7 +9,12 @@ #define MT_TX_FREE_VER GENMASK(18, 16) #define MT_TX_FREE_MSDU_CNT_V0 GENMASK(6, 0) /* 0: success, others: dropped */ -#define MT_TX_FREE_MPDU_HEADER BIT(30) +#define MT_TX_FREE_COUNT GENMASK(12, 0) +#define MT_TX_FREE_COUNT_V3 GENMASK(27, 24) +#define MT_TX_FREE_STAT GENMASK(14, 13) +#define MT_TX_FREE_STAT_V3 GENMASK(29, 28) +#define MT_TX_FREE_MPDU_HEADER BIT(15) +#define MT_TX_FREE_MPDU_HEADER_V3 BIT(30) #define MT_TX_FREE_MSDU_ID_V3 GENMASK(14, 0) #define MT_TXS5_F0_FINAL_MPDU BIT(31) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 1b361199c061..8ebbf186fab2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -248,7 +248,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, idx = MT7915_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = ext_phy; mvif->sta.wcid.hw_key_idx = -1; @@ -269,6 +269,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; mt7915_init_bitrate_mask(vif); + memset(&mvif->cap, -1, sizeof(mvif->cap)); mt7915_mcu_add_bss_info(phy, vif, true); mt7915_mcu_add_sta(dev, vif, NULL, true); @@ -308,10 +309,10 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw, phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); } @@ -470,7 +471,8 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed) ieee80211_wake_queues(hw); } - if (changed & IEEE80211_CONF_CHANGE_POWER) { + if (changed & (IEEE80211_CONF_CHANGE_POWER | + IEEE80211_CONF_CHANGE_CHANNEL)) { ret = mt7915_mcu_set_txpower_sku(phy); if (ret) return ret; @@ -599,6 +601,7 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, { struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = mt7915_hw_dev(hw); + int set_bss_info = -1, set_sta = -1; mutex_lock(&dev->mt76.mutex); @@ -607,15 +610,18 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, * and then peer references bss_info_rfch to set bandwidth cap. */ if (changed & BSS_CHANGED_BSSID && - vif->type == NL80211_IFTYPE_STATION) { - bool join = !is_zero_ether_addr(info->bssid); - - mt7915_mcu_add_bss_info(phy, vif, join); - mt7915_mcu_add_sta(dev, vif, NULL, join); - } - + vif->type == NL80211_IFTYPE_STATION) + set_bss_info = set_sta = !is_zero_ether_addr(info->bssid); if (changed & BSS_CHANGED_ASSOC) - mt7915_mcu_add_bss_info(phy, vif, vif->cfg.assoc); + set_bss_info = vif->cfg.assoc; + if (changed & BSS_CHANGED_BEACON_ENABLED && + vif->type != NL80211_IFTYPE_AP) + set_bss_info = set_sta = info->enable_beacon; + + if (set_bss_info == 1) + mt7915_mcu_add_bss_info(phy, vif, true); + if (set_sta == 1) + mt7915_mcu_add_sta(dev, vif, NULL, true); if (changed & BSS_CHANGED_ERP_CTS_PROT) mt7915_mac_enable_rtscts(dev, vif, info->use_cts_prot); @@ -629,11 +635,6 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { - mt7915_mcu_add_bss_info(phy, vif, true); - mt7915_mcu_add_sta(dev, vif, NULL, true); - } - /* ensure that enable txcmd_mode after bss_info */ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_set_tx(dev, vif); @@ -650,6 +651,62 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_FILS_DISCOVERY)) mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed); + if (set_bss_info == 0) + mt7915_mcu_add_bss_info(phy, vif, false); + if (set_sta == 0) + mt7915_mcu_add_sta(dev, vif, NULL, false); + + mutex_unlock(&dev->mt76.mutex); +} + +static void +mt7915_vif_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_vif_cap *vc = &mvif->cap; + + vc->ht_ldpc = vif->bss_conf.ht_ldpc; + vc->vht_ldpc = vif->bss_conf.vht_ldpc; + vc->vht_su_ebfer = vif->bss_conf.vht_su_beamformer; + vc->vht_su_ebfee = vif->bss_conf.vht_su_beamformee; + vc->vht_mu_ebfer = vif->bss_conf.vht_mu_beamformer; + vc->vht_mu_ebfee = vif->bss_conf.vht_mu_beamformee; + vc->he_ldpc = vif->bss_conf.he_ldpc; + vc->he_su_ebfer = vif->bss_conf.he_su_beamformer; + vc->he_su_ebfee = vif->bss_conf.he_su_beamformee; + vc->he_mu_ebfer = vif->bss_conf.he_mu_beamformer; +} + +static int +mt7915_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = mt7915_hw_dev(hw); + int err; + + mutex_lock(&dev->mt76.mutex); + + mt7915_vif_check_caps(phy, vif); + + err = mt7915_mcu_add_bss_info(phy, vif, true); + if (err) + goto out; + err = mt7915_mcu_add_sta(dev, vif, NULL, true); +out: + mutex_unlock(&dev->mt76.mutex); + + return err; +} + +static void +mt7915_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf) +{ + struct mt7915_dev *dev = mt7915_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mt7915_mcu_add_sta(dev, vif, NULL, false); mutex_unlock(&dev->mt76.mutex); } @@ -679,7 +736,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, return -ENOSPC; INIT_LIST_HEAD(&msta->rc_list); - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -714,12 +771,12 @@ void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) mt7915_mac_twt_teardown_flow(dev, msta, i); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + spin_lock_bh(&mdev->sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); } static void mt7915_tx(struct ieee80211_hw *hw, @@ -801,16 +858,16 @@ mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7915_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7915_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -842,7 +899,7 @@ mt7915_get_stats(struct ieee80211_hw *hw, { struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_dev *dev = mt7915_hw_dev(hw); - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; mutex_lock(&dev->mt76.mutex); @@ -1019,21 +1076,20 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); } - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + if (txrate->legacy || txrate->flags) { + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } - sinfo->txrate.flags = txrate->flags; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); /* offloading flows bypass networking stack, so driver counts and * reports sta statistics via NL80211_STA_INFO when WED is active. @@ -1042,14 +1098,10 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, sinfo->tx_bytes = msta->wcid.stats.tx_bytes; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64); - sinfo->tx_packets = msta->wcid.stats.tx_packets; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); - - sinfo->tx_failed = msta->wcid.stats.tx_failed; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); - - sinfo->tx_retries = msta->wcid.stats.tx_retries; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + if (!mt7915_mcu_wed_wa_tx_stats(phy->dev, msta->wcid.idx)) { + sinfo->tx_packets = msta->wcid.stats.tx_packets; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS); + } if (mtk_wed_get_rx_capa(&phy->dev->mt76.mmio.wed)) { sinfo->rx_bytes = msta->wcid.stats.rx_bytes; @@ -1060,6 +1112,12 @@ static void mt7915_sta_statistics(struct ieee80211_hw *hw, } } + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + sinfo->ack_signal = (s8)msta->ack_signal; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); @@ -1073,11 +1131,11 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta) struct mt7915_dev *dev = msta->vif->phy->dev; u32 *changed = data; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); msta->changed |= *changed; if (list_empty(&msta->rc_list)) list_add_tail(&msta->rc_list, &dev->sta_rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } static void mt7915_sta_rc_update(struct ieee80211_hw *hw, @@ -1253,6 +1311,38 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_vec_queue_overflow_drop_cnt", "rx_ba_cnt", + /* muru mu-mimo and ofdma related stats */ + "dl_cck_cnt", + "dl_ofdm_cnt", + "dl_htmix_cnt", + "dl_htgf_cnt", + "dl_vht_su_cnt", + "dl_vht_2mu_cnt", + "dl_vht_3mu_cnt", + "dl_vht_4mu_cnt", + "dl_he_su_cnt", + "dl_he_ext_su_cnt", + "dl_he_2ru_cnt", + "dl_he_2mu_cnt", + "dl_he_3ru_cnt", + "dl_he_3mu_cnt", + "dl_he_4ru_cnt", + "dl_he_4mu_cnt", + "dl_he_5to8ru_cnt", + "dl_he_9to16ru_cnt", + "dl_he_gtr16ru_cnt", + + "ul_hetrig_su_cnt", + "ul_hetrig_2ru_cnt", + "ul_hetrig_3ru_cnt", + "ul_hetrig_4ru_cnt", + "ul_hetrig_5to8ru_cnt", + "ul_hetrig_9to16ru_cnt", + "ul_hetrig_gtr16ru_cnt", + "ul_hetrig_2mu_cnt", + "ul_hetrig_3mu_cnt", + "ul_hetrig_4mu_cnt", + /* per vif counters */ "v_tx_mode_cck", "v_tx_mode_ofdm", @@ -1279,6 +1369,10 @@ static const char mt7915_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_9", "v_tx_mcs_10", "v_tx_mcs_11", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", }; #define MT7915_SSTATS_LEN ARRAY_SIZE(mt7915_gstrings_stats) @@ -1326,11 +1420,11 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, struct mt7915_dev *dev = mt7915_hw_dev(hw); struct mt7915_phy *phy = mt7915_hw_phy(hw); struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, .idx = mvif->mt76.idx, }; - struct mib_stats *mib = &phy->mib; /* See mt7915_ampdu_stat_read_phy, etc */ int i, ei = 0, stats_size; @@ -1403,6 +1497,37 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw, data[ei++] = mib->rx_vec_queue_overflow_drop_cnt; data[ei++] = mib->rx_ba_cnt; + data[ei++] = mib->dl_cck_cnt; + data[ei++] = mib->dl_ofdm_cnt; + data[ei++] = mib->dl_htmix_cnt; + data[ei++] = mib->dl_htgf_cnt; + data[ei++] = mib->dl_vht_su_cnt; + data[ei++] = mib->dl_vht_2mu_cnt; + data[ei++] = mib->dl_vht_3mu_cnt; + data[ei++] = mib->dl_vht_4mu_cnt; + data[ei++] = mib->dl_he_su_cnt; + data[ei++] = mib->dl_he_ext_su_cnt; + data[ei++] = mib->dl_he_2ru_cnt; + data[ei++] = mib->dl_he_2mu_cnt; + data[ei++] = mib->dl_he_3ru_cnt; + data[ei++] = mib->dl_he_3mu_cnt; + data[ei++] = mib->dl_he_4ru_cnt; + data[ei++] = mib->dl_he_4mu_cnt; + data[ei++] = mib->dl_he_5to8ru_cnt; + data[ei++] = mib->dl_he_9to16ru_cnt; + data[ei++] = mib->dl_he_gtr16ru_cnt; + + data[ei++] = mib->ul_hetrig_su_cnt; + data[ei++] = mib->ul_hetrig_2ru_cnt; + data[ei++] = mib->ul_hetrig_3ru_cnt; + data[ei++] = mib->ul_hetrig_4ru_cnt; + data[ei++] = mib->ul_hetrig_5to8ru_cnt; + data[ei++] = mib->ul_hetrig_9to16ru_cnt; + data[ei++] = mib->ul_hetrig_gtr16ru_cnt; + data[ei++] = mib->ul_hetrig_2mu_cnt; + data[ei++] = mib->ul_hetrig_3mu_cnt; + data[ei++] = mib->ul_hetrig_4mu_cnt; + /* Add values for all stations owned by this vif */ wi.initial_stat_idx = ei; ieee80211_iterate_stations_atomic(hw, mt7915_ethtool_worker, &wi); @@ -1526,6 +1651,8 @@ const struct ieee80211_ops mt7915_ops = { .conf_tx = mt7915_conf_tx, .configure_filter = mt7915_configure_filter, .bss_info_changed = mt7915_bss_info_changed, + .start_ap = mt7915_start_ap, + .stop_ap = mt7915_stop_ap, .sta_add = mt7915_sta_add, .sta_remove = mt7915_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 9fcb22fa1f97..50ae7bf3af91 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -13,6 +13,9 @@ case 0x7915: \ _fw = MT7915_##name; \ break; \ + case 0x7981: \ + _fw = MT7981_##name; \ + break; \ case 0x7986: \ _fw = MT7986_##name##__VA_ARGS__; \ break; \ @@ -164,7 +167,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd, } rxd = (struct mt76_connac2_mcu_rxd *)skb->data; - if (seq != rxd->seq) + if (seq != rxd->seq && + !(rxd->eid == MCU_CMD_EXT_CID && + rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) return -EAGAIN; if (cmd == MCU_CMD(PATCH_SEM_CONTROL)) { @@ -274,7 +279,7 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb) r = (struct mt7915_mcu_rdd_report *)skb->data; - if (r->band_idx > MT_BAND1) + if (r->band_idx > MT_RX_SEL2) return; if ((r->band_idx && !dev->phy.mt76->band_idx) && @@ -395,12 +400,14 @@ void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb) struct mt76_connac2_mcu_rxd *rxd; rxd = (struct mt76_connac2_mcu_rxd *)skb->data; - if (rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || - rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST || - rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || - rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || - rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY || - !rxd->seq) + if ((rxd->ext_eid == MCU_EXT_EVENT_THERMAL_PROTECT || + rxd->ext_eid == MCU_EXT_EVENT_FW_LOG_2_HOST || + rxd->ext_eid == MCU_EXT_EVENT_ASSERT_DUMP || + rxd->ext_eid == MCU_EXT_EVENT_PS_SYNC || + rxd->ext_eid == MCU_EXT_EVENT_BCC_NOTIFY || + !rxd->seq) && + !(rxd->eid == MCU_CMD_EXT_CID && + rxd->ext_eid == MCU_EXT_EVENT_WA_TX_STAT)) mt7915_mcu_rx_unsolicited_event(dev, skb); else mt76_mcu_rx_event(&dev->mt76, skb); @@ -706,6 +713,7 @@ static void mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct ieee80211_he_mcs_nss_supp mcs_map; struct sta_rec_he *he; @@ -739,7 +747,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G)) cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT; - if (vif->bss_conf.he_ldpc && + if (mvif->cap.he_ldpc && (elem->phy_cap_info[1] & IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)) cap |= STA_REC_HE_CAP_LDPC; @@ -848,6 +856,7 @@ static void mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; struct sta_rec_muru *muru; struct tlv *tlv; @@ -860,9 +869,9 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb, muru = (struct sta_rec_muru *)tlv; - muru->cfg.mimo_dl_en = vif->bss_conf.he_mu_beamformer || - vif->bss_conf.vht_mu_beamformer || - vif->bss_conf.vht_mu_beamformee; + muru->cfg.mimo_dl_en = mvif->cap.he_mu_ebfer || + mvif->cap.vht_mu_ebfer || + mvif->cap.vht_mu_ebfee; if (!is_mt7915(&dev->mt76)) muru->cfg.mimo_ul_en = true; muru->cfg.ofdma_dl_en = true; @@ -995,8 +1004,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb, mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr); if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv, - wtbl_hdr, vif->bss_conf.ht_ldpc, - vif->bss_conf.vht_ldpc); + wtbl_hdr, mvif->cap.ht_ldpc, + mvif->cap.vht_ldpc); return 0; } @@ -1005,6 +1014,7 @@ static inline bool mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; int tx_ant = hweight8(phy->mt76->chainmask) - 1; if (vif->type != NL80211_IFTYPE_STATION && @@ -1018,10 +1028,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem; if (bfee) - return vif->bss_conf.he_su_beamformee && + return mvif->cap.he_su_ebfee && HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]); else - return vif->bss_conf.he_su_beamformer && + return mvif->cap.he_su_ebfer && HE_PHY(CAP4_SU_BEAMFORMEE, pe->phy_cap_info[4]); } @@ -1029,10 +1039,10 @@ mt7915_is_ebf_supported(struct mt7915_phy *phy, struct ieee80211_vif *vif, u32 cap = sta->deflink.vht_cap.cap; if (bfee) - return vif->bss_conf.vht_su_beamformee && + return mvif->cap.vht_su_ebfee && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE); else - return vif->bss_conf.vht_su_beamformer && + return mvif->cap.vht_su_ebfer && (cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); } @@ -1527,7 +1537,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_TX_STBC; if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) cap |= STA_CAP_RX_STBC; - if (vif->bss_conf.ht_ldpc && + if (mvif->cap.ht_ldpc && (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) cap |= STA_CAP_LDPC; @@ -1553,7 +1563,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, cap |= STA_CAP_VHT_TX_STBC; if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1) cap |= STA_CAP_VHT_RX_STBC; - if (vif->bss_conf.vht_ldpc && + if (mvif->cap.vht_ldpc && (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)) cap |= STA_CAP_VHT_LDPC; @@ -2112,12 +2122,11 @@ int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enabled) sizeof(data), false); } -int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy) { struct mt7915_dev *dev = phy->dev; struct sk_buff *skb; - struct mt7915_mcu_muru_stats *mu_stats = - (struct mt7915_mcu_muru_stats *)ms; + struct mt7915_mcu_muru_stats *mu_stats; int ret; struct { @@ -2133,7 +2142,43 @@ int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms) if (ret) return ret; - memcpy(mu_stats, skb->data, sizeof(struct mt7915_mcu_muru_stats)); + mu_stats = (struct mt7915_mcu_muru_stats *)(skb->data); + + /* accumulate stats, these are clear-on-read */ +#define __dl_u32(s) phy->mib.dl_##s += le32_to_cpu(mu_stats->dl.s) +#define __ul_u32(s) phy->mib.ul_##s += le32_to_cpu(mu_stats->ul.s) + __dl_u32(cck_cnt); + __dl_u32(ofdm_cnt); + __dl_u32(htmix_cnt); + __dl_u32(htgf_cnt); + __dl_u32(vht_su_cnt); + __dl_u32(vht_2mu_cnt); + __dl_u32(vht_3mu_cnt); + __dl_u32(vht_4mu_cnt); + __dl_u32(he_su_cnt); + __dl_u32(he_2ru_cnt); + __dl_u32(he_2mu_cnt); + __dl_u32(he_3ru_cnt); + __dl_u32(he_3mu_cnt); + __dl_u32(he_4ru_cnt); + __dl_u32(he_4mu_cnt); + __dl_u32(he_5to8ru_cnt); + __dl_u32(he_9to16ru_cnt); + __dl_u32(he_gtr16ru_cnt); + + __ul_u32(hetrig_su_cnt); + __ul_u32(hetrig_2ru_cnt); + __ul_u32(hetrig_3ru_cnt); + __ul_u32(hetrig_4ru_cnt); + __ul_u32(hetrig_5to8ru_cnt); + __ul_u32(hetrig_9to16ru_cnt); + __ul_u32(hetrig_gtr16ru_cnt); + __ul_u32(hetrig_2mu_cnt); + __ul_u32(hetrig_3mu_cnt); + __ul_u32(hetrig_4mu_cnt); +#undef __dl_u32 +#undef __ul_u32 + dev_kfree_skb(skb); return 0; @@ -2993,7 +3038,7 @@ int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch) } ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD(GET_MIB_INFO), - req, sizeof(req), true, &skb); + req, len * sizeof(req[0]), true, &skb); if (ret) return ret; @@ -3733,6 +3778,62 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev, &req, sizeof(req), true); } +int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx) +{ + struct { + __le32 cmd; + __le32 num; + __le32 __rsv; + __le16 wlan_idx; + } req = { + .cmd = cpu_to_le32(0x15), + .num = cpu_to_le32(1), + .wlan_idx = cpu_to_le16(wlan_idx), + }; + struct mt7915_mcu_wa_tx_stat { + __le16 wlan_idx; + u8 __rsv[2]; + + /* tx_bytes is deprecated since WA byte counter uses u32, + * which easily leads to overflow. + */ + __le32 tx_bytes; + __le32 tx_packets; + } *res; + struct mt76_wcid *wcid; + struct sk_buff *skb; + int ret; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY), + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + if (!is_mt7915(&dev->mt76)) + skb_pull(skb, 4); + + res = (struct mt7915_mcu_wa_tx_stat *)skb->data; + + if (le16_to_cpu(res->wlan_idx) != wlan_idx) { + ret = -EINVAL; + goto out; + } + + rcu_read_lock(); + + wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); + if (wcid) + wcid->stats.tx_packets += le32_to_cpu(res->tx_packets); + else + ret = -EINVAL; + + rcu_read_unlock(); +out: + dev_kfree_skb(skb); + + return ret; +} + int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c index 45f3558bf31c..fc7ace638ce8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c @@ -417,7 +417,7 @@ static u32 mt7915_reg_map_l1(struct mt7915_dev *dev, u32 addr) u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); u32 l1_remap; - if (is_mt7986(&dev->mt76)) + if (is_mt798x(&dev->mt76)) return MT_CONN_INFRA_OFFSET(addr); l1_remap = is_mt7915(&dev->mt76) ? @@ -447,7 +447,7 @@ static u32 mt7915_reg_map_l2(struct mt7915_dev *dev, u32 addr) /* use read to push write */ dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2); } else { - u32 ofs = is_mt7986(&dev->mt76) ? 0x400000 : 0; + u32 ofs = is_mt798x(&dev->mt76) ? 0x400000 : 0; offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_MT7916, addr); base = FIELD_GET(MT_HIF_REMAP_L2_BASE_MT7916, addr); @@ -545,8 +545,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - struct mt7915_phy *phy; - int ret; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); @@ -554,43 +552,19 @@ static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed) dev->mt76.token_size = wed->wlan.token_start; spin_unlock_bh(&dev->mt76.token_lock); - ret = wait_event_timeout(dev->mt76.tx_wait, - !dev->mt76.wed_token_count, HZ); - if (!ret) - return -EAGAIN; - - phy = &dev->phy; - mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H); - - phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; - if (phy) - mt76_set(dev, MT_AGG_ACR4(phy->mt76->band_idx), - MT_AGG_ACR_PPDU_TXS2H); - - return 0; + return !wait_event_timeout(dev->mt76.tx_wait, + !dev->mt76.wed_token_count, HZ); } static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed) { struct mt7915_dev *dev; - struct mt7915_phy *phy; dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); spin_lock_bh(&dev->mt76.token_lock); dev->mt76.token_size = MT7915_TOKEN_SIZE; spin_unlock_bh(&dev->mt76.token_lock); - - /* MT_TXD5_TX_STATUS_HOST (MPDU format) has higher priority than - * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set. - */ - phy = &dev->phy; - mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), MT_AGG_ACR_PPDU_TXS2H); - - phy = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL; - if (phy) - mt76_clear(dev, MT_AGG_ACR4(phy->mt76->band_idx), - MT_AGG_ACR_PPDU_TXS2H); } static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed) @@ -785,7 +759,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, wed->wlan.nbuf = MT7915_HW_TOKEN_SIZE; wed->wlan.tx_tbit[0] = is_mt7915(&dev->mt76) ? 4 : 30; wed->wlan.tx_tbit[1] = is_mt7915(&dev->mt76) ? 5 : 31; - wed->wlan.txfree_tbit = is_mt7986(&dev->mt76) ? 2 : 1; + wed->wlan.txfree_tbit = is_mt798x(&dev->mt76) ? 2 : 1; wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf; wed->wlan.wcid_512 = !is_mt7915(&dev->mt76); @@ -795,7 +769,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr, if (is_mt7915(&dev->mt76)) { wed->wlan.rx_tbit[0] = 16; wed->wlan.rx_tbit[1] = 17; - } else if (is_mt7986(&dev->mt76)) { + } else if (is_mt798x(&dev->mt76)) { wed->wlan.rx_tbit[0] = 22; wed->wlan.rx_tbit[1] = 23; } else { @@ -853,6 +827,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev, dev->reg.map = mt7916_reg_map; dev->reg.map_size = ARRAY_SIZE(mt7916_reg_map); break; + case 0x7981: case 0x7986: dev->reg.reg_rev = mt7986_reg; dev->reg.offs_rev = mt7916_offs; @@ -1062,8 +1037,8 @@ static int __init mt7915_init(void) if (ret) goto error_pci; - if (IS_ENABLED(CONFIG_MT7986_WMAC)) { - ret = platform_driver_register(&mt7986_wmac_driver); + if (IS_ENABLED(CONFIG_MT798X_WMAC)) { + ret = platform_driver_register(&mt798x_wmac_driver); if (ret) goto error_wmac; } @@ -1080,8 +1055,8 @@ error_pci: static void __exit mt7915_exit(void) { - if (IS_ENABLED(CONFIG_MT7986_WMAC)) - platform_driver_unregister(&mt7986_wmac_driver); + if (IS_ENABLED(CONFIG_MT798X_WMAC)) + platform_driver_unregister(&mt798x_wmac_driver); pci_unregister_driver(&mt7915_pci_driver); pci_unregister_driver(&mt7915_hif_driver); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index b3ead3530740..0456e56f6348 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -34,6 +34,10 @@ #define MT7916_FIRMWARE_WM "mediatek/mt7916_wm.bin" #define MT7916_ROM_PATCH "mediatek/mt7916_rom_patch.bin" +#define MT7981_FIRMWARE_WA "mediatek/mt7981_wa.bin" +#define MT7981_FIRMWARE_WM "mediatek/mt7981_wm.bin" +#define MT7981_ROM_PATCH "mediatek/mt7981_rom_patch.bin" + #define MT7986_FIRMWARE_WA "mediatek/mt7986_wa.bin" #define MT7986_FIRMWARE_WM "mediatek/mt7986_wm.bin" #define MT7986_FIRMWARE_WM_MT7975 "mediatek/mt7986_wm_mt7975.bin" @@ -43,6 +47,9 @@ #define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin" #define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin" #define MT7916_EEPROM_DEFAULT "mediatek/mt7916_eeprom.bin" + +#define MT7981_EEPROM_MT7976_DEFAULT_DBDC "mediatek/mt7981_eeprom_mt7976_dbdc.bin" + #define MT7986_EEPROM_MT7975_DEFAULT "mediatek/mt7986_eeprom_mt7975.bin" #define MT7986_EEPROM_MT7975_DUAL_DEFAULT "mediatek/mt7986_eeprom_mt7975_dual.bin" #define MT7986_EEPROM_MT7976_DEFAULT "mediatek/mt7986_eeprom_mt7976.bin" @@ -129,7 +136,6 @@ struct mt7915_sta { struct mt7915_vif *vif; - struct list_head poll_list; struct list_head rc_list; u32 airtime_ac[8]; @@ -138,7 +144,6 @@ struct mt7915_sta { unsigned long changed; unsigned long jiffies; - unsigned long ampdu_state; struct mt76_connac_sta_key_conf bip; struct { @@ -147,9 +152,23 @@ struct mt7915_sta { } twt; }; +struct mt7915_vif_cap { + bool ht_ldpc:1; + bool vht_ldpc:1; + bool he_ldpc:1; + bool vht_su_ebfer:1; + bool vht_su_ebfee:1; + bool vht_mu_ebfer:1; + bool vht_mu_ebfee:1; + bool he_su_ebfer:1; + bool he_su_ebfee:1; + bool he_mu_ebfer:1; +}; + struct mt7915_vif { struct mt76_vif mt76; /* must be first */ + struct mt7915_vif_cap cap; struct mt7915_sta sta; struct mt7915_phy *phy; @@ -157,67 +176,6 @@ struct mt7915_vif { struct cfg80211_bitrate_mask bitrate_mask; }; -/* per-phy stats. */ -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - u32 tx_bf_cnt; - u32 tx_mu_mpdu_cnt; - u32 tx_mu_acked_mpdu_cnt; - u32 tx_su_acked_mpdu_cnt; - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ - u32 tx_bf_rx_fb_nc_cnt; - u32 tx_bf_rx_fb_nr_cnt; - u32 tx_bf_fb_cpl_cnt; - u32 tx_bf_fb_trig_cnt; - - u32 tx_ampdu_cnt; - u32 tx_stop_q_empty_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - u32 tx_pkt_ebf_cnt; - u32 tx_pkt_ibf_cnt; - - u32 tx_rwp_fail_cnt; - u32 tx_rwp_need_cnt; - - /* rx stats */ - u32 rx_fifo_full_cnt; - u32 channel_idle_cnt; - u32 primary_cca_busy_time; - u32 secondary_cca_busy_time; - u32 primary_energy_detect_time; - u32 cck_mdrdy_time; - u32 ofdm_mdrdy_time; - u32 green_mdrdy_time; - u32 rx_vector_mismatch_cnt; - u32 rx_delimiter_fail_cnt; - u32 rx_mrdy_cnt; - u32 rx_len_mismatch_cnt; - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ampdu_valid_subframe_cnt; - u32 rx_ampdu_valid_subframe_bytes_cnt; - u32 rx_pfdrop_cnt; - u32 rx_vec_queue_overflow_drop_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; -}; - /* crash-dump */ struct mt7915_crash_data { guid_t guid; @@ -263,7 +221,7 @@ struct mt7915_phy { u32 rx_ampdu_ts; u32 ampdu_ref; - struct mib_stats mib; + struct mt76_mib_stats mib; struct mt76_channel_state state_ts; #ifdef CONFIG_NL80211_TESTMODE @@ -328,9 +286,7 @@ struct mt7915_dev { #endif struct list_head sta_rc_list; - struct list_head sta_poll_list; struct list_head twt_list; - spinlock_t sta_poll_lock; u32 hw_pattern; @@ -420,8 +376,7 @@ mt7915_ext_phy(struct mt7915_dev *dev) static inline u32 mt7915_check_adie(struct mt7915_dev *dev, bool sku) { u32 mask = sku ? MT_CONNINFRA_SKU_MASK : MT_ADIE_TYPE_MASK; - - if (!is_mt7986(&dev->mt76)) + if (!is_mt798x(&dev->mt76)) return 0; return mt76_rr(dev, MT_CONNINFRA_SKU_DEC_ADDR) & mask; @@ -431,9 +386,9 @@ extern const struct ieee80211_ops mt7915_ops; extern const struct mt76_testmode_ops mt7915_testmode_ops; extern struct pci_driver mt7915_pci_driver; extern struct pci_driver mt7915_hif_driver; -extern struct platform_driver mt7986_wmac_driver; +extern struct platform_driver mt798x_wmac_driver; -#ifdef CONFIG_MT7986_WMAC +#ifdef CONFIG_MT798X_WMAC int mt7986_wmac_enable(struct mt7915_dev *dev); void mt7986_wmac_disable(struct mt7915_dev *dev); #else @@ -466,6 +421,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2); void mt7915_dma_prefetch(struct mt7915_dev *dev); void mt7915_dma_cleanup(struct mt7915_dev *dev); int mt7915_dma_reset(struct mt7915_dev *dev, bool force); +int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset); int mt7915_txbf_init(struct mt7915_dev *dev); void mt7915_init_txpower(struct mt7915_dev *dev, struct ieee80211_supported_band *sband); @@ -539,6 +495,7 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy, struct cfg80211_chan_def *chandef); +int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wcid); int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set); int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3); int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl); @@ -612,7 +569,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7915_tx_token_put(struct mt7915_dev *dev); void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len); @@ -623,7 +579,7 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy); void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy); void mt7915_update_channel(struct mt76_phy *mphy); int mt7915_mcu_muru_debug_set(struct mt7915_dev *dev, bool enable); -int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy, void *ms); +int mt7915_mcu_muru_debug_get(struct mt7915_phy *phy); int mt7915_mcu_wed_enable_rx_stats(struct mt7915_dev *dev); int mt7915_init_debugfs(struct mt7915_phy *phy); void mt7915_debugfs_rx_fw_monitor(struct mt7915_dev *dev, const void *data, int len); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index c8e478a55081..588cd87e24e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -145,6 +145,9 @@ enum offs_rev { #define MT_PLE_BASE 0x820c0000 #define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) +#define MT_PLE_HOST_RPT0 MT_PLE(0x030) +#define MT_PLE_HOST_RPT0_TX_LATENCY BIT(3) + #define MT_FL_Q_EMPTY MT_PLE(__OFFS(PLE_FL_Q_EMPTY)) #define MT_FL_Q0_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL)) #define MT_FL_Q2_CTRL MT_PLE(__OFFS(PLE_FL_Q_CTRL) + 0x8) @@ -871,7 +874,12 @@ enum offs_rev { #define MT_AFE_RG_WBG_EN_WPLL_UP_MASK BIT(20) #define MT_AFE_RG_WBG_EN_PLL_UP_MASK (MT_AFE_RG_WBG_EN_BPLL_UP_MASK | \ MT_AFE_RG_WBG_EN_WPLL_UP_MASK) -#define MT_AFE_RG_WBG_EN_TXCAL_MASK GENMASK(21, 17) +#define MT_AFE_RG_WBG_EN_TXCAL_WF4 BIT(29) +#define MT_AFE_RG_WBG_EN_TXCAL_BT BIT(21) +#define MT_AFE_RG_WBG_EN_TXCAL_WF3 BIT(20) +#define MT_AFE_RG_WBG_EN_TXCAL_WF2 BIT(19) +#define MT_AFE_RG_WBG_EN_TXCAL_WF1 BIT(18) +#define MT_AFE_RG_WBG_EN_TXCAL_WF0 BIT(17) #define MT_ADIE_SLP_CTRL_BASE(_band) (0x18005000 + ((_band) << 19)) #define MT_ADIE_SLP_CTRL(_band, ofs) (MT_ADIE_SLP_CTRL_BASE(_band) + (ofs)) @@ -1096,6 +1104,12 @@ enum offs_rev { #define MT_TOP_MCU_EMI_BASE MT_TOP(0x1c4) #define MT_TOP_MCU_EMI_BASE_MASK GENMASK(19, 0) +#define MT_TOP_WF_AP_PERI_BASE MT_TOP(0x1c8) +#define MT_TOP_WF_AP_PERI_BASE_MASK GENMASK(19, 0) + +#define MT_TOP_EFUSE_BASE MT_TOP(0x1cc) +#define MT_TOP_EFUSE_BASE_MASK GENMASK(19, 0) + #define MT_TOP_CONN_INFRA_WAKEUP MT_TOP(0x1a0) #define MT_TOP_CONN_INFRA_WAKEUP_MASK BIT(0) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c index 32c137066e7f..37348b208736 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/soc.c @@ -6,7 +6,6 @@ #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_reserved_mem.h> #include <linux/of_gpio.h> #include <linux/iopoll.h> @@ -16,6 +15,9 @@ #include "mt7915.h" +#define MT7981_CON_INFRA_VERSION 0x02090000 +#define MT7986_CON_INFRA_VERSION 0x02070000 + /* INFRACFG */ #define MT_INFRACFG_CONN2AP_SLPPROT 0x0d0 #define MT_INFRACFG_AP2CONN_SLPPROT 0x0d4 @@ -167,10 +169,14 @@ static u32 mt76_wmac_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) return val; } -static u8 mt7986_wmac_check_adie_type(struct mt7915_dev *dev) +static u8 mt798x_wmac_check_adie_type(struct mt7915_dev *dev) { u32 val; + /* Only DBDC A-die is used with MT7981 */ + if (is_mt7981(&dev->mt76)) + return ADIE_DBDC; + val = readl(dev->sku + MT_TOP_POS_SKU); return FIELD_GET(MT_TOP_POS_SKU_ADIE_DBDC_MASK, val); @@ -195,7 +201,7 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev) int ret; u8 type; - type = mt7986_wmac_check_adie_type(dev); + type = mt798x_wmac_check_adie_type(dev); pinctrl = devm_pinctrl_get(dev->mt76.dev); if (IS_ERR(pinctrl)) return PTR_ERR(pinctrl); @@ -257,16 +263,26 @@ static int mt7986_wmac_consys_lockup(struct mt7915_dev *dev, bool enable) return 0; } -static int mt7986_wmac_coninfra_check(struct mt7915_dev *dev) +static int mt798x_wmac_coninfra_check(struct mt7915_dev *dev) { u32 cur; + u32 con_infra_version; + + if (is_mt7981(&dev->mt76)) { + con_infra_version = MT7981_CON_INFRA_VERSION; + } else if (is_mt7986(&dev->mt76)) { + con_infra_version = MT7986_CON_INFRA_VERSION; + } else { + WARN_ON(1); + return -EINVAL; + } - return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000), + return read_poll_timeout(mt76_rr, cur, (cur == con_infra_version), USEC_PER_MSEC, 50 * USEC_PER_MSEC, false, dev, MT_CONN_INFRA_BASE); } -static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) +static int mt798x_wmac_coninfra_setup(struct mt7915_dev *dev) { struct device *pdev = dev->mt76.dev; struct reserved_mem *rmem; @@ -284,15 +300,25 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) val = (rmem->base >> 16) & MT_TOP_MCU_EMI_BASE_MASK; - /* Set conninfra subsys PLL check */ - mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, - MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); - mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, - MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + if (is_mt7986(&dev->mt76)) { + /* Set conninfra subsys PLL check */ + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + mt76_rmw_field(dev, MT_INFRA_CKGEN_BUS, + MT_INFRA_CKGEN_BUS_RDY_SEL_MASK, 0x1); + } mt76_rmw_field(dev, MT_TOP_MCU_EMI_BASE, MT_TOP_MCU_EMI_BASE_MASK, val); + if (is_mt7981(&dev->mt76)) { + mt76_rmw_field(dev, MT_TOP_WF_AP_PERI_BASE, + MT_TOP_WF_AP_PERI_BASE_MASK, 0x300d0000 >> 16); + + mt76_rmw_field(dev, MT_TOP_EFUSE_BASE, + MT_TOP_EFUSE_BASE_MASK, 0x11f20000 >> 16); + } + mt76_wr(dev, MT_INFRA_BUS_EMI_START, rmem->base); mt76_wr(dev, MT_INFRA_BUS_EMI_END, rmem->size); @@ -305,15 +331,18 @@ static int mt7986_wmac_coninfra_setup(struct mt7915_dev *dev) return 0; } -static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) +static int mt798x_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) { int ret; - u32 adie_main, adie_ext; + u32 adie_main = 0, adie_ext = 0; mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, MT_CONN_INFRA_ADIE1_RESET_MASK, 0x1); - mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, - MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); + + if (is_mt7986(&dev->mt76)) { + mt76_rmw_field(dev, MT_CONN_INFRA_ADIE_RESET, + MT_CONN_INFRA_ADIE2_RESET_MASK, 0x1); + } mt76_wmac_spi_lock(dev); @@ -321,9 +350,11 @@ static int mt7986_wmac_sku_setup(struct mt7915_dev *dev, u32 *adie_type) if (ret) goto out; - ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); - if (ret) - goto out; + if (is_mt7986(&dev->mt76)) { + ret = mt76_wmac_spi_read(dev, 1, MT_ADIE_CHIP_ID, &adie_ext); + if (ret) + goto out; + } *adie_type = FIELD_GET(MT_ADIE_CHIP_ID_MASK, adie_main) | (MT_ADIE_CHIP_ID_MASK & adie_ext); @@ -470,7 +501,7 @@ static int mt7986_wmac_adie_xtal_trim_7976(struct mt7915_dev *dev, u8 adie) return ret; } -static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) +static int mt798x_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) { u32 id, version, rg_xo_01, rg_xo_03; int ret; @@ -489,7 +520,14 @@ static int mt7986_wmac_adie_patch_7976(struct mt7915_dev *dev, u8 adie) rg_xo_01 = 0x1d59080f; rg_xo_03 = 0x34c00fe0; } else { - rg_xo_01 = 0x1959f80f; + if (is_mt7981(&dev->mt76)) { + rg_xo_01 = 0x1959c80f; + } else if (is_mt7986(&dev->mt76)) { + rg_xo_01 = 0x1959f80f; + } else { + WARN_ON(1); + return -EINVAL; + } rg_xo_03 = 0x34d00fe0; } @@ -611,7 +649,15 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) return ret; /* turn on SX0 LTBUF */ - ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); + if (is_mt7981(&dev->mt76)) { + ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000007); + } else if (is_mt7986(&dev->mt76)) { + ret = mt76_wmac_spi_write(dev, adie, 0x074, 0x00000002); + } else { + WARN_ON(1); + return -EINVAL; + } + if (ret) return ret; @@ -658,7 +704,10 @@ static int mt7986_wmac_adie_patch_7975(struct mt7915_dev *dev, u8 adie) return ret; /* set CKB driving and filter */ - return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); + if (is_mt7986(&dev->mt76)) + return mt76_wmac_spi_write(dev, adie, 0x2c8, 0x00000072); + + return ret; } static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) @@ -686,7 +735,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) ret = mt7986_wmac_adie_patch_7975(dev, adie); } else if (is_7976(dev, adie, adie_type)) { - if (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC) { + if (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC) { ret = mt76_wmac_spi_write(dev, adie, MT_ADIE_WRI_CK_SEL, 0x1c); if (ret) @@ -701,7 +750,7 @@ static int mt7986_wmac_adie_cfg(struct mt7915_dev *dev, u8 adie, u32 adie_type) if (ret) goto out; - ret = mt7986_wmac_adie_patch_7976(dev, adie); + ret = mt798x_wmac_adie_patch_7976(dev, adie); } out: mt76_wmac_spi_unlock(dev); @@ -714,6 +763,7 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) { int ret; u8 idx; + u32 txcal; mt76_wmac_spi_lock(dev); if (is_7975(dev, adie, adie_type)) @@ -744,12 +794,18 @@ mt7986_wmac_afe_cal(struct mt7915_dev *dev, u8 adie, bool dbdc, u32 adie_type) MT_AFE_RG_WBG_EN_WPLL_UP_MASK, 0x1); usleep_range(60, 100); - mt76_rmw_field(dev, MT_AFE_DIG_EN_01(idx), - MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x1f); + txcal = (MT_AFE_RG_WBG_EN_TXCAL_BT | + MT_AFE_RG_WBG_EN_TXCAL_WF0 | + MT_AFE_RG_WBG_EN_TXCAL_WF1 | + MT_AFE_RG_WBG_EN_TXCAL_WF2 | + MT_AFE_RG_WBG_EN_TXCAL_WF3); + if (is_mt7981(&dev->mt76)) + txcal |= MT_AFE_RG_WBG_EN_TXCAL_WF4; + + mt76_set(dev, MT_AFE_DIG_EN_01(idx), txcal); usleep_range(800, 1000); - mt76_rmw(dev, MT_AFE_DIG_EN_01(idx), - MT_AFE_RG_WBG_EN_TXCAL_MASK, 0x0); + mt76_clear(dev, MT_AFE_DIG_EN_01(idx), txcal); mt76_rmw(dev, MT_AFE_DIG_EN_03(idx), MT_AFE_RG_WBG_EN_PLL_UP_MASK, 0x0); @@ -806,7 +862,7 @@ static int mt7986_wmac_bus_timeout(struct mt7915_dev *dev) mt76_rmw_field(dev, MT_INFRA_BUS_ON_TIMEOUT, MT_INFRA_BUS_TIMEOUT_EN_MASK, 0xf); - return mt7986_wmac_coninfra_check(dev); + return mt798x_wmac_coninfra_check(dev); } static void mt7986_wmac_clock_enable(struct mt7915_dev *dev, u32 adie_type) @@ -876,14 +932,15 @@ static int mt7986_wmac_top_wfsys_wakeup(struct mt7915_dev *dev, bool enable) if (!enable) return 0; - return mt7986_wmac_coninfra_check(dev); + return mt798x_wmac_coninfra_check(dev); } static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable) { u32 cur; - mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0); + if (is_mt7986(&dev->mt76)) + mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0); mt76_rmw_field(dev, MT7986_TOP_WM_RESET, MT7986_TOP_WM_RESET_MASK, enable); @@ -1006,7 +1063,7 @@ mt7986_wmac_adie_setup(struct mt7915_dev *dev, u8 adie, u32 adie_type) if (ret) return ret; - if (!adie && (mt7986_wmac_check_adie_type(dev) == ADIE_DBDC)) + if (!adie && (mt798x_wmac_check_adie_type(dev) == ADIE_DBDC)) ret = mt7986_wmac_afe_cal(dev, adie, true, adie_type); return ret; @@ -1061,15 +1118,15 @@ int mt7986_wmac_enable(struct mt7915_dev *dev) if (ret) return ret; - ret = mt7986_wmac_coninfra_check(dev); + ret = mt798x_wmac_coninfra_check(dev); if (ret) return ret; - ret = mt7986_wmac_coninfra_setup(dev); + ret = mt798x_wmac_coninfra_setup(dev); if (ret) return ret; - ret = mt7986_wmac_sku_setup(dev, &adie_type); + ret = mt798x_wmac_sku_setup(dev, &adie_type); if (ret) return ret; @@ -1077,9 +1134,12 @@ int mt7986_wmac_enable(struct mt7915_dev *dev) if (ret) return ret; - ret = mt7986_wmac_adie_setup(dev, 1, adie_type); - if (ret) - return ret; + /* mt7981 doesn't support a second a-die */ + if (is_mt7986(&dev->mt76)) { + ret = mt7986_wmac_adie_setup(dev, 1, adie_type); + if (ret) + return ret; + } ret = mt7986_wmac_subsys_powerup(dev, adie_type); if (ret) @@ -1132,7 +1192,7 @@ void mt7986_wmac_disable(struct mt7915_dev *dev) mt7986_wmac_consys_reset(dev, false); } -static int mt7986_wmac_init(struct mt7915_dev *dev) +static int mt798x_wmac_init(struct mt7915_dev *dev) { struct device *pdev = dev->mt76.dev; struct platform_device *pfdev = to_platform_device(pdev); @@ -1165,7 +1225,7 @@ static int mt7986_wmac_init(struct mt7915_dev *dev) return 0; } -static int mt7986_wmac_probe(struct platform_device *pdev) +static int mt798x_wmac_probe(struct platform_device *pdev) { void __iomem *mem_base; struct mt7915_dev *dev; @@ -1203,7 +1263,7 @@ static int mt7986_wmac_probe(struct platform_device *pdev) if (ret) goto free_device; - ret = mt7986_wmac_init(dev); + ret = mt798x_wmac_init(dev); if (ret) goto free_irq; @@ -1225,7 +1285,7 @@ free_device: return ret; } -static int mt7986_wmac_remove(struct platform_device *pdev) +static int mt798x_wmac_remove(struct platform_device *pdev) { struct mt7915_dev *dev = platform_get_drvdata(pdev); @@ -1234,20 +1294,21 @@ static int mt7986_wmac_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id mt7986_wmac_of_match[] = { +static const struct of_device_id mt798x_wmac_of_match[] = { + { .compatible = "mediatek,mt7981-wmac", .data = (u32 *)0x7981 }, { .compatible = "mediatek,mt7986-wmac", .data = (u32 *)0x7986 }, {}, }; -MODULE_DEVICE_TABLE(of, mt7986_wmac_of_match); +MODULE_DEVICE_TABLE(of, mt798x_wmac_of_match); -struct platform_driver mt7986_wmac_driver = { +struct platform_driver mt798x_wmac_driver = { .driver = { - .name = "mt7986-wmac", - .of_match_table = mt7986_wmac_of_match, + .name = "mt798x-wmac", + .of_match_table = mt798x_wmac_of_match, }, - .probe = mt7986_wmac_probe, - .remove = mt7986_wmac_remove, + .probe = mt798x_wmac_probe, + .remove = mt798x_wmac_remove, }; MODULE_FIRMWARE(MT7986_FIRMWARE_WA); @@ -1255,3 +1316,7 @@ MODULE_FIRMWARE(MT7986_FIRMWARE_WM); MODULE_FIRMWARE(MT7986_FIRMWARE_WM_MT7975); MODULE_FIRMWARE(MT7986_ROM_PATCH); MODULE_FIRMWARE(MT7986_ROM_PATCH_MT7975); + +MODULE_FIRMWARE(MT7981_FIRMWARE_WA); +MODULE_FIRMWARE(MT7981_FIRMWARE_WM); +MODULE_FIRMWARE(MT7981_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig index adff2d7350b5..7ed51e057857 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: ISC config MT7921_COMMON tristate - select MT76_CONNAC_LIB + select MT792x_LIB select WANT_DEV_COREDUMP config MT7921E @@ -27,7 +27,7 @@ config MT7921S config MT7921U tristate "MediaTek MT7921U (USB) support" - select MT76_USB + select MT792x_USB select MT7921_COMMON depends on MAC80211 depends on USB diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile index e5d2d2e131a2..849be9e848e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7921/Makefile @@ -5,11 +5,8 @@ obj-$(CONFIG_MT7921E) += mt7921e.o obj-$(CONFIG_MT7921S) += mt7921s.o obj-$(CONFIG_MT7921U) += mt7921u.o -CFLAGS_trace.o := -I$(src) - -mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o +mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o -mt7921-common-$(CONFIG_ACPI) += acpi_sar.o -mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o +mt7921e-y := pci.o pci_mac.o pci_mcu.o mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o -mt7921u-y := usb.o usb_mac.o +mt7921u-y := usb.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h deleted file mode 100644 index 6f2c4a572572..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -/* Copyright (C) 2022 MediaTek Inc. */ - -#ifndef __MT7921_ACPI_SAR_H -#define __MT7921_ACPI_SAR_H - -#define MT7921_ASAR_MIN_DYN 1 -#define MT7921_ASAR_MAX_DYN 8 -#define MT7921_ASAR_MIN_GEO 3 -#define MT7921_ASAR_MAX_GEO 8 -#define MT7921_ASAR_MIN_FG 8 - -#define MT7921_ACPI_MTCL "MTCL" -#define MT7921_ACPI_MTDS "MTDS" -#define MT7921_ACPI_MTGS "MTGS" -#define MT7921_ACPI_MTFG "MTFG" - -struct mt7921_asar_dyn_limit { - u8 idx; - u8 frp[5]; -} __packed; - -struct mt7921_asar_dyn { - u8 names[4]; - u8 enable; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit, tbl); -} __packed; - -struct mt7921_asar_dyn_limit_v2 { - u8 idx; - u8 frp[11]; -} __packed; - -struct mt7921_asar_dyn_v2 { - u8 names[4]; - u8 enable; - u8 rsvd; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_dyn_limit_v2, tbl); -} __packed; - -struct mt7921_asar_geo_band { - u8 pwr; - u8 offset; -} __packed; - -struct mt7921_asar_geo_limit { - u8 idx; - /* 0:2G, 1:5G */ - struct mt7921_asar_geo_band band[2]; -} __packed; - -struct mt7921_asar_geo { - u8 names[4]; - u8 version; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit, tbl); -} __packed; - -struct mt7921_asar_geo_limit_v2 { - u8 idx; - /* 0:2G, 1:5G, 2:6G */ - struct mt7921_asar_geo_band band[3]; -} __packed; - -struct mt7921_asar_geo_v2 { - u8 names[4]; - u8 version; - u8 rsvd; - u8 nr_tbl; - DECLARE_FLEX_ARRAY(struct mt7921_asar_geo_limit_v2, tbl); -} __packed; - -struct mt7921_asar_cl { - u8 names[4]; - u8 version; - u8 mode_6g; - u8 cl6g[6]; -} __packed; - -struct mt7921_asar_fg { - u8 names[4]; - u8 version; - u8 rsvd; - u8 nr_flag; - u8 rsvd1; - u8 flag[]; -} __packed; - -struct mt7921_acpi_sar { - u8 ver; - union { - struct mt7921_asar_dyn *dyn; - struct mt7921_asar_dyn_v2 *dyn_v2; - }; - union { - struct mt7921_asar_geo *geo; - struct mt7921_asar_geo_v2 *geo_v2; - }; - struct mt7921_asar_cl *countrylist; - struct mt7921_asar_fg *fg; -}; - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c index d6b6edba2fec..616b66a3fde2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c @@ -6,11 +6,11 @@ static int mt7921_reg_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_wr(dev, dev->mt76.debugfs_reg, val); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -18,11 +18,11 @@ mt7921_reg_set(void *data, u64 val) static int mt7921_reg_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); *val = mt76_rr(dev, dev->mt76.debugfs_reg); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -32,14 +32,14 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, static int mt7921_fw_debug_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); dev->fw_debug = (u8)val; mt7921_mcu_fw_log_2_host(dev, dev->fw_debug); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -47,7 +47,7 @@ mt7921_fw_debug_set(void *data, u64 val) static int mt7921_fw_debug_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->fw_debug; @@ -57,128 +57,7 @@ mt7921_fw_debug_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get, mt7921_fw_debug_set, "%lld\n"); -static void -mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy, - struct seq_file *file) -{ - struct mt7921_dev *dev = file->private; - int bound[15], range[4], i; - - if (!phy) - return; - - mt7921_mac_update_mib_stats(phy); - - /* Tx ampdu stat */ - for (i = 0; i < ARRAY_SIZE(range); i++) - range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); - - for (i = 0; i < ARRAY_SIZE(bound); i++) - bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; - - seq_printf(file, "\nPhy0\n"); - - seq_printf(file, "Length: %8d | ", bound[0]); - for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) - seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); - - seq_puts(file, "\nCount: "); - for (i = 0; i < ARRAY_SIZE(bound); i++) - seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]); - seq_puts(file, "\n"); - - seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); -} - -static int -mt7921_tx_stats_show(struct seq_file *file, void *data) -{ - struct mt7921_dev *dev = file->private; - struct mt7921_phy *phy = &dev->phy; - struct mib_stats *mib = &phy->mib; - int i; - - mt7921_mutex_acquire(dev); - - mt7921_ampdu_stat_read_phy(phy, file); - - seq_puts(file, "Tx MSDU stat:\n"); - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { - seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ", - i + 1, mib->tx_amsdu[i]); - if (mib->tx_amsdu_cnt) - seq_printf(file, "(%3d%%)\n", - mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt); - else - seq_puts(file, "\n"); - } - - mt7921_mutex_release(dev); - - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(mt7921_tx_stats); - -static int -mt7921_queues_acq(struct seq_file *s, void *data) -{ - struct mt7921_dev *dev = dev_get_drvdata(s->private); - int i; - - mt7921_mutex_acquire(dev); - - for (i = 0; i < 4; i++) { - u32 ctrl, val, qlen = 0; - int j; - - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); - ctrl = BIT(31) | BIT(11) | (i << 24); - - for (j = 0; j < 32; j++) { - if (val & BIT(j)) - continue; - - mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); - qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, - GENMASK(11, 0)); - } - seq_printf(s, "AC%d: queued=%d\n", i, qlen); - } - - mt7921_mutex_release(dev); - - return 0; -} - -static int -mt7921_queues_read(struct seq_file *s, void *data) -{ - struct mt7921_dev *dev = dev_get_drvdata(s->private); - struct { - struct mt76_queue *q; - char *queue; - } queue_map[] = { - { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, - { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, - { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, - }; - int i; - - for (i = 0; i < ARRAY_SIZE(queue_map); i++) { - struct mt76_queue *q = queue_map[i].q; - - if (!q) - continue; - - seq_printf(s, - "%s: queued=%d head=%d tail=%d\n", - queue_map[i].queue, q->queued, q->head, - q->tail); - } - - return 0; -} +DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats); static void mt7921_seq_puts_array(struct seq_file *file, const char *str, @@ -211,13 +90,13 @@ mt7921_seq_puts_array(struct seq_file *file, const char *str, static int mt7921_txpwr(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct mt7921_txpwr txpwr; int ret; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt7921_get_txpwr_info(dev, &txpwr); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); if (ret) return ret; @@ -263,7 +142,7 @@ mt7921_txpwr(struct seq_file *s, void *data) static int mt7921_pm_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; if (mt76_is_usb(&dev->mt76)) @@ -296,7 +175,7 @@ out: static int mt7921_pm_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->pm.enable_user; @@ -308,7 +187,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n"); static int mt7921_deep_sleep_set(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; struct mt76_connac_pm *pm = &dev->pm; bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); bool enable = !!val; @@ -316,7 +195,7 @@ mt7921_deep_sleep_set(void *data, u64 val) if (mt76_is_usb(&dev->mt76)) return -EOPNOTSUPP; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (pm->ds_enable_user == enable) goto out; @@ -324,7 +203,7 @@ mt7921_deep_sleep_set(void *data, u64 val) pm->ds_enable = enable && !monitor; mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -332,7 +211,7 @@ out: static int mt7921_deep_sleep_get(void *data, u64 *val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; *val = dev->pm.ds_enable_user; @@ -342,67 +221,24 @@ mt7921_deep_sleep_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get, mt7921_deep_sleep_set, "%lld\n"); -static int -mt7921_pm_stats(struct seq_file *s, void *data) -{ - struct mt7921_dev *dev = dev_get_drvdata(s->private); - struct mt76_connac_pm *pm = &dev->pm; - - unsigned long awake_time = pm->stats.awake_time; - unsigned long doze_time = pm->stats.doze_time; - - if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) - awake_time += jiffies - pm->stats.last_wake_event; - else - doze_time += jiffies - pm->stats.last_doze_event; - - seq_printf(s, "awake time: %14u\ndoze time: %15u\n", - jiffies_to_msecs(awake_time), - jiffies_to_msecs(doze_time)); - - seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake); - - return 0; -} - -static int -mt7921_pm_idle_timeout_set(void *data, u64 val) -{ - struct mt7921_dev *dev = data; - - dev->pm.idle_timeout = msecs_to_jiffies(val); - - return 0; -} - -static int -mt7921_pm_idle_timeout_get(void *data, u64 *val) -{ - struct mt7921_dev *dev = data; - - *val = jiffies_to_msecs(dev->pm.idle_timeout); - - return 0; -} - -DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get, - mt7921_pm_idle_timeout_set, "%lld\n"); +DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get, + mt792x_pm_idle_timeout_set, "%lld\n"); static int mt7921_chip_reset(void *data, u64 val) { - struct mt7921_dev *dev = data; + struct mt792x_dev *dev = data; int ret = 0; switch (val) { case 1: /* Reset wifisys directly. */ - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); break; default: /* Collect the core dump before reset wifisys. */ - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt76_connac_mcu_chip_config(&dev->mt76); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); break; } @@ -414,7 +250,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n"); static int mt7921s_sched_quota_read(struct seq_file *s, void *data) { - struct mt7921_dev *dev = dev_get_drvdata(s->private); + struct mt792x_dev *dev = dev_get_drvdata(s->private); struct mt76_sdio *sdio = &dev->mt76.sdio; seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota); @@ -425,7 +261,7 @@ mt7921s_sched_quota_read(struct seq_file *s, void *data) return 0; } -int mt7921_init_debugfs(struct mt7921_dev *dev) +int mt7921_init_debugfs(struct mt792x_dev *dev) { struct dentry *dir; @@ -435,23 +271,23 @@ int mt7921_init_debugfs(struct mt7921_dev *dev) if (mt76_is_mmio(&dev->mt76)) debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", - dir, mt7921_queues_read); + dir, mt792x_queues_read); else debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir, mt76_queues_read); debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, - mt7921_queues_acq); + mt792x_queues_acq); debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, mt7921_txpwr); - debugfs_create_file("tx_stats", 0400, dir, dev, &mt7921_tx_stats_fops); + debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops); debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); debugfs_create_file("idle-timeout", 0600, dir, dev, &fops_pm_idle_timeout); debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset); debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, - mt7921_pm_stats); + mt792x_pm_stats); debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); if (mt76_is_sdio(&dev->mt76)) debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c index bf1da9fddfab..ff63f37f67d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c @@ -2,259 +2,84 @@ /* Copyright (C) 2020 MediaTek Inc. */ #include <linux/etherdevice.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/thermal.h> #include <linux/firmware.h> #include "mt7921.h" #include "../mt76_connac2_mac.h" #include "mcu.h" -static const struct ieee80211_iface_limit if_limits[] = { - { - .max = MT7921_MAX_INTERFACES, - .types = BIT(NL80211_IFTYPE_STATION) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_AP) +static ssize_t mt7921_thermal_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + switch (to_sensor_dev_attr(attr)->index) { + case 0: { + struct mt792x_phy *phy = dev_get_drvdata(dev); + struct mt792x_dev *mdev = phy->dev; + int temperature; + + mt792x_mutex_acquire(mdev); + temperature = mt7921_mcu_get_temperature(phy); + mt792x_mutex_release(mdev); + + if (temperature < 0) + return temperature; + /* display in millidegree Celsius */ + return sprintf(buf, "%u\n", temperature * 1000); } -}; + default: + return -EINVAL; + } +} +static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7921_thermal_temp, 0); -static const struct ieee80211_iface_combination if_comb[] = { - { - .limits = if_limits, - .n_limits = ARRAY_SIZE(if_limits), - .max_interfaces = MT7921_MAX_INTERFACES, - .num_different_channels = 1, - .beacon_int_infra_match = true, - }, +static struct attribute *mt7921_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, }; +ATTRIBUTE_GROUPS(mt7921_hwmon); -static const struct ieee80211_iface_limit if_limits_chanctx[] = { - { - .max = 2, - .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) - } -}; +static int mt7921_thermal_init(struct mt792x_phy *phy) +{ + struct wiphy *wiphy = phy->mt76->hw->wiphy; + struct device *hwmon; + const char *name; -static const struct ieee80211_iface_combination if_comb_chanctx[] = { - { - .limits = if_limits_chanctx, - .n_limits = ARRAY_SIZE(if_limits_chanctx), - .max_interfaces = 2, - .num_different_channels = 2, - .beacon_int_infra_match = false, - } -}; + if (!IS_REACHABLE(CONFIG_HWMON)) + return 0; + + name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7921_%s", + wiphy_name(wiphy)); + + hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, + mt7921_hwmon_groups); + if (IS_ERR(hwmon)) + return PTR_ERR(hwmon); + + return 0; +} static void mt7921_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; dev->country_ie_env = request->country_ie_env; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env); mt76_connac_mcu_set_channel_domain(hw->priv); mt7921_set_tx_sar_pwr(hw, NULL); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } -static int -mt7921_init_wiphy(struct ieee80211_hw *hw) -{ - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; - struct wiphy *wiphy = hw->wiphy; - - hw->queues = 4; - hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; - hw->netdev_features = NETIF_F_RXCSUM; - - hw->radiotap_timestamp.units_pos = - IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; - - phy->slottime = 9; - - hw->sta_data_size = sizeof(struct mt7921_sta); - hw->vif_data_size = sizeof(struct mt7921_vif); - - if (dev->fw_features & MT7921_FW_CAP_CNM) { - wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->iface_combinations = if_comb_chanctx; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx); - } else { - wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->iface_combinations = if_comb; - wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); - } - wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | - WIPHY_FLAG_4ADDR_STATION); - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); - wiphy->max_remain_on_channel_duration = 5000; - wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; - wiphy->max_scan_ssids = 4; - wiphy->max_sched_scan_plan_interval = - MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; - wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; - wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; - wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; - wiphy->max_sched_scan_reqs = 1; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - wiphy->reg_notifier = mt7921_regd_notifier; - - wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | - NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); - - ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); - ieee80211_hw_set(hw, HAS_RATE_CONTROL); - ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); - ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); - ieee80211_hw_set(hw, WANT_MONITOR_VIF); - ieee80211_hw_set(hw, SUPPORTS_PS); - ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); - ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); - ieee80211_hw_set(hw, CONNECTION_MONITOR); - - if (dev->pm.enable) - ieee80211_hw_set(hw, CONNECTION_MONITOR); - - hw->max_tx_fragments = 4; - - return 0; -} - -static void -mt7921_mac_init_band(struct mt7921_dev *dev, u8 band) -{ - u32 mask, set; - - mt76_rmw_field(dev, MT_TMAC_CTCR0(band), - MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); - mt76_set(dev, MT_TMAC_CTCR0(band), - MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | - MT_TMAC_CTCR0_INS_DDLMT_EN); - - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); - - /* enable MIB tx-rx time reporting */ - mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); - mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); - - mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); - /* disable rx rate report by default due to hw issues */ - mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); - - /* filter out non-resp frames and get instantaneous signal reporting */ - mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM; - set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | - FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); - mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); -} - -static u8 -mt7921_get_offload_capability(struct device *dev, const char *fw_wm) -{ - const struct mt76_connac2_fw_trailer *hdr; - struct mt7921_realease_info *rel_info; - const struct firmware *fw; - int ret, i, offset = 0; - const u8 *data, *end; - u8 offload_caps = 0; - - ret = request_firmware(&fw, fw_wm, dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev, "Invalid firmware\n"); - goto out; - } - - data = fw->data; - hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); - - for (i = 0; i < hdr->n_region; i++) { - const struct mt76_connac2_fw_region *region; - - region = (const void *)((const u8 *)hdr - - (hdr->n_region - i) * sizeof(*region)); - offset += le32_to_cpu(region->len); - } - - data += offset + 16; - rel_info = (struct mt7921_realease_info *)data; - data += sizeof(*rel_info); - end = data + le16_to_cpu(rel_info->len); - - while (data < end) { - rel_info = (struct mt7921_realease_info *)data; - data += sizeof(*rel_info); - - if (rel_info->tag == MT7921_FW_TAG_FEATURE) { - struct mt7921_fw_features *features; - - features = (struct mt7921_fw_features *)data; - offload_caps = features->data; - break; - } - - data += le16_to_cpu(rel_info->len) + rel_info->pad_len; - } - -out: - release_firmware(fw); - - return offload_caps; -} - -struct ieee80211_ops * -mt7921_get_mac80211_ops(struct device *dev, void *drv_data, u8 *fw_features) -{ - struct ieee80211_ops *ops; - - ops = devm_kmemdup(dev, &mt7921_ops, sizeof(mt7921_ops), GFP_KERNEL); - if (!ops) - return NULL; - - *fw_features = mt7921_get_offload_capability(dev, drv_data); - if (!(*fw_features & MT7921_FW_CAP_CNM)) { - ops->remain_on_channel = NULL; - ops->cancel_remain_on_channel = NULL; - ops->add_chanctx = NULL; - ops->remove_chanctx = NULL; - ops->change_chanctx = NULL; - ops->assign_vif_chanctx = NULL; - ops->unassign_vif_chanctx = NULL; - ops->mgd_prepare_tx = NULL; - ops->mgd_complete_tx = NULL; - } - return ops; -} -EXPORT_SYMBOL_GPL(mt7921_get_mac80211_ops); - -int mt7921_mac_init(struct mt7921_dev *dev) +int mt7921_mac_init(struct mt792x_dev *dev) { int i; @@ -264,17 +89,17 @@ int mt7921_mac_init(struct mt7921_dev *dev) /* enable hardware rx header translation */ mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN); - for (i = 0; i < MT7921_WTBL_SIZE; i++) + for (i = 0; i < MT792x_WTBL_SIZE; i++) mt7921_mac_wtbl_update(dev, i, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); for (i = 0; i < 2; i++) - mt7921_mac_init_band(dev, i); + mt792x_mac_init_band(dev, i); return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0); } EXPORT_SYMBOL_GPL(mt7921_mac_init); -static int __mt7921_init_hardware(struct mt7921_dev *dev) +static int __mt7921_init_hardware(struct mt792x_dev *dev) { int ret; @@ -282,7 +107,7 @@ static int __mt7921_init_hardware(struct mt7921_dev *dev) * which should be set before firmware download stage. */ mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - ret = mt7921_mcu_init(dev); + ret = mt792x_mcu_init(dev); if (ret) goto out; @@ -297,21 +122,21 @@ out: return ret; } -static int mt7921_init_hardware(struct mt7921_dev *dev) +static int mt7921_init_hardware(struct mt792x_dev *dev) { int ret, i; set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - for (i = 0; i < MT7921_MCU_INIT_RETRY_COUNT; i++) { + for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) { ret = __mt7921_init_hardware(dev); if (!ret) break; - mt7921_init_reset(dev); + mt792x_init_reset(dev); } - if (i == MT7921_MCU_INIT_RETRY_COUNT) { + if (i == MT792x_MCU_INIT_RETRY_COUNT) { dev_err(dev->mt76.dev, "hardware init failed\n"); return ret; } @@ -319,26 +144,9 @@ static int mt7921_init_hardware(struct mt7921_dev *dev) return 0; } -static int mt7921_init_wcid(struct mt7921_dev *dev) -{ - int idx; - - /* Beacon and mgmt frames should occupy wcid 0 */ - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); - if (idx) - return -ENOSPC; - - dev->mt76.global_wcid.idx = idx; - dev->mt76.global_wcid.hw_key_idx = -1; - dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET; - rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); - - return 0; -} - static void mt7921_init_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, init_work); int ret; @@ -362,13 +170,19 @@ static void mt7921_init_work(struct work_struct *work) return; } + ret = mt7921_thermal_init(&dev->phy); + if (ret) { + dev_err(dev->mt76.dev, "thermal init failed\n"); + return; + } + /* we support chip reset now */ dev->hw_init_done = true; mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable); } -int mt7921_register_device(struct mt7921_dev *dev) +int mt7921_register_device(struct mt792x_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); int ret; @@ -376,17 +190,17 @@ int mt7921_register_device(struct mt7921_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; - dev->mt76.tx_worker.fn = mt7921_tx_worker; + dev->mt76.tx_worker.fn = mt792x_tx_worker; - INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work); - INIT_WORK(&dev->pm.wake_work, mt7921_pm_wake_work); + INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work); + INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work); spin_lock_init(&dev->pm.wake.lock); mutex_init(&dev->pm.mutex); init_waitqueue_head(&dev->pm.wait); if (mt76_is_sdio(&dev->mt76)) init_waitqueue_head(&dev->mt76.sdio.wait); spin_lock_init(&dev->pm.txq_lock); - INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work); + INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work); INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work); INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work); #if IS_ENABLED(CONFIG_IPV6) @@ -395,17 +209,15 @@ int mt7921_register_device(struct mt7921_dev *dev) #endif skb_queue_head_init(&dev->phy.scan_event_list); skb_queue_head_init(&dev->coredump.msg_list); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); INIT_WORK(&dev->reset_work, mt7921_mac_reset_work); INIT_WORK(&dev->init_work, mt7921_init_work); INIT_WORK(&dev->phy.roc_work, mt7921_roc_work); - timer_setup(&dev->phy.roc_timer, mt7921_roc_timer, 0); + timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0); init_waitqueue_head(&dev->phy.roc_wait); - dev->pm.idle_timeout = MT7921_PM_TIMEOUT; + dev->pm.idle_timeout = MT792x_PM_TIMEOUT; dev->pm.stats.last_wake_event = jiffies; dev->pm.stats.last_doze_event = jiffies; if (!mt76_is_usb(&dev->mt76)) { @@ -418,16 +230,17 @@ int mt7921_register_device(struct mt7921_dev *dev) if (!mt76_is_mmio(&dev->mt76)) hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; - mt7921_init_acpi_sar(dev); + mt792x_init_acpi_sar(dev); - ret = mt7921_init_wcid(dev); + ret = mt792x_init_wcid(dev); if (ret) return ret; - ret = mt7921_init_wiphy(hw); + ret = mt792x_init_wiphy(hw); if (ret) return ret; + hw->wiphy->reg_notifier = mt7921_regd_notifier; dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING | IEEE80211_HT_CAP_MAX_AMSDU; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c index 1675bf520481..21f937454229 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c @@ -15,35 +15,7 @@ #define MT_WTBL_AC0_CTT_OFFSET 20 -static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) -{ - return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; -} - -static struct mt76_wcid *mt7921_rx_get_wcid(struct mt7921_dev *dev, - u16 idx, bool unicast) -{ - struct mt7921_sta *sta; - struct mt76_wcid *wcid; - - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) - return NULL; - - wcid = rcu_dereference(dev->mt76.wcid[idx]); - if (unicast || !wcid) - return wcid; - - if (!wcid->sta) - return NULL; - - sta = container_of(wcid, struct mt7921_sta, wcid); - if (!sta->vif) - return NULL; - - return &sta->vif->sta.wcid; -} - -bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask) { mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); @@ -52,7 +24,12 @@ bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask) 0, 5000); } -void mt7921_mac_sta_poll(struct mt7921_dev *dev) +static u32 mt7921_mac_wtbl_lmac_addr(int idx, u8 offset) +{ + return MT_WTBL_LMAC_OFFS(idx, 0) + offset * 4; +} + +static void mt7921_mac_sta_poll(struct mt792x_dev *dev) { static const u8 ac_to_tid[] = { [IEEE80211_AC_BE] = 0, @@ -61,16 +38,16 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) [IEEE80211_AC_VO] = 6 }; struct ieee80211_sta *sta; - struct mt7921_sta *msta; + struct mt792x_sta *msta; u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS]; LIST_HEAD(sta_poll_list); struct rate_info *rate; s8 rssi[4]; int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); while (true) { bool clear = false; @@ -78,15 +55,15 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) u16 idx; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, - struct mt7921_sta, poll_list); - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + struct mt792x_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; addr = mt7921_mac_wtbl_lmac_addr(idx, MT_WTBL_AC0_CTT_OFFSET); @@ -183,56 +160,9 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev) ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal); } } -EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll); - -static void -mt7921_get_status_freq_info(struct mt7921_dev *dev, struct mt76_phy *mphy, - struct mt76_rx_status *status, u8 chfreq) -{ - if (chfreq > 180) { - status->band = NL80211_BAND_6GHZ; - chfreq = (chfreq - 181) * 4 + 1; - } else if (chfreq > 14) { - status->band = NL80211_BAND_5GHZ; - } else { - status->band = NL80211_BAND_2GHZ; - } - status->freq = ieee80211_channel_to_frequency(chfreq, status->band); -} - -static void -mt7921_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) -{ - struct sk_buff *skb = priv; - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); - - if (status->signal > 0) - return; - - if (!ether_addr_equal(vif->addr, hdr->addr1)) - return; - - ewma_rssi_add(&mvif->rssi, -status->signal); -} - -static void -mt7921_mac_assoc_rssi(struct mt7921_dev *dev, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); - - if (!ieee80211_is_assoc_resp(hdr->frame_control) && - !ieee80211_is_auth(hdr->frame_control)) - return; - - ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), - IEEE80211_IFACE_ITER_RESUME_ALL, - mt7921_mac_rssi_iter, skb); -} static int -mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb) { u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; @@ -241,7 +171,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) u16 hdr_gap; __le32 *rxv = NULL, *rxd = (__le32 *)skb->data; struct mt76_phy *mphy = &dev->mt76.phy; - struct mt7921_phy *phy = &dev->phy; + struct mt792x_phy *phy = &dev->phy; struct ieee80211_supported_band *sband; u32 csum_status = *(u32 *)skb->cb; u32 rxd0 = le32_to_cpu(rxd[0]); @@ -249,7 +179,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); u32 rxd4 = le32_to_cpu(rxd[4]); - struct mt7921_sta *msta = NULL; + struct mt792x_sta *msta = NULL; u16 seq_ctrl = 0; __le16 fc = 0; u8 mode = 0; @@ -277,17 +207,18 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3); unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); - status->wcid = mt7921_rx_get_wcid(dev, idx, unicast); + status->wcid = mt792x_rx_get_wcid(dev, idx, unicast); if (status->wcid) { - msta = container_of(status->wcid, struct mt7921_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + msta = container_of(status->wcid, struct mt792x_sta, wcid); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } - mt7921_get_status_freq_info(dev, mphy, status, chfreq); + mt792x_get_status_freq_info(status, chfreq); switch (status->band) { case NL80211_BAND_5GHZ: @@ -496,7 +427,7 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_8023; } - mt7921_mac_assoc_rssi(dev, skb); + mt792x_mac_assoc_rssi(dev, skb); if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv, mode); @@ -511,33 +442,9 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb) return 0; } -static void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) +void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data) { - struct mt7921_sta *msta; - u16 fc, tid; - u32 val; - - if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)) - return; - - tid = le32_get_bits(txwi[1], MT_TXD1_TID); - if (tid >= 6) /* skip VO queue */ - return; - - val = le32_to_cpu(txwi[2]); - fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | - FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; - if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA))) - return; - - msta = (struct mt7921_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) - ieee80211_start_tx_ba_session(sta, tid, 0); -} - -void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) -{ - struct mt7921_sta *msta = NULL; + struct mt792x_sta *msta = NULL; struct mt76_wcid *wcid; __le32 *txs_data = data; u16 wcidx; @@ -552,7 +459,7 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) if (pid < MT_PACKET_ID_FIRST) return; - if (wcidx >= MT7921_WTBL_SIZE) + if (wcidx >= MT792x_WTBL_SIZE) return; rcu_read_lock(); @@ -561,59 +468,29 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data) if (!wcid) goto out; - msta = container_of(wcid, struct mt7921_sta, wcid); + msta = container_of(wcid, struct mt792x_sta, wcid); mt76_connac2_mac_add_txs_skb(&dev->mt76, wcid, pid, txs_data); if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); } -void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, - struct list_head *free_list) -{ - struct mt76_dev *mdev = &dev->mt76; - __le32 *txwi; - u16 wcid_idx; - - mt76_connac_txp_skb_unmap(mdev, t); - if (!t->skb) - goto out; - - txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t); - if (sta) { - struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; - - if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); - - wcid_idx = wcid->idx; - } else { - wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); - } - - __mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list); -out: - t->skb = NULL; - mt76_put_txwi(mdev, t); -} -EXPORT_SYMBOL_GPL(mt7921_txwi_free); - -static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) +static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) { struct mt76_connac_tx_free *free = data; __le32 *tx_info = (__le32 *)(data + sizeof(*free)); struct mt76_dev *mdev = &dev->mt76; struct mt76_txwi_cache *txwi; struct ieee80211_sta *sta = NULL; + struct mt76_wcid *wcid = NULL; struct sk_buff *skb, *tmp; void *end = data + len; LIST_HEAD(free_list); @@ -636,8 +513,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) * 1'b0: msdu_id with the same 'wcid pair' as above. */ if (info & MT_TX_FREE_PAIR) { - struct mt7921_sta *msta; - struct mt76_wcid *wcid; + struct mt792x_sta *msta; u16 idx; count++; @@ -647,22 +523,29 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) if (!sta) continue; - msta = container_of(wcid, struct mt7921_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + msta = container_of(wcid, struct mt792x_sta, wcid); + spin_lock_bh(&mdev->sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); stat = FIELD_GET(MT_TX_FREE_STATUS, info); + if (wcid) { + wcid->stats.tx_retries += + FIELD_GET(MT_TX_FREE_COUNT, info) - 1; + wcid->stats.tx_failed += !!stat; + } + txwi = mt76_token_release(mdev, msdu, &wake); if (!txwi) continue; - mt7921_txwi_free(dev, txwi, sta, stat, &free_list); + mt76_connac2_txwi_free(mdev, txwi, sta, &free_list); } if (wake) @@ -682,7 +565,7 @@ static void mt7921_mac_tx_free(struct mt7921_dev *dev, void *data, int len) bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); __le32 *rxd = (__le32 *)data; __le32 *end = (__le32 *)&rxd[len / 4]; enum rx_pkt_type type; @@ -707,7 +590,7 @@ EXPORT_SYMBOL_GPL(mt7921_rx_check); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); __le32 *rxd = (__le32 *)skb->data; __le32 *end = (__le32 *)&skb->data[skb->len]; enum rx_pkt_type type; @@ -747,128 +630,12 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } EXPORT_SYMBOL_GPL(mt7921_queue_rx_skb); -void mt7921_mac_reset_counters(struct mt7921_phy *phy) -{ - struct mt7921_dev *dev = phy->dev; - int i; - - for (i = 0; i < 4; i++) { - mt76_rr(dev, MT_TX_AGG_CNT(0, i)); - mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); - } - - dev->mt76.phy.survey_time = ktime_get_boottime(); - memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); - - /* reset airtime counters */ - mt76_rr(dev, MT_MIB_SDR9(0)); - mt76_rr(dev, MT_MIB_SDR36(0)); - mt76_rr(dev, MT_MIB_SDR37(0)); - - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); - mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); -} - -void mt7921_mac_set_timing(struct mt7921_phy *phy) -{ - s16 coverage_class = phy->coverage_class; - struct mt7921_dev *dev = phy->dev; - u32 val, reg_offset; - u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); - u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); - bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; - int sifs = is_2ghz ? 10 : 16, offset; - - if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) - return; - - mt76_set(dev, MT_ARB_SCR(0), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); - udelay(1); - - offset = 3 * coverage_class; - reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | - FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); - - mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset); - mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset); - mt76_wr(dev, MT_TMAC_ICR0(0), - FIELD_PREP(MT_IFS_EIFS, 360) | - FIELD_PREP(MT_IFS_RIFS, 2) | - FIELD_PREP(MT_IFS_SIFS, sifs) | - FIELD_PREP(MT_IFS_SLOT, phy->slottime)); - - if (phy->slottime < 20 || !is_2ghz) - val = MT7921_CFEND_RATE_DEFAULT; - else - val = MT7921_CFEND_RATE_11B; - - mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val); - mt76_clear(dev, MT_ARB_SCR(0), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); -} - -static u8 -mt7921_phy_get_nf(struct mt7921_phy *phy, int idx) -{ - return 0; -} - -static void -mt7921_phy_update_channel(struct mt76_phy *mphy, int idx) -{ - struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); - struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv; - struct mt76_channel_state *state; - u64 busy_time, tx_time, rx_time, obss_time; - int nf; - - busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), - MT_MIB_SDR9_BUSY_MASK); - tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), - MT_MIB_SDR36_TXTIME_MASK); - rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), - MT_MIB_SDR37_RXTIME_MASK); - obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), - MT_MIB_OBSSTIME_MASK); - - nf = mt7921_phy_get_nf(phy, idx); - if (!phy->noise) - phy->noise = nf << 4; - else if (nf) - phy->noise += nf - (phy->noise >> 4); - - state = mphy->chan_state; - state->cc_busy += busy_time; - state->cc_tx += tx_time; - state->cc_rx += rx_time + obss_time; - state->cc_bss_rx += rx_time; - state->noise = -(phy->noise >> 4); -} - -void mt7921_update_channel(struct mt76_phy *mphy) -{ - struct mt7921_dev *dev = container_of(mphy->dev, struct mt7921_dev, mt76); - - if (mt76_connac_pm_wake(mphy, &dev->pm)) - return; - - mt7921_phy_update_channel(mphy, 0); - /* reset obss airtime */ - mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); - - mt76_connac_power_save_sched(mphy, &dev->pm); -} -EXPORT_SYMBOL_GPL(mt7921_update_channel); - static void mt7921_vif_connect_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mvif->phy->dev; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mvif->phy->dev; struct ieee80211_hw *hw = mt76_hw(dev); if (vif->type == NL80211_IFTYPE_STATION) @@ -889,7 +656,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac, /* system error recovery */ void mt7921_mac_reset_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, reset_work); struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; @@ -905,7 +672,7 @@ void mt7921_mac_reset_work(struct work_struct *work) for (i = 0; i < 10; i++) { mutex_lock(&dev->mt76.mutex); - ret = mt7921_dev_reset(dev); + ret = mt792x_dev_reset(dev); mutex_unlock(&dev->mt76.mutex); if (!ret) @@ -932,185 +699,12 @@ void mt7921_mac_reset_work(struct work_struct *work) mt76_connac_power_save_sched(&dev->mt76.phy, pm); } -void mt7921_reset(struct mt76_dev *mdev) -{ - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt76_connac_pm *pm = &dev->pm; - - if (!dev->hw_init_done) - return; - - if (dev->hw_full_reset) - return; - - if (pm->suspended) - return; - - queue_work(dev->mt76.wq, &dev->reset_work); -} -EXPORT_SYMBOL_GPL(mt7921_reset); - -void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) -{ - struct mt7921_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; - int i, aggr0 = 0, aggr1; - u32 val; - - mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0), - MT_MIB_SDR3_FCS_ERR_MASK); - mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0), - MT_MIB_ACK_FAIL_COUNT_MASK); - mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0), - MT_MIB_BA_FAIL_COUNT_MASK); - mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0), - MT_MIB_RTS_COUNT_MASK); - mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), - MT_MIB_RTS_FAIL_COUNT_MASK); - - mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0)); - mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0)); - mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0)); - - val = mt76_rr(dev, MT_MIB_SDR32(0)); - mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val); - mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val); - - val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0)); - mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val); - mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val); - - val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0)); - mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val); - mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val); - mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val); - mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val); - - mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0)); - mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0)); - mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0)); - mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0)); - - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { - val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); - mib->tx_amsdu[i] += val; - mib->tx_amsdu_cnt += val; - } - - for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { - u32 val2; - - val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); - val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); - - phy->mt76->aggr_stats[aggr0++] += val & 0xffff; - phy->mt76->aggr_stats[aggr0++] += val >> 16; - phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff; - phy->mt76->aggr_stats[aggr1++] += val2 >> 16; - } -} - -void mt7921_mac_work(struct work_struct *work) -{ - struct mt7921_phy *phy; - struct mt76_phy *mphy; - - mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, - mac_work.work); - phy = mphy->priv; - - mt7921_mutex_acquire(phy->dev); - - mt76_update_survey(mphy); - if (++mphy->mac_work_count == 2) { - mphy->mac_work_count = 0; - - mt7921_mac_update_mib_stats(phy); - } - - mt7921_mutex_release(phy->dev); - - mt76_tx_status_check(mphy->dev, false); - ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); -} - -void mt7921_pm_wake_work(struct work_struct *work) -{ - struct mt7921_dev *dev; - struct mt76_phy *mphy; - - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, - pm.wake_work); - mphy = dev->phy.mt76; - - if (!mt7921_mcu_drv_pmctrl(dev)) { - struct mt76_dev *mdev = &dev->mt76; - int i; - - if (mt76_is_sdio(mdev)) { - mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - mt76_worker_schedule(&mdev->sdio.txrx_worker); - } else { - local_bh_disable(); - mt76_for_each_q_rx(mdev, i) - napi_schedule(&mdev->napi[i]); - local_bh_enable(); - mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - mt76_connac_tx_cleanup(mdev); - } - if (test_bit(MT76_STATE_RUNNING, &mphy->state)) - ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); - } - - ieee80211_wake_queues(mphy->hw); - wake_up(&dev->pm.wait); -} - -void mt7921_pm_power_save_work(struct work_struct *work) -{ - struct mt7921_dev *dev; - unsigned long delta; - struct mt76_phy *mphy; - - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, - pm.ps_work.work); - mphy = dev->phy.mt76; - - delta = dev->pm.idle_timeout; - if (test_bit(MT76_HW_SCANNING, &mphy->state) || - test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) || - dev->fw_assert) - goto out; - - if (mutex_is_locked(&dev->mt76.mutex)) - /* if mt76 mutex is held we should not put the device - * to sleep since we are currently accessing device - * register map. We need to wait for the next power_save - * trigger. - */ - goto out; - - if (time_is_after_jiffies(dev->pm.last_activity + delta)) { - delta = dev->pm.last_activity + delta - jiffies; - goto out; - } - - if (!mt7921_mcu_fw_pmctrl(dev)) { - cancel_delayed_work_sync(&mphy->mac_work); - return; - } -out: - queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta); -} - void mt7921_coredump_work(struct work_struct *work) { - struct mt7921_dev *dev; + struct mt792x_dev *dev; char *dump, *data; - dev = (struct mt7921_dev *)container_of(work, struct mt7921_dev, + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, coredump.work.work); if (time_is_after_jiffies(dev->coredump.last_activity + @@ -1149,12 +743,12 @@ void mt7921_coredump_work(struct work_struct *work) dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ, GFP_KERNEL); - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); } /* usb_sdio */ static void -mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, +mt7921_usb_sdio_write_txwi(struct mt792x_dev *dev, struct mt76_wcid *wcid, enum mt76_txq_id qid, struct ieee80211_sta *sta, struct ieee80211_key_conf *key, int pid, struct sk_buff *skb) @@ -1171,7 +765,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct sk_buff *skb = tx_info->skb; @@ -1180,11 +774,15 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (unlikely(tx_info->skb->len <= ETH_HLEN)) return -EINVAL; + err = skb_cow_head(skb, MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE); + if (err) + return err; + if (!wcid) wcid = &dev->mt76.global_wcid; if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; if (time_after(jiffies, msta->last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -1224,7 +822,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, sta = wcid_to_sta(wcid); if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) - mt7921_tx_check_aggr(sta, txwi); + mt76_connac2_tx_check_aggr(sta, txwi); skb_pull(e->skb, headroom); mt76_tx_complete_skb(mdev, e->wcid, e->skb); @@ -1233,11 +831,11 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb); bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mac_sta_poll(dev); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return false; } @@ -1246,8 +844,8 @@ EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data); #if IS_ENABLED(CONFIG_IPV6) void mt7921_set_ipv6_ns_work(struct work_struct *work) { - struct mt7921_dev *dev = container_of(work, struct mt7921_dev, - ipv6_ns_work); + struct mt792x_dev *dev = container_of(work, struct mt792x_dev, + ipv6_ns_work); struct sk_buff *skb; int ret = 0; @@ -1257,10 +855,10 @@ void mt7921_set_ipv6_ns_work(struct work_struct *work) if (!skb) break; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD(OFFLOAD), true); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } while (!ret); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index 3b6adb29cbef..0844d28b3223 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -10,7 +10,7 @@ #include "mcu.h" static int -mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, +mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, struct ieee80211_sband_iftype_data *data) { int i, idx = 0; @@ -185,7 +185,7 @@ mt7921_init_he_caps(struct mt7921_phy *phy, enum nl80211_band band, return idx; } -void mt7921_set_stream_he_caps(struct mt7921_phy *phy) +void mt7921_set_stream_he_caps(struct mt792x_phy *phy) { struct ieee80211_sband_iftype_data *data; struct ieee80211_supported_band *band; @@ -219,7 +219,7 @@ void mt7921_set_stream_he_caps(struct mt7921_phy *phy) } } -int __mt7921_start(struct mt7921_phy *phy) +int __mt7921_start(struct mt792x_phy *phy) { struct mt76_phy *mphy = phy->mt76; int err; @@ -240,11 +240,11 @@ int __mt7921_start(struct mt7921_phy *phy) if (err) return err; - mt7921_mac_reset_counters(phy); + mt792x_mac_reset_counters(phy); set_bit(MT76_STATE_RUNNING, &mphy->state); ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); return 0; } @@ -252,20 +252,20 @@ EXPORT_SYMBOL_GPL(__mt7921_start); static int mt7921_start(struct ieee80211_hw *hw) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int err; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); err = __mt7921_start(phy); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } void mt7921_stop(struct ieee80211_hw *hw) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -274,26 +274,26 @@ void mt7921_stop(struct ieee80211_hw *hw) cancel_work_sync(&dev->reset_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } EXPORT_SYMBOL_GPL(mt7921_stop); -static int mt7921_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int +mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); struct mt76_txq *mtxq; int idx, ret = 0; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mvif->mt76.idx >= MT7921_MAX_INTERFACES) { + if (mvif->mt76.idx >= MT792x_MAX_INTERFACES) { ret = -ENOSPC; goto out; } @@ -311,9 +311,9 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - idx = MT7921_WTBL_RESERVED - mvif->mt76.idx; + idx = MT792x_WTBL_RESERVED - mvif->mt76.idx; - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = mvif->mt76.band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -333,89 +333,55 @@ static int mt7921_add_interface(struct ieee80211_hw *hw, vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } -static void mt7921_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_sta *msta = &mvif->sta; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); - int idx = msta->wcid.idx; - - mt7921_mutex_acquire(dev); - mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); - - rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - - dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); - phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); - mt7921_mutex_release(dev); - - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); - - mt76_packet_id_flush(&dev->mt76, &msta->wcid); -} - static void mt7921_roc_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_phy *phy = priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = priv; mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id); } void mt7921_roc_work(struct work_struct *work) { - struct mt7921_phy *phy; + struct mt792x_phy *phy; - phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy, + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, roc_work); if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7921_roc_iter, phy); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); ieee80211_remain_on_channel_expired(phy->mt76->hw); } -void mt7921_roc_timer(struct timer_list *timer) -{ - struct mt7921_phy *phy = from_timer(phy, timer, roc_timer); - - ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); -} - -static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif) +static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif) { int err = 0; del_timer_sync(&phy->roc_timer); cancel_work_sync(&phy->roc_work); - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } -static int mt7921_set_roc(struct mt7921_phy *phy, - struct mt7921_vif *vif, +static int mt7921_set_roc(struct mt792x_phy *phy, + struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type) @@ -450,13 +416,13 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, int duration, enum ieee80211_roc_type type) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); int err; - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); err = mt7921_set_roc(phy, mvif, chan, duration, MT7921_ROC_REQ_ROC); - mt7921_mutex_release(phy->dev); + mt792x_mutex_release(phy->dev); return err; } @@ -464,20 +430,20 @@ static int mt7921_remain_on_channel(struct ieee80211_hw *hw, static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); return mt7921_abort_roc(phy, mvif); } -static int mt7921_set_channel(struct mt7921_phy *phy) +static int mt7921_set_channel(struct mt792x_phy *phy) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; int ret; cancel_delayed_work_sync(&phy->mt76->mac_work); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); set_bit(MT76_RESET, &phy->mt76->state); mt76_set_channel(phy->mt76); @@ -486,18 +452,18 @@ static int mt7921_set_channel(struct mt7921_phy *phy) if (ret) goto out; - mt7921_mac_set_timing(phy); + mt792x_mac_set_timeing(phy); - mt7921_mac_reset_counters(phy); + mt792x_mac_reset_counters(phy); phy->noise = 0; out: clear_bit(MT76_RESET, &phy->mt76->state); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); mt76_worker_schedule(&dev->mt76.tx_worker); ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); return ret; } @@ -506,9 +472,9 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_sta *msta = sta ? (struct mt7921_sta *)sta->drv_priv : + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = sta ? (struct mt792x_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; u8 *wcid_keyidx = &wcid->hw_key_idx; @@ -546,7 +512,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (cmd == SET_KEY) { *wcid_keyidx = idx; @@ -570,7 +536,7 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key, MCU_UNI_CMD(STA_REC_UPDATE), &mvif->wep_sta->wcid, cmd); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -578,7 +544,7 @@ out: static void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = priv; + struct mt792x_dev *dev = priv; struct ieee80211_hw *hw = mt76_hw(dev); bool pm_enable = dev->pm.enable; int err; @@ -599,7 +565,7 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) static void mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = priv; + struct mt792x_dev *dev = priv; struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR); @@ -614,7 +580,7 @@ mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt7921_mcu_set_beacon_filter(dev, vif, false); } -void mt7921_set_runtime_pm(struct mt7921_dev *dev) +void mt7921_set_runtime_pm(struct mt792x_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); struct mt76_connac_pm *pm = &dev->pm; @@ -630,8 +596,8 @@ void mt7921_set_runtime_pm(struct mt7921_dev *dev) static int mt7921_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int ret = 0; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -642,7 +608,7 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) ieee80211_wake_queues(hw); } - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (changed & IEEE80211_CONF_CHANGE_POWER) { ret = mt7921_set_tx_sar_pwr(hw, NULL); @@ -657,25 +623,11 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed) } out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } -static int -mt7921_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - unsigned int link_id, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - - /* no need to update right away, we'll get BSS_CHANGED_QOS */ - queue = mt76_connac_lmac_mapping(queue); - mvif->queue_params[queue] = *params; - - return 0; -} - static void mt7921_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -686,7 +638,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, #define MT7921_FILTER_OTHER_BSS BIT(6) #define MT7921_FILTER_ENABLE BIT(31) - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); u32 flags = MT7921_FILTER_ENABLE; #define MT7921_FILTER(_fif, _type) do { \ @@ -698,9 +650,9 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw, MT7921_FILTER(FIF_CONTROL, CONTROL); MT7921_FILTER(FIF_OTHER_BSS, OTHER_BSS); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_set_rxfilter(dev, flags, 0, 0); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); *total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL); } @@ -710,17 +662,17 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u64 changed) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; if (slottime != phy->slottime) { phy->slottime = slottime; - mt7921_mac_set_timing(phy); + mt792x_mac_set_timeing(phy); } } @@ -743,28 +695,28 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_ARP_FILTER) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt76_connac_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, info); } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int ret, idx; - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); if (idx < 0) return -ENOSPC; - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -796,11 +748,11 @@ EXPORT_SYMBOL_GPL(mt7921_mac_sta_add); void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid, @@ -814,15 +766,15 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } EXPORT_SYMBOL_GPL(mt7921_mac_sta_assoc); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); mt76_connac_pm_wake(&dev->mphy, &dev->pm); @@ -832,7 +784,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); if (vif->type == NL80211_IFTYPE_STATION) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mvif->wep_sta = NULL; ewma_rssi_init(&mvif->rssi); @@ -842,76 +794,22 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, mvif->ctx); } - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_connac_power_save_sched(&dev->mphy, &dev->pm); } EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove); -void mt7921_tx_worker(struct mt76_worker *w) -{ - struct mt7921_dev *dev = container_of(w, struct mt7921_dev, - mt76.tx_worker); - - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return; - } - - mt76_txq_schedule_all(&dev->mphy); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); -} - -static void mt7921_tx(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt76_phy *mphy = hw->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - int qid; - - if (control->sta) { - struct mt7921_sta *sta; - - sta = (struct mt7921_sta *)control->sta->drv_priv; - wcid = &sta->wcid; - } - - if (vif && !control->sta) { - struct mt7921_vif *mvif; - - mvif = (struct mt7921_vif *)vif->drv_priv; - wcid = &mvif->sta.wcid; - } - - if (mt76_connac_pm_ref(mphy, &dev->pm)) { - mt76_tx(mphy, control->sta, wcid, skb); - mt76_connac_pm_unref(mphy, &dev->pm); - return; - } - - qid = skb_get_queue_mapping(skb); - if (qid >= MT_TXQ_PSD) { - qid = IEEE80211_AC_BE; - skb_set_queue_mapping(skb, qid); - } - - mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb); -} - static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, 0); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } @@ -921,10 +819,10 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; u16 tid = params->tid; u16 ssn = params->ssn; struct mt76_txq *mtxq; @@ -935,7 +833,7 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mtxq = (struct mt76_txq *)txq->drv_priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); switch (action) { case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, @@ -954,21 +852,21 @@ mt7921_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); mt7921_mcu_uni_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return ret; } @@ -979,289 +877,22 @@ static int mt7921_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); if (dev->pm.ds_enable) { - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_sta_state_dp(&dev->mt76, old_state, new_state); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } return mt76_sta_state(hw, vif, sta, old_state, new_state); } -static int -mt7921_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mib_stats *mib = &phy->mib; - - mt7921_mutex_acquire(phy->dev); - - stats->dot11RTSSuccessCount = mib->rts_cnt; - stats->dot11RTSFailureCount = mib->rts_retries_cnt; - stats->dot11FCSErrorCount = mib->fcs_err_cnt; - stats->dot11ACKFailureCount = mib->ack_fail_cnt; - - mt7921_mutex_release(phy->dev); - - return 0; -} - -static const char mt7921_gstrings_stats[][ETH_GSTRING_LEN] = { - /* tx counters */ - "tx_ampdu_cnt", - "tx_mpdu_attempts", - "tx_mpdu_success", - "tx_pkt_ebf_cnt", - "tx_pkt_ibf_cnt", - "tx_ampdu_len:0-1", - "tx_ampdu_len:2-10", - "tx_ampdu_len:11-19", - "tx_ampdu_len:20-28", - "tx_ampdu_len:29-37", - "tx_ampdu_len:38-46", - "tx_ampdu_len:47-55", - "tx_ampdu_len:56-79", - "tx_ampdu_len:80-103", - "tx_ampdu_len:104-127", - "tx_ampdu_len:128-151", - "tx_ampdu_len:152-175", - "tx_ampdu_len:176-199", - "tx_ampdu_len:200-223", - "tx_ampdu_len:224-247", - "ba_miss_count", - "tx_beamformer_ppdu_iBF", - "tx_beamformer_ppdu_eBF", - "tx_beamformer_rx_feedback_all", - "tx_beamformer_rx_feedback_he", - "tx_beamformer_rx_feedback_vht", - "tx_beamformer_rx_feedback_ht", - "tx_msdu_pack_1", - "tx_msdu_pack_2", - "tx_msdu_pack_3", - "tx_msdu_pack_4", - "tx_msdu_pack_5", - "tx_msdu_pack_6", - "tx_msdu_pack_7", - "tx_msdu_pack_8", - /* rx counters */ - "rx_mpdu_cnt", - "rx_ampdu_cnt", - "rx_ampdu_bytes_cnt", - "rx_ba_cnt", - /* per vif counters */ - "v_tx_mode_cck", - "v_tx_mode_ofdm", - "v_tx_mode_ht", - "v_tx_mode_ht_gf", - "v_tx_mode_vht", - "v_tx_mode_he_su", - "v_tx_mode_he_ext_su", - "v_tx_mode_he_tb", - "v_tx_mode_he_mu", - "v_tx_bw_20", - "v_tx_bw_40", - "v_tx_bw_80", - "v_tx_bw_160", - "v_tx_mcs_0", - "v_tx_mcs_1", - "v_tx_mcs_2", - "v_tx_mcs_3", - "v_tx_mcs_4", - "v_tx_mcs_5", - "v_tx_mcs_6", - "v_tx_mcs_7", - "v_tx_mcs_8", - "v_tx_mcs_9", - "v_tx_mcs_10", - "v_tx_mcs_11", -}; - -static void -mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 sset, u8 *data) -{ - struct mt7921_dev *dev = mt7921_hw_dev(hw); - - if (sset != ETH_SS_STATS) - return; - - memcpy(data, *mt7921_gstrings_stats, sizeof(mt7921_gstrings_stats)); - - if (mt76_is_sdio(&dev->mt76)) - return; - - data += sizeof(mt7921_gstrings_stats); - page_pool_ethtool_stats_get_strings(data); -} - -static int -mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - int sset) -{ - struct mt7921_dev *dev = mt7921_hw_dev(hw); - - if (sset != ETH_SS_STATS) - return 0; - - if (mt76_is_sdio(&dev->mt76)) - return ARRAY_SIZE(mt7921_gstrings_stats); - - return ARRAY_SIZE(mt7921_gstrings_stats) + - page_pool_ethtool_stats_get_count(); -} - -static void -mt7921_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) -{ - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt76_ethtool_worker_info *wi = wi_data; - - if (msta->vif->mt76.idx != wi->idx) - return; - - mt76_ethtool_worker(wi, &msta->wcid.stats, false); -} - -static -void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ethtool_stats *stats, u64 *data) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - int stats_size = ARRAY_SIZE(mt7921_gstrings_stats); - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; - struct mt76_ethtool_worker_info wi = { - .data = data, - .idx = mvif->mt76.idx, - }; - int i, ei = 0; - - mt7921_mutex_acquire(dev); - - mt7921_mac_update_mib_stats(phy); - - data[ei++] = mib->tx_ampdu_cnt; - data[ei++] = mib->tx_mpdu_attempts_cnt; - data[ei++] = mib->tx_mpdu_success_cnt; - data[ei++] = mib->tx_pkt_ebf_cnt; - data[ei++] = mib->tx_pkt_ibf_cnt; - - /* Tx ampdu stat */ - for (i = 0; i < 15; i++) - data[ei++] = phy->mt76->aggr_stats[i]; - - data[ei++] = phy->mib.ba_miss_cnt; - - /* Tx Beamformer monitor */ - data[ei++] = mib->tx_bf_ibf_ppdu_cnt; - data[ei++] = mib->tx_bf_ebf_ppdu_cnt; - - /* Tx Beamformer Rx feedback monitor */ - data[ei++] = mib->tx_bf_rx_fb_all_cnt; - data[ei++] = mib->tx_bf_rx_fb_he_cnt; - data[ei++] = mib->tx_bf_rx_fb_vht_cnt; - data[ei++] = mib->tx_bf_rx_fb_ht_cnt; - - /* Tx amsdu info (pack-count histogram) */ - for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) - data[ei++] = mib->tx_amsdu[i]; - - /* rx counters */ - data[ei++] = mib->rx_mpdu_cnt; - data[ei++] = mib->rx_ampdu_cnt; - data[ei++] = mib->rx_ampdu_bytes_cnt; - data[ei++] = mib->rx_ba_cnt; - - /* Add values for all stations owned by this vif */ - wi.initial_stat_idx = ei; - ieee80211_iterate_stations_atomic(hw, mt7921_ethtool_worker, &wi); - - mt7921_mutex_release(dev); - - if (!wi.sta_count) - return; - - ei += wi.worker_stat_count; - - if (!mt76_is_sdio(&dev->mt76)) { - mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); - stats_size += page_pool_ethtool_stats_get_count(); - } - - if (ei != stats_size) - dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, stats_size); -} - -static u64 -mt7921_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; - union { - u64 t64; - u32 t32[2]; - } tsf; - u16 n; - - mt7921_mutex_acquire(dev); - - n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; - /* TSF software read */ - mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE); - tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); - tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); - - mt7921_mutex_release(dev); - - return tsf.t64; -} - -static void -mt7921_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u64 timestamp) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - u8 omac_idx = mvif->mt76.omac_idx; - union { - u64 t64; - u32 t32[2]; - } tsf = { .t64 = timestamp, }; - u16 n; - - mt7921_mutex_acquire(dev); - - n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; - mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); - mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]); - /* TSF software overwrite */ - mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); - - mt7921_mutex_release(dev); -} - -static void -mt7921_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) -{ - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = phy->dev; - - mt7921_mutex_acquire(dev); - phy->coverage_class = max_t(s16, coverage_class, 0); - mt7921_mac_set_timing(phy); - mt7921_mutex_release(dev); -} - void mt7921_scan_work(struct work_struct *work) { - struct mt7921_phy *phy; + struct mt792x_phy *phy; - phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy, + phy = (struct mt792x_phy *)container_of(work, struct mt792x_phy, scan_work.work); while (true) { @@ -1294,13 +925,13 @@ static int mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *req) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_hw_scan(mphy, vif, req); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1308,12 +939,12 @@ mt7921_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static void mt7921_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_cancel_hw_scan(mphy, vif); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int @@ -1321,11 +952,11 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_sched_scan_request *req, struct ieee80211_scan_ies *ies) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_sched_scan_req(mphy, vif, req); if (err < 0) @@ -1333,7 +964,7 @@ mt7921_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = mt76_connac_mcu_sched_scan_enable(mphy, vif, true); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1341,13 +972,13 @@ out: static int mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); struct mt76_phy *mphy = hw->priv; int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_sched_scan_enable(mphy, vif, false); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1355,17 +986,17 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); int max_nss = hweight8(hw->wiphy->available_antennas_tx); if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) return -EINVAL; if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) - tx_ant = BIT(ffs(tx_ant) - 1) - 1; + return -EINVAL; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); phy->mt76->antenna_mask = tx_ant; phy->mt76->chainmask = tx_ant; @@ -1373,48 +1004,17 @@ mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) mt76_set_stream_caps(phy->mt76, true); mt7921_set_stream_he_caps(phy); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } -static void mt7921_sta_statistics(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct station_info *sinfo) -{ - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct rate_info *txrate = &msta->wcid.rate; - - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; - } - sinfo->txrate.flags = txrate->flags; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); - - sinfo->ack_signal = (s8)msta->ack_signal; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); - - sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); -} - #ifdef CONFIG_PM static int mt7921_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mt76->mac_work); @@ -1422,7 +1022,7 @@ static int mt7921_suspend(struct ieee80211_hw *hw, cancel_delayed_work_sync(&dev->pm.ps_work); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, @@ -1430,17 +1030,17 @@ static int mt7921_suspend(struct ieee80211_hw *hw, mt7921_mcu_set_suspend_iter, &dev->mphy); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } static int mt7921_resume(struct ieee80211_hw *hw) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); set_bit(MT76_STATE_RUNNING, &phy->mt76->state); ieee80211_iterate_active_interfaces(hw, @@ -1449,51 +1049,34 @@ static int mt7921_resume(struct ieee80211_hw *hw) &dev->mphy); ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work, - MT7921_WATCHDOG_TIME); + MT792x_WATCHDOG_TIME); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return 0; } -static void mt7921_set_wakeup(struct ieee80211_hw *hw, bool enabled) -{ - struct mt7921_dev *dev = mt7921_hw_dev(hw); - struct mt76_dev *mdev = &dev->mt76; - - device_set_wakeup_enable(mdev->dev, enabled); -} - static void mt7921_set_rekey_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_gtk_rekey_data *data) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt76_connac_mcu_update_gtk_rekey(hw, vif, data); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } #endif /* CONFIG_PM */ -static void mt7921_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) -{ - struct mt7921_dev *dev = mt7921_hw_dev(hw); - - wait_event_timeout(dev->mt76.tx_wait, !mt76_has_tx_pending(&dev->mphy), - HZ / 2); -} - static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enabled) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); if (enabled) set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); @@ -1503,7 +1086,7 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, MCU_UNI_CMD(STA_REC_UPDATE)); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } #if IS_ENABLED(CONFIG_IPV6) @@ -1511,8 +1094,8 @@ static void mt7921_ipv6_addr_change(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct inet6_dev *idev) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mvif->phy->dev; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mvif->phy->dev; struct inet6_ifaddr *ifa; struct in6_addr ns_addrs[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; struct sk_buff *skb; @@ -1570,28 +1153,25 @@ int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { struct mt76_phy *mphy = hw->priv; - int err; if (sar) { - err = mt76_init_sar_power(hw, sar); + int err = mt76_init_sar_power(hw, sar); + if (err) return err; } + mt792x_init_acpi_sar_power(mt792x_hw_phy(hw), !sar); - mt7921_init_acpi_sar_power(mt7921_hw_phy(hw), !sar); - - err = mt76_connac_mcu_set_rate_txpower(mphy); - - return err; + return mt76_connac_mcu_set_rate_txpower(mphy); } static int mt7921_set_sar_specs(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env); if (err < 0) @@ -1599,7 +1179,7 @@ static int mt7921_set_sar_specs(struct ieee80211_hw *hw, err = mt7921_set_tx_sar_pwr(hw, sar); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1609,23 +1189,23 @@ mt7921_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, true, mvif->ctx); @@ -1639,7 +1219,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = mt7921_mcu_sta_update(dev, NULL, vif, true, MT76_STA_INFO_STATE_NONE); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); return err; } @@ -1648,12 +1228,12 @@ static void mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *link_conf) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_phy *phy = mt7921_hw_phy(hw); - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = mt792x_hw_dev(hw); int err; - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); err = mt7921_mcu_set_bss_pm(dev, vif, false); if (err) @@ -1663,7 +1243,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, mvif->ctx); out: - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static int @@ -1682,7 +1262,7 @@ mt7921_remove_chanctx(struct ieee80211_hw *hw, static void mt7921_ctx_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct ieee80211_chanctx_conf *ctx = priv; if (ctx != mvif->ctx) @@ -1699,77 +1279,47 @@ mt7921_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { - struct mt7921_phy *phy = mt7921_hw_phy(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); - mt7921_mutex_acquire(phy->dev); + mt792x_mutex_acquire(phy->dev); ieee80211_iterate_active_interfaces(phy->mt76->hw, IEEE80211_IFACE_ITER_ACTIVE, mt7921_ctx_iter, ctx); - mt7921_mutex_release(phy->dev); -} - -static int -mt7921_assign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf, - struct ieee80211_chanctx_conf *ctx) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - - mutex_lock(&dev->mt76.mutex); - mvif->ctx = ctx; - mutex_unlock(&dev->mt76.mutex); - - return 0; -} - -static void -mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf, - struct ieee80211_chanctx_conf *ctx) -{ - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); - - mutex_lock(&dev->mt76.mutex); - mvif->ctx = NULL; - mutex_unlock(&dev->mt76.mutex); + mt792x_mutex_release(phy->dev); } static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; - struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); u16 duration = info->duration ? info->duration : jiffies_to_msecs(HZ); - mt7921_mutex_acquire(dev); + mt792x_mutex_acquire(dev); mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration, MT7921_ROC_REQ_JOIN); - mt7921_mutex_release(dev); + mt792x_mutex_release(dev); } static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_prep_tx_info *info) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; mt7921_abort_roc(mvif->phy, mvif); } const struct ieee80211_ops mt7921_ops = { - .tx = mt7921_tx, + .tx = mt792x_tx, .start = mt7921_start, .stop = mt7921_stop, .add_interface = mt7921_add_interface, - .remove_interface = mt7921_remove_interface, + .remove_interface = mt792x_remove_interface, .config = mt7921_config, - .conf_tx = mt7921_conf_tx, + .conf_tx = mt792x_conf_tx, .configure_filter = mt7921_configure_filter, .bss_info_changed = mt7921_bss_info_changed, .start_ap = mt7921_start_ap, @@ -1787,19 +1337,19 @@ const struct ieee80211_ops mt7921_ops = { .release_buffered_frames = mt76_release_buffered_frames, .channel_switch_beacon = mt7921_channel_switch_beacon, .get_txpower = mt76_get_txpower, - .get_stats = mt7921_get_stats, - .get_et_sset_count = mt7921_get_et_sset_count, - .get_et_strings = mt7921_get_et_strings, - .get_et_stats = mt7921_get_et_stats, - .get_tsf = mt7921_get_tsf, - .set_tsf = mt7921_set_tsf, + .get_stats = mt792x_get_stats, + .get_et_sset_count = mt792x_get_et_sset_count, + .get_et_strings = mt792x_get_et_strings, + .get_et_stats = mt792x_get_et_stats, + .get_tsf = mt792x_get_tsf, + .set_tsf = mt792x_set_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, .set_antenna = mt7921_set_antenna, - .set_coverage_class = mt7921_set_coverage_class, + .set_coverage_class = mt792x_set_coverage_class, .hw_scan = mt7921_hw_scan, .cancel_hw_scan = mt7921_cancel_hw_scan, - .sta_statistics = mt7921_sta_statistics, + .sta_statistics = mt792x_sta_statistics, .sched_scan_start = mt7921_start_sched_scan, .sched_scan_stop = mt7921_stop_sched_scan, CFG80211_TESTMODE_CMD(mt7921_testmode_cmd) @@ -1807,18 +1357,18 @@ const struct ieee80211_ops mt7921_ops = { #ifdef CONFIG_PM .suspend = mt7921_suspend, .resume = mt7921_resume, - .set_wakeup = mt7921_set_wakeup, + .set_wakeup = mt792x_set_wakeup, .set_rekey_data = mt7921_set_rekey_data, #endif /* CONFIG_PM */ - .flush = mt7921_flush, + .flush = mt792x_flush, .set_sar_specs = mt7921_set_sar_specs, .remain_on_channel = mt7921_remain_on_channel, .cancel_remain_on_channel = mt7921_cancel_remain_on_channel, .add_chanctx = mt7921_add_chanctx, .remove_chanctx = mt7921_remove_chanctx, .change_chanctx = mt7921_change_chanctx, - .assign_vif_chanctx = mt7921_assign_vif_chanctx, - .unassign_vif_chanctx = mt7921_unassign_vif_chanctx, + .assign_vif_chanctx = mt792x_assign_vif_chanctx, + .unassign_vif_chanctx = mt792x_unassign_vif_chanctx, .mgd_prepare_tx = mt7921_mgd_prepare_tx, .mgd_complete_tx = mt7921_mgd_complete_tx, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c index f55caa00ac69..90c93970acab 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -4,9 +4,9 @@ #include <linux/fs.h> #include <linux/firmware.h> #include "mt7921.h" -#include "mt7921_trace.h" #include "mcu.h" #include "../mt76_connac2_mac.h" +#include "../mt792x_trace.h" #define MT_STA_BFER BIT(0) #define MT_STA_BFEE BIT(1) @@ -25,7 +25,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, if (!skb) { dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", cmd, seq); - mt7921_reset(mdev); + mt792x_reset(mdev); return -ETIMEDOUT; } @@ -69,7 +69,7 @@ int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, } EXPORT_SYMBOL_GPL(mt7921_mcu_parse_response); -static int mt7921_mcu_read_eeprom(struct mt7921_dev *dev, u32 offset, u8 *val) +static int mt7921_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) { struct mt7921_mcu_eeprom_info *res, req = { .addr = cpu_to_le32(round_down(offset, @@ -96,7 +96,7 @@ static int mt7921_mcu_set_ipv6_ns_filter(struct mt76_dev *dev, struct ieee80211_vif *vif, bool suspend) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -134,7 +134,7 @@ void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) #endif /* CONFIG_PM */ static void -mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_uni_roc_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_roc_grant_tlv *grant; struct mt76_connac2_mcu_rxd *rxd; @@ -157,17 +157,17 @@ mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; - struct mt7921_phy *phy = (struct mt7921_phy *)mphy->priv; + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; spin_lock_bh(&dev->mt76.lock); __skb_queue_tail(&phy->scan_event_list, skb); spin_unlock_bh(&dev->mt76.lock); ieee80211_queue_delayed_work(mphy->hw, &phy->scan_work, - MT7921_HW_SCAN_TIMEOUT); + MT792x_HW_SCAN_TIMEOUT); } static void @@ -188,7 +188,7 @@ mt7921_mcu_connection_loss_iter(void *priv, u8 *mac, } static void -mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_connection_loss_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac_beacon_loss_event *event; struct mt76_phy *mphy = &dev->mt76.phy; @@ -202,7 +202,7 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_debug_msg { __le16 id; @@ -229,7 +229,7 @@ mt7921_mcu_debug_msg_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_low_power_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_mcu_lp_event { u8 state; @@ -243,7 +243,7 @@ mt7921_mcu_low_power_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt7921_mcu_tx_done_event *event; @@ -254,7 +254,7 @@ mt7921_mcu_tx_done_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) +mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -288,7 +288,7 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb) } static void -mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev, +mt7921_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -305,7 +305,7 @@ mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev, dev_kfree_skb(skb); } -void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) +void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb) { struct mt76_connac2_mcu_rxd *rxd; @@ -339,11 +339,11 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb) } /** starec & wtbl **/ -int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; if (enable && !params->amsdu) msta->wcid.amsdu = false; @@ -353,48 +353,24 @@ int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, enable, true); } -int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable) { - struct mt7921_sta *msta = (struct mt7921_sta *)params->sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; return mt76_connac_mcu_sta_ba(&dev->mt76, &msta->vif->mt76, params, MCU_UNI_CMD(STA_REC_UPDATE), enable, false); } -static char *mt7921_patch_name(struct mt7921_dev *dev) -{ - char *ret; - - if (is_mt7922(&dev->mt76)) - ret = MT7922_ROM_PATCH; - else - ret = MT7921_ROM_PATCH; - - return ret; -} - -static char *mt7921_ram_name(struct mt7921_dev *dev) -{ - char *ret; - - if (is_mt7922(&dev->mt76)) - ret = MT7922_FIRMWARE_WM; - else - ret = MT7921_FIRMWARE_WM; - - return ret; -} - -static int mt7921_load_clc(struct mt7921_dev *dev, const char *fw_name) +static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name) { const struct mt76_connac2_fw_trailer *hdr; const struct mt76_connac2_fw_region *region; const struct mt7921_clc *clc; struct mt76_dev *mdev = &dev->mt76; - struct mt7921_phy *phy = &dev->phy; + struct mt792x_phy *phy = &dev->phy; const struct firmware *fw; int ret, i, len, offset = 0; u8 *clc_base = NULL, hw_encap = 0; @@ -472,42 +448,7 @@ out: return ret; } -static int mt7921_load_firmware(struct mt7921_dev *dev) -{ - int ret; - - ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev)); - if (ret) - return ret; - - if (mt76_is_sdio(&dev->mt76)) { - /* activate again */ - ret = __mt7921_mcu_fw_pmctrl(dev); - if (!ret) - ret = __mt7921_mcu_drv_pmctrl(dev); - } - - ret = mt76_connac2_load_ram(&dev->mt76, mt7921_ram_name(dev), NULL); - if (ret) - return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, - MT_TOP_MISC2_FW_N9_RDY, 1500)) { - dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); - - return -EIO; - } - -#ifdef CONFIG_PM - dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; -#endif /* CONFIG_PM */ - - dev_dbg(dev->mt76.dev, "Firmware init done\n"); - - return 0; -} - -int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) +int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl) { struct { u8 ctrl_val; @@ -520,11 +461,11 @@ int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl) &data, sizeof(data), false); } -int mt7921_run_firmware(struct mt7921_dev *dev) +int mt7921_run_firmware(struct mt792x_dev *dev) { int err; - err = mt7921_load_firmware(dev); + err = mt792x_load_firmware(dev); if (err) return err; @@ -533,7 +474,7 @@ int mt7921_run_firmware(struct mt7921_dev *dev) return err; set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); - err = mt7921_load_clc(dev, mt7921_ram_name(dev)); + err = mt7921_load_clc(dev, mt792x_ram_name(dev)); if (err) return err; @@ -541,9 +482,9 @@ int mt7921_run_firmware(struct mt7921_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_run_firmware); -int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) +int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct edca { __le16 cw_min; __le16 cw_max; @@ -635,12 +576,12 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif) &req_mu, sizeof(req_mu), false); } -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id) { int center_ch = ieee80211_frequency_to_channel(chan->center_freq); - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct { struct { u8 rsv[4]; @@ -702,10 +643,10 @@ int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct { struct { u8 rsv[4]; @@ -732,9 +673,9 @@ int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) +int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd) { - struct mt7921_dev *dev = phy->dev; + struct mt792x_dev *dev = phy->dev; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1; struct { @@ -791,7 +732,7 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd) return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } -int mt7921_mcu_set_eeprom(struct mt7921_dev *dev) +int mt7921_mcu_set_eeprom(struct mt792x_dev *dev) { struct req_hdr { u8 buffer_mode; @@ -807,9 +748,9 @@ int mt7921_mcu_set_eeprom(struct mt7921_dev *dev) } EXPORT_SYMBOL_GPL(mt7921_mcu_set_eeprom); -int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) +int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -845,10 +786,10 @@ int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif) } static int -mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, +mt7921_mcu_uni_bss_bcnft(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { struct { u8 bss_idx; @@ -881,10 +822,10 @@ mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif, } int -mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, +mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct { u8 bss_idx; u8 dtim_period; @@ -918,11 +859,11 @@ mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, &req, sizeof(req), false); } -int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, +int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; int rssi = -ewma_rssi_read(&mvif->rssi); struct mt76_sta_cmd_info info = { .sta = sta, @@ -933,60 +874,16 @@ int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, .offload_fw = true, .rcpi = to_rcpi(rssi), }; - struct mt7921_sta *msta; + struct mt792x_sta *msta; - msta = sta ? (struct mt7921_sta *)sta->drv_priv : NULL; + msta = sta ? (struct mt792x_sta *)sta->drv_priv : NULL; info.wcid = msta ? &msta->wcid : &mvif->sta.wcid; info.newly = msta ? state != MT76_STA_INFO_STATE_ASSOC : true; return mt76_connac_mcu_sta_cmd(&dev->mphy, &info); } -int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err = 0; - - mutex_lock(&pm->mutex); - - if (!test_bit(MT76_STATE_PM, &mphy->state)) - goto out; - - err = __mt7921_mcu_drv_pmctrl(dev); -out: - mutex_unlock(&pm->mutex); - - if (err) - mt7921_reset(&dev->mt76); - - return err; -} -EXPORT_SYMBOL_GPL(mt7921_mcu_drv_pmctrl); - -int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err = 0; - - mutex_lock(&pm->mutex); - - if (mt76_connac_skip_fw_pmctrl(mphy, pm)) - goto out; - - err = __mt7921_mcu_fw_pmctrl(dev); -out: - mutex_unlock(&pm->mutex); - - if (err) - mt7921_reset(&dev->mt76); - - return err; -} -EXPORT_SYMBOL_GPL(mt7921_mcu_fw_pmctrl); - -int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, +int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { @@ -1021,7 +918,7 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, return 0; } -int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) +int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr) { struct mt7921_txpwr_event *event; struct mt7921_txpwr_req req = { @@ -1044,7 +941,7 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr) return 0; } -int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, +int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable) { struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; @@ -1074,7 +971,7 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, true); } -int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, +int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx) { struct cfg80211_chan_def *chandef = &ctx->def; @@ -1143,12 +1040,12 @@ int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, } int -mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, +mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable) { - struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; struct mt76_wcid *wcid = &dev->mt76.global_wcid; struct ieee80211_mutable_offsets offs; struct { @@ -1221,7 +1118,7 @@ mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, } static -int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap, struct mt7921_clc *clc, u8 idx) @@ -1241,7 +1138,7 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, } __packed req = { .idx = idx, .env = env_cap, - .acpi_conf = mt7921_acpi_get_flags(&dev->phy), + .acpi_conf = mt792x_acpi_get_flags(&dev->phy), }; int ret, valid_cnt = 0; u8 i, *pos; @@ -1283,10 +1180,10 @@ int __mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, return 0; } -int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap) { - struct mt7921_phy *phy = (struct mt7921_phy *)&dev->phy; + struct mt792x_phy *phy = (struct mt792x_phy *)&dev->phy; int i, ret; /* submit all clc config */ @@ -1305,7 +1202,24 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, return 0; } -int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, +int mt7921_mcu_get_temperature(struct mt792x_phy *phy) +{ + struct mt792x_dev *dev = phy->dev; + struct { + u8 ctrl_id; + u8 action; + u8 band_idx; + u8 rsv[5]; + } req = { + .ctrl_id = THERMAL_SENSOR_TEMP_QUERY, + .band_idx = phy->mt76->band_idx, + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_CTRL), &req, + sizeof(req), true); +} + +int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map) { struct { diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h index 149acb1662d5..87dd06855f68 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h @@ -4,22 +4,8 @@ #ifndef __MT7921_H #define __MT7921_H -#include <linux/interrupt.h> -#include <linux/ktime.h> -#include "../mt76_connac_mcu.h" +#include "../mt792x.h" #include "regs.h" -#include "acpi_sar.h" - -#define MT7921_MAX_INTERFACES 4 -#define MT7921_WTBL_SIZE 20 -#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1) -#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \ - MT7921_MAX_INTERFACES) - -#define MT7921_PM_TIMEOUT (HZ / 12) -#define MT7921_HW_SCAN_TIMEOUT (HZ / 10) -#define MT7921_WATCHDOG_TIME (HZ / 4) -#define MT7921_RESET_TIMEOUT (30 * HZ) #define MT7921_TX_RING_SIZE 2048 #define MT7921_TX_MCU_RING_SIZE 256 @@ -28,27 +14,11 @@ #define MT7921_RX_RING_SIZE 1536 #define MT7921_RX_MCU_RING_SIZE 512 -#define MT7921_DRV_OWN_RETRY_COUNT 10 -#define MT7921_MCU_INIT_RETRY_COUNT 10 -#define MT7921_WFSYS_INIT_RETRY_COUNT 2 - -#define MT7921_FW_TAG_FEATURE 4 -#define MT7921_FW_CAP_CNM BIT(7) - -#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" -#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" - -#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin" -#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin" - #define MT7921_EEPROM_SIZE 3584 #define MT7921_TOKEN_SIZE 8192 #define MT7921_EEPROM_BLOCK_SIZE 16 -#define MT7921_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ -#define MT7921_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ - #define MT7921_SKU_RATE_NUM 161 #define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM #define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1) @@ -128,9 +98,6 @@ struct mt7921_sdio_intr { #define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) #define to_rcpi(rssi) (2 * (rssi) + 220) -struct mt7921_vif; -struct mt7921_sta; - enum mt7921_txq_id { MT7921_TXQ_BAND0, MT7921_TXQ_BAND1, @@ -144,70 +111,6 @@ enum mt7921_rxq_id { MT7921_RXQ_MCU_WM = 0, }; -DECLARE_EWMA(avg_signal, 10, 8) - -struct mt7921_sta { - struct mt76_wcid wcid; /* must be first */ - - struct mt7921_vif *vif; - - struct list_head poll_list; - u32 airtime_ac[8]; - - int ack_signal; - struct ewma_avg_signal avg_ack_signal; - - unsigned long last_txs; - unsigned long ampdu_state; - - struct mt76_connac_sta_key_conf bip; -}; - -DECLARE_EWMA(rssi, 10, 8); - -struct mt7921_vif { - struct mt76_vif mt76; /* must be first */ - - struct mt7921_sta sta; - struct mt7921_sta *wep_sta; - - struct mt7921_phy *phy; - - struct ewma_rssi rssi; - - struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; - struct ieee80211_chanctx_conf *ctx; -}; - -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_ampdu_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - u32 tx_pkt_ebf_cnt; - u32 tx_pkt_ibf_cnt; - - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; -}; - enum { MT7921_CLC_POWER, MT7921_CLC_CHAN, @@ -231,41 +134,6 @@ struct mt7921_clc { u8 data[]; } __packed; -struct mt7921_phy { - struct mt76_phy *mt76; - struct mt7921_dev *dev; - - struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; - - u64 omac_mask; - - u16 noise; - - s16 coverage_class; - u8 slottime; - - u32 rx_ampdu_ts; - u32 ampdu_ref; - - struct mib_stats mib; - - u8 sta_work_count; - - struct sk_buff_head scan_event_list; - struct delayed_work scan_work; -#ifdef CONFIG_ACPI - struct mt7921_acpi_sar *acpisar; -#endif - - struct mt7921_clc *clc[MT7921_CLC_MAX_NUM]; - - struct work_struct roc_work; - struct timer_list roc_timer; - wait_queue_head_t roc_wait; - u8 roc_token_id; - bool roc_grant; -}; - enum mt7921_eeprom_field { MT_EE_CHIP_ID = 0x000, MT_EE_VERSION = 0x002, @@ -277,52 +145,6 @@ enum mt7921_eeprom_field { #define MT_EE_HW_TYPE_ENCAP BIT(0) -#define mt7921_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) -#define mt7921_dev_reset(dev) ((dev)->hif_ops->reset(dev)) -#define mt7921_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) -#define __mt7921_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) -#define __mt7921_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) -struct mt7921_hif_ops { - int (*init_reset)(struct mt7921_dev *dev); - int (*reset)(struct mt7921_dev *dev); - int (*mcu_init)(struct mt7921_dev *dev); - int (*drv_own)(struct mt7921_dev *dev); - int (*fw_own)(struct mt7921_dev *dev); -}; - -struct mt7921_dev { - union { /* must be first */ - struct mt76_dev mt76; - struct mt76_phy mphy; - }; - - const struct mt76_bus_ops *bus_ops; - struct mt7921_phy phy; - - struct work_struct reset_work; - bool hw_full_reset:1; - bool hw_init_done:1; - bool fw_assert:1; - - struct list_head sta_poll_list; - spinlock_t sta_poll_lock; - - struct work_struct init_work; - - u8 fw_debug; - u8 fw_features; - - struct mt76_connac_pm pm; - struct mt76_connac_coredump coredump; - const struct mt7921_hif_ops *hif_ops; - - struct work_struct ipv6_ns_work; - /* IPv6 addresses for WoWLAN */ - struct sk_buff_head ipv6_ns_list; - - enum environment_cap country_ie_env; -}; - enum { TXPWR_USER, TXPWR_EEPROM, @@ -353,56 +175,31 @@ struct mt7921_txpwr { } data[TXPWR_MAX_NUM]; }; -static inline struct mt7921_phy * -mt7921_hw_phy(struct ieee80211_hw *hw) -{ - struct mt76_phy *phy = hw->priv; - - return phy->priv; -} - -static inline struct mt7921_dev * -mt7921_hw_dev(struct ieee80211_hw *hw) -{ - struct mt76_phy *phy = hw->priv; - - return container_of(phy->dev, struct mt7921_dev, mt76); -} - -#define mt7921_mutex_acquire(dev) \ - mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) -#define mt7921_mutex_release(dev) \ - mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) - extern const struct ieee80211_ops mt7921_ops; -u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr); - -int __mt7921_start(struct mt7921_phy *phy); -int mt7921_register_device(struct mt7921_dev *dev); -void mt7921_unregister_device(struct mt7921_dev *dev); -int mt7921_dma_init(struct mt7921_dev *dev); -int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force); -int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev); -void mt7921_dma_cleanup(struct mt7921_dev *dev); -int mt7921_run_firmware(struct mt7921_dev *dev); -int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif, +u32 mt7921_reg_map(struct mt792x_dev *dev, u32 addr); + +int __mt7921_start(struct mt792x_phy *phy); +int mt7921_register_device(struct mt792x_dev *dev); +void mt7921_unregister_device(struct mt792x_dev *dev); +int mt7921_run_firmware(struct mt792x_dev *dev); +int mt7921_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_sta_update(struct mt7921_dev *dev, struct ieee80211_sta *sta, +int mt7921_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta, struct ieee80211_vif *vif, bool enable, enum mt76_sta_info_state state); -int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd); -int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif); -int mt7921_mcu_set_eeprom(struct mt7921_dev *dev); -int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif, +int mt7921_mcu_set_chan_info(struct mt792x_phy *phy, int cmd); +int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif); +int mt7921_mcu_set_eeprom(struct mt792x_dev *dev); +int mt7921_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct rate_info *rate); -int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl); -void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb); -int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif, +int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl); +void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb); +int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif, u8 bit_op, u32 bit_map); static inline u32 -mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr) +mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr) { u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr); u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr); @@ -415,19 +212,19 @@ mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr) } static inline u32 -mt7921_l1_rr(struct mt7921_dev *dev, u32 addr) +mt7921_l1_rr(struct mt792x_dev *dev, u32 addr) { return mt76_rr(dev, mt7921_reg_map_l1(dev, addr)); } static inline void -mt7921_l1_wr(struct mt7921_dev *dev, u32 addr, u32 val) +mt7921_l1_wr(struct mt792x_dev *dev, u32 addr, u32 val) { mt76_wr(dev, mt7921_reg_map_l1(dev, addr), val); } static inline u32 -mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) +mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val) { val |= mt7921_l1_rr(dev, addr) & ~mask; mt7921_l1_wr(dev, addr, val); @@ -438,13 +235,8 @@ mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val) #define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val) #define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0) -static inline bool mt7921_dma_need_reinit(struct mt7921_dev *dev) -{ - return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); -} - static inline void -mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, +mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb, int type) { u32 hdr, len; @@ -457,89 +249,69 @@ mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb, } void mt7921_stop(struct ieee80211_hw *hw); -int mt7921_mac_init(struct mt7921_dev *dev); -bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask); -void mt7921_mac_reset_counters(struct mt7921_phy *phy); -void mt7921_mac_set_timing(struct mt7921_phy *phy); +int mt7921_mac_init(struct mt792x_dev *dev); +bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask); int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -void mt7921_mac_work(struct work_struct *work); void mt7921_mac_reset_work(struct work_struct *work); -void mt7921_mac_update_mib_stats(struct mt7921_phy *phy); -void mt7921_reset(struct mt76_dev *mdev); int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); -void mt7921_tx_worker(struct mt76_worker *w); -void mt7921_tx_token_put(struct mt7921_dev *dev); bool mt7921_rx_check(struct mt76_dev *mdev, void *data, int len); void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, struct sk_buff *skb, u32 *info); void mt7921_stats_work(struct work_struct *work); -void mt7921_set_stream_he_caps(struct mt7921_phy *phy); -void mt7921_update_channel(struct mt76_phy *mphy); -int mt7921_init_debugfs(struct mt7921_dev *dev); +void mt7921_set_stream_he_caps(struct mt792x_phy *phy); +int mt7921_init_debugfs(struct mt792x_dev *dev); -int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev, +int mt7921_mcu_set_beacon_filter(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_tx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable); -int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev, +int mt7921_mcu_uni_rx_ba(struct mt792x_dev *dev, struct ieee80211_ampdu_params *params, bool enable); void mt7921_scan_work(struct work_struct *work); void mt7921_roc_work(struct work_struct *work); -void mt7921_roc_timer(struct timer_list *timer); -int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif); -int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev); -void mt7921_pm_wake_work(struct work_struct *work); -void mt7921_pm_power_save_work(struct work_struct *work); +int mt7921_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif); void mt7921_coredump_work(struct work_struct *work); -int mt7921_wfsys_reset(struct mt7921_dev *dev); -int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr); +int mt7921_get_txpwr_info(struct mt792x_dev *dev, struct mt7921_txpwr *txpwr); int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len); int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, struct netlink_callback *cb, void *data, int len); -void mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t, - struct ieee80211_sta *sta, bool clear_status, - struct list_head *free_list); -void mt7921_mac_sta_poll(struct mt7921_dev *dev); int mt7921_mcu_parse_response(struct mt76_dev *mdev, int cmd, struct sk_buff *skb, int seq); -int mt7921e_driver_own(struct mt7921_dev *dev); -int mt7921e_mac_reset(struct mt7921_dev *dev); -int mt7921e_mcu_init(struct mt7921_dev *dev); -int mt7921s_wfsys_reset(struct mt7921_dev *dev); -int mt7921s_mac_reset(struct mt7921_dev *dev); -int mt7921s_init_reset(struct mt7921_dev *dev); -int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev); - -int mt7921s_mcu_init(struct mt7921_dev *dev); -int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev); -int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev); -void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data); -void mt7921_set_runtime_pm(struct mt7921_dev *dev); +int mt7921e_driver_own(struct mt792x_dev *dev); +int mt7921e_mac_reset(struct mt792x_dev *dev); +int mt7921e_mcu_init(struct mt792x_dev *dev); +int mt7921s_wfsys_reset(struct mt792x_dev *dev); +int mt7921s_mac_reset(struct mt792x_dev *dev); +int mt7921s_init_reset(struct mt792x_dev *dev); + +int mt7921s_mcu_init(struct mt792x_dev *dev); +int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev); +void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data); +void mt7921_set_runtime_pm(struct mt792x_dev *dev); void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); void mt7921_set_ipv6_ns_work(struct work_struct *work); -int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif, +int mt7921_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7921_mcu_config_sniffer(struct mt7921_vif *vif, +int mt7921_mcu_config_sniffer(struct mt792x_vif *vif, struct ieee80211_chanctx_conf *ctx); +int mt7921_mcu_get_temperature(struct mt792x_phy *phy); int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -550,51 +322,18 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev, bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update); /* usb */ -#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) -#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) - -int mt7921u_mcu_power_on(struct mt7921_dev *dev); -int mt7921u_wfsys_reset(struct mt7921_dev *dev); -int mt7921u_dma_init(struct mt7921_dev *dev, bool resume); -int mt7921u_init_reset(struct mt7921_dev *dev); -int mt7921u_mac_reset(struct mt7921_dev *dev); -int mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev, +int mt7921_mcu_uni_add_beacon_offload(struct mt792x_dev *dev, struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable); -#ifdef CONFIG_ACPI -int mt7921_init_acpi_sar(struct mt7921_dev *dev); -int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default); -u8 mt7921_acpi_get_flags(struct mt7921_phy *phy); -#else -static inline int -mt7921_init_acpi_sar(struct mt7921_dev *dev) -{ - return 0; -} - -static inline int -mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) -{ - return 0; -} - -static inline u8 -mt7921_acpi_get_flags(struct mt7921_phy *phy) -{ - return 0; -} -#endif int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw, const struct cfg80211_sar_specs *sar); -int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2, +int mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, enum environment_cap env_cap); -int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, struct ieee80211_channel *chan, int duration, enum mt7921_roc_req type, u8 token_id); -int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif, +int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif, u8 token_id); -struct ieee80211_ops *mt7921_get_mac80211_ops(struct device *dev, - void *drv_data, u8 *fw_features); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c index 95610a117d2f..3dda84a93717 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c @@ -9,8 +9,8 @@ #include "mt7921.h" #include "../mt76_connac2_mac.h" +#include "../dma.h" #include "mcu.h" -#include "../trace.h" static const struct pci_device_id mt7921_pci_device_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7961), @@ -28,81 +28,12 @@ static bool mt7921_disable_aspm; module_param_named(disable_aspm, mt7921_disable_aspm, bool, 0644); MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support"); -static void -mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +static int mt7921e_init_reset(struct mt792x_dev *dev) { - if (q == MT_RXQ_MAIN) - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_DATA); - else if (q == MT_RXQ_MCU_WA) - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM2); - else - mt76_connac_irq_enable(mdev, MT_INT_RX_DONE_WM); + return mt792x_wpdma_reset(dev, true); } -static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance) -{ - struct mt7921_dev *dev = dev_instance; - - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return IRQ_NONE; - - tasklet_schedule(&dev->mt76.irq_tasklet); - - return IRQ_HANDLED; -} - -static void mt7921_irq_tasklet(unsigned long data) -{ - struct mt7921_dev *dev = (struct mt7921_dev *)data; - u32 intr, mask = 0; - - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); - - intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA); - intr &= dev->mt76.mmio.irqmask; - mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr); - - trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); - - mask |= intr & MT_INT_RX_DONE_ALL; - if (intr & MT_INT_TX_DONE_MCU) - mask |= MT_INT_TX_DONE_MCU; - - if (intr & MT_INT_MCU_CMD) { - u32 intr_sw; - - intr_sw = mt76_rr(dev, MT_MCU_CMD); - /* ack MCU2HOST_SW_INT_STA */ - mt76_wr(dev, MT_MCU_CMD, intr_sw); - if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) { - mask |= MT_INT_RX_DONE_DATA; - intr |= MT_INT_RX_DONE_DATA; - } - } - - mt76_set_irq_mask(&dev->mt76, MT_WFDMA0_HOST_INT_ENA, mask, 0); - - if (intr & MT_INT_TX_DONE_ALL) - napi_schedule(&dev->mt76.tx_napi); - - if (intr & MT_INT_RX_DONE_WM) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); - - if (intr & MT_INT_RX_DONE_WM2) - napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); - - if (intr & MT_INT_RX_DONE_DATA) - napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); -} - -static int mt7921e_init_reset(struct mt7921_dev *dev) -{ - return mt7921_wpdma_reset(dev, true); -} - -static void mt7921e_unregister_device(struct mt7921_dev *dev) +static void mt7921e_unregister_device(struct mt792x_dev *dev) { int i; struct mt76_connac_pm *pm = &dev->pm; @@ -115,16 +46,16 @@ static void mt7921e_unregister_device(struct mt7921_dev *dev) cancel_work_sync(&pm->wake_work); cancel_work_sync(&dev->reset_work); - mt7921_tx_token_put(dev); - __mt7921_mcu_drv_pmctrl(dev); - mt7921_dma_cleanup(dev); - mt7921_wfsys_reset(dev); + mt76_connac2_tx_token_put(&dev->mt76); + __mt792x_mcu_drv_pmctrl(dev); + mt792x_dma_cleanup(dev); + mt792x_wfsys_reset(dev); skb_queue_purge(&dev->mt76.mcu.res_q); tasklet_disable(&dev->mt76.irq_tasklet); } -static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) +static u32 __mt7921_reg_addr(struct mt792x_dev *dev, u32 addr) { static const struct mt76_connac_reg_map fixed_map[] = { { 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */ @@ -203,7 +134,7 @@ static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr) static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); return dev->bus_ops->rr(mdev, addr); @@ -211,7 +142,7 @@ static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset) static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); dev->bus_ops->wr(mdev, addr, val); @@ -219,12 +150,77 @@ static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val) static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 addr = __mt7921_reg_addr(dev, offset); return dev->bus_ops->rmw(mdev, addr, mask, val); } +static int mt7921_dma_init(struct mt792x_dev *dev) +{ + int ret; + + mt76_dma_attach(&dev->mt76); + + ret = mt792x_dma_disable(dev, true); + if (ret) + return ret; + + /* init tx queue */ + ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, + MT7921_TX_RING_SIZE, + MT_TX_RING_BASE, 0); + if (ret) + return ret; + + mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4); + + /* command to WM */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM, + MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* firmware download */ + ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL, + MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); + if (ret) + return ret; + + /* event from WM before firmware download */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], + MT7921_RXQ_MCU_WM, + MT7921_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); + if (ret) + return ret; + + /* Change mcu queue after firmware download */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], + MT7921_RXQ_MCU_WM, + MT7921_RX_MCU_RING_SIZE, + MT_RX_BUF_SIZE, MT_WFDMA0(0x540)); + if (ret) + return ret; + + /* rx data */ + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], + MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE, + MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); + if (ret) + return ret; + + ret = mt76_init_queues(dev, mt792x_poll_rx); + if (ret < 0) + return ret; + + netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, + mt792x_poll_tx); + napi_enable(&dev->mt76.tx_napi); + + return mt792x_dma_enable(dev); +} + static int mt7921_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -241,22 +237,34 @@ static int mt7921_pci_probe(struct pci_dev *pdev, .tx_complete_skb = mt76_connac_tx_complete_skb, .rx_check = mt7921_rx_check, .rx_skb = mt7921_queue_rx_skb, - .rx_poll_complete = mt7921_rx_poll_complete, + .rx_poll_complete = mt792x_rx_poll_complete, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; - static const struct mt7921_hif_ops mt7921_pcie_ops = { + static const struct mt792x_hif_ops mt7921_pcie_ops = { .init_reset = mt7921e_init_reset, .reset = mt7921e_mac_reset, .mcu_init = mt7921e_mcu_init, - .drv_own = mt7921e_mcu_drv_pmctrl, - .fw_own = mt7921e_mcu_fw_pmctrl, + .drv_own = mt792xe_mcu_drv_pmctrl, + .fw_own = mt792xe_mcu_fw_pmctrl, + }; + static const struct mt792x_irq_map irq_map = { + .host_irq_enable = MT_WFDMA0_HOST_INT_ENA, + .tx = { + .all_complete_mask = MT_INT_TX_DONE_ALL, + .mcu_complete_mask = MT_INT_TX_DONE_MCU, + }, + .rx = { + .data_complete_mask = MT_INT_RX_DONE_DATA, + .wm_complete_mask = MT_INT_RX_DONE_WM, + .wm2_complete_mask = MT_INT_RX_DONE_WM2, + }, }; struct ieee80211_ops *ops; struct mt76_bus_ops *bus_ops; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; @@ -288,8 +296,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev, if (mt7921_disable_aspm) mt76_pci_disable_aspm(pdev); - ops = mt7921_get_mac80211_ops(&pdev->dev, (void *)id->driver_data, - &features); + ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7921_ops, + (void *)id->driver_data, &features); if (!ops) { ret = -ENOMEM; goto err_free_pci_vec; @@ -303,11 +311,12 @@ static int mt7921_pci_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, mdev); - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &mt7921_pcie_ops; + dev->irq_map = &irq_map; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - tasklet_init(&mdev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev); + tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev); dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; @@ -325,11 +334,11 @@ static int mt7921_pci_probe(struct pci_dev *pdev, bus_ops->rmw = mt7921_rmw; dev->mt76.bus = bus_ops; - ret = mt7921e_mcu_fw_pmctrl(dev); + ret = mt792xe_mcu_fw_pmctrl(dev); if (ret) goto err_free_dev; - ret = __mt7921e_mcu_drv_pmctrl(dev); + ret = __mt792xe_mcu_drv_pmctrl(dev); if (ret) goto err_free_dev; @@ -337,15 +346,15 @@ static int mt7921_pci_probe(struct pci_dev *pdev, (mt7921_l1_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); - ret = mt7921_wfsys_reset(dev); + ret = mt792x_wfsys_reset(dev); if (ret) goto err_free_dev; - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, irq_map.host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); - ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler, + ret = devm_request_irq(mdev->dev, pdev->irq, mt792x_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto err_free_dev; @@ -373,7 +382,7 @@ err_free_pci_vec: static void mt7921_pci_remove(struct pci_dev *pdev) { struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); mt7921e_unregister_device(dev); devm_free_irq(&pdev->dev, pdev->irq, dev); @@ -385,7 +394,7 @@ static int mt7921_pci_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; int i, err; @@ -394,7 +403,7 @@ static int mt7921_pci_suspend(struct device *device) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; @@ -424,12 +433,12 @@ static int mt7921_pci_suspend(struct device *device) MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN); /* disable interrupt */ - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); synchronize_irq(pdev->irq); tasklet_kill(&mdev->irq_tasklet); - err = mt7921_mcu_fw_pmctrl(dev); + err = mt792x_mcu_fw_pmctrl(dev); if (err) goto restore_napi; @@ -450,7 +459,7 @@ restore_suspend: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -459,21 +468,21 @@ static int mt7921_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct mt76_connac_pm *pm = &dev->pm; int i, err; - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto failed; - mt7921_wpdma_reinit_cond(dev); + mt792x_wpdma_reinit_cond(dev); /* enable interrupt */ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); mt76_connac_irq_enable(&dev->mt76, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); /* put dma enabled */ @@ -500,7 +509,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c index 6053a2556c20..e7a995e7e70a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mac.c @@ -10,7 +10,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; struct mt76_connac_hw_txp *txp; @@ -32,7 +32,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return id; if (sta) { - struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; if (time_after(jiffies, msta->last_txs + HZ / 4)) { info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; @@ -53,29 +53,15 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } -void mt7921_tx_token_put(struct mt7921_dev *dev) -{ - struct mt76_txwi_cache *txwi; - int id; - - spin_lock_bh(&dev->mt76.token_lock); - idr_for_each_entry(&dev->mt76.token, txwi, id) { - mt7921_txwi_free(dev, txwi, NULL, false, NULL); - dev->mt76.token_count--; - } - spin_unlock_bh(&dev->mt76.token_lock); - idr_destroy(&dev->mt76.token); -} - -int mt7921e_mac_reset(struct mt7921_dev *dev) +int mt7921e_mac_reset(struct mt792x_dev *dev) { int i, err; - mt7921e_mcu_drv_pmctrl(dev); + mt792xe_mcu_drv_pmctrl(dev); mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); set_bit(MT76_RESET, &dev->mphy.state); @@ -91,10 +77,10 @@ int mt7921e_mac_reset(struct mt7921_dev *dev) napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); napi_disable(&dev->mt76.tx_napi); - mt7921_tx_token_put(dev); + mt76_connac2_tx_token_put(&dev->mt76); idr_init(&dev->mt76.token); - mt7921_wpdma_reset(dev, true); + mt792x_wpdma_reset(dev, true); local_bh_disable(); mt76_for_each_q_rx(&dev->mt76, i) { @@ -106,9 +92,9 @@ int mt7921e_mac_reset(struct mt7921_dev *dev) dev->fw_assert = false; clear_bit(MT76_MCU_RESET, &dev->mphy.state); - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | - MT_INT_MCU_CMD); + mt76_wr(dev, dev->irq_map->host_irq_enable, + dev->irq_map->tx.all_complete_mask | + MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); err = mt7921e_driver_own(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c index 1aefbb6cf0ab..4cf1f2f0f968 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c @@ -4,7 +4,7 @@ #include "mt7921.h" #include "mcu.h" -int mt7921e_driver_own(struct mt7921_dev *dev) +int mt7921e_driver_own(struct mt792x_dev *dev) { u32 reg = mt7921_reg_map_l1(dev, MT_TOP_LPCR_HOST_BAND0); @@ -22,7 +22,7 @@ static int mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); enum mt76_mcuq_id txq = MT_MCUQ_WM; int ret; @@ -38,7 +38,7 @@ mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); } -int mt7921e_mcu_init(struct mt7921_dev *dev) +int mt7921e_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mt7921_mcu_ops = { .headroom = sizeof(struct mt76_connac2_mcu_txd), @@ -61,68 +61,3 @@ int mt7921e_mcu_init(struct mt7921_dev *dev) return err; } - -int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) -{ - int i, err = 0; - - for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { - mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); - if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, - PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) - break; - } - - if (i == MT7921_DRV_OWN_RETRY_COUNT) { - dev_err(dev->mt76.dev, "driver own failed\n"); - err = -EIO; - } - - return err; -} - -int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int err; - - err = __mt7921e_mcu_drv_pmctrl(dev); - if (err < 0) - goto out; - - mt7921_wpdma_reinit_cond(dev); - clear_bit(MT76_STATE_PM, &mphy->state); - - pm->stats.last_wake_event = jiffies; - pm->stats.doze_time += pm->stats.last_wake_event - - pm->stats.last_doze_event; -out: - return err; -} - -int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev) -{ - struct mt76_phy *mphy = &dev->mt76.phy; - struct mt76_connac_pm *pm = &dev->pm; - int i; - - for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) { - mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN); - if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, - PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1)) - break; - } - - if (i == MT7921_DRV_OWN_RETRY_COUNT) { - dev_err(dev->mt76.dev, "firmware own failed\n"); - clear_bit(MT76_STATE_PM, &mphy->state); - return -EIO; - } - - pm->stats.last_doze_event = jiffies; - pm->stats.awake_time += pm->stats.last_doze_event - - pm->stats.last_wake_event; - - return 0; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index e52977ff3349..43427a3a48af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -4,26 +4,7 @@ #ifndef __MT7921_REGS_H #define __MT7921_REGS_H -/* MCU WFDMA1 */ -#define MT_MCU_WFDMA1_BASE 0x3000 -#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) - -#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) -#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) -#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) -#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) -#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) - -#define MT_PLE_BASE 0x820c0000 -#define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) - -#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) -#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) -#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) -#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) - -#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) -#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) +#include "../mt792x_regs.h" #define MT_MDP_BASE 0x820cd000 #define MT_MDP(ofs) (MT_MDP_BASE + (ofs)) @@ -47,280 +28,7 @@ #define MT_MDP_TO_HIF 0 #define MT_MDP_TO_WM 1 -/* TMAC: band 0(0x21000), band 1(0xa1000) */ -#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) -#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) - -#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) -#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) - -#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) -#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) -#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) -#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) - -#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) -#define MT_IFS_EIFS GENMASK(8, 0) -#define MT_IFS_RIFS GENMASK(14, 10) -#define MT_IFS_SIFS GENMASK(22, 16) -#define MT_IFS_SLOT GENMASK(30, 24) - -#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) -#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) -#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) -#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) - -#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) -#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) - -#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000) -#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) - -#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) -#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) -#define MT_DMA_DCR0_RXD_G5_EN BIT(23) - -/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */ -#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000) -#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs)) - -#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008) -#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30) -#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24) - -/* LPON: band 0(0x24200), band 1(0xa4200) */ -#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000) -#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs)) - -#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080) -#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084) - -#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4) -#define MT_LPON_TCR_SW_MODE GENMASK(1, 0) -#define MT_LPON_TCR_SW_WRITE BIT(0) - -/* ETBF: band 0(0x24000), band 1(0xa4000) */ -#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) -#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) - -#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150) -#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) -#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0) - -#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158) -#define MT_ETBF_RX_FB_ALL GENMASK(31, 24) -#define MT_ETBF_RX_FB_HE GENMASK(23, 16) -#define MT_ETBF_RX_FB_VHT GENMASK(15, 8) -#define MT_ETBF_RX_FB_HT GENMASK(7, 0) - -/* MIB: band 0(0x24800), band 1(0xa4800) */ -#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) -#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) - -#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) -#define MT_MIB_TXDUR_EN BIT(8) -#define MT_MIB_RXDUR_EN BIT(9) - -#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) -#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) - -#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780) - -#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) -#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) - -#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558) -#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564) -#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568) - -#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048) -#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0) - -#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770) -#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774) -#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c) - -#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8) -#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16) -#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0) - -#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) -#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) - -#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) -#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) -#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) -#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) - -#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) -#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4) -#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc) - -#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) -#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) - -#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) -#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690) -#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518) -#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0) -#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520) -#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0) - -#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) -#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) - -#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2)) -#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2)) -#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2)) -#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) - -#define MT_WTBLON_TOP_BASE 0x820d4000 -#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) -#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) - -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) -#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) -#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) -#define MT_WTBL_UPDATE_BUSY BIT(31) - -#define MT_WTBL_BASE 0x820d8000 -#define MT_WTBL_LMAC_ID GENMASK(14, 8) -#define MT_WTBL_LMAC_DW GENMASK(7, 2) -#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ - FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ - FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) - -/* AGG: band 0(0x20800), band 1(0xa0800) */ -#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) -#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) - -#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) -#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) -#define MT_AGG_PCR0_MM_PROT BIT(0) -#define MT_AGG_PCR0_GF_PROT BIT(1) -#define MT_AGG_PCR0_BW20_PROT BIT(2) -#define MT_AGG_PCR0_BW40_PROT BIT(4) -#define MT_AGG_PCR0_BW80_PROT BIT(6) -#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8) -#define MT_AGG_PCR0_VHT_PROT BIT(13) -#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) - -#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) -#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) - -#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) -#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) -#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) - -#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) -#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) -#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) -#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) -#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) - -#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) -#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) - -/* ARB: band 0(0x20c00), band 1(0xa0c00) */ -#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000) -#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) - -#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) -#define MT_ARB_SCR_TX_DISABLE BIT(8) -#define MT_ARB_SCR_RX_DISABLE BIT(9) - -#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) - -/* RMAC: band 0(0x21400), band 1(0xa1400) */ -#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) -#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) - -#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) -#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) -#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) -#define MT_WF_RFCR_DROP_VERSION BIT(3) -#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) -#define MT_WF_RFCR_DROP_MCAST BIT(5) -#define MT_WF_RFCR_DROP_BCAST BIT(6) -#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) -#define MT_WF_RFCR_DROP_A3_MAC BIT(8) -#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) -#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) -#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) -#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) -#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) -#define MT_WF_RFCR_DROP_CTS BIT(14) -#define MT_WF_RFCR_DROP_RTS BIT(15) -#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) -#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) -#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) -#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) -#define MT_WF_RFCR_DROP_NDPA BIT(20) -#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) - -#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004) -#define MT_WF_RFCR1_DROP_ACK BIT(4) -#define MT_WF_RFCR1_DROP_BF_POLL BIT(5) -#define MT_WF_RFCR1_DROP_BA BIT(6) -#define MT_WF_RFCR1_DROP_CFEND BIT(7) -#define MT_WF_RFCR1_DROP_CFACK BIT(8) - -#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4) -#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) -#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) - -#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8) -#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) -#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380) - -/* WFDMA0 */ -#define MT_WFDMA0_BASE 0xd4000 -#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) - -#define MT_WFDMA0_RST MT_WFDMA0(0x100) -#define MT_WFDMA0_RST_LOGIC_RST BIT(4) -#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5) - -#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c) -#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0) -#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1) -#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) - -#define MT_MCU_CMD MT_WFDMA0(0x1f0) -#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0) -#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) -#define MT_MCU_CMD_STOP_DMA BIT(2) -#define MT_MCU_CMD_RESET_DONE BIT(3) -#define MT_MCU_CMD_RECOVERY_DONE BIT(4) -#define MT_MCU_CMD_NORMAL_STATE BIT(5) -#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) - -#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4) - -#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200) -#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */ -#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */ -#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */ -#define HOST_TX_DONE_INT_STS16 BIT(26) -#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/ - #define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204) -#define HOST_RX_DONE_INT_ENA0 BIT(0) -#define HOST_RX_DONE_INT_ENA1 BIT(1) -#define HOST_RX_DONE_INT_ENA2 BIT(2) -#define HOST_RX_DONE_INT_ENA3 BIT(3) -#define HOST_TX_DONE_INT_ENA0 BIT(4) -#define HOST_TX_DONE_INT_ENA1 BIT(5) -#define HOST_TX_DONE_INT_ENA2 BIT(6) -#define HOST_TX_DONE_INT_ENA3 BIT(7) -#define HOST_TX_DONE_INT_ENA4 BIT(8) -#define HOST_TX_DONE_INT_ENA5 BIT(9) -#define HOST_TX_DONE_INT_ENA6 BIT(10) -#define HOST_TX_DONE_INT_ENA7 BIT(11) #define HOST_TX_DONE_INT_ENA8 BIT(12) #define HOST_TX_DONE_INT_ENA9 BIT(13) #define HOST_TX_DONE_INT_ENA10 BIT(14) @@ -328,14 +36,10 @@ #define HOST_TX_DONE_INT_ENA12 BIT(16) #define HOST_TX_DONE_INT_ENA13 BIT(17) #define HOST_TX_DONE_INT_ENA14 BIT(18) -#define HOST_RX_COHERENT_EN BIT(20) -#define HOST_TX_COHERENT_EN BIT(21) #define HOST_RX_DONE_INT_ENA4 BIT(22) #define HOST_RX_DONE_INT_ENA5 BIT(23) #define HOST_TX_DONE_INT_ENA16 BIT(26) #define HOST_TX_DONE_INT_ENA17 BIT(27) -#define MCU2HOST_SW_INT_ENA BIT(29) -#define HOST_TX_DONE_INT_ENA18 BIT(30) /* WFDMA interrupt */ #define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2 @@ -347,7 +51,6 @@ #define MT_INT_TX_DONE_MCU_WM HOST_TX_DONE_INT_ENA17 #define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16 #define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0 -#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA #define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \ MT_INT_TX_DONE_FWDL) @@ -355,56 +58,8 @@ MT_INT_TX_DONE_BAND0 | \ GENMASK(18, 4)) -#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) -#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) -#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1) -#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) -#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) -#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) -#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) -#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) -#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) -#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) -#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) -#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) -#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30) - -#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) -#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) -#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6) -#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) - #define MT_RX_DATA_RING_BASE MT_WFDMA0(0x520) -#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600) -#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604) -#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608) -#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c) -#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610) -#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614) -#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618) -#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) -#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) - -#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) -#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) - -#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) -#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) -#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) -#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c) -#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690) -#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694) - -#define MT_TX_RING_BASE MT_WFDMA0(0x300) -#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500) - -/* WFDMA CSR */ -#define MT_WFDMA_EXT_CSR_BASE 0xd7000 -#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) -#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) -#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) - #define MT_INFRA_CFG_BASE 0xfe000 #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) @@ -414,121 +69,13 @@ #define MT_HIF_REMAP_L1_BASE GENMASK(31, 16) #define MT_HIF_REMAP_BASE_L1 0x40000 -#define MT_SWDEF_BASE 0x41f200 -#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) -#define MT_SWDEF_MODE MT_SWDEF(0x3c) -#define MT_SWDEF_NORMAL_MODE 0 -#define MT_SWDEF_ICAP_MODE 1 -#define MT_SWDEF_SPECTRUM_MODE 2 - -#define MT_TOP_BASE 0x18060000 -#define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) - -#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) -#define MT_TOP_LPCR_HOST_FW_OWN BIT(0) -#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) - -#define MT_TOP_MISC MT_TOP(0xf0) -#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) - -#define MT_MCU_WPDMA0_BASE 0x54000000 -#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs)) - -#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) -#define MT_WFDMA_NEED_REINIT BIT(1) - -#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) -#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) -#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) - -#define MT_HW_BOUND 0x70010020 -#define MT_HW_CHIPID 0x70010200 -#define MT_HW_REV 0x70010204 - -#define MT_PCIE_MAC_BASE 0x10000 -#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) -#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) -#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194) -#define MT_PCIE_MAC_PM_L0S_DIS BIT(8) - -#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) -#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) -#define MT_DMASHDL_DMASHDL_BYPASS BIT(28) -#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) -#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) -#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) -#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) -#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) -#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) -#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) -#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) - -#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2)) -#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) -#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) - -#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2)) -#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) -#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) - -#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) - -#define MT_WFDMA_HOST_CONFIG 0x7c027030 -#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) - -#define MT_UMAC(ofs) (0x74000000 + (ofs)) -#define MT_UDMA_TX_QSEL MT_UMAC(0x008) -#define MT_FW_DL_EN BIT(3) - -#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) -#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) -#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) - -#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) -#define MT_WL_RX_AGG_TO GENMASK(7, 0) -#define MT_WL_RX_AGG_LMT GENMASK(15, 8) -#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) -#define MT_WL_TX_DPH_CHK_EN BIT(17) -#define MT_WL_RX_MPSZ_PAD0 BIT(18) -#define MT_WL_RX_FLUSH BIT(19) -#define MT_TICK_1US_EN BIT(20) -#define MT_WL_RX_AGG_EN BIT(21) -#define MT_WL_RX_EN BIT(22) -#define MT_WL_TX_EN BIT(23) -#define MT_WL_RX_BUSY BIT(30) -#define MT_WL_TX_BUSY BIT(31) - -#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) -#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) -#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) - -#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) -#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) - -#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) -#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) -#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) -#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) - -#define MT_CONN_STATUS 0x7c053c10 -#define MT_WIFI_PATCH_DL_STATE BIT(0) - -#define MT_CONN_ON_LPCTL 0x7c060010 -#define PCIE_LPCR_HOST_OWN_SYNC BIT(2) -#define PCIE_LPCR_HOST_CLR_OWN BIT(1) -#define PCIE_LPCR_HOST_SET_OWN BIT(0) - #define MT_WFSYS_SW_RST_B 0x18000140 -#define WFSYS_SW_RST_B BIT(0) -#define WFSYS_SW_INIT_DONE BIT(4) -#define MT_CONN_ON_MISC 0x7c0600f0 -#define MT_TOP_MISC2_FW_PWR_ON BIT(0) -#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) +#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) -#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) -#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) -#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) -#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c index a77a309c0d60..dc1beb76df3e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c @@ -27,7 +27,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w) struct mt76_sdio *sdio = container_of(w, struct mt76_sdio, txrx_worker); struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio); - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { queue_work(mdev->wq, &dev->pm.wake_work); @@ -38,7 +38,7 @@ static void mt7921s_txrx_worker(struct mt76_worker *w) mt76_connac_pm_unref(&dev->mphy, &dev->pm); } -static void mt7921s_unregister_device(struct mt7921_dev *dev) +static void mt7921s_unregister_device(struct mt792x_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; @@ -102,7 +102,7 @@ static int mt7921s_probe(struct sdio_func *func, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; static const struct mt76_bus_ops mt7921s_ops = { .rr = mt76s_rr, @@ -114,7 +114,7 @@ static int mt7921s_probe(struct sdio_func *func, .rd_rp = mt76s_rd_rp, .type = MT76_BUS_SDIO, }; - static const struct mt7921_hif_ops mt7921_sdio_ops = { + static const struct mt792x_hif_ops mt7921_sdio_ops = { .init_reset = mt7921s_init_reset, .reset = mt7921s_mac_reset, .mcu_init = mt7921s_mcu_init, @@ -122,13 +122,13 @@ static int mt7921s_probe(struct sdio_func *func, .fw_own = mt7921s_mcu_fw_pmctrl, }; struct ieee80211_ops *ops; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; - ops = mt7921_get_mac80211_ops(&func->dev, (void *)id->driver_data, - &features); + ops = mt792x_get_mac80211_ops(&func->dev, &mt7921_ops, + (void *)id->driver_data, &features); if (!ops) return -ENOMEM; @@ -136,7 +136,7 @@ static int mt7921s_probe(struct sdio_func *func, if (!mdev) return -ENOMEM; - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &mt7921_sdio_ops; sdio_set_drvdata(func, dev); @@ -196,7 +196,7 @@ error: static void mt7921s_remove(struct sdio_func *func) { - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); mt7921s_unregister_device(dev); } @@ -204,7 +204,7 @@ static void mt7921s_remove(struct sdio_func *func) static int mt7921s_suspend(struct device *__dev) { struct sdio_func *func = dev_to_sdio_func(__dev); - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; int err; @@ -216,7 +216,7 @@ static int mt7921s_suspend(struct device *__dev) cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto restore_suspend; @@ -244,7 +244,7 @@ static int mt7921s_suspend(struct device *__dev) mt76_worker_disable(&mdev->sdio.txrx_worker); mt76_worker_disable(&mdev->sdio.net_worker); - err = mt7921_mcu_fw_pmctrl(dev); + err = mt792x_mcu_fw_pmctrl(dev); if (err) goto restore_txrx_worker; @@ -269,7 +269,7 @@ restore_suspend: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -277,14 +277,14 @@ restore_suspend: static int mt7921s_resume(struct device *__dev) { struct sdio_func *func = dev_to_sdio_func(__dev); - struct mt7921_dev *dev = sdio_get_drvdata(func); + struct mt792x_dev *dev = sdio_get_drvdata(func); struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; int err; clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state); - err = mt7921_mcu_drv_pmctrl(dev); + err = mt792x_mcu_drv_pmctrl(dev); if (err < 0) goto failed; @@ -302,7 +302,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c index cff9925c41ea..8edd0291c128 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c @@ -30,7 +30,7 @@ static u32 mt7921s_read_whcr(struct mt76_dev *dev) return sdio_readl(dev->sdio.func, MCR_WHCR, NULL); } -int mt7921s_wfsys_reset(struct mt7921_dev *dev) +int mt7921s_wfsys_reset(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; u32 val, status; @@ -71,7 +71,7 @@ int mt7921s_wfsys_reset(struct mt7921_dev *dev) return 0; } -int mt7921s_init_reset(struct mt7921_dev *dev) +int mt7921s_init_reset(struct mt792x_dev *dev) { set_bit(MT76_MCU_RESET, &dev->mphy.state); @@ -91,7 +91,7 @@ int mt7921s_init_reset(struct mt7921_dev *dev) return 0; } -int mt7921s_mac_reset(struct mt7921_dev *dev) +int mt7921s_mac_reset(struct mt792x_dev *dev) { int err; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c index 177679ce1c80..310eeca024ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c @@ -16,14 +16,14 @@ static int mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); enum mt7921_sdio_pkt_type type = MT7921_SDIO_CMD; enum mt76_mcuq_id txq = MT_MCUQ_WM; int ret, pad; /* We just return in case firmware assertion to avoid blocking the * common workqueue to run, for example, the coredump work might be - * blocked by mt7921_mac_work that is excuting register access via sdio + * blocked by mt792x_mac_work that is excuting register access via sdio * bus. */ if (dev->fw_assert) @@ -51,14 +51,14 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return ret; } -static u32 mt7921s_read_rm3r(struct mt7921_dev *dev) +static u32 mt7921s_read_rm3r(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; return sdio_readl(sdio->func, MCR_D2HRM3R, NULL); } -static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) +static u32 mt7921s_clear_rm3r_drv_own(struct mt792x_dev *dev) { struct mt76_sdio *sdio = &dev->mt76.sdio; u32 val; @@ -71,7 +71,7 @@ static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) return val; } -int mt7921s_mcu_init(struct mt7921_dev *dev) +int mt7921s_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mt7921s_mcu_ops = { .headroom = MT_SDIO_HDR_SIZE + @@ -97,7 +97,7 @@ int mt7921s_mcu_init(struct mt7921_dev *dev) return 0; } -int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) +int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev) { struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; @@ -133,7 +133,7 @@ int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) return 0; } -int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) +int mt7921s_mcu_fw_pmctrl(struct mt792x_dev *dev) { struct sdio_func *func = dev->mt76.sdio.func; struct mt76_phy *mphy = &dev->mt76.phy; diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c index 7f408212e716..e838d93477c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/testmode.c @@ -31,7 +31,7 @@ static const struct nla_policy mt7921_tm_policy[NUM_MT7921_TM_ATTRS] = { }; static int -mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req) +mt7921_tm_set(struct mt792x_dev *dev, struct mt7921_tm_cmd *req) { struct mt7921_rftest_cmd cmd = { .action = req->action, @@ -57,7 +57,7 @@ mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req) pm->enable = false; cancel_delayed_work_sync(&pm->ps_work); cancel_work_sync(&pm->wake_work); - __mt7921_mcu_drv_pmctrl(dev); + __mt792x_mcu_drv_pmctrl(dev); phy->test.state = MT76_TM_STATE_ON; } @@ -82,7 +82,7 @@ out: } static int -mt7921_tm_query(struct mt7921_dev *dev, struct mt7921_tm_cmd *req, +mt7921_tm_query(struct mt792x_dev *dev, struct mt7921_tm_cmd *req, struct mt7921_tm_evt *evt_resp) { struct mt7921_rftest_cmd cmd = { @@ -113,7 +113,7 @@ int mt7921_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, { struct nlattr *tb[NUM_MT76_TM_ATTRS]; struct mt76_phy *mphy = hw->priv; - struct mt7921_phy *phy = mphy->priv; + struct mt792x_phy *phy = mphy->priv; int err; if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || @@ -150,7 +150,7 @@ int mt7921_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg, { struct nlattr *tb[NUM_MT76_TM_ATTRS]; struct mt76_phy *mphy = hw->priv; - struct mt7921_phy *phy = mphy->priv; + struct mt792x_phy *phy = mphy->priv; int err; if (!test_bit(MT76_STATE_RUNNING, &mphy->state) || diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c b/drivers/net/wireless/mediatek/mt76/mt7921/trace.c deleted file mode 100644 index 4dc3c7b89ebd..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/trace.c +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: ISC -/* - * Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org> - */ - -#include <linux/module.h> - -#ifndef __CHECKER__ -#define CREATE_TRACE_POINTS -#include "mt7921_trace.h" - -#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c index 1f302c430339..59cd3d98bf90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c @@ -24,88 +24,11 @@ static const struct usb_device_id mt7921u_device_table[] = { { }, }; -static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - -static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr, - u32 mask, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, - USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; - ___mt76u_wr(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return val; -} - -static void mt7921u_copy(struct mt76_dev *dev, u32 offset, - const void *data, int len) -{ - struct mt76_usb *usb = &dev->usb; - int ret, i = 0, batch_len; - const u8 *val = data; - - len = round_up(len, 4); - - mutex_lock(&usb->usb_ctrl_mtx); - while (i < len) { - batch_len = min_t(int, usb->data_len, len - i); - memcpy(usb->data, val + i, batch_len); - ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, - (offset + i) >> 16, offset + i, - usb->data, batch_len); - if (ret < 0) - break; - - i += batch_len; - } - mutex_unlock(&usb->usb_ctrl_mtx); -} - -int mt7921u_mcu_power_on(struct mt7921_dev *dev) -{ - int ret; - - ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, - USB_DIR_OUT | MT_USB_TYPE_VENDOR, - 0x0, 0x1, NULL, 0); - if (ret) - return ret; - - if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, - MT_TOP_MISC2_FW_PWR_ON, 500)) { - dev_err(dev->mt76.dev, "Timeout for power on\n"); - ret = -EIO; - } - - return ret; -} - static int mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, int cmd, int *seq) { - struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); u32 pad, ep; int ret; @@ -131,7 +54,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, return ret; } -static int mt7921u_mcu_init(struct mt7921_dev *dev) +static int mt7921u_mcu_init(struct mt792x_dev *dev) { static const struct mt76_mcu_ops mcu_ops = { .headroom = MT_SDIO_HDR_SIZE + @@ -155,20 +78,69 @@ static int mt7921u_mcu_init(struct mt7921_dev *dev) return 0; } -static void mt7921u_stop(struct ieee80211_hw *hw) +static int mt7921u_mac_reset(struct mt792x_dev *dev) { - struct mt7921_dev *dev = mt7921_hw_dev(hw); + int err; + + mt76_txq_schedule_all(&dev->mphy); + mt76_worker_disable(&dev->mt76.tx_worker); + set_bit(MT76_RESET, &dev->mphy.state); + set_bit(MT76_MCU_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); mt76u_stop_tx(&dev->mt76); - mt7921_stop(hw); + + mt792xu_wfsys_reset(dev); + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + err = mt76u_resume_rx(&dev->mt76); + if (err) + goto out; + + err = mt792xu_mcu_power_on(dev); + if (err) + goto out; + + err = mt792xu_dma_init(dev, false); + if (err) + goto out; + + mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); + mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_run_firmware(dev); + if (err) + goto out; + + mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); + + err = mt7921_mcu_set_eeprom(dev); + if (err) + goto out; + + err = mt7921_mac_init(dev); + if (err) + goto out; + + err = __mt7921_start(&dev->phy); +out: + clear_bit(MT76_RESET, &dev->mphy.state); + + mt76_worker_enable(&dev->mt76.tx_worker); + + return err; } -static void mt7921u_cleanup(struct mt7921_dev *dev) +static void mt7921u_stop(struct ieee80211_hw *hw) { - clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); - mt7921u_wfsys_reset(dev); - skb_queue_purge(&dev->mt76.mcu.res_q); - mt76u_queues_deinit(&dev->mt76); + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mt76u_stop_tx(&dev->mt76); + mt7921_stop(hw); } static int mt7921u_probe(struct usb_interface *usb_intf, @@ -189,31 +161,31 @@ static int mt7921u_probe(struct usb_interface *usb_intf, .sta_add = mt7921_mac_sta_add, .sta_assoc = mt7921_mac_sta_assoc, .sta_remove = mt7921_mac_sta_remove, - .update_survey = mt7921_update_channel, + .update_survey = mt792x_update_channel, }; - static const struct mt7921_hif_ops hif_ops = { + static const struct mt792x_hif_ops hif_ops = { .mcu_init = mt7921u_mcu_init, - .init_reset = mt7921u_init_reset, + .init_reset = mt792xu_init_reset, .reset = mt7921u_mac_reset, }; static struct mt76_bus_ops bus_ops = { - .rr = mt7921u_rr, - .wr = mt7921u_wr, - .rmw = mt7921u_rmw, + .rr = mt792xu_rr, + .wr = mt792xu_wr, + .rmw = mt792xu_rmw, .read_copy = mt76u_read_copy, - .write_copy = mt7921u_copy, + .write_copy = mt792xu_copy, .type = MT76_BUS_USB, }; struct usb_device *udev = interface_to_usbdev(usb_intf); struct ieee80211_ops *ops; struct ieee80211_hw *hw; - struct mt7921_dev *dev; + struct mt792x_dev *dev; struct mt76_dev *mdev; u8 features; int ret; - ops = mt7921_get_mac80211_ops(&usb_intf->dev, (void *)id->driver_info, - &features); + ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7921_ops, + (void *)id->driver_info, &features); if (!ops) return -ENOMEM; @@ -222,7 +194,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (!mdev) return -ENOMEM; - dev = container_of(mdev, struct mt7921_dev, mt76); + dev = container_of(mdev, struct mt792x_dev, mt76); dev->fw_features = features; dev->hif_ops = &hif_ops; @@ -240,12 +212,12 @@ static int mt7921u_probe(struct usb_interface *usb_intf, dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) { - ret = mt7921u_wfsys_reset(dev); + ret = mt792xu_wfsys_reset(dev); if (ret) goto error; } - ret = mt7921u_mcu_power_on(dev); + ret = mt792xu_mcu_power_on(dev); if (ret) goto error; @@ -257,7 +229,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf, if (ret) goto error; - ret = mt7921u_dma_init(dev, false); + ret = mt792xu_dma_init(dev, false); if (ret) goto error; @@ -282,27 +254,10 @@ error: return ret; } -static void mt7921u_disconnect(struct usb_interface *usb_intf) -{ - struct mt7921_dev *dev = usb_get_intfdata(usb_intf); - - cancel_work_sync(&dev->init_work); - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) - return; - - mt76_unregister_device(&dev->mt76); - mt7921u_cleanup(dev); - - usb_set_intfdata(usb_intf, NULL); - usb_put_dev(interface_to_usbdev(usb_intf)); - - mt76_free_device(&dev->mt76); -} - #ifdef CONFIG_PM static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) { - struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt792x_dev *dev = usb_get_intfdata(intf); struct mt76_connac_pm *pm = &dev->pm; int err; @@ -322,14 +277,14 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } static int mt7921u_resume(struct usb_interface *intf) { - struct mt7921_dev *dev = usb_get_intfdata(intf); + struct mt792x_dev *dev = usb_get_intfdata(intf); struct mt76_connac_pm *pm = &dev->pm; bool reinit = true; int err, i; @@ -349,8 +304,8 @@ static int mt7921u_resume(struct usb_interface *intf) msleep(20); } - if (reinit || mt7921_dma_need_reinit(dev)) { - err = mt7921u_dma_init(dev, true); + if (reinit || mt792x_dma_need_reinit(dev)) { + err = mt792xu_dma_init(dev, true); if (err) goto failed; } @@ -364,7 +319,7 @@ failed: pm->suspended = false; if (err < 0) - mt7921_reset(&dev->mt76); + mt792x_reset(&dev->mt76); return err; } @@ -378,7 +333,7 @@ static struct usb_driver mt7921u_driver = { .name = KBUILD_MODNAME, .id_table = mt7921u_device_table, .probe = mt7921u_probe, - .disconnect = mt7921u_disconnect, + .disconnect = mt792xu_disconnect, #ifdef CONFIG_PM .suspend = mt7921u_suspend, .resume = mt7921u_resume, diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c deleted file mode 100644 index 50eb6e7fd6b5..000000000000 --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: ISC -/* Copyright (C) 2022 MediaTek Inc. - * - * Author: Lorenzo Bianconi <lorenzo@kernel.org> - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/usb.h> - -#include "mt7921.h" -#include "mcu.h" -#include "../mt76_connac2_mac.h" - -static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr) -{ - u32 ret; - - mutex_lock(&dev->usb.usb_ctrl_mtx); - ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, - USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); - mutex_unlock(&dev->usb.usb_ctrl_mtx); - - return ret; -} - -static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) -{ - mutex_lock(&dev->usb.usb_ctrl_mtx); - ___mt76u_wr(dev, MT_VEND_WRITE, - USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); - mutex_unlock(&dev->usb.usb_ctrl_mtx); -} - -static void mt7921u_dma_prefetch(struct mt7921_dev *dev) -{ - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), - MT_WPDMA0_BASE_PTR_MASK, 0x80); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), - MT_WPDMA0_BASE_PTR_MASK, 0xc0); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), - MT_WPDMA0_BASE_PTR_MASK, 0x100); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), - MT_WPDMA0_BASE_PTR_MASK, 0x140); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), - MT_WPDMA0_BASE_PTR_MASK, 0x180); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), - MT_WPDMA0_BASE_PTR_MASK, 0x280); - - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_MAX_CNT_MASK, 4); - mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), - MT_WPDMA0_BASE_PTR_MASK, 0x2c0); -} - -static void mt7921u_wfdma_init(struct mt7921_dev *dev) -{ - mt7921u_dma_prefetch(dev); - - mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); - mt76_set(dev, MT_UWFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | - MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - /* disable dmashdl */ - mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - - mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); -} - -static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev) -{ - if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) - return -ETIMEDOUT; - - mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); - mt76_set(dev, MT_WFDMA_HOST_CONFIG, - MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); - mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); - - return 0; -} - -static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset) -{ - u32 val; - - /* usb endpoint reset opt - * bits[4,9]: out blk ep 4-9 - * bits[20,21]: in blk ep 4-5 - * bits[22]: in int ep 6 - */ - val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); - if (reset) - val |= GENMASK(9, 4) | GENMASK(22, 20); - else - val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); - mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); -} - -int mt7921u_dma_init(struct mt7921_dev *dev, bool resume) -{ - int err; - - mt7921u_wfdma_init(dev); - - mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); - - mt76_set(dev, MT_UDMA_WLCFG_0, - MT_WL_RX_EN | MT_WL_TX_EN | - MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); - mt76_clear(dev, MT_UDMA_WLCFG_0, - MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); - mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); - - if (resume) - return 0; - - err = mt7921u_dma_rx_evt_ep4(dev); - if (err) - return err; - - mt7921u_epctl_rst_opt(dev, false); - - return 0; -} - -int mt7921u_wfsys_reset(struct mt7921_dev *dev) -{ - u32 val; - int i; - - mt7921u_epctl_rst_opt(dev, false); - - val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); - val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; - mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); - - usleep_range(10, 20); - - val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); - val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; - mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); - - mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); - for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) { - val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); - if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) - break; - - msleep(100); - } - - if (i == MT7921_WFSYS_INIT_RETRY_COUNT) - return -ETIMEDOUT; - - return 0; -} - -int mt7921u_init_reset(struct mt7921_dev *dev) -{ - set_bit(MT76_RESET, &dev->mphy.state); - - wake_up(&dev->mt76.mcu.wait); - skb_queue_purge(&dev->mt76.mcu.res_q); - - mt76u_stop_rx(&dev->mt76); - mt76u_stop_tx(&dev->mt76); - - mt7921u_wfsys_reset(dev); - - clear_bit(MT76_RESET, &dev->mphy.state); - - return mt76u_resume_rx(&dev->mt76); -} - -int mt7921u_mac_reset(struct mt7921_dev *dev) -{ - int err; - - mt76_txq_schedule_all(&dev->mphy); - mt76_worker_disable(&dev->mt76.tx_worker); - - set_bit(MT76_RESET, &dev->mphy.state); - set_bit(MT76_MCU_RESET, &dev->mphy.state); - - wake_up(&dev->mt76.mcu.wait); - skb_queue_purge(&dev->mt76.mcu.res_q); - - mt76u_stop_rx(&dev->mt76); - mt76u_stop_tx(&dev->mt76); - - mt7921u_wfsys_reset(dev); - - clear_bit(MT76_MCU_RESET, &dev->mphy.state); - err = mt76u_resume_rx(&dev->mt76); - if (err) - goto out; - - err = mt7921u_mcu_power_on(dev); - if (err) - goto out; - - err = mt7921u_dma_init(dev, false); - if (err) - goto out; - - mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); - mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); - - err = mt7921_run_firmware(dev); - if (err) - goto out; - - mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN); - - err = mt7921_mcu_set_eeprom(dev); - if (err) - goto out; - - err = mt7921_mac_init(dev); - if (err) - goto out; - - err = __mt7921_start(&dev->phy); -out: - clear_bit(MT76_RESET, &dev->mphy.state); - - mt76_worker_enable(&dev->mt76.tx_worker); - - return err; -} diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h new file mode 100644 index 000000000000..5d5ab8630041 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT792X_H +#define __MT792X_H + +#include <linux/interrupt.h> +#include <linux/ktime.h> + +#include "mt76_connac_mcu.h" +#include "mt792x_regs.h" +#include "mt792x_acpi_sar.h" + +#define MT792x_PM_TIMEOUT (HZ / 12) +#define MT792x_HW_SCAN_TIMEOUT (HZ / 10) + +#define MT792x_MAX_INTERFACES 4 +#define MT792x_WTBL_SIZE 20 +#define MT792x_WTBL_RESERVED (MT792x_WTBL_SIZE - 1) +#define MT792x_WTBL_STA (MT792x_WTBL_RESERVED - MT792x_MAX_INTERFACES) + +#define MT792x_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +#define MT792x_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + +#define MT792x_FW_TAG_FEATURE 4 +#define MT792x_FW_CAP_CNM BIT(7) + +/* NOTE: used to map mt76_rates. idx may change if firmware expands table */ +#define MT792x_BASIC_RATES_TBL 11 + +#define MT792x_WATCHDOG_TIME (HZ / 4) + +#define MT792x_DRV_OWN_RETRY_COUNT 10 +#define MT792x_MCU_INIT_RETRY_COUNT 10 +#define MT792x_WFSYS_INIT_RETRY_COUNT 2 + +#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin" +#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin" + +#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin" +#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin" + +struct mt792x_vif; +struct mt792x_sta; + +struct mt792x_realease_info { + __le16 len; + u8 pad_len; + u8 tag; +} __packed; + +struct mt792x_fw_features { + u8 segment; + u8 data; + u8 rsv[14]; +} __packed; + +enum { + MT792x_CLC_POWER, + MT792x_CLC_CHAN, + MT792x_CLC_MAX_NUM, +}; + +DECLARE_EWMA(avg_signal, 10, 8) + +struct mt792x_sta { + struct mt76_wcid wcid; /* must be first */ + + struct mt792x_vif *vif; + + u32 airtime_ac[8]; + + int ack_signal; + struct ewma_avg_signal avg_ack_signal; + + unsigned long last_txs; + + struct mt76_connac_sta_key_conf bip; +}; + +DECLARE_EWMA(rssi, 10, 8); + +struct mt792x_vif { + struct mt76_vif mt76; /* must be first */ + + struct mt792x_sta sta; + struct mt792x_sta *wep_sta; + + struct mt792x_phy *phy; + + struct ewma_rssi rssi; + + struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; + struct ieee80211_chanctx_conf *ctx; +}; + +struct mt792x_phy { + struct mt76_phy *mt76; + struct mt792x_dev *dev; + + struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES]; + + u64 omac_mask; + + u16 noise; + + s16 coverage_class; + u8 slottime; + + u32 rx_ampdu_ts; + u32 ampdu_ref; + + struct mt76_mib_stats mib; + + u8 sta_work_count; + + struct sk_buff_head scan_event_list; + struct delayed_work scan_work; +#ifdef CONFIG_ACPI + void *acpisar; +#endif + void *clc[MT792x_CLC_MAX_NUM]; + + struct work_struct roc_work; + struct timer_list roc_timer; + wait_queue_head_t roc_wait; + u8 roc_token_id; + bool roc_grant; +}; + +struct mt792x_irq_map { + u32 host_irq_enable; + struct { + u32 all_complete_mask; + u32 mcu_complete_mask; + } tx; + struct { + u32 data_complete_mask; + u32 wm_complete_mask; + u32 wm2_complete_mask; + } rx; +}; + +#define mt792x_init_reset(dev) ((dev)->hif_ops->init_reset(dev)) +#define mt792x_dev_reset(dev) ((dev)->hif_ops->reset(dev)) +#define mt792x_mcu_init(dev) ((dev)->hif_ops->mcu_init(dev)) +#define __mt792x_mcu_drv_pmctrl(dev) ((dev)->hif_ops->drv_own(dev)) +#define __mt792x_mcu_fw_pmctrl(dev) ((dev)->hif_ops->fw_own(dev)) + +struct mt792x_hif_ops { + int (*init_reset)(struct mt792x_dev *dev); + int (*reset)(struct mt792x_dev *dev); + int (*mcu_init)(struct mt792x_dev *dev); + int (*drv_own)(struct mt792x_dev *dev); + int (*fw_own)(struct mt792x_dev *dev); +}; + +struct mt792x_dev { + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + + const struct mt76_bus_ops *bus_ops; + struct mt792x_phy phy; + + struct work_struct reset_work; + bool hw_full_reset:1; + bool hw_init_done:1; + bool fw_assert:1; + bool has_eht:1; + + struct work_struct init_work; + + u8 fw_debug; + u8 fw_features; + + struct mt76_connac_pm pm; + struct mt76_connac_coredump coredump; + const struct mt792x_hif_ops *hif_ops; + const struct mt792x_irq_map *irq_map; + + struct work_struct ipv6_ns_work; + /* IPv6 addresses for WoWLAN */ + struct sk_buff_head ipv6_ns_list; + + enum environment_cap country_ie_env; + u32 backup_l1; + u32 backup_l2; +}; + +static inline struct mt792x_dev * +mt792x_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt792x_dev, mt76); +} + +static inline struct mt792x_phy * +mt792x_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + +static inline void +mt792x_get_status_freq_info(struct mt76_rx_status *status, u8 chfreq) +{ + if (chfreq > 180) { + status->band = NL80211_BAND_6GHZ; + chfreq = (chfreq - 181) * 4 + 1; + } else if (chfreq > 14) { + status->band = NL80211_BAND_5GHZ; + } else { + status->band = NL80211_BAND_2GHZ; + } + status->freq = ieee80211_channel_to_frequency(chfreq, status->band); +} + +static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev) +{ + return !mt76_get_field(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + +#define mt792x_mutex_acquire(dev) \ + mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm) +#define mt792x_mutex_release(dev) \ + mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm) + +void mt792x_pm_wake_work(struct work_struct *work); +void mt792x_pm_power_save_work(struct work_struct *work); +void mt792x_reset(struct mt76_dev *mdev); +void mt792x_update_channel(struct mt76_phy *mphy); +void mt792x_mac_reset_counters(struct mt792x_phy *phy); +void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band); +void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb); +struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, + bool unicast); +void mt792x_mac_update_mib_stats(struct mt792x_phy *phy); +void mt792x_mac_set_timeing(struct mt792x_phy *phy); +void mt792x_mac_work(struct work_struct *work); +void mt792x_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); +void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb); +int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params); +int mt792x_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats); +u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 timestamp); +void mt792x_tx_worker(struct mt76_worker *w); +void mt792x_roc_timer(struct timer_list *timer); +void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop); +int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx); +void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx); +void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled); +void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 sset, u8 *data); +int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int sset); +void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data); +void mt792x_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct station_info *sinfo); +void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class); +void mt792x_dma_cleanup(struct mt792x_dev *dev); +int mt792x_dma_enable(struct mt792x_dev *dev); +int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force); +int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev); +int mt792x_dma_disable(struct mt792x_dev *dev, bool force); +irqreturn_t mt792x_irq_handler(int irq, void *dev_instance); +void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); +int mt792x_poll_tx(struct napi_struct *napi, int budget); +int mt792x_poll_rx(struct napi_struct *napi, int budget); +void mt792x_irq_tasklet(unsigned long data); +int mt792x_wfsys_reset(struct mt792x_dev *dev); +int mt792x_tx_stats_show(struct seq_file *file, void *data); +int mt792x_queues_acq(struct seq_file *s, void *data); +int mt792x_queues_read(struct seq_file *s, void *data); +int mt792x_pm_stats(struct seq_file *s, void *data); +int mt792x_pm_idle_timeout_set(void *data, u64 val); +int mt792x_pm_idle_timeout_get(void *data, u64 *val); +int mt792x_init_wiphy(struct ieee80211_hw *hw); +struct ieee80211_ops * +mt792x_get_mac80211_ops(struct device *dev, + const struct ieee80211_ops *mac80211_ops, + void *drv_data, u8 *fw_features); +int mt792x_init_wcid(struct mt792x_dev *dev); +int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev); + +static inline char *mt792x_ram_name(struct mt792x_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7922: + return MT7922_FIRMWARE_WM; + default: + return MT7921_FIRMWARE_WM; + } +} + +static inline char *mt792x_patch_name(struct mt792x_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7922: + return MT7922_ROM_PATCH; + default: + return MT7921_ROM_PATCH; + } +} + +int mt792x_load_firmware(struct mt792x_dev *dev); + +/* usb */ +#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f) +#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e) +int mt792xu_dma_init(struct mt792x_dev *dev, bool resume); +int mt792xu_mcu_power_on(struct mt792x_dev *dev); +int mt792xu_wfsys_reset(struct mt792x_dev *dev); +int mt792xu_init_reset(struct mt792x_dev *dev); +u32 mt792xu_rr(struct mt76_dev *dev, u32 addr); +void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val); +u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val); +void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len); +void mt792xu_disconnect(struct usb_interface *usb_intf); + +int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev); +int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev); + +#ifdef CONFIG_ACPI +int mt792x_init_acpi_sar(struct mt792x_dev *dev); +int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default); +u8 mt792x_acpi_get_flags(struct mt792x_phy *phy); +#else +static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev) +{ + return 0; +} + +static inline int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, + bool set_default) +{ + return 0; +} + +static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) +{ + return 0; +} +#endif + +#endif /* __MT7925_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c index 48dd0decac5d..303c0f5c9c66 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/acpi_sar.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c @@ -1,15 +1,15 @@ // SPDX-License-Identifier: ISC -/* Copyright (C) 2022 MediaTek Inc. */ +/* Copyright (C) 2023 MediaTek Inc. */ #include <linux/acpi.h> -#include "mt7921.h" +#include "mt792x.h" static int -mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len) +mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len) { struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *sar_root, *sar_unit; struct mt76_dev *mdev = &dev->mt76; + union acpi_object *sar_root; acpi_handle root, handle; acpi_status status; u32 i = 0; @@ -45,18 +45,20 @@ mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len) goto free; } } + if (len) *len = sar_root->package.count; for (i = 0; i < sar_root->package.count; i++) { - sar_unit = &sar_root->package.elements[i]; + union acpi_object *sar_unit = &sar_root->package.elements[i]; if (sar_unit->type != ACPI_TYPE_INTEGER) break; + *(*tbl + i) = (u8)sar_unit->integer.value; } - ret = (i == sar_root->package.count) ? 0 : -EINVAL; + ret = i == sar_root->package.count ? 0 : -EINVAL; free: kfree(sar_root); @@ -64,36 +66,37 @@ free: } /* MTCL : Country List Table for 6G band */ -static int -mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version) +static void +mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version) { - *version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0) - ? 1 : 2; - return 0; + if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0) + *version = 1; + else + *version = 2; } /* MTDS : Dynamic SAR Power Table */ static int -mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version) +mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version) { int len, ret, sarlen, prelen, tblcnt; bool enable; - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len); + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len); if (ret) return ret; /* Table content validation */ switch (version) { case 1: - enable = ((struct mt7921_asar_dyn *)*table)->enable; - sarlen = sizeof(struct mt7921_asar_dyn_limit); - prelen = sizeof(struct mt7921_asar_dyn); + enable = ((struct mt792x_asar_dyn *)*table)->enable; + sarlen = sizeof(struct mt792x_asar_dyn_limit); + prelen = sizeof(struct mt792x_asar_dyn); break; case 2: - enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable; - sarlen = sizeof(struct mt7921_asar_dyn_limit_v2); - prelen = sizeof(struct mt7921_asar_dyn_v2); + enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable; + sarlen = sizeof(struct mt792x_asar_dyn_limit_v2); + prelen = sizeof(struct mt792x_asar_dyn_v2); break; default: return -EINVAL; @@ -101,88 +104,89 @@ mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version) tblcnt = (len - prelen) / sarlen; if (!enable || - tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN) - ret = -EINVAL; + tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN) + return -EINVAL; - return ret; + return 0; } /* MTGS : Geo SAR Power Table */ static int -mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version) +mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version) { - int len, ret = 0, sarlen, prelen, tblcnt; + int len, ret, sarlen, prelen, tblcnt; - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len); + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len); if (ret) return ret; /* Table content validation */ switch (version) { case 1: - sarlen = sizeof(struct mt7921_asar_geo_limit); - prelen = sizeof(struct mt7921_asar_geo); + sarlen = sizeof(struct mt792x_asar_geo_limit); + prelen = sizeof(struct mt792x_asar_geo); break; case 2: - sarlen = sizeof(struct mt7921_asar_geo_limit_v2); - prelen = sizeof(struct mt7921_asar_geo_v2); + sarlen = sizeof(struct mt792x_asar_geo_limit_v2); + prelen = sizeof(struct mt792x_asar_geo_v2); break; default: return -EINVAL; } tblcnt = (len - prelen) / sarlen; - if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO) - ret = -EINVAL; + if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO) + return -EINVAL; - return ret; + return 0; } /* MTFG : Flag Table */ static int -mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table) +mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table) { int len, ret; - ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len); + ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len); if (ret) return ret; - if (len < MT7921_ASAR_MIN_FG) - ret = -EINVAL; + if (len < MT792x_ASAR_MIN_FG) + return -EINVAL; - return ret; + return 0; } -int mt7921_init_acpi_sar(struct mt7921_dev *dev) +int mt792x_init_acpi_sar(struct mt792x_dev *dev) { - struct mt7921_acpi_sar *asar; + struct mt792x_acpi_sar *asar; int ret; asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL); if (!asar) return -ENOMEM; - mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); + mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver); /* MTDS is mandatory. Return error if table is invalid */ - ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); + ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver); if (ret) { devm_kfree(dev->mt76.dev, asar->dyn); devm_kfree(dev->mt76.dev, asar->countrylist); devm_kfree(dev->mt76.dev, asar); + return ret; } /* MTGS is optional */ - ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver); + ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver); if (ret) { devm_kfree(dev->mt76.dev, asar->geo); asar->geo = NULL; } /* MTFG is optional */ - ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg); + ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg); if (ret) { devm_kfree(dev->mt76.dev, asar->fg); asar->fg = NULL; @@ -191,13 +195,14 @@ int mt7921_init_acpi_sar(struct mt7921_dev *dev) return 0; } +EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar); static s8 -mt7921_asar_get_geo_pwr(struct mt7921_phy *phy, +mt792x_asar_get_geo_pwr(struct mt792x_phy *phy, enum nl80211_band band, s8 dyn_power) { - struct mt7921_acpi_sar *asar = phy->acpisar; - struct mt7921_asar_geo_band *band_pwr; + struct mt792x_acpi_sar *asar = phy->acpisar; + struct mt792x_asar_geo_band *band_pwr; s8 geo_power; u8 idx, max; @@ -248,12 +253,12 @@ mt7921_asar_get_geo_pwr(struct mt7921_phy *phy, } static s8 -mt7921_asar_range_pwr(struct mt7921_phy *phy, +mt792x_asar_range_pwr(struct mt792x_phy *phy, const struct cfg80211_sar_freq_ranges *range, u8 idx) { const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; - struct mt7921_acpi_sar *asar = phy->acpisar; + struct mt792x_acpi_sar *asar = phy->acpisar; u8 *limit, band, max; if (!capa) @@ -277,10 +282,10 @@ mt7921_asar_range_pwr(struct mt7921_phy *phy, else band = NL80211_BAND_2GHZ; - return mt7921_asar_get_geo_pwr(phy, band, limit[idx]); + return mt792x_asar_get_geo_pwr(phy, band, limit[idx]); } -int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) +int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default) { const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa; int i; @@ -300,41 +305,46 @@ int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default) continue; frp->power = min_t(s8, set_default ? 127 : frp->power, - mt7921_asar_range_pwr(phy, frp->range, i)); + mt792x_asar_range_pwr(phy, frp->range, i)); } return 0; } +EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power); -u8 mt7921_acpi_get_flags(struct mt7921_phy *phy) +u8 mt792x_acpi_get_flags(struct mt792x_phy *phy) { - struct mt7921_asar_fg *fg; + struct mt792x_acpi_sar *acpisar = phy->acpisar; + struct mt792x_asar_fg *fg; struct { u8 acpi_idx; u8 chip_idx; } map[] = { - {1, 1}, - {4, 2}, + { 1, 1 }, + { 4, 2 }, }; u8 flags = BIT(0); int i, j; - if (!phy->acpisar) + if (!acpisar) return 0; - fg = phy->acpisar->fg; + fg = acpisar->fg; if (!fg) return flags; /* pickup necessary settings per device and * translate the index of bitmap for chip command. */ - for (i = 0; i < fg->nr_flag; i++) - for (j = 0; j < ARRAY_SIZE(map); j++) + for (i = 0; i < fg->nr_flag; i++) { + for (j = 0; j < ARRAY_SIZE(map); j++) { if (fg->flag[i] == map[j].acpi_idx) { flags |= BIT(map[j].chip_idx); break; } + } + } return flags; } +EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h new file mode 100644 index 000000000000..d6d332e863ba --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT7921_ACPI_SAR_H +#define __MT7921_ACPI_SAR_H + +#define MT792x_ASAR_MIN_DYN 1 +#define MT792x_ASAR_MAX_DYN 8 +#define MT792x_ASAR_MIN_GEO 3 +#define MT792x_ASAR_MAX_GEO 8 +#define MT792x_ASAR_MIN_FG 8 + +#define MT792x_ACPI_MTCL "MTCL" +#define MT792x_ACPI_MTDS "MTDS" +#define MT792x_ACPI_MTGS "MTGS" +#define MT792x_ACPI_MTFG "MTFG" + +struct mt792x_asar_dyn_limit { + u8 idx; + u8 frp[5]; +} __packed; + +struct mt792x_asar_dyn { + u8 names[4]; + u8 enable; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit, tbl); +} __packed; + +struct mt792x_asar_dyn_limit_v2 { + u8 idx; + u8 frp[11]; +} __packed; + +struct mt792x_asar_dyn_v2 { + u8 names[4]; + u8 enable; + u8 rsvd; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_dyn_limit_v2, tbl); +} __packed; + +struct mt792x_asar_geo_band { + u8 pwr; + u8 offset; +} __packed; + +struct mt792x_asar_geo_limit { + u8 idx; + /* 0:2G, 1:5G */ + struct mt792x_asar_geo_band band[2]; +} __packed; + +struct mt792x_asar_geo { + u8 names[4]; + u8 version; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit, tbl); +} __packed; + +struct mt792x_asar_geo_limit_v2 { + u8 idx; + /* 0:2G, 1:5G, 2:6G */ + struct mt792x_asar_geo_band band[3]; +} __packed; + +struct mt792x_asar_geo_v2 { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_tbl; + DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl); +} __packed; + +struct mt792x_asar_cl { + u8 names[4]; + u8 version; + u8 mode_6g; + u8 cl6g[6]; +} __packed; + +struct mt792x_asar_fg { + u8 names[4]; + u8 version; + u8 rsvd; + u8 nr_flag; + u8 rsvd1; + u8 flag[]; +} __packed; + +struct mt792x_acpi_sar { + u8 ver; + union { + struct mt792x_asar_dyn *dyn; + struct mt792x_asar_dyn_v2 *dyn_v2; + }; + union { + struct mt792x_asar_geo *geo; + struct mt792x_asar_geo_v2 *geo_v2; + }; + struct mt792x_asar_cl *countrylist; + struct mt792x_asar_fg *fg; +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c new file mode 100644 index 000000000000..46be7f996c7e --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c @@ -0,0 +1,844 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/module.h> +#include <linux/firmware.h> + +#include "mt792x.h" +#include "dma.h" + +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = MT792x_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_STATION) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) + } +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = MT792x_MAX_INTERFACES, + .num_different_channels = 1, + .beacon_int_infra_match = true, + }, +}; + +static const struct ieee80211_iface_limit if_limits_chanctx[] = { + { + .max = 2, + .types = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_P2P_CLIENT) + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_GO) + } +}; + +static const struct ieee80211_iface_combination if_comb_chanctx[] = { + { + .limits = if_limits_chanctx, + .n_limits = ARRAY_SIZE(if_limits_chanctx), + .max_interfaces = 2, + .num_different_channels = 2, + .beacon_int_infra_match = false, + } +}; + +void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + int qid; + + if (control->sta) { + struct mt792x_sta *sta; + + sta = (struct mt792x_sta *)control->sta->drv_priv; + wcid = &sta->wcid; + } + + if (vif && !control->sta) { + struct mt792x_vif *mvif; + + mvif = (struct mt792x_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + + if (mt76_connac_pm_ref(mphy, &dev->pm)) { + mt76_tx(mphy, control->sta, wcid, skb); + mt76_connac_pm_unref(mphy, &dev->pm); + return; + } + + qid = skb_get_queue_mapping(skb); + if (qid >= MT_TXQ_PSD) { + qid = IEEE80211_AC_BE; + skb_set_queue_mapping(skb, qid); + } + + mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb); +} +EXPORT_SYMBOL_GPL(mt792x_tx); + +void mt792x_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_sta *msta = &mvif->sta; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + int idx = msta->wcid.idx; + + mt792x_mutex_acquire(dev); + mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); + mt76_connac_mcu_uni_add_dev(&dev->mphy, vif, &mvif->sta.wcid, false); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + + dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx); + phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); + mt792x_mutex_release(dev); + + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); + + mt76_packet_id_flush(&dev->mt76, &msta->wcid); +} +EXPORT_SYMBOL_GPL(mt792x_remove_interface); + +int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + unsigned int link_id, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + + /* no need to update right away, we'll get BSS_CHANGED_QOS */ + queue = mt76_connac_lmac_mapping(queue); + mvif->queue_params[queue] = *params; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_conf_tx); + +int mt792x_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt76_mib_stats *mib = &phy->mib; + + mt792x_mutex_acquire(phy->dev); + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + mt792x_mutex_release(phy->dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_get_stats); + +u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u8 omac_idx = mvif->mt76.omac_idx; + union { + u64 t64; + u32 t32[2]; + } tsf; + u16 n; + + mt792x_mutex_acquire(dev); + + n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; + /* TSF software read */ + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE); + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0)); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0)); + + mt792x_mutex_release(dev); + + return tsf.t64; +} +EXPORT_SYMBOL_GPL(mt792x_get_tsf); + +void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u64 timestamp) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + u8 omac_idx = mvif->mt76.omac_idx; + union { + u64 t64; + u32 t32[2]; + } tsf = { .t64 = timestamp, }; + u16 n; + + mt792x_mutex_acquire(dev); + + n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx; + mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]); + mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]); + /* TSF software overwrite */ + mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE); + + mt792x_mutex_release(dev); +} +EXPORT_SYMBOL_GPL(mt792x_set_tsf); + +void mt792x_tx_worker(struct mt76_worker *w) +{ + struct mt792x_dev *dev = container_of(w, struct mt792x_dev, + mt76.tx_worker); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return; + } + + mt76_txq_schedule_all(&dev->mphy); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); +} +EXPORT_SYMBOL_GPL(mt792x_tx_worker); + +void mt792x_roc_timer(struct timer_list *timer) +{ + struct mt792x_phy *phy = from_timer(phy, timer, roc_timer); + + ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); +} +EXPORT_SYMBOL_GPL(mt792x_roc_timer); + +void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + wait_event_timeout(dev->mt76.tx_wait, + !mt76_has_tx_pending(&dev->mphy), HZ / 2); +} +EXPORT_SYMBOL_GPL(mt792x_flush); + +int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mvif->ctx = ctx; + mutex_unlock(&dev->mt76.mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_assign_vif_chanctx); + +void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *link_conf, + struct ieee80211_chanctx_conf *ctx) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct mt792x_dev *dev = mt792x_hw_dev(hw); + + mutex_lock(&dev->mt76.mutex); + mvif->ctx = NULL; + mutex_unlock(&dev->mt76.mutex); +} +EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx); + +void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct mt792x_dev *dev = mt792x_hw_dev(hw); + struct mt76_dev *mdev = &dev->mt76; + + device_set_wakeup_enable(mdev->dev, enabled); +} +EXPORT_SYMBOL_GPL(mt792x_set_wakeup); + +static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = { + /* tx counters */ + "tx_ampdu_cnt", + "tx_mpdu_attempts", + "tx_mpdu_success", + "tx_pkt_ebf_cnt", + "tx_pkt_ibf_cnt", + "tx_ampdu_len:0-1", + "tx_ampdu_len:2-10", + "tx_ampdu_len:11-19", + "tx_ampdu_len:20-28", + "tx_ampdu_len:29-37", + "tx_ampdu_len:38-46", + "tx_ampdu_len:47-55", + "tx_ampdu_len:56-79", + "tx_ampdu_len:80-103", + "tx_ampdu_len:104-127", + "tx_ampdu_len:128-151", + "tx_ampdu_len:152-175", + "tx_ampdu_len:176-199", + "tx_ampdu_len:200-223", + "tx_ampdu_len:224-247", + "ba_miss_count", + "tx_beamformer_ppdu_iBF", + "tx_beamformer_ppdu_eBF", + "tx_beamformer_rx_feedback_all", + "tx_beamformer_rx_feedback_he", + "tx_beamformer_rx_feedback_vht", + "tx_beamformer_rx_feedback_ht", + "tx_msdu_pack_1", + "tx_msdu_pack_2", + "tx_msdu_pack_3", + "tx_msdu_pack_4", + "tx_msdu_pack_5", + "tx_msdu_pack_6", + "tx_msdu_pack_7", + "tx_msdu_pack_8", + /* rx counters */ + "rx_mpdu_cnt", + "rx_ampdu_cnt", + "rx_ampdu_bytes_cnt", + "rx_ba_cnt", + /* per vif counters */ + "v_tx_mode_cck", + "v_tx_mode_ofdm", + "v_tx_mode_ht", + "v_tx_mode_ht_gf", + "v_tx_mode_vht", + "v_tx_mode_he_su", + "v_tx_mode_he_ext_su", + "v_tx_mode_he_tb", + "v_tx_mode_he_mu", + "v_tx_mode_eht_su", + "v_tx_mode_eht_trig", + "v_tx_mode_eht_mu", + "v_tx_bw_20", + "v_tx_bw_40", + "v_tx_bw_80", + "v_tx_bw_160", + "v_tx_mcs_0", + "v_tx_mcs_1", + "v_tx_mcs_2", + "v_tx_mcs_3", + "v_tx_mcs_4", + "v_tx_mcs_5", + "v_tx_mcs_6", + "v_tx_mcs_7", + "v_tx_mcs_8", + "v_tx_mcs_9", + "v_tx_mcs_10", + "v_tx_mcs_11", + "v_tx_mcs_12", + "v_tx_mcs_13", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", +}; + +void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 sset, u8 *data) +{ + if (sset != ETH_SS_STATS) + return; + + memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats)); + + data += sizeof(mt792x_gstrings_stats); + page_pool_ethtool_stats_get_strings(data); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_strings); + +int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int sset) +{ + if (sset != ETH_SS_STATS) + return 0; + + return ARRAY_SIZE(mt792x_gstrings_stats) + + page_pool_ethtool_stats_get_count(); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_sset_count); + +static void +mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct mt76_ethtool_worker_info *wi = wi_data; + + if (msta->vif->mt76.idx != wi->idx) + return; + + mt76_ethtool_worker(wi, &msta->wcid.stats, true); +} + +void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data) +{ + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + int stats_size = ARRAY_SIZE(mt792x_gstrings_stats); + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + struct mt76_mib_stats *mib = &phy->mib; + struct mt76_ethtool_worker_info wi = { + .data = data, + .idx = mvif->mt76.idx, + }; + int i, ei = 0; + + mt792x_mutex_acquire(dev); + + mt792x_mac_update_mib_stats(phy); + + data[ei++] = mib->tx_ampdu_cnt; + data[ei++] = mib->tx_mpdu_attempts_cnt; + data[ei++] = mib->tx_mpdu_success_cnt; + data[ei++] = mib->tx_pkt_ebf_cnt; + data[ei++] = mib->tx_pkt_ibf_cnt; + + /* Tx ampdu stat */ + for (i = 0; i < 15; i++) + data[ei++] = phy->mt76->aggr_stats[i]; + + data[ei++] = phy->mib.ba_miss_cnt; + + /* Tx Beamformer monitor */ + data[ei++] = mib->tx_bf_ibf_ppdu_cnt; + data[ei++] = mib->tx_bf_ebf_ppdu_cnt; + + /* Tx Beamformer Rx feedback monitor */ + data[ei++] = mib->tx_bf_rx_fb_all_cnt; + data[ei++] = mib->tx_bf_rx_fb_he_cnt; + data[ei++] = mib->tx_bf_rx_fb_vht_cnt; + data[ei++] = mib->tx_bf_rx_fb_ht_cnt; + + /* Tx amsdu info (pack-count histogram) */ + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) + data[ei++] = mib->tx_amsdu[i]; + + /* rx counters */ + data[ei++] = mib->rx_mpdu_cnt; + data[ei++] = mib->rx_ampdu_cnt; + data[ei++] = mib->rx_ampdu_bytes_cnt; + data[ei++] = mib->rx_ba_cnt; + + /* Add values for all stations owned by this vif */ + wi.initial_stat_idx = ei; + ieee80211_iterate_stations_atomic(hw, mt792x_ethtool_worker, &wi); + + mt792x_mutex_release(dev); + + if (!wi.sta_count) + return; + + ei += wi.worker_stat_count; + + mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei); + stats_size += page_pool_ethtool_stats_get_count(); + + if (ei != stats_size) + dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, + stats_size); +} +EXPORT_SYMBOL_GPL(mt792x_get_et_stats); + +void mt792x_sta_statistics(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct station_info *sinfo) +{ + struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; + struct rate_info *txrate = &msta->wcid.rate; + + if (!txrate->legacy && !txrate->flags) + return; + + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->tx_failed = msta->wcid.stats.tx_failed; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); + + sinfo->tx_retries = msta->wcid.stats.tx_retries; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); + + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + + sinfo->ack_signal = (s8)msta->ack_signal; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL); + + sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); +} +EXPORT_SYMBOL_GPL(mt792x_sta_statistics); + +void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + + mt792x_mutex_acquire(dev); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt792x_mac_set_timeing(phy); + + mt792x_mutex_release(dev); +} +EXPORT_SYMBOL_GPL(mt792x_set_coverage_class); + +int mt792x_init_wiphy(struct ieee80211_hw *hw) +{ + struct mt792x_phy *phy = mt792x_hw_phy(hw); + struct mt792x_dev *dev = phy->dev; + struct wiphy *wiphy = hw->wiphy; + + hw->queues = 4; + if (dev->has_eht) { + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT; + } else { + hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE; + } + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; + + phy->slottime = 9; + + hw->sta_data_size = sizeof(struct mt792x_sta); + hw->vif_data_size = sizeof(struct mt792x_vif); + + if (dev->fw_features & MT792x_FW_CAP_CNM) { + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + wiphy->iface_combinations = if_comb_chanctx; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx); + } else { + wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + } + wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP | + WIPHY_FLAG_4ADDR_STATION); + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); + wiphy->max_remain_on_channel_duration = 5000; + wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN; + wiphy->max_scan_ssids = 4; + wiphy->max_sched_scan_plan_interval = + MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL; + wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN; + wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID; + wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH; + wiphy->max_sched_scan_reqs = 1; + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_SPLIT_SCAN_6GHZ; + + wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + + ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); + ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + ieee80211_hw_set(hw, CONNECTION_MONITOR); + + if (dev->pm.enable) + ieee80211_hw_set(hw, CONNECTION_MONITOR); + + hw->max_tx_fragments = 4; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_wiphy); + +static u8 +mt792x_get_offload_capability(struct device *dev, const char *fw_wm) +{ + const struct mt76_connac2_fw_trailer *hdr; + struct mt792x_realease_info *rel_info; + const struct firmware *fw; + int ret, i, offset = 0; + const u8 *data, *end; + u8 offload_caps = 0; + + ret = request_firmware(&fw, fw_wm, dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev, "Invalid firmware\n"); + goto out; + } + + data = fw->data; + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + + for (i = 0; i < hdr->n_region; i++) { + const struct mt76_connac2_fw_region *region; + + region = (const void *)((const u8 *)hdr - + (hdr->n_region - i) * sizeof(*region)); + offset += le32_to_cpu(region->len); + } + + data += offset + 16; + rel_info = (struct mt792x_realease_info *)data; + data += sizeof(*rel_info); + end = data + le16_to_cpu(rel_info->len); + + while (data < end) { + rel_info = (struct mt792x_realease_info *)data; + data += sizeof(*rel_info); + + if (rel_info->tag == MT792x_FW_TAG_FEATURE) { + struct mt792x_fw_features *features; + + features = (struct mt792x_fw_features *)data; + offload_caps = features->data; + break; + } + + data += le16_to_cpu(rel_info->len) + rel_info->pad_len; + } + +out: + release_firmware(fw); + + return offload_caps; +} + +struct ieee80211_ops * +mt792x_get_mac80211_ops(struct device *dev, + const struct ieee80211_ops *mac80211_ops, + void *drv_data, u8 *fw_features) +{ + struct ieee80211_ops *ops; + + ops = devm_kmemdup(dev, mac80211_ops, sizeof(struct ieee80211_ops), + GFP_KERNEL); + if (!ops) + return NULL; + + *fw_features = mt792x_get_offload_capability(dev, drv_data); + if (!(*fw_features & MT792x_FW_CAP_CNM)) { + ops->remain_on_channel = NULL; + ops->cancel_remain_on_channel = NULL; + ops->add_chanctx = NULL; + ops->remove_chanctx = NULL; + ops->change_chanctx = NULL; + ops->assign_vif_chanctx = NULL; + ops->unassign_vif_chanctx = NULL; + ops->mgd_prepare_tx = NULL; + ops->mgd_complete_tx = NULL; + } + return ops; +} +EXPORT_SYMBOL_GPL(mt792x_get_mac80211_ops); + +int mt792x_init_wcid(struct mt792x_dev *dev) +{ + int idx; + + /* Beacon and mgmt frames should occupy wcid 0 */ + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1); + if (idx) + return -ENOSPC; + + dev->mt76.global_wcid.idx = idx; + dev->mt76.global_wcid.hw_key_idx = -1; + dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET; + rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_init_wcid); + +int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err = 0; + + mutex_lock(&pm->mutex); + + if (!test_bit(MT76_STATE_PM, &mphy->state)) + goto out; + + err = __mt792x_mcu_drv_pmctrl(dev); +out: + mutex_unlock(&pm->mutex); + + if (err) + mt792x_reset(&dev->mt76); + + return err; +} +EXPORT_SYMBOL_GPL(mt792x_mcu_drv_pmctrl); + +int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err = 0; + + mutex_lock(&pm->mutex); + + if (mt76_connac_skip_fw_pmctrl(mphy, pm)) + goto out; + + err = __mt792x_mcu_fw_pmctrl(dev); +out: + mutex_unlock(&pm->mutex); + + if (err) + mt792x_reset(&dev->mt76); + + return err; +} +EXPORT_SYMBOL_GPL(mt792x_mcu_fw_pmctrl); + +int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + int i, err = 0; + + for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { + mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, + PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1)) + break; + } + + if (i == MT792x_DRV_OWN_RETRY_COUNT) { + dev_err(dev->mt76.dev, "driver own failed\n"); + err = -EIO; + } + + return err; +} +EXPORT_SYMBOL_GPL(__mt792xe_mcu_drv_pmctrl); + +int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int err; + + err = __mt792xe_mcu_drv_pmctrl(dev); + if (err < 0) + goto out; + + mt792x_wpdma_reinit_cond(dev); + clear_bit(MT76_STATE_PM, &mphy->state); + + pm->stats.last_wake_event = jiffies; + pm->stats.doze_time += pm->stats.last_wake_event - + pm->stats.last_doze_event; +out: + return err; +} +EXPORT_SYMBOL_GPL(mt792xe_mcu_drv_pmctrl); + +int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; + int i; + + for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) { + mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN); + if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL, + PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1)) + break; + } + + if (i == MT792x_DRV_OWN_RETRY_COUNT) { + dev_err(dev->mt76.dev, "firmware own failed\n"); + clear_bit(MT76_STATE_PM, &mphy->state); + return -EIO; + } + + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xe_mcu_fw_pmctrl); + +int mt792x_load_firmware(struct mt792x_dev *dev) +{ + int ret; + + ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev)); + if (ret) + return ret; + + if (mt76_is_sdio(&dev->mt76)) { + /* activate again */ + ret = __mt792x_mcu_fw_pmctrl(dev); + if (!ret) + ret = __mt792x_mcu_drv_pmctrl(dev); + } + + ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, + MT_TOP_MISC2_FW_N9_RDY, 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + + return -EIO; + } + +#ifdef CONFIG_PM + dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support; +#endif /* CONFIG_PM */ + + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_load_firmware); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c new file mode 100644 index 000000000000..9858d9a93851 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_debugfs.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include "mt792x.h" + +static void +mt792x_ampdu_stat_read_phy(struct mt792x_phy *phy, + struct seq_file *file) +{ + struct mt792x_dev *dev = file->private; + int bound[15], range[4], i; + + if (!phy) + return; + + mt792x_mac_update_mib_stats(phy); + + /* Tx ampdu stat */ + for (i = 0; i < ARRAY_SIZE(range); i++) + range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i)); + + for (i = 0; i < ARRAY_SIZE(bound); i++) + bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i % 4) + 1; + + seq_puts(file, "\nPhy0\n"); + + seq_printf(file, "Length: %8d | ", bound[0]); + for (i = 0; i < ARRAY_SIZE(bound) - 1; i++) + seq_printf(file, "%3d %3d | ", bound[i] + 1, bound[i + 1]); + + seq_puts(file, "\nCount: "); + for (i = 0; i < ARRAY_SIZE(bound); i++) + seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]); + seq_puts(file, "\n"); + + seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt); +} + +int mt792x_tx_stats_show(struct seq_file *file, void *data) +{ + struct mt792x_dev *dev = file->private; + struct mt792x_phy *phy = &dev->phy; + struct mt76_mib_stats *mib = &phy->mib; + int i; + + mt792x_mutex_acquire(dev); + + mt792x_ampdu_stat_read_phy(phy, file); + + seq_puts(file, "Tx MSDU stat:\n"); + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { + seq_printf(file, "AMSDU pack count of %d MSDU in TXD: %8d ", + i + 1, mib->tx_amsdu[i]); + if (mib->tx_amsdu_cnt) + seq_printf(file, "(%3d%%)\n", + mib->tx_amsdu[i] * 100 / mib->tx_amsdu_cnt); + else + seq_puts(file, "\n"); + } + + mt792x_mutex_release(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_tx_stats_show); + +int mt792x_queues_acq(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + int i; + + mt792x_mutex_acquire(dev); + + for (i = 0; i < 4; i++) { + u32 ctrl, val, qlen = 0; + int j; + + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i)); + ctrl = BIT(31) | BIT(11) | (i << 24); + + for (j = 0; j < 32; j++) { + if (val & BIT(j)) + continue; + + mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j); + qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, + GENMASK(11, 0)); + } + seq_printf(s, "AC%d: queued=%d\n", i, qlen); + } + + mt792x_mutex_release(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_queues_acq); + +int mt792x_queues_read(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + struct { + struct mt76_queue *q; + char *queue; + } queue_map[] = { + { dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" }, + { dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" }, + { dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(queue_map); i++) { + struct mt76_queue *q = queue_map[i].q; + + if (!q) + continue; + + seq_printf(s, + "%s: queued=%d head=%d tail=%d\n", + queue_map[i].queue, q->queued, q->head, + q->tail); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_queues_read); + +int mt792x_pm_stats(struct seq_file *s, void *data) +{ + struct mt792x_dev *dev = dev_get_drvdata(s->private); + struct mt76_connac_pm *pm = &dev->pm; + + unsigned long awake_time = pm->stats.awake_time; + unsigned long doze_time = pm->stats.doze_time; + + if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) + awake_time += jiffies - pm->stats.last_wake_event; + else + doze_time += jiffies - pm->stats.last_doze_event; + + seq_printf(s, "awake time: %14u\ndoze time: %15u\n", + jiffies_to_msecs(awake_time), + jiffies_to_msecs(doze_time)); + + seq_printf(s, "low power wakes: %9d\n", pm->stats.lp_wake); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_stats); + +int mt792x_pm_idle_timeout_set(void *data, u64 val) +{ + struct mt792x_dev *dev = data; + + dev->pm.idle_timeout = msecs_to_jiffies(val); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_set); + +int mt792x_pm_idle_timeout_get(void *data, u64 *val) +{ + struct mt792x_dev *dev = data; + + *val = jiffies_to_msecs(dev->pm.idle_timeout); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_pm_idle_timeout_get); diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c index 4153cd6c2a01..a3dbd3865b2f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c @@ -1,52 +1,93 @@ // SPDX-License-Identifier: ISC -/* Copyright (C) 2020 MediaTek Inc. */ +/* Copyright (C) 2023 MediaTek Inc. */ -#include "mt7921.h" -#include "../dma.h" -#include "../mt76_connac2_mac.h" +#include <linux/module.h> +#include <linux/firmware.h> -static int mt7921_poll_tx(struct napi_struct *napi, int budget) +#include "mt792x.h" +#include "dma.h" +#include "trace.h" + +irqreturn_t mt792x_irq_handler(int irq, void *dev_instance) { - struct mt7921_dev *dev; + struct mt792x_dev *dev = dev_instance; - dev = container_of(napi, struct mt7921_dev, mt76.tx_napi); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - napi_complete(napi); - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return 0; - } + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; - mt76_connac_tx_cleanup(&dev->mt76); - if (napi_complete(napi)) - mt76_connac_irq_enable(&dev->mt76, MT_INT_TX_DONE_ALL); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); + tasklet_schedule(&dev->mt76.irq_tasklet); - return 0; + return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(mt792x_irq_handler); -static int mt7921_poll_rx(struct napi_struct *napi, int budget) +void mt792x_irq_tasklet(unsigned long data) { - struct mt7921_dev *dev; - int done; + struct mt792x_dev *dev = (struct mt792x_dev *)data; + const struct mt792x_irq_map *irq_map = dev->irq_map; + u32 intr, mask = 0; - dev = container_of(napi->dev, struct mt7921_dev, mt76.napi_dev); + mt76_wr(dev, irq_map->host_irq_enable, 0); - if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { - napi_complete(napi); - queue_work(dev->mt76.wq, &dev->pm.wake_work); - return 0; + intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA); + intr &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr); + + trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask); + + mask |= intr & (irq_map->rx.data_complete_mask | + irq_map->rx.wm_complete_mask | + irq_map->rx.wm2_complete_mask); + if (intr & dev->irq_map->tx.mcu_complete_mask) + mask |= dev->irq_map->tx.mcu_complete_mask; + + if (intr & MT_INT_MCU_CMD) { + u32 intr_sw; + + intr_sw = mt76_rr(dev, MT_MCU_CMD); + /* ack MCU2HOST_SW_INT_STA */ + mt76_wr(dev, MT_MCU_CMD, intr_sw); + if (intr_sw & MT_MCU_CMD_WAKE_RX_PCIE) { + mask |= irq_map->rx.data_complete_mask; + intr |= irq_map->rx.data_complete_mask; + } } - done = mt76_dma_rx_poll(napi, budget); - mt76_connac_pm_unref(&dev->mphy, &dev->pm); - return done; + mt76_set_irq_mask(&dev->mt76, irq_map->host_irq_enable, mask, 0); + + if (intr & dev->irq_map->tx.all_complete_mask) + napi_schedule(&dev->mt76.tx_napi); + + if (intr & irq_map->rx.wm_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]); + + if (intr & irq_map->rx.wm2_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]); + + if (intr & irq_map->rx.data_complete_mask) + napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]); } +EXPORT_SYMBOL_GPL(mt792x_irq_tasklet); -static void mt7921_dma_prefetch(struct mt7921_dev *dev) +void mt792x_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { -#define PREFETCH(base, depth) ((base) << 16 | (depth)) + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + const struct mt792x_irq_map *irq_map = dev->irq_map; + + if (q == MT_RXQ_MAIN) + mt76_connac_irq_enable(mdev, irq_map->rx.data_complete_mask); + else if (q == MT_RXQ_MCU_WA) + mt76_connac_irq_enable(mdev, irq_map->rx.wm2_complete_mask); + else + mt76_connac_irq_enable(mdev, irq_map->rx.wm_complete_mask); +} +EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete); +#define PREFETCH(base, depth) ((base) << 16 | (depth)) +static void mt792x_dma_prefetch(struct mt792x_dev *dev) +{ mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4)); mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4)); mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4)); @@ -64,44 +105,10 @@ static void mt7921_dma_prefetch(struct mt7921_dev *dev) mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4)); } -static int mt7921_dma_disable(struct mt7921_dev *dev, bool force) -{ - /* disable WFDMA0 */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - - if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | - MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) - return -ETIMEDOUT; - - /* disable dmashdl */ - mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, - MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); - mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); - - if (force) { - /* reset */ - mt76_clear(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - - mt76_set(dev, MT_WFDMA0_RST, - MT_WFDMA0_RST_DMASHDL_ALL_RST | - MT_WFDMA0_RST_LOGIC_RST); - } - - return 0; -} - -static int mt7921_dma_enable(struct mt7921_dev *dev) +int mt792x_dma_enable(struct mt792x_dev *dev) { /* configure perfetch settings */ - mt7921_dma_prefetch(dev); + mt792x_dma_prefetch(dev); /* reset dma idx */ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); @@ -124,18 +131,23 @@ static int mt7921_dma_enable(struct mt7921_dev *dev) /* enable interrupts for TX/RX rings */ mt76_connac_irq_enable(&dev->mt76, - MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + dev->irq_map->tx.all_complete_mask | + dev->irq_map->rx.data_complete_mask | + dev->irq_map->rx.wm2_complete_mask | + dev->irq_map->rx.wm_complete_mask | MT_INT_MCU_CMD); mt76_set(dev, MT_MCU2HOST_SW_INT_ENA, MT_MCU_CMD_WAKE_RX_PCIE); return 0; } +EXPORT_SYMBOL_GPL(mt792x_dma_enable); -static int mt7921_dma_reset(struct mt7921_dev *dev, bool force) +static int +mt792x_dma_reset(struct mt792x_dev *dev, bool force) { int i, err; - err = mt7921_dma_disable(dev, force); + err = mt792x_dma_disable(dev, force); if (err) return err; @@ -151,23 +163,10 @@ static int mt7921_dma_reset(struct mt7921_dev *dev, bool force) mt76_tx_status_check(&dev->mt76, true); - return mt7921_dma_enable(dev); -} - -int mt7921_wfsys_reset(struct mt7921_dev *dev) -{ - mt76_clear(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B); - msleep(50); - mt76_set(dev, MT_WFSYS_SW_RST_B, WFSYS_SW_RST_B); - - if (!__mt76_poll_msec(&dev->mt76, MT_WFSYS_SW_RST_B, - WFSYS_SW_INIT_DONE, WFSYS_SW_INIT_DONE, 500)) - return -ETIMEDOUT; - - return 0; + return mt792x_dma_enable(dev); } -int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force) +int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force) { int i, err; @@ -182,11 +181,11 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force) mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]); if (force) { - err = mt7921_wfsys_reset(dev); + err = mt792x_wfsys_reset(dev); if (err) return err; } - err = mt7921_dma_reset(dev, force); + err = mt792x_dma_reset(dev, force); if (err) return err; @@ -195,19 +194,20 @@ int mt7921_wpdma_reset(struct mt7921_dev *dev, bool force) return 0; } +EXPORT_SYMBOL_GPL(mt792x_wpdma_reset); -int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev) +int mt792x_wpdma_reinit_cond(struct mt792x_dev *dev) { struct mt76_connac_pm *pm = &dev->pm; int err; /* check if the wpdma must be reinitialized */ - if (mt7921_dma_need_reinit(dev)) { + if (mt792x_dma_need_reinit(dev)) { /* disable interrutpts */ - mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); + mt76_wr(dev, dev->irq_map->host_irq_enable, 0); mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); - err = mt7921_wpdma_reset(dev, false); + err = mt792x_wpdma_reset(dev, false); if (err) { dev_err(dev->mt76.dev, "wpdma reset failed\n"); return err; @@ -220,73 +220,44 @@ int mt7921_wpdma_reinit_cond(struct mt7921_dev *dev) return 0; } +EXPORT_SYMBOL_GPL(mt792x_wpdma_reinit_cond); -int mt7921_dma_init(struct mt7921_dev *dev) +int mt792x_dma_disable(struct mt792x_dev *dev, bool force) { - int ret; - - mt76_dma_attach(&dev->mt76); - - ret = mt7921_dma_disable(dev, true); - if (ret) - return ret; - - /* init tx queue */ - ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0, - MT7921_TX_RING_SIZE, - MT_TX_RING_BASE, 0); - if (ret) - return ret; - - mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4); - - /* command to WM */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM, - MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE); - if (ret) - return ret; - - /* firmware download */ - ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL, - MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE); - if (ret) - return ret; - - /* event from WM before firmware download */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], - MT7921_RXQ_MCU_WM, - MT7921_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE); - if (ret) - return ret; - - /* Change mcu queue after firmware download */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], - MT7921_RXQ_MCU_WM, - MT7921_RX_MCU_RING_SIZE, - MT_RX_BUF_SIZE, MT_WFDMA0(0x540)); - if (ret) - return ret; - - /* rx data */ - ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], - MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE, - MT_RX_BUF_SIZE, MT_RX_DATA_RING_BASE); - if (ret) - return ret; - - ret = mt76_init_queues(dev, mt7921_poll_rx); - if (ret < 0) - return ret; - - netif_napi_add_tx(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, - mt7921_poll_tx); - napi_enable(&dev->mt76.tx_napi); - - return mt7921_dma_enable(dev); + /* disable WFDMA0 */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (!mt76_poll_msec_tick(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_BUSY | + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 100, 1)) + return -ETIMEDOUT; + + /* disable dmashdl */ + mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + if (force) { + /* reset */ + mt76_clear(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + + mt76_set(dev, MT_WFDMA0_RST, + MT_WFDMA0_RST_DMASHDL_ALL_RST | + MT_WFDMA0_RST_LOGIC_RST); + } + + return 0; } +EXPORT_SYMBOL_GPL(mt792x_dma_disable); -void mt7921_dma_cleanup(struct mt7921_dev *dev) +void mt792x_dma_cleanup(struct mt792x_dev *dev) { /* disable */ mt76_clear(dev, MT_WFDMA0_GLO_CFG, @@ -312,3 +283,62 @@ void mt7921_dma_cleanup(struct mt7921_dev *dev) mt76_dma_cleanup(&dev->mt76); } +EXPORT_SYMBOL_GPL(mt792x_dma_cleanup); + +int mt792x_poll_tx(struct napi_struct *napi, int budget) +{ + struct mt792x_dev *dev; + + dev = container_of(napi, struct mt792x_dev, mt76.tx_napi); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + + mt76_connac_tx_cleanup(&dev->mt76); + if (napi_complete(napi)) + mt76_connac_irq_enable(&dev->mt76, + dev->irq_map->tx.all_complete_mask); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_poll_tx); + +int mt792x_poll_rx(struct napi_struct *napi, int budget) +{ + struct mt792x_dev *dev; + int done; + + dev = container_of(napi->dev, struct mt792x_dev, mt76.napi_dev); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + done = mt76_dma_rx_poll(napi, budget); + mt76_connac_pm_unref(&dev->mphy, &dev->pm); + + return done; +} +EXPORT_SYMBOL_GPL(mt792x_poll_rx); + +int mt792x_wfsys_reset(struct mt792x_dev *dev) +{ + u32 addr = is_mt7921(&dev->mt76) ? 0x18000140 : 0x7c000140; + + mt76_clear(dev, addr, WFSYS_SW_RST_B); + msleep(50); + mt76_set(dev, addr, WFSYS_SW_RST_B); + + if (!__mt76_poll_msec(&dev->mt76, addr, WFSYS_SW_INIT_DONE, + WFSYS_SW_INIT_DONE, 500)) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792x_wfsys_reset); + diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_mac.c b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c new file mode 100644 index 000000000000..5d1f8229fdc1 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_mac.c @@ -0,0 +1,385 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. */ + +#include <linux/module.h> + +#include "mt792x.h" +#include "mt792x_regs.h" + +void mt792x_mac_work(struct work_struct *work) +{ + struct mt792x_phy *phy; + struct mt76_phy *mphy; + + mphy = (struct mt76_phy *)container_of(work, struct mt76_phy, + mac_work.work); + phy = mphy->priv; + + mt792x_mutex_acquire(phy->dev); + + mt76_update_survey(mphy); + if (++mphy->mac_work_count == 2) { + mphy->mac_work_count = 0; + + mt792x_mac_update_mib_stats(phy); + } + + mt792x_mutex_release(phy->dev); + + mt76_tx_status_check(mphy->dev, false); + ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work, + MT792x_WATCHDOG_TIME); +} +EXPORT_SYMBOL_GPL(mt792x_mac_work); + +void mt792x_mac_set_timeing(struct mt792x_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt792x_dev *dev = phy->dev; + u32 val, reg_offset; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); + bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; + int sifs = is_2ghz ? 10 : 16, offset; + + if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) + return; + + mt76_set(dev, MT_ARB_SCR(0), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + + mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset); + mt76_wr(dev, MT_TMAC_ICR0(0), + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20 || !is_2ghz) + val = MT792x_CFEND_RATE_DEFAULT; + else + val = MT792x_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val); + mt76_clear(dev, MT_ARB_SCR(0), + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); +} +EXPORT_SYMBOL_GPL(mt792x_mac_set_timeing); + +void mt792x_mac_update_mib_stats(struct mt792x_phy *phy) +{ + struct mt76_mib_stats *mib = &phy->mib; + struct mt792x_dev *dev = phy->dev; + int i, aggr0 = 0, aggr1; + u32 val; + + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0), + MT_MIB_SDR3_FCS_ERR_MASK); + mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0), + MT_MIB_ACK_FAIL_COUNT_MASK); + mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0), + MT_MIB_BA_FAIL_COUNT_MASK); + mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0), + MT_MIB_RTS_COUNT_MASK); + mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), + MT_MIB_RTS_FAIL_COUNT_MASK); + + mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0)); + mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0)); + mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0)); + + val = mt76_rr(dev, MT_MIB_SDR32(0)); + mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val); + mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val); + + val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0)); + mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val); + mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val); + + val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0)); + mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val); + mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val); + mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val); + mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val); + + mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0)); + mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0)); + mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0)); + mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0)); + + for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) { + val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i)); + mib->tx_amsdu[i] += val; + mib->tx_amsdu_cnt += val; + } + + for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { + u32 val2; + + val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); + val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); + + phy->mt76->aggr_stats[aggr0++] += val & 0xffff; + phy->mt76->aggr_stats[aggr0++] += val >> 16; + phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff; + phy->mt76->aggr_stats[aggr1++] += val2 >> 16; + } +} +EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats); + +struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx, + bool unicast) +{ + struct mt792x_sta *sta; + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + return NULL; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (unicast || !wcid) + return wcid; + + if (!wcid->sta) + return NULL; + + sta = container_of(wcid, struct mt792x_sta, wcid); + if (!sta->vif) + return NULL; + + return &sta->vif->sta.wcid; +} +EXPORT_SYMBOL_GPL(mt792x_rx_get_wcid); + +static void +mt792x_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct sk_buff *skb = priv; + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (status->signal > 0) + return; + + if (!ether_addr_equal(vif->addr, hdr->addr1)) + return; + + ewma_rssi_add(&mvif->rssi, -status->signal); +} + +void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb); + + if (!ieee80211_is_assoc_resp(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) + return; + + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt792x_mac_rssi_iter, skb); +} +EXPORT_SYMBOL_GPL(mt792x_mac_assoc_rssi); + +void mt792x_mac_reset_counters(struct mt792x_phy *phy) +{ + struct mt792x_dev *dev = phy->dev; + int i; + + for (i = 0; i < 4; i++) { + mt76_rr(dev, MT_TX_AGG_CNT(0, i)); + mt76_rr(dev, MT_TX_AGG_CNT2(0, i)); + } + + dev->mt76.phy.survey_time = ktime_get_boottime(); + memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats)); + + /* reset airtime counters */ + mt76_rr(dev, MT_MIB_SDR9(0)); + mt76_rr(dev, MT_MIB_SDR36(0)); + mt76_rr(dev, MT_MIB_SDR37(0)); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); +} +EXPORT_SYMBOL_GPL(mt792x_mac_reset_counters); + +static u8 +mt792x_phy_get_nf(struct mt792x_phy *phy, int idx) +{ + return 0; +} + +static void +mt792x_phy_update_channel(struct mt76_phy *mphy, int idx) +{ + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); + struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv; + struct mt76_channel_state *state; + u64 busy_time, tx_time, rx_time, obss_time; + int nf; + + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), + MT_MIB_SDR9_BUSY_MASK); + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), + MT_MIB_SDR36_TXTIME_MASK); + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), + MT_MIB_SDR37_RXTIME_MASK); + obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx), + MT_MIB_OBSSTIME_MASK); + + nf = mt792x_phy_get_nf(phy, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); + + state = mphy->chan_state; + state->cc_busy += busy_time; + state->cc_tx += tx_time; + state->cc_rx += rx_time + obss_time; + state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); +} + +void mt792x_update_channel(struct mt76_phy *mphy) +{ + struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76); + + if (mt76_connac_pm_wake(mphy, &dev->pm)) + return; + + mt792x_phy_update_channel(mphy, 0); + /* reset obss airtime */ + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR); + mt76_connac_power_save_sched(mphy, &dev->pm); +} +EXPORT_SYMBOL_GPL(mt792x_update_channel); + +void mt792x_reset(struct mt76_dev *mdev) +{ + struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76); + struct mt76_connac_pm *pm = &dev->pm; + + if (!dev->hw_init_done) + return; + + if (dev->hw_full_reset) + return; + + if (pm->suspended) + return; + + queue_work(dev->mt76.wq, &dev->reset_work); +} +EXPORT_SYMBOL_GPL(mt792x_reset); + +void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band) +{ + u32 mask, set; + + mt76_rmw_field(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); + mt76_set(dev, MT_TMAC_CTCR0(band), + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN); + + mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN); + + /* enable MIB tx-rx time reporting */ + mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN); + mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN); + + mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536); + /* disable rx rate report by default due to hw issues */ + mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN); + + /* filter out non-resp frames and get instantaneous signal reporting */ + mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM; + set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) | + FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3); + mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set); +} +EXPORT_SYMBOL_GPL(mt792x_mac_init_band); + +void mt792x_pm_wake_work(struct work_struct *work) +{ + struct mt792x_dev *dev; + struct mt76_phy *mphy; + + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, + pm.wake_work); + mphy = dev->phy.mt76; + + if (!mt792x_mcu_drv_pmctrl(dev)) { + struct mt76_dev *mdev = &dev->mt76; + int i; + + if (mt76_is_sdio(mdev)) { + mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); + mt76_worker_schedule(&mdev->sdio.txrx_worker); + } else { + local_bh_disable(); + mt76_for_each_q_rx(mdev, i) + napi_schedule(&mdev->napi[i]); + local_bh_enable(); + mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); + mt76_connac_tx_cleanup(mdev); + } + if (test_bit(MT76_STATE_RUNNING, &mphy->state)) + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT792x_WATCHDOG_TIME); + } + + ieee80211_wake_queues(mphy->hw); + wake_up(&dev->pm.wait); +} +EXPORT_SYMBOL_GPL(mt792x_pm_wake_work); + +void mt792x_pm_power_save_work(struct work_struct *work) +{ + struct mt792x_dev *dev; + unsigned long delta; + struct mt76_phy *mphy; + + dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev, + pm.ps_work.work); + mphy = dev->phy.mt76; + + delta = dev->pm.idle_timeout; + if (test_bit(MT76_HW_SCANNING, &mphy->state) || + test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) || + dev->fw_assert) + goto out; + + if (mutex_is_locked(&dev->mt76.mutex)) + /* if mt76 mutex is held we should not put the device + * to sleep since we are currently accessing device + * register map. We need to wait for the next power_save + * trigger. + */ + goto out; + + if (time_is_after_jiffies(dev->pm.last_activity + delta)) { + delta = dev->pm.last_activity + delta - jiffies; + goto out; + } + + if (!mt792x_mcu_fw_pmctrl(dev)) { + cancel_delayed_work_sync(&mphy->mac_work); + return; + } +out: + queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta); +} +EXPORT_SYMBOL_GPL(mt792x_pm_power_save_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h new file mode 100644 index 000000000000..a99af23e4b56 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h @@ -0,0 +1,479 @@ +/* SPDX-License-Identifier: ISC */ +/* Copyright (C) 2023 MediaTek Inc. */ + +#ifndef __MT792X_REGS_H +#define __MT792X_REGS_H + +/* MCU WFDMA1 */ +#define MT_MCU_WFDMA1_BASE 0x3000 +#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) + +#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108) +#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_DMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + +#define MT_PLE_BASE 0x820c0000 +#define MT_PLE(ofs) (MT_PLE_BASE + (ofs)) + +#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0) +#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4) +#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8) +#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec) + +#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n)) +#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2)) + +/* TMAC: band 0(0x21000), band 1(0xa1000) */ +#define MT_WF_TMAC_BASE(_band) ((_band) ? 0x820f4000 : 0x820e4000) +#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs)) + +#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0) +#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25) + +#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090) +#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + +#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4) +#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) +#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) +#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) + +#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c) +#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0) + +#define MT_WF_DMA_BASE(_band) ((_band) ? 0x820f7000 : 0x820e7000) +#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs)) + +#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000) +#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3) +#define MT_DMA_DCR0_RXD_G5_EN BIT(23) + +/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */ +#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000) +#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs)) + +#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008) +#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30) +#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24) + +/* LPON: band 0(0x24200), band 1(0xa4200) */ +#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000) +#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs)) + +#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080) +#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084) + +#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4) +#define MT_LPON_TCR_SW_MODE GENMASK(1, 0) +#define MT_LPON_TCR_SW_WRITE BIT(0) + +/* ETBF: band 0(0x24000), band 1(0xa4000) */ +#define MT_WF_ETBF_BASE(_band) ((_band) ? 0x820fa000 : 0x820ea000) +#define MT_WF_ETBF(_band, ofs) (MT_WF_ETBF_BASE(_band) + (ofs)) + +#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x150) +#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16) +#define MT_ETBF_TX_EBF_CNT GENMASK(15, 0) + +#define MT_ETBF_RX_FB_CNT(_band) MT_WF_ETBF(_band, 0x158) +#define MT_ETBF_RX_FB_ALL GENMASK(31, 24) +#define MT_ETBF_RX_FB_HE GENMASK(23, 16) +#define MT_ETBF_RX_FB_VHT GENMASK(15, 8) +#define MT_ETBF_RX_FB_HT GENMASK(7, 0) + +/* MIB: band 0(0x24800), band 1(0xa4800) */ +#define MT_WF_MIB_BASE(_band) ((_band) ? 0x820fd000 : 0x820ed000) +#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs)) + +#define MT_MIB_SCR1(_band) MT_WF_MIB(_band, 0x004) +#define MT_MIB_TXDUR_EN BIT(8) +#define MT_MIB_RXDUR_EN BIT(9) + +#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x698) +#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(31, 16) + +#define MT_MIB_SDR5(_band) MT_WF_MIB(_band, 0x780) + +#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c) +#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR12(_band) MT_WF_MIB(_band, 0x558) +#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x564) +#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x568) + +#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048) +#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0) + +#define MT_MIB_SDR22(_band) MT_WF_MIB(_band, 0x770) +#define MT_MIB_SDR23(_band) MT_WF_MIB(_band, 0x774) +#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, 0x55c) + +#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, 0x7a8) +#define MT_MIB_SDR9_IBF_CNT_MASK GENMASK(31, 16) +#define MT_MIB_SDR9_EBF_CNT_MASK GENMASK(15, 0) + +#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090) +#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0) + +#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x054) +#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0) +#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x058) +#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0) + +#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0) +#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4) +#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc) + +#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4)) +#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16) + +#define MT_MIB_MB_BSDR0(_band) MT_WF_MIB(_band, 0x688) +#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR1(_band) MT_WF_MIB(_band, 0x690) +#define MT_MIB_RTS_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR2(_band) MT_WF_MIB(_band, 0x518) +#define MT_MIB_BA_FAIL_COUNT_MASK GENMASK(15, 0) +#define MT_MIB_MB_BSDR3(_band) MT_WF_MIB(_band, 0x520) +#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(15, 0) + +#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4)) +#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0) + +#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x7dc + ((n) << 2)) +#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x7ec + ((n) << 2)) +#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2)) +#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0)) + +#define MT_WTBLON_TOP_BASE 0x820d4000 +#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) + +#define MT_WTBL_UPDATE_BUSY BIT(31) + +#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0) +#define MT_WTBL_ITCR_WR BIT(16) +#define MT_WTBL_ITCR_EXEC BIT(31) +#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8) +#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc) +#define MT_WTBL_SPE_IDX_SEL BIT(6) + +#define MT_WTBL_BASE 0x820d8000 +#define MT_WTBL_LMAC_ID GENMASK(14, 8) +#define MT_WTBL_LMAC_DW GENMASK(7, 2) +#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \ + FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \ + FIELD_PREP(MT_WTBL_LMAC_DW, _dw)) + +/* AGG: band 0(0x20800), band 1(0xa0800) */ +#define MT_WF_AGG_BASE(_band) ((_band) ? 0x820f2000 : 0x820e2000) +#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs)) + +#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4) +#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4) +#define MT_AGG_PCR0_MM_PROT BIT(0) +#define MT_AGG_PCR0_GF_PROT BIT(1) +#define MT_AGG_PCR0_BW20_PROT BIT(2) +#define MT_AGG_PCR0_BW40_PROT BIT(4) +#define MT_AGG_PCR0_BW80_PROT BIT(6) +#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8) +#define MT_AGG_PCR0_VHT_PROT BIT(13) +#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15) + +#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23) +#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0) + +#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084) +#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0) +#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16) + +#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098) +#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12) +#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6) +#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7) +#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24) + +#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0) +#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4) + +/* ARB: band 0(0x20c00), band 1(0xa0c00) */ +#define MT_WF_ARB_BASE(_band) ((_band) ? 0x820f3000 : 0x820e3000) +#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs)) + +#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080) +#define MT_ARB_SCR_TX_DISABLE BIT(8) +#define MT_ARB_SCR_RX_DISABLE BIT(9) + +#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4) + +/* RMAC: band 0(0x21400), band 1(0xa1400) */ +#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000) +#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs)) + +#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000) +#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) +#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) +#define MT_WF_RFCR_DROP_VERSION BIT(3) +#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) +#define MT_WF_RFCR_DROP_MCAST BIT(5) +#define MT_WF_RFCR_DROP_BCAST BIT(6) +#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) +#define MT_WF_RFCR_DROP_A3_MAC BIT(8) +#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) +#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) +#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) +#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) +#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) +#define MT_WF_RFCR_DROP_CTS BIT(14) +#define MT_WF_RFCR_DROP_RTS BIT(15) +#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) +#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) +#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) +#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) +#define MT_WF_RFCR_DROP_NDPA BIT(20) +#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) + +#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004) +#define MT_WF_RFCR1_DROP_ACK BIT(4) +#define MT_WF_RFCR1_DROP_BF_POLL BIT(5) +#define MT_WF_RFCR1_DROP_BA BIT(6) +#define MT_WF_RFCR1_DROP_CFEND BIT(7) +#define MT_WF_RFCR1_DROP_CFACK BIT(8) + +#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4) +#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) +#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) + +#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8) +#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) +#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380) + +/* WFDMA0 */ +#define MT_WFDMA0_BASE 0xd4000 +#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs)) + +#define MT_WFDMA0_RST MT_WFDMA0(0x100) +#define MT_WFDMA0_RST_LOGIC_RST BIT(4) +#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5) + +#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0) +#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1) +#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2) + +#define MT_MCU_CMD MT_WFDMA0(0x1f0) +#define MT_MCU_CMD_WAKE_RX_PCIE BIT(0) +#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_DMA BIT(2) +#define MT_MCU_CMD_RESET_DONE BIT(3) +#define MT_MCU_CMD_RECOVERY_DONE BIT(4) +#define MT_MCU_CMD_NORMAL_STATE BIT(5) +#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1) + +#define MT_MCU2HOST_SW_INT_ENA MT_WFDMA0(0x1f4) + +#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200) +#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */ +#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */ +#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */ +#define HOST_TX_DONE_INT_STS16 BIT(26) +#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/ + +#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208) +#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1) +#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6) +#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9) +#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) +#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21) +#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27) +#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28) +#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30) + +#define HOST_RX_DONE_INT_ENA0 BIT(0) +#define HOST_RX_DONE_INT_ENA1 BIT(1) +#define HOST_RX_DONE_INT_ENA2 BIT(2) +#define HOST_RX_DONE_INT_ENA3 BIT(3) +#define HOST_TX_DONE_INT_ENA0 BIT(4) +#define HOST_TX_DONE_INT_ENA1 BIT(5) +#define HOST_TX_DONE_INT_ENA2 BIT(6) +#define HOST_TX_DONE_INT_ENA3 BIT(7) +#define HOST_TX_DONE_INT_ENA4 BIT(8) +#define HOST_TX_DONE_INT_ENA5 BIT(9) +#define HOST_TX_DONE_INT_ENA6 BIT(10) +#define HOST_TX_DONE_INT_ENA7 BIT(11) +#define HOST_RX_COHERENT_EN BIT(20) +#define HOST_TX_COHERENT_EN BIT(21) +#define MCU2HOST_SW_INT_ENA BIT(29) +#define HOST_TX_DONE_INT_ENA18 BIT(30) + +#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA + +#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c) +#define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280) +#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0) +#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6) +#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0) + +#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600) +#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604) +#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608) +#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c) +#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610) +#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614) +#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618) +#define MT_WFDMA0_TX_RING15_EXT_CTRL MT_WFDMA0(0x63c) +#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640) +#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644) + +#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0) +#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16) + +#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680) +#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684) +#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688) +#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c) +#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690) +#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694) +#define MT_WFDMA0_RX_RING6_EXT_CTRL MT_WFDMA0(0x698) +#define MT_WFDMA0_RX_RING7_EXT_CTRL MT_WFDMA0(0x69c) + +#define MT_TX_RING_BASE MT_WFDMA0(0x300) +#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500) + +/* WFDMA CSR */ +#define MT_WFDMA_EXT_CSR_BASE 0xd7000 +#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs)) +#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44) +#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0) + +#define MT_SWDEF_BASE 0x41f200 +#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs)) +#define MT_SWDEF_MODE MT_SWDEF(0x3c) +#define MT_SWDEF_NORMAL_MODE 0 +#define MT_SWDEF_ICAP_MODE 1 +#define MT_SWDEF_SPECTRUM_MODE 2 + +#define MT_TOP_BASE 0x18060000 +#define MT_TOP(ofs) (MT_TOP_BASE + (ofs)) + +#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10) +#define MT_TOP_LPCR_HOST_FW_OWN BIT(0) +#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1) + +#define MT_TOP_MISC MT_TOP(0xf0) +#define MT_TOP_MISC_FW_STATE GENMASK(2, 0) + +#define MT_MCU_WPDMA0_BASE 0x54000000 +#define MT_MCU_WPDMA0(ofs) (MT_MCU_WPDMA0_BASE + (ofs)) + +#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120) +#define MT_WFDMA_NEED_REINIT BIT(1) + +#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs)) +#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600) +#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0) + +#define MT_HW_BOUND 0x70010020 +#define MT_HW_CHIPID 0x70010200 +#define MT_HW_REV 0x70010204 + +#define MT_PCIE_MAC_BASE 0x10000 +#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs)) +#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188) +#define MT_PCIE_MAC_PM MT_PCIE_MAC(0x194) +#define MT_PCIE_MAC_PM_L0S_DIS BIT(8) + +#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs)) +#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004) +#define MT_DMASHDL_DMASHDL_BYPASS BIT(28) +#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008) +#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c) +#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16) +#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010) +#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16) +#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c) +#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0) +#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16) + +#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2)) +#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) +#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) + +#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2)) +#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) +#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) + +#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2)) + +#define MT_WFDMA_HOST_CONFIG 0x7c027030 +#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6) + +#define MT_UMAC(ofs) (0x74000000 + (ofs)) +#define MT_UDMA_TX_QSEL MT_UMAC(0x008) +#define MT_FW_DL_EN BIT(3) + +#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c) +#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0) +#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8) + +#define MT_UDMA_WLCFG_0 MT_UMAC(0x18) +#define MT_WL_RX_AGG_TO GENMASK(7, 0) +#define MT_WL_RX_AGG_LMT GENMASK(15, 8) +#define MT_WL_TX_TMOUT_FUNC_EN BIT(16) +#define MT_WL_TX_DPH_CHK_EN BIT(17) +#define MT_WL_RX_MPSZ_PAD0 BIT(18) +#define MT_WL_RX_FLUSH BIT(19) +#define MT_TICK_1US_EN BIT(20) +#define MT_WL_RX_AGG_EN BIT(21) +#define MT_WL_RX_EN BIT(22) +#define MT_WL_TX_EN BIT(23) +#define MT_WL_RX_BUSY BIT(30) +#define MT_WL_TX_BUSY BIT(31) + +#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20) +#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22) +#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24) + +#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs)) +#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090) + +#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs)) +#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208) +#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0) +#define MT_UWFDMA0_GLO_CFG_EXT1 MT_UWFDMA0(0x2b4) +#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2)) + +#define MT_CONN_STATUS 0x7c053c10 +#define MT_WIFI_PATCH_DL_STATE BIT(0) + +#define MT_CONN_ON_LPCTL 0x7c060010 +#define PCIE_LPCR_HOST_SET_OWN BIT(0) +#define PCIE_LPCR_HOST_CLR_OWN BIT(1) +#define PCIE_LPCR_HOST_OWN_SYNC BIT(2) + +#define MT_CONN_ON_MISC 0x7c0600f0 +#define MT_TOP_MISC2_FW_PWR_ON BIT(0) +#define MT_TOP_MISC2_FW_N9_ON BIT(1) +#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0) + +#define MT_WF_SW_DEF_CR(ofs) (0x401a00 + (ofs)) +#define MT_WF_SW_DEF_CR_USB_MCU_EVENT MT_WF_SW_DEF_CR(0x028) +#define MT_WF_SW_SER_TRIGGER_SUSPEND BIT(6) +#define MT_WF_SW_SER_DONE_SUSPEND BIT(7) + +#define WFSYS_SW_RST_B BIT(0) +#define WFSYS_SW_INIT_DONE BIT(4) + +#endif /* __MT792X_REGS_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_trace.c b/drivers/net/wireless/mediatek/mt76/mt792x_trace.c new file mode 100644 index 000000000000..b6f284fb929d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_trace.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/module.h> + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt792x_trace.h" + +EXPORT_TRACEPOINT_SYMBOL_GPL(lp_event); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h b/drivers/net/wireless/mediatek/mt76/mt792x_trace.h index 9bc4db67f352..61f2aa260656 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921_trace.h +++ b/drivers/net/wireless/mediatek/mt76/mt792x_trace.h @@ -1,27 +1,27 @@ /* SPDX-License-Identifier: ISC */ /* - * Copyright (C) 2021 Lorenzo Bianconi <lorenzo@kernel.org> + * Copyright (C) 2023 Lorenzo Bianconi <lorenzo@kernel.org> */ -#if !defined(__MT7921_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -#define __MT7921_TRACE_H +#if !defined(__MT792X_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT792X_TRACE_H #include <linux/tracepoint.h> -#include "mt7921.h" +#include "mt792x.h" #undef TRACE_SYSTEM -#define TRACE_SYSTEM mt7921 +#define TRACE_SYSTEM mt792x #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name #define LP_STATE_PR_ARG __entry->lp_state ? "lp ready" : "lp not ready" TRACE_EVENT(lp_event, - TP_PROTO(struct mt7921_dev *dev, u8 lp_state), + TP_PROTO(struct mt792x_dev *dev, u8 lp_state), TP_ARGS(dev, lp_state), @@ -46,6 +46,6 @@ TRACE_EVENT(lp_event, #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . #undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE mt7921_trace +#define TRACE_INCLUDE_FILE mt792x_trace #include <trace/define_trace.h> diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_usb.c b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c new file mode 100644 index 000000000000..20e7f9c7c88c --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt792x_usb.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2023 MediaTek Inc. + * + * Author: Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> + +#include "mt792x.h" +#include "mt76_connac2_mac.h" + +u32 mt792xu_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} +EXPORT_SYMBOL_GPL(mt792xu_rr); + +void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} +EXPORT_SYMBOL_GPL(mt792xu_wr); + +u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, + USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask; + ___mt76u_wr(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return val; +} +EXPORT_SYMBOL_GPL(mt792xu_rmw); + +void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len) +{ + struct mt76_usb *usb = &dev->usb; + int ret, i = 0, batch_len; + const u8 *val = data; + + len = round_up(len, 4); + + mutex_lock(&usb->usb_ctrl_mtx); + while (i < len) { + batch_len = min_t(int, usb->data_len, len - i); + memcpy(usb->data, val + i, batch_len); + ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + (offset + i) >> 16, offset + i, + usb->data, batch_len); + if (ret < 0) + break; + + i += batch_len; + } + mutex_unlock(&usb->usb_ctrl_mtx); +} +EXPORT_SYMBOL_GPL(mt792xu_copy); + +int mt792xu_mcu_power_on(struct mt792x_dev *dev) +{ + int ret; + + ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON, + USB_DIR_OUT | MT_USB_TYPE_VENDOR, + 0x0, 0x1, NULL, 0); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, + MT_TOP_MISC2_FW_PWR_ON, 500)) { + dev_err(dev->mt76.dev, "Timeout for power on\n"); + ret = -EIO; + } + + return ret; +} +EXPORT_SYMBOL_GPL(mt792xu_mcu_power_on); + +static void mt792xu_cleanup(struct mt792x_dev *dev) +{ + clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state); + mt792xu_wfsys_reset(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); + mt76u_queues_deinit(&dev->mt76); +} + +static u32 mt792xu_uhw_rr(struct mt76_dev *dev, u32 addr) +{ + u32 ret; + + mutex_lock(&dev->usb.usb_ctrl_mtx); + ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE, + USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr); + mutex_unlock(&dev->usb.usb_ctrl_mtx); + + return ret; +} + +static void mt792xu_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val) +{ + mutex_lock(&dev->usb.usb_ctrl_mtx); + ___mt76u_wr(dev, MT_VEND_WRITE, + USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val); + mutex_unlock(&dev->usb.usb_ctrl_mtx); +} + +static void mt792xu_dma_prefetch(struct mt792x_dev *dev) +{ + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0), + MT_WPDMA0_BASE_PTR_MASK, 0x80); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1), + MT_WPDMA0_BASE_PTR_MASK, 0xc0); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2), + MT_WPDMA0_BASE_PTR_MASK, 0x100); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3), + MT_WPDMA0_BASE_PTR_MASK, 0x140); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4), + MT_WPDMA0_BASE_PTR_MASK, 0x180); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16), + MT_WPDMA0_BASE_PTR_MASK, 0x280); + + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_MAX_CNT_MASK, 4); + mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17), + MT_WPDMA0_BASE_PTR_MASK, 0x2c0); +} + +static void mt792xu_wfdma_init(struct mt792x_dev *dev) +{ + mt792xu_dma_prefetch(dev); + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 | + MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL | + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + /* disable dmashdl */ + mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0, + MT_WFDMA0_CSR_TX_DMASHDL_ENABLE); + mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS); + + mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT); +} + +static int mt792xu_dma_rx_evt_ep4(struct mt792x_dev *dev) +{ + if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000)) + return -ETIMEDOUT; + + mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + mt76_set(dev, MT_WFDMA_HOST_CONFIG, + MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN); + mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN); + + return 0; +} + +static void mt792xu_epctl_rst_opt(struct mt792x_dev *dev, bool reset) +{ + u32 val; + + /* usb endpoint reset opt + * bits[4,9]: out blk ep 4-9 + * bits[20,21]: in blk ep 4-5 + * bits[22]: in int ep 6 + */ + val = mt792xu_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT); + if (reset) + val |= GENMASK(9, 4) | GENMASK(22, 20); + else + val &= ~(GENMASK(9, 4) | GENMASK(22, 20)); + mt792xu_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val); +} + +int mt792xu_dma_init(struct mt792x_dev *dev, bool resume) +{ + int err; + + mt792xu_wfdma_init(dev); + + mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH); + + mt76_set(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_EN | MT_WL_TX_EN | + MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN); + mt76_clear(dev, MT_UDMA_WLCFG_0, + MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT); + mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT); + + if (resume) + return 0; + + err = mt792xu_dma_rx_evt_ep4(dev); + if (err) + return err; + + mt792xu_epctl_rst_opt(dev, false); + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xu_dma_init); + +int mt792xu_wfsys_reset(struct mt792x_dev *dev) +{ + u32 val; + int i; + + mt792xu_epctl_rst_opt(dev, false); + + val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + usleep_range(10, 20); + + val = mt792xu_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST); + val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH; + mt792xu_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val); + + mt792xu_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0); + for (i = 0; i < MT792x_WFSYS_INIT_RETRY_COUNT; i++) { + val = mt792xu_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS); + if (val & MT_UDMA_CONN_WFSYS_INIT_DONE) + break; + + msleep(100); + } + + if (i == MT792x_WFSYS_INIT_RETRY_COUNT) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL_GPL(mt792xu_wfsys_reset); + +int mt792xu_init_reset(struct mt792x_dev *dev) +{ + set_bit(MT76_RESET, &dev->mphy.state); + + wake_up(&dev->mt76.mcu.wait); + skb_queue_purge(&dev->mt76.mcu.res_q); + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); + + mt792xu_wfsys_reset(dev); + + clear_bit(MT76_RESET, &dev->mphy.state); + + return mt76u_resume_rx(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792xu_init_reset); + +void mt792xu_disconnect(struct usb_interface *usb_intf) +{ + struct mt792x_dev *dev = usb_get_intfdata(usb_intf); + + cancel_work_sync(&dev->init_work); + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return; + + mt76_unregister_device(&dev->mt76); + mt792xu_cleanup(dev); + + usb_set_intfdata(usb_intf, NULL); + usb_put_dev(interface_to_usbdev(usb_intf)); + + mt76_free_device(&dev->mt76); +} +EXPORT_SYMBOL_GPL(mt792xu_disconnect); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c index 513ab4ba41c9..4d40ec7ff57f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c @@ -474,10 +474,10 @@ mt7996_ampdu_stat_read_phy(struct mt7996_phy *phy, struct seq_file *file) static void mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s) { + struct mt76_mib_stats *mib = &phy->mib; static const char * const bw[] = { "BW20", "BW40", "BW80", "BW160" }; - struct mib_stats *mib = &phy->mib; /* Tx Beamformer monitor */ seq_puts(s, "\nTx Beamformer applied PPDU counts: "); @@ -523,7 +523,7 @@ mt7996_tx_stats_show(struct seq_file *file, void *data) { struct mt7996_phy *phy = file->private; struct mt7996_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; int i; u32 attempts, success, per; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c index 534143465d9b..586e247a1e06 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c @@ -128,7 +128,7 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset) } } -static int mt7996_dma_enable(struct mt7996_dev *dev) +void mt7996_dma_start(struct mt7996_dev *dev, bool reset) { u32 hif1_ofs = 0; u32 irq_mask; @@ -136,6 +136,50 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) if (dev->hif2) hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + /* enable WFDMA Tx/Rx */ + if (!reset) { + mt76_set(dev, MT_WFDMA0_GLO_CFG, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + + if (dev->hif2) + mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, + MT_WFDMA0_GLO_CFG_TX_DMA_EN | + MT_WFDMA0_GLO_CFG_RX_DMA_EN | + MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | + MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); + } + + /* enable interrupts for TX/RX rings */ + irq_mask = MT_INT_MCU_CMD; + if (reset) + goto done; + + irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU; + + if (!dev->mphy.band_idx) + irq_mask |= MT_INT_BAND0_RX_DONE; + + if (dev->dbdc_support) + irq_mask |= MT_INT_BAND1_RX_DONE; + + if (dev->tbtc_support) + irq_mask |= MT_INT_BAND2_RX_DONE; + +done: + mt7996_irq_enable(dev, irq_mask); + mt7996_irq_disable(dev, 0); +} + +static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset) +{ + u32 hif1_ofs = 0; + + if (dev->hif2) + hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0); + /* reset dma idx */ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0); if (dev->hif2) @@ -170,13 +214,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) mt76_poll(dev, MT_WFDMA_EXT_CSR_HIF_MISC, MT_WFDMA_EXT_CSR_HIF_MISC_BUSY, 0, 1000); - /* set WFDMA Tx/Rx */ - mt76_set(dev, MT_WFDMA0_GLO_CFG, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - /* GLO_CFG_EXT0 */ mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0, WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD | @@ -187,12 +224,6 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE); if (dev->hif2) { - mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs, - MT_WFDMA0_GLO_CFG_TX_DMA_EN | - MT_WFDMA0_GLO_CFG_RX_DMA_EN | - MT_WFDMA0_GLO_CFG_OMIT_TX_INFO | - MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2); - /* GLO_CFG_EXT0 */ mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs, WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD | @@ -216,23 +247,7 @@ static int mt7996_dma_enable(struct mt7996_dev *dev) /* TODO: redirect rx ring6 interrupt to pcie0 for wed function */ } - /* enable interrupts for TX/RX rings */ - irq_mask = MT_INT_RX_DONE_MCU | - MT_INT_TX_DONE_MCU | - MT_INT_MCU_CMD; - - if (!dev->mphy.band_idx) - irq_mask |= MT_INT_BAND0_RX_DONE; - - if (dev->dbdc_support) - irq_mask |= MT_INT_BAND1_RX_DONE; - - if (dev->tbtc_support) - irq_mask |= MT_INT_BAND2_RX_DONE; - - mt7996_irq_enable(dev, irq_mask); - - return 0; + mt7996_dma_start(dev, reset); } int mt7996_dma_init(struct mt7996_dev *dev) @@ -293,7 +308,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) /* event from WA */ ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA], MT_RXQ_ID(MT_RXQ_MCU_WA), - MT7996_RX_MCU_RING_SIZE, + MT7996_RX_MCU_RING_SIZE_WA, MT_RX_BUF_SIZE, MT_RXQ_RING_BASE(MT_RXQ_MCU_WA)); if (ret) @@ -347,7 +362,7 @@ int mt7996_dma_init(struct mt7996_dev *dev) mt7996_poll_tx); napi_enable(&dev->mt76.tx_napi); - mt7996_dma_enable(dev); + mt7996_dma_enable(dev, false); return 0; } @@ -413,7 +428,7 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force) mt76_for_each_q_rx(&dev->mt76, i) mt76_queue_rx_reset(dev, i); - mt7996_dma_enable(dev); + mt7996_dma_enable(dev, !force); } void mt7996_dma_cleanup(struct mt7996_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c index f1b48cdda58f..26e03b28935f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c @@ -4,6 +4,7 @@ */ #include <linux/etherdevice.h> +#include <linux/of.h> #include <linux/thermal.h> #include "mt7996.h" #include "mac.h" @@ -183,6 +184,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_DISCOVERY); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0); + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); if (!mdev->dev->of_node || !of_property_read_bool(mdev->dev->of_node, @@ -217,6 +219,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw) IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; phy->mt76->sband_5g.sband.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_1; + + ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); } mt76_set_stream_caps(phy->mt76, true); @@ -853,9 +857,7 @@ int mt7996_register_device(struct mt7996_dev *dev) INIT_WORK(&dev->rc_work, mt7996_mac_sta_rc_work); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7996_mac_work); INIT_LIST_HEAD(&dev->sta_rc_list); - INIT_LIST_HEAD(&dev->sta_poll_list); INIT_LIST_HEAD(&dev->twt_list); - spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); INIT_WORK(&dev->reset_work, mt7996_mac_reset_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 9b0f6053e0fa..ac8759febe48 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -13,10 +13,6 @@ #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2) -#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) -#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ - IEEE80211_RADIOTAP_HE_##f) - static const struct mt7996_dfs_radar_spec etsi_radar_specs = { .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 }, .radar_pattern = { @@ -111,9 +107,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) LIST_HEAD(sta_poll_list); int i; - spin_lock_bh(&dev->sta_poll_lock); - list_splice_init(&dev->sta_poll_list, &sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); rcu_read_lock(); @@ -124,15 +120,15 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev) s8 rssi[4]; u8 bw; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); if (list_empty(&sta_poll_list)) { - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); break; } msta = list_first_entry(&sta_poll_list, - struct mt7996_sta, poll_list); - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + struct mt7996_sta, wcid.poll_list); + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); idx = msta->wcid.idx; @@ -263,180 +259,6 @@ void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev, mt76_wr(dev, MT_WTBL_ITCR, ctrl); } -static void -mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, - struct ieee80211_radiotap_he *he, - __le32 *rxv) -{ - u32 ru, offs = 0; - - ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC); - - status->bw = RATE_INFO_BW_HE_RU; - - switch (ru) { - case 0 ... 36: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; - offs = ru; - break; - case 37 ... 52: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; - offs = ru - 37; - break; - case 53 ... 60: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; - offs = ru - 53; - break; - case 61 ... 64: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; - offs = ru - 61; - break; - case 65 ... 66: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; - offs = ru - 65; - break; - case 67: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; - break; - case 68: - status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; - break; - } - - he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | - le16_encode_bits(offs, - IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); -} - -static void -mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - static const struct ieee80211_radiotap_he_mu mu_known = { - .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | - HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | - HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), - .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), - }; - struct ieee80211_radiotap_he_mu *he_mu = NULL; - - status->flag |= RX_FLAG_RADIOTAP_HE_MU; - - he_mu = skb_push(skb, sizeof(mu_known)); - memcpy(he_mu, &mu_known, sizeof(mu_known)); - -#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) - - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); - if (status->he_dcm) - he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); - - he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | - MU_PREP(FLAGS2_SIG_B_SYMS_USERS, - le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); - - he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; - - if (status->bw >= RATE_INFO_BW_40) { - he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); - he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; - } - - if (status->bw >= RATE_INFO_BW_80) { - u32 ru_h, ru_l; - - he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; - - ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); - ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; - he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); - } -} - -static void -mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode) -{ - struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; - static const struct ieee80211_radiotap_he known = { - .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | - HE_BITS(DATA1_DATA_DCM_KNOWN) | - HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN) | - HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN), - .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN) | - HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN), - }; - struct ieee80211_radiotap_he *he = NULL; - u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; - - status->flag |= RX_FLAG_RADIOTAP_HE; - - he = skb_push(skb, sizeof(known)); - memcpy(he, &known, sizeof(known)); - - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | - HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); - he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); - he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | - le16_encode_bits(ltf_size, - IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); - if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) - he->data5 |= HE_BITS(DATA5_TXBF); - he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | - HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); - - switch (mode) { - case MT_PHY_TYPE_HE_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | - HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - - he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | - HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - break; - case MT_PHY_TYPE_HE_EXT_SU: - he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | - HE_BITS(DATA1_UL_DL_KNOWN) | - HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - break; - case MT_PHY_TYPE_HE_MU: - he->data1 |= HE_BITS(DATA1_FORMAT_MU) | - HE_BITS(DATA1_UL_DL_KNOWN); - - he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); - he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); - - mt7996_mac_decode_he_radiotap_ru(status, he, rxv); - mt7996_mac_decode_he_mu_radiotap(skb, rxv); - break; - case MT_PHY_TYPE_HE_TB: - he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | - HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | - HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - - he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); - - mt7996_mac_decode_he_radiotap_ru(status, he, rxv); - break; - default: - break; - } -} - /* The HW does not translate the mac header to 802.3 for mesh point */ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap) { @@ -681,10 +503,11 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) struct mt7996_sta *msta; msta = container_of(status->wcid, struct mt7996_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } status->freq = mphy->chandef.chan->center_freq; @@ -836,14 +659,19 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) skb_pull(skb, hdr_gap); if (!hdr_trans && status->amsdu && !(ieee80211_has_a4(fc) && is_mesh)) { pad_start = ieee80211_get_hdrlen_from_skb(skb); - } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR) && - get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) { + } else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) { /* When header translation failure is indicated, * the hardware will insert an extra 2-byte field * containing the data length after the protocol - * type field. + * type field. This happens either when the LLC-SNAP + * pattern did not match, or if a VLAN header was + * detected. */ - pad_start = 16; + pad_start = 12; + if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q) + pad_start += 4; + else + pad_start = 0; } if (pad_start) { @@ -881,7 +709,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb) } if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023)) - mt7996_mac_decode_he_radiotap(skb, rxv, mode); + mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode); if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; @@ -1007,7 +835,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; - struct mt7996_vif *mvif; + struct mt76_vif *mvif; u16 tx_count = 15; u32 val; bool beacon = !!(changed & (BSS_CHANGED_BEACON | @@ -1015,11 +843,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); - mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; if (mvif) { - omac_idx = mvif->mt76.omac_idx; - wmm_idx = mvif->mt76.wmm_idx; - band_idx = mvif->mt76.band_idx; + omac_idx = mvif->omac_idx; + wmm_idx = mvif->wmm_idx; + band_idx = mvif->band_idx; } if (inband_disc) { @@ -1198,7 +1026,7 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi) return; msta = (struct mt7996_sta *)sta->drv_priv; - if (!test_and_set_bit(tid, &msta->ampdu_state)) + if (!test_and_set_bit(tid, &msta->wcid.ampdu_state)) ieee80211_start_tx_ba_session(sta, tid, 0); } @@ -1286,10 +1114,11 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) continue; msta = container_of(wcid, struct mt7996_sta, wcid); - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&mdev->sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, + &mdev->sta_poll_list); + spin_unlock_bh(&mdev->sta_poll_lock); continue; } @@ -1324,9 +1153,10 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len) } static bool -mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid, - __le32 *txs_data, struct mt76_sta_stats *stats) +mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, + int pid, __le32 *txs_data) { + struct mt76_sta_stats *stats = &wcid->stats; struct ieee80211_supported_band *sband; struct mt76_dev *mdev = &dev->mt76; struct mt76_phy *mphy; @@ -1488,15 +1318,15 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data) msta = container_of(wcid, struct mt7996_sta, wcid); - mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data, &msta->stats); + mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data); if (!wcid->sta) goto out; - spin_lock_bh(&dev->sta_poll_lock); - if (list_empty(&msta->poll_list)) - list_add_tail(&msta->poll_list, &dev->sta_poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (list_empty(&msta->wcid.poll_list)) + list_add_tail(&msta->wcid.poll_list, &dev->mt76.sta_poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); out: rcu_read_unlock(); @@ -1609,20 +1439,19 @@ void mt7996_mac_reset_counters(struct mt7996_phy *phy) mt7996_mcu_get_chan_mib_info(phy, true); } -void mt7996_mac_set_timing(struct mt7996_phy *phy) +void mt7996_mac_set_coverage_class(struct mt7996_phy *phy) { s16 coverage_class = phy->coverage_class; struct mt7996_dev *dev = phy->dev; struct mt7996_phy *phy2 = mt7996_phy2(dev); struct mt7996_phy *phy3 = mt7996_phy3(dev); - u32 val, reg_offset; + u32 reg_offset; u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28); u8 band_idx = phy->mt76->band_idx; int offset; - bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ); if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; @@ -1635,34 +1464,12 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy) coverage_class = max_t(s16, coverage_class, phy3->coverage_class); - mt76_set(dev, MT_ARB_SCR(band_idx), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); - udelay(1); - offset = 3 * coverage_class; reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); mt76_wr(dev, MT_TMAC_CDTR(band_idx), cck + reg_offset); mt76_wr(dev, MT_TMAC_ODTR(band_idx), ofdm + reg_offset); - mt76_wr(dev, MT_TMAC_ICR0(band_idx), - FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) | - FIELD_PREP(MT_IFS_RIFS, 2) | - FIELD_PREP(MT_IFS_SIFS, 10) | - FIELD_PREP(MT_IFS_SLOT, phy->slottime)); - - if (!a_band) - mt76_wr(dev, MT_TMAC_ICR1(band_idx), - FIELD_PREP(MT_IFS_EIFS_CCK, 314)); - - if (phy->slottime < 20 || a_band) - val = MT7996_CFEND_RATE_DEFAULT; - else - val = MT7996_CFEND_RATE_11B; - - mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val); - mt76_clear(dev, MT_ARB_SCR(band_idx), - MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); } void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band) @@ -2046,6 +1853,12 @@ void mt7996_mac_reset_work(struct work_struct *work) mt7996_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); } + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + /* enable DMA Tx/Tx and interrupt */ + mt7996_dma_start(dev, false); + clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); if (phy2) @@ -2062,9 +1875,6 @@ void mt7996_mac_reset_work(struct work_struct *work) tasklet_schedule(&dev->mt76.irq_tasklet); - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - mt76_worker_enable(&dev->mt76.tx_worker); local_bh_disable(); @@ -2191,8 +2001,8 @@ void mt7996_reset(struct mt7996_dev *dev) void mt7996_mac_update_stats(struct mt7996_phy *phy) { + struct mt76_mib_stats *mib = &phy->mib; struct mt7996_dev *dev = phy->dev; - struct mib_stats *mib = &phy->mib; u8 band_idx = phy->mt76->band_idx; u32 cnt; int i; @@ -2339,7 +2149,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) u32 changed; LIST_HEAD(list); - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); list_splice_init(&dev->sta_rc_list, &list); while (!list_empty(&list)) { @@ -2347,7 +2157,7 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) list_del_init(&msta->rc_list); changed = msta->changed; msta->changed = 0; - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); sta = container_of((void *)msta, struct ieee80211_sta, drv_priv); vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv); @@ -2359,10 +2169,10 @@ void mt7996_mac_sta_rc_work(struct work_struct *work) /* TODO: smps change */ - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); } - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } void mt7996_mac_work(struct work_struct *work) diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h index bc4e6c55373e..e629324a5617 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.h @@ -6,320 +6,7 @@ #ifndef __MT7996_MAC_H #define __MT7996_MAC_H -#define MT_CT_PARSE_LEN 72 -#define MT_CT_DMA_BUF_NUM 2 - -#define MT_RXD0_LENGTH GENMASK(15, 0) -#define MT_RXD0_PKT_TYPE GENMASK(31, 27) - -#define MT_RXD0_MESH BIT(18) -#define MT_RXD0_MHCP BIT(19) -#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) -#define MT_RXD0_NORMAL_IP_SUM BIT(23) -#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) - -#define MT_RXD0_SW_PKT_TYPE_MASK GENMASK(31, 16) -#define MT_RXD0_SW_PKT_TYPE_MAP 0x380F -#define MT_RXD0_SW_PKT_TYPE_FRAME 0x3801 - -/* RXD DW1 */ -#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(11, 0) -#define MT_RXD1_NORMAL_GROUP_1 BIT(16) -#define MT_RXD1_NORMAL_GROUP_2 BIT(17) -#define MT_RXD1_NORMAL_GROUP_3 BIT(18) -#define MT_RXD1_NORMAL_GROUP_4 BIT(19) -#define MT_RXD1_NORMAL_GROUP_5 BIT(20) -#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21) -#define MT_RXD1_NORMAL_CM BIT(23) -#define MT_RXD1_NORMAL_CLM BIT(24) -#define MT_RXD1_NORMAL_ICV_ERR BIT(25) -#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26) -#define MT_RXD1_NORMAL_BAND_IDX GENMASK(28, 27) -#define MT_RXD1_NORMAL_SPP_EN BIT(29) -#define MT_RXD1_NORMAL_ADD_OM BIT(30) -#define MT_RXD1_NORMAL_SEC_DONE BIT(31) - -/* RXD DW2 */ -#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0) -#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8) -#define MT_RXD2_NORMAL_HDR_TRANS BIT(7) -#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 13) -#define MT_RXD2_NORMAL_SEC_MODE GENMASK(20, 16) -#define MT_RXD2_NORMAL_MU_BAR BIT(21) -#define MT_RXD2_NORMAL_SW_BIT BIT(22) -#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) -#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) -#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25) -#define MT_RXD2_NORMAL_INT_FRAME BIT(26) -#define MT_RXD2_NORMAL_FRAG BIT(27) -#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) -#define MT_RXD2_NORMAL_NDATA BIT(29) -#define MT_RXD2_NORMAL_NON_AMPDU BIT(30) -#define MT_RXD2_NORMAL_BF_REPORT BIT(31) - -/* RXD DW3 */ -#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) -#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8) -#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16) -#define MT_RXD3_NORMAL_U2M BIT(0) -#define MT_RXD3_NORMAL_HTC_VLD BIT(18) -#define MT_RXD3_NORMAL_BEACON_MC BIT(20) -#define MT_RXD3_NORMAL_BEACON_UC BIT(21) -#define MT_RXD3_NORMAL_CO_ANT BIT(22) -#define MT_RXD3_NORMAL_FCS_ERR BIT(24) -#define MT_RXD3_NORMAL_VLAN2ETH BIT(31) - -/* RXD DW4 */ -#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0) -#define MT_RXD4_FIRST_AMSDU_FRAME GENMASK(1, 0) -#define MT_RXD4_MID_AMSDU_FRAME BIT(1) -#define MT_RXD4_LAST_AMSDU_FRAME BIT(0) - -#define MT_RXV_HDR_BAND_IDX BIT(24) - -/* RXD GROUP4 */ -#define MT_RXD8_FRAME_CONTROL GENMASK(15, 0) - -#define MT_RXD10_SEQ_CTRL GENMASK(15, 0) -#define MT_RXD10_QOS_CTL GENMASK(31, 16) - -#define MT_RXD11_HT_CONTROL GENMASK(31, 0) - -/* P-RXV */ -#define MT_PRXV_TX_RATE GENMASK(6, 0) -#define MT_PRXV_TX_DCM BIT(4) -#define MT_PRXV_TX_ER_SU_106T BIT(5) -#define MT_PRXV_NSTS GENMASK(10, 7) -#define MT_PRXV_TXBF BIT(11) -#define MT_PRXV_HT_AD_CODE BIT(12) -#define MT_PRXV_HE_RU_ALLOC GENMASK(30, 22) -#define MT_PRXV_RCPI3 GENMASK(31, 24) -#define MT_PRXV_RCPI2 GENMASK(23, 16) -#define MT_PRXV_RCPI1 GENMASK(15, 8) -#define MT_PRXV_RCPI0 GENMASK(7, 0) -#define MT_PRXV_HT_SHORT_GI GENMASK(4, 3) -#define MT_PRXV_HT_STBC GENMASK(10, 9) -#define MT_PRXV_TX_MODE GENMASK(14, 11) -#define MT_PRXV_FRAME_MODE GENMASK(2, 0) -#define MT_PRXV_DCM BIT(5) - -/* C-RXV */ -#define MT_CRXV_HE_NUM_USER GENMASK(26, 20) -#define MT_CRXV_HE_LTF_SIZE GENMASK(28, 27) -#define MT_CRXV_HE_LDPC_EXT_SYM BIT(30) - -#define MT_CRXV_HE_PE_DISAMBIG BIT(1) -#define MT_CRXV_HE_UPLINK BIT(2) - -#define MT_CRXV_HE_MU_AID GENMASK(27, 17) -#define MT_CRXV_HE_BEAM_CHNG BIT(29) - -#define MT_CRXV_HE_DOPPLER BIT(0) -#define MT_CRXV_HE_BSS_COLOR GENMASK(15, 10) -#define MT_CRXV_HE_TXOP_DUR GENMASK(19, 17) - -#define MT_CRXV_HE_SR_MASK GENMASK(11, 8) -#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12) -#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17) -#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21) - -#define MT_CRXV_HE_RU0 GENMASK(8, 0) -#define MT_CRXV_HE_RU1 GENMASK(17, 9) -#define MT_CRXV_HE_RU2 GENMASK(26, 18) -#define MT_CRXV_HE_RU3_L GENMASK(31, 27) -#define MT_CRXV_HE_RU3_H GENMASK(3, 0) - -enum tx_header_format { - MT_HDR_FORMAT_802_3, - MT_HDR_FORMAT_CMD, - MT_HDR_FORMAT_802_11, - MT_HDR_FORMAT_802_11_EXT, -}; - -enum tx_pkt_type { - MT_TX_TYPE_CT, - MT_TX_TYPE_SF, - MT_TX_TYPE_CMD, - MT_TX_TYPE_FW, -}; - -enum tx_port_idx { - MT_TX_PORT_IDX_LMAC, - MT_TX_PORT_IDX_MCU -}; - -enum tx_mcu_port_q_idx { - MT_TX_MCU_PORT_RX_Q0 = 0x20, - MT_TX_MCU_PORT_RX_Q1, - MT_TX_MCU_PORT_RX_Q2, - MT_TX_MCU_PORT_RX_Q3, - MT_TX_MCU_PORT_RX_FWDL = 0x3e -}; - -enum tx_mgnt_type { - MT_TX_NORMAL, - MT_TX_TIMING, - MT_TX_ADDBA, -}; - -#define MT_CT_INFO_APPLY_TXD BIT(0) -#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1) -#define MT_CT_INFO_MGMT_FRAME BIT(2) -#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3) -#define MT_CT_INFO_HSR2_TX BIT(4) -#define MT_CT_INFO_FROM_HOST BIT(7) - -#define MT_TXD_SIZE (8 * 4) - -#define MT_TXD0_Q_IDX GENMASK(31, 25) -#define MT_TXD0_PKT_FMT GENMASK(24, 23) -#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) -#define MT_TXD0_TX_BYTES GENMASK(15, 0) - -#define MT_TXD1_FIXED_RATE BIT(31) -#define MT_TXD1_OWN_MAC GENMASK(30, 25) -#define MT_TXD1_TID GENMASK(24, 21) -#define MT_TXD1_BIP BIT(24) -#define MT_TXD1_ETH_802_3 BIT(20) -#define MT_TXD1_HDR_INFO GENMASK(20, 16) -#define MT_TXD1_HDR_FORMAT GENMASK(15, 14) -#define MT_TXD1_TGID GENMASK(13, 12) -#define MT_TXD1_WLAN_IDX GENMASK(11, 0) - -#define MT_TXD2_POWER_OFFSET GENMASK(31, 26) -#define MT_TXD2_MAX_TX_TIME GENMASK(25, 16) -#define MT_TXD2_FRAG GENMASK(15, 14) -#define MT_TXD2_HTC_VLD BIT(13) -#define MT_TXD2_DURATION BIT(12) -#define MT_TXD2_HDR_PAD GENMASK(11, 10) -#define MT_TXD2_RTS BIT(9) -#define MT_TXD2_OWN_MAC_MAP BIT(8) -#define MT_TXD2_BF_TYPE GENMASK(6, 7) -#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) -#define MT_TXD2_SUB_TYPE GENMASK(3, 0) - -#define MT_TXD3_SN_VALID BIT(31) -#define MT_TXD3_PN_VALID BIT(30) -#define MT_TXD3_SW_POWER_MGMT BIT(29) -#define MT_TXD3_BA_DISABLE BIT(28) -#define MT_TXD3_SEQ GENMASK(27, 16) -#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) -#define MT_TXD3_TX_COUNT GENMASK(10, 6) -#define MT_TXD3_HW_AMSDU BIT(5) -#define MT_TXD3_BCM BIT(4) -#define MT_TXD3_EEOSP BIT(3) -#define MT_TXD3_EMRD BIT(2) -#define MT_TXD3_PROTECT_FRAME BIT(1) -#define MT_TXD3_NO_ACK BIT(0) - -#define MT_TXD4_PN_LOW GENMASK(31, 0) - -#define MT_TXD5_PN_HIGH GENMASK(31, 16) -#define MT_TXD5_FL BIT(15) -#define MT_TXD5_BYPASS_TBB BIT(14) -#define MT_TXD5_BYPASS_RBB BIT(13) -#define MT_TXD5_BSS_COLOR_ZERO BIT(12) -#define MT_TXD5_TX_STATUS_HOST BIT(10) -#define MT_TXD5_TX_STATUS_MCU BIT(9) -#define MT_TXD5_TX_STATUS_FMT BIT(8) -#define MT_TXD5_PID GENMASK(7, 0) - -#define MT_TXD6_TX_SRC GENMASK(31, 30) -#define MT_TXD6_VTA BIT(28) -#define MT_TXD6_BW GENMASK(25, 22) -#define MT_TXD6_TX_RATE GENMASK(21, 16) -#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15) -#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10) -#define MT_TXD6_MSDU_CNT GENMASK(9, 4) -#define MT_TXD6_DIS_MAT BIT(3) -#define MT_TXD6_DAS BIT(2) -#define MT_TXD6_AMSDU_CAP BIT(1) - -#define MT_TXD7_TXD_LEN GENMASK(31, 30) -#define MT_TXD7_IP_SUM BIT(29) -#define MT_TXD7_DROP_BY_SDO BIT(28) -#define MT_TXD7_MAC_TXD BIT(27) -#define MT_TXD7_CTXD BIT(26) -#define MT_TXD7_CTXD_CNT GENMASK(25, 22) -#define MT_TXD7_UDP_TCP_SUM BIT(15) -#define MT_TXD7_TX_TIME GENMASK(9, 0) - -#define MT_TX_RATE_STBC BIT(14) -#define MT_TX_RATE_NSS GENMASK(13, 10) -#define MT_TX_RATE_MODE GENMASK(9, 6) -#define MT_TX_RATE_SU_EXT_TONE BIT(5) -#define MT_TX_RATE_DCM BIT(4) -/* VHT/HE only use bits 0-3 */ -#define MT_TX_RATE_IDX GENMASK(5, 0) - -#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27) -#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16) -#define MT_TXFREE0_RX_BYTE GENMASK(15, 0) - -#define MT_TXFREE1_VER GENMASK(18, 16) - -#define MT_TXFREE_INFO_PAIR BIT(31) -#define MT_TXFREE_INFO_HEADER BIT(30) -#define MT_TXFREE_INFO_WLAN_ID GENMASK(23, 12) -#define MT_TXFREE_INFO_MSDU_ID GENMASK(14, 0) - -#define MT_TXS0_BW GENMASK(31, 29) -#define MT_TXS0_TID GENMASK(28, 26) -#define MT_TXS0_AMPDU BIT(25) -#define MT_TXS0_TXS_FORMAT GENMASK(24, 23) -#define MT_TXS0_BA_ERROR BIT(22) -#define MT_TXS0_PS_FLAG BIT(21) -#define MT_TXS0_TXOP_TIMEOUT BIT(20) -#define MT_TXS0_BIP_ERROR BIT(19) - -#define MT_TXS0_QUEUE_TIMEOUT BIT(18) -#define MT_TXS0_RTS_TIMEOUT BIT(17) -#define MT_TXS0_ACK_TIMEOUT BIT(16) -#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) - -#define MT_TXS0_TX_STATUS_HOST BIT(15) -#define MT_TXS0_TX_STATUS_MCU BIT(14) -#define MT_TXS0_TX_RATE GENMASK(13, 0) - -#define MT_TXS1_SEQNO GENMASK(31, 20) -#define MT_TXS1_RESP_RATE GENMASK(19, 16) -#define MT_TXS1_RXV_SEQNO GENMASK(15, 8) -#define MT_TXS1_TX_POWER_DBM GENMASK(7, 0) - -#define MT_TXS2_BF_STATUS GENMASK(31, 30) -#define MT_TXS2_BAND GENMASK(29, 28) -#define MT_TXS2_WCID GENMASK(27, 16) -#define MT_TXS2_TX_DELAY GENMASK(15, 0) - -#define MT_TXS3_PID GENMASK(31, 24) -#define MT_TXS3_RATE_STBC BIT(7) -#define MT_TXS3_FIXED_RATE BIT(6) -#define MT_TXS3_SRC GENMASK(5, 4) -#define MT_TXS3_SHARED_ANTENNA BIT(3) -#define MT_TXS3_LAST_TX_RATE GENMASK(2, 0) - -#define MT_TXS4_TIMESTAMP GENMASK(31, 0) - -#define MT_TXS5_F0_FINAL_MPDU BIT(31) -#define MT_TXS5_F0_QOS BIT(30) -#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25) -#define MT_TXS5_F0_FRONT_TIME GENMASK(24, 0) -#define MT_TXS5_F1_MPDU_TX_COUNT GENMASK(31, 24) -#define MT_TXS5_F1_MPDU_TX_BYTES GENMASK(23, 0) - -#define MT_TXS6_F0_NOISE_3 GENMASK(31, 24) -#define MT_TXS6_F0_NOISE_2 GENMASK(23, 16) -#define MT_TXS6_F0_NOISE_1 GENMASK(15, 8) -#define MT_TXS6_F0_NOISE_0 GENMASK(7, 0) -#define MT_TXS6_F1_MPDU_FAIL_COUNT GENMASK(31, 24) -#define MT_TXS6_F1_MPDU_FAIL_BYTES GENMASK(23, 0) - -#define MT_TXS7_F0_RCPI_3 GENMASK(31, 24) -#define MT_TXS7_F0_RCPI_2 GENMASK(23, 16) -#define MT_TXS7_F0_RCPI_1 GENMASK(15, 8) -#define MT_TXS7_F0_RCPI_0 GENMASK(7, 0) -#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24) -#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0) +#include "../mt76_connac3_mac.h" struct mt7996_dfs_pulse { u32 max_width; /* us */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c index f306e9c50ea3..c3a479dc3f53 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c @@ -43,6 +43,10 @@ int mt7996_run(struct ieee80211_hw *hw) if (ret) goto out; + ret = mt7996_mcu_set_radio_en(phy, true); + if (ret) + goto out; + ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH); if (ret) goto out; @@ -82,6 +86,8 @@ static void mt7996_stop(struct ieee80211_hw *hw) mutex_lock(&dev->mt76.mutex); + mt7996_mcu_set_radio_en(phy, false); + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); mutex_unlock(&dev->mt76.mutex); @@ -190,17 +196,13 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, if (ret) goto out; - ret = mt7996_mcu_set_radio_en(phy, true); - if (ret) - goto out; - dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); idx = MT7996_WTBL_RESERVED - mvif->mt76.idx; INIT_LIST_HEAD(&mvif->sta.rc_list); - INIT_LIST_HEAD(&mvif->sta.poll_list); + INIT_LIST_HEAD(&mvif->sta.wcid.poll_list); mvif->sta.wcid.idx = idx; mvif->sta.wcid.phy_idx = band_idx; mvif->sta.wcid.hw_key_idx = -1; @@ -221,9 +223,9 @@ static int mt7996_add_interface(struct ieee80211_hw *hw, vif->offload_flags |= IEEE80211_OFFLOAD_ENCAP_4ADDR; if (phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) - mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; + mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL + 4; else - mvif->basic_rates_idx = MT7996_BASIC_RATES_TBL; + mvif->mt76.basic_rates_idx = MT7996_BASIC_RATES_TBL; mt7996_init_bitrate_mask(vif); @@ -253,7 +255,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, phy->monitor_vif = NULL; mt7996_mcu_add_dev_info(phy, vif, false); - mt7996_mcu_set_radio_en(phy, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); @@ -262,10 +263,10 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw, phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx); mutex_unlock(&dev->mt76.mutex); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); + spin_unlock_bh(&dev->mt76.sta_poll_lock); mt76_packet_id_flush(&dev->mt76, &msta->wcid); } @@ -286,7 +287,6 @@ int mt7996_set_channel(struct mt7996_phy *phy) if (ret) goto out; - mt7996_mac_set_timing(phy); ret = mt7996_dfs_init_radar_detector(phy); mt7996_mac_cca_stats_reset(phy); @@ -505,7 +505,7 @@ static u8 mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool beacon, bool mcast) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct mt76_phy *mphy = hw->priv; u16 rate; u8 i, idx, ht; @@ -517,7 +517,7 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7996_dev *dev = mt7996_hw_dev(hw); /* must odd index */ - idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->mt76.idx % 20); + idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20); mt7996_mac_set_fixed_rate_table(dev, idx, rate); return idx; } @@ -530,12 +530,32 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return mvif->basic_rates_idx; } +static void +mt7996_update_mu_group(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_dev *dev = mt7996_hw_dev(hw); + u8 band = mvif->mt76.band_idx; + u32 *mu; + + mu = (u32 *)info->mu_group.membership; + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD0(band), mu[0]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_VLD1(band), mu[1]); + + mu = (u32 *)info->mu_group.position; + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS0(band), mu[0]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS1(band), mu[1]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS2(band), mu[2]); + mt76_wr(dev, MT_WF_PHYRX_BAND_GID_TAB_POS3(band), mu[3]); +} + static void mt7996_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, u64 changed) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); @@ -563,7 +583,7 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, if (slottime != phy->slottime) { phy->slottime = slottime; - mt7996_mac_set_timing(phy); + mt7996_mcu_set_timing(phy, vif); } } @@ -602,6 +622,9 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw, changed & BSS_CHANGED_FILS_DISCOVERY) mt7996_mcu_beacon_inband_discov(dev, vif, changed); + if (changed & BSS_CHANGED_MU_GROUPS) + mt7996_update_mu_group(hw, vif, info); + mutex_unlock(&dev->mt76.mutex); } @@ -631,7 +654,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, return -ENOSPC; INIT_LIST_HEAD(&msta->rc_list); - INIT_LIST_HEAD(&msta->poll_list); + INIT_LIST_HEAD(&msta->wcid.poll_list); msta->vif = mvif; msta->wcid.sta = 1; msta->wcid.idx = idx; @@ -666,12 +689,12 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, for (i = 0; i < ARRAY_SIZE(msta->twt.flow); i++) mt7996_mac_twt_teardown_flow(dev, msta, i); - spin_lock_bh(&dev->sta_poll_lock); - if (!list_empty(&msta->poll_list)) - list_del_init(&msta->poll_list); + spin_lock_bh(&mdev->sta_poll_lock); + if (!list_empty(&msta->wcid.poll_list)) + list_del_init(&msta->wcid.poll_list); if (!list_empty(&msta->rc_list)) list_del_init(&msta->rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&mdev->sta_poll_lock); } static void mt7996_tx(struct ieee80211_hw *hw, @@ -751,16 +774,16 @@ mt7996_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7996_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: - set_bit(tid, &msta->ampdu_state); + set_bit(tid, &msta->wcid.ampdu_state); ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - clear_bit(tid, &msta->ampdu_state); + clear_bit(tid, &msta->wcid.ampdu_state); ret = mt7996_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; @@ -792,7 +815,7 @@ mt7996_get_stats(struct ieee80211_hw *hw, { struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_dev *dev = mt7996_hw_dev(hw); - struct mib_stats *mib = &phy->mib; + struct mt76_mib_stats *mib = &phy->mib; mutex_lock(&dev->mt76.mutex); @@ -903,7 +926,7 @@ mt7996_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) mutex_lock(&dev->mt76.mutex); phy->coverage_class = max_t(s16, coverage_class, 0); - mt7996_mac_set_timing(phy); + mt7996_mac_set_coverage_class(phy); mutex_unlock(&dev->mt76.mutex); } @@ -952,18 +975,19 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw, struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; struct rate_info *txrate = &msta->wcid.rate; - if (!txrate->legacy && !txrate->flags) - return; - - if (txrate->legacy) { - sinfo->txrate.legacy = txrate->legacy; - } else { - sinfo->txrate.mcs = txrate->mcs; - sinfo->txrate.nss = txrate->nss; - sinfo->txrate.bw = txrate->bw; - sinfo->txrate.he_gi = txrate->he_gi; - sinfo->txrate.he_dcm = txrate->he_dcm; - sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + if (txrate->legacy || txrate->flags) { + if (txrate->legacy) { + sinfo->txrate.legacy = txrate->legacy; + } else { + sinfo->txrate.mcs = txrate->mcs; + sinfo->txrate.nss = txrate->nss; + sinfo->txrate.bw = txrate->bw; + sinfo->txrate.he_gi = txrate->he_gi; + sinfo->txrate.he_dcm = txrate->he_dcm; + sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc; + } + sinfo->txrate.flags = txrate->flags; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); } sinfo->txrate.flags = txrate->flags; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); @@ -981,11 +1005,11 @@ static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta) struct mt7996_dev *dev = msta->vif->phy->dev; u32 *changed = data; - spin_lock_bh(&dev->sta_poll_lock); + spin_lock_bh(&dev->mt76.sta_poll_lock); msta->changed |= *changed; if (list_empty(&msta->rc_list)) list_add_tail(&msta->rc_list, &dev->sta_rc_list); - spin_unlock_bh(&dev->sta_poll_lock); + spin_unlock_bh(&dev->mt76.sta_poll_lock); } static void mt7996_sta_rc_update(struct ieee80211_hw *hw, @@ -1153,6 +1177,10 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = { "v_tx_mcs_11", "v_tx_mcs_12", "v_tx_mcs_13", + "v_tx_nss_1", + "v_tx_nss_2", + "v_tx_nss_3", + "v_tx_nss_4", }; #define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats) @@ -1186,7 +1214,7 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta) if (msta->vif->mt76.idx != wi->idx) return; - mt76_ethtool_worker(wi, &msta->stats, true); + mt76_ethtool_worker(wi, &msta->wcid.stats, true); } static @@ -1197,11 +1225,11 @@ void mt7996_get_et_stats(struct ieee80211_hw *hw, struct mt7996_dev *dev = mt7996_hw_dev(hw); struct mt7996_phy *phy = mt7996_hw_phy(hw); struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_mib_stats *mib = &phy->mib; struct mt76_ethtool_worker_info wi = { .data = data, .idx = mvif->mt76.idx, }; - struct mib_stats *mib = &phy->mib; /* See mt7996_ampdu_stat_read_phy, etc */ int i, ei = 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index 88e2f9d0e513..4a30db49ef33 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -339,7 +339,11 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb) if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys)) return; - mphy = dev->mt76.phys[r->band_idx]; + if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2) + mphy = dev->rdd2_phy->mt76; + else + mphy = dev->mt76.phys[r->band_idx]; + if (!mphy) return; @@ -600,7 +604,7 @@ static void mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7996_phy *phy) { - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv; struct bss_rate_tlv *bmc; struct cfg80211_chan_def *chandef = &phy->mt76->chandef; enum nl80211_band band = chandef->chan->band; @@ -701,6 +705,34 @@ mt7996_mcu_muar_config(struct mt7996_phy *phy, struct ieee80211_vif *vif, sizeof(req), true); } +static void +mt7996_mcu_bss_ifs_timing_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_phy *phy = mvif->phy; + struct bss_ifs_time_tlv *ifs_time; + struct tlv *tlv; + bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time)); + + ifs_time = (struct bss_ifs_time_tlv *)tlv; + ifs_time->slot_valid = true; + ifs_time->sifs_valid = true; + ifs_time->rifs_valid = true; + ifs_time->eifs_valid = true; + + ifs_time->slot_time = cpu_to_le16(phy->slottime); + ifs_time->sifs_time = cpu_to_le16(10); + ifs_time->rifs_time = cpu_to_le16(2); + ifs_time->eifs_time = cpu_to_le16(is_2ghz ? 78 : 84); + + if (is_2ghz) { + ifs_time->eifs_cck_valid = true; + ifs_time->eifs_cck_time = cpu_to_le16(314); + } +} + static int mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, @@ -712,6 +744,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct cfg80211_chan_def *chandef = &phy->chandef; struct mt76_connac_bss_basic_tlv *bss; u32 type = CONNECTION_INFRA_AP; + u16 sta_wlan_idx = wlan_idx; struct tlv *tlv; int idx; @@ -731,7 +764,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, struct mt76_wcid *wcid; wcid = (struct mt76_wcid *)sta->drv_priv; - wlan_idx = wcid->idx; + sta_wlan_idx = wcid->idx; } rcu_read_unlock(); } @@ -751,7 +784,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb, bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); bss->dtim_period = vif->bss_conf.dtim_period; bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx); - bss->sta_idx = cpu_to_le16(wlan_idx); + bss->sta_idx = cpu_to_le16(sta_wlan_idx); bss->conn_type = cpu_to_le32(type); bss->omac_idx = mvif->omac_idx; bss->band_idx = mvif->band_idx; @@ -825,6 +858,7 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, mt7996_mcu_bss_bmc_tlv(skb, vif, phy); mt7996_mcu_bss_ra_tlv(skb, vif, phy); mt7996_mcu_bss_txcmd_tlv(skb, true); + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); if (vif->bss_conf.he_support) mt7996_mcu_bss_he_tlv(skb, vif, phy); @@ -837,6 +871,23 @@ out: MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); } +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif) +{ + struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; + struct mt7996_dev *dev = phy->dev; + struct sk_buff *skb; + + skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, + MT7996_BSS_UPDATE_MAX_SIZE); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7996_mcu_bss_ifs_timing_tlv(skb, vif); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true); +} + static int mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif, struct ieee80211_ampdu_params *params, @@ -1050,6 +1101,59 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb, } } +static void +mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb, + struct ieee80211_vif *vif, struct ieee80211_sta *sta) +{ + struct ieee80211_he_cap_elem *elem = &sta->deflink.he_cap.he_cap_elem; + struct sta_rec_muru *muru; + struct tlv *tlv; + + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_AP) + return; + + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru)); + + muru = (struct sta_rec_muru *)tlv; + muru->cfg.mimo_dl_en = vif->bss_conf.eht_mu_beamformer || + vif->bss_conf.he_mu_beamformer || + vif->bss_conf.vht_mu_beamformer || + vif->bss_conf.vht_mu_beamformee; + muru->cfg.ofdma_dl_en = true; + + if (sta->deflink.vht_cap.vht_supported) + muru->mimo_dl.vht_mu_bfee = + !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE); + + if (!sta->deflink.he_cap.has_he) + return; + + muru->mimo_dl.partial_bw_dl_mimo = + HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]); + + muru->mimo_ul.full_ul_mimo = + HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]); + muru->mimo_ul.partial_ul_mimo = + HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]); + + muru->ofdma_dl.punc_pream_rx = + HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]); + muru->ofdma_dl.he_20m_in_40m_2g = + HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]); + muru->ofdma_dl.he_20m_in_160m = + HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + muru->ofdma_dl.he_80m_in_160m = + HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]); + + muru->ofdma_ul.t_frame_dur = + HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]); + muru->ofdma_ul.mu_cascading = + HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]); + muru->ofdma_ul.uo_ra = + HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]); +} + static inline bool mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool bfee) @@ -1727,7 +1831,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif, mt7996_mcu_sta_he_6g_tlv(skb, sta); /* starec eht */ mt7996_mcu_sta_eht_tlv(skb, sta); - /* TODO: starec muru */ + /* starec muru */ + mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta); /* starec bfee */ mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta); /* starec hdr trans */ @@ -2155,7 +2260,7 @@ out: static int mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, const struct mt7996_fw_trailer *hdr, - const u8 *data, bool is_wa) + const u8 *data, enum mt7996_ram_type type) { int i, offset = 0; u32 override = 0, option = 0; @@ -2167,8 +2272,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, region = (const struct mt7996_fw_region *)((const u8 *)hdr - (hdr->n_region - i) * sizeof(*region)); + /* DSP and WA use same mode */ mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76, - region->feature_set, is_wa); + region->feature_set, + type != MT7996_RAM_TYPE_WM); len = le32_to_cpu(region->len); addr = le32_to_cpu(region->addr); @@ -2195,19 +2302,22 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev, if (override) option |= FW_START_OVERRIDE; - if (is_wa) + if (type == MT7996_RAM_TYPE_WA) option |= FW_START_WORKING_PDA_CR4; + else if (type == MT7996_RAM_TYPE_DSP) + option |= FW_START_WORKING_PDA_DSP; return mt76_connac_mcu_start_firmware(&dev->mt76, override, option); } -static int mt7996_load_ram(struct mt7996_dev *dev) +static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type, + const char *fw_file, enum mt7996_ram_type ram_type) { const struct mt7996_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev); + ret = request_firmware(&fw, fw_file, dev->mt76.dev); if (ret) return ret; @@ -2217,37 +2327,13 @@ static int mt7996_load_ram(struct mt7996_dev *dev) goto out; } - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); + hdr = (const void *)(fw->data + fw->size - sizeof(*hdr)); + dev_info(dev->mt76.dev, "%s Firmware Version: %.10s, Build Time: %.15s\n", + fw_type, hdr->fw_ver, hdr->build_date); - dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false); + ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, ram_type); if (ret) { - dev_err(dev->mt76.dev, "Failed to start WM firmware\n"); - goto out; - } - - release_firmware(fw); - - ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev); - if (ret) - return ret; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; - } - - hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr)); - - dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n", - hdr->fw_ver, hdr->build_date); - - ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true); - if (ret) { - dev_err(dev->mt76.dev, "Failed to start WA firmware\n"); + dev_err(dev->mt76.dev, "Failed to start %s firmware\n", fw_type); goto out; } @@ -2261,6 +2347,24 @@ out: return ret; } +static int mt7996_load_ram(struct mt7996_dev *dev) +{ + int ret; + + ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM, + MT7996_RAM_TYPE_WM); + if (ret) + return ret; + + ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP, + MT7996_RAM_TYPE_DSP); + if (ret) + return ret; + + return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA, + MT7996_RAM_TYPE_WA); +} + static int mt7996_firmware_state(struct mt7996_dev *dev, bool wa) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h index d7075a4d0667..078f82858621 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h @@ -317,6 +317,22 @@ struct bss_sec_tlv { u8 __rsv2[1]; } __packed; +struct bss_ifs_time_tlv { + __le16 tag; + __le16 len; + u8 slot_valid; + u8 sifs_valid; + u8 rifs_valid; + u8 eifs_valid; + __le16 slot_time; + __le16 sifs_time; + __le16 rifs_time; + __le16 eifs_time; + u8 eifs_cck_valid; + u8 rsv; + __le16 eifs_cck_time; +} __packed; + struct bss_power_save { __le16 tag; __le16 len; @@ -552,6 +568,7 @@ enum { sizeof(struct bss_txcmd_tlv) + \ sizeof(struct bss_power_save) + \ sizeof(struct bss_sec_tlv) + \ + sizeof(struct bss_ifs_time_tlv) + \ sizeof(struct bss_mld_tlv)) #define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 4d7dcb95a620..7354e5cf8e67 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -26,15 +26,17 @@ #define MT7996_RX_RING_SIZE 1536 #define MT7996_RX_MCU_RING_SIZE 512 +#define MT7996_RX_MCU_RING_SIZE_WA 1024 #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin" #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin" +#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin" #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin" #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin" #define MT7996_EEPROM_SIZE 7680 #define MT7996_EEPROM_BLOCK_SIZE 16 -#define MT7996_TOKEN_SIZE 8192 +#define MT7996_TOKEN_SIZE 16384 #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ @@ -52,6 +54,12 @@ struct mt7996_sta; struct mt7996_dfs_pulse; struct mt7996_dfs_pattern; +enum mt7996_ram_type { + MT7996_RAM_TYPE_WM, + MT7996_RAM_TYPE_WA, + MT7996_RAM_TYPE_DSP, +}; + enum mt7996_txq_id { MT7996_TXQ_FWDL = 16, MT7996_TXQ_MCU_WM, @@ -95,7 +103,6 @@ struct mt7996_sta { struct mt7996_vif *vif; - struct list_head poll_list; struct list_head rc_list; u32 airtime_ac[8]; @@ -104,9 +111,6 @@ struct mt7996_sta { unsigned long changed; unsigned long jiffies; - unsigned long ampdu_state; - - struct mt76_sta_stats stats; struct mt76_connac_sta_key_conf bip; @@ -124,64 +128,6 @@ struct mt7996_vif { struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS]; struct cfg80211_bitrate_mask bitrate_mask; - - u8 basic_rates_idx; - u8 mcast_rates_idx; - u8 beacon_rates_idx; -}; - -/* per-phy stats. */ -struct mib_stats { - u32 ack_fail_cnt; - u32 fcs_err_cnt; - u32 rts_cnt; - u32 rts_retries_cnt; - u32 ba_miss_cnt; - u32 tx_mu_bf_cnt; - u32 tx_mu_mpdu_cnt; - u32 tx_mu_acked_mpdu_cnt; - u32 tx_su_acked_mpdu_cnt; - u32 tx_bf_ibf_ppdu_cnt; - u32 tx_bf_ebf_ppdu_cnt; - - u32 tx_bf_rx_fb_all_cnt; - u32 tx_bf_rx_fb_eht_cnt; - u32 tx_bf_rx_fb_he_cnt; - u32 tx_bf_rx_fb_vht_cnt; - u32 tx_bf_rx_fb_ht_cnt; - - u32 tx_bf_rx_fb_bw; /* value of last sample, not cumulative */ - u32 tx_bf_rx_fb_nc_cnt; - u32 tx_bf_rx_fb_nr_cnt; - u32 tx_bf_fb_cpl_cnt; - u32 tx_bf_fb_trig_cnt; - - u32 tx_ampdu_cnt; - u32 tx_stop_q_empty_cnt; - u32 tx_mpdu_attempts_cnt; - u32 tx_mpdu_success_cnt; - /* BF counter is PPDU-based, so remove MPDU-based BF counter */ - - u32 tx_rwp_fail_cnt; - u32 tx_rwp_need_cnt; - - /* rx stats */ - u32 rx_fifo_full_cnt; - u32 channel_idle_cnt; - u32 rx_vector_mismatch_cnt; - u32 rx_delimiter_fail_cnt; - u32 rx_len_mismatch_cnt; - u32 rx_mpdu_cnt; - u32 rx_ampdu_cnt; - u32 rx_ampdu_bytes_cnt; - u32 rx_ampdu_valid_subframe_cnt; - u32 rx_ampdu_valid_subframe_bytes_cnt; - u32 rx_pfdrop_cnt; - u32 rx_vec_queue_overflow_drop_cnt; - u32 rx_ba_cnt; - - u32 tx_amsdu[8]; - u32 tx_amsdu_cnt; }; /* crash-dump */ @@ -222,7 +168,7 @@ struct mt7996_phy { u32 rx_ampdu_ts; u32 ampdu_ref; - struct mib_stats mib; + struct mt76_mib_stats mib; struct mt76_channel_state state_ts; }; @@ -272,9 +218,7 @@ struct mt7996_dev { #endif struct list_head sta_rc_list; - struct list_head sta_poll_list; struct list_head twt_list; - spinlock_t sta_poll_lock; u32 hw_pattern; @@ -311,20 +255,6 @@ enum { }; enum { - MT_CTX0, - MT_HIF0 = 0x0, - - MT_LMAC_AC00 = 0x0, - MT_LMAC_AC01, - MT_LMAC_AC02, - MT_LMAC_AC03, - MT_LMAC_ALTX0 = 0x10, - MT_LMAC_BMC0, - MT_LMAC_BCN0, - MT_LMAC_PSMP0, -}; - -enum { MT_RX_SEL0, MT_RX_SEL1, MT_RX_SEL2, /* monitor chain */ @@ -405,6 +335,7 @@ int mt7996_dma_init(struct mt7996_dev *dev); void mt7996_dma_reset(struct mt7996_dev *dev, bool force); void mt7996_dma_prefetch(struct mt7996_dev *dev); void mt7996_dma_cleanup(struct mt7996_dev *dev); +void mt7996_dma_start(struct mt7996_dev *dev, bool reset); void mt7996_init_txpower(struct mt7996_dev *dev, struct ieee80211_supported_band *sband); int mt7996_txbf_init(struct mt7996_dev *dev); @@ -456,6 +387,7 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index, const struct mt7996_dfs_pattern *pattern); int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable); int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val); +int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif); int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch); int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index, u8 rx_sel, u8 val); @@ -519,7 +451,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, int pid, enum mt76_txq_id qid, u32 changed); -void mt7996_mac_set_timing(struct mt7996_phy *phy); +void mt7996_mac_set_coverage_class(struct mt7996_phy *phy); int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c index 64aee3fb5445..c5301050ff8b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c @@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table); MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table); MODULE_FIRMWARE(MT7996_FIRMWARE_WA); MODULE_FIRMWARE(MT7996_FIRMWARE_WM); +MODULE_FIRMWARE(MT7996_FIRMWARE_DSP); MODULE_FIRMWARE(MT7996_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h index d1d3d154195d..97beab924517 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/regs.h @@ -557,22 +557,29 @@ enum base_rev { #define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188) +/* PHYRX CSD */ +#define MT_WF_PHYRX_CSD_BASE 0x83000000 +#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \ + ((_band) << 20) + \ + ((_wf) << 16) + (ofs)) +#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000) + /* PHYRX CTRL */ #define MT_WF_PHYRX_BAND_BASE 0x83080000 #define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \ ((_band) << 20) + (ofs)) +#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054) +#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058) +#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c) +#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060) +#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064) +#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068) + #define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004) #define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0) #define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9) -/* PHYRX CSD */ -#define MT_WF_PHYRX_CSD_BASE 0x83000000 -#define MT_WF_PHYRX_CSD(_band, _wf, ofs) (MT_WF_PHYRX_CSD_BASE + \ - ((_band) << 20) + \ - ((_wf) << 16) + (ofs)) -#define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000) - /* PHYRX CSD BAND */ #define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230) #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18) diff --git a/drivers/net/wireless/mediatek/mt76/testmode.c b/drivers/net/wireless/mediatek/mt76/testmode.c index 0accc71a91c9..4644dace9bb3 100644 --- a/drivers/net/wireless/mediatek/mt76/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/testmode.c @@ -8,6 +8,7 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = { [MT76_TM_ATTR_RESET] = { .type = NLA_FLAG }, [MT76_TM_ATTR_STATE] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_COUNT] = { .type = NLA_U32 }, + [MT76_TM_ATTR_TX_LENGTH] = { .type = NLA_U32 }, [MT76_TM_ATTR_TX_RATE_MODE] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_NSS] = { .type = NLA_U8 }, [MT76_TM_ATTR_TX_RATE_IDX] = { .type = NLA_U8 }, diff --git a/drivers/net/wireless/mediatek/mt76/trace.h b/drivers/net/wireless/mediatek/mt76/trace.h index c3d0ef8e2890..109a07f9733a 100644 --- a/drivers/net/wireless/mediatek/mt76/trace.h +++ b/drivers/net/wireless/mediatek/mt76/trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEVICE_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEVICE_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s" #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 72b3ec715e47..6cc26cc6c517 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -121,6 +121,7 @@ int mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, struct sk_buff *skb) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); int pid; @@ -134,8 +135,14 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, return MT_PACKET_ID_NO_ACK; if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_CTL_RATE_CTRL_PROBE))) + IEEE80211_TX_CTL_RATE_CTRL_PROBE))) { + if (mtk_wed_device_active(&dev->mmio.wed) && + ((info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) || + ieee80211_is_data(hdr->frame_control))) + return MT_PACKET_ID_WED; + return MT_PACKET_ID_NO_SKB; + } spin_lock_bh(&dev->status_lock); @@ -263,8 +270,15 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff * #endif if (cb->pktid < MT_PACKET_ID_FIRST) { + struct ieee80211_rate_status rs = {}; + hw = mt76_tx_status_get_hw(dev, skb); status.sta = wcid_to_sta(wcid); + if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) { + rs.rate_idx = wcid->rate; + status.rates = &rs; + status.n_rates = 1; + } spin_lock_bh(&dev->rx_lock); ieee80211_tx_status_ext(hw, &status); spin_unlock_bh(&dev->rx_lock); diff --git a/drivers/net/wireless/mediatek/mt76/usb_trace.h b/drivers/net/wireless/mediatek/mt76/usb_trace.h index f5ab3215af80..7b261ddb2ac6 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_trace.h +++ b/drivers/net/wireless/mediatek/mt76/usb_trace.h @@ -14,7 +14,7 @@ #define MAXNAME 32 #define DEV_ENTRY __array(char, wiphy_name, 32) -#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ +#define DEV_ASSIGN strscpy(__entry->wiphy_name, \ wiphy_name(dev->hw->wiphy), MAXNAME) #define DEV_PR_FMT "%s " #define DEV_PR_ARG __entry->wiphy_name diff --git a/drivers/net/wireless/microchip/wilc1000/sdio.c b/drivers/net/wireless/microchip/wilc1000/sdio.c index a05bda7b9a3b..87948ba69a22 100644 --- a/drivers/net/wireless/microchip/wilc1000/sdio.c +++ b/drivers/net/wireless/microchip/wilc1000/sdio.c @@ -28,7 +28,6 @@ struct wilc_sdio { bool irq_gpio; u32 block_size; bool isinit; - int has_thrpt_enh3; u8 *cmd53_buf; }; @@ -722,21 +721,12 @@ static int wilc_sdio_init(struct wilc *wilc, bool resume) * make sure can read back chip id correctly **/ if (!resume) { - int rev; - ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid); if (ret) { dev_err(&func->dev, "Fail cmd read chip id...\n"); return ret; } dev_err(&func->dev, "chipid (%08x)\n", chipid); - rev = FIELD_GET(WILC_CHIP_REV_FIELD, chipid); - if (rev > FIELD_GET(WILC_CHIP_REV_FIELD, WILC_1000_BASE_ID_2A)) - sdio_priv->has_thrpt_enh3 = 1; - else - sdio_priv->has_thrpt_enh3 = 0; - dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", - sdio_priv->has_thrpt_enh3); } sdio_priv->isinit = true; @@ -809,102 +799,29 @@ static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; int ret; - int vmm_ctl; - - if (sdio_priv->has_thrpt_enh3) { - u32 reg = 0; - - if (sdio_priv->irq_gpio) - reg = val & (BIT(MAX_NUM_INT) - 1); - - /* select VMM table 0 */ - if (val & SEL_VMM_TBL0) - reg |= BIT(5); - /* select VMM table 1 */ - if (val & SEL_VMM_TBL1) - reg |= BIT(6); - /* enable VMM */ - if (val & EN_VMM) - reg |= BIT(7); - if (reg) { - struct sdio_cmd52 cmd; - - cmd.read_write = 1; - cmd.function = 0; - cmd.raw = 0; - cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; - cmd.data = reg; - - ret = wilc_sdio_cmd52(wilc, &cmd); - if (ret) { - dev_err(&func->dev, - "Failed cmd52, set (%02x) data (%d) ...\n", - cmd.address, __LINE__); - return ret; - } - } - return 0; - } - if (sdio_priv->irq_gpio) { - /* has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ - /* - * Cannot clear multiple interrupts. - * Must clear each interrupt individually. - */ - u32 flags; - int i; - - flags = val & (BIT(MAX_NUM_INT) - 1); - for (i = 0; i < NUM_INT_EXT && flags; i++) { - if (flags & BIT(i)) { - struct sdio_cmd52 cmd; - - cmd.read_write = 1; - cmd.function = 0; - cmd.raw = 0; - cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; - cmd.data = BIT(i); - - ret = wilc_sdio_cmd52(wilc, &cmd); - if (ret) { - dev_err(&func->dev, - "Failed cmd52, set (%02x) data (%d) ...\n", - cmd.address, __LINE__); - return ret; - } - flags &= ~BIT(i); - } - } + u32 reg = 0; - for (i = NUM_INT_EXT; i < MAX_NUM_INT && flags; i++) { - if (flags & BIT(i)) { - dev_err(&func->dev, - "Unexpected interrupt cleared %d...\n", - i); - flags &= ~BIT(i); - } - } - } + if (sdio_priv->irq_gpio) + reg = val & (BIT(MAX_NUM_INT) - 1); - vmm_ctl = 0; /* select VMM table 0 */ if (val & SEL_VMM_TBL0) - vmm_ctl |= BIT(0); + reg |= BIT(5); /* select VMM table 1 */ if (val & SEL_VMM_TBL1) - vmm_ctl |= BIT(1); + reg |= BIT(6); /* enable VMM */ if (val & EN_VMM) - vmm_ctl |= BIT(2); - - if (vmm_ctl) { + reg |= BIT(7); + if (reg) { struct sdio_cmd52 cmd; cmd.read_write = 1; cmd.function = 0; cmd.raw = 0; - cmd.address = WILC_SDIO_VMM_TBL_CTRL_REG; - cmd.data = vmm_ctl; + cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; + cmd.data = reg; + ret = wilc_sdio_cmd52(wilc, &cmd); if (ret) { dev_err(&func->dev, diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index b0fc5e68feec..77b4cdff73c3 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -74,6 +74,7 @@ static int wilc_spi_reset(struct wilc *wilc); #define CMD_SINGLE_READ 0xca #define CMD_RESET 0xcf +#define SPI_RETRY_MAX_LIMIT 10 #define SPI_ENABLE_VMM_RETRY_LIMIT 2 /* SPI response fields (section 11.1.2 in ATWILC1000 User Guide): */ @@ -830,59 +831,91 @@ static int wilc_spi_special_cmd(struct wilc *wilc, u8 cmd) return 0; } +static void wilc_spi_reset_cmd_sequence(struct wilc *wl, u8 attempt, u32 addr) +{ + struct spi_device *spi = to_spi_device(wl->dev); + struct wilc_spi *spi_priv = wl->bus_data; + + if (!spi_priv->probing_crc) + dev_err(&spi->dev, "Reset and retry %d %x\n", attempt, addr); + + usleep_range(1000, 1100); + wilc_spi_reset(wl); + usleep_range(1000, 1100); +} + static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) { struct spi_device *spi = to_spi_device(wilc->dev); int result; u8 cmd = CMD_SINGLE_READ; u8 clockless = 0; + u8 i; - if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) { + if (addr <= WILC_SPI_CLOCKLESS_ADDR_LIMIT) { /* Clockless register */ cmd = CMD_INTERNAL_READ; clockless = 1; } - result = wilc_spi_single_read(wilc, cmd, addr, data, clockless); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_single_read(wilc, cmd, addr, data, clockless); + if (!result) { + le32_to_cpus(data); + return 0; + } + + /* retry is not applicable for clockless registers */ + if (clockless) + break; + dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr); - return result; + wilc_spi_reset_cmd_sequence(wilc, i, addr); } - le32_to_cpus(data); - - return 0; + return result; } static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; if (size <= 4) return -EINVAL; - result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_READ, addr, buf, size); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_READ, addr, + buf, size); + if (!result) + return 0; + dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr); - return result; + + wilc_spi_reset_cmd_sequence(wilc, i, addr); } - return 0; + return result; } static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; - result = wilc_spi_write_cmd(wilc, CMD_INTERNAL_WRITE, adr, dat, 0); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_write_cmd(wilc, CMD_INTERNAL_WRITE, adr, + dat, 0); + if (!result) + return 0; dev_err(&spi->dev, "Failed internal write cmd...\n"); - return result; + + wilc_spi_reset_cmd_sequence(wilc, i, adr); } - return 0; + return result; } static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) @@ -890,17 +923,22 @@ static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) struct spi_device *spi = to_spi_device(wilc->dev); struct wilc_spi *spi_priv = wilc->bus_data; int result; + u8 i; - result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, data, 0); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, + data, 0); + if (!result) { + le32_to_cpus(data); + return 0; + } if (!spi_priv->probing_crc) dev_err(&spi->dev, "Failed internal read cmd...\n"); - return result; - } - le32_to_cpus(data); + wilc_spi_reset_cmd_sequence(wilc, i, adr); + } - return 0; + return result; } /******************************************** @@ -915,20 +953,27 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) int result; u8 cmd = CMD_SINGLE_WRITE; u8 clockless = 0; + u8 i; - if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) { + if (addr <= WILC_SPI_CLOCKLESS_ADDR_LIMIT) { /* Clockless register */ cmd = CMD_INTERNAL_WRITE; clockless = 1; } - result = wilc_spi_write_cmd(wilc, cmd, addr, data, clockless); - if (result) { + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_write_cmd(wilc, cmd, addr, data, clockless); + if (!result) + return 0; + dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr); - return result; - } - return 0; + if (clockless) + break; + + wilc_spi_reset_cmd_sequence(wilc, i, addr); + } + return result; } static int spi_data_rsp(struct wilc *wilc, u8 cmd) @@ -981,6 +1026,7 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct spi_device *spi = to_spi_device(wilc->dev); int result; + u8 i; /* * has to be greated than 4 @@ -988,26 +1034,38 @@ static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) if (size <= 4) return -EINVAL; - result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_WRITE, addr, NULL, size); - if (result) { - dev_err(&spi->dev, - "Failed cmd, write block (%08x)...\n", addr); - return result; - } + for (i = 0; i < SPI_RETRY_MAX_LIMIT; i++) { + result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_WRITE, addr, + NULL, size); + if (result) { + dev_err(&spi->dev, + "Failed cmd, write block (%08x)...\n", addr); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } - /* - * Data - */ - result = spi_data_write(wilc, buf, size); - if (result) { - dev_err(&spi->dev, "Failed block data write...\n"); - return result; - } + /* + * Data + */ + result = spi_data_write(wilc, buf, size); + if (result) { + dev_err(&spi->dev, "Failed block data write...\n"); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } - /* - * Data response - */ - return spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); + /* + * Data response + */ + result = spi_data_rsp(wilc, CMD_DMA_EXT_WRITE); + if (result) { + dev_err(&spi->dev, "Failed block data rsp...\n"); + wilc_spi_reset_cmd_sequence(wilc, i, addr); + continue; + } + break; + } + return result; } /******************************************** diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index f673aa9ba15a..47bcaec6f2db 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -1767,6 +1767,8 @@ struct rtl8xxxu_fileops rtl8192eu_fops = { .has_s0s1 = 0, .gen2_thermal_meter = 1, .needs_full_init = 1, + .supports_ap = 1, + .max_macid_num = 128, .adda_1t_init = 0x0fc01616, .adda_1t_path_on = 0x0fc01616, .adda_2t_path_on_a = 0x0fc01616, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c index 18dc5221a9c0..28e93835e05a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c @@ -2079,6 +2079,8 @@ struct rtl8xxxu_fileops rtl8192fu_fops = { .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, .max_aggr_num = 0x1f1f, + .supports_ap = 1, + .max_macid_num = 128, .trxff_boundary = 0x3f3f, .pbp_rx = PBP_PAGE_SIZE_256, .pbp_tx = PBP_PAGE_SIZE_256, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c index f0d17b75c5f1..871b8cca8a18 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c @@ -1875,6 +1875,8 @@ struct rtl8xxxu_fileops rtl8710bu_fops = { */ .ustime_tsf_edca = 0x28, .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 16, .adda_1t_init = 0x03c00016, .adda_1t_path_on = 0x03c00016, .trxff_boundary = 0x3f7f, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index 13ad5d5b73f4..954369ed6226 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -1742,6 +1742,8 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, .max_aggr_num = 0x0c14, + .supports_ap = 1, + .max_macid_num = 128, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 567bbedd8ee0..a1b674e3caaa 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -140,7 +140,7 @@ struct rtw_beacon_filter_iter_data { u8 *payload; }; -static void rtw_fw_bcn_filter_notify_vif_iter(void *data, u8 *mac, +static void rtw_fw_bcn_filter_notify_vif_iter(void *data, struct ieee80211_vif *vif) { struct rtw_beacon_filter_iter_data *iter_data = data; diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index c853e2f2d448..4a33d2e47f33 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -185,8 +185,7 @@ static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif) bf_info->cur_csi_rpt_rate = new_csi_rate_idx; } -static void rtw_vif_watch_dog_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) { struct rtw_watch_dog_iter_data *iter_data = data; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; @@ -1303,7 +1302,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, si->stbc_en = stbc_en; si->ldpc_en = ldpc_en; si->rf_type = rf_type; - si->wireless_set = wireless_set; si->sgi_enable = is_support_sgi; si->vht_enable = is_vht_enable; si->ra_mask = ra_mask; @@ -2183,10 +2181,12 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) release_firmware(wow_fw->firmware); destroy_workqueue(rtwdev->tx_wq); + timer_delete_sync(&rtwdev->tx_report.purge_timer); spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); skb_queue_purge(&rtwdev->tx_report.queue); - skb_queue_purge(&rtwdev->coex.queue); spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags); + skb_queue_purge(&rtwdev->coex.queue); + skb_queue_purge(&rtwdev->c2h_queue); list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, build_list) { @@ -2329,7 +2329,7 @@ struct rtw_iter_port_switch_data { struct rtw_vif *rtwvif_ap; }; -static void rtw_port_switch_iter(void *data, u8 *mac, struct ieee80211_vif *vif) +static void rtw_port_switch_iter(void *data, struct ieee80211_vif *vif) { struct rtw_iter_port_switch_data *iter_data = data; struct rtw_dev *rtwdev = iter_data->rtwdev; @@ -2381,8 +2381,7 @@ void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) rtw_iterate_vifs(rtwdev, rtw_port_switch_iter, &iter_data); } -static void rtw_check_sta_active_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_check_sta_active_iter(void *data, struct ieee80211_vif *vif) { struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; bool *active = data; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index f9dd2ab941c8..c42ef8294d59 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -511,12 +511,6 @@ struct rtw_txpwr_idx { struct rtw_5g_txpwr_idx pwr_idx_5g; }; -struct rtw_timer_list { - struct timer_list timer; - void (*function)(void *data); - void *args; -}; - struct rtw_channel_params { u8 center_chan; u8 primary_chan; @@ -734,9 +728,7 @@ struct rtw_ra_report { struct rtw_txq { struct list_head list; - unsigned long flags; - unsigned long last_push; }; #define RTW_BC_MC_MACID 1 @@ -754,7 +746,6 @@ struct rtw_sta_info { u8 rate_id; enum rtw_bandwidth bw_mode; enum rtw_rf_type rf_type; - enum rtw_wireless_set wireless_set; u8 stbc_en:2; u8 ldpc_en:2; bool sgi_enable; diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 43e80a3a8136..07e8cbd436cd 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -37,8 +37,7 @@ int rtw_enter_ips(struct rtw_dev *rtwdev) return 0; } -static void rtw_restore_port_cfg_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_restore_port_cfg_iter(void *data, struct ieee80211_vif *vif) { struct rtw_dev *rtwdev = data; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; @@ -320,8 +319,7 @@ static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, data->found_vif = vif; } -static void rtw_vif_recalc_lps_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rtw_vif_recalc_lps_iter(void *data, struct ieee80211_vif *vif) { __rtw_vif_recalc_lps(data, vif); } diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c index 2821119dc930..f63900b6621d 100644 --- a/drivers/net/wireless/realtek/rtw88/tx.c +++ b/drivers/net/wireless/realtek/rtw88/tx.c @@ -606,8 +606,6 @@ static int rtw_txq_push_skb(struct rtw_dev *rtwdev, rtw_err(rtwdev, "failed to write TX skb to HCI\n"); return ret; } - rtwtxq->last_push = jiffies; - return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 4a57efdba97b..91ed6d10ba8a 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -142,7 +142,6 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev, struct usb_host_interface *host_interface = &interface->altsetting[0]; struct usb_interface_descriptor *interface_desc = &host_interface->desc; struct usb_endpoint_descriptor *endpoint; - struct usb_device *usbd = interface_to_usbdev(interface); int num_out_pipes = 0; int i; u8 num; @@ -184,22 +183,6 @@ static int rtw_usb_parse(struct rtw_dev *rtwdev, } } - switch (usbd->speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - rtwusb->bulkout_size = RTW_USB_FULL_SPEED_BULK_SIZE; - break; - case USB_SPEED_HIGH: - rtwusb->bulkout_size = RTW_USB_HIGH_SPEED_BULK_SIZE; - break; - case USB_SPEED_SUPER: - rtwusb->bulkout_size = RTW_USB_SUPER_SPEED_BULK_SIZE; - break; - default: - rtw_err(rtwdev, "failed to detect usb speed\n"); - return -EINVAL; - } - rtwdev->hci.bulkout_num = num_out_pipes; if (num_out_pipes < 1 || num_out_pipes > 4) { @@ -654,7 +637,6 @@ static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb) for (i = 0; i < RTW_USB_RXCB_NUM; i++) { struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i]; - rxcb->n = i; rxcb->rtwdev = rtwusb->rtwdev; rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rxcb->rx_urb) diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h index ad1d7955c6a5..86697a5c0103 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.h +++ b/drivers/net/wireless/realtek/rtw88/usb.h @@ -18,10 +18,6 @@ #define RTW_USB_VENQT_CMD_IDX 0x00 -#define RTW_USB_SUPER_SPEED_BULK_SIZE 1024 -#define RTW_USB_HIGH_SPEED_BULK_SIZE 512 -#define RTW_USB_FULL_SPEED_BULK_SIZE 64 - #define RTW_USB_TX_SEL_HQ BIT(0) #define RTW_USB_TX_SEL_LQ BIT(1) #define RTW_USB_TX_SEL_NQ BIT(2) @@ -58,7 +54,6 @@ struct rx_usb_ctrl_block { struct rtw_dev *rtwdev; struct urb *rx_urb; struct sk_buff *rx_skb; - int n; }; struct rtw_usb_tx_data { @@ -74,12 +69,10 @@ struct rtw_usb { __le32 *usb_data; unsigned int usb_data_index; - u32 bulkout_size; u8 pipe_interrupt; u8 pipe_in; u8 out_ep[RTW_USB_EP_MAX]; int qsel_to_ep[TX_DESC_QSEL_MAX]; - u8 usb_txagg_num; struct workqueue_struct *txwq, *rxwq; diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c index ff3c269fb1a7..e222d3c01a77 100644 --- a/drivers/net/wireless/realtek/rtw88/util.c +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -159,7 +159,6 @@ void rtw_iterate_stas(struct rtw_dev *rtwdev, struct rtw_vifs_entry { struct list_head list; struct ieee80211_vif *vif; - u8 mac[ETH_ALEN]; }; struct rtw_iter_vifs_data { @@ -177,13 +176,11 @@ static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) return; vifs_entry->vif = vif; - ether_addr_copy(vifs_entry->mac, mac); list_add_tail(&vifs_entry->list, &iter_stas->list); } void rtw_iterate_vifs(struct rtw_dev *rtwdev, - void (*iterator)(void *data, u8 *mac, - struct ieee80211_vif *vif), + void (*iterator)(void *data, struct ieee80211_vif *vif), void *data) { struct rtw_iter_vifs_data iter_data; @@ -204,7 +201,7 @@ void rtw_iterate_vifs(struct rtw_dev *rtwdev, list_for_each_entry_safe(vif_entry, tmp, &iter_data.list, list) { list_del_init(&vif_entry->list); - iterator(data, vif_entry->mac, vif_entry->vif); + iterator(data, vif_entry->vif); kfree(vif_entry); } } diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h index dc8965525400..f8399128a9a3 100644 --- a/drivers/net/wireless/realtek/rtw88/util.h +++ b/drivers/net/wireless/realtek/rtw88/util.h @@ -18,8 +18,7 @@ struct rtw_dev; ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) void rtw_iterate_vifs(struct rtw_dev *rtwdev, - void (*iterator)(void *data, u8 *mac, - struct ieee80211_vif *vif), + void (*iterator)(void *data, struct ieee80211_vif *vif), void *data); void rtw_iterate_stas(struct rtw_dev *rtwdev, void (*iterator)(void *data, diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 69b181fa2966..62c21c09cf92 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -1456,16 +1456,16 @@ static bool rtw89_core_rx_ppdu_match(struct rtw89_dev *rtwdev, bool ret; data_rate = desc_info->data_rate; - data_rate_mode = GET_DATA_RATE_MODE(data_rate); + data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate); if (data_rate_mode == DATA_RATE_MODE_NON_HT) { - rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); + rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate); /* rate_idx is still hardware value here */ } else if (data_rate_mode == DATA_RATE_MODE_HT) { - rate_idx = GET_DATA_RATE_HT_IDX(data_rate); + rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate); } else if (data_rate_mode == DATA_RATE_MODE_VHT) { - rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); + rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); } else if (data_rate_mode == DATA_RATE_MODE_HE) { - rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); + rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } @@ -1929,26 +1929,26 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev, rx_status->bw = rtw89_hw_to_rate_info_bw(desc_info->bw); data_rate = desc_info->data_rate; - data_rate_mode = GET_DATA_RATE_MODE(data_rate); + data_rate_mode = rtw89_get_data_rate_mode(rtwdev, data_rate); if (data_rate_mode == DATA_RATE_MODE_NON_HT) { rx_status->encoding = RX_ENC_LEGACY; - rx_status->rate_idx = GET_DATA_RATE_NOT_HT_IDX(data_rate); + rx_status->rate_idx = rtw89_get_data_not_ht_idx(rtwdev, data_rate); /* convert rate_idx after we get the correct band */ } else if (data_rate_mode == DATA_RATE_MODE_HT) { rx_status->encoding = RX_ENC_HT; - rx_status->rate_idx = GET_DATA_RATE_HT_IDX(data_rate); + rx_status->rate_idx = rtw89_get_data_ht_mcs(rtwdev, data_rate); if (desc_info->gi_ltf) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; } else if (data_rate_mode == DATA_RATE_MODE_VHT) { rx_status->encoding = RX_ENC_VHT; - rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); - rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; + rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); + rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; if (desc_info->gi_ltf) rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI; } else if (data_rate_mode == DATA_RATE_MODE_HE) { rx_status->encoding = RX_ENC_HE; - rx_status->rate_idx = GET_DATA_RATE_VHT_HE_IDX(data_rate); - rx_status->nss = GET_DATA_RATE_NSS(data_rate) + 1; + rx_status->rate_idx = rtw89_get_data_mcs(rtwdev, data_rate); + rx_status->nss = rtw89_get_data_nss(rtwdev, data_rate) + 1; } else { rtw89_warn(rtwdev, "invalid RX rate mode %d\n", data_rate_mode); } @@ -3508,7 +3508,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev) set_bit(RTW89_FLAG_RUNNING, rtwdev->flags); rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON); - rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable); + rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.log.enable); rtw89_fw_h2c_init_ba_cam(rtwdev); return 0; @@ -3779,6 +3779,12 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev) return ret; } + ret = rtw89_fw_recognize_elements(rtwdev); + if (ret) { + rtw89_err(rtwdev, "failed to recognize firmware elements\n"); + return ret; + } + ret = rtw89_chip_efuse_info_setup(rtwdev); if (ret) return ret; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index d2c67db97db1..fa4bbc4095ab 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -109,6 +109,14 @@ enum rtw89_core_chip_id { RTL8852B, RTL8852C, RTL8851B, + RTL8922A, +}; + +enum rtw89_chip_gen { + RTW89_CHIP_AX, + RTW89_CHIP_BE, + + RTW89_CHIP_GEN_NUM, }; enum rtw89_cv { @@ -387,10 +395,201 @@ enum rtw89_hw_rate { RTW89_HW_RATE_HE_NSS4_MCS9 = 0x1B9, RTW89_HW_RATE_HE_NSS4_MCS10 = 0x1BA, RTW89_HW_RATE_HE_NSS4_MCS11 = 0x1BB, + + RTW89_HW_RATE_V1_MCS0 = 0x100, + RTW89_HW_RATE_V1_MCS1 = 0x101, + RTW89_HW_RATE_V1_MCS2 = 0x102, + RTW89_HW_RATE_V1_MCS3 = 0x103, + RTW89_HW_RATE_V1_MCS4 = 0x104, + RTW89_HW_RATE_V1_MCS5 = 0x105, + RTW89_HW_RATE_V1_MCS6 = 0x106, + RTW89_HW_RATE_V1_MCS7 = 0x107, + RTW89_HW_RATE_V1_MCS8 = 0x108, + RTW89_HW_RATE_V1_MCS9 = 0x109, + RTW89_HW_RATE_V1_MCS10 = 0x10A, + RTW89_HW_RATE_V1_MCS11 = 0x10B, + RTW89_HW_RATE_V1_MCS12 = 0x10C, + RTW89_HW_RATE_V1_MCS13 = 0x10D, + RTW89_HW_RATE_V1_MCS14 = 0x10E, + RTW89_HW_RATE_V1_MCS15 = 0x10F, + RTW89_HW_RATE_V1_MCS16 = 0x110, + RTW89_HW_RATE_V1_MCS17 = 0x111, + RTW89_HW_RATE_V1_MCS18 = 0x112, + RTW89_HW_RATE_V1_MCS19 = 0x113, + RTW89_HW_RATE_V1_MCS20 = 0x114, + RTW89_HW_RATE_V1_MCS21 = 0x115, + RTW89_HW_RATE_V1_MCS22 = 0x116, + RTW89_HW_RATE_V1_MCS23 = 0x117, + RTW89_HW_RATE_V1_MCS24 = 0x118, + RTW89_HW_RATE_V1_MCS25 = 0x119, + RTW89_HW_RATE_V1_MCS26 = 0x11A, + RTW89_HW_RATE_V1_MCS27 = 0x11B, + RTW89_HW_RATE_V1_MCS28 = 0x11C, + RTW89_HW_RATE_V1_MCS29 = 0x11D, + RTW89_HW_RATE_V1_MCS30 = 0x11E, + RTW89_HW_RATE_V1_MCS31 = 0x11F, + RTW89_HW_RATE_V1_VHT_NSS1_MCS0 = 0x200, + RTW89_HW_RATE_V1_VHT_NSS1_MCS1 = 0x201, + RTW89_HW_RATE_V1_VHT_NSS1_MCS2 = 0x202, + RTW89_HW_RATE_V1_VHT_NSS1_MCS3 = 0x203, + RTW89_HW_RATE_V1_VHT_NSS1_MCS4 = 0x204, + RTW89_HW_RATE_V1_VHT_NSS1_MCS5 = 0x205, + RTW89_HW_RATE_V1_VHT_NSS1_MCS6 = 0x206, + RTW89_HW_RATE_V1_VHT_NSS1_MCS7 = 0x207, + RTW89_HW_RATE_V1_VHT_NSS1_MCS8 = 0x208, + RTW89_HW_RATE_V1_VHT_NSS1_MCS9 = 0x209, + RTW89_HW_RATE_V1_VHT_NSS1_MCS10 = 0x20A, + RTW89_HW_RATE_V1_VHT_NSS1_MCS11 = 0x20B, + RTW89_HW_RATE_V1_VHT_NSS2_MCS0 = 0x220, + RTW89_HW_RATE_V1_VHT_NSS2_MCS1 = 0x221, + RTW89_HW_RATE_V1_VHT_NSS2_MCS2 = 0x222, + RTW89_HW_RATE_V1_VHT_NSS2_MCS3 = 0x223, + RTW89_HW_RATE_V1_VHT_NSS2_MCS4 = 0x224, + RTW89_HW_RATE_V1_VHT_NSS2_MCS5 = 0x225, + RTW89_HW_RATE_V1_VHT_NSS2_MCS6 = 0x226, + RTW89_HW_RATE_V1_VHT_NSS2_MCS7 = 0x227, + RTW89_HW_RATE_V1_VHT_NSS2_MCS8 = 0x228, + RTW89_HW_RATE_V1_VHT_NSS2_MCS9 = 0x229, + RTW89_HW_RATE_V1_VHT_NSS2_MCS10 = 0x22A, + RTW89_HW_RATE_V1_VHT_NSS2_MCS11 = 0x22B, + RTW89_HW_RATE_V1_VHT_NSS3_MCS0 = 0x240, + RTW89_HW_RATE_V1_VHT_NSS3_MCS1 = 0x241, + RTW89_HW_RATE_V1_VHT_NSS3_MCS2 = 0x242, + RTW89_HW_RATE_V1_VHT_NSS3_MCS3 = 0x243, + RTW89_HW_RATE_V1_VHT_NSS3_MCS4 = 0x244, + RTW89_HW_RATE_V1_VHT_NSS3_MCS5 = 0x245, + RTW89_HW_RATE_V1_VHT_NSS3_MCS6 = 0x246, + RTW89_HW_RATE_V1_VHT_NSS3_MCS7 = 0x247, + RTW89_HW_RATE_V1_VHT_NSS3_MCS8 = 0x248, + RTW89_HW_RATE_V1_VHT_NSS3_MCS9 = 0x249, + RTW89_HW_RATE_V1_VHT_NSS3_MCS10 = 0x24A, + RTW89_HW_RATE_V1_VHT_NSS3_MCS11 = 0x24B, + RTW89_HW_RATE_V1_VHT_NSS4_MCS0 = 0x260, + RTW89_HW_RATE_V1_VHT_NSS4_MCS1 = 0x261, + RTW89_HW_RATE_V1_VHT_NSS4_MCS2 = 0x262, + RTW89_HW_RATE_V1_VHT_NSS4_MCS3 = 0x263, + RTW89_HW_RATE_V1_VHT_NSS4_MCS4 = 0x264, + RTW89_HW_RATE_V1_VHT_NSS4_MCS5 = 0x265, + RTW89_HW_RATE_V1_VHT_NSS4_MCS6 = 0x266, + RTW89_HW_RATE_V1_VHT_NSS4_MCS7 = 0x267, + RTW89_HW_RATE_V1_VHT_NSS4_MCS8 = 0x268, + RTW89_HW_RATE_V1_VHT_NSS4_MCS9 = 0x269, + RTW89_HW_RATE_V1_VHT_NSS4_MCS10 = 0x26A, + RTW89_HW_RATE_V1_VHT_NSS4_MCS11 = 0x26B, + RTW89_HW_RATE_V1_HE_NSS1_MCS0 = 0x300, + RTW89_HW_RATE_V1_HE_NSS1_MCS1 = 0x301, + RTW89_HW_RATE_V1_HE_NSS1_MCS2 = 0x302, + RTW89_HW_RATE_V1_HE_NSS1_MCS3 = 0x303, + RTW89_HW_RATE_V1_HE_NSS1_MCS4 = 0x304, + RTW89_HW_RATE_V1_HE_NSS1_MCS5 = 0x305, + RTW89_HW_RATE_V1_HE_NSS1_MCS6 = 0x306, + RTW89_HW_RATE_V1_HE_NSS1_MCS7 = 0x307, + RTW89_HW_RATE_V1_HE_NSS1_MCS8 = 0x308, + RTW89_HW_RATE_V1_HE_NSS1_MCS9 = 0x309, + RTW89_HW_RATE_V1_HE_NSS1_MCS10 = 0x30A, + RTW89_HW_RATE_V1_HE_NSS1_MCS11 = 0x30B, + RTW89_HW_RATE_V1_HE_NSS2_MCS0 = 0x320, + RTW89_HW_RATE_V1_HE_NSS2_MCS1 = 0x321, + RTW89_HW_RATE_V1_HE_NSS2_MCS2 = 0x322, + RTW89_HW_RATE_V1_HE_NSS2_MCS3 = 0x323, + RTW89_HW_RATE_V1_HE_NSS2_MCS4 = 0x324, + RTW89_HW_RATE_V1_HE_NSS2_MCS5 = 0x325, + RTW89_HW_RATE_V1_HE_NSS2_MCS6 = 0x326, + RTW89_HW_RATE_V1_HE_NSS2_MCS7 = 0x327, + RTW89_HW_RATE_V1_HE_NSS2_MCS8 = 0x328, + RTW89_HW_RATE_V1_HE_NSS2_MCS9 = 0x329, + RTW89_HW_RATE_V1_HE_NSS2_MCS10 = 0x32A, + RTW89_HW_RATE_V1_HE_NSS2_MCS11 = 0x32B, + RTW89_HW_RATE_V1_HE_NSS3_MCS0 = 0x340, + RTW89_HW_RATE_V1_HE_NSS3_MCS1 = 0x341, + RTW89_HW_RATE_V1_HE_NSS3_MCS2 = 0x342, + RTW89_HW_RATE_V1_HE_NSS3_MCS3 = 0x343, + RTW89_HW_RATE_V1_HE_NSS3_MCS4 = 0x344, + RTW89_HW_RATE_V1_HE_NSS3_MCS5 = 0x345, + RTW89_HW_RATE_V1_HE_NSS3_MCS6 = 0x346, + RTW89_HW_RATE_V1_HE_NSS3_MCS7 = 0x347, + RTW89_HW_RATE_V1_HE_NSS3_MCS8 = 0x348, + RTW89_HW_RATE_V1_HE_NSS3_MCS9 = 0x349, + RTW89_HW_RATE_V1_HE_NSS3_MCS10 = 0x34A, + RTW89_HW_RATE_V1_HE_NSS3_MCS11 = 0x34B, + RTW89_HW_RATE_V1_HE_NSS4_MCS0 = 0x360, + RTW89_HW_RATE_V1_HE_NSS4_MCS1 = 0x361, + RTW89_HW_RATE_V1_HE_NSS4_MCS2 = 0x362, + RTW89_HW_RATE_V1_HE_NSS4_MCS3 = 0x363, + RTW89_HW_RATE_V1_HE_NSS4_MCS4 = 0x364, + RTW89_HW_RATE_V1_HE_NSS4_MCS5 = 0x365, + RTW89_HW_RATE_V1_HE_NSS4_MCS6 = 0x366, + RTW89_HW_RATE_V1_HE_NSS4_MCS7 = 0x367, + RTW89_HW_RATE_V1_HE_NSS4_MCS8 = 0x368, + RTW89_HW_RATE_V1_HE_NSS4_MCS9 = 0x369, + RTW89_HW_RATE_V1_HE_NSS4_MCS10 = 0x36A, + RTW89_HW_RATE_V1_HE_NSS4_MCS11 = 0x36B, + RTW89_HW_RATE_V1_EHT_NSS1_MCS0 = 0x400, + RTW89_HW_RATE_V1_EHT_NSS1_MCS1 = 0x401, + RTW89_HW_RATE_V1_EHT_NSS1_MCS2 = 0x402, + RTW89_HW_RATE_V1_EHT_NSS1_MCS3 = 0x403, + RTW89_HW_RATE_V1_EHT_NSS1_MCS4 = 0x404, + RTW89_HW_RATE_V1_EHT_NSS1_MCS5 = 0x405, + RTW89_HW_RATE_V1_EHT_NSS1_MCS6 = 0x406, + RTW89_HW_RATE_V1_EHT_NSS1_MCS7 = 0x407, + RTW89_HW_RATE_V1_EHT_NSS1_MCS8 = 0x408, + RTW89_HW_RATE_V1_EHT_NSS1_MCS9 = 0x409, + RTW89_HW_RATE_V1_EHT_NSS1_MCS10 = 0x40A, + RTW89_HW_RATE_V1_EHT_NSS1_MCS11 = 0x40B, + RTW89_HW_RATE_V1_EHT_NSS1_MCS12 = 0x40C, + RTW89_HW_RATE_V1_EHT_NSS1_MCS13 = 0x40D, + RTW89_HW_RATE_V1_EHT_NSS1_MCS14 = 0x40E, + RTW89_HW_RATE_V1_EHT_NSS1_MCS15 = 0x40F, + RTW89_HW_RATE_V1_EHT_NSS2_MCS0 = 0x420, + RTW89_HW_RATE_V1_EHT_NSS2_MCS1 = 0x421, + RTW89_HW_RATE_V1_EHT_NSS2_MCS2 = 0x422, + RTW89_HW_RATE_V1_EHT_NSS2_MCS3 = 0x423, + RTW89_HW_RATE_V1_EHT_NSS2_MCS4 = 0x424, + RTW89_HW_RATE_V1_EHT_NSS2_MCS5 = 0x425, + RTW89_HW_RATE_V1_EHT_NSS2_MCS6 = 0x426, + RTW89_HW_RATE_V1_EHT_NSS2_MCS7 = 0x427, + RTW89_HW_RATE_V1_EHT_NSS2_MCS8 = 0x428, + RTW89_HW_RATE_V1_EHT_NSS2_MCS9 = 0x429, + RTW89_HW_RATE_V1_EHT_NSS2_MCS10 = 0x42A, + RTW89_HW_RATE_V1_EHT_NSS2_MCS11 = 0x42B, + RTW89_HW_RATE_V1_EHT_NSS2_MCS12 = 0x42C, + RTW89_HW_RATE_V1_EHT_NSS2_MCS13 = 0x42D, + RTW89_HW_RATE_V1_EHT_NSS3_MCS0 = 0x440, + RTW89_HW_RATE_V1_EHT_NSS3_MCS1 = 0x441, + RTW89_HW_RATE_V1_EHT_NSS3_MCS2 = 0x442, + RTW89_HW_RATE_V1_EHT_NSS3_MCS3 = 0x443, + RTW89_HW_RATE_V1_EHT_NSS3_MCS4 = 0x444, + RTW89_HW_RATE_V1_EHT_NSS3_MCS5 = 0x445, + RTW89_HW_RATE_V1_EHT_NSS3_MCS6 = 0x446, + RTW89_HW_RATE_V1_EHT_NSS3_MCS7 = 0x447, + RTW89_HW_RATE_V1_EHT_NSS3_MCS8 = 0x448, + RTW89_HW_RATE_V1_EHT_NSS3_MCS9 = 0x449, + RTW89_HW_RATE_V1_EHT_NSS3_MCS10 = 0x44A, + RTW89_HW_RATE_V1_EHT_NSS3_MCS11 = 0x44B, + RTW89_HW_RATE_V1_EHT_NSS3_MCS12 = 0x44C, + RTW89_HW_RATE_V1_EHT_NSS3_MCS13 = 0x44D, + RTW89_HW_RATE_V1_EHT_NSS4_MCS0 = 0x460, + RTW89_HW_RATE_V1_EHT_NSS4_MCS1 = 0x461, + RTW89_HW_RATE_V1_EHT_NSS4_MCS2 = 0x462, + RTW89_HW_RATE_V1_EHT_NSS4_MCS3 = 0x463, + RTW89_HW_RATE_V1_EHT_NSS4_MCS4 = 0x464, + RTW89_HW_RATE_V1_EHT_NSS4_MCS5 = 0x465, + RTW89_HW_RATE_V1_EHT_NSS4_MCS6 = 0x466, + RTW89_HW_RATE_V1_EHT_NSS4_MCS7 = 0x467, + RTW89_HW_RATE_V1_EHT_NSS4_MCS8 = 0x468, + RTW89_HW_RATE_V1_EHT_NSS4_MCS9 = 0x469, + RTW89_HW_RATE_V1_EHT_NSS4_MCS10 = 0x46A, + RTW89_HW_RATE_V1_EHT_NSS4_MCS11 = 0x46B, + RTW89_HW_RATE_V1_EHT_NSS4_MCS12 = 0x46C, + RTW89_HW_RATE_V1_EHT_NSS4_MCS13 = 0x46D, + RTW89_HW_RATE_NR, + RTW89_HW_RATE_INVAL, RTW89_HW_RATE_MASK_MOD = GENMASK(8, 7), RTW89_HW_RATE_MASK_VAL = GENMASK(6, 0), + RTW89_HW_RATE_V1_MASK_MOD = GENMASK(10, 8), + RTW89_HW_RATE_V1_MASK_VAL = GENMASK(7, 0), }; /* 2G channels, @@ -2504,9 +2703,10 @@ struct rtw89_ra_info { * Bit2 : HT * Bit3 : VHT * Bit4 : HE + * Bit5 : EHT */ - u8 mode_ctrl:5; - u8 bw_cap:2; + u8 mode_ctrl:6; + u8 bw_cap:3; /* enum rtw89_bandwidth */ u8 macid; u8 dcm_cap:1; u8 er_cap:1; @@ -3177,10 +3377,12 @@ struct rtw89_antdiv_info { struct rtw89_chip_info { enum rtw89_core_chip_id chip_id; + enum rtw89_chip_gen chip_gen; const struct rtw89_chip_ops *ops; const char *fw_basename; u8 fw_format_max; bool try_ce_fw; + u32 needed_fw_elms; u32 fifo_size; bool small_fifo_size; u32 dle_scc_rsvd_size; @@ -3347,6 +3549,9 @@ enum rtw89_fw_type { RTW89_FW_NORMAL = 1, RTW89_FW_WOWLAN = 3, RTW89_FW_NORMAL_CE = 5, + RTW89_FW_BBMCU0 = 64, + RTW89_FW_BBMCU1 = 65, + RTW89_FW_LOGFMT = 255, }; enum rtw89_fw_feature { @@ -3361,6 +3566,7 @@ enum rtw89_fw_feature { }; struct rtw89_fw_suit { + enum rtw89_fw_type type; const u8 *data; u32 size; u8 major_ver; @@ -3373,6 +3579,8 @@ struct rtw89_fw_suit { u16 build_hour; u16 build_min; u8 cmd_ver; + u8 hdr_ver; + u32 commitid; }; #define RTW89_FW_VER_CODE(major, minor, sub, idx) \ @@ -3397,6 +3605,22 @@ struct rtw89_fw_req_info { struct completion completion; }; +struct rtw89_fw_log { + struct rtw89_fw_suit suit; + bool enable; + u32 last_fmt_id; + u32 fmt_count; + const __le32 *fmt_ids; + const char *(*fmts)[]; +}; + +struct rtw89_fw_elm_info { + struct rtw89_phy_table *bb_tbl; + struct rtw89_phy_table *bb_gain; + struct rtw89_phy_table *rf_radio[RF_PATH_MAX]; + struct rtw89_phy_table *rf_nctl; +}; + struct rtw89_fw_info { struct rtw89_fw_req_info req; int fw_format; @@ -3406,8 +3630,11 @@ struct rtw89_fw_info { u8 c2h_counter; struct rtw89_fw_suit normal; struct rtw89_fw_suit wowlan; - bool fw_log_enable; + struct rtw89_fw_suit bbmcu0; + struct rtw89_fw_suit bbmcu1; + struct rtw89_fw_log log; u32 feature_map; + struct rtw89_fw_elm_info elm_info; }; #define RTW89_CHK_FW_FEATURE(_feat, _fw) \ @@ -4940,8 +5167,19 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev, { struct rtw89_fw_info *fw_info = &rtwdev->fw; - if (type == RTW89_FW_WOWLAN) + switch (type) { + case RTW89_FW_WOWLAN: return &fw_info->wowlan; + case RTW89_FW_LOGFMT: + return &fw_info->log.suit; + case RTW89_FW_BBMCU0: + return &fw_info->bbmcu0; + case RTW89_FW_BBMCU1: + return &fw_info->bbmcu1; + default: + break; + } + return &fw_info->normal; } diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index a4bbac916e22..f1e5ac4186c2 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -3193,29 +3193,33 @@ static ssize_t rtw89_debug_priv_btc_manual_set(struct file *filp, struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; struct rtw89_btc *btc = &rtwdev->btc; bool btc_manual; + int ret; - if (kstrtobool_from_user(user_buf, count, &btc_manual)) - goto out; + ret = kstrtobool_from_user(user_buf, count, &btc_manual); + if (ret) + return ret; btc->ctrl.manual = btc_manual; -out: + return count; } -static ssize_t rtw89_debug_fw_log_btc_manual_set(struct file *filp, - const char __user *user_buf, - size_t count, loff_t *loff) +static ssize_t rtw89_debug_fw_log_manual_set(struct file *filp, + const char __user *user_buf, + size_t count, loff_t *loff) { struct rtw89_debugfs_priv *debugfs_priv = filp->private_data; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; - struct rtw89_fw_info *fw_info = &rtwdev->fw; + struct rtw89_fw_log *log = &rtwdev->fw.log; bool fw_log_manual; if (kstrtobool_from_user(user_buf, count, &fw_log_manual)) goto out; mutex_lock(&rtwdev->mutex); - fw_info->fw_log_enable = fw_log_manual; + log->enable = fw_log_manual; + if (log->enable) + rtw89_fw_log_prepare(rtwdev); rtw89_fw_h2c_fw_log(rtwdev, fw_log_manual); mutex_unlock(&rtwdev->mutex); out: @@ -3323,20 +3327,26 @@ rtw89_debug_append_rx_rate(struct seq_file *m, struct rtw89_pkt_stat *pkt_stat, pkt_stat->rx_rate_cnt[first_rate + i]); } +#define FIRST_RATE_SAME(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_ ## rate} +#define FIRST_RATE_ENUM(rate) {RTW89_HW_RATE_ ## rate, RTW89_HW_RATE_V1_ ## rate} +#define FIRST_RATE_GEV1(rate) {RTW89_HW_RATE_INVAL, RTW89_HW_RATE_V1_ ## rate} + static const struct rtw89_rx_rate_cnt_info { - enum rtw89_hw_rate first_rate; + enum rtw89_hw_rate first_rate[RTW89_CHIP_GEN_NUM]; int len; int ext; const char *rate_mode; } rtw89_rx_rate_cnt_infos[] = { - {RTW89_HW_RATE_CCK1, 4, 0, "Legacy:"}, - {RTW89_HW_RATE_OFDM6, 8, 0, "OFDM:"}, - {RTW89_HW_RATE_MCS0, 8, 0, "HT 0:"}, - {RTW89_HW_RATE_MCS8, 8, 0, "HT 1:"}, - {RTW89_HW_RATE_VHT_NSS1_MCS0, 10, 2, "VHT 1SS:"}, - {RTW89_HW_RATE_VHT_NSS2_MCS0, 10, 2, "VHT 2SS:"}, - {RTW89_HW_RATE_HE_NSS1_MCS0, 12, 0, "HE 1SS:"}, - {RTW89_HW_RATE_HE_NSS2_MCS0, 12, 0, "HE 2ss:"}, + {FIRST_RATE_SAME(CCK1), 4, 0, "Legacy:"}, + {FIRST_RATE_SAME(OFDM6), 8, 0, "OFDM:"}, + {FIRST_RATE_ENUM(MCS0), 8, 0, "HT 0:"}, + {FIRST_RATE_ENUM(MCS8), 8, 0, "HT 1:"}, + {FIRST_RATE_ENUM(VHT_NSS1_MCS0), 10, 2, "VHT 1SS:"}, + {FIRST_RATE_ENUM(VHT_NSS2_MCS0), 10, 2, "VHT 2SS:"}, + {FIRST_RATE_ENUM(HE_NSS1_MCS0), 12, 0, "HE 1SS:"}, + {FIRST_RATE_ENUM(HE_NSS2_MCS0), 12, 0, "HE 2SS:"}, + {FIRST_RATE_GEV1(EHT_NSS1_MCS0), 14, 2, "EHT 1SS:"}, + {FIRST_RATE_GEV1(EHT_NSS2_MCS0), 14, 0, "EHT 2SS:"}, }; static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) @@ -3345,7 +3355,9 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; struct rtw89_traffic_stats *stats = &rtwdev->stats; struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.last_pkt_stat; + const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_rx_rate_cnt_info *info; + enum rtw89_hw_rate first_rate; int i; seq_printf(m, "TP TX: %u [%u] Mbps (lv: %d), RX: %u [%u] Mbps (lv: %d)\n", @@ -3357,15 +3369,20 @@ static int rtw89_debug_priv_phy_info_get(struct seq_file *m, void *v) stats->rx_avg_len); seq_puts(m, "RX count:\n"); + for (i = 0; i < ARRAY_SIZE(rtw89_rx_rate_cnt_infos); i++) { info = &rtw89_rx_rate_cnt_infos[i]; + first_rate = info->first_rate[chip->chip_gen]; + if (first_rate >= RTW89_HW_RATE_NR) + continue; + seq_printf(m, "%10s [", info->rate_mode); rtw89_debug_append_rx_rate(m, pkt_stat, - info->first_rate, info->len); + first_rate, info->len); if (info->ext) { seq_puts(m, "]["); rtw89_debug_append_rx_rate(m, pkt_stat, - info->first_rate + info->len, info->ext); + first_rate + info->len, info->ext); } seq_puts(m, "]\n"); } @@ -3569,7 +3586,7 @@ static struct rtw89_debugfs_priv rtw89_debug_priv_btc_manual = { }; static struct rtw89_debugfs_priv rtw89_debug_priv_fw_log_manual = { - .cb_write = rtw89_debug_fw_log_btc_manual_set, + .cb_write = rtw89_debug_fw_log_manual_set, }; static struct rtw89_debugfs_priv rtw89_debug_priv_phy_info = { diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 9637f5e48d84..2811a94b5f69 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -86,8 +86,8 @@ int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev) return 0; } -static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, - struct rtw89_fw_bin_info *info) +static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, + struct rtw89_fw_bin_info *info) { const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw; struct rtw89_fw_hdr_section_info *section_info; @@ -154,6 +154,94 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, return 0; } +static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, + struct rtw89_fw_bin_info *info) +{ + const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw; + struct rtw89_fw_hdr_section_info *section_info; + const struct rtw89_fw_dynhdr_hdr *fwdynhdr; + const struct rtw89_fw_hdr_section_v1 *section; + const u8 *fw_end = fw + len; + const u8 *bin; + u32 base_hdr_len; + u32 mssc_len = 0; + u32 i; + + info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_SEC_NUM); + base_hdr_len = struct_size(fw_hdr, sections, info->section_num); + info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR); + + if (info->dynamic_hdr_en) { + info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE); + info->dynamic_hdr_len = info->hdr_len - base_hdr_len; + fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len); + if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) { + rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n"); + return -EINVAL; + } + } else { + info->hdr_len = base_hdr_len; + info->dynamic_hdr_len = 0; + } + + bin = fw + info->hdr_len; + + /* jump to section header */ + section_info = info->section_info; + for (i = 0; i < info->section_num; i++) { + section = &fw_hdr->sections[i]; + section_info->type = + le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SECTIONTYPE); + if (section_info->type == FWDL_SECURITY_SECTION_TYPE) { + section_info->mssc = + le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC); + mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN; + } else { + section_info->mssc = 0; + } + + section_info->len = + le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SEC_SIZE); + if (le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_CHECKSUM)) + section_info->len += FWDL_SECTION_CHKSUM_LEN; + section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_REDL); + section_info->dladdr = + le32_get_bits(section->w0, FWSECTION_HDR_V1_W0_DL_ADDR); + section_info->addr = bin; + bin += section_info->len; + section_info++; + } + + if (fw_end != bin + mssc_len) { + rtw89_err(rtwdev, "[ERR]fw bin size\n"); + return -EINVAL; + } + + return 0; +} + +static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, + const struct rtw89_fw_suit *fw_suit, + struct rtw89_fw_bin_info *info) +{ + const u8 *fw = fw_suit->data; + u32 len = fw_suit->size; + + if (!fw || !len) { + rtw89_err(rtwdev, "fw type %d isn't recognized\n", fw_suit->type); + return -ENOENT; + } + + switch (fw_suit->hdr_ver) { + case 0: + return rtw89_fw_hdr_parser_v0(rtwdev, fw, len, info); + case 1: + return rtw89_fw_hdr_parser_v1(rtwdev, fw, len, info); + default: + return -ENOENT; + } +} + static int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, struct rtw89_fw_suit *fw_suit, bool nowarn) @@ -178,42 +266,110 @@ int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, for (i = 0; i < mfw_hdr->fw_nr; i++) { mfw_info = &mfw_hdr->info[i]; - if (mfw_info->cv != rtwdev->hal.cv || - mfw_info->type != type || - mfw_info->mp) - continue; - - fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); - fw_suit->size = le32_to_cpu(mfw_info->size); - return 0; + if (mfw_info->type == type) { + if (mfw_info->cv == rtwdev->hal.cv && !mfw_info->mp) + goto found; + if (type == RTW89_FW_LOGFMT) + goto found; + } } if (!nowarn) rtw89_err(rtwdev, "no suitable firmware found\n"); return -ENOENT; + +found: + fw_suit->data = mfw + le32_to_cpu(mfw_info->shift); + fw_suit->size = le32_to_cpu(mfw_info->size); + return 0; } -static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev, - enum rtw89_fw_type type, - struct rtw89_fw_suit *fw_suit) +static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev) { - const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data; + struct rtw89_fw_info *fw_info = &rtwdev->fw; + const struct firmware *firmware = fw_info->req.firmware; + const struct rtw89_mfw_hdr *mfw_hdr = + (const struct rtw89_mfw_hdr *)firmware->data; + const struct rtw89_mfw_info *mfw_info; + u32 size; + + if (mfw_hdr->sig != RTW89_MFW_SIG) { + rtw89_warn(rtwdev, "not mfw format\n"); + return 0; + } + + mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1]; + size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size); + + return size; +} +static void rtw89_fw_update_ver_v0(struct rtw89_dev *rtwdev, + struct rtw89_fw_suit *fw_suit, + const struct rtw89_fw_hdr *hdr) +{ fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION); fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION); fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION); fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX); + fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_W2_COMMITID); fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR); fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH); fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE); fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR); fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN); fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION); +} + +static void rtw89_fw_update_ver_v1(struct rtw89_dev *rtwdev, + struct rtw89_fw_suit *fw_suit, + const struct rtw89_fw_hdr_v1 *hdr) +{ + fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MAJOR_VERSION); + fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MINOR_VERSION); + fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBVERSION); + fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBINDEX); + fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_V1_W2_COMMITID); + fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_V1_W5_YEAR); + fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MONTH); + fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_V1_W4_DATE); + fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_V1_W4_HOUR); + fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MIN); + fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_V1_W3_CMD_VERSERION); +} + +static int rtw89_fw_update_ver(struct rtw89_dev *rtwdev, + enum rtw89_fw_type type, + struct rtw89_fw_suit *fw_suit) +{ + const struct rtw89_fw_hdr *v0 = (const struct rtw89_fw_hdr *)fw_suit->data; + const struct rtw89_fw_hdr_v1 *v1 = (const struct rtw89_fw_hdr_v1 *)fw_suit->data; + + if (type == RTW89_FW_LOGFMT) + return 0; + + fw_suit->type = type; + fw_suit->hdr_ver = le32_get_bits(v0->w3, FW_HDR_W3_HDR_VER); + + switch (fw_suit->hdr_ver) { + case 0: + rtw89_fw_update_ver_v0(rtwdev, fw_suit, v0); + break; + case 1: + rtw89_fw_update_ver_v1(rtwdev, fw_suit, v1); + break; + default: + rtw89_err(rtwdev, "Unknown firmware header version %u\n", + fw_suit->hdr_ver); + return -ENOENT; + } rtw89_info(rtwdev, - "Firmware version %u.%u.%u.%u, cmd version %u, type %u\n", + "Firmware version %u.%u.%u.%u (%08x), cmd version %u, type %u\n", fw_suit->major_ver, fw_suit->minor_ver, fw_suit->sub_ver, - fw_suit->sub_idex, fw_suit->cmd_ver, type); + fw_suit->sub_idex, fw_suit->commitid, fw_suit->cmd_ver, type); + + return 0; } static @@ -227,9 +383,22 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type, if (ret) return ret; - rtw89_fw_update_ver(rtwdev, type, fw_suit); + return rtw89_fw_update_ver(rtwdev, type, fw_suit); +} - return 0; +static +int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const void *data) +{ + enum rtw89_fw_type type = (enum rtw89_fw_type)data; + struct rtw89_fw_suit *fw_suit; + + fw_suit = rtw89_fw_suit_get(rtwdev, type); + fw_suit->data = elm->u.common.contents; + fw_suit->size = le32_to_cpu(elm->size); + + return rtw89_fw_update_ver(rtwdev, type, fw_suit); } #define __DEF_FW_FEAT_COND(__cond, __op) \ @@ -312,31 +481,17 @@ rtw89_early_fw_feature_recognize(struct device *device, struct rtw89_fw_info *early_fw, int *used_fw_format) { - union rtw89_compat_fw_hdr buf = {}; const struct firmware *firmware; - bool full_req = false; char fw_name[64]; int fw_format; u32 ver_code; int ret; - /* If SECURITY_LOADPIN_ENFORCE is enabled, reading partial files will - * be denied (-EPERM). Then, we don't get right firmware things as - * expected. So, in this case, we have to request full firmware here. - */ - if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE)) - full_req = true; - for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) { rtw89_fw_get_filename(fw_name, sizeof(fw_name), chip->fw_basename, fw_format); - if (full_req) - ret = request_firmware(&firmware, fw_name, device); - else - ret = request_partial_firmware_into_buf(&firmware, fw_name, - device, &buf, sizeof(buf), - 0); + ret = request_firmware(&firmware, fw_name, device); if (!ret) { dev_info(device, "loaded firmware %s\n", fw_name); *used_fw_format = fw_format; @@ -349,10 +504,7 @@ rtw89_early_fw_feature_recognize(struct device *device, return NULL; } - if (full_req) - ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data); - else - ver_code = rtw89_compat_fw_hdr_ver_code(&buf); + ver_code = rtw89_compat_fw_hdr_ver_code(firmware->data); if (!ver_code) goto out; @@ -360,11 +512,7 @@ rtw89_early_fw_feature_recognize(struct device *device, rtw89_fw_iterate_feature_cfg(early_fw, chip, ver_code); out: - if (full_req) - return firmware; - - release_firmware(firmware); - return NULL; + return firmware; } int rtw89_fw_recognize(struct rtw89_dev *rtwdev) @@ -386,6 +534,9 @@ normal_done: /* It still works if wowlan firmware isn't existing. */ __rtw89_fw_recognize(rtwdev, RTW89_FW_WOWLAN, false); + /* It still works if log format file isn't existing. */ + __rtw89_fw_recognize(rtwdev, RTW89_FW_LOGFMT, true); + rtw89_fw_recognize_features(rtwdev); rtw89_coex_recognize_ver(rtwdev); @@ -393,6 +544,153 @@ normal_done: return 0; } +static +int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, + const void *data) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + struct rtw89_phy_table *tbl; + struct rtw89_reg2_def *regs; + enum rtw89_rf_path rf_path; + u32 n_regs, i; + u8 idx; + + tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); + if (!tbl) + return -ENOMEM; + + switch (le32_to_cpu(elm->id)) { + case RTW89_FW_ELEMENT_ID_BB_REG: + elm_info->bb_tbl = tbl; + break; + case RTW89_FW_ELEMENT_ID_BB_GAIN: + elm_info->bb_gain = tbl; + break; + case RTW89_FW_ELEMENT_ID_RADIO_A: + case RTW89_FW_ELEMENT_ID_RADIO_B: + case RTW89_FW_ELEMENT_ID_RADIO_C: + case RTW89_FW_ELEMENT_ID_RADIO_D: + rf_path = (enum rtw89_rf_path)data; + idx = elm->u.reg2.idx; + + elm_info->rf_radio[idx] = tbl; + tbl->rf_path = rf_path; + tbl->config = rtw89_phy_config_rf_reg_v1; + break; + case RTW89_FW_ELEMENT_ID_RF_NCTL: + elm_info->rf_nctl = tbl; + break; + default: + kfree(tbl); + return -ENOENT; + } + + n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]); + regs = kcalloc(n_regs, sizeof(tbl->regs[0]), GFP_KERNEL); + if (!regs) + goto out; + + for (i = 0; i < n_regs; i++) { + regs[i].addr = le32_to_cpu(elm->u.reg2.regs[i].addr); + regs[i].data = le32_to_cpu(elm->u.reg2.regs[i].data); + } + + tbl->n_regs = n_regs; + tbl->regs = regs; + + return 0; + +out: + kfree(tbl); + return -ENOMEM; +} + +struct rtw89_fw_element_handler { + int (*fn)(struct rtw89_dev *rtwdev, + const struct rtw89_fw_element_hdr *elm, const void *data); + const void *data; + const char *name; +}; + +static const struct rtw89_fw_element_handler __fw_element_handlers[] = { + [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm, + (const void *)RTW89_FW_BBMCU0, NULL}, + [RTW89_FW_ELEMENT_ID_BBMCU1] = {__rtw89_fw_recognize_from_elm, + (const void *)RTW89_FW_BBMCU1, NULL}, + [RTW89_FW_ELEMENT_ID_BB_REG] = {rtw89_build_phy_tbl_from_elm, NULL, "BB"}, + [RTW89_FW_ELEMENT_ID_BB_GAIN] = {rtw89_build_phy_tbl_from_elm, NULL, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_A] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_A, "radio A"}, + [RTW89_FW_ELEMENT_ID_RADIO_B] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_B, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_C] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_C, NULL}, + [RTW89_FW_ELEMENT_ID_RADIO_D] = {rtw89_build_phy_tbl_from_elm, + (const void *)RF_PATH_D, NULL}, + [RTW89_FW_ELEMENT_ID_RF_NCTL] = {rtw89_build_phy_tbl_from_elm, NULL, "NCTL"}, +}; + +int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_info *fw_info = &rtwdev->fw; + const struct firmware *firmware = fw_info->req.firmware; + const struct rtw89_chip_info *chip = rtwdev->chip; + u32 unrecognized_elements = chip->needed_fw_elms; + const struct rtw89_fw_element_handler *handler; + const struct rtw89_fw_element_hdr *hdr; + u32 elm_size; + u32 elem_id; + u32 offset; + int ret; + + BUILD_BUG_ON(sizeof(chip->needed_fw_elms) * 8 < RTW89_FW_ELEMENT_ID_NUM); + + offset = rtw89_mfw_get_size(rtwdev); + offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); + if (offset == 0) + return -EINVAL; + + while (offset + sizeof(*hdr) < firmware->size) { + hdr = (const struct rtw89_fw_element_hdr *)(firmware->data + offset); + + elm_size = le32_to_cpu(hdr->size); + if (offset + elm_size >= firmware->size) { + rtw89_warn(rtwdev, "firmware element size exceeds\n"); + break; + } + + elem_id = le32_to_cpu(hdr->id); + if (elem_id >= ARRAY_SIZE(__fw_element_handlers)) + goto next; + + handler = &__fw_element_handlers[elem_id]; + if (!handler->fn) + goto next; + + ret = handler->fn(rtwdev, hdr, handler->data); + if (ret) + return ret; + + if (handler->name) + rtw89_info(rtwdev, "Firmware element %s version: %4ph\n", + handler->name, hdr->ver); + + unrecognized_elements &= ~BIT(elem_id); +next: + offset += sizeof(*hdr) + elm_size; + offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN); + } + + if (unrecognized_elements) { + rtw89_err(rtwdev, "Firmware elements 0x%08x are unrecognized\n", + unrecognized_elements); + return -ENOENT; + } + + return 0; +} + void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len) @@ -593,8 +891,6 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) struct rtw89_fw_info *fw_info = &rtwdev->fw; struct rtw89_fw_suit *fw_suit = rtw89_fw_suit_get(rtwdev, type); struct rtw89_fw_bin_info info; - const u8 *fw = fw_suit->data; - u32 len = fw_suit->size; u8 val; int ret; @@ -603,12 +899,7 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) if (ret) return ret; - if (!fw || !len) { - rtw89_err(rtwdev, "fw type %d isn't recognized\n", type); - return -ENOENT; - } - - ret = rtw89_fw_hdr_parser(rtwdev, fw, len, &info); + ret = rtw89_fw_hdr_parser(rtwdev, fw_suit, &info); if (ret) { rtw89_err(rtwdev, "parse fw header fail\n"); goto fwdl_err; @@ -622,13 +913,14 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type) goto fwdl_err; } - ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len - info.dynamic_hdr_len); + ret = rtw89_fw_download_hdr(rtwdev, fw_suit->data, info.hdr_len - + info.dynamic_hdr_len); if (ret) { ret = -EBUSY; goto fwdl_err; } - ret = rtw89_fw_download_main(rtwdev, fw, &info); + ret = rtw89_fw_download_main(rtwdev, fw_suit->data, &info); if (ret) { ret = -EBUSY; goto fwdl_err; @@ -695,6 +987,27 @@ void rtw89_load_firmware_work(struct work_struct *work) rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false); } +static void rtw89_free_phy_tbl_from_elm(struct rtw89_phy_table *tbl) +{ + if (!tbl) + return; + + kfree(tbl->regs); + kfree(tbl); +} + +static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; + int i; + + rtw89_free_phy_tbl_from_elm(elm_info->bb_tbl); + rtw89_free_phy_tbl_from_elm(elm_info->bb_gain); + for (i = 0; i < ARRAY_SIZE(elm_info->rf_radio); i++) + rtw89_free_phy_tbl_from_elm(elm_info->rf_radio[i]); + rtw89_free_phy_tbl_from_elm(elm_info->rf_nctl); +} + void rtw89_unload_firmware(struct rtw89_dev *rtwdev) { struct rtw89_fw_info *fw = &rtwdev->fw; @@ -709,6 +1022,151 @@ void rtw89_unload_firmware(struct rtw89_dev *rtwdev) */ fw->req.firmware = NULL; } + + kfree(fw->log.fmts); + rtw89_unload_firmware_elements(rtwdev); +} + +static u32 rtw89_fw_log_get_fmt_idx(struct rtw89_dev *rtwdev, u32 fmt_id) +{ + struct rtw89_fw_log *fw_log = &rtwdev->fw.log; + u32 i; + + if (fmt_id > fw_log->last_fmt_id) + return 0; + + for (i = 0; i < fw_log->fmt_count; i++) { + if (le32_to_cpu(fw_log->fmt_ids[i]) == fmt_id) + return i; + } + return 0; +} + +static int rtw89_fw_log_create_fmts_dict(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_log *log = &rtwdev->fw.log; + const struct rtw89_fw_logsuit_hdr *suit_hdr; + struct rtw89_fw_suit *suit = &log->suit; + const void *fmts_ptr, *fmts_end_ptr; + u32 fmt_count; + int i; + + suit_hdr = (const struct rtw89_fw_logsuit_hdr *)suit->data; + fmt_count = le32_to_cpu(suit_hdr->count); + log->fmt_ids = suit_hdr->ids; + fmts_ptr = &suit_hdr->ids[fmt_count]; + fmts_end_ptr = suit->data + suit->size; + log->fmts = kcalloc(fmt_count, sizeof(char *), GFP_KERNEL); + if (!log->fmts) + return -ENOMEM; + + for (i = 0; i < fmt_count; i++) { + fmts_ptr = memchr_inv(fmts_ptr, 0, fmts_end_ptr - fmts_ptr); + if (!fmts_ptr) + break; + + (*log->fmts)[i] = fmts_ptr; + log->last_fmt_id = le32_to_cpu(log->fmt_ids[i]); + log->fmt_count++; + fmts_ptr += strlen(fmts_ptr); + } + + return 0; +} + +int rtw89_fw_log_prepare(struct rtw89_dev *rtwdev) +{ + struct rtw89_fw_log *log = &rtwdev->fw.log; + struct rtw89_fw_suit *suit = &log->suit; + + if (!suit || !suit->data) { + rtw89_debug(rtwdev, RTW89_DBG_FW, "no log format file\n"); + return -EINVAL; + } + if (log->fmts) + return 0; + + return rtw89_fw_log_create_fmts_dict(rtwdev); +} + +static void rtw89_fw_log_dump_data(struct rtw89_dev *rtwdev, + const struct rtw89_fw_c2h_log_fmt *log_fmt, + u32 fmt_idx, u8 para_int, bool raw_data) +{ + const char *(*fmts)[] = rtwdev->fw.log.fmts; + char str_buf[RTW89_C2H_FW_LOG_STR_BUF_SIZE]; + u32 args[RTW89_C2H_FW_LOG_MAX_PARA_NUM] = {0}; + int i; + + if (log_fmt->argc > RTW89_C2H_FW_LOG_MAX_PARA_NUM) { + rtw89_warn(rtwdev, "C2H log: Arg count is unexpected %d\n", + log_fmt->argc); + return; + } + + if (para_int) + for (i = 0 ; i < log_fmt->argc; i++) + args[i] = le32_to_cpu(log_fmt->u.argv[i]); + + if (raw_data) { + if (para_int) + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, + "fw_enc(%d, %d, %d) %*ph", le32_to_cpu(log_fmt->fmt_id), + para_int, log_fmt->argc, (int)sizeof(args), args); + else + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, + "fw_enc(%d, %d, %d, %s)", le32_to_cpu(log_fmt->fmt_id), + para_int, log_fmt->argc, log_fmt->u.raw); + } else { + snprintf(str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, (*fmts)[fmt_idx], + args[0x0], args[0x1], args[0x2], args[0x3], args[0x4], + args[0x5], args[0x6], args[0x7], args[0x8], args[0x9], + args[0xa], args[0xb], args[0xc], args[0xd], args[0xe], + args[0xf]); + } + + rtw89_info(rtwdev, "C2H log: %s", str_buf); +} + +void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len) +{ + const struct rtw89_fw_c2h_log_fmt *log_fmt; + u8 para_int; + u32 fmt_idx; + + if (len < RTW89_C2H_HEADER_LEN) { + rtw89_err(rtwdev, "c2h log length is wrong!\n"); + return; + } + + buf += RTW89_C2H_HEADER_LEN; + len -= RTW89_C2H_HEADER_LEN; + log_fmt = (const struct rtw89_fw_c2h_log_fmt *)buf; + + if (len < RTW89_C2H_FW_FORMATTED_LOG_MIN_LEN) + goto plain_log; + + if (log_fmt->signature != cpu_to_le16(RTW89_C2H_FW_LOG_SIGNATURE)) + goto plain_log; + + if (!rtwdev->fw.log.fmts) + return; + + para_int = u8_get_bits(log_fmt->feature, RTW89_C2H_FW_LOG_FEATURE_PARA_INT); + fmt_idx = rtw89_fw_log_get_fmt_idx(rtwdev, le32_to_cpu(log_fmt->fmt_id)); + + if (!para_int && log_fmt->argc != 0 && fmt_idx != 0) + rtw89_info(rtwdev, "C2H log: %s%s", + (*rtwdev->fw.log.fmts)[fmt_idx], log_fmt->u.raw); + else if (fmt_idx != 0 && para_int) + rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, false); + else + rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, true); + return; + +plain_log: + rtw89_info(rtwdev, "C2H log: %*s", len, buf); + } #define H2C_CAM_LEN 60 @@ -922,7 +1380,7 @@ int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable) } skb_put(skb, H2C_LOG_CFG_LEN); - SET_LOG_CFG_LEVEL(skb->data, RTW89_FW_LOG_LEVEL_SER); + SET_LOG_CFG_LEVEL(skb->data, RTW89_FW_LOG_LEVEL_LOUD); SET_LOG_CFG_PATH(skb->data, BIT(RTW89_FW_LOG_LEVEL_C2H)); SET_LOG_CFG_COMP(skb->data, comp); SET_LOG_CFG_COMP_EXT(skb->data, 0); @@ -1903,61 +2361,76 @@ fail: return ret; } -#define H2C_RA_LEN 16 int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi) { + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_h2c_ra_v1 *h2c_v1; + struct rtw89_h2c_ra *h2c; + u32 len = sizeof(*h2c); + bool format_v1 = false; struct sk_buff *skb; - u8 *cmd; int ret; - skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_RA_LEN); + if (chip->chip_gen == RTW89_CHIP_BE) { + len = sizeof(*h2c_v1); + format_v1 = true; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); if (!skb) { rtw89_err(rtwdev, "failed to alloc skb for h2c join\n"); return -ENOMEM; } - skb_put(skb, H2C_RA_LEN); - cmd = skb->data; + skb_put(skb, len); + h2c = (struct rtw89_h2c_ra *)skb->data; rtw89_debug(rtwdev, RTW89_DBG_RA, "ra cmd msk: %llx ", ra->ra_mask); - RTW89_SET_FWCMD_RA_MODE(cmd, ra->mode_ctrl); - RTW89_SET_FWCMD_RA_BW_CAP(cmd, ra->bw_cap); - RTW89_SET_FWCMD_RA_MACID(cmd, ra->macid); - RTW89_SET_FWCMD_RA_DCM(cmd, ra->dcm_cap); - RTW89_SET_FWCMD_RA_ER(cmd, ra->er_cap); - RTW89_SET_FWCMD_RA_INIT_RATE_LV(cmd, ra->init_rate_lv); - RTW89_SET_FWCMD_RA_UPD_ALL(cmd, ra->upd_all); - RTW89_SET_FWCMD_RA_SGI(cmd, ra->en_sgi); - RTW89_SET_FWCMD_RA_LDPC(cmd, ra->ldpc_cap); - RTW89_SET_FWCMD_RA_STBC(cmd, ra->stbc_cap); - RTW89_SET_FWCMD_RA_SS_NUM(cmd, ra->ss_num); - RTW89_SET_FWCMD_RA_GILTF(cmd, ra->giltf); - RTW89_SET_FWCMD_RA_UPD_BW_NSS_MASK(cmd, ra->upd_bw_nss_mask); - RTW89_SET_FWCMD_RA_UPD_MASK(cmd, ra->upd_mask); - RTW89_SET_FWCMD_RA_MASK_0(cmd, FIELD_GET(MASKBYTE0, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_1(cmd, FIELD_GET(MASKBYTE1, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_2(cmd, FIELD_GET(MASKBYTE2, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_3(cmd, FIELD_GET(MASKBYTE3, ra->ra_mask)); - RTW89_SET_FWCMD_RA_MASK_4(cmd, FIELD_GET(MASKBYTE4, ra->ra_mask)); - RTW89_SET_FWCMD_RA_FIX_GILTF_EN(cmd, ra->fix_giltf_en); - RTW89_SET_FWCMD_RA_FIX_GILTF(cmd, ra->fix_giltf); - - if (csi) { - RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(cmd, 1); - RTW89_SET_FWCMD_RA_BAND_NUM(cmd, ra->band_num); - RTW89_SET_FWCMD_RA_CR_TBL_SEL(cmd, ra->cr_tbl_sel); - RTW89_SET_FWCMD_RA_FIXED_CSI_RATE_EN(cmd, ra->fixed_csi_rate_en); - RTW89_SET_FWCMD_RA_RA_CSI_RATE_EN(cmd, ra->ra_csi_rate_en); - RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(cmd, ra->csi_mcs_ss_idx); - RTW89_SET_FWCMD_RA_FIXED_CSI_MODE(cmd, ra->csi_mode); - RTW89_SET_FWCMD_RA_FIXED_CSI_GI_LTF(cmd, ra->csi_gi_ltf); - RTW89_SET_FWCMD_RA_FIXED_CSI_BW(cmd, ra->csi_bw); - } - + h2c->w0 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_W0_MODE) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_W0_BW_CAP) | + le32_encode_bits(ra->macid, RTW89_H2C_RA_W0_MACID) | + le32_encode_bits(ra->dcm_cap, RTW89_H2C_RA_W0_DCM) | + le32_encode_bits(ra->er_cap, RTW89_H2C_RA_W0_ER) | + le32_encode_bits(ra->init_rate_lv, RTW89_H2C_RA_W0_INIT_RATE_LV) | + le32_encode_bits(ra->upd_all, RTW89_H2C_RA_W0_UPD_ALL) | + le32_encode_bits(ra->en_sgi, RTW89_H2C_RA_W0_SGI) | + le32_encode_bits(ra->ldpc_cap, RTW89_H2C_RA_W0_LDPC) | + le32_encode_bits(ra->stbc_cap, RTW89_H2C_RA_W0_STBC) | + le32_encode_bits(ra->ss_num, RTW89_H2C_RA_W0_SS_NUM) | + le32_encode_bits(ra->giltf, RTW89_H2C_RA_W0_GILTF) | + le32_encode_bits(ra->upd_bw_nss_mask, RTW89_H2C_RA_W0_UPD_BW_NSS_MASK) | + le32_encode_bits(ra->upd_mask, RTW89_H2C_RA_W0_UPD_MASK); + h2c->w1 = le32_encode_bits(ra->ra_mask, RTW89_H2C_RA_W1_RAMASK_LO32); + h2c->w2 = le32_encode_bits(ra->ra_mask >> 32, RTW89_H2C_RA_W2_RAMASK_HI32); + h2c->w3 = le32_encode_bits(ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) | + le32_encode_bits(ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF); + + if (!format_v1) + goto csi; + + h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c; + h2c_v1->w4 = le32_encode_bits(ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) | + le32_encode_bits(ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT); + +csi: + if (!csi) + goto done; + + h2c->w2 |= le32_encode_bits(1, RTW89_H2C_RA_W2_BFEE_CSI_CTL); + h2c->w3 |= le32_encode_bits(ra->band_num, RTW89_H2C_RA_W3_BAND_NUM) | + le32_encode_bits(ra->cr_tbl_sel, RTW89_H2C_RA_W3_CR_TBL_SEL) | + le32_encode_bits(ra->fixed_csi_rate_en, RTW89_H2C_RA_W3_FIXED_CSI_RATE_EN) | + le32_encode_bits(ra->ra_csi_rate_en, RTW89_H2C_RA_W3_RA_CSI_RATE_EN) | + le32_encode_bits(ra->csi_mcs_ss_idx, RTW89_H2C_RA_W3_FIXED_CSI_MCS_SS_IDX) | + le32_encode_bits(ra->csi_mode, RTW89_H2C_RA_W3_FIXED_CSI_MODE) | + le32_encode_bits(ra->csi_gi_ltf, RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF) | + le32_encode_bits(ra->csi_bw, RTW89_H2C_RA_W3_FIXED_CSI_BW); + +done: rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RA, H2C_FUNC_OUTSRC_RA_MACIDCFG, 0, 0, - H2C_RA_LEN); + len); ret = rtw89_h2c_tx(rtwdev, skb, false); if (ret) { @@ -2815,12 +3288,13 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev) static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h) { + const struct rtw89_c2h_hdr *hdr = (const struct rtw89_c2h_hdr *)c2h->data; struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(c2h); - attr->category = RTW89_GET_C2H_CATEGORY(c2h->data); - attr->class = RTW89_GET_C2H_CLASS(c2h->data); - attr->func = RTW89_GET_C2H_FUNC(c2h->data); - attr->len = RTW89_GET_C2H_LEN(c2h->data); + attr->category = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_CATEGORY); + attr->class = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_CLASS); + attr->func = le32_get_bits(hdr->w0, RTW89_C2H_HDR_W0_FUNC); + attr->len = le32_get_bits(hdr->w1, RTW89_C2H_HDR_W1_LEN); } static bool rtw89_fw_c2h_chk_atomic(struct rtw89_dev *rtwdev, diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 45f927dc212e..775f4e8fbda4 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -291,160 +291,52 @@ struct rtw89_pktofld_info { bool cancel; }; -static inline void RTW89_SET_FWCMD_RA_IS_DIS(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(0)); -} - -static inline void RTW89_SET_FWCMD_RA_MODE(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(5, 1)); -} - -static inline void RTW89_SET_FWCMD_RA_BW_CAP(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(7, 6)); -} - -static inline void RTW89_SET_FWCMD_RA_MACID(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(15, 8)); -} - -static inline void RTW89_SET_FWCMD_RA_DCM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(16)); -} - -static inline void RTW89_SET_FWCMD_RA_ER(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(17)); -} - -static inline void RTW89_SET_FWCMD_RA_INIT_RATE_LV(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(19, 18)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_ALL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(20)); -} - -static inline void RTW89_SET_FWCMD_RA_SGI(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(21)); -} - -static inline void RTW89_SET_FWCMD_RA_LDPC(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(22)); -} - -static inline void RTW89_SET_FWCMD_RA_STBC(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(23)); -} - -static inline void RTW89_SET_FWCMD_RA_SS_NUM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(26, 24)); -} - -static inline void RTW89_SET_FWCMD_RA_GILTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, GENMASK(29, 27)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_BW_NSS_MASK(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(30)); -} - -static inline void RTW89_SET_FWCMD_RA_UPD_MASK(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x00, val, BIT(31)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_0(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_1(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(15, 8)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_2(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(23, 16)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_3(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x01, val, GENMASK(31, 24)); -} - -static inline void RTW89_SET_FWCMD_RA_MASK_4(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x02, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_BFEE_CSI_CTL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x02, val, BIT(31)); -} - -static inline void RTW89_SET_FWCMD_RA_BAND_NUM(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(7, 0)); -} - -static inline void RTW89_SET_FWCMD_RA_RA_CSI_RATE_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(8)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_RATE_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(9)); -} - -static inline void RTW89_SET_FWCMD_RA_CR_TBL_SEL(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(10)); -} - -static inline void RTW89_SET_FWCMD_RA_FIX_GILTF_EN(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, BIT(11)); -} - -static inline void RTW89_SET_FWCMD_RA_FIX_GILTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(14, 12)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MCS_SS_IDX(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(23, 16)); -} - -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_MODE(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(25, 24)); -} +struct rtw89_h2c_ra { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; +} __packed; -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_GI_LTF(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(28, 26)); -} +#define RTW89_H2C_RA_W0_IS_DIS BIT(0) +#define RTW89_H2C_RA_W0_MODE GENMASK(5, 1) +#define RTW89_H2C_RA_W0_BW_CAP GENMASK(7, 6) +#define RTW89_H2C_RA_W0_MACID GENMASK(15, 8) +#define RTW89_H2C_RA_W0_DCM BIT(16) +#define RTW89_H2C_RA_W0_ER BIT(17) +#define RTW89_H2C_RA_W0_INIT_RATE_LV GENMASK(19, 18) +#define RTW89_H2C_RA_W0_UPD_ALL BIT(20) +#define RTW89_H2C_RA_W0_SGI BIT(21) +#define RTW89_H2C_RA_W0_LDPC BIT(22) +#define RTW89_H2C_RA_W0_STBC BIT(23) +#define RTW89_H2C_RA_W0_SS_NUM GENMASK(26, 24) +#define RTW89_H2C_RA_W0_GILTF GENMASK(29, 27) +#define RTW89_H2C_RA_W0_UPD_BW_NSS_MASK BIT(30) +#define RTW89_H2C_RA_W0_UPD_MASK BIT(31) +#define RTW89_H2C_RA_W1_RAMASK_LO32 GENMASK(31, 0) +#define RTW89_H2C_RA_W2_RAMASK_HI32 GENMASK(30, 0) +#define RTW89_H2C_RA_W2_BFEE_CSI_CTL BIT(31) +#define RTW89_H2C_RA_W3_BAND_NUM GENMASK(7, 0) +#define RTW89_H2C_RA_W3_RA_CSI_RATE_EN BIT(8) +#define RTW89_H2C_RA_W3_FIXED_CSI_RATE_EN BIT(9) +#define RTW89_H2C_RA_W3_CR_TBL_SEL BIT(10) +#define RTW89_H2C_RA_W3_FIX_GILTF_EN BIT(11) +#define RTW89_H2C_RA_W3_FIX_GILTF GENMASK(14, 12) +#define RTW89_H2C_RA_W3_FIXED_CSI_MCS_SS_IDX GENMASK(23, 16) +#define RTW89_H2C_RA_W3_FIXED_CSI_MODE GENMASK(25, 24) +#define RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF GENMASK(28, 26) +#define RTW89_H2C_RA_W3_FIXED_CSI_BW GENMASK(31, 29) + +struct rtw89_h2c_ra_v1 { + struct rtw89_h2c_ra v0; + __le32 w4; + __le32 w5; +} __packed; -static inline void RTW89_SET_FWCMD_RA_FIXED_CSI_BW(void *cmd, u32 val) -{ - le32p_replace_bits((__le32 *)(cmd) + 0x03, val, GENMASK(31, 29)); -} +#define RTW89_H2C_RA_V1_W4_MODE_EHT GENMASK(6, 0) +#define RTW89_H2C_RA_V1_W4_BW_EHT GENMASK(10, 8) +#define RTW89_H2C_RA_V1_W4_RAMASK_UHL16 GENMASK(31, 16) +#define RTW89_H2C_RA_V1_W5_RAMASK_UHH16 GENMASK(15, 0) static inline void RTW89_SET_FWCMD_SEC_IDX(void *cmd, u32 val) { @@ -571,7 +463,9 @@ struct rtw89_fw_hdr { #define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8) #define FW_HDR_W1_SUBVERSION GENMASK(23, 16) #define FW_HDR_W1_SUBINDEX GENMASK(31, 24) +#define FW_HDR_W2_COMMITID GENMASK(31, 0) #define FW_HDR_W3_LEN GENMASK(23, 16) +#define FW_HDR_W3_HDR_VER GENMASK(31, 24) #define FW_HDR_W4_MONTH GENMASK(7, 0) #define FW_HDR_W4_DATE GENMASK(15, 8) #define FW_HDR_W4_HOUR GENMASK(23, 16) @@ -581,6 +475,54 @@ struct rtw89_fw_hdr { #define FW_HDR_W7_DYN_HDR BIT(16) #define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24) +struct rtw89_fw_hdr_section_v1 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; +} __packed; + +#define FWSECTION_HDR_V1_W0_DL_ADDR GENMASK(31, 0) +#define FWSECTION_HDR_V1_W1_METADATA GENMASK(31, 24) +#define FWSECTION_HDR_V1_W1_SECTIONTYPE GENMASK(27, 24) +#define FWSECTION_HDR_V1_W1_SEC_SIZE GENMASK(23, 0) +#define FWSECTION_HDR_V1_W1_CHECKSUM BIT(28) +#define FWSECTION_HDR_V1_W1_REDL BIT(29) +#define FWSECTION_HDR_V1_W2_MSSC GENMASK(7, 0) +#define FWSECTION_HDR_V1_W2_BBMCU_IDX GENMASK(27, 24) + +struct rtw89_fw_hdr_v1 { + __le32 w0; + __le32 w1; + __le32 w2; + __le32 w3; + __le32 w4; + __le32 w5; + __le32 w6; + __le32 w7; + __le32 w8; + __le32 w9; + __le32 w10; + __le32 w11; + struct rtw89_fw_hdr_section_v1 sections[]; +} __packed; + +#define FW_HDR_V1_W1_MAJOR_VERSION GENMASK(7, 0) +#define FW_HDR_V1_W1_MINOR_VERSION GENMASK(15, 8) +#define FW_HDR_V1_W1_SUBVERSION GENMASK(23, 16) +#define FW_HDR_V1_W1_SUBINDEX GENMASK(31, 24) +#define FW_HDR_V1_W2_COMMITID GENMASK(31, 0) +#define FW_HDR_V1_W3_CMD_VERSERION GENMASK(23, 16) +#define FW_HDR_V1_W3_HDR_VER GENMASK(31, 24) +#define FW_HDR_V1_W4_MONTH GENMASK(7, 0) +#define FW_HDR_V1_W4_DATE GENMASK(15, 8) +#define FW_HDR_V1_W4_HOUR GENMASK(23, 16) +#define FW_HDR_V1_W4_MIN GENMASK(31, 24) +#define FW_HDR_V1_W5_YEAR GENMASK(15, 0) +#define FW_HDR_V1_W5_HDR_SIZE GENMASK(31, 16) +#define FW_HDR_V1_W6_SEC_NUM GENMASK(15, 8) +#define FW_HDR_V1_W7_DYN_HDR BIT(16) + static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) { le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0)); @@ -3209,14 +3151,15 @@ inline void RTW89_SET_FWCMD_MCC_SET_DURATION_DURATION_Y(void *cmd, u32 val) #define RTW89_C2H_HEADER_LEN 8 -#define RTW89_GET_C2H_CATEGORY(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(1, 0)) -#define RTW89_GET_C2H_CLASS(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(7, 2)) -#define RTW89_GET_C2H_FUNC(c2h) \ - le32_get_bits(*((const __le32 *)c2h), GENMASK(15, 8)) -#define RTW89_GET_C2H_LEN(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 1), GENMASK(13, 0)) +struct rtw89_c2h_hdr { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_C2H_HDR_W0_CATEGORY GENMASK(1, 0) +#define RTW89_C2H_HDR_W0_CLASS GENMASK(7, 2) +#define RTW89_C2H_HDR_W0_FUNC GENMASK(15, 8) +#define RTW89_C2H_HDR_W1_LEN GENMASK(13, 0) struct rtw89_fw_c2h_attr { u8 category; @@ -3232,9 +3175,6 @@ static inline struct rtw89_fw_c2h_attr *RTW89_SKB_C2H_CB(struct sk_buff *skb) return (struct rtw89_fw_c2h_attr *)skb->cb; } -#define RTW89_GET_C2H_LOG_SRT_PRT(c2h) (char *)((__le32 *)(c2h) + 2) -#define RTW89_GET_C2H_LOG_LEN(len) ((len) - RTW89_C2H_HEADER_LEN) - struct rtw89_c2h_done_ack { __le32 w0; __le32 w1; @@ -3256,6 +3196,26 @@ struct rtw89_c2h_done_ack { #define RTW89_GET_MAC_C2H_REV_ACK_H2C_SEQ(c2h) \ le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16)) +struct rtw89_fw_c2h_log_fmt { + __le16 signature; + u8 feature; + u8 syntax; + __le32 fmt_id; + u8 file_num; + __le16 line_num; + u8 argc; + union { + DECLARE_FLEX_ARRAY(u8, raw); + DECLARE_FLEX_ARRAY(__le32, argv); + } __packed u; +} __packed; + +#define RTW89_C2H_FW_FORMATTED_LOG_MIN_LEN 11 +#define RTW89_C2H_FW_LOG_FEATURE_PARA_INT BIT(2) +#define RTW89_C2H_FW_LOG_MAX_PARA_NUM 16 +#define RTW89_C2H_FW_LOG_SIGNATURE 0xA5A5 +#define RTW89_C2H_FW_LOG_STR_BUF_SIZE 512 + struct rtw89_c2h_mac_bcnfltr_rpt { __le32 w0; __le32 w1; @@ -3267,24 +3227,32 @@ struct rtw89_c2h_mac_bcnfltr_rpt { #define RTW89_C2H_MAC_BCNFLTR_RPT_W2_EVENT GENMASK(11, 10) #define RTW89_C2H_MAC_BCNFLTR_RPT_W2_MA GENMASK(23, 16) -#define RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(15, 0)) -#define RTW89_GET_PHY_C2H_RA_RPT_RETRY_RATIO(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(23, 16)) -#define RTW89_GET_PHY_C2H_RA_RPT_MCSNSS(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(6, 0)) -#define RTW89_GET_PHY_C2H_RA_RPT_MD_SEL(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(9, 8)) -#define RTW89_GET_PHY_C2H_RA_RPT_GILTF(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(12, 10)) -#define RTW89_GET_PHY_C2H_RA_RPT_BW(c2h) \ - le32_get_bits(*((const __le32 *)(c2h) + 3), GENMASK(14, 13)) - -/* VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS - * HT-new: [6:5]: NA, [4:0]: MCS +struct rtw89_c2h_ra_rpt { + struct rtw89_c2h_hdr hdr; + __le32 w2; + __le32 w3; +} __packed; + +#define RTW89_C2H_RA_RPT_W2_MACID GENMASK(15, 0) +#define RTW89_C2H_RA_RPT_W2_RETRY_RATIO GENMASK(23, 16) +#define RTW89_C2H_RA_RPT_W2_MCSNSS_B7 BIT(31) +#define RTW89_C2H_RA_RPT_W3_MCSNSS GENMASK(6, 0) +#define RTW89_C2H_RA_RPT_W3_MD_SEL GENMASK(9, 8) +#define RTW89_C2H_RA_RPT_W3_GILTF GENMASK(12, 10) +#define RTW89_C2H_RA_RPT_W3_BW GENMASK(14, 13) +#define RTW89_C2H_RA_RPT_W3_MD_SEL_B2 BIT(15) +#define RTW89_C2H_RA_RPT_W3_BW_B2 BIT(16) + +/* For WiFi 6 chips: + * VHT, HE, HT-old: [6:4]: NSS, [3:0]: MCS + * HT-new: [6:5]: NA, [4:0]: MCS + * For WiFi 7 chips (V1): + * HT, VHT, HE, EHT: [7:5]: NSS, [4:0]: MCS */ #define RTW89_RA_RATE_MASK_NSS GENMASK(6, 4) #define RTW89_RA_RATE_MASK_MCS GENMASK(3, 0) +#define RTW89_RA_RATE_MASK_NSS_V1 GENMASK(7, 5) +#define RTW89_RA_RATE_MASK_MCS_V1 GENMASK(4, 0) #define RTW89_RA_RATE_MASK_HT_MCS GENMASK(4, 0) #define RTW89_MK_HT_RATE(nss, mcs) (FIELD_PREP(GENMASK(4, 3), nss) | \ FIELD_PREP(GENMASK(2, 0), mcs)) @@ -3426,6 +3394,51 @@ struct rtw89_mfw_hdr { struct rtw89_mfw_info info[]; } __packed; +struct rtw89_fw_logsuit_hdr { + __le32 rsvd; + __le32 count; + __le32 ids[]; +} __packed; + +#define RTW89_FW_ELEMENT_ALIGN 16 + +enum rtw89_fw_element_id { + RTW89_FW_ELEMENT_ID_BBMCU0 = 0, + RTW89_FW_ELEMENT_ID_BBMCU1 = 1, + RTW89_FW_ELEMENT_ID_BB_REG = 2, + RTW89_FW_ELEMENT_ID_BB_GAIN = 3, + RTW89_FW_ELEMENT_ID_RADIO_A = 4, + RTW89_FW_ELEMENT_ID_RADIO_B = 5, + RTW89_FW_ELEMENT_ID_RADIO_C = 6, + RTW89_FW_ELEMENT_ID_RADIO_D = 7, + RTW89_FW_ELEMENT_ID_RF_NCTL = 8, + + RTW89_FW_ELEMENT_ID_NUM, +}; + +struct rtw89_fw_element_hdr { + __le32 id; /* enum rtw89_fw_element_id */ + __le32 size; /* exclude header size */ + u8 ver[4]; + __le32 rsvd0; + __le32 rsvd1; + __le32 rsvd2; + union { + struct { + u8 priv[8]; + u8 contents[]; + } __packed common; + struct { + u8 idx; + u8 rsvd[7]; + struct { + __le32 addr; + __le32 data; + } __packed regs[]; + } __packed reg2; + } __packed u; +} __packed; + struct fwcmd_hdr { __le32 hdr0; __le32 hdr1; @@ -3607,6 +3620,7 @@ struct rtw89_fw_h2c_rf_get_mccch { int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev); int rtw89_fw_recognize(struct rtw89_dev *rtwdev); +int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev); const struct firmware * rtw89_early_fw_feature_recognize(struct device *device, const struct rtw89_chip_info *chip, @@ -3616,6 +3630,8 @@ int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type); void rtw89_load_firmware_work(struct work_struct *work); void rtw89_unload_firmware(struct rtw89_dev *rtwdev); int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev); +int rtw89_fw_log_prepare(struct rtw89_dev *rtwdev); +void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len); void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb, u8 type, u8 cat, u8 class, u8 func, bool rack, bool dack, u32 len); diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index c93e6250cb8b..cebefa3b1db3 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -4437,8 +4437,7 @@ rtw89_mac_c2h_done_ack(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, u32 le static void rtw89_mac_c2h_log(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len) { - rtw89_info(rtwdev, "%*s", RTW89_GET_C2H_LOG_LEN(len), - RTW89_GET_C2H_LOG_SRT_PRT(c2h->data)); + rtw89_fw_log_dump(rtwdev, c2h->data, len); } static void diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index fb15c852fdd4..c40c4f8c1271 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -444,6 +444,12 @@ static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next, return true; } +#define RTW89_HW_RATE_BY_CHIP_GEN(rate) \ + { \ + [RTW89_CHIP_AX] = RTW89_HW_RATE_ ## rate, \ + [RTW89_CHIP_BE] = RTW89_HW_RATE_V1_ ## rate, \ + } + void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) @@ -452,39 +458,46 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; struct rtw89_phy_rate_pattern next_pattern = {0}; const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); - static const u16 hw_rate_he[] = {RTW89_HW_RATE_HE_NSS1_MCS0, - RTW89_HW_RATE_HE_NSS2_MCS0, - RTW89_HW_RATE_HE_NSS3_MCS0, - RTW89_HW_RATE_HE_NSS4_MCS0}; - static const u16 hw_rate_vht[] = {RTW89_HW_RATE_VHT_NSS1_MCS0, - RTW89_HW_RATE_VHT_NSS2_MCS0, - RTW89_HW_RATE_VHT_NSS3_MCS0, - RTW89_HW_RATE_VHT_NSS4_MCS0}; - static const u16 hw_rate_ht[] = {RTW89_HW_RATE_MCS0, - RTW89_HW_RATE_MCS8, - RTW89_HW_RATE_MCS16, - RTW89_HW_RATE_MCS24}; + static const u16 hw_rate_he[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS2_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS3_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(HE_NSS4_MCS0), + }; + static const u16 hw_rate_vht[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS1_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS2_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS3_MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(VHT_NSS4_MCS0), + }; + static const u16 hw_rate_ht[][RTW89_CHIP_GEN_NUM] = { + RTW89_HW_RATE_BY_CHIP_GEN(MCS0), + RTW89_HW_RATE_BY_CHIP_GEN(MCS8), + RTW89_HW_RATE_BY_CHIP_GEN(MCS16), + RTW89_HW_RATE_BY_CHIP_GEN(MCS24), + }; u8 band = chan->band_type; enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); + enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; u8 tx_nss = rtwdev->hal.tx_nss; u8 i; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_he[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_he[i][chip_gen], RA_MASK_HE_RATES, RTW89_RA_MODE_HE, mask->control[nl_band].he_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_vht[i][chip_gen], RA_MASK_VHT_RATES, RTW89_RA_MODE_VHT, mask->control[nl_band].vht_mcs[i], 0, true)) goto out; for (i = 0; i < tx_nss; i++) - if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i], + if (!__check_rate_pattern(&next_pattern, hw_rate_ht[i][chip_gen], RA_MASK_HT_RATES, RTW89_RA_MODE_HT, mask->control[nl_band].ht_mcs[i], 0, true)) @@ -1342,12 +1355,16 @@ static void rtw89_phy_init_reg(struct rtw89_dev *rtwdev, void rtw89_phy_init_bb_reg(struct rtw89_dev *rtwdev) { + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; - const struct rtw89_phy_table *bb_table = chip->bb_table; - const struct rtw89_phy_table *bb_gain_table = chip->bb_gain_table; + const struct rtw89_phy_table *bb_table; + const struct rtw89_phy_table *bb_gain_table; + bb_table = elm_info->bb_tbl ? elm_info->bb_tbl : chip->bb_table; rtw89_phy_init_reg(rtwdev, bb_table, rtw89_phy_config_bb_reg, NULL); rtw89_chip_init_txpwr_unit(rtwdev, RTW89_PHY_0); + + bb_gain_table = elm_info->bb_gain ? elm_info->bb_gain : chip->bb_gain_table; if (bb_gain_table) rtw89_phy_init_reg(rtwdev, bb_gain_table, rtw89_phy_config_bb_gain, NULL); @@ -1365,6 +1382,7 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) { void (*config)(struct rtw89_dev *rtwdev, const struct rtw89_reg2_def *reg, enum rtw89_rf_path rf_path, void *data); + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_phy_table *rf_table; struct rtw89_fw_h2c_rf_reg_info *rf_reg_info; @@ -1375,7 +1393,8 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) return; for (path = RF_PATH_A; path < chip->rf_path_num; path++) { - rf_table = chip->rf_table[path]; + rf_table = elm_info->rf_radio[path] ? + elm_info->rf_radio[path] : chip->rf_table[path]; rf_reg_info->rf_path = rf_table->rf_path; if (noio) config = rtw89_phy_config_rf_reg_noio; @@ -1392,6 +1411,7 @@ void rtw89_phy_init_rf_reg(struct rtw89_dev *rtwdev, bool noio) static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) { + struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info; const struct rtw89_chip_info *chip = rtwdev->chip; const struct rtw89_phy_table *nctl_table; u32 val; @@ -1414,7 +1434,7 @@ static void rtw89_phy_init_rf_nctl(struct rtw89_dev *rtwdev) if (ret) rtw89_err(rtwdev, "failed to poll nctl block\n"); - nctl_table = chip->nctl_table; + nctl_table = elm_info->rf_nctl ? elm_info->rf_nctl : chip->nctl_table; rtw89_phy_init_reg(rtwdev, nctl_table, rtw89_phy_config_bb_reg, NULL); if (chip->nctl_post_table) @@ -2231,21 +2251,34 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) struct rtw89_phy_iter_ra_data *ra_data = (struct rtw89_phy_iter_ra_data *)data; struct rtw89_dev *rtwdev = ra_data->rtwdev; struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + const struct rtw89_c2h_ra_rpt *c2h = + (const struct rtw89_c2h_ra_rpt *)ra_data->c2h->data; struct rtw89_ra_report *ra_report = &rtwsta->ra_report; - struct sk_buff *c2h = ra_data->c2h; + const struct rtw89_chip_info *chip = rtwdev->chip; + bool format_v1 = chip->chip_gen == RTW89_CHIP_BE; u8 mode, rate, bw, giltf, mac_id; u16 legacy_bitrate; bool valid; u8 mcs = 0; + u8 t; - mac_id = RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h->data); + mac_id = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MACID); if (mac_id != rtwsta->mac_id) return; - rate = RTW89_GET_PHY_C2H_RA_RPT_MCSNSS(c2h->data); - bw = RTW89_GET_PHY_C2H_RA_RPT_BW(c2h->data); - giltf = RTW89_GET_PHY_C2H_RA_RPT_GILTF(c2h->data); - mode = RTW89_GET_PHY_C2H_RA_RPT_MD_SEL(c2h->data); + rate = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MCSNSS); + bw = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW); + giltf = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_GILTF); + mode = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL); + + if (format_v1) { + t = le32_get_bits(c2h->w2, RTW89_C2H_RA_RPT_W2_MCSNSS_B7); + rate |= u8_encode_bits(t, BIT(7)); + t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_BW_B2); + bw |= u8_encode_bits(t, BIT(2)); + t = le32_get_bits(c2h->w3, RTW89_C2H_RA_RPT_W3_MD_SEL_B2); + mode |= u8_encode_bits(t, BIT(2)); + } if (mode == RTW89_RA_RPT_MODE_LEGACY) { valid = rtw89_ra_report_to_bitrate(rtwdev, rate, &legacy_bitrate); @@ -2273,16 +2306,24 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) break; case RTW89_RA_RPT_MODE_VHT: ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; - ra_report->txrate.mcs = FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate); - ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1; + ra_report->txrate.mcs = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) : + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS); + ra_report->txrate.nss = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 : + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1; if (giltf) ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; mcs = ra_report->txrate.mcs; break; case RTW89_RA_RPT_MODE_HE: ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS; - ra_report->txrate.mcs = FIELD_GET(RTW89_RA_RATE_MASK_MCS, rate); - ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1; + ra_report->txrate.mcs = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS_V1) : + u8_get_bits(rate, RTW89_RA_RATE_MASK_MCS); + ra_report->txrate.nss = format_v1 ? + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS_V1) + 1 : + u8_get_bits(rate, RTW89_RA_RATE_MASK_NSS) + 1; if (giltf == RTW89_GILTF_2XHE08 || giltf == RTW89_GILTF_1XHE08) ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_0_8; else if (giltf == RTW89_GILTF_2XHE16 || giltf == RTW89_GILTF_1XHE16) @@ -2295,8 +2336,11 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta) ra_report->txrate.bw = rtw89_hw_to_rate_info_bw(bw); ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate); - ra_report->hw_rate = FIELD_PREP(RTW89_HW_RATE_MASK_MOD, mode) | - FIELD_PREP(RTW89_HW_RATE_MASK_VAL, rate); + ra_report->hw_rate = format_v1 ? + u16_encode_bits(mode, RTW89_HW_RATE_V1_MASK_MOD) | + u16_encode_bits(rate, RTW89_HW_RATE_V1_MASK_VAL) : + u16_encode_bits(mode, RTW89_HW_RATE_MASK_MOD) | + u16_encode_bits(rate, RTW89_HW_RATE_MASK_VAL); ra_report->might_fallback_legacy = mcs <= 2; sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report); rtwsta->max_agg_wait = sta->deflink.agg.max_rc_amsdu_len / 1500 - 1; @@ -2977,7 +3021,7 @@ static void rtw89_phy_antdiv_sts_instance_add(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu, struct rtw89_antdiv_stats *stats) { - if (GET_DATA_RATE_MODE(phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) { + if (rtw89_get_data_rate_mode(rtwdev, phy_ppdu->rate) == DATA_RATE_MODE_NON_HT) { if (phy_ppdu->rate < RTW89_HW_RATE_OFDM6) { ewma_rssi_add(&stats->cck_rssi_avg, phy_ppdu->rssi_avg); stats->pkt_cnt_cck++; diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index c3ffcb645ebf..b5740639e267 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -2334,10 +2334,12 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8851b = { const struct rtw89_chip_info rtw8851b_chip_info = { .chip_id = RTL8851B, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8851b_chip_ops, .fw_basename = RTW8851B_FW_BASENAME, .fw_format_max = RTW8851B_FW_FORMAT_MAX, .try_ce_fw = true, + .needed_fw_elms = 0, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 6257414a3b4b..41f05276406d 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2071,10 +2071,12 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { const struct rtw89_chip_info rtw8852a_chip_info = { .chip_id = RTL8852A, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852a_chip_ops, .fw_basename = RTW8852A_FW_BASENAME, .fw_format_max = RTW8852A_FW_FORMAT_MAX, .try_ce_fw = false, + .needed_fw_elms = 0, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 718f993da62a..eb2210cb7e09 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2503,10 +2503,12 @@ static const struct wiphy_wowlan_support rtw_wowlan_stub_8852b = { const struct rtw89_chip_info rtw8852b_chip_info = { .chip_id = RTL8852B, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852b_chip_ops, .fw_basename = RTW8852B_FW_BASENAME, .fw_format_max = RTW8852B_FW_FORMAT_MAX, .try_ce_fw = true, + .needed_fw_elms = 0, .fifo_size = 196608, .small_fifo_size = true, .dle_scc_rsvd_size = 98304, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index 9c7c9812d4f4..b1af72fbf085 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2802,10 +2802,12 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { const struct rtw89_chip_info rtw8852c_chip_info = { .chip_id = RTL8852C, + .chip_gen = RTW89_CHIP_AX, .ops = &rtw8852c_chip_ops, .fw_basename = RTW8852C_FW_BASENAME, .fw_format_max = RTW8852C_FW_FORMAT_MAX, .try_ce_fw = false, + .needed_fw_elms = 0, .fifo_size = 458752, .small_fifo_size = false, .dle_scc_rsvd_size = 0, diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index ec96da36eacc..02cff0f7d86b 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -8,19 +8,56 @@ #include "debug.h" #define DATA_RATE_MODE_CTRL_MASK GENMASK(8, 7) +#define DATA_RATE_MODE_CTRL_MASK_V1 GENMASK(10, 8) #define DATA_RATE_NOT_HT_IDX_MASK GENMASK(3, 0) #define DATA_RATE_MODE_NON_HT 0x0 #define DATA_RATE_HT_IDX_MASK GENMASK(4, 0) +#define DATA_RATE_HT_IDX_MASK_V1 GENMASK(4, 0) #define DATA_RATE_MODE_HT 0x1 #define DATA_RATE_VHT_HE_NSS_MASK GENMASK(6, 4) #define DATA_RATE_VHT_HE_IDX_MASK GENMASK(3, 0) +#define DATA_RATE_NSS_MASK_V1 GENMASK(7, 5) +#define DATA_RATE_MCS_MASK_V1 GENMASK(4, 0) #define DATA_RATE_MODE_VHT 0x2 #define DATA_RATE_MODE_HE 0x3 -#define GET_DATA_RATE_MODE(r) FIELD_GET(DATA_RATE_MODE_CTRL_MASK, r) -#define GET_DATA_RATE_NOT_HT_IDX(r) FIELD_GET(DATA_RATE_NOT_HT_IDX_MASK, r) -#define GET_DATA_RATE_HT_IDX(r) FIELD_GET(DATA_RATE_HT_IDX_MASK, r) -#define GET_DATA_RATE_VHT_HE_IDX(r) FIELD_GET(DATA_RATE_VHT_HE_IDX_MASK, r) -#define GET_DATA_RATE_NSS(r) FIELD_GET(DATA_RATE_VHT_HE_NSS_MASK, r) +#define DATA_RATE_MODE_EHT 0x4 + +static inline u8 rtw89_get_data_rate_mode(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_MODE_CTRL_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_MODE_CTRL_MASK); +} + +static inline u8 rtw89_get_data_not_ht_idx(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + return u16_get_bits(hw_rate, DATA_RATE_NOT_HT_IDX_MASK); +} + +static inline u8 rtw89_get_data_ht_mcs(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_HT_IDX_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_HT_IDX_MASK); +} + +static inline u8 rtw89_get_data_mcs(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_MCS_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_VHT_HE_IDX_MASK); +} + +static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate) +{ + if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) + return u16_get_bits(hw_rate, DATA_RATE_NSS_MASK_V1); + + return u16_get_bits(hw_rate, DATA_RATE_VHT_HE_NSS_MASK); +} /* TX WD BODY DWORD 0 */ #define RTW89_TXWD_BODY0_WP_OFFSET GENMASK(31, 24) diff --git a/drivers/net/wireless/silabs/wfx/bus_sdio.c b/drivers/net/wireless/silabs/wfx/bus_sdio.c index 51a0d58a9070..909d5f346a01 100644 --- a/drivers/net/wireless/silabs/wfx/bus_sdio.c +++ b/drivers/net/wireless/silabs/wfx/bus_sdio.c @@ -10,7 +10,7 @@ #include <linux/mmc/sdio_func.h> #include <linux/mmc/card.h> #include <linux/interrupt.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_irq.h> #include <linux/irq.h> #include <linux/align.h> diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c index 850c26bc9524..8505d84eeed6 100644 --- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c @@ -1006,7 +1006,7 @@ resubmit: * @usb: the zd1211rw-private USB structure * @skb: a &struct sk_buff pointer * - * This function tranmits a frame to the device. It doesn't wait for + * This function transmits a frame to the device. It doesn't wait for * completion. The frame must contain the control set and have all the * control set information available. * |