mt76 patches for 6.10

- fixes
 - mt7603 stability improvements
 - mt7921 LED control
 - mt7925 EHT radiotap support
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCZjNw8gAKCRDXfRQdAqdu
 9fGGAKCB12huzzRR/UIM21G6YFXQsHE+fQCgy5pPqDVlhWC/F7ZCS5jSPQtZfk8=
 =/JDa
 -----END PGP SIGNATURE-----

Merge tag 'mt76-for-kvalo-2024-05-02' of https://github.com/nbd168/wireless

mt76 patches for 6.10

- fixes
- mt7603 stability improvements
- mt7921 LED control
- mt7925 EHT radiotap support
This commit is contained in:
Kalle Valo 2024-05-03 13:27:45 +03:00
commit d08aeb97ce
39 changed files with 656 additions and 145 deletions

View File

@ -532,7 +532,7 @@ error:
}
static int
mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
mt76_dma_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
{
@ -542,6 +542,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_tx_info tx_info = {
.skb = skb,
};
struct mt76_dev *dev = phy->dev;
struct ieee80211_hw *hw;
int len, n = 0, ret = -ENOMEM;
struct mt76_txwi_cache *t;
@ -549,7 +550,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
dma_addr_t addr;
u8 *txwi;
if (test_bit(MT76_RESET, &dev->phy.state))
if (test_bit(MT76_RESET, &phy->state))
goto free_skb;
t = mt76_get_txwi(dev);

View File

@ -465,6 +465,7 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
ieee80211_hw_set(hw, SPECTRUM_MGMT);
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD) &&
hw->max_tx_fragments > 1) {

View File

@ -256,7 +256,7 @@ struct mt76_queue_ops {
int idx, int n_desc, int bufsize,
u32 ring_base);
int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
int (*tx_queue_skb)(struct mt76_phy *phy, struct mt76_queue *q,
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
@ -1127,7 +1127,7 @@ static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
#define mt76_init_queues(dev, ...) (dev)->mt76.queue_ops->init(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__)
#define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__)
#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mt76), __VA_ARGS__)
#define mt76_tx_queue_skb(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb(&((dev)->mphy), __VA_ARGS__)
#define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__)
#define mt76_queue_rx_cleanup(dev, ...) (dev)->mt76.queue_ops->rx_cleanup(&((dev)->mt76), __VA_ARGS__)

View File

@ -4,6 +4,13 @@
#include "mac.h"
#include "../dma.h"
static const u8 wmm_queue_map[] = {
[IEEE80211_AC_BK] = 0,
[IEEE80211_AC_BE] = 1,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_VO] = 3,
};
static void
mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
{
@ -22,10 +29,10 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
struct ieee80211_sta *sta;
struct mt7603_sta *msta;
struct mt76_wcid *wcid;
u8 tid = 0, hwq = 0;
void *priv;
int idx;
u32 val;
u8 tid = 0;
if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr))
goto free;
@ -42,19 +49,36 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
goto free;
priv = msta = container_of(wcid, struct mt7603_sta, wcid);
val = le32_to_cpu(txd[0]);
val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT);
txd[0] = cpu_to_le32(val);
sta = container_of(priv, struct ieee80211_sta, drv_priv);
hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE];
if (ieee80211_is_data_qos(hdr->frame_control))
hwq = wmm_queue_map[IEEE80211_AC_BE];
if (ieee80211_is_data_qos(hdr->frame_control)) {
tid = *ieee80211_get_qos_ctl(hdr) &
IEEE80211_QOS_CTL_TAG1D_MASK;
skb_set_queue_mapping(skb, tid_to_ac[tid]);
IEEE80211_QOS_CTL_TAG1D_MASK;
u8 qid = tid_to_ac[tid];
hwq = wmm_queue_map[qid];
skb_set_queue_mapping(skb, qid);
} else if (ieee80211_is_data(hdr->frame_control)) {
skb_set_queue_mapping(skb, IEEE80211_AC_BE);
hwq = wmm_queue_map[IEEE80211_AC_BE];
} else {
skb_pull(skb, MT_TXD_SIZE);
if (!ieee80211_is_bufferable_mmpdu(skb))
goto free;
skb_push(skb, MT_TXD_SIZE);
skb_set_queue_mapping(skb, MT_TXQ_PSD);
hwq = MT_TX_HW_QUEUE_MGMT;
}
ieee80211_sta_set_buffered(sta, tid, true);
val = le32_to_cpu(txd[0]);
val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
val |= FIELD_PREP(MT_TXD0_Q_IDX, hwq);
txd[0] = cpu_to_le32(val);
spin_lock_bh(&dev->ps_lock);
__skb_queue_tail(&msta->psq, skb);
if (skb_queue_len(&msta->psq) >= 64) {
@ -151,12 +175,6 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget)
int mt7603_dma_init(struct mt7603_dev *dev)
{
static const u8 wmm_queue_map[] = {
[IEEE80211_AC_BK] = 0,
[IEEE80211_AC_BE] = 1,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_VO] = 3,
};
int ret;
int i;

View File

@ -1393,6 +1393,7 @@ void mt7603_pse_client_reset(struct mt7603_dev *dev)
MT_CLIENT_RESET_TX_R_E_2_S);
/* Start PSE client TX abort */
mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1);
mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S,
MT_CLIENT_RESET_TX_R_E_1_S, 500);

View File

@ -177,6 +177,11 @@ static inline bool is_mt7925(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7925;
}
static inline bool is_mt7920(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7920;
}
static inline bool is_mt7922(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7922;
@ -184,7 +189,7 @@ static inline bool is_mt7922(struct mt76_dev *dev)
static inline bool is_mt7921(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7961 || is_mt7922(dev);
return mt76_chip(dev) == 0x7961 || is_mt7922(dev) || is_mt7920(dev);
}
static inline bool is_mt7663(struct mt76_dev *dev)
@ -259,6 +264,7 @@ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
{
switch (mt76_chip(dev)) {
case 0x7961:
case 0x7920:
case 0x7922:
case 0x7925:
case 0x7663:
@ -445,4 +451,6 @@ void mt76_connac2_tx_token_put(struct mt76_dev *dev);
/* connac3 */
void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
u8 mode);
void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv,
u8 mode);
#endif /* __MT76_CONNAC_H */

View File

@ -6,8 +6,11 @@
#include "dma.h"
#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
#define EHT_BITS(f) cpu_to_le32(IEEE80211_RADIOTAP_EHT_##f)
#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
IEEE80211_RADIOTAP_HE_##f)
#define EHT_PREP(f, m, v) le32_encode_bits(le32_get_bits(v, MT_CRXV_EHT_##m),\
IEEE80211_RADIOTAP_EHT_##f)
static void
mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
@ -180,3 +183,85 @@ void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
}
}
EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
static void *
mt76_connac3_mac_radiotap_push_tlv(struct sk_buff *skb, u16 type, u16 len)
{
struct ieee80211_radiotap_tlv *tlv;
tlv = skb_push(skb, sizeof(*tlv) + len);
tlv->type = cpu_to_le16(type);
tlv->len = cpu_to_le16(len);
memset(tlv->data, 0, len);
return tlv->data;
}
void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv,
u8 mode)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_radiotap_eht_usig *usig;
struct ieee80211_radiotap_eht *eht;
u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
u8 bw = FIELD_GET(MT_PRXV_FRAME_MODE, le32_to_cpu(rxv[2]));
if (WARN_ONCE(skb_mac_header(skb) != skb->data,
"Should push tlv at the top of mac hdr"))
return;
eht = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT,
sizeof(*eht) + sizeof(u32));
usig = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
sizeof(*usig));
status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
eht->known |= EHT_BITS(KNOWN_SPATIAL_REUSE) |
EHT_BITS(KNOWN_GI) |
EHT_BITS(KNOWN_EHT_LTF) |
EHT_BITS(KNOWN_LDPC_EXTRA_SYM_OM) |
EHT_BITS(KNOWN_PE_DISAMBIGUITY_OM) |
EHT_BITS(KNOWN_NSS_S);
eht->data[0] |=
EHT_PREP(DATA0_SPATIAL_REUSE, SR_MASK, rxv[13]) |
cpu_to_le32(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI, status->eht.gi) |
FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF, ltf_size)) |
EHT_PREP(DATA0_PE_DISAMBIGUITY_OM, PE_DISAMBIG, rxv[5]) |
EHT_PREP(DATA0_LDPC_EXTRA_SYM_OM, LDPC_EXT_SYM, rxv[4]);
eht->data[7] |= le32_encode_bits(status->nss, IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
eht->user_info[0] |=
EHT_BITS(USER_INFO_MCS_KNOWN) |
EHT_BITS(USER_INFO_CODING_KNOWN) |
EHT_BITS(USER_INFO_NSS_KNOWN_O) |
EHT_BITS(USER_INFO_BEAMFORMING_KNOWN_O) |
EHT_BITS(USER_INFO_DATA_FOR_USER) |
le32_encode_bits(status->rate_idx, IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
le32_encode_bits(status->nss, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O);
if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
eht->user_info[0] |= EHT_BITS(USER_INFO_BEAMFORMING_O);
if (le32_to_cpu(rxv[0]) & MT_PRXV_HT_AD_CODE)
eht->user_info[0] |= EHT_BITS(USER_INFO_CODING);
if (mode == MT_PHY_TYPE_EHT_MU)
eht->user_info[0] |= EHT_BITS(USER_INFO_STA_ID_KNOWN) |
EHT_PREP(USER_INFO_STA_ID, MU_AID, rxv[8]);
usig->common |=
EHT_BITS(USIG_COMMON_PHY_VER_KNOWN) |
EHT_BITS(USIG_COMMON_BW_KNOWN) |
EHT_BITS(USIG_COMMON_UL_DL_KNOWN) |
EHT_BITS(USIG_COMMON_BSS_COLOR_KNOWN) |
EHT_BITS(USIG_COMMON_TXOP_KNOWN) |
le32_encode_bits(0, IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER) |
le32_encode_bits(bw, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW) |
EHT_PREP(USIG_COMMON_UL_DL, UPLINK, rxv[5]) |
EHT_PREP(USIG_COMMON_BSS_COLOR, BSS_COLOR, rxv[9]) |
EHT_PREP(USIG_COMMON_TXOP, TXOP_DUR, rxv[9]);
}
EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_eht_radiotap);

View File

@ -142,6 +142,28 @@ enum {
#define MT_CRXV_HE_RU3_L GENMASK(31, 27)
#define MT_CRXV_HE_RU3_H GENMASK(3, 0)
#define MT_CRXV_EHT_NUM_USER GENMASK(26, 20)
#define MT_CRXV_EHT_LTF_SIZE GENMASK(28, 27)
#define MT_CRXV_EHT_LDPC_EXT_SYM BIT(30)
#define MT_CRXV_EHT_PE_DISAMBIG BIT(1)
#define MT_CRXV_EHT_UPLINK BIT(2)
#define MT_CRXV_EHT_MU_AID GENMASK(27, 17)
#define MT_CRXV_EHT_BEAM_CHNG BIT(29)
#define MT_CRXV_EHT_DOPPLER BIT(0)
#define MT_CRXV_EHT_BSS_COLOR GENMASK(15, 10)
#define MT_CRXV_EHT_TXOP_DUR GENMASK(23, 17)
#define MT_CRXV_EHT_SR_MASK GENMASK(11, 8)
#define MT_CRXV_EHT_SR1_MASK GENMASK(15, 12)
#define MT_CRXV_EHT_SR2_MASK GENMASK(19, 16)
#define MT_CRXV_EHT_SR3_MASK GENMASK(23, 20)
#define MT_CRXV_EHT_RU0 GENMASK(8, 0)
#define MT_CRXV_EHT_RU1 GENMASK(17, 9)
#define MT_CRXV_EHT_RU2 GENMASK(26, 18)
#define MT_CRXV_EHT_RU3_L GENMASK(31, 27)
#define MT_CRXV_EHT_RU3_H GENMASK(3, 0)
#define MT_CRXV_EHT_SIG_MCS GENMASK(19, 18)
#define MT_CRXV_EHT_LTF_SYM GENMASK(22, 20)
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,

View File

@ -257,7 +257,7 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len,
};
u16 ntlv;
ptlv = skb_put(skb, len);
ptlv = skb_put_zero(skb, len);
memcpy(ptlv, &tlv, sizeof(tlv));
ntlv = le16_to_cpu(ntlv_hdr->tlv_num);
@ -283,7 +283,7 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
};
struct sk_buff *skb;
if (is_mt799x(dev) && !wcid->sta)
if (wcid && !wcid->sta)
hdr.muar_idx = 0xe;
mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,
@ -392,7 +392,14 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
if (!sta) {
basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);
eth_broadcast_addr(basic->peer_addr);
if (vif->type == NL80211_IFTYPE_STATION &&
!is_zero_ether_addr(vif->bss_conf.bssid)) {
memcpy(basic->peer_addr, vif->bss_conf.bssid, ETH_ALEN);
basic->aid = cpu_to_le16(vif->cfg.aid);
} else {
eth_broadcast_addr(basic->peer_addr);
}
return;
}
@ -1670,7 +1677,7 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
set_bit(MT76_HW_SCANNING, &phy->state);
mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;
req = (struct mt76_connac_hw_scan_req *)skb_put(skb, sizeof(*req));
req = (struct mt76_connac_hw_scan_req *)skb_put_zero(skb, sizeof(*req));
req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;
req->bss_idx = mvif->idx;
@ -1798,7 +1805,7 @@ int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;
req = (struct mt76_connac_sched_scan_req *)skb_put(skb, sizeof(*req));
req = (struct mt76_connac_sched_scan_req *)skb_put_zero(skb, sizeof(*req));
req->version = 1;
req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;
@ -2321,7 +2328,7 @@ int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
return -ENOMEM;
skb_put_data(skb, &hdr, sizeof(hdr));
gtk_tlv = (struct mt76_connac_gtk_rekey_tlv *)skb_put(skb,
gtk_tlv = (struct mt76_connac_gtk_rekey_tlv *)skb_put_zero(skb,
sizeof(*gtk_tlv));
gtk_tlv->tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY);
gtk_tlv->len = cpu_to_le16(sizeof(*gtk_tlv));
@ -2446,7 +2453,7 @@ mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,
return -ENOMEM;
skb_put_data(skb, &hdr, sizeof(hdr));
ptlv = (struct mt76_connac_wow_pattern_tlv *)skb_put(skb, sizeof(*ptlv));
ptlv = (struct mt76_connac_wow_pattern_tlv *)skb_put_zero(skb, sizeof(*ptlv));
ptlv->tag = cpu_to_le16(UNI_SUSPEND_WOW_PATTERN);
ptlv->len = cpu_to_le16(sizeof(*ptlv));
ptlv->data_len = pattern->pattern_len;
@ -2527,6 +2534,7 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend)
__le16 tag;
__le16 len;
u8 suspend;
u8 pad[7];
} __packed hif_suspend;
} req = {
.hif_suspend = {

View File

@ -610,6 +610,12 @@ struct sta_rec_ra_fixed {
u8 mmps_mode;
} __packed;
struct sta_rec_tx_proc {
__le16 tag;
__le16 len;
__le32 flag;
} __packed;
/* wtbl_rec */
struct wtbl_req_hdr {
@ -777,6 +783,7 @@ struct wtbl_raw {
sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct sta_rec_pn_info) + \
sizeof(struct sta_rec_tx_proc) + \
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
@ -1004,6 +1011,7 @@ enum {
MCU_EVENT_CH_PRIVILEGE = 0x18,
MCU_EVENT_SCHED_SCAN_DONE = 0x23,
MCU_EVENT_DBG_MSG = 0x27,
MCU_EVENT_RSSI_NOTIFY = 0x96,
MCU_EVENT_TXPWR = 0xd0,
MCU_EVENT_EXT = 0xed,
MCU_EVENT_RESTART_DL = 0xef,
@ -1182,6 +1190,7 @@ enum {
MCU_EXT_CMD_EFUSE_ACCESS = 0x01,
MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
MCU_EXT_CMD_RF_TEST = 0x04,
MCU_EXT_CMD_ID_RADIO_ON_OFF_CTRL = 0x05,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
@ -1213,6 +1222,7 @@ enum {
MCU_EXT_CMD_TXDPD_CAL = 0x60,
MCU_EXT_CMD_CAL_CACHE = 0x67,
MCU_EXT_CMD_RED_ENABLE = 0x68,
MCU_EXT_CMD_CP_SUPPORT = 0x75,
MCU_EXT_CMD_SET_RADAR_TH = 0x7c,
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
@ -1303,6 +1313,7 @@ enum {
MCU_CE_CMD_SCHED_SCAN_ENABLE = 0x61,
MCU_CE_CMD_SCHED_SCAN_REQ = 0x62,
MCU_CE_CMD_GET_NIC_CAPAB = 0x8a,
MCU_CE_CMD_RSSI_MONITOR = 0xa1,
MCU_CE_CMD_SET_MU_EDCA_PARMS = 0xb0,
MCU_CE_CMD_REG_WRITE = 0xc0,
MCU_CE_CMD_REG_READ = 0xc0,
@ -1448,6 +1459,10 @@ struct mt76_connac_beacon_loss_event {
u8 pad[2];
} __packed;
struct mt76_connac_rssi_notify_event {
__le32 rssi[4];
} __packed;
struct mt76_connac_mcu_bss_event {
u8 bss_idx;
u8 is_absent;

View File

@ -9,28 +9,34 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
u8 *eeprom = mdev->eeprom.data;
u32 val = eeprom[MT_EE_DO_PRE_CAL];
u32 offs;
u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
u32 size, val = eeprom[offs];
int ret;
if (!dev->flash_mode)
if (!dev->flash_mode || !val)
return 0;
if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
return 0;
size = mt7915_get_cal_group_size(dev) + mt7915_get_cal_dpd_size(dev);
val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL);
dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
if (!dev->cal)
return -ENOMEM;
offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, val);
ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);
if (!ret)
return ret;
return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", val);
ret = mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
if (!ret)
return ret;
dev_warn(mdev->dev, "missing precal data, size=%d\n", size);
devm_kfree(mdev->dev, dev->cal);
dev->cal = NULL;
return ret;
}
static int mt7915_check_eeprom(struct mt7915_dev *dev)
@ -256,10 +262,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
return ret;
}
ret = mt7915_eeprom_load_precal(dev);
if (ret)
return ret;
mt7915_eeprom_load_precal(dev);
mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);

View File

@ -19,6 +19,7 @@ enum mt7915_eeprom_field {
MT_EE_DDIE_FT_VERSION = 0x050,
MT_EE_DO_PRE_CAL = 0x062,
MT_EE_WIFI_CONF = 0x190,
MT_EE_DO_PRE_CAL_V2 = 0x19a,
MT_EE_RATE_DELTA_2G = 0x252,
MT_EE_RATE_DELTA_5G = 0x29d,
MT_EE_TX0_POWER_2G = 0x2fc,
@ -39,10 +40,19 @@ enum mt7915_eeprom_field {
};
#define MT_EE_WIFI_CAL_GROUP BIT(0)
#define MT_EE_WIFI_CAL_DPD GENMASK(2, 1)
#define MT_EE_WIFI_CAL_DPD_2G BIT(2)
#define MT_EE_WIFI_CAL_DPD_5G BIT(1)
#define MT_EE_WIFI_CAL_DPD_6G BIT(3)
#define MT_EE_WIFI_CAL_DPD GENMASK(3, 1)
#define MT_EE_CAL_UNIT 1024
#define MT_EE_CAL_GROUP_SIZE (49 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_DPD_SIZE (54 * MT_EE_CAL_UNIT)
#define MT_EE_CAL_GROUP_SIZE_7915 (49 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_GROUP_SIZE_7916 (54 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_GROUP_SIZE_7975 (54 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_GROUP_SIZE_7976 (94 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_GROUP_SIZE_7916_6G (94 * MT_EE_CAL_UNIT + 16)
#define MT_EE_CAL_DPD_SIZE_V1 (54 * MT_EE_CAL_UNIT)
#define MT_EE_CAL_DPD_SIZE_V2 (300 * MT_EE_CAL_UNIT)
#define MT_EE_CAL_DPD_SIZE_V2_7981 (102 * MT_EE_CAL_UNIT) /* no 6g dpd data */
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
@ -156,6 +166,37 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
return val & MT_EE_WIFI_CONF7_TSSI0_5G;
}
static inline u32
mt7915_get_cal_group_size(struct mt7915_dev *dev)
{
u8 *eep = dev->mt76.eeprom.data;
u32 val;
if (is_mt7915(&dev->mt76)) {
return MT_EE_CAL_GROUP_SIZE_7915;
} else if (is_mt7916(&dev->mt76)) {
val = eep[MT_EE_WIFI_CONF + 1];
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
return (val == MT_EE_V2_BAND_SEL_6GHZ) ? MT_EE_CAL_GROUP_SIZE_7916_6G :
MT_EE_CAL_GROUP_SIZE_7916;
} else if (mt7915_check_adie(dev, false)) {
return MT_EE_CAL_GROUP_SIZE_7976;
} else {
return MT_EE_CAL_GROUP_SIZE_7975;
}
}
static inline u32
mt7915_get_cal_dpd_size(struct mt7915_dev *dev)
{
if (is_mt7915(&dev->mt76))
return MT_EE_CAL_DPD_SIZE_V1;
else if (is_mt7981(&dev->mt76))
return MT_EE_CAL_DPD_SIZE_V2_7981;
else
return MT_EE_CAL_DPD_SIZE_V2;
}
extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
#endif

View File

@ -823,7 +823,7 @@ mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (ret < 0)
return ret;
if (dev->flash_mode) {
if (dev->cal) {
ret = mt7915_mcu_apply_group_cal(dev);
if (ret)
return ret;
@ -934,11 +934,10 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
/* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;
if (vif != NL80211_IFTYPE_AP)
if (vif != NL80211_IFTYPE_AP && vif != NL80211_IFTYPE_STATION)
return;
elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
sts - 1);
@ -947,6 +946,11 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
sts_160 - 1);
elem->phy_cap_info[5] |= c;
if (vif != NL80211_IFTYPE_AP)
return;
elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB |
IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB;
elem->phy_cap_info[6] |= c;

View File

@ -140,8 +140,15 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
msta->airtime_ac[i] = mt76_rr(dev, addr);
msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
tx_time[i] = msta->airtime_ac[i] - tx_last;
rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
if (msta->airtime_ac[i] <= tx_last)
tx_time[i] = 0;
else
tx_time[i] = msta->airtime_ac[i] - tx_last;
if (msta->airtime_ac[i + 4] <= rx_last)
rx_time[i] = 0;
else
rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
if ((tx_last | rx_last) & BIT(30))
clear = true;
@ -1338,10 +1345,8 @@ mt7915_mac_restart(struct mt7915_dev *dev)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
if (ext_phy) {
if (ext_phy)
set_bit(MT76_RESET, &ext_phy->state);
set_bit(MT76_MCU_RESET, &ext_phy->state);
}
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);

View File

@ -329,7 +329,7 @@ int mt7915_set_channel(struct mt7915_phy *phy)
mt76_set_channel(phy->mt76);
if (dev->flash_mode) {
if (dev->cal) {
ret = mt7915_mcu_apply_tx_dpd(phy);
if (ret)
goto out;
@ -744,6 +744,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
bool ext_phy = mvif->phy != &dev->phy;
int ret, idx;
u32 addr;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
if (idx < 0)
@ -767,6 +768,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (ret)
return ret;
addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 30);
mt76_rmw_field(dev, addr, GENMASK(7, 0), 0xa0);
return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);
}
@ -1657,6 +1661,10 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
#endif
const struct ieee80211_ops mt7915_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
.change_chanctx = ieee80211_emulate_change_chanctx,
.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
.tx = mt7915_tx,
.start = mt7915_start,
.stop = mt7915_stop,

View File

@ -424,7 +424,7 @@ mt7915_mcu_add_nested_subtlv(struct sk_buff *skb, int sub_tag, int sub_len,
.len = cpu_to_le16(sub_len),
};
ptlv = skb_put(skb, sub_len);
ptlv = skb_put_zero(skb, sub_len);
memcpy(ptlv, &tlv, sizeof(tlv));
le16_add_cpu(sub_ntlv, 1);
@ -1193,7 +1193,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
const u8 matrix[4][4] = {
static const u8 matrix[4][4] = {
{0, 0, 0, 0},
{1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */
{2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
@ -1919,8 +1919,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
bcn = (struct bss_info_bcn *)tlv;
bcn->enable = true;
if (changed & BSS_CHANGED_FILS_DISCOVERY &&
vif->bss_conf.fils_discovery.max_interval) {
if (changed & BSS_CHANGED_FILS_DISCOVERY) {
interval = vif->bss_conf.fils_discovery.max_interval;
skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
@ -1957,7 +1956,7 @@ mt7915_mcu_add_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vif,
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
discov->tx_interval = interval;
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
discov->enable = true;
discov->enable = !!interval;
buf = (u8 *)sub_tlv + sizeof(*discov);
@ -2904,9 +2903,10 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
{
u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
u32 total = MT_EE_CAL_GROUP_SIZE;
u32 total = mt7915_get_cal_group_size(dev);
u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_GROUP))
if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
return 0;
/*
@ -2942,9 +2942,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
return -1;
}
static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
static int mt7915_dpd_freq_idx(struct mt7915_dev *dev, u16 freq, u8 bw)
{
static const u16 freq_list[] = {
static const u16 freq_list_v1[] = {
5180, 5200, 5220, 5240,
5260, 5280, 5300, 5320,
5500, 5520, 5540, 5560,
@ -2952,65 +2952,135 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
5660, 5680, 5700, 5745,
5765, 5785, 5805, 5825
};
int offset_2g = ARRAY_SIZE(freq_list);
static const u16 freq_list_v2[] = {
/* 6G BW20*/
5955, 5975, 5995, 6015,
6035, 6055, 6075, 6095,
6115, 6135, 6155, 6175,
6195, 6215, 6235, 6255,
6275, 6295, 6315, 6335,
6355, 6375, 6395, 6415,
6435, 6455, 6475, 6495,
6515, 6535, 6555, 6575,
6595, 6615, 6635, 6655,
6675, 6695, 6715, 6735,
6755, 6775, 6795, 6815,
6835, 6855, 6875, 6895,
6915, 6935, 6955, 6975,
6995, 7015, 7035, 7055,
7075, 7095, 7115,
/* 6G BW160 */
6025, 6185, 6345, 6505,
6665, 6825, 6985,
/* 5G BW20 */
5180, 5200, 5220, 5240,
5260, 5280, 5300, 5320,
5500, 5520, 5540, 5560,
5580, 5600, 5620, 5640,
5660, 5680, 5700, 5720,
5745, 5765, 5785, 5805,
5825, 5845, 5865, 5885,
/* 5G BW160 */
5250, 5570, 5815
};
static const u16 freq_list_v2_7981[] = {
/* 5G BW20 */
5180, 5200, 5220, 5240,
5260, 5280, 5300, 5320,
5500, 5520, 5540, 5560,
5580, 5600, 5620, 5640,
5660, 5680, 5700, 5720,
5745, 5765, 5785, 5805,
5825, 5845, 5865, 5885,
/* 5G BW160 */
5250, 5570, 5815
};
const u16 *freq_list = freq_list_v1;
int n_freqs = ARRAY_SIZE(freq_list_v1);
int idx;
if (!is_mt7915(&dev->mt76)) {
if (is_mt7981(&dev->mt76)) {
freq_list = freq_list_v2_7981;
n_freqs = ARRAY_SIZE(freq_list_v2_7981);
} else {
freq_list = freq_list_v2;
n_freqs = ARRAY_SIZE(freq_list_v2);
}
}
if (freq < 4000) {
if (freq < 2432)
return offset_2g;
return n_freqs;
if (freq < 2457)
return offset_2g + 1;
return n_freqs + 1;
return offset_2g + 2;
return n_freqs + 2;
}
if (bw == NL80211_CHAN_WIDTH_80P80 || bw == NL80211_CHAN_WIDTH_160)
if (bw == NL80211_CHAN_WIDTH_80P80)
return -1;
if (bw != NL80211_CHAN_WIDTH_20) {
idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
freq + 10);
idx = mt7915_find_freq_idx(freq_list, n_freqs, freq + 10);
if (idx >= 0)
return idx;
idx = mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list),
freq - 10);
idx = mt7915_find_freq_idx(freq_list, n_freqs, freq - 10);
if (idx >= 0)
return idx;
}
return mt7915_find_freq_idx(freq_list, ARRAY_SIZE(freq_list), freq);
return mt7915_find_freq_idx(freq_list, n_freqs, freq);
}
int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
u16 total = 2, center_freq = chandef->center_freq1;
enum nl80211_band band = chandef->chan->band;
u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
u16 center_freq = chandef->center_freq1;
u8 *cal = dev->cal, *eep = dev->mt76.eeprom.data;
u8 dpd_mask, cal_num = is_mt7915(&dev->mt76) ? 2 : 3;
int idx;
if (!(eep[MT_EE_DO_PRE_CAL] & MT_EE_WIFI_CAL_DPD))
switch (band) {
case NL80211_BAND_2GHZ:
dpd_mask = MT_EE_WIFI_CAL_DPD_2G;
break;
case NL80211_BAND_5GHZ:
dpd_mask = MT_EE_WIFI_CAL_DPD_5G;
break;
case NL80211_BAND_6GHZ:
dpd_mask = MT_EE_WIFI_CAL_DPD_6G;
break;
default:
dpd_mask = 0;
break;
}
if (!(eep[offs] & dpd_mask))
return 0;
idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
idx = mt7915_dpd_freq_idx(dev, center_freq, chandef->width);
if (idx < 0)
return -EINVAL;
/* Items: Tx DPD, Tx Flatness */
idx = idx * 2;
cal += MT_EE_CAL_GROUP_SIZE;
idx = idx * cal_num;
cal += mt7915_get_cal_group_size(dev) + (idx * MT_EE_CAL_UNIT);
while (total--) {
while (cal_num--) {
int ret;
cal += (idx * MT_EE_CAL_UNIT);
ret = mt7915_mcu_set_pre_cal(dev, idx, cal, MT_EE_CAL_UNIT,
MCU_EXT_CMD(DPD_PRE_CAL_INFO));
if (ret)
return ret;
idx++;
cal += MT_EE_CAL_UNIT;
}
return 0;
@ -3801,30 +3871,38 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
{
struct {
__le32 cmd;
__le32 num;
__le32 __rsv;
__le16 wlan_idx;
} req = {
__le32 arg0;
__le32 arg1;
__le16 arg2;
} __packed req = {
.cmd = cpu_to_le32(0x15),
.num = cpu_to_le32(1),
.wlan_idx = cpu_to_le16(wlan_idx),
};
struct mt7915_mcu_wa_tx_stat {
__le16 wlan_idx;
u8 __rsv[2];
__le16 wcid;
u8 __rsv2[2];
/* tx_bytes is deprecated since WA byte counter uses u32,
* which easily leads to overflow.
*/
__le32 tx_bytes;
__le32 tx_packets;
} *res;
} __packed *res;
struct mt76_wcid *wcid;
struct sk_buff *skb;
int ret;
int ret, len;
u16 ret_wcid;
if (is_mt7915(&dev->mt76)) {
req.arg0 = cpu_to_le32(wlan_idx);
len = sizeof(req) - sizeof(req.arg2);
} else {
req.arg0 = cpu_to_le32(1);
req.arg2 = cpu_to_le16(wlan_idx);
len = sizeof(req);
}
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WA_PARAM_CMD(QUERY),
&req, sizeof(req), true, &skb);
&req, len, true, &skb);
if (ret)
return ret;
@ -3833,7 +3911,11 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
res = (struct mt7915_mcu_wa_tx_stat *)skb->data;
if (le16_to_cpu(res->wlan_idx) != wlan_idx) {
ret_wcid = le16_to_cpu(res->wcid);
if (is_mt7915(&dev->mt76))
ret_wcid &= 0xff;
if (ret_wcid != wlan_idx) {
ret = -EINVAL;
goto out;
}

View File

@ -302,6 +302,10 @@ struct mt7915_dev {
struct rchan *relay_fwlog;
void *cal;
u32 cur_prek_offset;
u8 dpd_chan_num_2g;
u8 dpd_chan_num_5g;
u8 dpd_chan_num_6g;
struct {
u8 debug_wm;

View File

@ -7,7 +7,6 @@
#include <linux/pinctrl/consumer.h>
#include <linux/of.h>
#include <linux/of_reserved_mem.h>
#include <linux/of_gpio.h>
#include <linux/iopoll.h>
#include <linux/reset.h>
#include <linux/of_net.h>

View File

@ -663,6 +663,7 @@ void mt7921_mac_reset_work(struct work_struct *work)
int i, ret;
dev_dbg(dev->mt76.dev, "chip reset\n");
set_bit(MT76_RESET, &dev->mphy.state);
dev->hw_full_reset = true;
ieee80211_stop_queues(hw);
@ -691,6 +692,7 @@ void mt7921_mac_reset_work(struct work_struct *work)
}
dev->hw_full_reset = false;
clear_bit(MT76_RESET, &dev->mphy.state);
pm->suspended = false;
ieee80211_wake_queues(hw);
ieee80211_iterate_active_interfaces(hw,

View File

@ -242,6 +242,15 @@ int __mt7921_start(struct mt792x_phy *phy)
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT792x_WATCHDOG_TIME);
if (mt76_is_mmio(mphy->dev)) {
err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_LED_CTRL_ENABLE);
if (err)
return err;
err = mt7921_mcu_radio_led_ctrl(phy->dev, EXT_CMD_RADIO_ON_LED);
if (err)
return err;
}
return 0;
}
@ -259,6 +268,22 @@ static int mt7921_start(struct ieee80211_hw *hw)
return err;
}
static void mt7921_stop(struct ieee80211_hw *hw)
{
struct mt792x_dev *dev = mt792x_hw_dev(hw);
int err = 0;
if (mt76_is_mmio(&dev->mt76)) {
mt792x_mutex_acquire(dev);
err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED);
mt792x_mutex_release(dev);
if (err)
return;
}
mt792x_stop(hw);
}
static int
mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
@ -310,6 +335,8 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
}
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
out:
mt792x_mutex_release(dev);
@ -679,6 +706,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_PS)
mt7921_mcu_uni_bss_ps(dev, vif);
if (changed & BSS_CHANGED_CQM)
mt7921_mcu_set_rssimonitor(dev, vif);
if (changed & BSS_CHANGED_ASSOC) {
mt7921_mcu_sta_update(dev, NULL, vif, true,
MT76_STA_INFO_STATE_ASSOC);
@ -1372,7 +1402,7 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
const struct ieee80211_ops mt7921_ops = {
.tx = mt792x_tx,
.start = mt7921_start,
.stop = mt792x_stop,
.stop = mt7921_stop,
.add_interface = mt7921_add_interface,
.remove_interface = mt792x_remove_interface,
.config = mt7921_config,

View File

@ -253,6 +253,42 @@ mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)
mt7921_mac_add_txs(dev, event->txs);
}
static void
mt7921_mcu_rssi_monitor_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt76_connac_rssi_notify_event *event = priv;
enum nl80211_cqm_rssi_threshold_event nl_event;
s32 rssi = le32_to_cpu(event->rssi[mvif->mt76.idx]);
if (!rssi)
return;
if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
return;
if (rssi > vif->bss_conf.cqm_rssi_thold)
nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
else
nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL);
}
static void
mt7921_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac_rssi_notify_event *event;
skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
event = (struct mt76_connac_rssi_notify_event *)skb->data;
ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7921_mcu_rssi_monitor_iter, event);
}
static void
mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
@ -281,6 +317,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)
case MCU_EVENT_TX_DONE:
mt7921_mcu_tx_done_event(dev, skb);
break;
case MCU_EVENT_RSSI_NOTIFY:
mt7921_mcu_rssi_monitor_event(dev, skb);
break;
default:
break;
}
@ -327,6 +366,7 @@ void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
if (rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT ||
rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||
rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
rxd->eid == MCU_EVENT_RSSI_NOTIFY ||
rxd->eid == MCU_EVENT_SCAN_DONE ||
rxd->eid == MCU_EVENT_TX_DONE ||
rxd->eid == MCU_EVENT_DBG_MSG ||
@ -606,6 +646,20 @@ int mt7921_run_firmware(struct mt792x_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7921_run_firmware);
int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value)
{
struct {
u8 ctrlid;
u8 rsv[3];
} __packed req = {
.ctrlid = value,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ID_RADIO_ON_OFF_CTRL),
&req, sizeof(req), false);
}
EXPORT_SYMBOL_GPL(mt7921_mcu_radio_led_ctrl);
int mt7921_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
@ -1100,12 +1154,12 @@ int mt7921_mcu_config_sniffer(struct mt792x_vif *vif,
{
struct cfg80211_chan_def *chandef = &ctx->def;
int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
const u8 ch_band[] = {
static const u8 ch_band[] = {
[NL80211_BAND_2GHZ] = 1,
[NL80211_BAND_5GHZ] = 2,
[NL80211_BAND_6GHZ] = 3,
};
const u8 ch_width[] = {
static const u8 ch_width[] = {
[NL80211_CHAN_WIDTH_20_NOHT] = 0,
[NL80211_CHAN_WIDTH_20] = 0,
[NL80211_CHAN_WIDTH_40] = 0,
@ -1391,3 +1445,24 @@ int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER),
&data, sizeof(data), false);
}
int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct {
u8 enable;
s8 cqm_rssi_high;
s8 cqm_rssi_low;
u8 bss_idx;
u16 duration;
u8 rsv2[2];
} __packed data = {
.enable = vif->cfg.assoc,
.cqm_rssi_high = vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst,
.cqm_rssi_low = vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst,
.bss_idx = mvif->mt76.idx,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(RSSI_MONITOR),
&data, sizeof(data), false);
}

View File

@ -27,6 +27,10 @@
#define MCU_UNI_EVENT_ROC 0x27
#define MCU_UNI_EVENT_CLC 0x80
#define EXT_CMD_RADIO_LED_CTRL_ENABLE 0x1
#define EXT_CMD_RADIO_ON_LED 0x2
#define EXT_CMD_RADIO_OFF_LED 0x3
enum {
UNI_ROC_ACQUIRE,
UNI_ROC_ABORT,
@ -196,6 +200,7 @@ int mt7921_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl);
void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb);
int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
u8 bit_op, u32 bit_map);
int mt7921_mcu_radio_led_ctrl(struct mt792x_dev *dev, u8 value);
static inline u32
mt7921_reg_map_l1(struct mt792x_dev *dev, u32 addr)
@ -323,4 +328,5 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
u8 token_id);
void mt7921_roc_abort_sync(struct mt792x_dev *dev);
int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif);
#endif

View File

@ -24,6 +24,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, 0x0616),
.driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7920),
.driver_data = (kernel_ulong_t)MT7920_FIRMWARE_WM },
{ },
};
@ -269,9 +271,9 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
struct mt76_bus_ops *bus_ops;
struct mt792x_dev *dev;
struct mt76_dev *mdev;
u16 cmd, chipid;
u8 features;
int ret;
u16 cmd;
ret = pcim_enable_device(pdev);
if (ret)
@ -345,7 +347,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_free_dev;
mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
chipid = mt7921_l1_rr(dev, MT_HW_CHIPID);
if (chipid == 0x7961 && (mt7921_l1_rr(dev, MT_HW_BOUND) & BIT(7)))
chipid = 0x7920;
mdev->rev = (chipid << 16) |
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
@ -422,6 +427,10 @@ static int mt7921_pci_suspend(struct device *device)
wait_event_timeout(dev->wait,
!dev->regd_in_progress, 5 * HZ);
err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_OFF_LED);
if (err < 0)
goto restore_suspend;
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
if (err)
goto restore_suspend;
@ -520,9 +529,11 @@ static int mt7921_pci_resume(struct device *device)
mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
if (err < 0)
goto failed;
mt7921_regd_update(dev);
err = mt7921_mcu_radio_led_ctrl(dev, EXT_CMD_RADIO_ON_LED);
failed:
pm->suspended = false;
@ -551,6 +562,8 @@ static struct pci_driver mt7921_pci_driver = {
module_pci_driver(mt7921_pci_driver);
MODULE_DEVICE_TABLE(pci, mt7921_pci_device_table);
MODULE_FIRMWARE(MT7920_FIRMWARE_WM);
MODULE_FIRMWARE(MT7920_ROM_PATCH);
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
MODULE_FIRMWARE(MT7921_ROM_PATCH);
MODULE_FIRMWARE(MT7922_FIRMWARE_WM);

View File

@ -64,7 +64,6 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)
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);
@ -115,7 +114,6 @@ int mt7921e_mac_reset(struct mt792x_dev *dev)
err = __mt7921_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
local_bh_disable();
napi_enable(&dev->mt76.tx_napi);

View File

@ -98,7 +98,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
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);
@ -135,7 +134,6 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)
err = __mt7921_start(&dev->phy);
out:
clear_bit(MT76_RESET, &dev->mphy.state);
mt76_worker_enable(&dev->mt76.tx_worker);

View File

@ -590,14 +590,25 @@ mt7925_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
qos_ctl = *ieee80211_get_qos_ctl(hdr);
}
skb_set_mac_header(skb, (unsigned char *)hdr - skb->data);
} else {
status->flag |= RX_FLAG_8023;
}
mt792x_mac_assoc_rssi(dev, skb);
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
if (rxv && !(status->flag & RX_FLAG_8023)) {
switch (status->encoding) {
case RX_ENC_EHT:
mt76_connac3_mac_decode_eht_radiotap(skb, rxv, mode);
break;
case RX_ENC_HE:
mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
break;
default:
break;
}
}
if (!status->wcid || !ieee80211_is_data_qos(fc))
return 0;

View File

@ -1768,12 +1768,12 @@ int mt7925_mcu_config_sniffer(struct mt792x_vif *vif,
struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &mphy->chandef;
int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
const u8 ch_band[] = {
static const u8 ch_band[] = {
[NL80211_BAND_2GHZ] = 1,
[NL80211_BAND_5GHZ] = 2,
[NL80211_BAND_6GHZ] = 3,
};
const u8 ch_width[] = {
static const u8 ch_width[] = {
[NL80211_CHAN_WIDTH_20_NOHT] = 0,
[NL80211_CHAN_WIDTH_20] = 0,
[NL80211_CHAN_WIDTH_40] = 0,

View File

@ -535,7 +535,7 @@ struct mt7925_wow_pattern_tlv {
u8 offset;
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
u8 rsv[4];
u8 rsv[7];
} __packed;
static inline enum connac3_mcu_cipher_type

View File

@ -26,6 +26,7 @@
#define MT792x_FW_CAP_CNM BIT(7)
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 11
@ -36,10 +37,12 @@
#define MT792x_MCU_INIT_RETRY_COUNT 10
#define MT792x_WFSYS_INIT_RETRY_COUNT 2
#define MT7920_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1a.bin"
#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 MT7920_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1a_2_hdr.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"
@ -326,6 +329,8 @@ int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev);
static inline char *mt792x_ram_name(struct mt792x_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7920:
return MT7920_FIRMWARE_WM;
case 0x7922:
return MT7922_FIRMWARE_WM;
case 0x7925:
@ -338,6 +343,8 @@ static inline char *mt792x_ram_name(struct mt792x_dev *dev)
static inline char *mt792x_patch_name(struct mt792x_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7920:
return MT7920_ROM_PATCH;
case 0x7922:
return MT7922_ROM_PATCH;
case 0x7925:

View File

@ -225,6 +225,11 @@ mt7996_radar_trigger(void *data, u64 val)
if (val > MT_RX_SEL2)
return -EINVAL;
if (val == MT_RX_SEL2 && !dev->rdd2_phy) {
dev_err(dev->mt76.dev, "Background radar is not enabled\n");
return -EINVAL;
}
return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE,
val, 0, 0);
}

View File

@ -1655,14 +1655,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
if (phy2) {
if (phy2)
set_bit(MT76_RESET, &phy2->mt76->state);
set_bit(MT76_MCU_RESET, &phy2->mt76->state);
}
if (phy3) {
if (phy3)
set_bit(MT76_RESET, &phy3->mt76->state);
set_bit(MT76_MCU_RESET, &phy3->mt76->state);
}
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);

View File

@ -35,6 +35,14 @@ int mt7996_run(struct ieee80211_hw *hw)
ret = mt7996_mcu_set_hdr_trans(dev, true);
if (ret)
goto out;
if (is_mt7992(&dev->mt76)) {
u8 queue = mt76_connac_lmac_mapping(IEEE80211_AC_VI);
ret = mt7996_mcu_cp_support(dev, queue);
if (ret)
goto out;
}
}
mt7996_mac_enable_nf(dev, phy->mt76->band_idx);
@ -238,7 +246,11 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
mt7996_init_bitrate_mask(vif);
mt7996_mcu_add_bss_info(phy, vif, true);
mt7996_mcu_add_sta(dev, vif, NULL, true);
/* defer the first STA_REC of BMC entry to BSS_CHANGED_BSSID for STA
* interface, since firmware only records BSSID when the entry is new
*/
if (vif->type != NL80211_IFTYPE_STATION)
mt7996_mcu_add_sta(dev, vif, NULL, true, true);
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
out:
@ -256,7 +268,7 @@ 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_sta(dev, vif, NULL, false);
mt7996_mcu_add_sta(dev, vif, NULL, false, false);
mt7996_mcu_add_bss_info(phy, vif, false);
if (vif == phy->monitor_vif)
@ -340,10 +352,6 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* fall back to sw encryption for unsupported ciphers */
switch (key->cipher) {
case WLAN_CIPHER_SUITE_AES_CMAC:
wcid_keyidx = &wcid->hw_key_idx2;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
break;
case WLAN_CIPHER_SUITE_TKIP:
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
@ -351,6 +359,11 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP_256:
case WLAN_CIPHER_SUITE_SMS4:
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
wcid_keyidx = &wcid->hw_key_idx2;
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
fallthrough;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
if (key->keyidx == 6 || key->keyidx == 7)
@ -438,7 +451,7 @@ 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[] = {
static const u8 mq_to_aci[] = {
[IEEE80211_AC_VO] = 3,
[IEEE80211_AC_VI] = 2,
[IEEE80211_AC_BE] = 0,
@ -599,7 +612,8 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
(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);
mt7996_mcu_add_sta(dev, vif, NULL, true,
!!(changed & BSS_CHANGED_BSSID));
}
if (changed & BSS_CHANGED_ERP_CTS_PROT)
@ -688,7 +702,7 @@ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
mt7996_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
ret = mt7996_mcu_add_sta(dev, vif, sta, true);
ret = mt7996_mcu_add_sta(dev, vif, sta, true, true);
if (ret)
return ret;
@ -702,7 +716,7 @@ void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
int i;
mt7996_mcu_add_sta(dev, vif, sta, false);
mt7996_mcu_add_sta(dev, vif, sta, false, false);
mt7996_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);

View File

@ -355,7 +355,10 @@ mt7996_mcu_rx_radar_detected(struct mt7996_dev *dev, struct sk_buff *skb)
if (r->band_idx >= ARRAY_SIZE(dev->mt76.phys))
return;
if (dev->rdd2_phy && r->band_idx == MT_RX_SEL2)
if (r->band_idx == MT_RX_SEL2 && !dev->rdd2_phy)
return;
if (r->band_idx == MT_RX_SEL2)
mphy = dev->rdd2_phy->mt76;
else
mphy = dev->mt76.phys[r->band_idx];
@ -819,11 +822,14 @@ mt7996_mcu_bss_mbssid_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct bss_info_uni_mbssid *mbssid;
struct tlv *tlv;
if (!vif->bss_conf.bssid_indicator)
return;
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) {
if (enable) {
mbssid->max_indicator = vif->bss_conf.bssid_indicator;
mbssid->mbss_idx = vif->bss_conf.bssid_index;
mbssid->tx_bss_omac_idx = 0;
@ -1650,7 +1656,7 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
const u8 matrix[4][4] = {
static const u8 matrix[4][4] = {
{0, 0, 0, 0},
{1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */
{2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */
@ -1748,6 +1754,18 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
}
static void
mt7996_mcu_sta_tx_proc_tlv(struct sk_buff *skb)
{
struct sta_rec_tx_proc *tx_proc;
struct tlv *tlv;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_TX_PROC, sizeof(*tx_proc));
tx_proc = (struct sta_rec_tx_proc *)tlv;
tx_proc->flag = cpu_to_le32(0);
}
static void
mt7996_mcu_sta_hdrt_tlv(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -1778,10 +1796,10 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
else
hdr_trans->from_ds = true;
wcid = (struct mt76_wcid *)sta->drv_priv;
if (!wcid)
if (!sta)
return;
wcid = (struct mt76_wcid *)sta->drv_priv;
hdr_trans->dis_rx_hdr_tran = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {
hdr_trans->to_ds = true;
@ -1968,6 +1986,7 @@ static void
mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
#define INIT_RCPI 180
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt76_phy *mphy = mvif->phy->mt76;
struct cfg80211_chan_def *chandef = &mphy->chandef;
@ -2065,6 +2084,8 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
}
ra->sta_cap = cpu_to_le32(cap);
memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi));
}
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
@ -2133,7 +2154,7 @@ mt7996_mcu_add_group(struct mt7996_dev *dev, struct ieee80211_vif *vif,
}
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable)
struct ieee80211_sta *sta, bool enable, bool newly)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta;
@ -2149,11 +2170,16 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
return PTR_ERR(skb);
/* starec basic */
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable,
!rcu_access_pointer(dev->mt76.wcid[msta->wcid.idx]));
mt76_connac_mcu_sta_basic_tlv(&dev->mt76, skb, vif, sta, enable, newly);
if (!enable)
goto out;
/* starec hdr trans */
mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta);
/* starec tx proc */
mt7996_mcu_sta_tx_proc_tlv(skb);
/* tag order is in accordance with firmware dependency. */
if (sta) {
/* starec hdrt mode */
@ -2178,8 +2204,6 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mt7996_mcu_sta_muru_tlv(dev, skb, vif, sta);
/* starec bfee */
mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
/* starec hdr trans */
mt7996_mcu_sta_hdr_trans_tlv(dev, skb, vif, sta);
}
ret = mt7996_mcu_add_group(dev, vif, sta);
@ -3729,6 +3753,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
} __packed * res;
struct sk_buff *skb;
int ret;
u32 temp;
ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
&req, sizeof(req), true, &skb);
@ -3736,8 +3761,10 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
return ret;
res = (void *)skb->data;
temp = le32_to_cpu(res->temperature);
dev_kfree_skb(skb);
return le32_to_cpu(res->temperature);
return temp;
}
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
@ -4464,7 +4491,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
u8 band_idx;
} __packed req = {
.tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
.len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4),
.len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4),
.power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
.power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
.band_idx = phy->mt76->band_idx,
@ -4479,7 +4506,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
mphy->txpower_cur = tx_power;
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
sizeof(req) + MT7996_SKU_RATE_NUM);
sizeof(req) + MT7996_SKU_PATH_NUM);
if (!skb)
return -ENOMEM;
@ -4503,6 +4530,22 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
/* eht */
skb_put_data(skb, &la.eht[0], sizeof(la.eht));
/* padding */
skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WM_UNI_CMD(TXPOWER), true);
}
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode)
{
__le32 cp_mode;
if (mode < mt76_connac_lmac_mapping(IEEE80211_AC_BE) ||
mode > mt76_connac_lmac_mapping(IEEE80211_AC_VO))
return -EINVAL;
cp_mode = cpu_to_le32(mode);
return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(CP_SUPPORT),
&cp_mode, sizeof(cp_mode), true);
}

View File

@ -519,7 +519,7 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
u32 i, intr, mask, intr1;
u32 i, intr, mask, intr1 = 0;
if (dev->hif2 && mtk_wed_device_active(wed_hif2)) {
mtk_wed_device_irq_set_mask(wed_hif2, 0);

View File

@ -50,6 +50,7 @@
#define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7996_SKU_RATE_NUM 417
#define MT7996_SKU_PATH_NUM 494
#define MT7996_MAX_TWT_AGRT 16
#define MT7996_MAX_STA_TWT_AGRT 8
@ -450,7 +451,7 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
int mt7996_mcu_add_bss_info(struct mt7996_phy *phy,
struct ieee80211_vif *vif, int enable);
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable);
struct ieee80211_sta *sta, bool enable, bool newly);
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
struct ieee80211_ampdu_params *params,
bool add);
@ -612,6 +613,7 @@ int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
#ifdef CONFIG_MAC80211_DEBUGFS
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);

View File

@ -499,7 +499,8 @@ static void mt76s_tx_status_data(struct mt76_worker *worker)
dev = container_of(sdio, struct mt76_dev, sdio);
while (true) {
if (test_bit(MT76_REMOVED, &dev->phy.state))
if (test_bit(MT76_RESET, &dev->phy.state) ||
test_bit(MT76_REMOVED, &dev->phy.state))
break;
if (!dev->drv->tx_status_data(dev, &update))
@ -514,13 +515,14 @@ static void mt76s_tx_status_data(struct mt76_worker *worker)
}
static int
mt76s_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
mt76s_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
{
struct mt76_tx_info tx_info = {
.skb = skb,
};
struct mt76_dev *dev = phy->dev;
int err, len = skb->len;
u16 idx = q->head;
@ -548,10 +550,7 @@ static int
mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
struct sk_buff *skb, u32 tx_info)
{
int ret = -ENOSPC, len = skb->len, pad;
if (q->queued == q->ndesc)
goto error;
int ret, len = skb->len, pad;
pad = round_up(skb->len, 4) - skb->len;
ret = mt76_skb_adjust_pad(skb, pad);
@ -560,6 +559,12 @@ mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
spin_lock_bh(&q->lock);
if (q->queued == q->ndesc) {
ret = -ENOSPC;
spin_unlock_bh(&q->lock);
goto error;
}
q->entry[q->head].buf_sz = len;
q->entry[q->head].skb = skb;

View File

@ -53,7 +53,7 @@ void mt76_testmode_tx_pending(struct mt76_phy *phy)
q->queued < q->ndesc / 2) {
int ret;
ret = dev->queue_ops->tx_queue_skb(dev, q, qid, skb_get(skb),
ret = dev->queue_ops->tx_queue_skb(phy, q, qid, skb_get(skb),
wcid, NULL);
if (ret < 0)
break;

View File

@ -308,7 +308,7 @@ __mt76_tx_queue_skb(struct mt76_phy *phy, int qid, struct sk_buff *skb,
int idx;
non_aql = !info->tx_time_est;
idx = dev->queue_ops->tx_queue_skb(dev, q, qid, skb, wcid, sta);
idx = dev->queue_ops->tx_queue_skb(phy, q, qid, skb, wcid, sta);
if (idx < 0 || !sta)
return idx;

View File

@ -850,13 +850,14 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb,
}
static int
mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
mt76u_tx_queue_skb(struct mt76_phy *phy, struct mt76_queue *q,
enum mt76_txq_id qid, struct sk_buff *skb,
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
{
struct mt76_tx_info tx_info = {
.skb = skb,
};
struct mt76_dev *dev = phy->dev;
u16 idx = q->head;
int err;