wireless-next patches for v6.6

The first pull request for v6.6 and only driver patches this time.
 Nothing special really standing out, it has been quiet most likely due
 to vacations.
 
 Major changes:
 
 rtl8xxxu
 
 * enable AP mode for: RTL8192FU, RTL8710BU (RTL8188GU), RTL8192EU and RTL8723BU
 
 mwifiex
 
 * allow moving to a different namespace
 
 mt76
 
 * preparation for mt7925 support
 
 * mt7981 support
 
 ath12k
 
 * Extremely High Throughput (EHT) PHY support for Wi-Fi 7
 -----BEGIN PGP SIGNATURE-----
 
 iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmTM6gkRHGt2YWxvQGtl
 cm5lbC5vcmcACgkQbhckVSbrbZuuAggAjRQi7Vjsfr+GlZ+g/y/vf+ircw8YjKgy
 wJqnQ0fnJ4rpyxqVFjMr+ocuOrdBufTSs/W4fqOBbbg9oimsgg+vxIQA8GmQIUVQ
 ZQVWQHVqPLQ6NVp/YZJnt9seeCewGHW6UZxG9k0MqR1RJn+KinmSjWKRo1D56niL
 rJQAK0FWrVqkj5nt9lKRJLMGxX0k/ftrdZgHanUOVCNYi9Ukx0jXSbqSMftTk7xz
 r3jtuY5zAV+2GXoMIbW4ogBks4Yx06XzVycByzj+dYt5E3VBdDFX+mXlsw9vnjbv
 whVzsuMnYBu6CCFlKDPdGsmrzZA0GrLCRZE9uw7yhwZZ+qKkQZ8kNw==
 =5r3T
 -----END PGP SIGNATURE-----

Merge tag 'wireless-next-2023-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Kalle Valo says:

====================
wireless-next patches for v6.6

The first pull request for v6.6 and only driver patches this time.
Nothing special really standing out, it has been quiet most likely due
to vacations.

Major changes:

rtl8xxxu
 - enable AP mode for: RTL8192FU, RTL8710BU (RTL8188GU),
   RTL8192EU and RTL8723BU

mwifiex
 - allow moving to a different namespace

mt76
 - preparation for mt7925 support
 - mt7981 support

ath12k
 - Extremely High Throughput (EHT) PHY support for Wi-Fi 7

* tag 'wireless-next-2023-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (172 commits)
  wifi: rtw89: return failure if needed firmware elements are not recognized
  wifi: rtw89: add to parse firmware elements of BB and RF tables
  wifi: rtw89: introduce infrastructure of firmware elements
  wifi: rtw89: add firmware suit for BB MCU 0/1
  wifi: rtw89: add firmware parser for v1 format
  wifi: rtw89: introduce v1 format of firmware header
  wifi: rtw89: support firmware log with formatted text
  wifi: rtw89: recognize log format from firmware file
  wifi: ath12k: avoid deadlock by change ieee80211_queue_work for regd_update_work
  wifi: ath12k: add handler for scan event WMI_SCAN_EVENT_DEQUEUED
  wifi: ath12k: relax list iteration in ath12k_mac_vif_unref()
  wifi: ath12k: configure puncturing bitmap
  wifi: ath12k: parse WMI service ready ext2 event
  wifi: ath12k: add MLO header in peer association
  wifi: ath12k: peer assoc for 320 MHz
  wifi: ath12k: add WMI support for EHT peer
  wifi: ath12k: prepare EHT peer assoc parameters
  wifi: ath12k: add EHT PHY modes
  wifi: ath12k: propagate EHT capabilities to userspace
  wifi: ath12k: WMI support to process EHT capabilities
  ...
====================

Link: https://lore.kernel.org/r/87msz7j942.fsf@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2023-08-04 18:34:25 -07:00
commit 81083076a0
165 changed files with 8291 additions and 5775 deletions

View File

@ -28,6 +28,7 @@ properties:
- mediatek,mt76
- mediatek,mt7628-wmac
- mediatek,mt7622-wmac
- mediatek,mt7981-wmac
- mediatek,mt7986-wmac
reg:
@ -71,6 +72,14 @@ properties:
ieee80211-freq-limit: true
nvmem-cells:
items:
- description: NVMEM cell with EEPROM
nvmem-cell-names:
items:
- const: eeprom
mediatek,eeprom-data:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
@ -84,6 +93,7 @@ properties:
- description: offset containing EEPROM data
description:
Phandle to a MTD partition + offset containing EEPROM data
deprecated: true
big-endian:
$ref: /schemas/types.yaml#/definitions/flag
@ -258,7 +268,8 @@ examples:
interrupt-parent = <&cpuintc>;
interrupts = <6>;
mediatek,mtd-eeprom = <&factory 0x0>;
nvmem-cells = <&eeprom>;
nvmem-cell-names = "eeprom";
};
- |

View File

@ -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"

View File

@ -14,6 +14,7 @@
#include "ahb.h"
#include "debug.h"
#include "hif.h"
#include "qmi.h"
#include <linux/remoteproc.h>
#include "pcic.h"
#include <linux/soc/qcom/smem.h>
@ -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;

View File

@ -86,7 +86,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -167,7 +168,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -248,7 +250,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -332,8 +335,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = false,
.idle_ps = false,
.supports_sta_ps = false,
.cold_boot_calib = false,
.cbcal_restart_fw = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fw_mem_mode = 2,
.num_vdevs = 8,
.num_peers = 128,
@ -413,7 +417,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -495,7 +500,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = false,
.coldboot_cal_mm = false,
.coldboot_cal_ftm = false,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -578,7 +584,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_shadow_regs = true,
.idle_ps = true,
.supports_sta_ps = true,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = false,
.fw_mem_mode = 0,
.num_vdevs = 16 + 1,
@ -667,7 +674,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_suspend = false,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.single_pdev_only = false,
.cold_boot_calib = true,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
.cbcal_restart_fw = true,
.fix_l1ss = true,
.supports_dynamic_smps_6ghz = false,
@ -749,6 +757,18 @@ void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
ath11k_fw_stats_bcn_free(&stats->bcn);
}
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab)
{
if (!ath11k_cold_boot_cal)
return false;
if (ath11k_ftm_mode)
return ab->hw_params.coldboot_cal_ftm;
else
return ab->hw_params.coldboot_cal_mm;
}
int ath11k_core_suspend(struct ath11k_base *ab)
{
int ret;

View File

@ -1186,6 +1186,7 @@ void ath11k_core_halt(struct ath11k *ar);
int ath11k_core_resume(struct ath11k_base *ab);
int ath11k_core_suspend(struct ath11k_base *ab);
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *filename);

View File

@ -2408,7 +2408,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_status->freq = center_freq;
} else if (channel_num >= 1 && channel_num <= 14) {
rx_status->band = NL80211_BAND_2GHZ;
} else if (channel_num >= 36 && channel_num <= 173) {
} else if (channel_num >= 36 && channel_num <= 177) {
rx_status->band = NL80211_BAND_5GHZ;
} else {
spin_lock_bh(&ar->data_lock);

View File

@ -187,7 +187,8 @@ struct ath11k_hw_params {
bool supports_shadow_regs;
bool idle_ps;
bool supports_sta_ps;
bool cold_boot_calib;
bool coldboot_cal_mm;
bool coldboot_cal_ftm;
bool cbcal_restart_fw;
int fw_mem_mode;
u32 num_vdevs;

View File

@ -8255,7 +8255,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
const struct cfg80211_bitrate_mask *mask)
{
bool he_fixed_rate = false, vht_fixed_rate = false;
struct ath11k_peer *peer, *tmp;
struct ath11k_peer *peer;
const u16 *vht_mcs_mask, *he_mcs_mask;
struct ieee80211_link_sta *deflink;
u8 vht_nss, he_nss;
@ -8278,7 +8278,7 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
rcu_read_lock();
spin_lock_bh(&ar->ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
list_for_each_entry(peer, &ar->ab->peers, list) {
if (peer->sta) {
deflink = &peer->sta->deflink;

View File

@ -15,6 +15,7 @@
#include "mhi.h"
#include "debug.h"
#include "pcic.h"
#include "qmi.h"
#define ATH11K_PCI_BAR_NUM 0
#define ATH11K_PCI_DMA_MASK 32
@ -897,6 +898,7 @@ unsupported_wcn6855_soc:
ath11k_err(ab, "failed to init core: %d\n", ret);
goto err_irq_affinity_cleanup;
}
ath11k_qmi_fwreset_from_cold_boot(ab);
return 0;
err_irq_affinity_cleanup:

View File

@ -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,

View File

@ -37,7 +37,7 @@
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
#define ATH11K_FIRMWARE_MODE_OFF 4
#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ)
#define ATH11K_COLD_BOOT_FW_RESET_DELAY (60 * HZ)
#define ATH11K_QMI_DEVICE_BAR_SIZE 0x200000
@ -519,5 +519,6 @@ void ath11k_qmi_msg_recv_work(struct work_struct *work);
void ath11k_qmi_deinit_service(struct ath11k_base *ab);
int ath11k_qmi_init_service(struct ath11k_base *ab);
void ath11k_qmi_free_resource(struct ath11k_base *ab);
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab);
#endif

View File

@ -238,6 +238,7 @@ struct ath12k_vif {
u32 key_cipher;
u8 tx_encap_type;
u8 vdev_stats_id;
u32 punct_bitmap;
};
struct ath12k_vif_iter {
@ -580,6 +581,14 @@ struct ath12k_band_cap {
u32 he_cap_phy_info[PSOC_HOST_MAX_PHY_SIZE];
struct ath12k_wmi_ppe_threshold_arg he_ppet;
u16 he_6ghz_capa;
u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
u32 eht_cap_phy_info[WMI_MAX_EHTCAP_PHY_SIZE];
u32 eht_mcs_20_only;
u32 eht_mcs_80;
u32 eht_mcs_160;
u32 eht_mcs_320;
struct ath12k_wmi_ppe_threshold_arg eht_ppet;
u32 eht_cap_info_internal;
};
struct ath12k_pdev_cap {
@ -614,6 +623,12 @@ struct ath12k_pdev {
struct mlo_timestamp timestamp;
};
struct ath12k_fw_pdev {
u32 pdev_id;
u32 phy_id;
u32 supported_bands;
};
struct ath12k_board_data {
const struct firmware *fw;
const void *data;
@ -669,7 +684,26 @@ struct ath12k_base {
struct mutex core_lock;
/* Protects data like peers */
spinlock_t base_lock;
/* Single pdev device (struct ath12k_hw_params::single_pdev_only):
*
* Firmware maintains data for all bands but advertises a single
* phy to the host which is stored as a single element in this
* array.
*
* Other devices:
*
* This array will contain as many elements as the number of
* radios.
*/
struct ath12k_pdev pdevs[MAX_RADIOS];
/* struct ath12k_hw_params::single_pdev_only devices use this to
* store phy specific data
*/
struct ath12k_fw_pdev fw_pdev[MAX_RADIOS];
u8 fw_pdev_count;
struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS];
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map;

View File

@ -2539,7 +2539,7 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
struct ath12k_skb_rxcb *rxcb;
struct sk_buff *msdu;
struct ath12k *ar;
u8 mac_id;
u8 mac_id, pdev_id;
int ret;
if (skb_queue_empty(msdu_list))
@ -2550,8 +2550,9 @@ static void ath12k_dp_rx_process_received_packets(struct ath12k_base *ab,
while ((msdu = __skb_dequeue(msdu_list))) {
rxcb = ATH12K_SKB_RXCB(msdu);
mac_id = rxcb->mac_id;
ar = ab->pdevs[mac_id].ar;
if (!rcu_dereference(ab->pdevs_active[mac_id])) {
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!rcu_dereference(ab->pdevs_active[pdev_id])) {
dev_kfree_skb_any(msdu);
continue;
}
@ -3385,6 +3386,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
dma_addr_t paddr;
bool is_frag;
bool drop = false;
int pdev_id;
tot_n_bufs_reaped = 0;
quota = budget;
@ -3440,7 +3442,8 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
mac_id = le32_get_bits(reo_desc->info0,
HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
ar = ab->pdevs[mac_id].ar;
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (!ath12k_dp_process_rx_err_buf(ar, reo_desc, drop,
msdu_cookies[i]))

View File

@ -347,6 +347,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
{
struct ath12k *ar;
struct ath12k_skb_cb *skb_cb;
u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
skb_cb = ATH12K_SKB_CB(msdu);
@ -357,7 +358,7 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,
dev_kfree_skb_any(msdu);
ar = ab->pdevs[mac_id].ar;
ar = ab->pdevs[pdev_id].ar;
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);
}
@ -536,7 +537,7 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
struct hal_tx_status ts = { 0 };
struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id];
struct hal_wbm_release_ring *desc;
u8 mac_id;
u8 mac_id, pdev_id;
u64 desc_va;
spin_lock_bh(&status_ring->lock);
@ -605,7 +606,8 @@ void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id)
continue;
}
ar = ab->pdevs[mac_id].ar;
pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);
ar = ab->pdevs[pdev_id].ar;
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
wake_up(&ar->dp.tx_empty_waitq);

View File

@ -182,32 +182,35 @@ ath12k_phymodes[NUM_NL80211_BANDS][ATH12K_CHAN_WIDTH_NUM] = {
[NL80211_BAND_2GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20_2G,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20_2G,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40_2G,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80_2G,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20_2G,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20_2G,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40_2G,
[NL80211_CHAN_WIDTH_80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_80P80] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_160] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_320] = MODE_UNKNOWN,
},
[NL80211_BAND_5GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
[NL80211_BAND_6GHZ] = {
[NL80211_CHAN_WIDTH_5] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_10] = MODE_UNKNOWN,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_20] = MODE_11AX_HE20,
[NL80211_CHAN_WIDTH_40] = MODE_11AX_HE40,
[NL80211_CHAN_WIDTH_80] = MODE_11AX_HE80,
[NL80211_CHAN_WIDTH_160] = MODE_11AX_HE160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11AX_HE80_80,
[NL80211_CHAN_WIDTH_20_NOHT] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_20] = MODE_11BE_EHT20,
[NL80211_CHAN_WIDTH_40] = MODE_11BE_EHT40,
[NL80211_CHAN_WIDTH_80] = MODE_11BE_EHT80,
[NL80211_CHAN_WIDTH_160] = MODE_11BE_EHT160,
[NL80211_CHAN_WIDTH_80P80] = MODE_11BE_EHT80_80,
[NL80211_CHAN_WIDTH_320] = MODE_11BE_EHT320,
},
};
@ -292,6 +295,24 @@ static const char *ath12k_mac_phymode_str(enum wmi_phy_mode mode)
return "11ax-he40-2g";
case MODE_11AX_HE80_2G:
return "11ax-he80-2g";
case MODE_11BE_EHT20:
return "11be-eht20";
case MODE_11BE_EHT40:
return "11be-eht40";
case MODE_11BE_EHT80:
return "11be-eht80";
case MODE_11BE_EHT80_80:
return "11be-eht80+80";
case MODE_11BE_EHT160:
return "11be-eht160";
case MODE_11BE_EHT160_160:
return "11be-eht160+160";
case MODE_11BE_EHT320:
return "11be-eht320";
case MODE_11BE_EHT20_2G:
return "11be-eht20-2g";
case MODE_11BE_EHT40_2G:
return "11be-eht40-2g";
case MODE_UNKNOWN:
/* skip */
break;
@ -821,6 +842,7 @@ static int ath12k_mac_monitor_vdev_start(struct ath12k *ar, int vdev_id,
arg.pref_tx_streams = ar->num_tx_chains;
arg.pref_rx_streams = ar->num_rx_chains;
arg.punct_bitmap = 0xFFFFFFFF;
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
@ -1637,9 +1659,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
sizeof(arg->peer_he_cap_macinfo));
sizeof(he_cap->he_cap_elem.mac_cap_info));
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
sizeof(arg->peer_he_cap_phyinfo));
sizeof(he_cap->he_cap_elem.phy_cap_info));
arg->peer_he_ops = vif->bss_conf.he_oper.params;
/* the top most byte is used to indicate BSS color info */
@ -1929,6 +1951,41 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
return MODE_UNKNOWN;
}
static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
struct ieee80211_sta *sta)
{
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)
if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
return MODE_11BE_EHT320;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11BE_EHT160;
if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
return MODE_11BE_EHT80_80;
ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]);
return MODE_11BE_EHT160;
}
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
return MODE_11BE_EHT80;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
return MODE_11BE_EHT40;
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
return MODE_11BE_EHT20;
return MODE_UNKNOWN;
}
static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -1950,7 +2007,12 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
switch (band) {
case NL80211_BAND_2GHZ:
if (sta->deflink.he_cap.has_he) {
if (sta->deflink.eht_cap.has_eht) {
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11BE_EHT40_2G;
else
phymode = MODE_11BE_EHT20_2G;
} else if (sta->deflink.he_cap.has_he) {
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
phymode = MODE_11AX_HE80_2G;
else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
@ -1977,8 +2039,10 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
break;
case NL80211_BAND_5GHZ:
case NL80211_BAND_6GHZ:
/* Check HE first */
if (sta->deflink.he_cap.has_he) {
/* Check EHT first */
if (sta->deflink.eht_cap.has_eht) {
phymode = ath12k_mac_get_phymode_eht(ar, sta);
} else if (sta->deflink.he_cap.has_he) {
phymode = ath12k_mac_get_phymode_he(ar, sta);
} else if (sta->deflink.vht_cap.vht_supported &&
!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
@ -2004,6 +2068,152 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
WARN_ON(phymode == MODE_UNKNOWN);
}
static void ath12k_mac_set_eht_mcs(u8 rx_tx_mcs7, u8 rx_tx_mcs9,
u8 rx_tx_mcs11, u8 rx_tx_mcs13,
u32 *rx_mcs, u32 *tx_mcs)
{
*rx_mcs = 0;
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_0_7);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_8_9);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_10_11);
u32p_replace_bits(rx_mcs,
u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_RX),
WMI_EHT_MCS_NSS_12_13);
*tx_mcs = 0;
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs7, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_0_7);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs9, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_8_9);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs11, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_10_11);
u32p_replace_bits(tx_mcs,
u8_get_bits(rx_tx_mcs13, IEEE80211_EHT_MCS_NSS_TX),
WMI_EHT_MCS_NSS_12_13);
}
static void ath12k_mac_set_eht_ppe_threshold(const u8 *ppe_thres,
struct ath12k_wmi_ppe_threshold_arg *ppet)
{
u32 bit_pos = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE, val;
u8 nss, ru, i;
u8 ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
ppet->numss_m1 = u8_get_bits(ppe_thres[0], IEEE80211_EHT_PPE_THRES_NSS_MASK);
ppet->ru_bit_mask = u16_get_bits(get_unaligned_le16(ppe_thres),
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
for (nss = 0; nss <= ppet->numss_m1; nss++) {
for (ru = 0;
ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
ru++) {
if ((ppet->ru_bit_mask & BIT(ru)) == 0)
continue;
val = 0;
for (i = 0; i < ppet_bit_len_per_ru; i++) {
val |= (((ppe_thres[bit_pos / 8] >>
(bit_pos % 8)) & 0x1) << i);
bit_pos++;
}
ppet->ppet16_ppet8_ru3_ru0[nss] |=
(val << (ru * ppet_bit_len_per_ru));
}
}
}
static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
struct ath12k_vif *arvif = (struct ath12k_vif *)vif->drv_priv;
u32 *rx_mcs, *tx_mcs;
if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
return;
arg->eht_flag = true;
if ((eht_cap->eht_cap_elem.phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT) &&
eht_cap->eht_ppe_thres[0] != 0)
ath12k_mac_set_eht_ppe_threshold(eht_cap->eht_ppe_thres,
&arg->peer_eht_ppet);
memcpy(arg->peer_eht_cap_mac, eht_cap->eht_cap_elem.mac_cap_info,
sizeof(eht_cap->eht_cap_elem.mac_cap_info));
memcpy(arg->peer_eht_cap_phy, eht_cap->eht_cap_elem.phy_cap_info,
sizeof(eht_cap->eht_cap_elem.phy_cap_info));
rx_mcs = arg->peer_eht_rx_mcs_set;
tx_mcs = arg->peer_eht_tx_mcs_set;
switch (sta->deflink.bandwidth) {
case IEEE80211_STA_RX_BW_320:
bw = &eht_cap->eht_mcs_nss_supp.bw._320;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_320]);
arg->peer_eht_mcs_count++;
fallthrough;
case IEEE80211_STA_RX_BW_160:
bw = &eht_cap->eht_mcs_nss_supp.bw._160;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_160]);
arg->peer_eht_mcs_count++;
fallthrough;
default:
if ((he_cap->he_cap_elem.phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) {
bw_20 = &eht_cap->eht_mcs_nss_supp.only_20mhz;
ath12k_mac_set_eht_mcs(bw_20->rx_tx_mcs7_max_nss,
bw_20->rx_tx_mcs9_max_nss,
bw_20->rx_tx_mcs11_max_nss,
bw_20->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
} else {
bw = &eht_cap->eht_mcs_nss_supp.bw._80;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs9_max_nss,
bw->rx_tx_mcs11_max_nss,
bw->rx_tx_mcs13_max_nss,
&rx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80],
&tx_mcs[WMI_EHTCAP_TXRX_MCS_NSS_IDX_80]);
}
arg->peer_eht_mcs_count++;
break;
}
arg->punct_bitmap = ~arvif->punct_bitmap;
}
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -2023,6 +2233,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
ath12k_peer_assoc_h_ht(ar, vif, sta, arg);
ath12k_peer_assoc_h_vht(ar, vif, sta, arg);
ath12k_peer_assoc_h_he(ar, vif, sta, arg);
ath12k_peer_assoc_h_eht(ar, vif, sta, arg);
ath12k_peer_assoc_h_qos(ar, vif, sta, arg);
ath12k_peer_assoc_h_phymode(ar, vif, sta, arg);
ath12k_peer_assoc_h_smps(sta, arg);
@ -2554,6 +2765,9 @@ static void ath12k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP)
ath12k_mac_fils_discovery(arvif, info);
if (changed & BSS_CHANGED_EHT_PUNCTURING)
arvif->punct_bitmap = info->eht_puncturing;
mutex_unlock(&ar->conf_mutex);
}
@ -2755,9 +2969,12 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
arg.scan_id = ATH12K_SCAN_ID;
if (req->ie_len) {
arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
if (!arg.extraie.ptr) {
ret = -ENOMEM;
goto exit;
}
arg.extraie.len = req->ie_len;
arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
memcpy(arg.extraie.ptr, req->ie, req->ie_len);
}
if (req->n_ssids) {
@ -2770,6 +2987,14 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels) {
arg.num_chan = req->n_channels;
arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
GFP_KERNEL);
if (!arg.chan_list) {
ret = -ENOMEM;
goto exit;
}
for (i = 0; i < arg.num_chan; i++)
arg.chan_list[i] = req->channels[i]->center_freq;
}
@ -2788,6 +3013,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
ATH12K_MAC_SCAN_TIMEOUT_MSECS));
exit:
kfree(arg.chan_list);
if (req->ie_len)
kfree(arg.extraie.ptr);
@ -4209,18 +4436,178 @@ static __le16 ath12k_mac_setup_he_6ghz_cap(struct ath12k_pdev_cap *pcap,
return cpu_to_le16(bcap->he_6ghz_capa);
}
static int ath12k_mac_copy_he_cap(struct ath12k *ar,
struct ath12k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
int band)
static void ath12k_mac_copy_he_cap(struct ath12k_band_cap *band_cap,
int iftype, u8 num_tx_chains,
struct ieee80211_sta_he_cap *he_cap)
{
struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
struct ieee80211_he_mcs_nss_supp *mcs_nss = &he_cap->he_mcs_nss_supp;
he_cap->has_he = true;
memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
sizeof(he_cap_elem->mac_cap_info));
memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
sizeof(he_cap_elem->phy_cap_info));
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] |= num_tx_chains - 1;
switch (iftype) {
case NL80211_IFTYPE_AP:
he_cap_elem->phy_cap_info[3] &=
~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[0] &= ~IEEE80211_HE_MAC_CAP0_TWT_RES;
he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_MESH_POINT:
ath12k_mac_filter_he_cap_mesh(he_cap_elem);
break;
}
mcs_nss->rx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
mcs_nss->tx_mcs_80 = cpu_to_le16(band_cap->he_mcs & 0xffff);
mcs_nss->rx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->tx_mcs_160 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->rx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
mcs_nss->tx_mcs_80p80 = cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
ath12k_gen_ppe_thresh(&band_cap->he_ppet, he_cap->ppe_thres);
}
static void
ath12k_mac_copy_eht_mcs_nss(struct ath12k_band_cap *band_cap,
struct ieee80211_eht_mcs_nss_supp *mcs_nss,
const struct ieee80211_he_cap_elem *he_cap,
const struct ieee80211_eht_cap_elem_fixed *eht_cap)
{
if ((he_cap->phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0)
memcpy(&mcs_nss->only_20mhz, &band_cap->eht_mcs_20_only,
sizeof(struct ieee80211_eht_mcs_nss_supp_20mhz_only));
if (he_cap->phy_cap_info[0] &
(IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))
memcpy(&mcs_nss->bw._80, &band_cap->eht_mcs_80,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
if (he_cap->phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
memcpy(&mcs_nss->bw._160, &band_cap->eht_mcs_160,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
memcpy(&mcs_nss->bw._320, &band_cap->eht_mcs_320,
sizeof(struct ieee80211_eht_mcs_nss_supp_bw));
}
static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *fw_ppet,
struct ieee80211_sta_eht_cap *cap)
{
u16 bit = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE;
u8 i, nss, ru, ppet_bit_len_per_ru = IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
u8p_replace_bits(&cap->eht_ppe_thres[0], fw_ppet->numss_m1,
IEEE80211_EHT_PPE_THRES_NSS_MASK);
u16p_replace_bits((u16 *)&cap->eht_ppe_thres[0], fw_ppet->ru_bit_mask,
IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
for (nss = 0; nss <= fw_ppet->numss_m1; nss++) {
for (ru = 0;
ru < hweight16(IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
ru++) {
u32 val = 0;
if ((fw_ppet->ru_bit_mask & BIT(ru)) == 0)
continue;
u32p_replace_bits(&val, fw_ppet->ppet16_ppet8_ru3_ru0[nss] >>
(ru * ppet_bit_len_per_ru),
GENMASK(ppet_bit_len_per_ru - 1, 0));
for (i = 0; i < ppet_bit_len_per_ru; i++) {
cap->eht_ppe_thres[bit / 8] |=
(((val >> i) & 0x1) << ((bit % 8)));
bit++;
}
}
}
}
static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
struct ieee80211_he_cap_elem *he_cap_elem,
int iftype,
struct ieee80211_sta_eht_cap *eht_cap)
{
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
eht_cap->has_eht = true;
memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
sizeof(eht_cap_elem->mac_cap_info));
memcpy(eht_cap_elem->phy_cap_info, band_cap->eht_cap_phy_info,
sizeof(eht_cap_elem->phy_cap_info));
switch (iftype) {
case NL80211_IFTYPE_AP:
eht_cap_elem->phy_cap_info[0] &=
~IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ;
eht_cap_elem->phy_cap_info[4] &=
~IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO;
eht_cap_elem->phy_cap_info[5] &=
~IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP;
break;
case NL80211_IFTYPE_STATION:
eht_cap_elem->phy_cap_info[7] &=
~(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
eht_cap_elem->phy_cap_info[7] &=
~(IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ);
break;
default:
break;
}
ath12k_mac_copy_eht_mcs_nss(band_cap, &eht_cap->eht_mcs_nss_supp,
he_cap_elem, eht_cap_elem);
if (eht_cap_elem->phy_cap_info[5] &
IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT)
ath12k_mac_copy_eht_ppe_thresh(&band_cap->eht_ppet, eht_cap);
}
static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
struct ath12k_pdev_cap *cap,
struct ieee80211_sband_iftype_data *data,
int band)
{
struct ath12k_band_cap *band_cap = &cap->band[band];
int i, idx = 0;
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
struct ath12k_band_cap *band_cap = &cap->band[band];
struct ieee80211_he_cap_elem *he_cap_elem =
&he_cap->he_cap_elem;
switch (i) {
case NL80211_IFTYPE_STATION:
@ -4233,102 +4620,56 @@ static int ath12k_mac_copy_he_cap(struct ath12k *ar,
}
data[idx].types_mask = BIT(i);
he_cap->has_he = true;
memcpy(he_cap_elem->mac_cap_info, band_cap->he_cap_info,
sizeof(he_cap_elem->mac_cap_info));
memcpy(he_cap_elem->phy_cap_info, band_cap->he_cap_phy_info,
sizeof(he_cap_elem->phy_cap_info));
he_cap_elem->mac_cap_info[1] &=
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] &=
~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK;
he_cap_elem->phy_cap_info[5] |= ar->num_tx_chains - 1;
switch (i) {
case NL80211_IFTYPE_AP:
he_cap_elem->phy_cap_info[3] &=
~IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_STATION:
he_cap_elem->mac_cap_info[0] &=
~IEEE80211_HE_MAC_CAP0_TWT_RES;
he_cap_elem->mac_cap_info[0] |=
IEEE80211_HE_MAC_CAP0_TWT_REQ;
he_cap_elem->phy_cap_info[9] |=
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU;
break;
case NL80211_IFTYPE_MESH_POINT:
ath12k_mac_filter_he_cap_mesh(he_cap_elem);
break;
}
he_cap->he_mcs_nss_supp.rx_mcs_80 =
cpu_to_le16(band_cap->he_mcs & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_80 =
cpu_to_le16(band_cap->he_mcs & 0xffff);
he_cap->he_mcs_nss_supp.rx_mcs_160 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_160 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.rx_mcs_80p80 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
he_cap->he_mcs_nss_supp.tx_mcs_80p80 =
cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff);
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
if (he_cap_elem->phy_cap_info[6] &
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT)
ath12k_gen_ppe_thresh(&band_cap->he_ppet,
he_cap->ppe_thres);
ath12k_mac_copy_he_cap(band_cap, i, ar->num_tx_chains, he_cap);
if (band == NL80211_BAND_6GHZ) {
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
}
ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
&data[idx].eht_cap);
idx++;
}
return idx;
}
static void ath12k_mac_setup_he_cap(struct ath12k *ar,
struct ath12k_pdev_cap *cap)
static void ath12k_mac_setup_sband_iftype_data(struct ath12k *ar,
struct ath12k_pdev_cap *cap)
{
struct ieee80211_supported_band *band;
struct ieee80211_supported_band *sband;
enum nl80211_band band;
int count;
if (cap->supported_bands & WMI_HOST_WLAN_2G_CAP) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_2GHZ],
NL80211_BAND_2GHZ);
band = &ar->mac.sbands[NL80211_BAND_2GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_2GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_2GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_5GHZ],
NL80211_BAND_5GHZ);
band = &ar->mac.sbands[NL80211_BAND_5GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_5GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_5GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
if (cap->supported_bands & WMI_HOST_WLAN_5G_CAP &&
ar->supports_6ghz) {
count = ath12k_mac_copy_he_cap(ar, cap,
ar->mac.iftype[NL80211_BAND_6GHZ],
NL80211_BAND_6GHZ);
band = &ar->mac.sbands[NL80211_BAND_6GHZ];
band->iftype_data = ar->mac.iftype[NL80211_BAND_6GHZ];
band->n_iftype_data = count;
band = NL80211_BAND_6GHZ;
count = ath12k_mac_copy_sband_iftype_data(ar, cap,
ar->mac.iftype[band],
band);
sband = &ar->mac.sbands[band];
sband->iftype_data = ar->mac.iftype[band];
sband->n_iftype_data = count;
}
}
@ -4373,7 +4714,7 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant)
/* Reload HT/VHT/HE capability */
ath12k_mac_setup_ht_vht_cap(ar, &ar->pdev->cap, NULL);
ath12k_mac_setup_he_cap(ar, &ar->pdev->cap);
ath12k_mac_setup_sband_iftype_data(ar, &ar->pdev->cap);
return 0;
}
@ -5201,7 +5542,7 @@ err:
static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif)
{
struct ath12k_tx_desc_info *tx_desc_info, *tmp1;
struct ath12k_tx_desc_info *tx_desc_info;
struct ath12k_skb_cb *skb_cb;
struct sk_buff *skb;
int i;
@ -5209,8 +5550,8 @@ static void ath12k_mac_vif_unref(struct ath12k_dp *dp, struct ieee80211_vif *vif
for (i = 0; i < ATH12K_HW_MAX_QUEUES; i++) {
spin_lock_bh(&dp->tx_desc_lock[i]);
list_for_each_entry_safe(tx_desc_info, tmp1, &dp->tx_desc_used_list[i],
list) {
list_for_each_entry(tx_desc_info, &dp->tx_desc_used_list[i],
list) {
skb = tx_desc_info->skb;
if (!skb)
continue;
@ -5466,6 +5807,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.vdev_id = arvif->vdev_id;
arg.dtim_period = arvif->dtim_period;
arg.bcn_intval = arvif->beacon_interval;
arg.punct_bitmap = ~arvif->punct_bitmap;
arg.freq = chandef->chan->center_freq;
arg.band_center_freq1 = chandef->center_freq1;
@ -5508,9 +5850,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac vdev %d start center_freq %d phymode %s\n",
"mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n",
arg.vdev_id, arg.freq,
ath12k_mac_phymode_str(arg.mode));
ath12k_mac_phymode_str(arg.mode), arg.punct_bitmap);
ret = ath12k_wmi_vdev_start(ar, &arg, restart);
if (ret) {
@ -5837,6 +6179,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
"mac chanctx assign ptr %pK vdev_id %i\n",
ctx, arvif->vdev_id);
arvif->punct_bitmap = link_conf->eht_puncturing;
/* for some targets bss peer must be created before vdev_start */
if (ab->hw_params->vdev_start_delay &&
arvif->vdev_type != WMI_VDEV_TYPE_AP &&
@ -6388,6 +6732,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
{
struct ath12k *ar = hw->priv;
struct ath12k_base *ab = ar->ab;
struct ath12k_vif *arvif;
int recovery_count;
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
@ -6416,6 +6761,26 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
}
}
list_for_each_entry(arvif, &ar->arvifs, list) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"reconfig cipher %d up %d vdev type %d\n",
arvif->key_cipher,
arvif->is_up,
arvif->vdev_type);
/* After trigger disconnect, then upper layer will
* trigger connect again, then the PN number of
* upper layer will be reset to keep up with AP
* side, hence PN number mis-match will not happened.
*/
if (arvif->is_up &&
arvif->vdev_type == WMI_VDEV_TYPE_STA &&
arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
ieee80211_hw_restart_disconnect(arvif->vif);
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"restart disconnect\n");
}
}
}
mutex_unlock(&ar->conf_mutex);
@ -6854,7 +7219,7 @@ static int __ath12k_mac_register(struct ath12k *ar)
goto err;
ath12k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
ath12k_mac_setup_he_cap(ar, cap);
ath12k_mac_setup_sband_iftype_data(ar, cap);
ret = ath12k_mac_setup_iface_combinations(ar);
if (ret) {
@ -6943,6 +7308,8 @@ static int __ath12k_mac_register(struct ath12k *ar)
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP);
}
wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_PUNCT);
ath12k_reg_init(ar);
if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) {

View File

@ -33,7 +33,7 @@ struct ath12k_generic_iter {
#define IEEE80211_VHT_MCS_SUPPORT_0_11_MASK GENMASK(23, 16)
#define IEEE80211_DISABLE_VHT_MCS_SUPPORT_0_11 BIT(24)
#define ATH12K_CHAN_WIDTH_NUM 8
#define ATH12K_CHAN_WIDTH_NUM 14
#define ATH12K_TX_POWER_MAX_VAL 70
#define ATH12K_TX_POWER_MIN_VAL 0

View File

@ -387,7 +387,7 @@ static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
mlo_capable_valid),
},
{
.data_type = QMI_OPT_FLAG,
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,

View File

@ -62,9 +62,27 @@ struct ath12k_wmi_svc_rdy_ext_parse {
bool dma_ring_cap_done;
};
struct ath12k_wmi_svc_rdy_ext2_arg {
u32 reg_db_version;
u32 hw_min_max_tx_power_2ghz;
u32 hw_min_max_tx_power_5ghz;
u32 chwidth_num_peer_caps;
u32 preamble_puncture_bw;
u32 max_user_per_ppdu_ofdma;
u32 max_user_per_ppdu_mumimo;
u32 target_cap_flags;
u32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
u32 max_num_linkview_peers;
u32 max_num_msduq_supported_per_tid;
u32 default_num_msduq_supported_per_tid;
};
struct ath12k_wmi_svc_rdy_ext2_parse {
struct ath12k_wmi_svc_rdy_ext2_arg arg;
struct ath12k_wmi_dma_ring_caps_parse dma_caps_parse;
bool dma_ring_cap_done;
bool spectral_bin_scaling_done;
bool mac_phy_caps_ext_done;
};
struct ath12k_wmi_rdy_parse {
@ -445,8 +463,10 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
const struct ath12k_wmi_soc_mac_phy_hw_mode_caps_params *hw_caps = svc->hw_caps;
const struct ath12k_wmi_hw_mode_cap_params *wmi_hw_mode_caps = svc->hw_mode_caps;
const struct ath12k_wmi_mac_phy_caps_params *wmi_mac_phy_caps = svc->mac_phy_caps;
struct ath12k_base *ab = wmi_handle->wmi_ab->ab;
struct ath12k_band_cap *cap_band;
struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
struct ath12k_fw_pdev *fw_pdev;
u32 phy_map;
u32 hw_idx, phy_idx = 0;
int i;
@ -475,6 +495,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);
pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);
fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];
fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);
fw_pdev->pdev_id = le32_to_cpu(mac_caps->pdev_id);
fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);
ab->fw_pdev_count++;
/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from
* band to band for a single radio, need to see how this should be
* handled.
@ -995,6 +1021,7 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
cmd->cac_duration_ms = cpu_to_le32(arg->cac_duration_ms);
cmd->regdomain = cpu_to_le32(arg->regdomain);
cmd->he_ops = cpu_to_le32(arg->he_ops);
cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);
if (!restart) {
if (arg->ssid) {
@ -1791,6 +1818,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
bool hw_crypto_disabled)
{
cmd->peer_flags = 0;
cmd->peer_flags_ext = 0;
if (arg->is_wme_set) {
if (arg->qos_flag)
@ -1805,6 +1833,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
cmd->peer_flags |= cpu_to_le32(WMI_PEER_80MHZ);
if (arg->bw_160)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);
if (arg->bw_320)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
/* Typically if STBC is enabled for VHT it should be enabled
* for HT as well
@ -1832,6 +1862,8 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_REQ);
if (arg->twt_responder)
cmd->peer_flags |= cpu_to_le32(WMI_PEER_TWT_RESP);
if (arg->eht_flag)
cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_EHT);
}
/* Suppress authorization for all AUTH modes that need 4-way handshake
@ -1876,6 +1908,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
struct wmi_peer_assoc_complete_cmd *cmd;
struct ath12k_wmi_vht_rate_set_params *mcs;
struct ath12k_wmi_he_rate_set_params *he_mcs;
struct ath12k_wmi_eht_rate_set_params *eht_mcs;
struct sk_buff *skb;
struct wmi_tlv *tlv;
void *ptr;
@ -1892,7 +1925,9 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
TLV_HDR_SIZE + (peer_legacy_rates_align * sizeof(u8)) +
TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) +
sizeof(*mcs) + TLV_HDR_SIZE +
(sizeof(*he_mcs) * arg->peer_he_mcs_count);
(sizeof(*he_mcs) * arg->peer_he_mcs_count) +
TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count) +
TLV_HDR_SIZE + TLV_HDR_SIZE;
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@ -1908,6 +1943,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_new_assoc = cpu_to_le32(arg->peer_new_assoc);
cmd->peer_associd = cpu_to_le32(arg->peer_associd);
cmd->punct_bitmap = cpu_to_le32(arg->punct_bitmap);
ath12k_wmi_copy_peer_flags(cmd, arg,
test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED,
@ -1939,6 +1975,16 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_ppet.ppet16_ppet8_ru3_ru0[i] =
cpu_to_le32(arg->peer_ppet.ppet16_ppet8_ru3_ru0[i]);
/* Update 11be capabilities */
memcpy_and_pad(cmd->peer_eht_cap_mac, sizeof(cmd->peer_eht_cap_mac),
arg->peer_eht_cap_mac, sizeof(arg->peer_eht_cap_mac),
0);
memcpy_and_pad(cmd->peer_eht_cap_phy, sizeof(cmd->peer_eht_cap_phy),
arg->peer_eht_cap_phy, sizeof(arg->peer_eht_cap_phy),
0);
memcpy_and_pad(&cmd->peer_eht_ppet, sizeof(cmd->peer_eht_ppet),
&arg->peer_eht_ppet, sizeof(arg->peer_eht_ppet), 0);
/* Update peer legacy rate information */
ptr += sizeof(*cmd);
@ -2005,8 +2051,36 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ptr += sizeof(*he_mcs);
}
/* MLO header tag with 0 length */
len = 0;
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
/* Loop through the EHT rate set */
len = arg->peer_eht_mcs_count * sizeof(*eht_mcs);
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
for (i = 0; i < arg->peer_eht_mcs_count; i++) {
eht_mcs = ptr;
eht_mcs->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_HE_RATE_SET,
sizeof(*eht_mcs));
eht_mcs->rx_mcs_set = cpu_to_le32(arg->peer_eht_rx_mcs_set[i]);
eht_mcs->tx_mcs_set = cpu_to_le32(arg->peer_eht_tx_mcs_set[i]);
ptr += sizeof(*eht_mcs);
}
/* ML partner links tag with 0 length */
len = 0;
tlv = ptr;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x\n",
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n",
cmd->vdev_id, cmd->peer_associd, arg->peer_mac,
cmd->peer_flags, cmd->peer_rate_caps, cmd->peer_caps,
cmd->peer_listen_intval, cmd->peer_ht_caps,
@ -2016,7 +2090,10 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
cmd->peer_he_ops, cmd->peer_he_cap_info_ext,
cmd->peer_he_cap_phy[0], cmd->peer_he_cap_phy[1],
cmd->peer_he_cap_phy[2],
cmd->peer_bw_rxnss_override);
cmd->peer_bw_rxnss_override, cmd->peer_flags_ext,
cmd->peer_eht_cap_mac[0], cmd->peer_eht_cap_mac[1],
cmd->peer_eht_cap_phy[0], cmd->peer_eht_cap_phy[1],
cmd->peer_eht_cap_phy[2]);
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_ASSOC_CMDID);
if (ret) {
@ -3705,6 +3782,10 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
for (i = 0 ; i < svc_rdy_ext->n_hw_mode_caps; i++) {
hw_mode_caps = &svc_rdy_ext->hw_mode_caps[i];
mode = le32_to_cpu(hw_mode_caps->hw_mode_id);
if (mode >= WMI_HOST_HW_MODE_MAX)
continue;
pref = soc->wmi_ab.preferred_hw_mode;
if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
@ -3811,6 +3892,7 @@ static int ath12k_wmi_ext_soc_hal_reg_caps_parse(struct ath12k_base *soc,
soc->num_radios = 0;
phy_id_map = le32_to_cpu(svc_rdy_ext->pref_hw_mode_caps.phy_id_map);
soc->fw_pdev_count = 0;
while (phy_id_map && soc->num_radios < MAX_RADIOS) {
ret = ath12k_pull_mac_phy_cap_svc_ready_ext(wmi_handle,
@ -4038,14 +4120,165 @@ err:
return ret;
}
static int ath12k_pull_svc_ready_ext2(struct ath12k_wmi_pdev *wmi_handle,
const void *ptr,
struct ath12k_wmi_svc_rdy_ext2_arg *arg)
{
const struct wmi_service_ready_ext2_event *ev = ptr;
if (!ev)
return -EINVAL;
arg->reg_db_version = le32_to_cpu(ev->reg_db_version);
arg->hw_min_max_tx_power_2ghz = le32_to_cpu(ev->hw_min_max_tx_power_2ghz);
arg->hw_min_max_tx_power_5ghz = le32_to_cpu(ev->hw_min_max_tx_power_5ghz);
arg->chwidth_num_peer_caps = le32_to_cpu(ev->chwidth_num_peer_caps);
arg->preamble_puncture_bw = le32_to_cpu(ev->preamble_puncture_bw);
arg->max_user_per_ppdu_ofdma = le32_to_cpu(ev->max_user_per_ppdu_ofdma);
arg->max_user_per_ppdu_mumimo = le32_to_cpu(ev->max_user_per_ppdu_mumimo);
arg->target_cap_flags = le32_to_cpu(ev->target_cap_flags);
return 0;
}
static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
const __le32 cap_mac_info[],
const __le32 cap_phy_info[],
const __le32 supp_mcs[],
const struct ath12k_wmi_ppe_threshold_params *ppet,
__le32 cap_info_internal)
{
struct ath12k_band_cap *cap_band = &pdev->cap.band[band];
u8 i;
for (i = 0; i < WMI_MAX_EHTCAP_MAC_SIZE; i++)
cap_band->eht_cap_mac_info[i] = le32_to_cpu(cap_mac_info[i]);
for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++)
cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]);
cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]);
cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]);
if (band != NL80211_BAND_2GHZ) {
cap_band->eht_mcs_160 = le32_to_cpu(supp_mcs[2]);
cap_band->eht_mcs_320 = le32_to_cpu(supp_mcs[3]);
}
cap_band->eht_ppet.numss_m1 = le32_to_cpu(ppet->numss_m1);
cap_band->eht_ppet.ru_bit_mask = le32_to_cpu(ppet->ru_info);
for (i = 0; i < WMI_MAX_NUM_SS; i++)
cap_band->eht_ppet.ppet16_ppet8_ru3_ru0[i] =
le32_to_cpu(ppet->ppet16_ppet8_ru3_ru0[i]);
cap_band->eht_cap_info_internal = le32_to_cpu(cap_info_internal);
}
static int
ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
const struct ath12k_wmi_caps_ext_params *caps,
struct ath12k_pdev *pdev)
{
u32 bands;
int i;
if (ab->hw_params->single_pdev_only) {
for (i = 0; i < ab->fw_pdev_count; i++) {
struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];
if (fw_pdev->pdev_id == le32_to_cpu(caps->pdev_id) &&
fw_pdev->phy_id == le32_to_cpu(caps->phy_id)) {
bands = fw_pdev->supported_bands;
break;
}
}
if (i == ab->fw_pdev_count)
return -EINVAL;
} else {
bands = pdev->cap.supported_bands;
}
if (bands & WMI_HOST_WLAN_2G_CAP) {
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_2GHZ,
caps->eht_cap_mac_info_2ghz,
caps->eht_cap_phy_info_2ghz,
caps->eht_supp_mcs_ext_2ghz,
&caps->eht_ppet_2ghz,
caps->eht_cap_info_internal);
}
if (bands & WMI_HOST_WLAN_5G_CAP) {
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_5GHZ,
caps->eht_cap_mac_info_5ghz,
caps->eht_cap_phy_info_5ghz,
caps->eht_supp_mcs_ext_5ghz,
&caps->eht_ppet_5ghz,
caps->eht_cap_info_internal);
ath12k_wmi_eht_caps_parse(pdev, NL80211_BAND_6GHZ,
caps->eht_cap_mac_info_5ghz,
caps->eht_cap_phy_info_5ghz,
caps->eht_supp_mcs_ext_5ghz,
&caps->eht_ppet_5ghz,
caps->eht_cap_info_internal);
}
return 0;
}
static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,
u16 len, const void *ptr,
void *data)
{
const struct ath12k_wmi_caps_ext_params *caps = ptr;
int i = 0, ret;
if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT)
return -EPROTO;
if (ab->hw_params->single_pdev_only) {
if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id))
return 0;
} else {
for (i = 0; i < ab->num_radios; i++) {
if (ab->pdevs[i].pdev_id == le32_to_cpu(caps->pdev_id))
break;
}
if (i == ab->num_radios)
return -EINVAL;
}
ret = ath12k_wmi_tlv_mac_phy_caps_ext_parse(ab, caps, &ab->pdevs[i]);
if (ret) {
ath12k_warn(ab,
"failed to parse extended MAC PHY capabilities for pdev %d: %d\n",
ret, ab->pdevs[i].pdev_id);
return ret;
}
return 0;
}
static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
{
struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0];
struct ath12k_wmi_svc_rdy_ext2_parse *parse = data;
int ret;
switch (tag) {
case WMI_TAG_SERVICE_READY_EXT2_EVENT:
ret = ath12k_pull_svc_ready_ext2(wmi_handle, ptr,
&parse->arg);
if (ret) {
ath12k_warn(ab,
"failed to extract wmi service ready ext2 parameters: %d\n",
ret);
return ret;
}
break;
case WMI_TAG_ARRAY_STRUCT:
if (!parse->dma_ring_cap_done) {
ret = ath12k_wmi_dma_ring_caps(ab, len, ptr,
@ -4054,6 +4287,23 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
return ret;
parse->dma_ring_cap_done = true;
} else if (!parse->spectral_bin_scaling_done) {
/* TODO: This is a place-holder as WMI tag for
* spectral scaling is before
* WMI_TAG_MAC_PHY_CAPABILITIES_EXT
*/
parse->spectral_bin_scaling_done = true;
} else if (!parse->mac_phy_caps_ext_done) {
ret = ath12k_wmi_tlv_iter(ab, ptr, len,
ath12k_wmi_tlv_mac_phy_caps_ext,
parse);
if (ret) {
ath12k_warn(ab, "failed to parse extended MAC PHY capabilities WMI TLV: %d\n",
ret);
return ret;
}
parse->mac_phy_caps_ext_done = true;
}
break;
default:
@ -5223,7 +5473,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
ar = ab->pdevs[pdev_idx].ar;
kfree(ab->new_regd[pdev_idx]);
ab->new_regd[pdev_idx] = regd;
ieee80211_queue_work(ar->hw, &ar->regd_update_work);
queue_work(ab->workqueue, &ar->regd_update_work);
} else {
/* Multiple events for the same *ar is not expected. But we
* can still clear any previously stored default_regd if we
@ -5698,6 +5948,8 @@ static void ath12k_scan_event(struct ath12k_base *ab, struct sk_buff *skb)
ath12k_wmi_event_scan_start_failed(ar);
break;
case WMI_SCAN_EVENT_DEQUEUED:
__ath12k_mac_scan_finish(ar);
break;
case WMI_SCAN_EVENT_PREEMPTED:
case WMI_SCAN_EVENT_RESTARTED:
case WMI_SCAN_EVENT_FOREIGN_CHAN_EXIT:

View File

@ -1167,6 +1167,11 @@ enum wmi_tlv_peer_flags {
};
enum wmi_tlv_peer_flags_ext {
WMI_PEER_EXT_EHT = BIT(0),
WMI_PEER_EXT_320MHZ = BIT(1),
};
/** Enum list of TLV Tags for each parameter structure type. */
enum wmi_tlv_tag {
WMI_TAG_LAST_RESERVED = 15,
@ -1920,10 +1925,12 @@ enum wmi_tlv_tag {
/* TODO add all the missing cmds */
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
WMI_TAG_SERVICE_READY_EXT2_EVENT = 0x334,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_MAC_PHY_CAPABILITIES_EXT = 0x36F,
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
WMI_TAG_EHT_RATE_SET = 0x3C4,
WMI_TAG_MAX
};
@ -2581,6 +2588,69 @@ struct ath12k_wmi_soc_hal_reg_caps_params {
__le32 num_phy;
} __packed;
#define WMI_MAX_EHTCAP_MAC_SIZE 2
#define WMI_MAX_EHTCAP_PHY_SIZE 3
#define WMI_MAX_EHTCAP_RATE_SET 3
/* Used for EHT MCS-NSS array. Data at each array index follows the format given
* in IEEE P802.11be/D2.0, May 20229.4.2.313.4.
*
* Index interpretation:
* 0 - 20 MHz only sta, all 4 bytes valid
* 1 - index for bandwidths <= 80 MHz except 20 MHz-only, first 3 bytes valid
* 2 - index for 160 MHz, first 3 bytes valid
* 3 - index for 320 MHz, first 3 bytes valid
*/
#define WMI_MAX_EHT_SUPP_MCS_2G_SIZE 2
#define WMI_MAX_EHT_SUPP_MCS_5G_SIZE 4
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_80 0
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_160 1
#define WMI_EHTCAP_TXRX_MCS_NSS_IDX_320 2
#define WMI_EHT_MCS_NSS_0_7 GENMASK(3, 0)
#define WMI_EHT_MCS_NSS_8_9 GENMASK(7, 4)
#define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8)
#define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12)
struct wmi_service_ready_ext2_event {
__le32 reg_db_version;
__le32 hw_min_max_tx_power_2ghz;
__le32 hw_min_max_tx_power_5ghz;
__le32 chwidth_num_peer_caps;
__le32 preamble_puncture_bw;
__le32 max_user_per_ppdu_ofdma;
__le32 max_user_per_ppdu_mumimo;
__le32 target_cap_flags;
__le32 eht_cap_mac_info[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 max_num_linkview_peers;
__le32 max_num_msduq_supported_per_tid;
__le32 default_num_msduq_supported_per_tid;
} __packed;
struct ath12k_wmi_caps_ext_params {
__le32 hw_mode_id;
union {
struct {
__le16 pdev_id;
__le16 hw_link_id;
} __packed ath12k_wmi_pdev_to_link_map;
__le32 pdev_id;
};
__le32 phy_id;
__le32 wireless_modes_ext;
__le32 eht_cap_mac_info_2ghz[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 eht_cap_mac_info_5ghz[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 rsvd0[2];
__le32 eht_cap_phy_info_2ghz[WMI_MAX_EHTCAP_PHY_SIZE];
__le32 eht_cap_phy_info_5ghz[WMI_MAX_EHTCAP_PHY_SIZE];
struct ath12k_wmi_ppe_threshold_params eht_ppet_2ghz;
struct ath12k_wmi_ppe_threshold_params eht_ppet_5ghz;
__le32 eht_cap_info_internal;
__le32 eht_supp_mcs_ext_2ghz[WMI_MAX_EHT_SUPP_MCS_2G_SIZE];
__le32 eht_supp_mcs_ext_5ghz[WMI_MAX_EHT_SUPP_MCS_5G_SIZE];
} __packed;
/* 2 word representation of MAC addr */
struct ath12k_wmi_mac_addr_params {
u8 addr[ETH_ALEN];
@ -2705,6 +2775,11 @@ struct wmi_vdev_start_request_cmd {
__le32 he_ops;
__le32 cac_duration_ms;
__le32 regdomain;
__le32 min_data_rate;
__le32 mbssid_flags;
__le32 mbssid_tx_vdev_id;
__le32 eht_ops;
__le32 punct_bitmap;
} __packed;
#define MGMT_TX_DL_FRM_LEN 64
@ -2758,8 +2833,17 @@ enum wmi_phy_mode {
MODE_11AX_HE20_2G = 21,
MODE_11AX_HE40_2G = 22,
MODE_11AX_HE80_2G = 23,
MODE_UNKNOWN = 24,
MODE_MAX = 24
MODE_11BE_EHT20 = 24,
MODE_11BE_EHT40 = 25,
MODE_11BE_EHT80 = 26,
MODE_11BE_EHT80_80 = 27,
MODE_11BE_EHT160 = 28,
MODE_11BE_EHT160_160 = 29,
MODE_11BE_EHT320 = 30,
MODE_11BE_EHT20_2G = 31,
MODE_11BE_EHT40_2G = 32,
MODE_UNKNOWN = 33,
MODE_MAX = 33,
};
struct wmi_vdev_start_req_arg {
@ -2795,6 +2879,10 @@ struct wmi_vdev_start_req_arg {
u32 pref_rx_streams;
u32 pref_tx_streams;
u32 num_noa_descriptors;
u32 min_data_rate;
u32 mbssid_flags;
u32 mbssid_tx_vdev_id;
u32 punct_bitmap;
};
struct ath12k_wmi_peer_create_arg {
@ -3034,7 +3122,6 @@ enum scan_dwelltime_adaptive_mode {
#define WLAN_SCAN_MAX_NUM_SSID 10
#define WLAN_SCAN_MAX_NUM_BSSID 10
#define WLAN_SCAN_MAX_NUM_CHANNELS 40
struct ath12k_wmi_element_info_arg {
u32 len;
@ -3243,7 +3330,7 @@ struct ath12k_wmi_scan_req_arg {
u32 num_bssid;
u32 num_ssids;
u32 n_probes;
u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS];
u32 *chan_list;
u32 notify_scan_events;
struct cfg80211_ssid ssid[WLAN_SCAN_MAX_NUM_SSID];
struct ath12k_wmi_mac_addr_params bssid_list[WLAN_SCAN_MAX_NUM_BSSID];
@ -3491,6 +3578,7 @@ struct ath12k_wmi_peer_assoc_arg {
bool bw_40;
bool bw_80;
bool bw_160;
bool bw_320;
bool stbc_flag;
bool ldpc_flag;
bool static_mimops_flag;
@ -3518,6 +3606,14 @@ struct ath12k_wmi_peer_assoc_arg {
bool twt_responder;
bool twt_requester;
struct ath12k_wmi_ppe_threshold_arg peer_ppet;
bool eht_flag;
u32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE];
u32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE];
u32 peer_eht_mcs_count;
u32 peer_eht_rx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet;
u32 punct_bitmap;
};
struct wmi_peer_assoc_complete_cmd {
@ -3549,6 +3645,15 @@ struct wmi_peer_assoc_complete_cmd {
__le32 peer_he_cap_info_internal;
__le32 min_data_rate;
__le32 peer_he_caps_6ghz;
__le32 sta_type;
__le32 bss_max_idle_option;
__le32 auth_mode;
__le32 peer_flags_ext;
__le32 punct_bitmap;
__le32 peer_eht_cap_mac[WMI_MAX_EHTCAP_MAC_SIZE];
__le32 peer_eht_cap_phy[WMI_MAX_EHTCAP_PHY_SIZE];
__le32 peer_eht_ops;
struct ath12k_wmi_ppe_threshold_params peer_eht_ppet;
} __packed;
struct wmi_stop_scan_cmd {
@ -3776,6 +3881,12 @@ struct ath12k_wmi_he_rate_set_params {
__le32 tx_mcs_set;
} __packed;
struct ath12k_wmi_eht_rate_set_params {
__le32 tlv_header;
__le32 rx_mcs_set;
__le32 tx_mcs_set;
} __packed;
#define MAX_REG_RULES 10
#define REG_ALPHA2_LEN 2
#define MAX_6G_REG_RULES 5

View File

@ -982,8 +982,6 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
ah->debug.level = ath5k_debug;
phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
if (!phydir)
return;
debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
debugfs_create_file("registers", 0400, phydir, ah, &registers_fops);

View File

@ -1793,8 +1793,6 @@ int ath6kl_debug_init_fs(struct ath6kl *ar)
{
ar->debugfs_phy = debugfs_create_dir("ath6kl",
ar->wiphy->debugfsdir);
if (!ar->debugfs_phy)
return -ENOMEM;
debugfs_create_file("tgt_stats", 0400, ar->debugfs_phy, ar,
&fops_tgt_stats);

View File

@ -132,8 +132,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)mem, irq);
wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
hw_name, mem, irq);
return 0;

View File

@ -115,8 +115,10 @@ struct ath_tx_status {
u8 qid;
u16 desc_id;
u8 tid;
u32 ba_low;
u32 ba_high;
struct_group(ba,
u32 ba_low;
u32 ba_high;
);
u32 evm0;
u32 evm1;
u32 evm2;

View File

@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->sc_ah->msi_reg = 0;
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)sc->mem, pdev->irq);
wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
hw_name, sc->mem, pdev->irq);
return 0;

View File

@ -466,9 +466,11 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
*nframes = 0;
isaggr = bf_isaggr(bf);
memset(ba, 0, WME_BA_BMP_SIZE >> 3);
if (isaggr) {
seq_st = ts->ts_seqnum;
memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
}
while (bf) {
@ -551,7 +553,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (isaggr && txok) {
if (ts->ts_flags & ATH9K_TX_BA) {
seq_st = ts->ts_seqnum;
memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
} else {
/*
* AR5416 can become deaf/mute when BA

View File

@ -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>

View File

@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
&s->tid_crypto_rx[tid];
struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
const u8 *pn = (u8 *)&d->mac.pn_15_0;
const u8 *pn = (u8 *)&d->mac.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,

View File

@ -343,8 +343,10 @@ struct vring_rx_mac {
u32 d0;
u32 d1;
u16 w4;
u16 pn_15_0;
u32 pn_47_16;
struct_group_attr(pn, __packed,
u16 pn_15_0;
u32 pn_47_16;
);
} __packed;
/* Rx descriptor - DMA part

View File

@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil,
s = &wil->sta[cid];
c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid];
cc = &c->key_id[key_id];
pn = (u8 *)&st->ext.pn_15_0;
pn = (u8 *)&st->ext.pn;
if (!cc->key_set) {
wil_err_ratelimited(wil,

View File

@ -330,8 +330,10 @@ struct wil_rx_status_extension {
u32 d0;
u32 d1;
__le16 seq_num; /* only lower 12 bits */
u16 pn_15_0;
u32 pn_47_16;
struct_group_attr(pn, __packed,
u16 pn_15_0;
u32 pn_47_16;
);
} __packed;
struct wil_rx_status_extended {

View File

@ -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) */

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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];
};

View File

@ -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));

View File

@ -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 */

View File

@ -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;

View File

@ -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"

View File

@ -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);
}

View File

@ -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:

View File

@ -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);

View File

@ -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))

View File

@ -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,

View File

@ -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;
}
/*

View File

@ -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);

View File

@ -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);

View File

@ -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) +

View File

@ -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,

View File

@ -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"

View File

@ -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/

View File

@ -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;

View File

@ -6,35 +6,40 @@
#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;
const void *data;
int size;
data = of_get_property(np, "mediatek,eeprom-data", &size);
if (!data)
return -ENOENT;
if (size > len)
return -EINVAL;
memcpy(eep, data, size);
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 void *data;
const char *part;
phandle phandle;
int size;
size_t retlen;
int size;
int ret;
if (!np)
return -ENOENT;
data = of_get_property(np, "mediatek,eeprom-data", &size);
if (data) {
if (size > len)
return -EINVAL;
memcpy(eep, data, size);
return 0;
}
list = of_get_property(np, "mediatek,mtd-eeprom", &size);
if (!list)
return -ENOENT;
@ -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

View File

@ -76,6 +76,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 +661,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 +1746,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);

View File

@ -277,7 +277,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 +316,7 @@ struct mt76_wcid {
int inactive_count;
struct rate_info rate;
unsigned long ampdu_state;
u16 idx;
u8 hw_key_idx;
@ -336,6 +337,8 @@ struct mt76_wcid {
struct idr pktid;
struct mt76_sta_stats stats;
struct list_head poll_list;
};
struct mt76_txq {
@ -702,6 +705,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 +829,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 +866,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];

View File

@ -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);

View File

@ -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);

View File

@ -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))

View File

@ -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);
}

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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))

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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,
};

View File

@ -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);

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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];

View File

@ -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));
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 = __dl_u32(he_2mu_cnt) +
__dl_u32(he_3mu_cnt) +
__dl_u32(he_4mu_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));
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 = __ul_u32(hetrig_2mu_cnt) +
__ul_u32(hetrig_3mu_cnt) +
__ul_u32(hetrig_4mu_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);

View File

@ -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,12 +250,90 @@ 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;
u32 irq_mask;
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);
@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
@ -841,74 +842,6 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
return MT_TXD_SIZE + sizeof(*txp);
}
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)
{
@ -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);

View File

@ -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)

View File

@ -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,

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;
return read_poll_timeout(mt76_rr, cur, (cur == 0x02070000),
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 == 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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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;
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,
},
};
mt792x_mutex_acquire(mdev);
temperature = mt7921_mcu_get_temperature(phy);
mt792x_mutex_release(mdev);
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)
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_chanctx[] = {
{
.limits = if_limits_chanctx,
.n_limits = ARRAY_SIZE(if_limits_chanctx),
.max_interfaces = 2,
.num_different_channels = 2,
.beacon_int_infra_match = false,
}
static struct attribute *mt7921_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(mt7921_hwmon);
static int mt7921_thermal_init(struct mt792x_phy *phy)
{
struct wiphy *wiphy = phy->mt76->hw->wiphy;
struct device *hwmon;
const char *name;
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;

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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 {

View File

@ -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);
u32 mt7921_reg_map(struct mt792x_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,
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 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 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 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

View File

@ -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;
}

Some files were not shown because too many files have changed in this diff Show More