Merge tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says: ==================== wireless-next patches for v6.7 The second pull request for v6.7, with only driver changes this time. We have now support for mt7925 PCIe and USB variants, few new features and of course some fixes. Major changes: mt76 - mt7925 support ath12k - read board data variant name from SMBIOS wfx - Remain-On-Channel (ROC) support * tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (109 commits) wifi: rtw89: mac: do bf_monitor only if WiFi 6 chips wifi: rtw89: mac: set bf_assoc capabilities according to chip gen wifi: rtw89: mac: set bfee_ctrl() according to chip gen wifi: rtw89: mac: add registers of MU-EDCA parameters for WiFi 7 chips wifi: rtw89: mac: generalize register of MU-EDCA switch according to chip gen wifi: rtw89: mac: update RTS threshold according to chip gen wifi: rtlwifi: simplify TX command fill callbacks wifi: hostap: remove unused ioctl function wifi: atmel: remove unused ioctl function wifi: rtw89: coex: add annotation __counted_by() to struct rtw89_btc_btf_set_mon_reg wifi: rtw89: coex: add annotation __counted_by() for struct rtw89_btc_btf_set_slot_table wifi: rtw89: add EHT radiotap in monitor mode wifi: rtw89: show EHT rate in debugfs wifi: rtw89: parse TX EHT rate selected by firmware from RA C2H report wifi: rtw89: Add EHT rate mask as parameters of RA H2C command wifi: rtw89: parse EHT information from RX descriptor and PPDU status packet wifi: radiotap: add bandwidth definition of EHT U-SIG wifi: rtlwifi: use convenient list_count_nodes() wifi: p54: Annotate struct p54_cal_database with __counted_by wifi: brcmfmac: fweh: Add __counted_by for struct brcmf_fweh_queue_item and use struct_size() ... ==================== Link: https://lore.kernel.org/r/20231016143822.880D8C433C8@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -1964,20 +1964,13 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
bool val;
|
||||
u32 pdev_param;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (kstrtobool(buf, &val) != 0)
|
||||
return -EINVAL;
|
||||
ret = kstrtobool_from_user(ubuf, count, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ar->coex_support)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -2000,7 +1993,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
|
||||
ath10k_warn(ar, "failed to enable btcoex: %zd\n", ret);
|
||||
ret = count;
|
||||
goto exit;
|
||||
}
|
||||
@@ -2103,19 +2096,12 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret;
|
||||
ssize_t ret;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (kstrtobool(buf, &val) != 0)
|
||||
return -EINVAL;
|
||||
ret = kstrtobool_from_user(ubuf, count, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
@@ -2239,21 +2225,16 @@ static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
ssize_t ret;
|
||||
u32 mask;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoint(buf, 0, &mask))
|
||||
return -EINVAL;
|
||||
ret = kstrtoint_from_user(user_buf, count, 0, &mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ar->sta_tid_stats_mask = mask;
|
||||
|
||||
return len;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_sta_tid_stats_mask = {
|
||||
|
||||
@@ -728,20 +728,13 @@ static int ath10k_peer_create(struct ath10k *ar,
|
||||
const u8 *addr,
|
||||
enum wmi_peer_type peer_type)
|
||||
{
|
||||
struct ath10k_vif *arvif;
|
||||
struct ath10k_peer *peer;
|
||||
int num_peers = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
num_peers = ar->num_peers;
|
||||
|
||||
/* Each vdev consumes a peer entry as well */
|
||||
list_for_each_entry(arvif, &ar->arvifs, list)
|
||||
num_peers++;
|
||||
|
||||
if (num_peers >= ar->max_num_peers)
|
||||
/* Each vdev consumes a peer entry as well. */
|
||||
if (ar->num_peers + list_count_nodes(&ar->arvifs) >= ar->max_num_peers)
|
||||
return -ENOBUFS;
|
||||
|
||||
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
|
||||
@@ -4503,18 +4496,21 @@ void __ath10k_scan_finish(struct ath10k *ar)
|
||||
break;
|
||||
case ATH10K_SCAN_RUNNING:
|
||||
case ATH10K_SCAN_ABORTING:
|
||||
if (ar->scan.is_roc && ar->scan.roc_notify)
|
||||
ieee80211_remain_on_channel_expired(ar->hw);
|
||||
fallthrough;
|
||||
case ATH10K_SCAN_STARTING:
|
||||
if (!ar->scan.is_roc) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = (ar->scan.state ==
|
||||
ATH10K_SCAN_ABORTING),
|
||||
.aborted = ((ar->scan.state ==
|
||||
ATH10K_SCAN_ABORTING) ||
|
||||
(ar->scan.state ==
|
||||
ATH10K_SCAN_STARTING)),
|
||||
};
|
||||
|
||||
ieee80211_scan_completed(ar->hw, &info);
|
||||
} else if (ar->scan.roc_notify) {
|
||||
ieee80211_remain_on_channel_expired(ar->hw);
|
||||
}
|
||||
fallthrough;
|
||||
case ATH10K_SCAN_STARTING:
|
||||
|
||||
ar->scan.state = ATH10K_SCAN_IDLE;
|
||||
ar->scan_channel = NULL;
|
||||
ar->scan.roc_freq = 0;
|
||||
|
||||
@@ -828,12 +828,20 @@ static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar,
|
||||
|
||||
static inline void ath10k_snoc_irq_disable(struct ath10k *ar)
|
||||
{
|
||||
ath10k_ce_disable_interrupts(ar);
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int id;
|
||||
|
||||
for (id = 0; id < CE_COUNT_MAX; id++)
|
||||
disable_irq(ar_snoc->ce_irqs[id].irq_line);
|
||||
}
|
||||
|
||||
static inline void ath10k_snoc_irq_enable(struct ath10k *ar)
|
||||
{
|
||||
ath10k_ce_enable_interrupts(ar);
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int id;
|
||||
|
||||
for (id = 0; id < CE_COUNT_MAX; id++)
|
||||
enable_irq(ar_snoc->ce_irqs[id].irq_line);
|
||||
}
|
||||
|
||||
static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
|
||||
@@ -1090,6 +1098,8 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar,
|
||||
goto err_free_rri;
|
||||
}
|
||||
|
||||
ath10k_ce_enable_interrupts(ar);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_rri:
|
||||
@@ -1253,8 +1263,8 @@ static int ath10k_snoc_request_irq(struct ath10k *ar)
|
||||
|
||||
for (id = 0; id < CE_COUNT_MAX; id++) {
|
||||
ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
|
||||
ath10k_snoc_per_engine_handler, 0,
|
||||
ce_name[id], ar);
|
||||
ath10k_snoc_per_engine_handler,
|
||||
IRQF_NO_AUTOEN, ce_name[id], ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar,
|
||||
"failed to register IRQ handler for CE %d: %d\n",
|
||||
|
||||
@@ -384,16 +384,11 @@ static ssize_t write_file_spectral_count(struct file *file,
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
ssize_t ret;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
ret = kstrtoul_from_user(user_buf, count, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val > 255)
|
||||
return -EINVAL;
|
||||
@@ -440,16 +435,11 @@ static ssize_t write_file_spectral_bins(struct file *file,
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned long val;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
ssize_t ret;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
ret = kstrtoul_from_user(user_buf, count, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/inetdevice.h>
|
||||
@@ -7196,6 +7197,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
struct wmi_vdev_start_req_arg arg = {};
|
||||
const struct cfg80211_chan_def *chandef = &ctx->def;
|
||||
int ret = 0;
|
||||
unsigned int dfs_cac_time;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@@ -7275,20 +7277,21 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
|
||||
arvif->vif->addr, arvif->vdev_id);
|
||||
|
||||
/* Enable CAC Flag in the driver by checking the channel DFS cac time,
|
||||
* i.e dfs_cac_ms value which will be valid only for radar channels
|
||||
* and state as NL80211_DFS_USABLE which indicates CAC needs to be
|
||||
/* Enable CAC Flag in the driver by checking the all sub-channel's DFS
|
||||
* state as NL80211_DFS_USABLE which indicates CAC needs to be
|
||||
* done before channel usage. This flags is used to drop rx packets.
|
||||
* during CAC.
|
||||
*/
|
||||
/* TODO Set the flag for other interface types as required */
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
|
||||
chandef->chan->dfs_cac_ms &&
|
||||
chandef->chan->dfs_state == NL80211_DFS_USABLE) {
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP && ctx->radar_enabled &&
|
||||
cfg80211_chandef_dfs_usable(ar->hw->wiphy, chandef)) {
|
||||
set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
|
||||
dfs_cac_time = cfg80211_chandef_dfs_cac_time(ar->hw->wiphy,
|
||||
chandef);
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
"CAC Started in chan_freq %d for vdev %d\n",
|
||||
arg.channel.freq, arg.vdev_id);
|
||||
"cac started dfs_cac_time %u center_freq %d center_freq1 %d for vdev %d\n",
|
||||
dfs_cac_time, arg.channel.freq, chandef->center_freq1,
|
||||
arg.vdev_id);
|
||||
}
|
||||
|
||||
ret = ath11k_mac_set_txbf_conf(arvif);
|
||||
@@ -9057,6 +9060,14 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
|
||||
if (ar->state != ATH11K_STATE_ON)
|
||||
goto err_fallback;
|
||||
|
||||
/* Firmware doesn't provide Tx power during CAC hence no need to fetch
|
||||
* the stats.
|
||||
*/
|
||||
if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
req_param.pdev_id = ar->pdev->pdev_id;
|
||||
req_param.stats_id = WMI_REQUEST_PDEV_STAT;
|
||||
|
||||
|
||||
@@ -398,6 +398,75 @@ static void ath12k_core_stop(struct ath12k_base *ab)
|
||||
/* De-Init of components as needed */
|
||||
}
|
||||
|
||||
static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
|
||||
{
|
||||
struct ath12k_base *ab = data;
|
||||
const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC;
|
||||
struct ath12k_smbios_bdf *smbios = (struct ath12k_smbios_bdf *)hdr;
|
||||
ssize_t copied;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
if (ab->qmi.target.bdf_ext[0] != '\0')
|
||||
return;
|
||||
|
||||
if (hdr->type != ATH12K_SMBIOS_BDF_EXT_TYPE)
|
||||
return;
|
||||
|
||||
if (hdr->length != ATH12K_SMBIOS_BDF_EXT_LENGTH) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"wrong smbios bdf ext type length (%d).\n",
|
||||
hdr->length);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!smbios->bdf_enabled) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only one string exists (per spec) */
|
||||
if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"bdf variant magic does not match.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len = min_t(size_t,
|
||||
strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"bdf variant name contains non ascii chars.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy extension name without magic prefix */
|
||||
copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
|
||||
sizeof(ab->qmi.target.bdf_ext));
|
||||
if (copied < 0) {
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"bdf variant string is longer than the buffer can accommodate\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
||||
"found and validated bdf variant smbios_type 0x%x bdf %s\n",
|
||||
ATH12K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
|
||||
}
|
||||
|
||||
int ath12k_core_check_smbios(struct ath12k_base *ab)
|
||||
{
|
||||
ab->qmi.target.bdf_ext[0] = '\0';
|
||||
dmi_walk(ath12k_core_check_bdfext, ab);
|
||||
|
||||
if (ab->qmi.target.bdf_ext[0] == '\0')
|
||||
return -ENODATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath12k_core_soc_create(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "qmi.h"
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
@@ -32,6 +34,15 @@
|
||||
/* Pending management packets threshold for dropping probe responses */
|
||||
#define ATH12K_PRB_RSP_DROP_THRESHOLD ((ATH12K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4)
|
||||
|
||||
/* SMBIOS type containing Board Data File Name Extension */
|
||||
#define ATH12K_SMBIOS_BDF_EXT_TYPE 0xF8
|
||||
|
||||
/* SMBIOS type structure length (excluding strings-set) */
|
||||
#define ATH12K_SMBIOS_BDF_EXT_LENGTH 0x9
|
||||
|
||||
/* The magic used by QCA spec */
|
||||
#define ATH12K_SMBIOS_BDF_EXT_MAGIC "BDF_"
|
||||
|
||||
#define ATH12K_INVALID_HW_MAC_ID 0xFF
|
||||
#define ATH12K_RX_RATE_TABLE_NUM 320
|
||||
#define ATH12K_RX_RATE_TABLE_11AX_NUM 576
|
||||
@@ -129,6 +140,13 @@ struct ath12k_ext_irq_grp {
|
||||
struct net_device napi_ndev;
|
||||
};
|
||||
|
||||
struct ath12k_smbios_bdf {
|
||||
struct dmi_header hdr;
|
||||
u32 padding;
|
||||
u8 bdf_enabled;
|
||||
u8 bdf_ext[];
|
||||
} __packed;
|
||||
|
||||
#define HEHANDLE_CAP_PHYINFO_SIZE 3
|
||||
#define HECAP_PHYINFO_SIZE 9
|
||||
#define HECAP_MACINFO_SIZE 5
|
||||
@@ -792,7 +810,8 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
|
||||
int ath12k_core_fetch_bdf(struct ath12k_base *ath12k,
|
||||
struct ath12k_board_data *bd);
|
||||
void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd);
|
||||
|
||||
int ath12k_core_check_dt(struct ath12k_base *ath12k);
|
||||
int ath12k_core_check_smbios(struct ath12k_base *ab);
|
||||
void ath12k_core_halt(struct ath12k *ar);
|
||||
int ath12k_core_resume(struct ath12k_base *ab);
|
||||
int ath12k_core_suspend(struct ath12k_base *ab);
|
||||
|
||||
@@ -64,7 +64,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask,
|
||||
vaf.va = &args;
|
||||
|
||||
if (ath12k_debug_mask & mask)
|
||||
dev_dbg(ab->dev, "%pV", &vaf);
|
||||
dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
|
||||
|
||||
/* TODO: trace log */
|
||||
|
||||
|
||||
@@ -3526,23 +3526,13 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
|
||||
struct sk_buff_head *msdu_list)
|
||||
{
|
||||
struct ath12k_base *ab = ar->ab;
|
||||
u16 msdu_len, peer_id;
|
||||
u16 msdu_len;
|
||||
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
|
||||
u8 l3pad_bytes;
|
||||
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
|
||||
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
|
||||
|
||||
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
|
||||
peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
|
||||
|
||||
spin_lock(&ab->base_lock);
|
||||
if (!ath12k_peer_find_by_id(ab, peer_id)) {
|
||||
spin_unlock(&ab->base_lock);
|
||||
ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
|
||||
peer_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_unlock(&ab->base_lock);
|
||||
|
||||
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
|
||||
/* First buffer will be freed by the caller, so deduct it's length */
|
||||
|
||||
@@ -4554,7 +4554,8 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
|
||||
}
|
||||
}
|
||||
|
||||
static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
|
||||
static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
|
||||
struct ath12k_band_cap *band_cap,
|
||||
struct ieee80211_he_cap_elem *he_cap_elem,
|
||||
int iftype,
|
||||
struct ieee80211_sta_eht_cap *eht_cap)
|
||||
@@ -4562,6 +4563,10 @@ static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_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));
|
||||
|
||||
if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)))
|
||||
return;
|
||||
|
||||
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));
|
||||
@@ -4627,7 +4632,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
|
||||
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,
|
||||
ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i,
|
||||
&data[idx].eht_cap);
|
||||
idx++;
|
||||
}
|
||||
@@ -5847,6 +5852,59 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static enum wmi_phy_mode
|
||||
ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
|
||||
enum wmi_phy_mode mode,
|
||||
enum nl80211_band band,
|
||||
enum nl80211_iftype type)
|
||||
{
|
||||
struct ieee80211_sta_eht_cap *eht_cap;
|
||||
enum wmi_phy_mode down_mode;
|
||||
|
||||
if (mode < MODE_11BE_EHT20)
|
||||
return mode;
|
||||
|
||||
eht_cap = &ar->mac.iftype[band][type].eht_cap;
|
||||
if (eht_cap->has_eht)
|
||||
return mode;
|
||||
|
||||
switch (mode) {
|
||||
case MODE_11BE_EHT20:
|
||||
down_mode = MODE_11AX_HE20;
|
||||
break;
|
||||
case MODE_11BE_EHT40:
|
||||
down_mode = MODE_11AX_HE40;
|
||||
break;
|
||||
case MODE_11BE_EHT80:
|
||||
down_mode = MODE_11AX_HE80;
|
||||
break;
|
||||
case MODE_11BE_EHT80_80:
|
||||
down_mode = MODE_11AX_HE80_80;
|
||||
break;
|
||||
case MODE_11BE_EHT160:
|
||||
case MODE_11BE_EHT160_160:
|
||||
case MODE_11BE_EHT320:
|
||||
down_mode = MODE_11AX_HE160;
|
||||
break;
|
||||
case MODE_11BE_EHT20_2G:
|
||||
down_mode = MODE_11AX_HE20_2G;
|
||||
break;
|
||||
case MODE_11BE_EHT40_2G:
|
||||
down_mode = MODE_11AX_HE40_2G;
|
||||
break;
|
||||
default:
|
||||
down_mode = mode;
|
||||
break;
|
||||
}
|
||||
|
||||
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
||||
"mac vdev start phymode %s downgrade to %s\n",
|
||||
ath12k_mac_phymode_str(mode),
|
||||
ath12k_mac_phymode_str(down_mode));
|
||||
|
||||
return down_mode;
|
||||
}
|
||||
|
||||
static int
|
||||
ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
@@ -5873,6 +5931,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
|
||||
arg.band_center_freq2 = chandef->center_freq2;
|
||||
arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
|
||||
|
||||
arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
|
||||
chandef->chan->band,
|
||||
arvif->vif->type);
|
||||
arg.min_power = 0;
|
||||
arg.max_power = chandef->chan->max_power * 2;
|
||||
arg.max_reg_power = chandef->chan->max_reg_power * 2;
|
||||
|
||||
@@ -370,8 +370,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
||||
ret = ath12k_mhi_get_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to get msi for mhi\n");
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
goto free_controller;
|
||||
}
|
||||
|
||||
mhi_ctrl->iova_start = 0;
|
||||
@@ -388,11 +387,15 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
|
||||
ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config);
|
||||
if (ret) {
|
||||
ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
return ret;
|
||||
goto free_controller;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_controller:
|
||||
mhi_free_controller(mhi_ctrl);
|
||||
ab_pci->mhi_ctrl = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)
|
||||
|
||||
@@ -2213,6 +2213,7 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
|
||||
struct qmi_txn txn = {};
|
||||
unsigned int board_id = ATH12K_BOARD_ID_DEFAULT;
|
||||
int ret = 0;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
@@ -2297,6 +2298,10 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
|
||||
ab->qmi.target.fw_build_timestamp,
|
||||
ab->qmi.target.fw_build_id);
|
||||
|
||||
r = ath12k_core_check_smbios(ab);
|
||||
if (r)
|
||||
ath12k_dbg(ab, ATH12K_DBG_QMI, "SMBIOS bdf variant name not set.\n");
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2158,6 +2158,9 @@ enum wmi_tlv_service {
|
||||
WMI_MAX_EXT_SERVICE = 256,
|
||||
|
||||
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
|
||||
|
||||
WMI_TLV_SERVICE_11BE = 289,
|
||||
|
||||
WMI_MAX_EXT2_SERVICE,
|
||||
};
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ static void carl9170_usb_tx_data_complete(struct urb *urb)
|
||||
switch (urb->status) {
|
||||
/* everything is fine */
|
||||
case 0:
|
||||
carl9170_tx_callback(ar, (void *)urb->context);
|
||||
carl9170_tx_callback(ar, urb->context);
|
||||
break;
|
||||
|
||||
/* disconnect */
|
||||
@@ -369,7 +369,7 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
|
||||
struct urb *urb;
|
||||
|
||||
while ((urb = usb_get_from_anchor(&ar->tx_err))) {
|
||||
struct sk_buff *skb = (void *)urb->context;
|
||||
struct sk_buff *skb = urb->context;
|
||||
|
||||
carl9170_tx_drop(ar, skb);
|
||||
carl9170_tx_callback(ar, skb);
|
||||
@@ -397,7 +397,7 @@ static void carl9170_usb_tasklet(struct tasklet_struct *t)
|
||||
|
||||
static void carl9170_usb_rx_complete(struct urb *urb)
|
||||
{
|
||||
struct ar9170 *ar = (struct ar9170 *)urb->context;
|
||||
struct ar9170 *ar = urb->context;
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(!ar))
|
||||
@@ -559,7 +559,7 @@ static int carl9170_usb_flush(struct ar9170 *ar)
|
||||
int ret, err = 0;
|
||||
|
||||
while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
|
||||
struct sk_buff *skb = (void *)urb->context;
|
||||
struct sk_buff *skb = urb->context;
|
||||
carl9170_tx_drop(ar, skb);
|
||||
carl9170_tx_callback(ar, skb);
|
||||
usb_free_urb(urb);
|
||||
@@ -668,7 +668,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
|
||||
memcpy(ar->cmd.data, payload, plen);
|
||||
|
||||
spin_lock_bh(&ar->cmd_lock);
|
||||
ar->readbuf = (u8 *)out;
|
||||
ar->readbuf = out;
|
||||
ar->readlen = outlen;
|
||||
spin_unlock_bh(&ar->cmd_lock);
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
|
||||
struct channel_detector {
|
||||
struct list_head head;
|
||||
u16 freq;
|
||||
struct pri_detector **detectors;
|
||||
struct pri_detector *detectors[];
|
||||
};
|
||||
|
||||
/* channel_detector_reset() - reset detector lines for a given channel */
|
||||
@@ -183,14 +183,13 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd,
|
||||
if (cd == NULL)
|
||||
return;
|
||||
list_del(&cd->head);
|
||||
if (cd->detectors) {
|
||||
for (i = 0; i < dpd->num_radar_types; i++) {
|
||||
struct pri_detector *de = cd->detectors[i];
|
||||
if (de != NULL)
|
||||
de->exit(de);
|
||||
}
|
||||
|
||||
for (i = 0; i < dpd->num_radar_types; i++) {
|
||||
struct pri_detector *de = cd->detectors[i];
|
||||
if (de != NULL)
|
||||
de->exit(de);
|
||||
}
|
||||
kfree(cd->detectors);
|
||||
|
||||
kfree(cd);
|
||||
}
|
||||
|
||||
@@ -200,16 +199,12 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
|
||||
u32 i;
|
||||
struct channel_detector *cd;
|
||||
|
||||
cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
|
||||
cd = kzalloc(struct_size(cd, detectors, dpd->num_radar_types), GFP_ATOMIC);
|
||||
if (cd == NULL)
|
||||
goto fail;
|
||||
|
||||
INIT_LIST_HEAD(&cd->head);
|
||||
cd->freq = freq;
|
||||
cd->detectors = kmalloc_array(dpd->num_radar_types,
|
||||
sizeof(*cd->detectors), GFP_ATOMIC);
|
||||
if (cd->detectors == NULL)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < dpd->num_radar_types; i++) {
|
||||
const struct radar_detector_specs *rs = &dpd->radar_spec[i];
|
||||
|
||||
@@ -571,7 +571,6 @@ static const struct {
|
||||
{ REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
|
||||
|
||||
static void build_wpa_mib(struct atmel_private *priv);
|
||||
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
static void atmel_copy_to_card(struct net_device *dev, u16 dest,
|
||||
const unsigned char *src, u16 len);
|
||||
static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
|
||||
@@ -1487,7 +1486,6 @@ static const struct net_device_ops atmel_netdev_ops = {
|
||||
.ndo_stop = atmel_close,
|
||||
.ndo_set_mac_address = atmel_set_mac_address,
|
||||
.ndo_start_xmit = start_tx,
|
||||
.ndo_do_ioctl = atmel_ioctl,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
};
|
||||
|
||||
@@ -2616,76 +2614,6 @@ static const struct iw_handler_def atmel_handler_def = {
|
||||
.get_wireless_stats = atmel_get_wireless_stats
|
||||
};
|
||||
|
||||
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct atmel_private *priv = netdev_priv(dev);
|
||||
struct atmel_priv_ioctl com;
|
||||
struct iwreq *wrq = (struct iwreq *) rq;
|
||||
unsigned char *new_firmware;
|
||||
char domain[REGDOMAINSZ + 1];
|
||||
|
||||
switch (cmd) {
|
||||
case ATMELIDIFC:
|
||||
wrq->u.param.value = ATMELMAGIC;
|
||||
break;
|
||||
|
||||
case ATMELFWL:
|
||||
if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
rc = -EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
new_firmware = memdup_user(com.data, com.len);
|
||||
if (IS_ERR(new_firmware)) {
|
||||
rc = PTR_ERR(new_firmware);
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(priv->firmware);
|
||||
|
||||
priv->firmware = new_firmware;
|
||||
priv->firmware_length = com.len;
|
||||
strncpy(priv->firmware_id, com.id, 31);
|
||||
priv->firmware_id[31] = '\0';
|
||||
break;
|
||||
|
||||
case ATMELRD:
|
||||
if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) {
|
||||
rc = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!capable(CAP_NET_ADMIN)) {
|
||||
rc = -EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
domain[REGDOMAINSZ] = 0;
|
||||
rc = -EINVAL;
|
||||
for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
|
||||
if (!strcasecmp(channel_table[i].name, domain)) {
|
||||
priv->config_reg_domain = channel_table[i].reg_domain;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0 && priv->station_state != STATION_STATE_DOWN)
|
||||
rc = atmel_open(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct auth_body {
|
||||
__le16 alg;
|
||||
__le16 trans_seq;
|
||||
|
||||
@@ -33,7 +33,7 @@ struct brcmf_fweh_queue_item {
|
||||
u8 ifaddr[ETH_ALEN];
|
||||
struct brcmf_event_msg_be emsg;
|
||||
u32 datalen;
|
||||
u8 data[];
|
||||
u8 data[] __counted_by(datalen);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -418,17 +418,17 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
|
||||
datalen + sizeof(*event_packet) > packet_len)
|
||||
return;
|
||||
|
||||
event = kzalloc(sizeof(*event) + datalen, gfp);
|
||||
event = kzalloc(struct_size(event, data, datalen), gfp);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->datalen = datalen;
|
||||
event->code = code;
|
||||
event->ifidx = event_packet->msg.ifidx;
|
||||
|
||||
/* use memcpy to get aligned event message */
|
||||
memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
|
||||
memcpy(event->data, data, datalen);
|
||||
event->datalen = datalen;
|
||||
memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
|
||||
|
||||
brcmf_fweh_queue_event(fweh, event);
|
||||
|
||||
@@ -92,7 +92,6 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb);
|
||||
extern const struct iw_handler_def hostap_iw_handler_def;
|
||||
extern const struct ethtool_ops prism2_ethtool_ops;
|
||||
|
||||
int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||
int hostap_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
|
||||
void __user *data, int cmd);
|
||||
|
||||
|
||||
@@ -732,8 +732,7 @@ static int prism2_download(local_info_t *local,
|
||||
goto out;
|
||||
}
|
||||
|
||||
dl = kzalloc(sizeof(*dl) + param->num_areas *
|
||||
sizeof(struct prism2_download_data_area), GFP_KERNEL);
|
||||
dl = kzalloc(struct_size(dl, data, param->num_areas), GFP_KERNEL);
|
||||
if (dl == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
|
||||
@@ -2316,21 +2316,6 @@ static const struct iw_priv_args prism2_priv[] = {
|
||||
};
|
||||
|
||||
|
||||
static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
union iwreq_data *uwrq, char *extra)
|
||||
@@ -2910,146 +2895,6 @@ static int prism2_ioctl_priv_writemif(struct net_device *dev,
|
||||
}
|
||||
|
||||
|
||||
static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
int ret = 0;
|
||||
union iwreq_data wrqu;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
|
||||
"- update software to use iwconfig mode monitor\n",
|
||||
dev->name, task_pid_nr(current), current->comm);
|
||||
|
||||
/* Backward compatibility code - this can be removed at some point */
|
||||
|
||||
if (*i == 0) {
|
||||
/* Disable monitor mode - old mode was not saved, so go to
|
||||
* Master mode */
|
||||
wrqu.mode = IW_MODE_MASTER;
|
||||
ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL);
|
||||
} else if (*i == 1) {
|
||||
/* netlink socket mode is not supported anymore since it did
|
||||
* not separate different devices from each other and was not
|
||||
* best method for delivering large amount of packets to
|
||||
* user space */
|
||||
ret = -EOPNOTSUPP;
|
||||
} else if (*i == 2 || *i == 3) {
|
||||
switch (*i) {
|
||||
case 2:
|
||||
local->monitor_type = PRISM2_MONITOR_80211;
|
||||
break;
|
||||
case 3:
|
||||
local->monitor_type = PRISM2_MONITOR_PRISM;
|
||||
break;
|
||||
}
|
||||
wrqu.mode = IW_MODE_MONITOR;
|
||||
ret = prism2_ioctl_siwmode(dev, NULL, &wrqu, NULL);
|
||||
hostap_monitor_mode_enable(local);
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_ioctl_priv_reset(struct net_device *dev, int *i)
|
||||
{
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i);
|
||||
switch (*i) {
|
||||
case 0:
|
||||
/* Disable and enable card */
|
||||
local->func->hw_shutdown(dev, 1);
|
||||
local->func->hw_config(dev, 0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* COR sreset */
|
||||
local->func->hw_reset(dev);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Disable and enable port 0 */
|
||||
local->func->reset_port(dev);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING);
|
||||
if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL,
|
||||
NULL))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL,
|
||||
NULL))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_DEBUG "Unknown reset request %d\n", *i);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i)
|
||||
{
|
||||
int rid = *i;
|
||||
int value = *(i + 1);
|
||||
|
||||
printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value);
|
||||
|
||||
if (hostap_set_word(dev, rid, value))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
|
||||
static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (*cmd) {
|
||||
case AP_MAC_CMD_POLICY_OPEN:
|
||||
local->ap->mac_restrictions.policy = MAC_POLICY_OPEN;
|
||||
break;
|
||||
case AP_MAC_CMD_POLICY_ALLOW:
|
||||
local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW;
|
||||
break;
|
||||
case AP_MAC_CMD_POLICY_DENY:
|
||||
local->ap->mac_restrictions.policy = MAC_POLICY_DENY;
|
||||
break;
|
||||
case AP_MAC_CMD_FLUSH:
|
||||
ap_control_flush_macs(&local->ap->mac_restrictions);
|
||||
break;
|
||||
case AP_MAC_CMD_KICKALL:
|
||||
ap_control_kickall(local->ap);
|
||||
hostap_deauth_all_stas(local->dev, local->ap, 0);
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
|
||||
|
||||
#ifdef PRISM2_DOWNLOAD_SUPPORT
|
||||
static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
|
||||
{
|
||||
@@ -3963,79 +3808,6 @@ const struct iw_handler_def hostap_iw_handler_def =
|
||||
.get_wireless_stats = hostap_get_wireless_stats,
|
||||
};
|
||||
|
||||
/* Private ioctls (iwpriv) that have not yet been converted
|
||||
* into new wireless extensions API */
|
||||
int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
struct iwreq *wrq = (struct iwreq *) ifr;
|
||||
struct hostap_interface *iface;
|
||||
local_info_t *local;
|
||||
int ret = 0;
|
||||
|
||||
iface = netdev_priv(dev);
|
||||
local = iface->local;
|
||||
|
||||
switch (cmd) {
|
||||
case PRISM2_IOCTL_INQUIRE:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_MONITOR:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_RESET:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_WDS_ADD:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_WDS_DEL:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_SET_RID_WORD:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = prism2_ioctl_priv_set_rid_word(dev,
|
||||
(int *) wrq->u.name);
|
||||
break;
|
||||
|
||||
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
|
||||
case PRISM2_IOCTL_MACCMD:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name);
|
||||
break;
|
||||
|
||||
case PRISM2_IOCTL_ADDMAC:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = ap_control_add_mac(&local->ap->mac_restrictions,
|
||||
wrq->u.ap_addr.sa_data);
|
||||
break;
|
||||
case PRISM2_IOCTL_DELMAC:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = ap_control_del_mac(&local->ap->mac_restrictions,
|
||||
wrq->u.ap_addr.sa_data);
|
||||
break;
|
||||
case PRISM2_IOCTL_KICKMAC:
|
||||
if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
|
||||
else ret = ap_control_kick_mac(local->ap, local->dev,
|
||||
wrq->u.ap_addr.sa_data);
|
||||
break;
|
||||
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private ioctls that are not used with iwpriv;
|
||||
* in SIOCDEVPRIVATE range */
|
||||
|
||||
@@ -796,7 +796,6 @@ static const struct net_device_ops hostap_netdev_ops = {
|
||||
|
||||
.ndo_open = prism2_open,
|
||||
.ndo_stop = prism2_close,
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_siocdevprivate = hostap_siocdevprivate,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
@@ -809,7 +808,6 @@ static const struct net_device_ops hostap_mgmt_netdev_ops = {
|
||||
|
||||
.ndo_open = prism2_open,
|
||||
.ndo_stop = prism2_close,
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_siocdevprivate = hostap_siocdevprivate,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
@@ -822,7 +820,6 @@ static const struct net_device_ops hostap_master_ops = {
|
||||
|
||||
.ndo_open = prism2_open,
|
||||
.ndo_stop = prism2_close,
|
||||
.ndo_do_ioctl = hostap_ioctl,
|
||||
.ndo_siocdevprivate = hostap_siocdevprivate,
|
||||
.ndo_set_mac_address = prism2_set_mac_address,
|
||||
.ndo_set_rx_mode = hostap_set_multicast_list,
|
||||
|
||||
@@ -617,7 +617,7 @@ struct prism2_download_data {
|
||||
u32 addr; /* wlan card address */
|
||||
u32 len;
|
||||
u8 *data; /* allocated data */
|
||||
} data[];
|
||||
} data[] __counted_by(num_areas);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ struct p54_cal_database {
|
||||
size_t entry_size;
|
||||
size_t offset;
|
||||
size_t len;
|
||||
u8 data[];
|
||||
u8 data[] __counted_by(len);
|
||||
};
|
||||
|
||||
#define EEPROM_READBACK_LEN 0x3fc
|
||||
|
||||
@@ -44,3 +44,4 @@ source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt7996/Kconfig"
|
||||
source "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig"
|
||||
|
||||
@@ -44,3 +44,4 @@ obj-$(CONFIG_MT7615_COMMON) += mt7615/
|
||||
obj-$(CONFIG_MT7915E) += mt7915/
|
||||
obj-$(CONFIG_MT7921_COMMON) += mt7921/
|
||||
obj-$(CONFIG_MT7996E) += mt7996/
|
||||
obj-$(CONFIG_MT7925_COMMON) += mt7925/
|
||||
|
||||
@@ -109,8 +109,6 @@ mt76_register_debugfs_fops(struct mt76_phy *phy,
|
||||
struct dentry *dir;
|
||||
|
||||
dir = debugfs_create_dir("mt76", phy->hw->wiphy->debugfsdir);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
debugfs_create_u8("led_pin", 0600, dir, &phy->leds.pin);
|
||||
debugfs_create_u32("regidx", 0600, dir, &dev->debugfs_reg);
|
||||
|
||||
@@ -53,6 +53,11 @@ mt76_alloc_txwi(struct mt76_dev *dev)
|
||||
|
||||
addr = dma_map_single(dev->dma_dev, txwi, dev->drv->txwi_size,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
|
||||
kfree(txwi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t = (struct mt76_txwi_cache *)(txwi + dev->drv->txwi_size);
|
||||
t->dma_addr = addr;
|
||||
|
||||
@@ -330,9 +335,6 @@ mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
if (e->txwi == DMA_DUMMY_DATA)
|
||||
e->txwi = NULL;
|
||||
|
||||
if (e->skb == DMA_DUMMY_DATA)
|
||||
e->skb = NULL;
|
||||
|
||||
*prev_e = *e;
|
||||
memset(e, 0, sizeof(*e));
|
||||
}
|
||||
@@ -737,16 +739,18 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
if (!q->ndesc)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
do {
|
||||
spin_lock_bh(&q->lock);
|
||||
buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
|
||||
spin_unlock_bh(&q->lock);
|
||||
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
mt76_put_page_pool_buf(buf, false);
|
||||
} while (1);
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
if (q->rx_head) {
|
||||
dev_kfree_skb(q->rx_head);
|
||||
q->rx_head = NULL;
|
||||
|
||||
@@ -188,7 +188,7 @@ static bool mt76_string_prop_find(struct property *prop, const char *str)
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct device_node *
|
||||
struct device_node *
|
||||
mt76_find_power_limits_node(struct mt76_dev *dev)
|
||||
{
|
||||
struct device_node *np = dev->dev->of_node;
|
||||
@@ -227,6 +227,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
|
||||
of_node_put(np);
|
||||
return fallback;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_find_power_limits_node);
|
||||
|
||||
static const __be32 *
|
||||
mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min)
|
||||
@@ -241,7 +242,7 @@ mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min)
|
||||
return prop->value;
|
||||
}
|
||||
|
||||
static struct device_node *
|
||||
struct device_node *
|
||||
mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
|
||||
{
|
||||
struct device_node *cur;
|
||||
@@ -265,6 +266,8 @@ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_find_channel_node);
|
||||
|
||||
|
||||
static s8
|
||||
mt76_get_txs_delta(struct device_node *np, u8 nss)
|
||||
|
||||
@@ -415,6 +415,9 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
spin_lock_init(&phy->tx_lock);
|
||||
|
||||
SET_IEEE80211_DEV(hw, dev->dev);
|
||||
SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
|
||||
|
||||
@@ -452,7 +455,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
|
||||
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
|
||||
|
||||
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
|
||||
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) &&
|
||||
hw->max_tx_fragments > 1) {
|
||||
ieee80211_hw_set(hw, TX_AMSDU);
|
||||
ieee80211_hw_set(hw, TX_FRAG_LIST);
|
||||
}
|
||||
@@ -688,6 +692,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
int ret;
|
||||
|
||||
dev_set_drvdata(dev->dev, dev);
|
||||
mt76_wcid_init(&dev->global_wcid);
|
||||
ret = mt76_phy_init(phy, hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -743,6 +748,7 @@ void mt76_unregister_device(struct mt76_dev *dev)
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS))
|
||||
mt76_led_cleanup(&dev->phy);
|
||||
mt76_tx_status_check(dev, true);
|
||||
mt76_wcid_cleanup(dev, &dev->global_wcid);
|
||||
ieee80211_unregister_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_unregister_device);
|
||||
@@ -1411,7 +1417,7 @@ mt76_sta_add(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
wcid->phy_idx = phy->band_idx;
|
||||
rcu_assign_pointer(dev->wcid[wcid->idx], wcid);
|
||||
|
||||
mt76_packet_id_init(wcid);
|
||||
mt76_wcid_init(wcid);
|
||||
out:
|
||||
mutex_unlock(&dev->mutex);
|
||||
|
||||
@@ -1430,7 +1436,7 @@ void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
if (dev->drv->sta_remove)
|
||||
dev->drv->sta_remove(dev, vif, sta);
|
||||
|
||||
mt76_packet_id_flush(dev, wcid);
|
||||
mt76_wcid_cleanup(dev, wcid);
|
||||
|
||||
mt76_wcid_mask_clear(dev->wcid_mask, idx);
|
||||
mt76_wcid_mask_clear(dev->wcid_phy_mask, idx);
|
||||
@@ -1486,6 +1492,47 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_sta_pre_rcu_remove);
|
||||
|
||||
void mt76_wcid_init(struct mt76_wcid *wcid)
|
||||
{
|
||||
INIT_LIST_HEAD(&wcid->tx_list);
|
||||
skb_queue_head_init(&wcid->tx_pending);
|
||||
|
||||
INIT_LIST_HEAD(&wcid->list);
|
||||
idr_init(&wcid->pktid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_wcid_init);
|
||||
|
||||
void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
{
|
||||
struct mt76_phy *phy = dev->phys[wcid->phy_idx];
|
||||
struct ieee80211_hw *hw;
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *skb;
|
||||
|
||||
mt76_tx_status_lock(dev, &list);
|
||||
mt76_tx_status_skb_get(dev, wcid, -1, &list);
|
||||
mt76_tx_status_unlock(dev, &list);
|
||||
|
||||
idr_destroy(&wcid->pktid);
|
||||
|
||||
spin_lock_bh(&phy->tx_lock);
|
||||
|
||||
if (!list_empty(&wcid->tx_list))
|
||||
list_del_init(&wcid->tx_list);
|
||||
|
||||
spin_lock(&wcid->tx_pending.lock);
|
||||
skb_queue_splice_tail_init(&wcid->tx_pending, &list);
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
spin_unlock_bh(&phy->tx_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)) != NULL) {
|
||||
hw = mt76_tx_status_get_hw(dev, skb);
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int *dbm)
|
||||
{
|
||||
@@ -1697,11 +1744,16 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_init_queue);
|
||||
|
||||
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx)
|
||||
u16 mt76_calculate_default_rate(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif, int rateidx)
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = mvif->ctx ?
|
||||
&mvif->ctx->def :
|
||||
&phy->chandef;
|
||||
int offset = 0;
|
||||
|
||||
if (phy->chandef.chan->band != NL80211_BAND_2GHZ)
|
||||
if (chandef->chan->band != NL80211_BAND_2GHZ)
|
||||
offset = 4;
|
||||
|
||||
/* pick the lowest rate for hidden nodes */
|
||||
|
||||
@@ -334,6 +334,9 @@ struct mt76_wcid {
|
||||
u32 tx_info;
|
||||
bool sw_iv;
|
||||
|
||||
struct list_head tx_list;
|
||||
struct sk_buff_head tx_pending;
|
||||
|
||||
struct list_head list;
|
||||
struct idr pktid;
|
||||
|
||||
@@ -376,7 +379,7 @@ struct mt76_rx_tid {
|
||||
|
||||
u8 started:1, stopped:1, timer_pending:1;
|
||||
|
||||
struct sk_buff *reorder_buf[];
|
||||
struct sk_buff *reorder_buf[] __counted_by(size);
|
||||
};
|
||||
|
||||
#define MT_TX_CB_DMA_DONE BIT(0)
|
||||
@@ -709,6 +712,7 @@ struct mt76_vif {
|
||||
u8 basic_rates_idx;
|
||||
u8 mcast_rates_idx;
|
||||
u8 beacon_rates_idx;
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
};
|
||||
|
||||
struct mt76_phy {
|
||||
@@ -719,6 +723,8 @@ struct mt76_phy {
|
||||
unsigned long state;
|
||||
u8 band_idx;
|
||||
|
||||
spinlock_t tx_lock;
|
||||
struct list_head tx_list;
|
||||
struct mt76_queue *q_tx[__MT_TXQ_MAX];
|
||||
|
||||
struct cfg80211_chan_def chandef;
|
||||
@@ -967,6 +973,7 @@ struct mt76_power_limits {
|
||||
s8 ofdm[8];
|
||||
s8 mcs[4][10];
|
||||
s8 ru[7][12];
|
||||
s8 eht[16][16];
|
||||
};
|
||||
|
||||
struct mt76_ethtool_worker_info {
|
||||
@@ -1100,7 +1107,8 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
|
||||
struct mt76_queue *
|
||||
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
|
||||
int ring_base, u32 flags);
|
||||
u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx);
|
||||
u16 mt76_calculate_default_rate(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif, int rateidx);
|
||||
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
|
||||
int n_desc, int ring_base, u32 flags)
|
||||
{
|
||||
@@ -1529,6 +1537,11 @@ mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd,
|
||||
|
||||
void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);
|
||||
|
||||
struct device_node *
|
||||
mt76_find_power_limits_node(struct mt76_dev *dev);
|
||||
struct device_node *
|
||||
mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan);
|
||||
|
||||
s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
struct mt76_power_limits *dest,
|
||||
@@ -1598,22 +1611,7 @@ mt76_token_put(struct mt76_dev *dev, int token)
|
||||
return txwi;
|
||||
}
|
||||
|
||||
static inline void mt76_packet_id_init(struct mt76_wcid *wcid)
|
||||
{
|
||||
INIT_LIST_HEAD(&wcid->list);
|
||||
idr_init(&wcid->pktid);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mt76_packet_id_flush(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
{
|
||||
struct sk_buff_head list;
|
||||
|
||||
mt76_tx_status_lock(dev, &list);
|
||||
mt76_tx_status_skb_get(dev, wcid, -1, &list);
|
||||
mt76_tx_status_unlock(dev, &list);
|
||||
|
||||
idr_destroy(&wcid->pktid);
|
||||
}
|
||||
void mt76_wcid_init(struct mt76_wcid *wcid);
|
||||
void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,23 @@ struct beacon_bc_data {
|
||||
int count[MT7603_MAX_INTERFACES];
|
||||
};
|
||||
|
||||
static void
|
||||
mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev)
|
||||
{
|
||||
if (dev->beacon_check % 5 != 4)
|
||||
return;
|
||||
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
|
||||
mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);
|
||||
mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);
|
||||
|
||||
mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
|
||||
mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
|
||||
mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);
|
||||
mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -16,6 +33,8 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
|
||||
struct sk_buff *skb = NULL;
|
||||
u32 om_idx = mvif->idx;
|
||||
u32 val;
|
||||
|
||||
if (!(mdev->beacon_mask & BIT(mvif->idx)))
|
||||
return;
|
||||
@@ -24,20 +43,33 @@ mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
if (om_idx)
|
||||
om_idx |= 0x10;
|
||||
val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE |
|
||||
FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) |
|
||||
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
|
||||
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8);
|
||||
|
||||
spin_lock_bh(&dev->ps_lock);
|
||||
|
||||
mt76_wr(dev, MT_DMA_FQCR0, val |
|
||||
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN));
|
||||
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
|
||||
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_DMA_FQCR0, val |
|
||||
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC));
|
||||
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {
|
||||
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],
|
||||
MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);
|
||||
|
||||
spin_lock_bh(&dev->ps_lock);
|
||||
mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY |
|
||||
FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) |
|
||||
FIELD_PREP(MT_DMA_FQCR0_TARGET_QID,
|
||||
dev->mphy.q_tx[MT_TXQ_CAB]->hw_idx) |
|
||||
FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |
|
||||
FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8));
|
||||
|
||||
if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000))
|
||||
dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&dev->ps_lock);
|
||||
}
|
||||
|
||||
@@ -81,6 +113,18 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
data.dev = dev;
|
||||
__skb_queue_head_init(&data.q);
|
||||
|
||||
/* Flush all previous CAB queue packets and beacons */
|
||||
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
|
||||
|
||||
if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0)
|
||||
dev->beacon_check++;
|
||||
else
|
||||
dev->beacon_check = 0;
|
||||
mt7603_mac_stuck_beacon_recovery(dev);
|
||||
|
||||
q = dev->mphy.q_tx[MT_TXQ_BEACON];
|
||||
spin_lock(&q->lock);
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
@@ -89,14 +133,9 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
mt76_queue_kick(dev, q);
|
||||
spin_unlock(&q->lock);
|
||||
|
||||
/* Flush all previous CAB queue packets */
|
||||
mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);
|
||||
|
||||
mt76_csa_check(mdev);
|
||||
if (mdev->csa_complete)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
q = dev->mphy.q_tx[MT_TXQ_CAB];
|
||||
do {
|
||||
@@ -108,7 +147,7 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
skb_queue_len(&data.q) < 8);
|
||||
|
||||
if (skb_queue_empty(&data.q))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(data.tail); i++) {
|
||||
if (!data.tail[i])
|
||||
@@ -136,11 +175,6 @@ void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
MT_WF_ARB_CAB_START_BSSn(0) |
|
||||
(MT_WF_ARB_CAB_START_BSS0n(1) *
|
||||
((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));
|
||||
|
||||
out:
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);
|
||||
if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > hweight8(mdev->beacon_mask))
|
||||
dev->beacon_check++;
|
||||
}
|
||||
|
||||
void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)
|
||||
|
||||
@@ -42,11 +42,13 @@ irqreturn_t mt7603_irq_handler(int irq, void *dev_instance)
|
||||
}
|
||||
|
||||
if (intr & MT_INT_RX_DONE(0)) {
|
||||
dev->rx_pse_check = 0;
|
||||
mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
|
||||
napi_schedule(&dev->mt76.napi[0]);
|
||||
}
|
||||
|
||||
if (intr & MT_INT_RX_DONE(1)) {
|
||||
dev->rx_pse_check = 0;
|
||||
mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
|
||||
napi_schedule(&dev->mt76.napi[1]);
|
||||
}
|
||||
|
||||
@@ -184,6 +184,13 @@ mt7603_mac_init(struct mt7603_dev *dev)
|
||||
|
||||
mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE);
|
||||
|
||||
if (is_mt7628(dev)) {
|
||||
mt76_set(dev, MT_TMAC_TCR,
|
||||
MT_TMAC_TCR_TXOP_BURST_STOP | BIT(1) | BIT(0));
|
||||
mt76_set(dev, MT_TXREQ, BIT(27));
|
||||
mt76_set(dev, MT_AGG_TMP, GENMASK(4, 2));
|
||||
}
|
||||
|
||||
mt7603_set_tmac_template(dev);
|
||||
|
||||
/* Enable RX group to HIF */
|
||||
@@ -517,6 +524,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
|
||||
hw->max_rates = 3;
|
||||
hw->max_report_rates = 7;
|
||||
hw->max_rate_tries = 11;
|
||||
hw->max_tx_fragments = 1;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
@@ -1441,15 +1441,6 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
|
||||
|
||||
mt7603_beacon_set_timer(dev, -1, 0);
|
||||
|
||||
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
|
||||
dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY ||
|
||||
dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK ||
|
||||
dev->cur_reset_cause == RESET_CAUSE_TX_HANG)
|
||||
mt7603_pse_reset(dev);
|
||||
|
||||
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED])
|
||||
goto skip_dma_reset;
|
||||
|
||||
mt7603_mac_stop(dev);
|
||||
|
||||
mt76_clear(dev, MT_WPDMA_GLO_CFG,
|
||||
@@ -1459,28 +1450,32 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev)
|
||||
|
||||
mt7603_irq_disable(dev, mask);
|
||||
|
||||
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
|
||||
|
||||
mt7603_pse_client_reset(dev);
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true);
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
|
||||
|
||||
mt7603_dma_sched_reset(dev);
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
}
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] ||
|
||||
dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY)
|
||||
mt7603_pse_reset(dev);
|
||||
|
||||
mt7603_dma_sched_reset(dev);
|
||||
if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) {
|
||||
mt7603_mac_dma_start(dev);
|
||||
|
||||
mt7603_mac_dma_start(dev);
|
||||
mt7603_irq_enable(dev, mask);
|
||||
|
||||
mt7603_irq_enable(dev, mask);
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
}
|
||||
|
||||
skip_dma_reset:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
@@ -1570,20 +1565,29 @@ static bool mt7603_rx_pse_busy(struct mt7603_dev *dev)
|
||||
{
|
||||
u32 addr, val;
|
||||
|
||||
if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
|
||||
return true;
|
||||
|
||||
if (mt7603_rx_fifo_busy(dev))
|
||||
return false;
|
||||
goto out;
|
||||
|
||||
addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
|
||||
mt76_wr(dev, addr, 3);
|
||||
val = mt76_rr(dev, addr) >> 16;
|
||||
|
||||
if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
|
||||
return true;
|
||||
if (!(val & BIT(0)))
|
||||
return false;
|
||||
|
||||
return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
|
||||
if (is_mt7628(dev))
|
||||
val &= 0xa000;
|
||||
else
|
||||
val &= 0x8000;
|
||||
if (!val)
|
||||
return false;
|
||||
|
||||
out:
|
||||
if (mt76_rr(dev, MT_INT_SOURCE_CSR) &
|
||||
(MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -70,7 +70,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.vif = mvif;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
eth_broadcast_addr(bc_addr);
|
||||
mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);
|
||||
@@ -110,7 +110,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
|
||||
}
|
||||
|
||||
void mt7603_init_edcca(struct mt7603_dev *dev)
|
||||
|
||||
@@ -469,6 +469,11 @@ enum {
|
||||
#define MT_WF_SEC_BASE 0x21a00
|
||||
#define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs))
|
||||
|
||||
#define MT_WF_CFG_OFF_BASE 0x21e00
|
||||
#define MT_WF_CFG_OFF(ofs) (MT_WF_CFG_OFF_BASE + (ofs))
|
||||
#define MT_WF_CFG_OFF_WOCCR MT_WF_CFG_OFF(0x004)
|
||||
#define MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS BIT(4)
|
||||
|
||||
#define MT_SEC_SCR MT_WF_SEC(0x004)
|
||||
#define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0)
|
||||
|
||||
|
||||
@@ -58,10 +58,7 @@ int mt7615_thermal_init(struct mt7615_dev *dev)
|
||||
wiphy_name(wiphy));
|
||||
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, dev,
|
||||
mt7615_hwmon_groups);
|
||||
if (IS_ERR(hwmon))
|
||||
return PTR_ERR(hwmon);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7615_thermal_init);
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
|
||||
mvif->sta.wcid.idx = idx;
|
||||
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
mt7615_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -279,7 +279,7 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
|
||||
list_del_init(&msta->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->sta.wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);
|
||||
}
|
||||
|
||||
int mt7615_set_channel(struct mt7615_phy *phy)
|
||||
|
||||
@@ -2147,7 +2147,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
|
||||
};
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
|
||||
@@ -106,7 +106,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
else
|
||||
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
|
||||
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
tx_info->skb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -172,6 +172,11 @@ struct mt76_connac_tx_free {
|
||||
|
||||
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
|
||||
|
||||
static inline bool is_mt7925(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7925;
|
||||
}
|
||||
|
||||
static inline bool is_mt7922(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7922;
|
||||
@@ -245,6 +250,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
|
||||
switch (mt76_chip(dev)) {
|
||||
case 0x7961:
|
||||
case 0x7922:
|
||||
case 0x7925:
|
||||
case 0x7663:
|
||||
case 0x7622:
|
||||
return false;
|
||||
|
||||
@@ -257,6 +257,8 @@ enum tx_mgnt_type {
|
||||
#define MT_TXD7_UDP_TCP_SUM BIT(15)
|
||||
#define MT_TXD7_TX_TIME GENMASK(9, 0)
|
||||
|
||||
#define MT_TXD9_WLAN_IDX GENMASK(23, 8)
|
||||
|
||||
#define MT_TX_RATE_STBC BIT(14)
|
||||
#define MT_TX_RATE_NSS GENMASK(13, 10)
|
||||
#define MT_TX_RATE_MODE GENMASK(9, 6)
|
||||
@@ -269,7 +271,7 @@ enum tx_mgnt_type {
|
||||
#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_TXFREE1_VER GENMASK(19, 16)
|
||||
|
||||
#define MT_TXFREE_INFO_PAIR BIT(31)
|
||||
#define MT_TXFREE_INFO_HEADER BIT(30)
|
||||
@@ -315,6 +317,7 @@ enum tx_mgnt_type {
|
||||
|
||||
#define MT_TXS4_TIMESTAMP GENMASK(31, 0)
|
||||
|
||||
/* MPDU based TXS */
|
||||
#define MT_TXS5_F0_FINAL_MPDU BIT(31)
|
||||
#define MT_TXS5_F0_QOS BIT(30)
|
||||
#define MT_TXS5_F0_TX_COUNT GENMASK(29, 25)
|
||||
@@ -336,4 +339,17 @@ enum tx_mgnt_type {
|
||||
#define MT_TXS7_F1_MPDU_RETRY_COUNT GENMASK(31, 24)
|
||||
#define MT_TXS7_F1_MPDU_RETRY_BYTES GENMASK(23, 0)
|
||||
|
||||
/* PPDU based TXS */
|
||||
#define MT_TXS5_MPDU_TX_CNT GENMASK(30, 20)
|
||||
#define MT_TXS5_MPDU_TX_BYTE_SCALE BIT(15)
|
||||
#define MT_TXS5_MPDU_TX_BYTE GENMASK(14, 0)
|
||||
|
||||
#define MT_TXS6_MPDU_FAIL_CNT GENMASK(30, 20)
|
||||
#define MT_TXS6_MPDU_FAIL_BYTE_SCALE BIT(15)
|
||||
#define MT_TXS6_MPDU_FAIL_BYTE GENMASK(14, 0)
|
||||
|
||||
#define MT_TXS7_MPDU_RETRY_CNT GENMASK(30, 20)
|
||||
#define MT_TXS7_MPDU_RETRY_BYTE_SCALE BIT(15)
|
||||
#define MT_TXS7_MPDU_RETRY_BYTE GENMASK(14, 0)
|
||||
|
||||
#endif /* __MT76_CONNAC3_MAC_H */
|
||||
|
||||
@@ -151,23 +151,6 @@ void mt76_connac_tx_complete_skb(struct mt76_dev *mdev,
|
||||
return;
|
||||
}
|
||||
|
||||
/* error path */
|
||||
if (e->skb == DMA_DUMMY_DATA) {
|
||||
struct mt76_connac_txp_common *txp;
|
||||
struct mt76_txwi_cache *t;
|
||||
u16 token;
|
||||
|
||||
txp = mt76_connac_txwi_to_txp(mdev, e->txwi);
|
||||
if (is_mt76_fw_txp(mdev))
|
||||
token = le16_to_cpu(txp->fw.token);
|
||||
else
|
||||
token = le16_to_cpu(txp->hw.msdu_id[0]) &
|
||||
~MT_MSDU_ID_VALID;
|
||||
|
||||
t = mt76_token_put(mdev, token);
|
||||
e->skb = t ? t->skb : NULL;
|
||||
}
|
||||
|
||||
if (e->skb)
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
@@ -187,7 +170,7 @@ void mt76_connac_write_hw_txp(struct mt76_dev *dev,
|
||||
|
||||
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev))
|
||||
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_AMSDU_LAST |
|
||||
@@ -231,7 +214,7 @@ mt76_connac_txp_skb_unmap_hw(struct mt76_dev *dev,
|
||||
u32 last_mask;
|
||||
int i;
|
||||
|
||||
if (is_mt7663(dev) || is_mt7921(dev))
|
||||
if (is_mt7663(dev) || is_mt7921(dev) || is_mt7925(dev))
|
||||
last_mask = MT_TXD_LEN_LAST;
|
||||
else
|
||||
last_mask = MT_TXD_LEN_MSDU_LAST;
|
||||
@@ -310,7 +293,10 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
{
|
||||
u8 nss = 0, mode = 0, band = mphy->chandef.chan->band;
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = mvif->ctx ?
|
||||
&mvif->ctx->def : &mphy->chandef;
|
||||
u8 nss = 0, mode = 0, band = chandef->chan->band;
|
||||
int rateidx = 0, mcast_rate;
|
||||
|
||||
if (!vif)
|
||||
@@ -343,7 +329,7 @@ u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
|
||||
legacy:
|
||||
rateidx = mt76_calculate_default_rate(mphy, rateidx);
|
||||
rateidx = mt76_calculate_default_rate(mphy, vif, rateidx);
|
||||
mode = rateidx >> 8;
|
||||
rateidx &= GENMASK(7, 0);
|
||||
out:
|
||||
|
||||
@@ -66,6 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
|
||||
|
||||
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
|
||||
(is_mt7921(dev) && addr == 0x900000) ||
|
||||
(is_mt7925(dev) && addr == 0x900000) ||
|
||||
(is_mt7996(dev) && addr == 0x900000))
|
||||
cmd = MCU_CMD(PATCH_START_REQ);
|
||||
else
|
||||
@@ -745,7 +746,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
he->pkt_ext = 2;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
|
||||
@@ -777,20 +778,23 @@ mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
|
||||
he->pkt_ext = IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2);
|
||||
|
||||
static u8
|
||||
u8
|
||||
mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
struct ieee80211_sta_vht_cap *vht_cap;
|
||||
const struct ieee80211_sta_he_cap *he_cap;
|
||||
const struct ieee80211_sta_eht_cap *eht_cap;
|
||||
u8 mode = 0;
|
||||
|
||||
if (sta) {
|
||||
ht_cap = &sta->deflink.ht_cap;
|
||||
vht_cap = &sta->deflink.vht_cap;
|
||||
he_cap = &sta->deflink.he_cap;
|
||||
eht_cap = &sta->deflink.eht_cap;
|
||||
} else {
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
@@ -798,6 +802,7 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
ht_cap = &sband->ht_cap;
|
||||
vht_cap = &sband->vht_cap;
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);
|
||||
eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_2GHZ) {
|
||||
@@ -808,6 +813,9 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_TYPE_BIT_HE;
|
||||
|
||||
if (eht_cap && eht_cap->has_eht)
|
||||
mode |= PHY_TYPE_BIT_BE;
|
||||
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
|
||||
mode |= PHY_TYPE_BIT_OFDM;
|
||||
|
||||
@@ -819,17 +827,23 @@ mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_TYPE_BIT_HE;
|
||||
|
||||
if (eht_cap && eht_cap->has_eht)
|
||||
mode |= PHY_TYPE_BIT_BE;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_v2);
|
||||
|
||||
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif,
|
||||
u8 rcpi, u8 sta_state)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &mphy->chandef;
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = mvif->ctx ?
|
||||
&mvif->ctx->def : &mphy->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct mt76_dev *dev = mphy->dev;
|
||||
struct sta_rec_ra_info *ra_info;
|
||||
@@ -1369,7 +1383,10 @@ EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext);
|
||||
const struct ieee80211_sta_he_cap *
|
||||
mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)
|
||||
{
|
||||
enum nl80211_band band = phy->chandef.chan->band;
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = mvif->ctx ?
|
||||
&mvif->ctx->def : &phy->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = phy->hw->wiphy->bands[band];
|
||||
@@ -1924,126 +1941,6 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);
|
||||
|
||||
static void mt76_connac_mcu_parse_tx_resource(struct mt76_dev *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_sdio *sdio = &dev->sdio;
|
||||
struct mt76_connac_tx_resource {
|
||||
__le32 version;
|
||||
__le32 pse_data_quota;
|
||||
__le32 pse_mcu_quota;
|
||||
__le32 ple_data_quota;
|
||||
__le32 ple_mcu_quota;
|
||||
__le16 pse_page_size;
|
||||
__le16 ple_page_size;
|
||||
u8 pp_padding;
|
||||
u8 pad[3];
|
||||
} __packed * tx_res;
|
||||
|
||||
tx_res = (struct mt76_connac_tx_resource *)skb->data;
|
||||
sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);
|
||||
sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota);
|
||||
sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);
|
||||
sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);
|
||||
sdio->sched.deficit = tx_res->pp_padding;
|
||||
}
|
||||
|
||||
static void mt76_connac_mcu_parse_phy_cap(struct mt76_dev *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_connac_phy_cap {
|
||||
u8 ht;
|
||||
u8 vht;
|
||||
u8 _5g;
|
||||
u8 max_bw;
|
||||
u8 nss;
|
||||
u8 dbdc;
|
||||
u8 tx_ldpc;
|
||||
u8 rx_ldpc;
|
||||
u8 tx_stbc;
|
||||
u8 rx_stbc;
|
||||
u8 hw_path;
|
||||
u8 he;
|
||||
} __packed * cap;
|
||||
|
||||
enum {
|
||||
WF0_24G,
|
||||
WF0_5G
|
||||
};
|
||||
|
||||
cap = (struct mt76_connac_phy_cap *)skb->data;
|
||||
|
||||
dev->phy.antenna_mask = BIT(cap->nss) - 1;
|
||||
dev->phy.chainmask = dev->phy.antenna_mask;
|
||||
dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
|
||||
dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
|
||||
}
|
||||
|
||||
int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy)
|
||||
{
|
||||
struct mt76_connac_cap_hdr {
|
||||
__le16 n_element;
|
||||
u8 rsv[2];
|
||||
} __packed * hdr;
|
||||
struct sk_buff *skb;
|
||||
int ret, i;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),
|
||||
NULL, 0, true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = (struct mt76_connac_cap_hdr *)skb->data;
|
||||
if (skb->len < sizeof(*hdr)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
|
||||
for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
|
||||
struct tlv_hdr {
|
||||
__le32 type;
|
||||
__le32 len;
|
||||
} __packed * tlv = (struct tlv_hdr *)skb->data;
|
||||
int len;
|
||||
|
||||
if (skb->len < sizeof(*tlv))
|
||||
break;
|
||||
|
||||
skb_pull(skb, sizeof(*tlv));
|
||||
|
||||
len = le32_to_cpu(tlv->len);
|
||||
if (skb->len < len)
|
||||
break;
|
||||
|
||||
switch (le32_to_cpu(tlv->type)) {
|
||||
case MT_NIC_CAP_6G:
|
||||
phy->cap.has_6ghz = skb->data[0];
|
||||
break;
|
||||
case MT_NIC_CAP_MAC_ADDR:
|
||||
memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);
|
||||
break;
|
||||
case MT_NIC_CAP_PHY:
|
||||
mt76_connac_mcu_parse_phy_cap(phy->dev, skb);
|
||||
break;
|
||||
case MT_NIC_CAP_TX_RESOURCE:
|
||||
if (mt76_is_sdio(phy->dev))
|
||||
mt76_connac_mcu_parse_tx_resource(phy->dev,
|
||||
skb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
skb_pull(skb, len);
|
||||
}
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_get_nic_capability);
|
||||
|
||||
static void
|
||||
mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
|
||||
struct mt76_power_limits *limits,
|
||||
@@ -2087,9 +1984,9 @@ mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
|
||||
}
|
||||
}
|
||||
|
||||
static s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
s8 target_power)
|
||||
s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
s8 target_power)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct ieee80211_supported_band *sband;
|
||||
@@ -2126,6 +2023,7 @@ static s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
|
||||
|
||||
return target_power;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_ch_power);
|
||||
|
||||
static int
|
||||
mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
@@ -2144,7 +2042,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
112, 114, 116, 118, 120, 122, 124,
|
||||
126, 128, 132, 134, 136, 138, 140,
|
||||
142, 144, 149, 151, 153, 155, 157,
|
||||
159, 161, 165
|
||||
159, 161, 165, 169, 173, 177
|
||||
};
|
||||
static const u8 chan_list_6ghz[] = {
|
||||
1, 3, 5, 7, 9, 11, 13,
|
||||
@@ -2164,11 +2062,15 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
209, 211, 213, 215, 217, 219, 221,
|
||||
225, 227, 229, 233
|
||||
};
|
||||
int i, n_chan, batch_size, idx = 0, tx_power, last_ch;
|
||||
int i, n_chan, batch_size, idx = 0, tx_power, last_ch, err = 0;
|
||||
struct mt76_connac_sku_tlv sku_tlbv;
|
||||
struct mt76_power_limits limits;
|
||||
struct mt76_power_limits *limits;
|
||||
const u8 *ch_list;
|
||||
|
||||
limits = devm_kmalloc(dev->dev, sizeof(*limits), GFP_KERNEL);
|
||||
if (!limits)
|
||||
return -ENOMEM;
|
||||
|
||||
sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
|
||||
tx_power = 2 * phy->hw->conf.power_level;
|
||||
if (!tx_power)
|
||||
@@ -2195,14 +2097,16 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
|
||||
for (i = 0; i < batch_size; i++) {
|
||||
struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {};
|
||||
int j, err, msg_len, num_ch;
|
||||
int j, msg_len, num_ch;
|
||||
struct sk_buff *skb;
|
||||
|
||||
num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len;
|
||||
msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
|
||||
skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb_reserve(skb, sizeof(tx_power_tlv));
|
||||
|
||||
@@ -2233,14 +2137,14 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
tx_power);
|
||||
sar_power = mt76_get_sar_power(phy, &chan, reg_power);
|
||||
|
||||
mt76_get_rate_power_limits(phy, &chan, &limits,
|
||||
mt76_get_rate_power_limits(phy, &chan, limits,
|
||||
sar_power);
|
||||
|
||||
tx_power_tlv.last_msg = ch_list[idx] == last_ch;
|
||||
sku_tlbv.channel = ch_list[idx];
|
||||
|
||||
mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
|
||||
&limits, band);
|
||||
limits, band);
|
||||
skb_put_data(skb, &sku_tlbv, sku_len);
|
||||
}
|
||||
__skb_push(skb, sizeof(tx_power_tlv));
|
||||
@@ -2250,10 +2154,12 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
|
||||
MCU_CE_CMD(SET_RATE_TX_POWER),
|
||||
false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
devm_kfree(dev->dev, limits);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
|
||||
@@ -2457,7 +2363,7 @@ mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
sizeof(req), true);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
bool suspend)
|
||||
{
|
||||
@@ -2482,8 +2388,9 @@ mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_gtk_rekey);
|
||||
|
||||
static int
|
||||
int
|
||||
mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable, u8 mdtim,
|
||||
@@ -2512,6 +2419,7 @@ mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
|
||||
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_mode);
|
||||
|
||||
static int
|
||||
mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
|
||||
@@ -2547,7 +2455,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
|
||||
return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
bool suspend, struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
@@ -2599,6 +2507,7 @@ mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_wow_ctrl);
|
||||
|
||||
int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend)
|
||||
{
|
||||
@@ -3064,7 +2973,7 @@ static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
|
||||
@@ -191,6 +191,7 @@ struct mt76_connac2_fw_region {
|
||||
struct tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct bss_info_omac {
|
||||
@@ -795,6 +796,7 @@ enum {
|
||||
STA_REC_PHY = 0x15,
|
||||
STA_REC_HE_6G = 0x17,
|
||||
STA_REC_HE_V2 = 0x19,
|
||||
STA_REC_MLD = 0x20,
|
||||
STA_REC_EHT = 0x22,
|
||||
STA_REC_HDRT = 0x28,
|
||||
STA_REC_HDR_TRANS = 0x2B,
|
||||
@@ -919,6 +921,7 @@ enum {
|
||||
PHY_TYPE_HT_INDEX,
|
||||
PHY_TYPE_VHT_INDEX,
|
||||
PHY_TYPE_HE_INDEX,
|
||||
PHY_TYPE_BE_INDEX,
|
||||
PHY_TYPE_INDEX_NUM
|
||||
};
|
||||
|
||||
@@ -928,6 +931,7 @@ enum {
|
||||
#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX)
|
||||
#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX)
|
||||
#define PHY_TYPE_BIT_HE BIT(PHY_TYPE_HE_INDEX)
|
||||
#define PHY_TYPE_BIT_BE BIT(PHY_TYPE_BE_INDEX)
|
||||
|
||||
#define MT_WTBL_RATE_TX_MODE GENMASK(9, 6)
|
||||
#define MT_WTBL_RATE_MCS GENMASK(5, 0)
|
||||
@@ -1009,8 +1013,17 @@ enum {
|
||||
enum {
|
||||
MCU_UNI_EVENT_RESULT = 0x01,
|
||||
MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
|
||||
MCU_UNI_EVENT_ACCESS_REG = 0x6,
|
||||
MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
|
||||
MCU_UNI_EVENT_COREDUMP = 0x0a,
|
||||
MCU_UNI_EVENT_BSS_BEACON_LOSS = 0x0c,
|
||||
MCU_UNI_EVENT_SCAN_DONE = 0x0e,
|
||||
MCU_UNI_EVENT_RDD_REPORT = 0x11,
|
||||
MCU_UNI_EVENT_ROC = 0x27,
|
||||
MCU_UNI_EVENT_TX_DONE = 0x2d,
|
||||
MCU_UNI_EVENT_NIC_CAPAB = 0x43,
|
||||
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
|
||||
MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
|
||||
};
|
||||
|
||||
#define MCU_UNI_CMD_EVENT BIT(1)
|
||||
@@ -1209,12 +1222,17 @@ enum {
|
||||
MCU_UNI_CMD_RX_HDR_TRANS = 0x12,
|
||||
MCU_UNI_CMD_SER = 0x13,
|
||||
MCU_UNI_CMD_TWT = 0x14,
|
||||
MCU_UNI_CMD_SET_DOMAIN_INFO = 0x15,
|
||||
MCU_UNI_CMD_SCAN_REQ = 0x16,
|
||||
MCU_UNI_CMD_RDD_CTRL = 0x19,
|
||||
MCU_UNI_CMD_GET_MIB_INFO = 0x22,
|
||||
MCU_UNI_CMD_GET_STAT_INFO = 0x23,
|
||||
MCU_UNI_CMD_SNIFFER = 0x24,
|
||||
MCU_UNI_CMD_SR = 0x25,
|
||||
MCU_UNI_CMD_ROC = 0x27,
|
||||
MCU_UNI_CMD_SET_DBDC_PARMS = 0x28,
|
||||
MCU_UNI_CMD_TXPOWER = 0x2b,
|
||||
MCU_UNI_CMD_SET_POWER_LIMIT = 0x2c,
|
||||
MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
|
||||
MCU_UNI_CMD_RA = 0x2f,
|
||||
MCU_UNI_CMD_MURU = 0x31,
|
||||
@@ -1224,6 +1242,8 @@ enum {
|
||||
MCU_UNI_CMD_VOW = 0x37,
|
||||
MCU_UNI_CMD_RRO = 0x57,
|
||||
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
|
||||
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
|
||||
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
|
||||
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
|
||||
};
|
||||
|
||||
@@ -1279,6 +1299,7 @@ enum {
|
||||
UNI_BSS_INFO_RLM = 2,
|
||||
UNI_BSS_INFO_BSS_COLOR = 4,
|
||||
UNI_BSS_INFO_HE_BASIC = 5,
|
||||
UNI_BSS_INFO_11V_MBSSID = 6,
|
||||
UNI_BSS_INFO_BCN_CONTENT = 7,
|
||||
UNI_BSS_INFO_BCN_CSA = 8,
|
||||
UNI_BSS_INFO_BCN_BCC = 9,
|
||||
@@ -1293,6 +1314,7 @@ enum {
|
||||
UNI_BSS_INFO_IFS_TIME = 23,
|
||||
UNI_BSS_INFO_OFFLOAD = 25,
|
||||
UNI_BSS_INFO_MLD = 26,
|
||||
UNI_BSS_INFO_PM_DISABLE = 27,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1302,6 +1324,17 @@ enum {
|
||||
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
|
||||
};
|
||||
|
||||
enum UNI_ALL_STA_INFO_TAG {
|
||||
UNI_ALL_STA_TX_RATE,
|
||||
UNI_ALL_STA_TX_STAT,
|
||||
UNI_ALL_STA_TXRX_ADM_STAT,
|
||||
UNI_ALL_STA_TXRX_AIR_TIME,
|
||||
UNI_ALL_STA_DATA_TX_RETRY_COUNT,
|
||||
UNI_ALL_STA_GI_MODE,
|
||||
UNI_ALL_STA_TXRX_MSDU_COUNT,
|
||||
UNI_ALL_STA_MAX_NUM
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_NIC_CAP_TX_RESOURCE,
|
||||
MT_NIC_CAP_TX_EFUSE_ADDR,
|
||||
@@ -1322,6 +1355,7 @@ enum {
|
||||
MT_NIC_CAP_ANTSWP = 0x16,
|
||||
MT_NIC_CAP_WFDMA_REALLOC,
|
||||
MT_NIC_CAP_6G,
|
||||
MT_NIC_CAP_CHIP_CAP = 0x20,
|
||||
};
|
||||
|
||||
#define UNI_WOW_DETECT_TYPE_MAGIC BIT(0)
|
||||
@@ -1549,6 +1583,15 @@ struct bss_info_uni_he {
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct bss_info_uni_mbssid {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 max_indicator;
|
||||
u8 mbss_idx;
|
||||
u8 tx_bss_omac_idx;
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
struct mt76_connac_gtk_rekey_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -1739,7 +1782,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa)
|
||||
|
||||
ret |= feature_set & FW_FEATURE_SET_ENCRYPT ?
|
||||
DL_MODE_ENCRYPT | DL_MODE_RESET_SEC_IV : 0;
|
||||
if (is_mt7921(dev))
|
||||
if (is_mt7921(dev) || is_mt7925(dev))
|
||||
ret |= feature_set & FW_FEATURE_ENCRY_MODE ?
|
||||
DL_CONFIG_ENCRY_MODE_SEL : 0;
|
||||
ret |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
@@ -1807,6 +1850,9 @@ void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,
|
||||
int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct mt76_wcid *wcid, int cmd);
|
||||
void mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta);
|
||||
u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band, struct ieee80211_sta *sta);
|
||||
int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
@@ -1851,7 +1897,6 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
|
||||
int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
|
||||
int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
|
||||
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
|
||||
int mt76_connac_mcu_get_nic_capability(struct mt76_phy *phy);
|
||||
|
||||
int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
@@ -1866,9 +1911,17 @@ int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy,
|
||||
int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,
|
||||
struct mt76_vif *vif,
|
||||
struct ieee80211_bss_conf *info);
|
||||
int mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
bool suspend);
|
||||
int mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
bool suspend, struct cfg80211_wowlan *wowlan);
|
||||
int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_gtk_rekey_data *key);
|
||||
int mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable, u8 mdtim,
|
||||
bool wow_suspend);
|
||||
int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
|
||||
void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif);
|
||||
@@ -1879,6 +1932,9 @@ int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
|
||||
int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable);
|
||||
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct mt76_connac_coredump *coredump);
|
||||
s8 mt76_connac_get_ch_power(struct mt76_phy *phy,
|
||||
struct ieee80211_channel *chan,
|
||||
s8 target_power);
|
||||
int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy);
|
||||
int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
@@ -136,7 +136,8 @@ EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer);
|
||||
void
|
||||
mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76x02_dev *dev = (struct mt76x02_dev *)priv;
|
||||
struct beacon_bc_data *data = priv;
|
||||
struct mt76x02_dev *dev = data->dev;
|
||||
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
@@ -147,7 +148,7 @@ mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
mt76x02_mac_set_beacon(dev, skb);
|
||||
__skb_queue_tail(&data->q, skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter);
|
||||
|
||||
@@ -182,9 +183,6 @@ mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev,
|
||||
{
|
||||
int i, nframes;
|
||||
|
||||
data->dev = dev;
|
||||
__skb_queue_head_init(&data->q);
|
||||
|
||||
do {
|
||||
nframes = skb_queue_len(&data->q);
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
|
||||
@@ -16,13 +16,17 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
struct mt76x02_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet);
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_queue *q = dev->mphy.q_tx[MT_TXQ_PSD];
|
||||
struct beacon_bc_data data = {};
|
||||
struct beacon_bc_data data = {
|
||||
.dev = dev,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
int i;
|
||||
|
||||
if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
return;
|
||||
|
||||
__skb_queue_head_init(&data.q);
|
||||
|
||||
mt76x02_resync_beacon_timer(dev);
|
||||
|
||||
/* Prevent corrupt transmissions during update */
|
||||
@@ -31,7 +35,10 @@ static void mt76x02_pre_tbtt_tasklet(struct tasklet_struct *t)
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76x02_update_beacon_iter, dev);
|
||||
mt76x02_update_beacon_iter, &data);
|
||||
|
||||
while ((skb = __skb_dequeue(&data.q)) != NULL)
|
||||
mt76x02_mac_set_beacon(dev, skb);
|
||||
|
||||
mt76_wr(dev, MT_BCN_BYPASS_MASK,
|
||||
0xff00 | ~(0xff00 >> dev->beacon_data_count));
|
||||
|
||||
@@ -182,7 +182,9 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
|
||||
{
|
||||
struct mt76x02_dev *dev =
|
||||
container_of(work, struct mt76x02_dev, pre_tbtt_work);
|
||||
struct beacon_bc_data data = {};
|
||||
struct beacon_bc_data data = {
|
||||
.dev = dev,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
int nbeacons;
|
||||
|
||||
@@ -192,15 +194,20 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
|
||||
if (mt76_hw(dev)->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
return;
|
||||
|
||||
__skb_queue_head_init(&data.q);
|
||||
|
||||
mt76x02_resync_beacon_timer(dev);
|
||||
|
||||
/* Prevent corrupt transmissions during update */
|
||||
mt76_set(dev, MT_BCN_BYPASS_MASK, 0xffff);
|
||||
dev->beacon_data_count = 0;
|
||||
|
||||
ieee80211_iterate_active_interfaces(mt76_hw(dev),
|
||||
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt76x02_update_beacon_iter, dev);
|
||||
mt76x02_update_beacon_iter, &data);
|
||||
|
||||
while ((skb = __skb_dequeue(&data.q)) != NULL)
|
||||
mt76x02_mac_set_beacon(dev, skb);
|
||||
|
||||
mt76_csa_check(&dev->mt76);
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif,
|
||||
mvif->idx = idx;
|
||||
mvif->group_wcid.idx = MT_VIF_WCID(idx);
|
||||
mvif->group_wcid.hw_key_idx = -1;
|
||||
mt76_packet_id_init(&mvif->group_wcid);
|
||||
mt76_wcid_init(&mvif->group_wcid);
|
||||
|
||||
mtxq = (struct mt76_txq *)vif->txq->drv_priv;
|
||||
rcu_assign_pointer(dev->mt76.wcid[MT_VIF_WCID(idx)], &mvif->group_wcid);
|
||||
@@ -346,7 +346,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);
|
||||
rcu_assign_pointer(dev->mt76.wcid[mvif->group_wcid.idx], NULL);
|
||||
mt76_packet_id_flush(&dev->mt76, &mvif->group_wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &mvif->group_wcid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);
|
||||
|
||||
|
||||
@@ -213,10 +213,7 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
|
||||
|
||||
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
|
||||
mt7915_hwmon_groups);
|
||||
if (IS_ERR(hwmon))
|
||||
return PTR_ERR(hwmon);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
static void mt7915_led_set_config(struct led_classdev *led_cdev,
|
||||
@@ -347,6 +344,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
|
||||
if (mtk_wed_device_active(&mdev->mmio.wed))
|
||||
hw->netdev_features |= NETIF_F_HW_TC;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
|
||||
|
||||
@@ -393,8 +393,12 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
phy->mt76->sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
if (is_mt7915(&dev->mt76))
|
||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
else
|
||||
phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_2;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
@@ -404,10 +408,11 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
phy->mt76->sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_4;
|
||||
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
@@ -417,6 +422,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
|
||||
} else {
|
||||
phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_2;
|
||||
|
||||
vht_cap->cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
|
||||
@@ -809,7 +809,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
|
||||
else
|
||||
txp->rept_wds_wcid = cpu_to_le16(0x3ff);
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
tx_info->skb = NULL;
|
||||
|
||||
/* pass partial skb header to fw */
|
||||
tx_info->buf[1].len = MT_CT_PARSE_LEN;
|
||||
|
||||
@@ -253,7 +253,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
|
||||
mvif->sta.wcid.phy_idx = ext_phy;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
mt7915_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -314,7 +314,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
|
||||
list_del_init(&msta->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
|
||||
}
|
||||
|
||||
int mt7915_set_channel(struct mt7915_phy *phy)
|
||||
@@ -483,16 +483,22 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
bool band = phy->mt76->band_idx;
|
||||
u32 rxfilter = phy->rxfilter;
|
||||
|
||||
if (!enabled)
|
||||
phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
|
||||
else
|
||||
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
if (!enabled) {
|
||||
rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
|
||||
dev->monitor_mask &= ~BIT(band);
|
||||
} else {
|
||||
rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
dev->monitor_mask |= BIT(band);
|
||||
}
|
||||
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
|
||||
enabled);
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_MDP_DCR0_RX_HDR_TRANS_EN,
|
||||
!dev->monitor_mask);
|
||||
mt76_testmode_reset(phy->mt76, true);
|
||||
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
|
||||
mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
@@ -527,6 +533,7 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
|
||||
MT_WF_RFCR1_DROP_BA |
|
||||
MT_WF_RFCR1_DROP_CFEND |
|
||||
MT_WF_RFCR1_DROP_CFACK;
|
||||
u32 rxfilter;
|
||||
u32 flags = 0;
|
||||
|
||||
#define MT76_FILTER(_flag, _hw) do { \
|
||||
@@ -561,7 +568,12 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
|
||||
MT_WF_RFCR_DROP_NDPA);
|
||||
|
||||
*total_flags = flags;
|
||||
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
|
||||
rxfilter = phy->rxfilter;
|
||||
if (hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
else
|
||||
rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
|
||||
mt76_wr(dev, MT_WF_RFCR(band), rxfilter);
|
||||
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
|
||||
@@ -646,11 +658,13 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mt7915_update_bss_color(hw, vif, &info->he_bss_color);
|
||||
|
||||
if (changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY))
|
||||
BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7915_mcu_add_beacon(hw, vif, info->enable_beacon, changed);
|
||||
|
||||
if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY))
|
||||
mt7915_mcu_add_inband_discov(dev, vif, changed);
|
||||
|
||||
if (set_bss_info == 0)
|
||||
mt7915_mcu_add_bss_info(phy, vif, false);
|
||||
if (set_sta == 0)
|
||||
@@ -1386,7 +1400,7 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
|
||||
memcpy(data, mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
|
||||
data += sizeof(mt7915_gstrings_stats);
|
||||
page_pool_ethtool_stats_get_strings(data);
|
||||
}
|
||||
@@ -1639,6 +1653,20 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct net_device *netdev, enum tc_setup_type type,
|
||||
void *type_data)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
|
||||
if (!mtk_wed_device_active(wed))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct ieee80211_ops mt7915_ops = {
|
||||
@@ -1693,5 +1721,6 @@ const struct ieee80211_ops mt7915_ops = {
|
||||
.set_radar_background = mt7915_set_radar_background,
|
||||
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
|
||||
.net_fill_forward_path = mt7915_net_fill_forward_path,
|
||||
.net_setup_tc = mt7915_net_setup_tc,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -225,8 +225,10 @@ int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
|
||||
static void
|
||||
mt7915_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->bss_conf.csa_active)
|
||||
ieee80211_csa_finish(vif);
|
||||
if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -326,7 +328,7 @@ mt7915_mcu_rx_log_message(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
static void
|
||||
mt7915_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (!vif->bss_conf.color_change_active)
|
||||
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
ieee80211_color_change_finish(vif);
|
||||
@@ -906,6 +908,8 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
|
||||
muru->ofdma_ul.uo_ra =
|
||||
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
|
||||
muru->ofdma_ul.rx_ctrl_frame_to_mbss =
|
||||
HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1015,13 +1019,13 @@ 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;
|
||||
int sts = hweight16(phy->mt76->chainmask);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_AP)
|
||||
return false;
|
||||
|
||||
if (!bfee && tx_ant < 2)
|
||||
if (!bfee && sts < 2)
|
||||
return false;
|
||||
|
||||
if (sta->deflink.he_cap.has_he) {
|
||||
@@ -1882,10 +1886,9 @@ mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct bss_info_bcn *bcn,
|
||||
u32 changed)
|
||||
int
|
||||
mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
u32 changed)
|
||||
{
|
||||
#define OFFLOAD_TX_MODE_SU BIT(0)
|
||||
#define OFFLOAD_TX_MODE_MU BIT(1)
|
||||
@@ -1895,14 +1898,27 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct mt76_wcid *wcid = &dev->mt76.global_wcid;
|
||||
struct bss_info_bcn *bcn;
|
||||
struct bss_info_inband_discovery *discov;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct tlv *tlv;
|
||||
struct sk_buff *rskb, *skb = NULL;
|
||||
struct tlv *tlv, *sub_tlv;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
u8 *buf, interval;
|
||||
int len;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
return 0;
|
||||
|
||||
rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, NULL,
|
||||
MT7915_MAX_BSS_OFFLOAD_SIZE);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(rskb, BSS_INFO_OFFLOAD, sizeof(*bcn));
|
||||
bcn = (struct bss_info_bcn *)tlv;
|
||||
bcn->enable = true;
|
||||
|
||||
if (changed & BSS_CHANGED_FILS_DISCOVERY &&
|
||||
vif->bss_conf.fils_discovery.max_interval) {
|
||||
interval = vif->bss_conf.fils_discovery.max_interval;
|
||||
@@ -1913,27 +1929,29 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
if (!skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->control.vif = vif;
|
||||
info->band = band;
|
||||
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, ext_phy);
|
||||
|
||||
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
|
||||
len = (len & 0x3) ? ((len | 0x3) + 1) : len;
|
||||
|
||||
if (len > (MT7915_MAX_BSS_OFFLOAD_SIZE - rskb->len)) {
|
||||
if (skb->len > MT7915_MAX_BEACON_SIZE) {
|
||||
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
|
||||
dev_kfree_skb(rskb);
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
|
||||
len, &bcn->sub_ntlv, &bcn->len);
|
||||
discov = (struct bss_info_inband_discovery *)tlv;
|
||||
sub_tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_DISCOV,
|
||||
len, &bcn->sub_ntlv, &bcn->len);
|
||||
discov = (struct bss_info_inband_discovery *)sub_tlv;
|
||||
discov->tx_mode = OFFLOAD_TX_MODE_SU;
|
||||
/* 0: UNSOL PROBE RESP, 1: FILS DISCOV */
|
||||
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
|
||||
@@ -1941,13 +1959,16 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
|
||||
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
|
||||
discov->enable = true;
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*discov);
|
||||
buf = (u8 *)sub_tlv + sizeof(*discov);
|
||||
|
||||
mt7915_mac_write_txwi(&dev->mt76, (__le32 *)buf, skb, wcid, 0, NULL,
|
||||
0, changed);
|
||||
memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
|
||||
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
@@ -1980,11 +2001,14 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb->len > MT7915_MAX_BEACON_SIZE - MT_TXD_SIZE) {
|
||||
if (skb->len > MT7915_MAX_BEACON_SIZE) {
|
||||
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
|
||||
dev_kfree_skb(rskb);
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1997,11 +2021,6 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
|
||||
changed & BSS_CHANGED_FILS_DISCOVERY)
|
||||
mt7915_mcu_beacon_inband_discov(dev, vif, rskb,
|
||||
bcn, changed);
|
||||
|
||||
out:
|
||||
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
|
||||
MCU_EXT_CMD(BSS_INFO_UPDATE), true);
|
||||
@@ -2725,10 +2744,10 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
if (mt76_connac_spe_idx(phy->mt76->antenna_mask))
|
||||
req.tx_path_num = fls(phy->mt76->antenna_mask);
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
|
||||
phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
|
||||
NL80211_IFTYPE_AP))
|
||||
|
||||
@@ -495,10 +495,14 @@ enum {
|
||||
SER_RECOVER
|
||||
};
|
||||
|
||||
#define MT7915_MAX_BEACON_SIZE 512
|
||||
#define MT7915_MAX_INBAND_FRAME_SIZE 256
|
||||
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
|
||||
MT7915_MAX_INBAND_FRAME_SIZE + \
|
||||
#define MT7915_MAX_BEACON_SIZE 1308
|
||||
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_bcn) + \
|
||||
sizeof(struct bss_info_bcn_cntdwn) + \
|
||||
sizeof(struct bss_info_bcn_mbss) + \
|
||||
MT_TXD_SIZE + \
|
||||
sizeof(struct bss_info_bcn_cont))
|
||||
#define MT7915_MAX_BSS_OFFLOAD_SIZE (MT7915_MAX_BEACON_SIZE + \
|
||||
MT7915_BEACON_UPDATE_SIZE)
|
||||
|
||||
#define MT7915_BSS_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
@@ -511,12 +515,6 @@ enum {
|
||||
sizeof(struct bss_info_bmc_rate) +\
|
||||
sizeof(struct bss_info_ext_bss))
|
||||
|
||||
#define MT7915_BEACON_UPDATE_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct bss_info_bcn_cntdwn) + \
|
||||
sizeof(struct bss_info_bcn_mbss) + \
|
||||
sizeof(struct bss_info_bcn_cont) + \
|
||||
sizeof(struct bss_info_inband_discovery))
|
||||
|
||||
static inline s8
|
||||
mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
|
||||
{
|
||||
|
||||
@@ -295,6 +295,8 @@ struct mt7915_dev {
|
||||
bool muru_debug;
|
||||
bool ibf;
|
||||
|
||||
u8 monitor_mask;
|
||||
|
||||
struct dentry *debugfs_dir;
|
||||
struct rchan *relay_fwlog;
|
||||
|
||||
@@ -447,6 +449,8 @@ int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev,
|
||||
bool add);
|
||||
int mt7915_mcu_update_bss_color(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct cfg80211_he_bss_color *he_bss_color);
|
||||
int mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
u32 changed);
|
||||
int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int enable, u32 changed);
|
||||
int mt7915_mcu_add_obss_spr(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
|
||||
@@ -172,6 +172,7 @@ enum offs_rev {
|
||||
|
||||
#define MT_MDP_DCR0 MT_MDP(0x000)
|
||||
#define MT_MDP_DCR0_DAMSDU_EN BIT(15)
|
||||
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
|
||||
|
||||
#define MT_MDP_DCR1 MT_MDP(0x004)
|
||||
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
|
||||
|
||||
@@ -1219,10 +1219,7 @@ static int mt798x_wmac_init(struct mt7915_dev *dev)
|
||||
return PTR_ERR(dev->sku);
|
||||
|
||||
dev->rstc = devm_reset_control_get(pdev, "consys");
|
||||
if (IS_ERR(dev->rstc))
|
||||
return PTR_ERR(dev->rstc);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(dev->rstc);
|
||||
}
|
||||
|
||||
static int mt798x_wmac_probe(struct platform_device *pdev)
|
||||
|
||||
@@ -55,10 +55,56 @@ static int mt7921_thermal_init(struct mt792x_phy *phy)
|
||||
|
||||
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
|
||||
mt7921_hwmon_groups);
|
||||
if (IS_ERR(hwmon))
|
||||
return PTR_ERR(hwmon);
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void
|
||||
mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
|
||||
{
|
||||
#define IS_UNII_INVALID(idx, sfreq, efreq) \
|
||||
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct device_node *np, *band_np;
|
||||
struct ieee80211_channel *ch;
|
||||
int i, cfreq;
|
||||
|
||||
np = mt76_find_power_limits_node(mdev);
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_5GHZ];
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-5g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-4 */
|
||||
if (IS_UNII_INVALID(0, 5850, 5925))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_6GHZ];
|
||||
band_np = np ? of_get_child_by_name(np, "txpower-6g") : NULL;
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
cfreq = ch->center_freq;
|
||||
|
||||
if (np && (!band_np || !mt76_find_channel_node(band_np, ch))) {
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* UNII-5/6/7/8 */
|
||||
if (IS_UNII_INVALID(1, 5925, 6425) ||
|
||||
IS_UNII_INVALID(2, 6425, 6525) ||
|
||||
IS_UNII_INVALID(3, 6525, 6875) ||
|
||||
IS_UNII_INVALID(4, 6875, 7125))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -77,6 +123,8 @@ mt7921_regd_notifier(struct wiphy *wiphy,
|
||||
mt76_connac_mcu_set_channel_domain(hw->priv);
|
||||
mt7921_set_tx_sar_pwr(hw, NULL);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
mt7921_regd_channel_update(wiphy, dev);
|
||||
}
|
||||
|
||||
int mt7921_mac_init(struct mt792x_dev *dev)
|
||||
|
||||
@@ -794,7 +794,7 @@ int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
mt7921_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
|
||||
|
||||
type = mt76_is_sdio(mdev) ? MT7921_SDIO_DATA : 0;
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
mt792x_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
if (mt76_is_usb(mdev))
|
||||
pad += 4;
|
||||
|
||||
@@ -259,25 +259,6 @@ static int mt7921_start(struct ieee80211_hw *hw)
|
||||
return err;
|
||||
}
|
||||
|
||||
void mt7921_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
|
||||
cancel_delayed_work_sync(&phy->mt76->mac_work);
|
||||
|
||||
cancel_delayed_work_sync(&dev->pm.ps_work);
|
||||
cancel_work_sync(&dev->pm.wake_work);
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_stop);
|
||||
|
||||
static int
|
||||
mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -315,7 +296,7 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
mt7921_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -701,6 +682,38 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_phy *phy = mvif->phy;
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
|
||||
if (hweight64(dev->mt76.vif_mask) > 1) {
|
||||
phy->power_type = MT_AP_DEFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (vif->bss_conf.power_type) {
|
||||
case IEEE80211_REG_SP_AP:
|
||||
phy->power_type = MT_AP_SP;
|
||||
break;
|
||||
case IEEE80211_REG_VLP_AP:
|
||||
phy->power_type = MT_AP_VLP;
|
||||
break;
|
||||
case IEEE80211_REG_LPI_AP:
|
||||
phy->power_type = MT_AP_LPI;
|
||||
break;
|
||||
case IEEE80211_REG_UNSET_AP:
|
||||
default:
|
||||
phy->power_type = MT_AP_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mt7921_mcu_set_clc(dev, dev->mt76.alpha2, dev->country_ie_env);
|
||||
}
|
||||
|
||||
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
@@ -736,6 +749,8 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt7921_regd_set_6ghz_power_type(vif);
|
||||
|
||||
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
|
||||
|
||||
return 0;
|
||||
@@ -753,7 +768,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
|
||||
true, mvif->ctx);
|
||||
true, mvif->mt76.ctx);
|
||||
|
||||
ewma_avg_signal_init(&msta->avg_ack_signal);
|
||||
|
||||
@@ -788,7 +803,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
if (!sta->tdls)
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
|
||||
&mvif->sta.wcid, false,
|
||||
mvif->ctx);
|
||||
mvif->mt76.ctx);
|
||||
}
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
@@ -1205,7 +1220,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
|
||||
true, mvif->ctx);
|
||||
true, mvif->mt76.ctx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -1237,7 +1252,7 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
|
||||
mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
|
||||
mvif->ctx);
|
||||
mvif->mt76.ctx);
|
||||
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
@@ -1262,7 +1277,7 @@ static void mt7921_ctx_iter(void *priv, u8 *mac,
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct ieee80211_chanctx_conf *ctx = priv;
|
||||
|
||||
if (ctx != mvif->ctx)
|
||||
if (ctx != mvif->mt76.ctx)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
@@ -1295,7 +1310,7 @@ static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
|
||||
jiffies_to_msecs(HZ);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
|
||||
mt7921_set_roc(mvif->phy, mvif, mvif->mt76.ctx->def.chan, duration,
|
||||
MT7921_ROC_REQ_JOIN);
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
@@ -1312,7 +1327,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
.tx = mt792x_tx,
|
||||
.start = mt7921_start,
|
||||
.stop = mt7921_stop,
|
||||
.stop = mt792x_stop,
|
||||
.add_interface = mt7921_add_interface,
|
||||
.remove_interface = mt792x_remove_interface,
|
||||
.config = mt7921_config,
|
||||
|
||||
@@ -448,6 +448,129 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921_mcu_parse_tx_resource(struct mt76_dev *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_sdio *sdio = &dev->sdio;
|
||||
struct mt7921_tx_resource {
|
||||
__le32 version;
|
||||
__le32 pse_data_quota;
|
||||
__le32 pse_mcu_quota;
|
||||
__le32 ple_data_quota;
|
||||
__le32 ple_mcu_quota;
|
||||
__le16 pse_page_size;
|
||||
__le16 ple_page_size;
|
||||
u8 pp_padding;
|
||||
u8 pad[3];
|
||||
} __packed * tx_res;
|
||||
|
||||
tx_res = (struct mt7921_tx_resource *)skb->data;
|
||||
sdio->sched.pse_data_quota = le32_to_cpu(tx_res->pse_data_quota);
|
||||
sdio->sched.pse_mcu_quota = le32_to_cpu(tx_res->pse_mcu_quota);
|
||||
sdio->sched.ple_data_quota = le32_to_cpu(tx_res->ple_data_quota);
|
||||
sdio->sched.pse_page_size = le16_to_cpu(tx_res->pse_page_size);
|
||||
sdio->sched.deficit = tx_res->pp_padding;
|
||||
}
|
||||
|
||||
static void mt7921_mcu_parse_phy_cap(struct mt76_dev *dev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt7921_phy_cap {
|
||||
u8 ht;
|
||||
u8 vht;
|
||||
u8 _5g;
|
||||
u8 max_bw;
|
||||
u8 nss;
|
||||
u8 dbdc;
|
||||
u8 tx_ldpc;
|
||||
u8 rx_ldpc;
|
||||
u8 tx_stbc;
|
||||
u8 rx_stbc;
|
||||
u8 hw_path;
|
||||
u8 he;
|
||||
} __packed * cap;
|
||||
|
||||
enum {
|
||||
WF0_24G,
|
||||
WF0_5G
|
||||
};
|
||||
|
||||
cap = (struct mt7921_phy_cap *)skb->data;
|
||||
|
||||
dev->phy.antenna_mask = BIT(cap->nss) - 1;
|
||||
dev->phy.chainmask = dev->phy.antenna_mask;
|
||||
dev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
|
||||
dev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
|
||||
}
|
||||
|
||||
static int mt7921_mcu_get_nic_capability(struct mt792x_phy *mphy)
|
||||
{
|
||||
struct mt76_connac_cap_hdr {
|
||||
__le16 n_element;
|
||||
u8 rsv[2];
|
||||
} __packed * hdr;
|
||||
struct sk_buff *skb;
|
||||
struct mt76_phy *phy = mphy->mt76;
|
||||
int ret, i;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(phy->dev, MCU_CE_CMD(GET_NIC_CAPAB),
|
||||
NULL, 0, true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = (struct mt76_connac_cap_hdr *)skb->data;
|
||||
if (skb->len < sizeof(*hdr)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
|
||||
for (i = 0; i < le16_to_cpu(hdr->n_element); i++) {
|
||||
struct tlv_hdr {
|
||||
__le32 type;
|
||||
__le32 len;
|
||||
} __packed * tlv = (struct tlv_hdr *)skb->data;
|
||||
int len;
|
||||
|
||||
if (skb->len < sizeof(*tlv))
|
||||
break;
|
||||
|
||||
skb_pull(skb, sizeof(*tlv));
|
||||
|
||||
len = le32_to_cpu(tlv->len);
|
||||
if (skb->len < len)
|
||||
break;
|
||||
|
||||
switch (le32_to_cpu(tlv->type)) {
|
||||
case MT_NIC_CAP_6G:
|
||||
phy->cap.has_6ghz = skb->data[0];
|
||||
break;
|
||||
case MT_NIC_CAP_MAC_ADDR:
|
||||
memcpy(phy->macaddr, (void *)skb->data, ETH_ALEN);
|
||||
break;
|
||||
case MT_NIC_CAP_PHY:
|
||||
mt7921_mcu_parse_phy_cap(phy->dev, skb);
|
||||
break;
|
||||
case MT_NIC_CAP_TX_RESOURCE:
|
||||
if (mt76_is_sdio(phy->dev))
|
||||
mt7921_mcu_parse_tx_resource(phy->dev,
|
||||
skb);
|
||||
break;
|
||||
case MT_NIC_CAP_CHIP_CAP:
|
||||
memcpy(&mphy->chip_cap, (void *)skb->data, sizeof(u64));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
skb_pull(skb, len);
|
||||
}
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)
|
||||
{
|
||||
struct {
|
||||
@@ -469,7 +592,7 @@ int mt7921_run_firmware(struct mt792x_dev *dev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mt76_connac_mcu_get_nic_capability(&dev->mphy);
|
||||
err = mt7921_mcu_get_nic_capability(&dev->phy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1123,7 +1246,9 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
struct mt7921_clc *clc,
|
||||
u8 idx)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
#define CLC_CAP_EVT_EN BIT(0)
|
||||
#define CLC_CAP_DTS_EN BIT(1)
|
||||
struct sk_buff *skb, *ret_skb = NULL;
|
||||
struct {
|
||||
u8 ver;
|
||||
u8 pad0;
|
||||
@@ -1131,13 +1256,15 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
u8 idx;
|
||||
u8 env;
|
||||
u8 acpi_conf;
|
||||
u8 pad1;
|
||||
u8 cap;
|
||||
u8 alpha2[2];
|
||||
u8 type[2];
|
||||
u8 rsvd[64];
|
||||
u8 env_6g;
|
||||
u8 rsvd[63];
|
||||
} __packed req = {
|
||||
.idx = idx,
|
||||
.env = env_cap,
|
||||
.env_6g = dev->phy.power_type,
|
||||
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
|
||||
};
|
||||
int ret, valid_cnt = 0;
|
||||
@@ -1146,6 +1273,11 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
if (!clc)
|
||||
return 0;
|
||||
|
||||
if (dev->phy.chip_cap & MT792x_CHIP_CAP_CLC_EVT_EN)
|
||||
req.cap |= CLC_CAP_EVT_EN;
|
||||
if (mt76_find_power_limits_node(&dev->mt76))
|
||||
req.cap |= CLC_CAP_DTS_EN;
|
||||
|
||||
pos = clc->data;
|
||||
for (i = 0; i < clc->nr_country; i++) {
|
||||
struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;
|
||||
@@ -1167,10 +1299,21 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
return -ENOMEM;
|
||||
skb_put_data(skb, rule->data, len);
|
||||
|
||||
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_CE_CMD(SET_CLC), false);
|
||||
ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
|
||||
MCU_CE_CMD(SET_CLC),
|
||||
!!(req.cap & CLC_CAP_EVT_EN),
|
||||
&ret_skb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret_skb) {
|
||||
struct mt7921_clc_info_tlv *info;
|
||||
|
||||
info = (struct mt7921_clc_info_tlv *)(ret_skb->data + 4);
|
||||
dev->phy.clc_chan_conf = info->chan_conf;
|
||||
dev_kfree_skb(ret_skb);
|
||||
}
|
||||
|
||||
valid_cnt++;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,4 +99,17 @@ struct mt7921_rftest_evt {
|
||||
__le32 param0;
|
||||
__le32 param1;
|
||||
} __packed;
|
||||
|
||||
struct mt7921_clc_info_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 chan_conf; /* BIT(0) : Enable UNII-4
|
||||
* BIT(1) : Enable UNII-5
|
||||
* BIT(2) : Enable UNII-6
|
||||
* BIT(3) : Enable UNII-7
|
||||
* BIT(4) : Enable UNII-8
|
||||
*/
|
||||
u8 rsv[63];
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
@@ -23,10 +23,8 @@
|
||||
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
|
||||
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
|
||||
|
||||
#define MT7921_SDIO_HDR_TX_BYTES GENMASK(15, 0)
|
||||
#define MT7921_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
|
||||
|
||||
#define MCU_UNI_EVENT_ROC 0x27
|
||||
#define MCU_UNI_EVENT_CLC 0x80
|
||||
|
||||
enum {
|
||||
UNI_ROC_ACQUIRE,
|
||||
@@ -235,20 +233,6 @@ mt7921_l1_rmw(struct mt792x_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 void
|
||||
mt7921_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
|
||||
int type)
|
||||
{
|
||||
u32 hdr, len;
|
||||
|
||||
len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr);
|
||||
hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, len) |
|
||||
FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type);
|
||||
|
||||
put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
|
||||
}
|
||||
|
||||
void mt7921_stop(struct ieee80211_hw *hw);
|
||||
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,
|
||||
|
||||
@@ -17,6 +17,8 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
|
||||
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7922),
|
||||
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ITTIM, 0x7922),
|
||||
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
|
||||
.driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
|
||||
|
||||
@@ -48,7 +48,7 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
|
||||
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
|
||||
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
tx_info->skb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
type = MT7921_SDIO_FWDL;
|
||||
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
mt792x_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
else
|
||||
ep = MT_EP_OUT_AC_BE;
|
||||
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, 0);
|
||||
mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
|
||||
pad = round_up(skb->len, 4) + 4 - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
@@ -135,14 +135,6 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt7921u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
mt7921_stop(hw);
|
||||
}
|
||||
|
||||
static int mt7921u_probe(struct usb_interface *usb_intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@@ -189,7 +181,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
ops->stop = mt7921u_stop;
|
||||
ops->stop = mt792xu_stop;
|
||||
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: ISC
|
||||
config MT7925_COMMON
|
||||
tristate
|
||||
select MT792x_LIB
|
||||
select WANT_DEV_COREDUMP
|
||||
|
||||
config MT7925E
|
||||
tristate "MediaTek MT7925E (PCIe) support"
|
||||
select MT7925_COMMON
|
||||
depends on MAC80211
|
||||
depends on PCI
|
||||
help
|
||||
This adds support for MT7925-based wireless PCIe devices,
|
||||
which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be
|
||||
2x2:2SS 4096-QAM, 160MHz channels.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config MT7925U
|
||||
tristate "MediaTek MT7925U (USB) support"
|
||||
select MT792x_USB
|
||||
select MT7925_COMMON
|
||||
depends on MAC80211
|
||||
depends on USB
|
||||
help
|
||||
This adds support for MT7925-based wireless USB devices,
|
||||
which support operation at 6GHz, 5GHz, and 2.4GHz IEEE 802.11be
|
||||
2x2:2SS 4096-QAM, 160MHz channels.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: ISC
|
||||
|
||||
obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o
|
||||
obj-$(CONFIG_MT7925E) += mt7925e.o
|
||||
obj-$(CONFIG_MT7925U) += mt7925u.o
|
||||
|
||||
mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o
|
||||
mt7925e-y := pci.o pci_mac.o pci_mcu.o
|
||||
mt7925u-y := usb.o
|
||||
@@ -0,0 +1,319 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static int
|
||||
mt7925_reg_set(void *data, u64 val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
u32 regval = val;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, ®val, true);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_reg_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
u32 regval;
|
||||
int ret;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, ®val, false);
|
||||
mt792x_mutex_release(dev);
|
||||
if (!ret)
|
||||
*val = regval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set,
|
||||
"0x%08llx\n");
|
||||
static int
|
||||
mt7925_fw_debug_set(void *data, u64 val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
dev->fw_debug = (u8)val;
|
||||
mt7925_mcu_fw_log_2_host(dev, dev->fw_debug);
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_fw_debug_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
|
||||
*val = dev->fw_debug;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get,
|
||||
mt7925_fw_debug_set, "%lld\n");
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats);
|
||||
|
||||
static void
|
||||
mt7925_seq_puts_array(struct seq_file *file, const char *str,
|
||||
s8 val[][2], int len, u8 band_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
seq_printf(file, "%-22s:", str);
|
||||
for (i = 0; i < len; i++)
|
||||
if (val[i][band_idx] == 127)
|
||||
seq_printf(file, " %6s", "N.A");
|
||||
else
|
||||
seq_printf(file, " %6d", val[i][band_idx]);
|
||||
seq_puts(file, "\n");
|
||||
}
|
||||
|
||||
#define mt7925_print_txpwr_entry(prefix, rate, idx) \
|
||||
({ \
|
||||
mt7925_seq_puts_array(s, #prefix " (tmac)", \
|
||||
txpwr->rate, \
|
||||
ARRAY_SIZE(txpwr->rate), \
|
||||
idx); \
|
||||
})
|
||||
|
||||
static inline void
|
||||
mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx)
|
||||
{
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11",
|
||||
"mcs12", "mcs13", "mcs14", "mcs15");
|
||||
mt7925_print_txpwr_entry(EHT26, eht26, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT52, eht52, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT106, eht106, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT242, eht242, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT484, eht484, band_idx);
|
||||
|
||||
mt7925_print_txpwr_entry(EHT996, eht996, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);
|
||||
mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_txpwr(struct seq_file *s, void *data)
|
||||
{
|
||||
struct mt792x_dev *dev = dev_get_drvdata(s->private);
|
||||
struct mt7925_txpwr *txpwr = NULL;
|
||||
u8 band_idx = dev->mphy.band_idx;
|
||||
int ret = 0;
|
||||
|
||||
txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL);
|
||||
|
||||
if (!txpwr)
|
||||
return -ENOMEM;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_get_txpwr_info(dev, band_idx, txpwr);
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s\n",
|
||||
" ", "1m", "2m", "5m", "11m");
|
||||
mt7925_print_txpwr_entry(CCK, cck, band_idx);
|
||||
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "6m", "9m", "12m", "18m", "24m", "36m",
|
||||
"48m", "54m");
|
||||
mt7925_print_txpwr_entry(OFDM, ofdm, band_idx);
|
||||
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7");
|
||||
mt7925_print_txpwr_entry(HT20, ht20, band_idx);
|
||||
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7", "mcs32");
|
||||
mt7925_print_txpwr_entry(HT40, ht40, band_idx);
|
||||
|
||||
seq_printf(s, "%-22s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
|
||||
" ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
|
||||
"mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
|
||||
mt7925_print_txpwr_entry(VHT20, vht20, band_idx);
|
||||
mt7925_print_txpwr_entry(VHT40, vht40, band_idx);
|
||||
|
||||
mt7925_print_txpwr_entry(VHT80, vht80, band_idx);
|
||||
mt7925_print_txpwr_entry(VHT160, vht160, band_idx);
|
||||
|
||||
mt7925_print_txpwr_entry(HE26, he26, band_idx);
|
||||
mt7925_print_txpwr_entry(HE52, he52, band_idx);
|
||||
mt7925_print_txpwr_entry(HE106, he106, band_idx);
|
||||
mt7925_print_txpwr_entry(HE242, he242, band_idx);
|
||||
mt7925_print_txpwr_entry(HE484, he484, band_idx);
|
||||
|
||||
mt7925_print_txpwr_entry(HE996, he996, band_idx);
|
||||
mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);
|
||||
|
||||
mt7925_eht_txpwr(s, txpwr, band_idx);
|
||||
|
||||
out:
|
||||
devm_kfree(dev->mt76.dev, txpwr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_pm_set(void *data, u64 val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
if (mt76_is_usb(&dev->mt76))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (val == pm->enable_user)
|
||||
goto out;
|
||||
|
||||
if (!pm->enable_user) {
|
||||
pm->stats.last_wake_event = jiffies;
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
}
|
||||
/* make sure the chip is awake here and ps_work is scheduled
|
||||
* just at end of the this routine.
|
||||
*/
|
||||
pm->enable = false;
|
||||
mt76_connac_pm_wake(&dev->mphy, pm);
|
||||
|
||||
pm->enable_user = val;
|
||||
mt7925_set_runtime_pm(dev);
|
||||
mt76_connac_power_save_sched(&dev->mphy, pm);
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_pm_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
|
||||
*val = dev->pm.enable_user;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, "%lld\n");
|
||||
|
||||
static int
|
||||
mt7925_deep_sleep_set(void *data, u64 val)
|
||||
{
|
||||
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;
|
||||
|
||||
if (mt76_is_usb(&dev->mt76))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
if (pm->ds_enable_user == enable)
|
||||
goto out;
|
||||
|
||||
pm->ds_enable_user = enable;
|
||||
pm->ds_enable = enable && !monitor;
|
||||
mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
|
||||
out:
|
||||
mt792x_mutex_release(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_deep_sleep_get(void *data, u64 *val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
|
||||
*val = dev->pm.ds_enable_user;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get,
|
||||
mt7925_deep_sleep_set, "%lld\n");
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,
|
||||
mt792x_pm_idle_timeout_set, "%lld\n");
|
||||
|
||||
static int mt7925_chip_reset(void *data, u64 val)
|
||||
{
|
||||
struct mt792x_dev *dev = data;
|
||||
int ret = 0;
|
||||
|
||||
switch (val) {
|
||||
case 1:
|
||||
/* Reset wifisys directly. */
|
||||
mt792x_reset(&dev->mt76);
|
||||
break;
|
||||
default:
|
||||
/* Collect the core dump before reset wifisys. */
|
||||
mt792x_mutex_acquire(dev);
|
||||
ret = mt7925_mcu_chip_config(dev, "assert");
|
||||
mt792x_mutex_release(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n");
|
||||
|
||||
int mt7925_init_debugfs(struct mt792x_dev *dev)
|
||||
{
|
||||
struct dentry *dir;
|
||||
|
||||
dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
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,
|
||||
mt792x_queues_acq);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
|
||||
mt7925_txpwr);
|
||||
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,
|
||||
mt792x_pm_stats);
|
||||
debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "mt7925.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static void
|
||||
mt7925_regd_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *req)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
|
||||
/* allow world regdom at the first boot only */
|
||||
if (!memcmp(req->alpha2, "00", 2) &&
|
||||
mdev->alpha2[0] && mdev->alpha2[1])
|
||||
return;
|
||||
|
||||
/* do not need to update the same country twice */
|
||||
if (!memcmp(req->alpha2, mdev->alpha2, 2) &&
|
||||
dev->country_ie_env == req->country_ie_env)
|
||||
return;
|
||||
|
||||
memcpy(mdev->alpha2, req->alpha2, 2);
|
||||
mdev->region = req->dfs_region;
|
||||
dev->country_ie_env = req->country_ie_env;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt7925_mcu_set_clc(dev, req->alpha2, req->country_ie_env);
|
||||
mt7925_mcu_set_channel_domain(hw->priv);
|
||||
mt7925_set_tx_sar_pwr(hw, NULL);
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
|
||||
u16 rate = mt76_rates[i].hw_value;
|
||||
u16 idx = MT792x_BASIC_RATES_TBL + i;
|
||||
|
||||
rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
|
||||
FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
|
||||
mt7925_mac_set_fixed_rate_table(dev, idx, rate);
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_mac_init(struct mt792x_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
|
||||
/* enable hardware de-agg */
|
||||
mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
|
||||
|
||||
for (i = 0; i < MT792x_WTBL_SIZE; i++)
|
||||
mt7925_mac_wtbl_update(dev, i,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
for (i = 0; i < 2; i++)
|
||||
mt792x_mac_init_band(dev, i);
|
||||
|
||||
mt7925_mac_init_basic_rates(dev);
|
||||
|
||||
memzero_explicit(&dev->mt76.alpha2, sizeof(dev->mt76.alpha2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mac_init);
|
||||
|
||||
static int __mt7925_init_hardware(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt792x_mcu_init(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mt76_eeprom_override(&dev->mphy);
|
||||
|
||||
ret = mt7925_mcu_set_eeprom(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7925_mac_init(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7925_init_hardware(struct mt792x_dev *dev)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
|
||||
for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) {
|
||||
ret = __mt7925_init_hardware(dev);
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
mt792x_init_reset(dev);
|
||||
}
|
||||
|
||||
if (i == MT792x_MCU_INIT_RETRY_COUNT) {
|
||||
dev_err(dev->mt76.dev, "hardware init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7925_init_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
|
||||
init_work);
|
||||
int ret;
|
||||
|
||||
ret = mt7925_init_hardware(dev);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7925_set_stream_he_eht_caps(&dev->phy);
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "register device failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mt7925_init_debugfs(dev);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "register debugfs failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* we support chip reset now */
|
||||
dev->hw_init_done = true;
|
||||
|
||||
mt7925_mcu_set_deep_sleep(dev, dev->pm.ds_enable);
|
||||
}
|
||||
|
||||
int mt7925_register_device(struct mt792x_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
int ret;
|
||||
|
||||
dev->phy.dev = dev;
|
||||
dev->phy.mt76 = &dev->mt76.phy;
|
||||
dev->mt76.phy.priv = &dev->phy;
|
||||
dev->mt76.tx_worker.fn = mt792x_tx_worker;
|
||||
|
||||
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);
|
||||
spin_lock_init(&dev->pm.txq_lock);
|
||||
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work);
|
||||
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7925_scan_work);
|
||||
INIT_DELAYED_WORK(&dev->coredump.work, mt7925_coredump_work);
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
INIT_WORK(&dev->ipv6_ns_work, mt7925_set_ipv6_ns_work);
|
||||
skb_queue_head_init(&dev->ipv6_ns_list);
|
||||
#endif
|
||||
skb_queue_head_init(&dev->phy.scan_event_list);
|
||||
skb_queue_head_init(&dev->coredump.msg_list);
|
||||
|
||||
INIT_WORK(&dev->reset_work, mt7925_mac_reset_work);
|
||||
INIT_WORK(&dev->init_work, mt7925_init_work);
|
||||
|
||||
INIT_WORK(&dev->phy.roc_work, mt7925_roc_work);
|
||||
timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0);
|
||||
init_waitqueue_head(&dev->phy.roc_wait);
|
||||
|
||||
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)) {
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
dev->pm.ds_enable = true;
|
||||
}
|
||||
|
||||
if (!mt76_is_mmio(&dev->mt76))
|
||||
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
|
||||
mt792x_init_acpi_sar(dev);
|
||||
|
||||
ret = mt792x_init_wcid(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt792x_init_wiphy(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hw->wiphy->reg_notifier = mt7925_regd_notifier;
|
||||
dev->mphy.sband_2g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
dev->mphy.sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_2;
|
||||
dev->mphy.sband_5g.sband.ht_cap.cap |=
|
||||
IEEE80211_HT_CAP_LDPC_CODING |
|
||||
IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
dev->mphy.sband_2g.sband.ht_cap.ampdu_density =
|
||||
IEEE80211_HT_MPDU_DENSITY_1;
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
|
||||
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
||||
(3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
|
||||
dev->mphy.sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160;
|
||||
|
||||
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
|
||||
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
|
||||
|
||||
queue_work(system_wq, &dev->init_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_register_device);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7925_MAC_H
|
||||
#define __MT7925_MAC_H
|
||||
|
||||
#include "../mt76_connac3_mac.h"
|
||||
|
||||
#define MT_WTBL_TXRX_CAP_RATE_OFFSET 7
|
||||
#define MT_WTBL_TXRX_RATE_G2_HE 24
|
||||
#define MT_WTBL_TXRX_RATE_G2 12
|
||||
|
||||
#define MT_WTBL_AC0_CTT_OFFSET 20
|
||||
|
||||
static inline u32 mt7925_mac_wtbl_lmac_addr(struct mt792x_dev *dev, u16 wcid, u8 dw)
|
||||
{
|
||||
mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
|
||||
FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
|
||||
|
||||
return MT_WTBL_LMAC_OFFS(wcid, dw);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,537 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7925_MCU_H
|
||||
#define __MT7925_MCU_H
|
||||
|
||||
#include "../mt76_connac_mcu.h"
|
||||
|
||||
/* ext event table */
|
||||
enum {
|
||||
MCU_EXT_EVENT_RATE_REPORT = 0x87,
|
||||
};
|
||||
|
||||
struct mt7925_mcu_eeprom_info {
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
u8 data[MT7925_EEPROM_BLOCK_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define MT_RA_RATE_NSS GENMASK(8, 6)
|
||||
#define MT_RA_RATE_MCS GENMASK(3, 0)
|
||||
#define MT_RA_RATE_TX_MODE GENMASK(12, 9)
|
||||
#define MT_RA_RATE_DCM_EN BIT(4)
|
||||
#define MT_RA_RATE_BW GENMASK(14, 13)
|
||||
|
||||
struct mt7925_mcu_rxd {
|
||||
__le32 rxd[8];
|
||||
|
||||
__le16 len;
|
||||
__le16 pkt_type_id;
|
||||
|
||||
u8 eid;
|
||||
u8 seq;
|
||||
u8 option;
|
||||
u8 __rsv;
|
||||
|
||||
u8 ext_eid;
|
||||
u8 __rsv1[2];
|
||||
u8 s2d_index;
|
||||
|
||||
u8 tlv[];
|
||||
};
|
||||
|
||||
struct mt7925_mcu_uni_event {
|
||||
u8 cid;
|
||||
u8 pad[3];
|
||||
__le32 status; /* 0: success, others: fail */
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
MT_EBF = BIT(0), /* explicit beamforming */
|
||||
MT_IBF = BIT(1) /* implicit beamforming */
|
||||
};
|
||||
|
||||
struct mt7925_mcu_reg_event {
|
||||
__le32 reg;
|
||||
__le32 val;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_mcu_ant_id_config {
|
||||
u8 ant_id[4];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_txpwr_req {
|
||||
u8 _rsv[4];
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 format_id;
|
||||
u8 catg;
|
||||
u8 band_idx;
|
||||
u8 _rsv1;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_txpwr_event {
|
||||
u8 rsv[4];
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 catg;
|
||||
u8 band_idx;
|
||||
u8 ch_band;
|
||||
u8 format; /* 0:Legacy, 1:HE */
|
||||
|
||||
/* Rate power info */
|
||||
struct mt7925_txpwr txpwr;
|
||||
|
||||
s8 pwr_max;
|
||||
s8 pwr_min;
|
||||
u8 rsv1;
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
TM_SWITCH_MODE,
|
||||
TM_SET_AT_CMD,
|
||||
TM_QUERY_AT_CMD,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT7925_TM_NORMAL,
|
||||
MT7925_TM_TESTMODE,
|
||||
MT7925_TM_ICAP,
|
||||
MT7925_TM_ICAP_OVERLAP,
|
||||
MT7925_TM_WIFISPECTRUM,
|
||||
};
|
||||
|
||||
struct mt7925_rftest_cmd {
|
||||
u8 action;
|
||||
u8 rsv[3];
|
||||
__le32 param0;
|
||||
__le32 param1;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_rftest_evt {
|
||||
__le32 param0;
|
||||
__le32 param1;
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
UNI_CHANNEL_SWITCH,
|
||||
UNI_CHANNEL_RX_PATH,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_CHIP_CONFIG_CHIP_CFG = 0x2,
|
||||
UNI_CHIP_CONFIG_NIC_CAPA = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_BAND_CONFIG_RADIO_ENABLE,
|
||||
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
|
||||
UNI_BAND_CONFIG_SET_MAC80211_RX_FILTER = 0x0C,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_WSYS_CONFIG_FW_LOG_CTRL,
|
||||
UNI_WSYS_CONFIG_FW_DBG_CTRL,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_EFUSE_ACCESS = 1,
|
||||
UNI_EFUSE_BUFFER_MODE,
|
||||
UNI_EFUSE_FREE_BLOCK,
|
||||
UNI_EFUSE_BUFFER_RD,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_CMD_ACCESS_REG_BASIC = 0x0,
|
||||
UNI_CMD_ACCESS_RF_REG_BASIC,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_MBMC_SETTING,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_EVENT_SCAN_DONE_BASIC = 0,
|
||||
UNI_EVENT_SCAN_DONE_CHNLINFO = 2,
|
||||
UNI_EVENT_SCAN_DONE_NLO = 3,
|
||||
};
|
||||
|
||||
struct mt7925_mcu_scan_chinfo_event {
|
||||
u8 nr_chan;
|
||||
u8 alpha2[3];
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
UNI_SCAN_REQ = 1,
|
||||
UNI_SCAN_CANCEL = 2,
|
||||
UNI_SCAN_SCHED_REQ = 3,
|
||||
UNI_SCAN_SCHED_ENABLE = 4,
|
||||
UNI_SCAN_SSID = 10,
|
||||
UNI_SCAN_BSSID,
|
||||
UNI_SCAN_CHANNEL,
|
||||
UNI_SCAN_IE,
|
||||
UNI_SCAN_MISC,
|
||||
UNI_SCAN_SSID_MATCH_SETS,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_SNIFFER_ENABLE,
|
||||
UNI_SNIFFER_CONFIG,
|
||||
};
|
||||
|
||||
struct scan_hdr_tlv {
|
||||
/* fixed field */
|
||||
u8 seq_num;
|
||||
u8 bss_idx;
|
||||
u8 pad[2];
|
||||
/* tlv */
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct scan_req_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 scan_type; /* 0: PASSIVE SCAN
|
||||
* 1: ACTIVE SCAN
|
||||
*/
|
||||
u8 probe_req_num; /* Number of probe request for each SSID */
|
||||
u8 scan_func; /* BIT(0) Enable random MAC scan
|
||||
* BIT(1) Disable DBDC scan type 1~3.
|
||||
* BIT(2) Use DBDC scan type 3 (dedicated one RF to scan).
|
||||
*/
|
||||
u8 src_mask;
|
||||
__le16 channel_min_dwell_time;
|
||||
__le16 channel_dwell_time; /* channel Dwell interval */
|
||||
__le16 timeout_value;
|
||||
__le16 probe_delay_time;
|
||||
u8 func_mask_ext;
|
||||
};
|
||||
|
||||
struct scan_ssid_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 ssid_type; /* BIT(0) wildcard SSID
|
||||
* BIT(1) P2P wildcard SSID
|
||||
* BIT(2) specified SSID + wildcard SSID
|
||||
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
|
||||
*/
|
||||
u8 ssids_num;
|
||||
u8 pad[2];
|
||||
struct mt76_connac_mcu_scan_ssid ssids[4];
|
||||
};
|
||||
|
||||
struct scan_bssid_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 match_ch;
|
||||
u8 match_ssid_ind;
|
||||
u8 rcpi;
|
||||
u8 pad[3];
|
||||
};
|
||||
|
||||
struct scan_chan_info_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 channel_type; /* 0: Full channels
|
||||
* 1: Only 2.4GHz channels
|
||||
* 2: Only 5GHz channels
|
||||
* 3: P2P social channel only (channel #1, #6 and #11)
|
||||
* 4: Specified channels
|
||||
* Others: Reserved
|
||||
*/
|
||||
u8 channels_num; /* valid when channel_type is 4 */
|
||||
u8 pad[2];
|
||||
struct mt76_connac_mcu_scan_channel channels[64];
|
||||
};
|
||||
|
||||
struct scan_ie_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
__le16 ies_len;
|
||||
u8 band;
|
||||
u8 pad;
|
||||
u8 ies[MT76_CONNAC_SCAN_IE_LEN];
|
||||
};
|
||||
|
||||
struct scan_misc_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 random_mac[ETH_ALEN];
|
||||
u8 rsv[2];
|
||||
};
|
||||
|
||||
struct scan_sched_req {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 version;
|
||||
u8 stop_on_match;
|
||||
u8 intervals_num;
|
||||
u8 scan_func;
|
||||
__le16 intervals[MT76_CONNAC_MAX_NUM_SCHED_SCAN_INTERVAL];
|
||||
};
|
||||
|
||||
struct scan_sched_ssid_match_sets {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 match_num;
|
||||
u8 rsv[3];
|
||||
|
||||
struct mt76_connac_mcu_scan_match match[MT76_CONNAC_MAX_SCAN_MATCH];
|
||||
};
|
||||
|
||||
struct scan_sched_enable {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 active;
|
||||
u8 rsv[3];
|
||||
};
|
||||
|
||||
struct mbmc_set_req {
|
||||
u8 pad[4];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct mbmc_conf_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 mbmc_en;
|
||||
u8 band;
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
struct edca {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 queue;
|
||||
u8 set;
|
||||
u8 cw_min;
|
||||
u8 cw_max;
|
||||
__le16 txop;
|
||||
u8 aifs;
|
||||
u8 __rsv;
|
||||
};
|
||||
|
||||
struct bss_req_hdr {
|
||||
u8 bss_idx;
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct bss_rate_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 __rsv1[4];
|
||||
__le16 bc_trans;
|
||||
__le16 mc_trans;
|
||||
u8 short_preamble;
|
||||
u8 bc_fixed_rate;
|
||||
u8 mc_fixed_rate;
|
||||
u8 __rsv2;
|
||||
} __packed;
|
||||
|
||||
struct bss_mld_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 group_mld_id;
|
||||
u8 own_mld_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 remap_idx;
|
||||
u8 link_id;
|
||||
u8 __rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_ba_uni {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 tid;
|
||||
u8 ba_type;
|
||||
u8 amsdu;
|
||||
u8 ba_en;
|
||||
__le16 ssn;
|
||||
__le16 winsize;
|
||||
u8 ba_rdd_rro;
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_eht {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 tid_bitmap;
|
||||
u8 _rsv;
|
||||
__le16 mac_cap;
|
||||
__le64 phy_cap;
|
||||
__le64 phy_cap_ext;
|
||||
u8 mcs_map_bw20[4];
|
||||
u8 mcs_map_bw80[3];
|
||||
u8 mcs_map_bw160[3];
|
||||
u8 mcs_map_bw320[3];
|
||||
u8 _rsv2[3];
|
||||
} __packed;
|
||||
|
||||
struct sec_key_uni {
|
||||
__le16 wlan_idx;
|
||||
u8 mgmt_prot;
|
||||
u8 cipher_id;
|
||||
u8 cipher_len;
|
||||
u8 key_id;
|
||||
u8 key_len;
|
||||
u8 need_resp;
|
||||
u8 key[32];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_sec_uni {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 add;
|
||||
u8 n_cipher;
|
||||
u8 rsv[2];
|
||||
|
||||
struct sec_key_uni key[2];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_hdr_trans {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 from_ds;
|
||||
u8 to_ds;
|
||||
u8 dis_rx_hdr_tran;
|
||||
u8 rsv;
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_mld {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
__le16 primary_id;
|
||||
__le16 secondary_id;
|
||||
__le16 wlan_id;
|
||||
u8 link_num;
|
||||
u8 rsv[3];
|
||||
struct {
|
||||
__le16 wlan_id;
|
||||
u8 bss_idx;
|
||||
u8 rsv;
|
||||
} __packed link[2];
|
||||
} __packed;
|
||||
|
||||
#define MT7925_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
|
||||
sizeof(struct sta_rec_basic) + \
|
||||
sizeof(struct sta_rec_bf) + \
|
||||
sizeof(struct sta_rec_ht) + \
|
||||
sizeof(struct sta_rec_he_v2) + \
|
||||
sizeof(struct sta_rec_ba_uni) + \
|
||||
sizeof(struct sta_rec_vht) + \
|
||||
sizeof(struct sta_rec_uapsd) + \
|
||||
sizeof(struct sta_rec_amsdu) + \
|
||||
sizeof(struct sta_rec_bfee) + \
|
||||
sizeof(struct sta_rec_phy) + \
|
||||
sizeof(struct sta_rec_ra) + \
|
||||
sizeof(struct sta_rec_sec) + \
|
||||
sizeof(struct sta_rec_ra_fixed) + \
|
||||
sizeof(struct sta_rec_he_6g_capa) + \
|
||||
sizeof(struct sta_rec_eht) + \
|
||||
sizeof(struct sta_rec_hdr_trans) + \
|
||||
sizeof(struct sta_rec_mld) + \
|
||||
sizeof(struct tlv))
|
||||
|
||||
#define MT7925_BSS_UPDATE_MAX_SIZE (sizeof(struct bss_req_hdr) + \
|
||||
sizeof(struct mt76_connac_bss_basic_tlv) + \
|
||||
sizeof(struct mt76_connac_bss_qos_tlv) + \
|
||||
sizeof(struct bss_rate_tlv) + \
|
||||
sizeof(struct bss_mld_tlv) + \
|
||||
sizeof(struct bss_info_uni_he) + \
|
||||
sizeof(struct bss_info_uni_bss_color) + \
|
||||
sizeof(struct tlv))
|
||||
|
||||
#define MT_CONNAC3_SKU_POWER_LIMIT 449
|
||||
struct mt7925_sku_tlv {
|
||||
u8 channel;
|
||||
s8 pwr_limit[MT_CONNAC3_SKU_POWER_LIMIT];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_tx_power_limit_tlv {
|
||||
u8 rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
/* DW0 - common info*/
|
||||
u8 ver;
|
||||
u8 pad0;
|
||||
__le16 rsv1;
|
||||
/* DW1 - cmd hint */
|
||||
u8 n_chan; /* # channel */
|
||||
u8 band; /* 2.4GHz - 5GHz - 6GHz */
|
||||
u8 last_msg;
|
||||
u8 limit_type;
|
||||
/* DW3 */
|
||||
u8 alpha2[4]; /* regulatory_request.alpha2 */
|
||||
u8 pad2[32];
|
||||
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_arpns_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 enable;
|
||||
u8 ips_num;
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_wow_pattern_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 bss_idx;
|
||||
u8 index; /* pattern index */
|
||||
u8 enable; /* 0: disable
|
||||
* 1: enable
|
||||
*/
|
||||
u8 data_len; /* pattern length */
|
||||
u8 offset;
|
||||
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
|
||||
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
|
||||
u8 rsv[4];
|
||||
} __packed;
|
||||
|
||||
int mt7925_mcu_set_dbdc(struct mt76_phy *phy);
|
||||
int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_sched_scan_request *sreq);
|
||||
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
int enable);
|
||||
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
|
||||
int mt7925_mcu_set_channel_domain(struct mt76_phy *phy);
|
||||
int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable);
|
||||
int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy);
|
||||
int mt7925_mcu_update_arp_filter(struct mt76_dev *dev,
|
||||
struct mt76_vif *vif,
|
||||
struct ieee80211_bss_conf *info);
|
||||
#endif
|
||||
@@ -0,0 +1,309 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7925_H
|
||||
#define __MT7925_H
|
||||
|
||||
#include "../mt792x.h"
|
||||
#include "regs.h"
|
||||
|
||||
#define MT7925_BEACON_RATES_TBL 25
|
||||
|
||||
#define MT7925_TX_RING_SIZE 2048
|
||||
#define MT7925_TX_MCU_RING_SIZE 256
|
||||
#define MT7925_TX_FWDL_RING_SIZE 128
|
||||
|
||||
#define MT7925_RX_RING_SIZE 1536
|
||||
#define MT7925_RX_MCU_RING_SIZE 512
|
||||
|
||||
#define MT7925_EEPROM_SIZE 3584
|
||||
#define MT7925_TOKEN_SIZE 8192
|
||||
|
||||
#define MT7925_EEPROM_BLOCK_SIZE 16
|
||||
|
||||
#define MT7925_SKU_RATE_NUM 161
|
||||
#define MT7925_SKU_MAX_DELTA_IDX MT7925_SKU_RATE_NUM
|
||||
#define MT7925_SKU_TABLE_SIZE (MT7925_SKU_RATE_NUM + 1)
|
||||
|
||||
#define MCU_UNI_EVENT_ROC 0x27
|
||||
|
||||
enum {
|
||||
UNI_ROC_ACQUIRE,
|
||||
UNI_ROC_ABORT,
|
||||
UNI_ROC_NUM
|
||||
};
|
||||
|
||||
enum mt7925_roc_req {
|
||||
MT7925_ROC_REQ_JOIN,
|
||||
MT7925_ROC_REQ_ROC,
|
||||
MT7925_ROC_REQ_NUM
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_EVENT_ROC_GRANT = 0,
|
||||
UNI_EVENT_ROC_TAG_NUM
|
||||
};
|
||||
|
||||
struct mt7925_roc_grant_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 bss_idx;
|
||||
u8 tokenid;
|
||||
u8 status;
|
||||
u8 primarychannel;
|
||||
u8 rfsco;
|
||||
u8 rfband;
|
||||
u8 channelwidth;
|
||||
u8 centerfreqseg1;
|
||||
u8 centerfreqseg2;
|
||||
u8 reqtype;
|
||||
u8 dbdcband;
|
||||
u8 rsv[1];
|
||||
__le32 max_interval;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_beacon_loss_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 reason;
|
||||
u8 nr_btolink;
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_uni_beacon_loss_event {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct mt7925_beacon_loss_tlv beacon_loss;
|
||||
} __packed;
|
||||
|
||||
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
|
||||
#define to_rcpi(rssi) (2 * (rssi) + 220)
|
||||
|
||||
enum mt7925_txq_id {
|
||||
MT7925_TXQ_BAND0,
|
||||
MT7925_TXQ_BAND1,
|
||||
MT7925_TXQ_MCU_WM = 15,
|
||||
MT7925_TXQ_FWDL,
|
||||
};
|
||||
|
||||
enum mt7925_rxq_id {
|
||||
MT7925_RXQ_BAND0 = 2,
|
||||
MT7925_RXQ_BAND1,
|
||||
MT7925_RXQ_MCU_WM = 0,
|
||||
MT7925_RXQ_MCU_WM2, /* for tx done */
|
||||
};
|
||||
|
||||
enum {
|
||||
MODE_OPEN = 0,
|
||||
MODE_SHARED = 1,
|
||||
MODE_WPA = 3,
|
||||
MODE_WPA_PSK = 4,
|
||||
MODE_WPA_NONE = 5,
|
||||
MODE_WPA2 = 6,
|
||||
MODE_WPA2_PSK = 7,
|
||||
MODE_WPA3_SAE = 11,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT7925_CLC_POWER,
|
||||
MT7925_CLC_CHAN,
|
||||
MT7925_CLC_MAX_NUM,
|
||||
};
|
||||
|
||||
struct mt7925_clc_rule {
|
||||
u8 alpha2[2];
|
||||
u8 type[2];
|
||||
u8 seg_idx;
|
||||
u8 rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc_segment {
|
||||
u8 idx;
|
||||
u8 rsv1[3];
|
||||
u32 offset;
|
||||
u32 len;
|
||||
u8 rsv2[4];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc {
|
||||
__le32 len;
|
||||
u8 idx;
|
||||
u8 ver;
|
||||
u8 nr_country;
|
||||
u8 type;
|
||||
u8 nr_seg;
|
||||
u8 rsv[7];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
enum mt7925_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
__MT_EE_MAX = 0x9ff
|
||||
};
|
||||
|
||||
enum {
|
||||
TXPWR_USER,
|
||||
TXPWR_EEPROM,
|
||||
TXPWR_MAC,
|
||||
TXPWR_MAX_NUM,
|
||||
};
|
||||
|
||||
struct mt7925_txpwr {
|
||||
s8 cck[4][2];
|
||||
s8 ofdm[8][2];
|
||||
s8 ht20[8][2];
|
||||
s8 ht40[9][2];
|
||||
s8 vht20[12][2];
|
||||
s8 vht40[12][2];
|
||||
s8 vht80[12][2];
|
||||
s8 vht160[12][2];
|
||||
s8 he26[12][2];
|
||||
s8 he52[12][2];
|
||||
s8 he106[12][2];
|
||||
s8 he242[12][2];
|
||||
s8 he484[12][2];
|
||||
s8 he996[12][2];
|
||||
s8 he996x2[12][2];
|
||||
s8 eht26[16][2];
|
||||
s8 eht52[16][2];
|
||||
s8 eht106[16][2];
|
||||
s8 eht242[16][2];
|
||||
s8 eht484[16][2];
|
||||
s8 eht996[16][2];
|
||||
s8 eht996x2[16][2];
|
||||
s8 eht996x4[16][2];
|
||||
s8 eht26_52[16][2];
|
||||
s8 eht26_106[16][2];
|
||||
s8 eht484_242[16][2];
|
||||
s8 eht996_484[16][2];
|
||||
s8 eht996_484_242[16][2];
|
||||
s8 eht996x2_484[16][2];
|
||||
s8 eht996x3[16][2];
|
||||
s8 eht996x3_484[16][2];
|
||||
};
|
||||
|
||||
extern const struct ieee80211_ops mt7925_ops;
|
||||
|
||||
int __mt7925_start(struct mt792x_phy *phy);
|
||||
int mt7925_register_device(struct mt792x_dev *dev);
|
||||
void mt7925_unregister_device(struct mt792x_dev *dev);
|
||||
int mt7925_run_firmware(struct mt792x_dev *dev);
|
||||
int mt7925_mcu_set_bss_pm(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_sta_update(struct mt792x_dev *dev, struct ieee80211_sta *sta,
|
||||
struct ieee80211_vif *vif, bool enable,
|
||||
enum mt76_sta_info_state state);
|
||||
int mt7925_mcu_set_chan_info(struct mt792x_phy *phy, u16 tag);
|
||||
int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif);
|
||||
int mt7925_mcu_set_eeprom(struct mt792x_dev *dev);
|
||||
int mt7925_mcu_get_rx_rate(struct mt792x_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct rate_info *rate);
|
||||
int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl);
|
||||
void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb);
|
||||
int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd);
|
||||
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map);
|
||||
|
||||
int mt7925_mac_init(struct mt792x_dev *dev);
|
||||
int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
bool mt7925_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
|
||||
void mt7925_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7925_mac_reset_work(struct work_struct *work);
|
||||
int mt7925e_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 mt7925_tx_token_put(struct mt792x_dev *dev);
|
||||
bool mt7925_rx_check(struct mt76_dev *mdev, void *data, int len);
|
||||
void mt7925_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
void mt7925_stats_work(struct work_struct *work);
|
||||
void mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy);
|
||||
int mt7925_init_debugfs(struct mt792x_dev *dev);
|
||||
|
||||
int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
void mt7925_scan_work(struct work_struct *work);
|
||||
void mt7925_roc_work(struct work_struct *work);
|
||||
int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev, struct ieee80211_vif *vif);
|
||||
void mt7925_coredump_work(struct work_struct *work);
|
||||
int mt7925_get_txpwr_info(struct mt792x_dev *dev, u8 band_idx,
|
||||
struct mt7925_txpwr *txpwr);
|
||||
void mt7925_mac_set_fixed_rate_table(struct mt792x_dev *dev,
|
||||
u8 tbl_idx, u16 rate_idx);
|
||||
void mt7925_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
void mt7925_txwi_free(struct mt792x_dev *dev, struct mt76_txwi_cache *t,
|
||||
struct ieee80211_sta *sta, bool clear_status,
|
||||
struct list_head *free_list);
|
||||
int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
struct sk_buff *skb, int seq);
|
||||
|
||||
int mt7925e_mac_reset(struct mt792x_dev *dev);
|
||||
int mt7925e_mcu_init(struct mt792x_dev *dev);
|
||||
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
|
||||
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
|
||||
void mt7925_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif);
|
||||
void mt7925_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||
struct ieee80211_vif *vif);
|
||||
void mt7925_set_ipv6_ns_work(struct work_struct *work);
|
||||
|
||||
int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_config_sniffer(struct mt792x_vif *vif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
|
||||
int mt7925_usb_sdio_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 mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e);
|
||||
bool mt7925_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
|
||||
int mt7925_mcu_uni_add_beacon_offload(struct mt792x_dev *dev,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_set_tx_sar_pwr(struct ieee80211_hw *hw,
|
||||
const struct cfg80211_sar_specs *sar);
|
||||
|
||||
int mt7925_mcu_regval(struct mt792x_dev *dev, u32 regidx, u32 *val, bool set);
|
||||
int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
enum environment_cap env_cap);
|
||||
int mt7925_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
|
||||
struct ieee80211_channel *chan, int duration,
|
||||
enum mt7925_roc_req type, u8 token_id);
|
||||
int mt7925_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
|
||||
u8 token_id);
|
||||
int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *wait_seq);
|
||||
int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt76_connac_sta_key_conf *sta_key_conf,
|
||||
struct ieee80211_key_conf *key, int mcu_cmd,
|
||||
struct mt76_wcid *wcid, enum set_key_cmd cmd);
|
||||
int mt7925_mcu_set_rts_thresh(struct mt792x_phy *phy, u32 val);
|
||||
int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,586 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "../dma.h"
|
||||
|
||||
static const struct pci_device_id mt7925_pci_device_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7925),
|
||||
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0717),
|
||||
.driver_data = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
static bool mt7925_disable_aspm;
|
||||
module_param_named(disable_aspm, mt7925_disable_aspm, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_aspm, "disable PCI ASPM support");
|
||||
|
||||
static int mt7925e_init_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
return mt792x_wpdma_reset(dev, true);
|
||||
}
|
||||
|
||||
static void mt7925e_unregister_device(struct mt792x_dev *dev)
|
||||
{
|
||||
int i;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
napi_disable(&dev->mt76.napi[i]);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
|
||||
mt7925_tx_token_put(dev);
|
||||
__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 void mt7925_reg_remap_restore(struct mt792x_dev *dev)
|
||||
{
|
||||
/* remap to ori status */
|
||||
if (unlikely(dev->backup_l1)) {
|
||||
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->backup_l1);
|
||||
dev->backup_l1 = 0;
|
||||
}
|
||||
|
||||
if (dev->backup_l2) {
|
||||
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->backup_l2);
|
||||
dev->backup_l2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 mt7925_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);
|
||||
|
||||
dev->backup_l1 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
|
||||
MT_HIF_REMAP_L1_MASK,
|
||||
FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
|
||||
|
||||
/* use read to push write */
|
||||
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L1 + offset;
|
||||
}
|
||||
|
||||
static u32 mt7925_reg_map_l2(struct mt792x_dev *dev, u32 addr)
|
||||
{
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, MT_HIF_REMAP_BASE_L2);
|
||||
|
||||
dev->backup_l2 = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
|
||||
MT_HIF_REMAP_L1_MASK,
|
||||
FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
|
||||
|
||||
dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, addr);
|
||||
/* use read to push write */
|
||||
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L1;
|
||||
}
|
||||
|
||||
static u32 __mt7925_reg_addr(struct mt792x_dev *dev, u32 addr)
|
||||
{
|
||||
static const struct mt76_connac_reg_map fixed_map[] = {
|
||||
{ 0x830c0000, 0x000000, 0x0001000 }, /* WF_MCU_BUS_CR_REMAP */
|
||||
{ 0x54000000, 0x002000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA0 */
|
||||
{ 0x55000000, 0x003000, 0x0001000 }, /* WFDMA PCIE0 MCU DMA1 */
|
||||
{ 0x56000000, 0x004000, 0x0001000 }, /* WFDMA reserved */
|
||||
{ 0x57000000, 0x005000, 0x0001000 }, /* WFDMA MCU wrap CR */
|
||||
{ 0x58000000, 0x006000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
|
||||
{ 0x59000000, 0x007000, 0x0001000 }, /* WFDMA PCIE1 MCU DMA1 */
|
||||
{ 0x820c0000, 0x008000, 0x0004000 }, /* WF_UMAC_TOP (PLE) */
|
||||
{ 0x820c8000, 0x00c000, 0x0002000 }, /* WF_UMAC_TOP (PSE) */
|
||||
{ 0x820cc000, 0x00e000, 0x0002000 }, /* WF_UMAC_TOP (PP) */
|
||||
{ 0x74030000, 0x010000, 0x0001000 }, /* PCIe MAC */
|
||||
{ 0x820e0000, 0x020000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_CFG) */
|
||||
{ 0x820e1000, 0x020400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_TRB) */
|
||||
{ 0x820e2000, 0x020800, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_AGG) */
|
||||
{ 0x820e3000, 0x020c00, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_ARB) */
|
||||
{ 0x820e4000, 0x021000, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_TMAC) */
|
||||
{ 0x820e5000, 0x021400, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_RMAC) */
|
||||
{ 0x820ce000, 0x021c00, 0x0000200 }, /* WF_LMAC_TOP (WF_SEC) */
|
||||
{ 0x820e7000, 0x021e00, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
|
||||
{ 0x820cf000, 0x022000, 0x0001000 }, /* WF_LMAC_TOP (WF_PF) */
|
||||
{ 0x820e9000, 0x023400, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
|
||||
{ 0x820ea000, 0x024000, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_ETBF) */
|
||||
{ 0x820eb000, 0x024200, 0x0000400 }, /* WF_LMAC_TOP BN0 (WF_LPON) */
|
||||
{ 0x820ec000, 0x024600, 0x0000200 }, /* WF_LMAC_TOP BN0 (WF_INT) */
|
||||
{ 0x820ed000, 0x024800, 0x0000800 }, /* WF_LMAC_TOP BN0 (WF_MIB) */
|
||||
{ 0x820ca000, 0x026000, 0x0002000 }, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
|
||||
{ 0x820d0000, 0x030000, 0x0010000 }, /* WF_LMAC_TOP (WF_WTBLON) */
|
||||
{ 0x40000000, 0x070000, 0x0010000 }, /* WF_UMAC_SYSRAM */
|
||||
{ 0x00400000, 0x080000, 0x0010000 }, /* WF_MCU_SYSRAM */
|
||||
{ 0x00410000, 0x090000, 0x0010000 }, /* WF_MCU_SYSRAM (configure register) */
|
||||
{ 0x820f0000, 0x0a0000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_CFG) */
|
||||
{ 0x820f1000, 0x0a0600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_TRB) */
|
||||
{ 0x820f2000, 0x0a0800, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_AGG) */
|
||||
{ 0x820f3000, 0x0a0c00, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_ARB) */
|
||||
{ 0x820f4000, 0x0a1000, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_TMAC) */
|
||||
{ 0x820f5000, 0x0a1400, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_RMAC) */
|
||||
{ 0x820f7000, 0x0a1e00, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_DMA) */
|
||||
{ 0x820f9000, 0x0a3400, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
|
||||
{ 0x820fa000, 0x0a4000, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_ETBF) */
|
||||
{ 0x820fb000, 0x0a4200, 0x0000400 }, /* WF_LMAC_TOP BN1 (WF_LPON) */
|
||||
{ 0x820fc000, 0x0a4600, 0x0000200 }, /* WF_LMAC_TOP BN1 (WF_INT) */
|
||||
{ 0x820fd000, 0x0a4800, 0x0000800 }, /* WF_LMAC_TOP BN1 (WF_MIB) */
|
||||
{ 0x820c4000, 0x0a8000, 0x0004000 }, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
|
||||
{ 0x820b0000, 0x0ae000, 0x0001000 }, /* [APB2] WFSYS_ON */
|
||||
{ 0x80020000, 0x0b0000, 0x0010000 }, /* WF_TOP_MISC_OFF */
|
||||
{ 0x81020000, 0x0c0000, 0x0010000 }, /* WF_TOP_MISC_ON */
|
||||
{ 0x7c020000, 0x0d0000, 0x0010000 }, /* CONN_INFRA, wfdma */
|
||||
{ 0x7c060000, 0x0e0000, 0x0010000 }, /* CONN_INFRA, conn_host_csr_top */
|
||||
{ 0x7c000000, 0x0f0000, 0x0010000 }, /* CONN_INFRA */
|
||||
{ 0x70020000, 0x1f0000, 0x0010000 }, /* Reserved for CBTOP, can't switch */
|
||||
{ 0x7c500000, 0x060000, 0x2000000 }, /* remap */
|
||||
{ 0x0, 0x0, 0x0 } /* End */
|
||||
};
|
||||
int i;
|
||||
|
||||
if (addr < 0x200000)
|
||||
return addr;
|
||||
|
||||
mt7925_reg_remap_restore(dev);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
|
||||
u32 ofs;
|
||||
|
||||
if (addr < fixed_map[i].phys)
|
||||
continue;
|
||||
|
||||
ofs = addr - fixed_map[i].phys;
|
||||
if (ofs > fixed_map[i].size)
|
||||
continue;
|
||||
|
||||
return fixed_map[i].maps + ofs;
|
||||
}
|
||||
|
||||
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
|
||||
(addr >= 0x70000000 && addr < 0x78000000) ||
|
||||
(addr >= 0x7c000000 && addr < 0x7c400000))
|
||||
return mt7925_reg_map_l1(dev, addr);
|
||||
|
||||
return mt7925_reg_map_l2(dev, addr);
|
||||
}
|
||||
|
||||
static u32 mt7925_rr(struct mt76_dev *mdev, u32 offset)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
u32 addr = __mt7925_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rr(mdev, addr);
|
||||
}
|
||||
|
||||
static void mt7925_wr(struct mt76_dev *mdev, u32 offset, u32 val)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
u32 addr = __mt7925_reg_addr(dev, offset);
|
||||
|
||||
dev->bus_ops->wr(mdev, addr, val);
|
||||
}
|
||||
|
||||
static u32 mt7925_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
u32 addr = __mt7925_reg_addr(dev, offset);
|
||||
|
||||
return dev->bus_ops->rmw(mdev, addr, mask, val);
|
||||
}
|
||||
|
||||
static int mt7925_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, MT7925_TXQ_BAND0,
|
||||
MT7925_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, MT7925_TXQ_MCU_WM,
|
||||
MT7925_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* firmware download */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7925_TXQ_FWDL,
|
||||
MT7925_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx event */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
|
||||
MT7925_RXQ_MCU_WM, MT7925_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE, MT_RX_EVENT_RING_BASE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* rx data */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
|
||||
MT7925_RXQ_BAND0, MT7925_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 mt7925_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_hw_txp),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
|
||||
MT_DRV_AMSDU_OFFLOAD,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.token_size = MT7925_TOKEN_SIZE,
|
||||
.tx_prepare_skb = mt7925e_tx_prepare_skb,
|
||||
.tx_complete_skb = mt76_connac_tx_complete_skb,
|
||||
.rx_check = mt7925_rx_check,
|
||||
.rx_skb = mt7925_queue_rx_skb,
|
||||
.rx_poll_complete = mt792x_rx_poll_complete,
|
||||
.sta_add = mt7925_mac_sta_add,
|
||||
.sta_assoc = mt7925_mac_sta_assoc,
|
||||
.sta_remove = mt7925_mac_sta_remove,
|
||||
.update_survey = mt792x_update_channel,
|
||||
};
|
||||
static const struct mt792x_hif_ops mt7925_pcie_ops = {
|
||||
.init_reset = mt7925e_init_reset,
|
||||
.reset = mt7925e_mac_reset,
|
||||
.mcu_init = mt7925e_mcu_init,
|
||||
.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 = HOST_RX_DONE_INT_ENA2,
|
||||
.wm_complete_mask = HOST_RX_DONE_INT_ENA0,
|
||||
},
|
||||
};
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt76_bus_ops *bus_ops;
|
||||
struct mt792x_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
u8 features;
|
||||
int ret;
|
||||
u16 cmd;
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
|
||||
if (!(cmd & PCI_COMMAND_MEMORY)) {
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
pci_write_config_word(pdev, PCI_COMMAND, cmd);
|
||||
}
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto err_free_pci_vec;
|
||||
|
||||
if (mt7925_disable_aspm)
|
||||
mt76_pci_disable_aspm(pdev);
|
||||
|
||||
ops = mt792x_get_mac80211_ops(&pdev->dev, &mt7925_ops,
|
||||
(void *)id->driver_data, &features);
|
||||
if (!ops) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pci_vec;
|
||||
}
|
||||
|
||||
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pci_vec;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, mdev);
|
||||
|
||||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &mt7925_pcie_ops;
|
||||
dev->irq_map = &irq_map;
|
||||
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
|
||||
tasklet_init(&mdev->irq_tasklet, mt792x_irq_tasklet, (unsigned long)dev);
|
||||
|
||||
dev->phy.dev = dev;
|
||||
dev->phy.mt76 = &dev->mt76.phy;
|
||||
dev->mt76.phy.priv = &dev->phy;
|
||||
dev->bus_ops = dev->mt76.bus;
|
||||
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
|
||||
GFP_KERNEL);
|
||||
if (!bus_ops) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
bus_ops->rr = mt7925_rr;
|
||||
bus_ops->wr = mt7925_wr;
|
||||
bus_ops->rmw = mt7925_rmw;
|
||||
dev->mt76.bus = bus_ops;
|
||||
|
||||
ret = __mt792x_mcu_fw_pmctrl(dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
ret = __mt792xe_mcu_drv_pmctrl(dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
|
||||
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
ret = mt792x_wfsys_reset(dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
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, mt792x_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
ret = mt7925_dma_init(dev);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
ret = mt7925_register_device(dev);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
devm_free_irq(&pdev->dev, pdev->irq, dev);
|
||||
err_free_dev:
|
||||
mt76_free_device(&dev->mt76);
|
||||
err_free_pci_vec:
|
||||
pci_free_irq_vectors(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7925_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
|
||||
mt7925e_unregister_device(dev);
|
||||
devm_free_irq(&pdev->dev, pdev->irq, dev);
|
||||
mt76_free_device(&dev->mt76);
|
||||
pci_free_irq_vectors(pdev);
|
||||
}
|
||||
|
||||
static int mt7925_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int i, err;
|
||||
|
||||
pm->suspended = true;
|
||||
flush_work(&dev->reset_work);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
|
||||
err = mt792x_mcu_drv_pmctrl(dev);
|
||||
if (err < 0)
|
||||
goto restore_suspend;
|
||||
|
||||
/* always enable deep sleep during suspend to reduce
|
||||
* power consumption
|
||||
*/
|
||||
mt7925_mcu_set_deep_sleep(dev, true);
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
|
||||
if (err)
|
||||
goto restore_suspend;
|
||||
|
||||
napi_disable(&mdev->tx_napi);
|
||||
mt76_worker_disable(&mdev->tx_worker);
|
||||
|
||||
mt76_for_each_q_rx(mdev, i) {
|
||||
napi_disable(&mdev->napi[i]);
|
||||
}
|
||||
|
||||
/* wait until dma is idle */
|
||||
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
|
||||
|
||||
/* put dma disabled */
|
||||
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
/* disable interrupt */
|
||||
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_DIS,
|
||||
dev->irq_map->tx.all_complete_mask |
|
||||
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
|
||||
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
|
||||
|
||||
synchronize_irq(pdev->irq);
|
||||
tasklet_kill(&mdev->irq_tasklet);
|
||||
|
||||
err = mt792x_mcu_fw_pmctrl(dev);
|
||||
if (err)
|
||||
goto restore_napi;
|
||||
|
||||
return 0;
|
||||
|
||||
restore_napi:
|
||||
mt76_for_each_q_rx(mdev, i) {
|
||||
napi_enable(&mdev->napi[i]);
|
||||
}
|
||||
napi_enable(&mdev->tx_napi);
|
||||
|
||||
if (!pm->ds_enable)
|
||||
mt7925_mcu_set_deep_sleep(dev, false);
|
||||
|
||||
mt76_connac_mcu_set_hif_suspend(mdev, false);
|
||||
|
||||
restore_suspend:
|
||||
pm->suspended = false;
|
||||
|
||||
if (err < 0)
|
||||
mt792x_reset(&dev->mt76);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7925_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct mt76_dev *mdev = pci_get_drvdata(pdev);
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int i, err;
|
||||
|
||||
err = mt792x_mcu_drv_pmctrl(dev);
|
||||
if (err < 0)
|
||||
goto failed;
|
||||
|
||||
mt792x_wpdma_reinit_cond(dev);
|
||||
|
||||
/* enable interrupt */
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
mt76_connac_irq_enable(&dev->mt76,
|
||||
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 */
|
||||
mt76_set(dev, MT_WFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
mt76_worker_enable(&mdev->tx_worker);
|
||||
|
||||
local_bh_disable();
|
||||
mt76_for_each_q_rx(mdev, i) {
|
||||
napi_enable(&mdev->napi[i]);
|
||||
napi_schedule(&mdev->napi[i]);
|
||||
}
|
||||
napi_enable(&mdev->tx_napi);
|
||||
napi_schedule(&mdev->tx_napi);
|
||||
local_bh_enable();
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
|
||||
|
||||
/* restore previous ds setting */
|
||||
if (!pm->ds_enable)
|
||||
mt7925_mcu_set_deep_sleep(dev, false);
|
||||
|
||||
failed:
|
||||
pm->suspended = false;
|
||||
|
||||
if (err < 0)
|
||||
mt792x_reset(&dev->mt76);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt7925_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
mt7925_pci_remove(pdev);
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(mt7925_pm_ops, mt7925_pci_suspend, mt7925_pci_resume);
|
||||
|
||||
static struct pci_driver mt7925_pci_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mt7925_pci_device_table,
|
||||
.probe = mt7925_pci_probe,
|
||||
.remove = mt7925_pci_remove,
|
||||
.shutdown = mt7925_pci_shutdown,
|
||||
.driver.pm = pm_sleep_ptr(&mt7925_pm_ops),
|
||||
};
|
||||
|
||||
module_pci_driver(mt7925_pci_driver);
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table);
|
||||
MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7925_ROM_PATCH);
|
||||
MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>");
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
@@ -0,0 +1,148 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
int mt7925e_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)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct mt76_connac_hw_txp *txp;
|
||||
struct mt76_txwi_cache *t;
|
||||
int id, pid;
|
||||
u8 *txwi = (u8 *)txwi_ptr;
|
||||
|
||||
if (unlikely(tx_info->skb->len <= ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
|
||||
t->skb = tx_info->skb;
|
||||
|
||||
id = mt76_token_consume(mdev, &t);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
if (sta) {
|
||||
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;
|
||||
msta->last_txs = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
mt7925_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
|
||||
txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE);
|
||||
memset(txp, 0, sizeof(struct mt76_connac_hw_txp));
|
||||
mt76_connac_write_hw_txp(mdev, tx_info, txp, id);
|
||||
|
||||
tx_info->skb = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7925_tx_token_put(struct mt792x_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) {
|
||||
mt7925_txwi_free(dev, txwi, NULL, false, NULL);
|
||||
dev->mt76.token_count--;
|
||||
}
|
||||
spin_unlock_bh(&dev->mt76.token_lock);
|
||||
idr_destroy(&dev->mt76.token);
|
||||
}
|
||||
|
||||
int mt7925e_mac_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
const struct mt792x_irq_map *irq_map = dev->irq_map;
|
||||
int i, err;
|
||||
|
||||
mt792xe_mcu_drv_pmctrl(dev);
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
if (irq_map->rx.data_complete_mask)
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]);
|
||||
if (irq_map->rx.wm_complete_mask)
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU]);
|
||||
if (irq_map->rx.wm2_complete_mask)
|
||||
napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]);
|
||||
if (irq_map->tx.all_complete_mask)
|
||||
napi_disable(&dev->mt76.tx_napi);
|
||||
|
||||
mt7925_tx_token_put(dev);
|
||||
idr_init(&dev->mt76.token);
|
||||
|
||||
mt792x_wpdma_reset(dev, true);
|
||||
|
||||
local_bh_disable();
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
napi_enable(&dev->mt76.napi[i]);
|
||||
napi_schedule(&dev->mt76.napi[i]);
|
||||
}
|
||||
napi_enable(&dev->mt76.tx_napi);
|
||||
napi_schedule(&dev->mt76.tx_napi);
|
||||
local_bh_enable();
|
||||
|
||||
dev->fw_assert = false;
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_wr(dev, dev->irq_map->host_irq_enable,
|
||||
dev->irq_map->tx.all_complete_mask |
|
||||
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
|
||||
|
||||
err = mt792xe_mcu_fw_pmctrl(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = __mt792xe_mcu_drv_pmctrl(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7925_run_firmware(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7925_mcu_set_eeprom(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7925_mac_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = __mt7925_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "mcu.h"
|
||||
|
||||
static int
|
||||
mt7925_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
enum mt76_mcuq_id txq = MT_MCUQ_WM;
|
||||
int ret;
|
||||
|
||||
ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
if (cmd == MCU_CMD(FW_SCATTER))
|
||||
txq = MT_MCUQ_FWDL;
|
||||
|
||||
return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0);
|
||||
}
|
||||
|
||||
int mt7925e_mcu_init(struct mt792x_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7925_mcu_ops = {
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7925_mcu_send_message,
|
||||
.mcu_parse_response = mt7925_mcu_parse_response,
|
||||
};
|
||||
int err;
|
||||
|
||||
dev->mt76.mcu_ops = &mt7925_mcu_ops;
|
||||
|
||||
err = mt792xe_mcu_fw_pmctrl(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = __mt792xe_mcu_drv_pmctrl(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_rmw_field(dev, MT_PCIE_MAC_PM, MT_PCIE_MAC_PM_L0S_DIS, 1);
|
||||
|
||||
err = mt7925_run_firmware(dev);
|
||||
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#ifndef __MT7925_REGS_H
|
||||
#define __MT7925_REGS_H
|
||||
|
||||
#include "../mt792x_regs.h"
|
||||
|
||||
#define MT_MDP_BASE 0x820cc800
|
||||
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
|
||||
|
||||
#define MT_MDP_DCR0 MT_MDP(0x000)
|
||||
#define MT_MDP_DCR0_DAMSDU_EN BIT(15)
|
||||
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
|
||||
|
||||
#define MT_MDP_DCR1 MT_MDP(0x004)
|
||||
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
|
||||
|
||||
#define MT_MDP_BNRCFR0(_band) MT_MDP(0x090 + ((_band) << 8))
|
||||
#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4)
|
||||
#define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6)
|
||||
#define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8)
|
||||
|
||||
#define MT_MDP_BNRCFR1(_band) MT_MDP(0x094 + ((_band) << 8))
|
||||
#define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22)
|
||||
#define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27)
|
||||
#define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29)
|
||||
#define MT_MDP_TO_HIF 0
|
||||
#define MT_MDP_TO_WM 1
|
||||
|
||||
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x228)
|
||||
#define MT_WFDMA0_HOST_INT_DIS MT_WFDMA0(0x22c)
|
||||
#define HOST_RX_DONE_INT_ENA4 BIT(12)
|
||||
#define HOST_RX_DONE_INT_ENA5 BIT(13)
|
||||
#define HOST_RX_DONE_INT_ENA6 BIT(14)
|
||||
#define HOST_RX_DONE_INT_ENA7 BIT(15)
|
||||
#define HOST_RX_DONE_INT_ENA8 BIT(16)
|
||||
#define HOST_RX_DONE_INT_ENA9 BIT(17)
|
||||
#define HOST_RX_DONE_INT_ENA10 BIT(18)
|
||||
#define HOST_RX_DONE_INT_ENA11 BIT(19)
|
||||
#define HOST_TX_DONE_INT_ENA15 BIT(25)
|
||||
#define HOST_TX_DONE_INT_ENA16 BIT(26)
|
||||
#define HOST_TX_DONE_INT_ENA17 BIT(27)
|
||||
|
||||
/* WFDMA interrupt */
|
||||
#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
|
||||
#define MT_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0
|
||||
#define MT_INT_RX_DONE_WM2 HOST_RX_DONE_INT_ENA1
|
||||
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_DATA | \
|
||||
MT_INT_RX_DONE_WM | \
|
||||
MT_INT_RX_DONE_WM2)
|
||||
|
||||
#define MT_INT_TX_DONE_MCU_WM (HOST_TX_DONE_INT_ENA15 | \
|
||||
HOST_TX_DONE_INT_ENA17)
|
||||
|
||||
#define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16
|
||||
#define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0
|
||||
|
||||
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \
|
||||
MT_INT_TX_DONE_FWDL)
|
||||
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \
|
||||
MT_INT_TX_DONE_BAND0 | \
|
||||
GENMASK(18, 4))
|
||||
|
||||
#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x500)
|
||||
|
||||
#define MT_INFRA_CFG_BASE 0xd1000
|
||||
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
|
||||
|
||||
#define MT_HIF_REMAP_L1 0x155024
|
||||
#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_BASE_L1 0x130000
|
||||
|
||||
#define MT_HIF_REMAP_L2 0x0120
|
||||
#if IS_ENABLED(CONFIG_MT76_DEV)
|
||||
#define MT_HIF_REMAP_BASE_L2 (0x7c500000 - (0x7c000000 - 0x18000000))
|
||||
#else
|
||||
#define MT_HIF_REMAP_BASE_L2 0x18500000
|
||||
#endif
|
||||
|
||||
#define MT_WFSYS_SW_RST_B 0x7c000140
|
||||
|
||||
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
|
||||
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
|
||||
|
||||
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380)
|
||||
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
|
||||
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,332 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2023 MediaTek Inc. */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static const struct usb_device_id mt7925u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7925, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7925_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int
|
||||
mt7925u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
u32 pad, ep;
|
||||
int ret;
|
||||
|
||||
ret = mt7925_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdev->mcu.timeout = 3 * HZ;
|
||||
|
||||
if (cmd != MCU_CMD(FW_SCATTER))
|
||||
ep = MT_EP_OUT_INBAND_CMD;
|
||||
else
|
||||
ep = MT_EP_OUT_AC_BE;
|
||||
|
||||
mt792x_skb_add_usb_sdio_hdr(dev, skb, 0);
|
||||
pad = round_up(skb->len, 4) + 4 - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
|
||||
1000, ep);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7925u_mcu_init(struct mt792x_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mcu_ops = {
|
||||
.headroom = MT_SDIO_HDR_SIZE +
|
||||
sizeof(struct mt76_connac2_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7925u_mcu_send_message,
|
||||
.mcu_parse_response = mt7925_mcu_parse_response,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mcu_ops;
|
||||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
ret = mt7925_run_firmware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7925u_mac_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
mt792xu_wfsys_reset(dev);
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
err = mt76u_resume_rx(&dev->mt76);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt792xu_mcu_power_on(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt792xu_dma_init(dev, false);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7925_run_firmware(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7925_mcu_set_eeprom(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7925_mac_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = __mt7925_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7925u_probe(struct usb_interface *usb_intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.txwi_size = MT_SDIO_TXD_SIZE,
|
||||
.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ |
|
||||
MT_DRV_AMSDU_OFFLOAD,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.tx_prepare_skb = mt7925_usb_sdio_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7925_usb_sdio_tx_complete_skb,
|
||||
.tx_status_data = mt7925_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7925_queue_rx_skb,
|
||||
.rx_check = mt7925_rx_check,
|
||||
.sta_add = mt7925_mac_sta_add,
|
||||
.sta_assoc = mt7925_mac_sta_assoc,
|
||||
.sta_remove = mt7925_mac_sta_remove,
|
||||
.update_survey = mt792x_update_channel,
|
||||
};
|
||||
static const struct mt792x_hif_ops hif_ops = {
|
||||
.mcu_init = mt7925u_mcu_init,
|
||||
.init_reset = mt792xu_init_reset,
|
||||
.reset = mt7925u_mac_reset,
|
||||
};
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt792xu_rr,
|
||||
.wr = mt792xu_wr,
|
||||
.rmw = mt792xu_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt792xu_copy,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(usb_intf);
|
||||
struct ieee80211_ops *ops;
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt792x_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
u8 features;
|
||||
int ret;
|
||||
|
||||
ops = mt792x_get_mac80211_ops(&usb_intf->dev, &mt7925_ops,
|
||||
(void *)id->driver_info, &features);
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
ops->stop = mt792xu_stop;
|
||||
|
||||
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
dev->fw_features = features;
|
||||
dev->hif_ops = &hif_ops;
|
||||
|
||||
udev = usb_get_dev(udev);
|
||||
usb_reset_device(udev);
|
||||
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
||||
ret = __mt76u_init(mdev, usb_intf, &bus_ops);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
if (mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY)) {
|
||||
ret = mt792xu_wfsys_reset(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = mt792xu_mcu_power_on(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt76u_alloc_mcu_queue(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt76u_alloc_queues(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = mt792xu_dma_init(dev, false);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
hw = mt76_hw(dev);
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
hw->max_tx_fragments = mdev->usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
|
||||
|
||||
ret = mt7925_register_device(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mt7925u_suspend(struct usb_interface *intf, pm_message_t state)
|
||||
{
|
||||
struct mt792x_dev *dev = usb_get_intfdata(intf);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int err;
|
||||
|
||||
pm->suspended = true;
|
||||
flush_work(&dev->reset_work);
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
|
||||
if (err)
|
||||
goto failed;
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
pm->suspended = false;
|
||||
|
||||
if (err < 0)
|
||||
mt792x_reset(&dev->mt76);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7925u_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct mt792x_dev *dev = usb_get_intfdata(intf);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
bool reinit = true;
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
u32 val = mt76_rr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT);
|
||||
|
||||
if (!(val & MT_WF_SW_SER_TRIGGER_SUSPEND)) {
|
||||
reinit = false;
|
||||
break;
|
||||
}
|
||||
if (val & MT_WF_SW_SER_DONE_SUSPEND) {
|
||||
mt76_wr(dev, MT_WF_SW_DEF_CR_USB_MCU_EVENT, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
if (reinit || mt792x_dma_need_reinit(dev)) {
|
||||
err = mt792xu_dma_init(dev, true);
|
||||
if (err)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
err = mt76u_resume_rx(&dev->mt76);
|
||||
if (err < 0)
|
||||
goto failed;
|
||||
|
||||
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
|
||||
failed:
|
||||
pm->suspended = false;
|
||||
|
||||
if (err < 0)
|
||||
mt792x_reset(&dev->mt76);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt7925u_device_table);
|
||||
MODULE_FIRMWARE(MT7925_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7925_ROM_PATCH);
|
||||
|
||||
static struct usb_driver mt7925u_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mt7925u_device_table,
|
||||
.probe = mt7925u_probe,
|
||||
.disconnect = mt792xu_disconnect,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mt7925u_suspend,
|
||||
.resume = mt7925u_resume,
|
||||
.reset_resume = mt7925u_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
.soft_unbind = 1,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
module_usb_driver(mt7925u_driver);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
@@ -25,6 +25,8 @@
|
||||
#define MT792x_FW_TAG_FEATURE 4
|
||||
#define MT792x_FW_CAP_CNM BIT(7)
|
||||
|
||||
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
|
||||
|
||||
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
|
||||
#define MT792x_BASIC_RATES_TBL 11
|
||||
|
||||
@@ -36,9 +38,14 @@
|
||||
|
||||
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
|
||||
#define MT7922_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7922_1.bin"
|
||||
#define MT7925_FIRMWARE_WM "mediatek/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin"
|
||||
|
||||
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
|
||||
#define MT7922_ROM_PATCH "mediatek/WIFI_MT7922_patch_mcu_1_1_hdr.bin"
|
||||
#define MT7925_ROM_PATCH "mediatek/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin"
|
||||
|
||||
#define MT792x_SDIO_HDR_TX_BYTES GENMASK(15, 0)
|
||||
#define MT792x_SDIO_HDR_PKT_TYPE GENMASK(17, 16)
|
||||
|
||||
struct mt792x_vif;
|
||||
struct mt792x_sta;
|
||||
@@ -61,6 +68,14 @@ enum {
|
||||
MT792x_CLC_MAX_NUM,
|
||||
};
|
||||
|
||||
enum mt792x_reg_power_type {
|
||||
MT_AP_UNSET = 0,
|
||||
MT_AP_DEFAULT,
|
||||
MT_AP_LPI,
|
||||
MT_AP_SP,
|
||||
MT_AP_VLP,
|
||||
};
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
|
||||
struct mt792x_sta {
|
||||
@@ -91,7 +106,6 @@ struct mt792x_vif {
|
||||
struct ewma_rssi rssi;
|
||||
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
struct ieee80211_chanctx_conf *ctx;
|
||||
};
|
||||
|
||||
struct mt792x_phy {
|
||||
@@ -113,6 +127,8 @@ struct mt792x_phy {
|
||||
struct mt76_mib_stats mib;
|
||||
|
||||
u8 sta_work_count;
|
||||
u8 clc_chan_conf;
|
||||
enum mt792x_reg_power_type power_type;
|
||||
|
||||
struct sk_buff_head scan_event_list;
|
||||
struct delayed_work scan_work;
|
||||
@@ -120,6 +136,7 @@ struct mt792x_phy {
|
||||
void *acpisar;
|
||||
#endif
|
||||
void *clc[MT792x_CLC_MAX_NUM];
|
||||
u64 chip_cap;
|
||||
|
||||
struct work_struct roc_work;
|
||||
struct timer_list roc_timer;
|
||||
@@ -229,6 +246,7 @@ static inline bool mt792x_dma_need_reinit(struct mt792x_dev *dev)
|
||||
#define mt792x_mutex_release(dev) \
|
||||
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
|
||||
|
||||
void mt792x_stop(struct ieee80211_hw *hw);
|
||||
void mt792x_pm_wake_work(struct work_struct *work);
|
||||
void mt792x_pm_power_save_work(struct work_struct *work);
|
||||
void mt792x_reset(struct mt76_dev *mdev);
|
||||
@@ -308,6 +326,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7922:
|
||||
return MT7922_FIRMWARE_WM;
|
||||
case 0x7925:
|
||||
return MT7925_FIRMWARE_WM;
|
||||
default:
|
||||
return MT7921_FIRMWARE_WM;
|
||||
}
|
||||
@@ -318,6 +338,8 @@ static inline char *mt792x_patch_name(struct mt792x_dev *dev)
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7922:
|
||||
return MT7922_ROM_PATCH;
|
||||
case 0x7925:
|
||||
return MT7925_ROM_PATCH;
|
||||
default:
|
||||
return MT7921_ROM_PATCH;
|
||||
}
|
||||
@@ -337,6 +359,20 @@ void mt792xu_wr(struct mt76_dev *dev, u32 addr, u32 val);
|
||||
u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
|
||||
void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len);
|
||||
void mt792xu_disconnect(struct usb_interface *usb_intf);
|
||||
void mt792xu_stop(struct ieee80211_hw *hw);
|
||||
|
||||
static inline void
|
||||
mt792x_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
|
||||
int type)
|
||||
{
|
||||
u32 hdr, len;
|
||||
|
||||
len = mt76_is_usb(&dev->mt76) ? skb->len : skb->len + sizeof(hdr);
|
||||
hdr = FIELD_PREP(MT792x_SDIO_HDR_TX_BYTES, len) |
|
||||
FIELD_PREP(MT792x_SDIO_HDR_PKT_TYPE, type);
|
||||
|
||||
put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
|
||||
}
|
||||
|
||||
int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);
|
||||
int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev);
|
||||
|
||||
@@ -91,6 +91,28 @@ void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_tx);
|
||||
|
||||
void mt792x_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
|
||||
cancel_delayed_work_sync(&phy->mt76->mac_work);
|
||||
|
||||
cancel_delayed_work_sync(&dev->pm.ps_work);
|
||||
cancel_work_sync(&dev->pm.wake_work);
|
||||
cancel_work_sync(&dev->reset_work);
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
if (is_mt7921(&dev->mt76)) {
|
||||
mt792x_mutex_acquire(dev);
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_stop);
|
||||
|
||||
void mt792x_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -115,7 +137,7 @@ void mt792x_remove_interface(struct ieee80211_hw *hw,
|
||||
list_del_init(&msta->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_remove_interface);
|
||||
|
||||
@@ -243,7 +265,7 @@ int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mvif->ctx = ctx;
|
||||
mvif->mt76.ctx = ctx;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return 0;
|
||||
@@ -259,7 +281,7 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
mvif->ctx = NULL;
|
||||
mvif->mt76.ctx = NULL;
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx);
|
||||
@@ -358,7 +380,7 @@ void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
memcpy(data, *mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));
|
||||
memcpy(data, mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));
|
||||
|
||||
data += sizeof(mt792x_gstrings_stats);
|
||||
page_pool_ethtool_stats_get_strings(data);
|
||||
|
||||
@@ -88,25 +88,44 @@ EXPORT_SYMBOL_GPL(mt792x_rx_poll_complete);
|
||||
#define PREFETCH(base, depth) ((base) << 16 | (depth))
|
||||
static void mt792x_dma_prefetch(struct mt792x_dev *dev)
|
||||
{
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4));
|
||||
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
|
||||
if (is_mt7925(&dev->mt76)) {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0000, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x0040, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x0080, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x00c0, 0x4));
|
||||
/* tx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x0100, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x0200, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x0300, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x0400, 0x10));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING15_EXT_CTRL, PREFETCH(0x0500, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x0540, 0x4));
|
||||
} else {
|
||||
/* rx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4));
|
||||
/* tx ring */
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4));
|
||||
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
|
||||
}
|
||||
}
|
||||
|
||||
int mt792x_dma_enable(struct mt792x_dev *dev)
|
||||
{
|
||||
if (is_mt7925(&dev->mt76))
|
||||
mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
|
||||
|
||||
/* configure perfetch settings */
|
||||
mt792x_dma_prefetch(dev);
|
||||
|
||||
|
||||
@@ -287,6 +287,15 @@ int mt792xu_init_reset(struct mt792x_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_init_reset);
|
||||
|
||||
void mt792xu_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
mt792x_stop(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792xu_stop);
|
||||
|
||||
void mt792xu_disconnect(struct usb_interface *usb_intf)
|
||||
{
|
||||
struct mt792x_dev *dev = usb_get_intfdata(usb_intf);
|
||||
|
||||
@@ -54,23 +54,31 @@ static void mt7996_led_set_config(struct led_classdev *led_cdev,
|
||||
dev = container_of(mphy->dev, struct mt7996_dev, mt76);
|
||||
|
||||
/* select TX blink mode, 2: only data frames */
|
||||
mt76_rmw_field(dev, MT_TMAC_TCR0(0), MT_TMAC_TCR0_TX_BLINK, 2);
|
||||
mt76_rmw_field(dev, MT_TMAC_TCR0(mphy->band_idx), MT_TMAC_TCR0_TX_BLINK, 2);
|
||||
|
||||
/* enable LED */
|
||||
mt76_wr(dev, MT_LED_EN(0), 1);
|
||||
mt76_wr(dev, MT_LED_EN(mphy->band_idx), 1);
|
||||
|
||||
/* set LED Tx blink on/off time */
|
||||
val = FIELD_PREP(MT_LED_TX_BLINK_ON_MASK, delay_on) |
|
||||
FIELD_PREP(MT_LED_TX_BLINK_OFF_MASK, delay_off);
|
||||
mt76_wr(dev, MT_LED_TX_BLINK(0), val);
|
||||
mt76_wr(dev, MT_LED_TX_BLINK(mphy->band_idx), val);
|
||||
|
||||
/* turn LED off */
|
||||
if (delay_off == 0xff && delay_on == 0x0) {
|
||||
val = MT_LED_CTRL_POLARITY | MT_LED_CTRL_KICK;
|
||||
} else {
|
||||
/* control LED */
|
||||
val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
|
||||
if (mphy->band_idx == MT_BAND1)
|
||||
val |= MT_LED_CTRL_BLINK_BAND_SEL;
|
||||
}
|
||||
|
||||
/* control LED */
|
||||
val = MT_LED_CTRL_BLINK_MODE | MT_LED_CTRL_KICK;
|
||||
if (mphy->leds.al)
|
||||
val |= MT_LED_CTRL_POLARITY;
|
||||
|
||||
mt76_wr(dev, MT_LED_CTRL(0), val);
|
||||
mt76_clear(dev, MT_LED_CTRL(0), MT_LED_CTRL_KICK);
|
||||
mt76_wr(dev, MT_LED_CTRL(mphy->band_idx), val);
|
||||
mt76_clear(dev, MT_LED_CTRL(mphy->band_idx), MT_LED_CTRL_KICK);
|
||||
}
|
||||
|
||||
static int mt7996_led_set_blink(struct led_classdev *led_cdev,
|
||||
@@ -173,6 +181,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
wiphy->reg_notifier = mt7996_regd_notifier;
|
||||
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
|
||||
wiphy->mbssid_max_interfaces = 16;
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BSS_COLOR);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
|
||||
@@ -196,6 +205,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
||||
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_MULTI_BSSID);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
|
||||
@@ -223,6 +233,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
}
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
phy->mt76->leds.cdev.brightness_set = mt7996_led_set_brightness;
|
||||
phy->mt76->leds.cdev.blink_set = mt7996_led_set_blink;
|
||||
}
|
||||
|
||||
mt76_set_stream_caps(phy->mt76, true);
|
||||
mt7996_set_stream_vht_txbf_caps(phy);
|
||||
mt7996_set_stream_he_eht_caps(phy);
|
||||
@@ -258,6 +274,11 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
|
||||
set = FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_MODE, 0) |
|
||||
FIELD_PREP(MT_WTBLOFF_RSCR_RCPI_PARAM, 0x3);
|
||||
mt76_rmw(dev, MT_WTBLOFF_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.
|
||||
*/
|
||||
mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
|
||||
}
|
||||
|
||||
static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
|
||||
@@ -733,16 +754,17 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
|
||||
|
||||
val = max_t(u8, sts - 1, 3);
|
||||
eht_cap_elem->phy_cap_info[0] |=
|
||||
u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
|
||||
u8_encode_bits(u8_get_bits(val, BIT(0)),
|
||||
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[1] =
|
||||
u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),
|
||||
u8_encode_bits(u8_get_bits(val, GENMASK(2, 1)),
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1,
|
||||
u8_encode_bits(val,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1,
|
||||
u8_encode_bits(val,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[2] =
|
||||
@@ -869,12 +891,6 @@ int mt7996_register_device(struct mt7996_dev *dev)
|
||||
|
||||
mt7996_init_wiphy(hw);
|
||||
|
||||
/* init led callbacks */
|
||||
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
|
||||
dev->mphy.leds.cdev.brightness_set = mt7996_led_set_brightness;
|
||||
dev->mphy.leds.cdev.blink_set = mt7996_led_set_blink;
|
||||
}
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
|
||||
@@ -433,7 +433,9 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
status->bw = RATE_INFO_BW_160;
|
||||
break;
|
||||
/* rxv reports bw 320-1 and 320-2 separately */
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
case IEEE80211_STA_RX_BW_320 + 1:
|
||||
status->bw = RATE_INFO_BW_320;
|
||||
break;
|
||||
default:
|
||||
@@ -948,15 +950,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
if (sta) {
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
|
||||
if (time_after(jiffies, msta->jiffies + HZ / 4)) {
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
msta->jiffies = jiffies;
|
||||
}
|
||||
}
|
||||
|
||||
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
|
||||
t->skb = tx_info->skb;
|
||||
|
||||
@@ -991,11 +984,9 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
}
|
||||
|
||||
txp->fw.token = cpu_to_le16(id);
|
||||
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
|
||||
txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
|
||||
else
|
||||
txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
txp->fw.rept_wds_wcid = cpu_to_le16(sta ? wcid->idx : 0xfff);
|
||||
|
||||
tx_info->skb = NULL;
|
||||
|
||||
/* pass partial skb header to fw */
|
||||
tx_info->buf[1].len = MT_CT_PARSE_LEN;
|
||||
@@ -1006,22 +997,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7996_sta *msta;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
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);
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
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 (is_8023) {
|
||||
fc = IEEE80211_FTYPE_DATA |
|
||||
(sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
|
||||
} else {
|
||||
/* No need to get precise TID for Action/Management Frame,
|
||||
* since it will not meet the following Frame Control
|
||||
* condition anyway.
|
||||
*/
|
||||
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
fc = le16_to_cpu(hdr->frame_control) &
|
||||
(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
|
||||
}
|
||||
|
||||
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
|
||||
return;
|
||||
|
||||
@@ -1049,9 +1053,9 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
|
||||
wcid_idx = wcid->idx;
|
||||
|
||||
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7996_tx_check_aggr(sta, txwi);
|
||||
mt7996_tx_check_aggr(sta, t->skb);
|
||||
} else {
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
|
||||
}
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
@@ -1070,6 +1074,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
|
||||
struct mt76_txwi_cache *txwi;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct mt76_wcid *wcid;
|
||||
LIST_HEAD(free_list);
|
||||
struct sk_buff *skb, *tmp;
|
||||
void *end = data + len;
|
||||
@@ -1088,7 +1093,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 4))
|
||||
if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
|
||||
return;
|
||||
|
||||
total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
|
||||
@@ -1104,7 +1109,6 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
info = le32_to_cpu(*cur_info);
|
||||
if (info & MT_TXFREE_INFO_PAIR) {
|
||||
struct mt7996_sta *msta;
|
||||
struct mt76_wcid *wcid;
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
|
||||
@@ -1120,10 +1124,21 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
&mdev->sta_poll_list);
|
||||
spin_unlock_bh(&mdev->sta_poll_lock);
|
||||
continue;
|
||||
}
|
||||
} else if (info & MT_TXFREE_INFO_HEADER) {
|
||||
u32 tx_retries = 0, tx_failed = 0;
|
||||
|
||||
if (info & MT_TXFREE_INFO_HEADER)
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
tx_retries =
|
||||
FIELD_GET(MT_TXFREE_INFO_COUNT, info) - 1;
|
||||
tx_failed = tx_retries +
|
||||
!!FIELD_GET(MT_TXFREE_INFO_STAT, info);
|
||||
|
||||
wcid->stats.tx_retries += tx_retries;
|
||||
wcid->stats.tx_failed += tx_failed;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
msdu = (info >> (15 * i)) & MT_TXFREE_INFO_MSDU_ID;
|
||||
@@ -1167,22 +1182,31 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
|
||||
bool cck = false;
|
||||
u32 txrate, txs, mode, stbc;
|
||||
|
||||
mt76_tx_status_lock(mdev, &list);
|
||||
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
|
||||
if (!skb)
|
||||
goto out_no_skb;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
mt76_tx_status_lock(mdev, &list);
|
||||
skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
|
||||
|
||||
info->status.ampdu_len = 1;
|
||||
info->status.ampdu_ack_len = !!(info->flags &
|
||||
IEEE80211_TX_STAT_ACK);
|
||||
if (skb) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (!(txs & MT_TXS0_ACK_ERROR_MASK))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
info->status.rates[0].idx = -1;
|
||||
info->status.ampdu_len = 1;
|
||||
info->status.ampdu_ack_len =
|
||||
!!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
|
||||
info->status.rates[0].idx = -1;
|
||||
}
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wcid->sta) {
|
||||
struct ieee80211_sta *sta;
|
||||
u8 tid;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
tid = FIELD_GET(MT_TXS0_TID, txs);
|
||||
ieee80211_refresh_tx_agg_session_timer(sta, tid);
|
||||
}
|
||||
|
||||
txrate = FIELD_GET(MT_TXS0_TX_RATE, txs);
|
||||
|
||||
@@ -1282,9 +1306,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
|
||||
wcid->rate = rate;
|
||||
|
||||
out:
|
||||
mt76_tx_status_skb_done(mdev, skb, &list);
|
||||
|
||||
out_no_skb:
|
||||
if (skb)
|
||||
mt76_tx_status_skb_done(mdev, skb, &list);
|
||||
mt76_tx_status_unlock(mdev, &list);
|
||||
|
||||
return !!skb;
|
||||
@@ -1298,13 +1321,10 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
|
||||
u16 wcidx;
|
||||
u8 pid;
|
||||
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
|
||||
|
||||
if (pid < MT_PACKET_ID_FIRST)
|
||||
if (pid < MT_PACKET_ID_NO_SKB)
|
||||
return;
|
||||
|
||||
if (wcidx >= mt7996_wtbl_size(dev))
|
||||
@@ -2191,6 +2211,11 @@ void mt7996_mac_work(struct work_struct *work)
|
||||
mphy->mac_work_count = 0;
|
||||
|
||||
mt7996_mac_update_stats(phy);
|
||||
|
||||
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
|
||||
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
|
||||
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mphy->dev->mutex);
|
||||
|
||||
@@ -190,7 +190,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
|
||||
mvif->mt76.omac_idx = idx;
|
||||
mvif->phy = phy;
|
||||
mvif->mt76.band_idx = band_idx;
|
||||
mvif->mt76.wmm_idx = band_idx;
|
||||
mvif->mt76.wmm_idx = vif->type != NL80211_IFTYPE_AP;
|
||||
|
||||
ret = mt7996_mcu_add_dev_info(phy, vif, true);
|
||||
if (ret)
|
||||
@@ -207,7 +207,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
|
||||
mvif->sta.wcid.phy_idx = band_idx;
|
||||
mvif->sta.wcid.hw_key_idx = -1;
|
||||
mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
mt76_packet_id_init(&mvif->sta.wcid);
|
||||
mt76_wcid_init(&mvif->sta.wcid);
|
||||
|
||||
mt7996_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
@@ -248,8 +248,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
int idx = msta->wcid.idx;
|
||||
|
||||
mt7996_mcu_add_bss_info(phy, vif, false);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, false);
|
||||
mt7996_mcu_add_bss_info(phy, vif, false);
|
||||
|
||||
if (vif == phy->monitor_vif)
|
||||
phy->monitor_vif = NULL;
|
||||
@@ -268,7 +268,7 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
|
||||
list_del_init(&msta->wcid.poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
mt76_packet_id_flush(&dev->mt76, &msta->wcid);
|
||||
mt76_wcid_cleanup(&dev->mt76, &msta->wcid);
|
||||
}
|
||||
|
||||
int mt7996_set_channel(struct mt7996_phy *phy)
|
||||
@@ -414,10 +414,16 @@ mt7996_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
const u8 mq_to_aci[] = {
|
||||
[IEEE80211_AC_VO] = 3,
|
||||
[IEEE80211_AC_VI] = 2,
|
||||
[IEEE80211_AC_BE] = 0,
|
||||
[IEEE80211_AC_BK] = 1,
|
||||
};
|
||||
|
||||
/* firmware uses access class index */
|
||||
mvif->queue_params[mq_to_aci[queue]] = *params;
|
||||
/* no need to update right away, we'll get BSS_CHANGED_QOS */
|
||||
queue = mt76_connac_lmac_mapping(queue);
|
||||
mvif->queue_params[queue] = *params;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -564,17 +570,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
||||
/* station mode uses BSSID to map the wlan entry to a peer,
|
||||
* 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);
|
||||
|
||||
mt7996_mcu_add_bss_info(phy, vif, join);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, join);
|
||||
if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
|
||||
(changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
|
||||
(changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
|
||||
mt7996_mcu_add_bss_info(phy, vif, true);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, true);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC)
|
||||
mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT)
|
||||
mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
|
||||
|
||||
@@ -595,11 +597,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mvif->basic_rates_idx =
|
||||
mt7996_get_rates_table(hw, vif, false, false);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
|
||||
mt7996_mcu_add_bss_info(phy, vif, true);
|
||||
mt7996_mcu_add_sta(dev, vif, NULL, true);
|
||||
}
|
||||
|
||||
/* ensure that enable txcmd_mode after bss_info */
|
||||
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7996_mcu_set_tx(dev, vif);
|
||||
@@ -618,8 +615,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mt7996_mcu_add_beacon(hw, vif, info->enable_beacon);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP ||
|
||||
changed & BSS_CHANGED_FILS_DISCOVERY)
|
||||
if (changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
BSS_CHANGED_FILS_DISCOVERY))
|
||||
mt7996_mcu_beacon_inband_discov(dev, vif, changed);
|
||||
|
||||
if (changed & BSS_CHANGED_MU_GROUPS)
|
||||
@@ -660,7 +657,6 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
msta->wcid.idx = idx;
|
||||
msta->wcid.phy_idx = band_idx;
|
||||
msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
msta->jiffies = jiffies;
|
||||
|
||||
ewma_avg_signal_init(&msta->avg_ack_signal);
|
||||
|
||||
@@ -972,6 +968,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct rate_info *txrate = &msta->wcid.rate;
|
||||
|
||||
@@ -992,11 +989,31 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
|
||||
sinfo->txrate.flags = txrate->flags;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
|
||||
|
||||
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);
|
||||
|
||||
sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
|
||||
|
||||
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
|
||||
sinfo->tx_bytes = msta->wcid.stats.tx_bytes;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES64);
|
||||
|
||||
sinfo->rx_bytes = msta->wcid.stats.rx_bytes;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES64);
|
||||
|
||||
sinfo->tx_packets = msta->wcid.stats.tx_packets;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
|
||||
|
||||
sinfo->rx_packets = msta->wcid.stats.rx_packets;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7996_sta_rc_work(void *data, struct ieee80211_sta *sta)
|
||||
@@ -1192,7 +1209,7 @@ void mt7996_get_et_strings(struct ieee80211_hw *hw,
|
||||
u32 sset, u8 *data)
|
||||
{
|
||||
if (sset == ETH_SS_STATS)
|
||||
memcpy(data, *mt7996_gstrings_stats,
|
||||
memcpy(data, mt7996_gstrings_stats,
|
||||
sizeof(mt7996_gstrings_stats));
|
||||
}
|
||||
|
||||
|
||||
@@ -324,8 +324,10 @@ int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
|
||||
static void
|
||||
mt7996_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif->bss_conf.csa_active)
|
||||
ieee80211_csa_finish(vif);
|
||||
if (!vif->bss_conf.csa_active || vif->type == NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
ieee80211_csa_finish(vif);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -399,7 +401,7 @@ out:
|
||||
static void
|
||||
mt7996_mcu_cca_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (!vif->bss_conf.color_change_active)
|
||||
if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
ieee80211_color_change_finish(vif);
|
||||
@@ -447,6 +449,54 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7996_mcu_all_sta_info_event *res;
|
||||
u16 i;
|
||||
|
||||
skb_pull(skb, sizeof(struct mt7996_mcu_rxd));
|
||||
|
||||
res = (struct mt7996_mcu_all_sta_info_event *)skb->data;
|
||||
|
||||
for (i = 0; i < le16_to_cpu(res->sta_num); i++) {
|
||||
u8 ac;
|
||||
u16 wlan_idx;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
switch (le16_to_cpu(res->tag)) {
|
||||
case UNI_ALL_STA_TXRX_ADM_STAT:
|
||||
wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
||||
|
||||
if (!wcid)
|
||||
break;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
wcid->stats.tx_bytes +=
|
||||
le32_to_cpu(res->adm_stat[i].tx_bytes[ac]);
|
||||
wcid->stats.rx_bytes +=
|
||||
le32_to_cpu(res->adm_stat[i].rx_bytes[ac]);
|
||||
}
|
||||
break;
|
||||
case UNI_ALL_STA_TXRX_MSDU_COUNT:
|
||||
wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
||||
|
||||
if (!wcid)
|
||||
break;
|
||||
|
||||
wcid->stats.tx_packets +=
|
||||
le32_to_cpu(res->msdu_cnt[i].tx_msdu_cnt);
|
||||
wcid->stats.rx_packets +=
|
||||
le32_to_cpu(res->msdu_cnt[i].rx_msdu_cnt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
@@ -491,6 +541,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
case MCU_UNI_EVENT_RDD_REPORT:
|
||||
mt7996_mcu_rx_radar_detected(dev, skb);
|
||||
break;
|
||||
case MCU_UNI_EVENT_ALL_STA_INFO:
|
||||
mt7996_mcu_rx_all_sta_info_event(dev, skb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -600,6 +653,24 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
struct mt7996_phy *phy, int enable)
|
||||
{
|
||||
struct bss_info_uni_mbssid *mbssid;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_11V_MBSSID, sizeof(*mbssid));
|
||||
|
||||
mbssid = (struct bss_info_uni_mbssid *)tlv;
|
||||
|
||||
if (enable && vif->bss_conf.bssid_indicator) {
|
||||
mbssid->max_indicator = vif->bss_conf.bssid_indicator;
|
||||
mbssid->mbss_idx = vif->bss_conf.bssid_index;
|
||||
mbssid->tx_bss_omac_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_bss_bmc_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
|
||||
struct mt7996_phy *phy)
|
||||
@@ -866,6 +937,9 @@ int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
|
||||
/* this tag is necessary no matter if the vif is MLD */
|
||||
mt7996_mcu_bss_mld_tlv(skb, vif);
|
||||
}
|
||||
|
||||
mt7996_mcu_bss_mbssid_tlv(skb, vif, phy, enable);
|
||||
|
||||
out:
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
@@ -1152,6 +1226,8 @@ mt7996_mcu_sta_muru_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
||||
HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
|
||||
muru->ofdma_ul.uo_ra =
|
||||
HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
|
||||
muru->ofdma_ul.rx_ctrl_frame_to_mbss =
|
||||
HE_MAC(CAP3_RX_CTRL_FRAME_TO_MULTIBSS, elem->mac_cap_info[3]);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -1624,6 +1700,132 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
MCU_WM_UNI_CMD(RA), true);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, void *data, u32 field)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct sta_phy *phy = data;
|
||||
struct sta_rec_ra_fixed *ra;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||
&msta->wcid,
|
||||
MT7996_STA_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
|
||||
ra = (struct sta_rec_ra_fixed *)tlv;
|
||||
|
||||
switch (field) {
|
||||
case RATE_PARAM_AUTO:
|
||||
break;
|
||||
case RATE_PARAM_FIXED:
|
||||
case RATE_PARAM_FIXED_MCS:
|
||||
case RATE_PARAM_FIXED_GI:
|
||||
case RATE_PARAM_FIXED_HE_LTF:
|
||||
if (phy)
|
||||
ra->phy = *phy;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ra->field = cpu_to_le32(field);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
|
||||
struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
|
||||
enum nl80211_band band = chandef->chan->band;
|
||||
struct sta_phy phy = {};
|
||||
int ret, nrates = 0;
|
||||
|
||||
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
|
||||
do { \
|
||||
u8 i, gi = mask->control[band]._gi; \
|
||||
gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \
|
||||
phy.sgi = gi; \
|
||||
phy.he_ltf = mask->control[band].he_ltf; \
|
||||
for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \
|
||||
if (!mask->control[band]._mcs[i]) \
|
||||
continue; \
|
||||
nrates += hweight16(mask->control[band]._mcs[i]); \
|
||||
phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \
|
||||
if (_ht) \
|
||||
phy.mcs += 8 * i; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (sta->deflink.he_cap.has_he) {
|
||||
__sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1);
|
||||
} else if (sta->deflink.vht_cap.vht_supported) {
|
||||
__sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0);
|
||||
} else if (sta->deflink.ht_cap.ht_supported) {
|
||||
__sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0);
|
||||
} else {
|
||||
nrates = hweight32(mask->control[band].legacy);
|
||||
phy.mcs = ffs(mask->control[band].legacy) - 1;
|
||||
}
|
||||
#undef __sta_phy_bitrate_mask_check
|
||||
|
||||
/* fall back to auto rate control */
|
||||
if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
|
||||
mask->control[band].he_gi == GENMASK(7, 0) &&
|
||||
mask->control[band].he_ltf == GENMASK(7, 0) &&
|
||||
nrates != 1)
|
||||
return 0;
|
||||
|
||||
/* fixed single rate */
|
||||
if (nrates == 1) {
|
||||
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
|
||||
RATE_PARAM_FIXED_MCS);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fixed GI */
|
||||
if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
|
||||
mask->control[band].he_gi != GENMASK(7, 0)) {
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
u32 addr;
|
||||
|
||||
/* firmware updates only TXCMD but doesn't take WTBL into
|
||||
* account, so driver should update here to reflect the
|
||||
* actual txrate hardware sends out.
|
||||
*/
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
|
||||
if (sta->deflink.he_cap.has_he)
|
||||
mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
|
||||
else
|
||||
mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
|
||||
|
||||
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
|
||||
RATE_PARAM_FIXED_GI);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* fixed HE_LTF */
|
||||
if (mask->control[band].he_ltf != GENMASK(7, 0)) {
|
||||
ret = mt7996_mcu_set_fixed_field(dev, vif, sta, &phy,
|
||||
RATE_PARAM_FIXED_HE_LTF);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
||||
@@ -1733,6 +1935,7 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||
&msta->wcid,
|
||||
@@ -1752,8 +1955,12 @@ int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
*/
|
||||
mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_mcu_add_rate_ctrl_fixed(dev, vif, sta);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1995,6 +2202,59 @@ mt7996_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
|
||||
info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif, struct bss_bcn_content_tlv *bcn,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
struct bss_bcn_mbss_tlv *mbss;
|
||||
const struct element *elem;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!vif->bss_conf.bssid_indicator)
|
||||
return;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_MBSSID, sizeof(*mbss));
|
||||
|
||||
mbss = (struct bss_bcn_mbss_tlv *)tlv;
|
||||
mbss->offset[0] = cpu_to_le16(offs->tim_offset);
|
||||
mbss->bitmap = cpu_to_le32(1);
|
||||
|
||||
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID,
|
||||
&skb->data[offs->mbssid_off],
|
||||
skb->len - offs->mbssid_off) {
|
||||
const struct element *sub_elem;
|
||||
|
||||
if (elem->datalen < 2)
|
||||
continue;
|
||||
|
||||
for_each_element(sub_elem, elem->data + 1, elem->datalen - 1) {
|
||||
const struct ieee80211_bssid_index *idx;
|
||||
const u8 *idx_ie;
|
||||
|
||||
/* not a valid BSS profile */
|
||||
if (sub_elem->id || sub_elem->datalen < 4)
|
||||
continue;
|
||||
|
||||
/* Find WLAN_EID_MULTI_BSSID_IDX
|
||||
* in the merged nontransmitted profile
|
||||
*/
|
||||
idx_ie = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||
sub_elem->data, sub_elem->datalen);
|
||||
if (!idx_ie || idx_ie[1] < sizeof(*idx))
|
||||
continue;
|
||||
|
||||
idx = (void *)(idx_ie + 2);
|
||||
if (!idx->bssid_index || idx->bssid_index > 31)
|
||||
continue;
|
||||
|
||||
mbss->offset[idx->bssid_index] = cpu_to_le16(idx_ie -
|
||||
skb->data);
|
||||
mbss->bitmap |= cpu_to_le32(BIT(idx->bssid_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct sk_buff *skb,
|
||||
@@ -2016,7 +2276,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
bcn->bcc_ie_pos = cpu_to_le16(offset - 3);
|
||||
}
|
||||
|
||||
buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
|
||||
buf = (u8 *)bcn + sizeof(*bcn);
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
|
||||
BSS_CHANGED_BEACON);
|
||||
|
||||
@@ -2034,26 +2294,25 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
struct bss_bcn_content_tlv *bcn;
|
||||
int len;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
return 0;
|
||||
|
||||
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
|
||||
MT7996_BEACON_UPDATE_SIZE);
|
||||
MT7996_MAX_BSS_OFFLOAD_SIZE);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb,
|
||||
UNI_BSS_INFO_BCN_CONTENT, sizeof(*bcn));
|
||||
bcn = (struct bss_bcn_content_tlv *)tlv;
|
||||
bcn->enable = en;
|
||||
|
||||
if (!en)
|
||||
goto out;
|
||||
|
||||
skb = ieee80211_beacon_get_template(hw, vif, &offs, 0);
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb->len > MAX_BEACON_SIZE - MT_TXD_SIZE) {
|
||||
if (skb->len > MT7996_MAX_BEACON_SIZE) {
|
||||
dev_err(dev->mt76.dev, "Bcn size limit exceed\n");
|
||||
dev_kfree_skb(rskb);
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2061,11 +2320,18 @@ int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
|
||||
|
||||
len = sizeof(*bcn) + MT_TXD_SIZE + skb->len;
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len);
|
||||
bcn = (struct bss_bcn_content_tlv *)tlv;
|
||||
bcn->enable = en;
|
||||
if (!en)
|
||||
goto out;
|
||||
|
||||
mt7996_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
/* TODO: subtag - 11v MBSSID */
|
||||
mt7996_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
|
||||
mt7996_mcu_beacon_cntdwn(vif, rskb, skb, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
return mt76_mcu_skb_send_msg(&phy->dev->mt76, rskb,
|
||||
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
@@ -2086,9 +2352,13 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
struct sk_buff *rskb, *skb = NULL;
|
||||
struct tlv *tlv;
|
||||
u8 *buf, interval;
|
||||
int len;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
return 0;
|
||||
|
||||
rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
|
||||
MT7996_INBAND_FRAME_SIZE);
|
||||
MT7996_MAX_BSS_OFFLOAD_SIZE);
|
||||
if (IS_ERR(rskb))
|
||||
return PTR_ERR(rskb);
|
||||
|
||||
@@ -2102,11 +2372,14 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
skb = ieee80211_get_unsol_bcast_probe_resp_tmpl(hw, vif);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
dev_kfree_skb(rskb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb->len > MAX_INBAND_FRAME_SIZE - MT_TXD_SIZE) {
|
||||
if (skb->len > MT7996_MAX_BEACON_SIZE) {
|
||||
dev_err(dev->mt76.dev, "inband discovery size limit exceed\n");
|
||||
dev_kfree_skb(rskb);
|
||||
dev_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2116,7 +2389,9 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
info->band = band;
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->mt76->band_idx);
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, sizeof(*discov));
|
||||
len = sizeof(*discov) + MT_TXD_SIZE + skb->len;
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_OFFLOAD, len);
|
||||
|
||||
discov = (struct bss_inband_discovery_tlv *)tlv;
|
||||
discov->tx_mode = OFFLOAD_TX_MODE_SU;
|
||||
@@ -2127,7 +2402,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
discov->enable = true;
|
||||
discov->wcid = cpu_to_le16(MT7996_WTBL_RESERVED);
|
||||
|
||||
buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
|
||||
buf = (u8 *)tlv + sizeof(*discov);
|
||||
|
||||
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0, changed);
|
||||
|
||||
@@ -2679,7 +2954,7 @@ int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif)
|
||||
|
||||
e = (struct edca *)tlv;
|
||||
e->set = WMM_PARAM_SET;
|
||||
e->queue = ac + mvif->mt76.wmm_idx * MT7996_MAX_WMM_SETS;
|
||||
e->queue = ac;
|
||||
e->aifs = q->aifs;
|
||||
e->txop = cpu_to_le16(q->txop);
|
||||
|
||||
@@ -2960,10 +3235,10 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
|
||||
.channel_band = ch_band[chandef->chan->band],
|
||||
};
|
||||
|
||||
if (tag == UNI_CHANNEL_RX_PATH ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
if (phy->mt76->hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
else if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL ||
|
||||
phy->mt76->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
else if (!cfg80211_reg_can_beacon(phy->mt76->hw->wiphy, chandef,
|
||||
NL80211_IFTYPE_AP))
|
||||
@@ -3307,8 +3582,8 @@ int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action)
|
||||
|
||||
tlv = mt7996_mcu_add_uni_tlv(skb, action, sizeof(*req_mod_en));
|
||||
req_mod_en = (struct bf_mod_en_ctrl *)tlv;
|
||||
req_mod_en->bf_num = 2;
|
||||
req_mod_en->bf_bitmap = GENMASK(0, 0);
|
||||
req_mod_en->bf_num = 3;
|
||||
req_mod_en->bf_bitmap = GENMASK(2, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -3548,7 +3823,9 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||
int cmd)
|
||||
{
|
||||
struct {
|
||||
u8 _rsv[4];
|
||||
/* fixed field */
|
||||
u8 bss;
|
||||
u8 _rsv[3];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -3566,7 +3843,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||
u8 exponent;
|
||||
u8 is_ap;
|
||||
u8 agrt_params;
|
||||
u8 __rsv2[135];
|
||||
u8 __rsv2[23];
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(UNI_CMD_TWT_ARGT_UPDATE),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
@@ -3576,6 +3853,7 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||
.flowid = flow->id,
|
||||
.peer_id = cpu_to_le16(flow->wcid),
|
||||
.duration = flow->duration,
|
||||
.bss = mvif->mt76.idx,
|
||||
.bss_idx = mvif->mt76.idx,
|
||||
.start_tsf = cpu_to_le64(flow->tsf),
|
||||
.mantissa = flow->mantissa,
|
||||
@@ -3786,3 +4064,20 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
|
||||
sizeof(req), true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
struct {
|
||||
u8 _rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(tag),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
@@ -153,6 +153,32 @@ struct mt7996_mcu_mib {
|
||||
__le64 data;
|
||||
} __packed;
|
||||
|
||||
struct mt7996_mcu_all_sta_info_event {
|
||||
u8 rsv[4];
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 more;
|
||||
u8 rsv2;
|
||||
__le16 sta_num;
|
||||
u8 rsv3[2];
|
||||
|
||||
union {
|
||||
struct {
|
||||
__le16 wlan_idx;
|
||||
u8 rsv[2];
|
||||
__le32 tx_bytes[IEEE80211_NUM_ACS];
|
||||
__le32 rx_bytes[IEEE80211_NUM_ACS];
|
||||
} adm_stat[0];
|
||||
|
||||
struct {
|
||||
__le16 wlan_idx;
|
||||
u8 rsv[2];
|
||||
__le32 tx_msdu_cnt;
|
||||
__le32 rx_msdu_cnt;
|
||||
} msdu_cnt[0];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
enum mt7996_chan_mib_offs {
|
||||
UNI_MIB_OBSS_AIRTIME = 26,
|
||||
UNI_MIB_NON_WIFI_TIME = 27,
|
||||
@@ -270,8 +296,6 @@ struct bss_inband_discovery_tlv {
|
||||
u8 enable;
|
||||
__le16 wcid;
|
||||
__le16 prob_rsp_len;
|
||||
#define MAX_INBAND_FRAME_SIZE 512
|
||||
u8 pkt[MAX_INBAND_FRAME_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct bss_bcn_content_tlv {
|
||||
@@ -283,8 +307,6 @@ struct bss_bcn_content_tlv {
|
||||
u8 enable;
|
||||
u8 type;
|
||||
__le16 pkt_len;
|
||||
#define MAX_BEACON_SIZE 512
|
||||
u8 pkt[MAX_BEACON_SIZE];
|
||||
} __packed;
|
||||
|
||||
struct bss_bcn_cntdwn_tlv {
|
||||
@@ -591,13 +613,14 @@ enum {
|
||||
sizeof(struct sta_rec_hdr_trans) + \
|
||||
sizeof(struct tlv))
|
||||
|
||||
#define MT7996_MAX_BEACON_SIZE 1342
|
||||
#define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \
|
||||
sizeof(struct bss_bcn_content_tlv) + \
|
||||
MT_TXD_SIZE + \
|
||||
sizeof(struct bss_bcn_cntdwn_tlv) + \
|
||||
sizeof(struct bss_bcn_mbss_tlv))
|
||||
|
||||
#define MT7996_INBAND_FRAME_SIZE (sizeof(struct bss_req_hdr) + \
|
||||
sizeof(struct bss_inband_discovery_tlv))
|
||||
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
|
||||
MT7996_BEACON_UPDATE_SIZE)
|
||||
|
||||
enum {
|
||||
UNI_BAND_CONFIG_RADIO_ENABLE,
|
||||
|
||||
@@ -110,7 +110,6 @@ struct mt7996_sta {
|
||||
struct ewma_avg_signal avg_ack_signal;
|
||||
|
||||
unsigned long changed;
|
||||
unsigned long jiffies;
|
||||
|
||||
struct mt76_connac_sta_key_conf bip;
|
||||
|
||||
@@ -402,6 +401,7 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
|
||||
int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
|
||||
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
|
||||
void mt7996_mcu_exit(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
|
||||
|
||||
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
|
||||
{
|
||||
|
||||
@@ -243,6 +243,13 @@ enum base_rev {
|
||||
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
|
||||
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
|
||||
|
||||
/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */
|
||||
#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band))
|
||||
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_AGG_ACR4(_band) MT_WF_AGG(_band, 0x3c)
|
||||
#define MT_AGG_ACR_PPDU_TXS2H BIT(1)
|
||||
|
||||
/* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */
|
||||
#define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band))
|
||||
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
|
||||
@@ -509,6 +516,7 @@ enum base_rev {
|
||||
|
||||
#define MT_LED_CTRL(_n) MT_LED_PHYS(0x00 + ((_n) * 4))
|
||||
#define MT_LED_CTRL_KICK BIT(7)
|
||||
#define MT_LED_CTRL_BLINK_BAND_SEL BIT(4)
|
||||
#define MT_LED_CTRL_BLINK_MODE BIT(2)
|
||||
#define MT_LED_CTRL_POLARITY BIT(1)
|
||||
|
||||
|
||||
@@ -329,40 +329,32 @@ void
|
||||
mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct mt76_queue *q;
|
||||
int qid = skb_get_queue_mapping(skb);
|
||||
|
||||
if (mt76_testmode_enabled(phy)) {
|
||||
ieee80211_free_txskb(phy->hw, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WARN_ON(qid >= MT_TXQ_PSD)) {
|
||||
qid = MT_TXQ_BE;
|
||||
skb_set_queue_mapping(skb, qid);
|
||||
}
|
||||
|
||||
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_bufferable_mmpdu(skb)) {
|
||||
qid = MT_TXQ_PSD;
|
||||
}
|
||||
if (WARN_ON(skb_get_queue_mapping(skb) >= MT_TXQ_PSD))
|
||||
skb_set_queue_mapping(skb, MT_TXQ_BE);
|
||||
|
||||
if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
|
||||
ieee80211_get_tx_rates(info->control.vif, sta, skb,
|
||||
info->control.rates, 1);
|
||||
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
q = phy->q_tx[qid];
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
|
||||
dev->queue_ops->kick(dev, q);
|
||||
spin_unlock_bh(&q->lock);
|
||||
spin_lock_bh(&wcid->tx_pending.lock);
|
||||
__skb_queue_tail(&wcid->tx_pending, skb);
|
||||
spin_unlock_bh(&wcid->tx_pending.lock);
|
||||
|
||||
spin_lock_bh(&phy->tx_lock);
|
||||
if (list_empty(&wcid->tx_list))
|
||||
list_add_tail(&wcid->tx_list, &phy->tx_list);
|
||||
spin_unlock_bh(&phy->tx_lock);
|
||||
|
||||
mt76_worker_schedule(&phy->dev->tx_worker);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_tx);
|
||||
|
||||
@@ -593,10 +585,86 @@ void mt76_txq_schedule(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_txq_schedule);
|
||||
|
||||
static int
|
||||
mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_queue *q;
|
||||
struct sk_buff *skb;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&wcid->tx_pending.lock);
|
||||
while ((skb = skb_peek(&wcid->tx_pending)) != NULL) {
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int qid = skb_get_queue_mapping(skb);
|
||||
|
||||
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_bufferable_mmpdu(skb))
|
||||
qid = MT_TXQ_PSD;
|
||||
|
||||
q = phy->q_tx[qid];
|
||||
if (mt76_txq_stopped(q)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
__skb_unlink(skb, &wcid->tx_pending);
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
sta = wcid_to_sta(wcid);
|
||||
spin_lock(&q->lock);
|
||||
__mt76_tx_queue_skb(phy, qid, skb, wcid, sta, NULL);
|
||||
dev->queue_ops->kick(dev, q);
|
||||
spin_unlock(&q->lock);
|
||||
|
||||
spin_lock(&wcid->tx_pending.lock);
|
||||
}
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
{
|
||||
if (list_empty(&phy->tx_list))
|
||||
return;
|
||||
|
||||
local_bh_disable();
|
||||
rcu_read_lock();
|
||||
|
||||
spin_lock(&phy->tx_lock);
|
||||
while (!list_empty(&phy->tx_list)) {
|
||||
struct mt76_wcid *wcid = NULL;
|
||||
int ret;
|
||||
|
||||
wcid = list_first_entry(&phy->tx_list, struct mt76_wcid, tx_list);
|
||||
list_del_init(&wcid->tx_list);
|
||||
|
||||
spin_unlock(&phy->tx_lock);
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid);
|
||||
spin_lock(&phy->tx_lock);
|
||||
|
||||
if (ret) {
|
||||
if (list_empty(&wcid->tx_list))
|
||||
list_add_tail(&wcid->tx_list, &phy->tx_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&phy->tx_lock);
|
||||
|
||||
rcu_read_unlock();
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
void mt76_txq_schedule_all(struct mt76_phy *phy)
|
||||
{
|
||||
int i;
|
||||
|
||||
mt76_txq_schedule_pending(phy);
|
||||
for (i = 0; i <= MT_TXQ_BK; i++)
|
||||
mt76_txq_schedule(phy, i);
|
||||
}
|
||||
|
||||
@@ -1897,7 +1897,7 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
/*this is wrong, fill_tx_cmddesc needs update*/
|
||||
pdesc = &ring->desc[0];
|
||||
|
||||
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
|
||||
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb);
|
||||
|
||||
__skb_queue_tail(&ring->queue, skb);
|
||||
|
||||
|
||||
@@ -665,9 +665,8 @@ void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
|
||||
}
|
||||
|
||||
void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
|
||||
u8 *pdesc8, bool firstseg,
|
||||
bool lastseg, struct sk_buff *skb)
|
||||
void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
@@ -687,8 +686,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
|
||||
}
|
||||
clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE);
|
||||
|
||||
if (firstseg)
|
||||
set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
|
||||
set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
|
||||
|
||||
set_tx_desc_tx_rate(pdesc, DESC92C_RATE1M);
|
||||
|
||||
|
||||
@@ -797,6 +797,5 @@ bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw,
|
||||
u8 hw_queue, u16 index);
|
||||
void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
|
||||
void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
|
||||
bool firstseg, bool lastseg,
|
||||
struct sk_buff *skb);
|
||||
#endif
|
||||
|
||||
@@ -518,9 +518,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
|
||||
rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
|
||||
}
|
||||
|
||||
void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
|
||||
u8 *pdesc8, bool firstseg,
|
||||
bool lastseg, struct sk_buff *skb)
|
||||
void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc8,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
@@ -540,9 +539,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
|
||||
}
|
||||
clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE);
|
||||
|
||||
if (firstseg)
|
||||
set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
|
||||
|
||||
set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
|
||||
set_tx_desc_tx_rate(pdesc, DESC_RATE1M);
|
||||
|
||||
set_tx_desc_seq(pdesc, 0);
|
||||
|
||||
@@ -527,6 +527,5 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
|
||||
u8 hw_queue, u16 index);
|
||||
void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
|
||||
void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
|
||||
bool b_firstseg, bool b_lastseg,
|
||||
struct sk_buff *skb);
|
||||
#endif
|
||||
|
||||
@@ -1539,7 +1539,7 @@ static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
* if its "here".
|
||||
*
|
||||
* This is maybe necessary:
|
||||
* rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
|
||||
* rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, skb);
|
||||
*/
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user