mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-17 02:15:57 +00:00
mt76 patches for 5.18
- bugfixes - mbssid support for mt7915 - 6 GHz support for mt7915 - mt7921u driver -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCYjJGDAAKCRDXfRQdAqdu 9SCmAJ0Uy6pWjbGm7z9qQGZjhE7FyrqQPQCggD0MIbXKQRQPGH7wLdoLmNaSYdg= =LmRF -----END PGP SIGNATURE----- Merge tag 'mt76-for-kvalo-2022-03-16' of https://github.com/nbd168/wireless mt76 patches for 5.18 - bugfixes - mbssid support for mt7915 - 6 GHz support for mt7915 - mt7921u driver
This commit is contained in:
commit
a93ccb5c38
@ -942,10 +942,11 @@ mt76_rx_signal(struct mt76_rx_status *status)
|
||||
for (chains = status->chains; chains; chains >>= 1, chain_signal++) {
|
||||
int cur, diff;
|
||||
|
||||
if (!(chains & BIT(0)))
|
||||
cur = *chain_signal;
|
||||
if (!(chains & BIT(0)) ||
|
||||
cur > 0)
|
||||
continue;
|
||||
|
||||
cur = *chain_signal;
|
||||
if (cur > signal)
|
||||
swap(cur, signal);
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#define MT_MCU_RING_SIZE 32
|
||||
#define MT_RX_BUF_SIZE 2048
|
||||
#define MT_SKB_HEAD_LEN 128
|
||||
#define MT_SKB_HEAD_LEN 256
|
||||
|
||||
#define MT_MAX_NON_AQL_PKT 16
|
||||
#define MT_TXQ_FREE_THR 32
|
||||
@ -1274,13 +1274,21 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
|
||||
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
|
||||
struct mt76_sta_stats *stats);
|
||||
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
|
||||
int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u16 val, u16 offset, void *buf, size_t len);
|
||||
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
void *buf, size_t len);
|
||||
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
|
||||
const u16 offset, const u32 val);
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
bool ext);
|
||||
void mt76u_read_copy(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len);
|
||||
u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr);
|
||||
void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u32 addr, u32 val);
|
||||
int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
struct mt76_bus_ops *ops);
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
|
||||
int mt76u_alloc_mcu_queue(struct mt76_dev *dev);
|
||||
int mt76u_alloc_queues(struct mt76_dev *dev);
|
||||
void mt76u_stop_tx(struct mt76_dev *dev);
|
||||
|
@ -76,7 +76,7 @@ void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
__le32 *end = (__le32 *)&skb->data[skb->len];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
if (q == MT_RXQ_MCU) {
|
||||
if (type == PKT_TYPE_RX_EVENT)
|
||||
|
@ -1130,7 +1130,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta,
|
||||
}
|
||||
|
||||
rate_set_tsf = READ_ONCE(sta->rate_set_tsf);
|
||||
rs_idx = !((u32)(FIELD_GET(MT_TXS1_F0_TIMESTAMP, le32_to_cpu(txs_data[1])) -
|
||||
rs_idx = !((u32)(le32_get_bits(txs_data[1], MT_TXS1_F0_TIMESTAMP) -
|
||||
rate_set_tsf) < 1000000);
|
||||
rs_idx ^= rate_set_tsf & BIT(0);
|
||||
rs = &sta->rateset[rs_idx];
|
||||
@ -1244,14 +1244,11 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
|
||||
struct mt7603_sta *msta = NULL;
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u32 txs;
|
||||
u8 wcidx;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[4]);
|
||||
pid = FIELD_GET(MT_TXS4_PID, txs);
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
wcidx = FIELD_GET(MT_TXS3_WCID, txs);
|
||||
pid = le32_get_bits(txs_data[4], MT_TXS4_PID);
|
||||
wcidx = le32_get_bits(txs_data[3], MT_TXS3_WCID);
|
||||
|
||||
if (pid == MT_PACKET_ID_NO_ACK)
|
||||
return;
|
||||
|
@ -261,7 +261,7 @@ static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD1_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[1])) !=
|
||||
if (le32_get_bits(rxd[1], MT_RXD1_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD1_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
@ -1427,7 +1427,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,
|
||||
}
|
||||
|
||||
rate_set_tsf = READ_ONCE(sta->rate_set_tsf);
|
||||
rs_idx = !((u32)(FIELD_GET(MT_TXS4_F0_TIMESTAMP, le32_to_cpu(txs_data[4])) -
|
||||
rs_idx = !((u32)(le32_get_bits(txs_data[4], MT_TXS4_F0_TIMESTAMP) -
|
||||
rate_set_tsf) < 1000000);
|
||||
rs_idx ^= rate_set_tsf & BIT(0);
|
||||
rs = &sta->rateset[rs_idx];
|
||||
@ -1558,14 +1558,11 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
|
||||
struct mt76_wcid *wcid;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
__le32 *txs_data = data;
|
||||
u32 txs;
|
||||
u8 wcidx;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
pid = FIELD_GET(MT_TXS0_PID, txs);
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
pid = le32_get_bits(txs_data[0], MT_TXS0_PID);
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
|
||||
if (pid == MT_PACKET_ID_NO_ACK)
|
||||
return;
|
||||
@ -1653,7 +1650,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);
|
||||
}
|
||||
|
||||
count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl));
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT);
|
||||
if (is_mt7615(&dev->mt76)) {
|
||||
__le16 *token = &free->token[0];
|
||||
|
||||
@ -1686,7 +1683,8 @@ bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)
|
||||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7615_mac_tx_free(dev, data, len);
|
||||
@ -1710,8 +1708,8 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
enum rx_pkt_type type;
|
||||
u16 flag;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
|
||||
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
|
||||
type = PKT_TYPE_NORMAL_MCU;
|
||||
|
||||
|
@ -880,7 +880,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,
|
||||
NULL, wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta,
|
||||
NULL, wtbl_hdr, true);
|
||||
NULL, wtbl_hdr, true, true);
|
||||
mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, &msta->wcid,
|
||||
NULL, wtbl_hdr);
|
||||
}
|
||||
@ -2151,7 +2151,8 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd)
|
||||
.center_chan2 = ieee80211_frequency_to_channel(freq2),
|
||||
};
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->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;
|
||||
|
@ -559,6 +559,7 @@ void mt7663_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e);
|
||||
int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);
|
||||
int mt7663u_mcu_init(struct mt7615_dev *dev);
|
||||
int mt7663u_mcu_power_on(struct mt7615_dev *dev);
|
||||
|
||||
/* sdio */
|
||||
int mt7663s_mcu_init(struct mt7615_dev *dev);
|
||||
|
@ -21,6 +21,64 @@ static const struct usb_device_id mt7615_device_table[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
static u32 mt7663u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7663u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt7663u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt7663u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt7663u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
@ -66,6 +124,14 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
||||
.sta_remove = mt7615_mac_sta_remove,
|
||||
.update_survey = mt7615_update_channel,
|
||||
};
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt7663u_rr,
|
||||
.wr = mt7663u_wr,
|
||||
.rmw = mt7663u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt7663u_copy,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(usb_intf);
|
||||
struct ieee80211_ops *ops;
|
||||
struct mt7615_dev *dev;
|
||||
@ -92,7 +158,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
||||
INIT_WORK(&dev->mcu_work, mt7663u_init_work);
|
||||
dev->reg_map = mt7663_usb_sdio_reg_map;
|
||||
dev->ops = ops;
|
||||
ret = mt76u_init(mdev, usb_intf, true);
|
||||
ret = __mt76u_init(mdev, usb_intf, &bus_ops);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
@ -100,27 +166,15 @@ static int mt7663u_probe(struct usb_interface *usb_intf,
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
if (mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_dbg(dev->mt76.dev, "Usb device already powered on\n");
|
||||
set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state);
|
||||
goto alloc_queues;
|
||||
}
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
ret = mt7663u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
} else {
|
||||
set_bit(MT76_STATE_POWER_OFF, &dev->mphy.state);
|
||||
}
|
||||
|
||||
alloc_queues:
|
||||
ret = mt76u_alloc_mcu_queue(&dev->mt76);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -42,6 +42,26 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_power_on(struct mt7615_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_init(struct mt7615_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7663u_mcu_ops = {
|
||||
@ -57,23 +77,17 @@ int mt7663u_mcu_init(struct mt7615_dev *dev)
|
||||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) {
|
||||
mt7615_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
|
||||
return -EIO;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
ret = mt7615_mcu_restart(&dev->mt76);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = mt7663u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __mt7663_load_firmware(dev);
|
||||
|
@ -899,24 +899,33 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_smps_tlv);
|
||||
|
||||
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv, bool ldpc)
|
||||
void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc)
|
||||
{
|
||||
struct wtbl_ht *ht = NULL;
|
||||
struct tlv *tlv;
|
||||
u32 flags = 0;
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
if (sta->ht_cap.ht_supported || sta->he_6ghz_capa.capa) {
|
||||
tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht),
|
||||
wtbl_tlv, sta_wtbl);
|
||||
ht = (struct wtbl_ht *)tlv;
|
||||
ht->ldpc = ldpc &&
|
||||
ht->ldpc = ht_ldpc &&
|
||||
!!(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING);
|
||||
ht->af = sta->ht_cap.ampdu_factor;
|
||||
ht->mm = sta->ht_cap.ampdu_density;
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
ht->af = sta->ht_cap.ampdu_factor;
|
||||
ht->mm = sta->ht_cap.ampdu_density;
|
||||
} else {
|
||||
ht->af = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
|
||||
ht->mm = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
|
||||
}
|
||||
|
||||
ht->ht = true;
|
||||
}
|
||||
|
||||
if (sta->vht_cap.vht_supported) {
|
||||
if (sta->vht_cap.vht_supported || sta->he_6ghz_capa.capa) {
|
||||
struct wtbl_vht *vht;
|
||||
u8 af;
|
||||
|
||||
@ -924,7 +933,7 @@ void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
sizeof(*vht), wtbl_tlv,
|
||||
sta_wtbl);
|
||||
vht = (struct wtbl_vht *)tlv;
|
||||
vht->ldpc = ldpc &&
|
||||
vht->ldpc = vht_ldpc &&
|
||||
!!(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vht->vht = true;
|
||||
|
||||
@ -1004,7 +1013,8 @@ int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
sta_wtbl, wtbl_hdr);
|
||||
if (info->sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
|
||||
sta_wtbl, wtbl_hdr, true);
|
||||
sta_wtbl, wtbl_hdr,
|
||||
true, true);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
@ -1044,7 +1054,7 @@ void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
if (enable && tx) {
|
||||
u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
|
||||
static const u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };
|
||||
int i;
|
||||
|
||||
for (i = 7; i > 0; i--) {
|
||||
@ -1241,7 +1251,7 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_24G;
|
||||
} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
|
||||
} else if (band == NL80211_BAND_5GHZ) {
|
||||
mode |= PHY_MODE_A;
|
||||
|
||||
if (ht_cap->ht_supported)
|
||||
@ -1250,8 +1260,11 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
if (vht_cap->vht_supported)
|
||||
mode |= PHY_MODE_AC;
|
||||
|
||||
if (he_cap && he_cap->has_he && band == NL80211_BAND_5GHZ)
|
||||
if (he_cap && he_cap->has_he)
|
||||
mode |= PHY_MODE_AX_5G;
|
||||
} else if (band == NL80211_BAND_6GHZ) {
|
||||
mode |= PHY_MODE_A | PHY_MODE_AN |
|
||||
PHY_MODE_AC | PHY_MODE_AX_5G;
|
||||
}
|
||||
|
||||
return mode;
|
||||
@ -2662,11 +2675,25 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
struct bss_info_basic *bss;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
|
||||
bss = (struct bss_info_basic *)tlv;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) {
|
||||
u8 bssid_id = vif->bss_conf.bssid_indicator;
|
||||
struct wiphy *wiphy = phy->hw->wiphy;
|
||||
|
||||
if (bssid_id > ilog2(wiphy->mbssid_max_interfaces))
|
||||
return -EINVAL;
|
||||
|
||||
bss->non_tx_bssid = vif->bss_conf.bssid_index;
|
||||
bss->max_bssid = bssid_id;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (enable) {
|
||||
rcu_read_lock();
|
||||
@ -2691,9 +2718,6 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
break;
|
||||
}
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));
|
||||
|
||||
bss = (struct bss_info_basic *)tlv;
|
||||
bss->network_type = cpu_to_le32(type);
|
||||
bss->bmc_wcid_lo = to_wcid_lo(wlan_idx);
|
||||
bss->bmc_wcid_hi = to_wcid_hi(wlan_idx);
|
||||
|
@ -993,6 +993,7 @@ enum {
|
||||
MCU_UNI_CMD_SUSPEND = 0x05,
|
||||
MCU_UNI_CMD_OFFLOAD = 0x06,
|
||||
MCU_UNI_CMD_HIF_CTRL = 0x07,
|
||||
MCU_UNI_CMD_SNIFFER = 0x24,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -1561,7 +1562,7 @@ void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
|
||||
u8 rcpi, u8 state);
|
||||
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta, void *sta_wtbl,
|
||||
void *wtbl_tlv, bool ldpc);
|
||||
void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc);
|
||||
void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx, void *sta_wtbl,
|
||||
|
@ -245,7 +245,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
|
||||
usb_set_intfdata(usb_intf, dev);
|
||||
|
||||
mt76x02u_init_mcu(mdev);
|
||||
ret = mt76u_init(mdev, usb_intf, false);
|
||||
ret = mt76u_init(mdev, usb_intf);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -57,7 +57,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
||||
usb_set_intfdata(intf, dev);
|
||||
|
||||
mt76x02u_init_mcu(mdev);
|
||||
err = mt76u_init(mdev, intf, false);
|
||||
err = mt76u_init(mdev, intf);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
|
@ -135,9 +135,24 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
|
||||
|
||||
val = eeprom[MT_EE_WIFI_CONF + phy->band_idx];
|
||||
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
|
||||
if (val == MT_EE_BAND_SEL_DEFAULT &&
|
||||
(!is_mt7915(&dev->mt76) || dev->dbdc_support))
|
||||
val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
|
||||
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
switch (val) {
|
||||
case MT_EE_V2_BAND_SEL_5GHZ:
|
||||
phy->mt76->cap.has_5ghz = true;
|
||||
return;
|
||||
case MT_EE_V2_BAND_SEL_6GHZ:
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
return;
|
||||
case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
|
||||
phy->mt76->cap.has_5ghz = true;
|
||||
phy->mt76->cap.has_6ghz = true;
|
||||
return;
|
||||
default:
|
||||
phy->mt76->cap.has_2ghz = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case MT_EE_BAND_SEL_5GHZ:
|
||||
@ -248,32 +263,43 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
{
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
int index, target_power;
|
||||
bool tssi_on;
|
||||
bool tssi_on, is_7976;
|
||||
|
||||
if (chain_idx > 3)
|
||||
return -EINVAL;
|
||||
|
||||
tssi_on = mt7915_tssi_enabled(dev, chan->band);
|
||||
is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
|
||||
|
||||
if (chan->band == NL80211_BAND_2GHZ) {
|
||||
u32 power = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_TX0_POWER_2G : MT_EE_TX0_POWER_2G_V2;
|
||||
if (is_7976) {
|
||||
index = MT_EE_TX0_POWER_2G_V2 + chain_idx;
|
||||
target_power = eeprom[index];
|
||||
} else {
|
||||
index = MT_EE_TX0_POWER_2G + chain_idx * 3;
|
||||
target_power = eeprom[index];
|
||||
|
||||
index = power + chain_idx * 3;
|
||||
target_power = eeprom[index];
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 1];
|
||||
}
|
||||
} else if (chan->band == NL80211_BAND_5GHZ) {
|
||||
int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976);
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 1];
|
||||
if (is_7976) {
|
||||
index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5;
|
||||
target_power = eeprom[index + group];
|
||||
} else {
|
||||
index = MT_EE_TX0_POWER_5G + chain_idx * 12;
|
||||
target_power = eeprom[index + group];
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 8];
|
||||
}
|
||||
} else {
|
||||
int group = mt7915_get_channel_group(chan->hw_value);
|
||||
u32 power = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_TX0_POWER_5G : MT_EE_TX0_POWER_5G_V2;
|
||||
int group = mt7915_get_channel_group_6g(chan->hw_value);
|
||||
|
||||
index = power + chain_idx * 12;
|
||||
target_power = eeprom[index + group];
|
||||
|
||||
if (!tssi_on)
|
||||
target_power += eeprom[index + 8];
|
||||
index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8;
|
||||
target_power = is_7976 ? eeprom[index + group] : 0;
|
||||
}
|
||||
|
||||
return target_power;
|
||||
@ -282,22 +308,20 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
|
||||
{
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
u32 val;
|
||||
u32 val, offs;
|
||||
s8 delta;
|
||||
u32 rate_2g, rate_5g;
|
||||
|
||||
rate_2g = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_RATE_DELTA_2G : MT_EE_RATE_DELTA_2G_V2;
|
||||
|
||||
rate_5g = is_mt7915(&dev->mt76) ?
|
||||
MT_EE_RATE_DELTA_5G : MT_EE_RATE_DELTA_5G_V2;
|
||||
bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
val = eeprom[rate_2g];
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G;
|
||||
else
|
||||
val = eeprom[rate_5g];
|
||||
offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0;
|
||||
|
||||
if (!(val & MT_EE_RATE_DELTA_EN))
|
||||
val = eeprom[offs];
|
||||
|
||||
if (!offs || !(val & MT_EE_RATE_DELTA_EN))
|
||||
return 0;
|
||||
|
||||
delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
|
||||
|
@ -25,8 +25,10 @@ enum mt7915_eeprom_field {
|
||||
MT_EE_TX0_POWER_5G = 0x34b,
|
||||
MT_EE_RATE_DELTA_2G_V2 = 0x7d3,
|
||||
MT_EE_RATE_DELTA_5G_V2 = 0x81e,
|
||||
MT_EE_RATE_DELTA_6G_V2 = 0x884, /* 6g fields only appear in eeprom v2 */
|
||||
MT_EE_TX0_POWER_2G_V2 = 0x441,
|
||||
MT_EE_TX0_POWER_5G_V2 = 0x445,
|
||||
MT_EE_TX0_POWER_6G_V2 = 0x465,
|
||||
MT_EE_ADIE_FT_VERSION = 0x9a0,
|
||||
|
||||
__MT_EE_MAX = 0xe00,
|
||||
@ -76,6 +78,13 @@ enum mt7915_eeprom_band {
|
||||
MT_EE_BAND_SEL_DUAL,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_EE_V2_BAND_SEL_2GHZ,
|
||||
MT_EE_V2_BAND_SEL_5GHZ,
|
||||
MT_EE_V2_BAND_SEL_6GHZ,
|
||||
MT_EE_V2_BAND_SEL_5GHZ_6GHZ,
|
||||
};
|
||||
|
||||
enum mt7915_sku_rate_group {
|
||||
SKU_CCK,
|
||||
SKU_OFDM,
|
||||
@ -96,8 +105,20 @@ enum mt7915_sku_rate_group {
|
||||
};
|
||||
|
||||
static inline int
|
||||
mt7915_get_channel_group(int channel)
|
||||
mt7915_get_channel_group_5g(int channel, bool is_7976)
|
||||
{
|
||||
if (is_7976) {
|
||||
if (channel <= 64)
|
||||
return 0;
|
||||
if (channel <= 96)
|
||||
return 1;
|
||||
if (channel <= 128)
|
||||
return 2;
|
||||
if (channel <= 144)
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (channel >= 184 && channel <= 196)
|
||||
return 0;
|
||||
if (channel <= 48)
|
||||
@ -115,6 +136,15 @@ mt7915_get_channel_group(int channel)
|
||||
return 7;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mt7915_get_channel_group_6g(int channel)
|
||||
{
|
||||
if (channel <= 29)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP(channel - 29, 32);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
|
@ -312,6 +312,7 @@ mt7915_regd_notifier(struct wiphy *wiphy,
|
||||
|
||||
mt7915_init_txpower(dev, &mphy->sband_2g.sband);
|
||||
mt7915_init_txpower(dev, &mphy->sband_5g.sband);
|
||||
mt7915_init_txpower(dev, &mphy->sband_6g.sband);
|
||||
|
||||
mphy->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||
mt7915_dfs_init_radar_detector(phy);
|
||||
@ -342,6 +343,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
wiphy->reg_notifier = mt7915_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);
|
||||
@ -359,6 +361,7 @@ mt7915_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
|
||||
ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
|
||||
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
|
||||
|
||||
hw->max_tx_fragments = 4;
|
||||
@ -558,6 +561,7 @@ static void mt7915_init_work(struct work_struct *work)
|
||||
mt7915_mac_init(dev);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
|
||||
mt7915_init_txpower(dev, &dev->mphy.sband_6g.sband);
|
||||
mt7915_txbf_init(dev);
|
||||
}
|
||||
|
||||
@ -579,7 +583,7 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
|
||||
val &= ~MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
/* release wfsys then mcu re-excutes romcode */
|
||||
/* release wfsys then mcu re-executes romcode */
|
||||
val |= MT_TOP_PWR_SW_RST;
|
||||
mt76_wr(dev, MT_TOP_PWR_CTRL, val);
|
||||
|
||||
@ -724,11 +728,18 @@ void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
|
||||
mt7915_set_stream_he_txbf_caps(struct mt7915_dev *dev,
|
||||
struct ieee80211_sta_he_cap *he_cap,
|
||||
int vif, int nss)
|
||||
{
|
||||
struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
|
||||
u8 c;
|
||||
u8 c, nss_160;
|
||||
|
||||
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
|
||||
if (is_mt7915(&dev->mt76) && !dev->dbdc_support)
|
||||
nss_160 = nss / 2;
|
||||
else
|
||||
nss_160 = nss;
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (vif == NL80211_IFTYPE_MESH_POINT)
|
||||
@ -782,13 +793,21 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap,
|
||||
/* num_snd_dim
|
||||
* for mt7915, max supported nss is 2 for bw > 80MHz
|
||||
*/
|
||||
c = (nss - 1) |
|
||||
IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2;
|
||||
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
|
||||
nss - 1) |
|
||||
FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_MASK,
|
||||
nss_160 - 1);
|
||||
elem->phy_cap_info[5] |= c;
|
||||
|
||||
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;
|
||||
|
||||
if (!is_mt7915(&dev->mt76)) {
|
||||
c = IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ;
|
||||
elem->phy_cap_info[7] |= c;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -872,7 +891,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
@ -911,7 +930,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
|
||||
else if (band == NL80211_BAND_5GHZ)
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
|
||||
|
||||
@ -950,7 +969,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
|
||||
mt7915_set_stream_he_txbf_caps(he_cap, i, nss);
|
||||
mt7915_set_stream_he_txbf_caps(dev, he_cap, i, nss);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
@ -961,6 +980,21 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
|
||||
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
|
||||
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_8,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
|
||||
|
||||
data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
@ -990,6 +1024,15 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_6ghz) {
|
||||
data = phy->iftype[NL80211_BAND_6GHZ];
|
||||
n = mt7915_init_he_caps(phy, NL80211_BAND_6GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_6g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
|
||||
|
@ -226,8 +226,8 @@ mt7915_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
||||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0]));
|
||||
ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1]));
|
||||
ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
|
||||
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
|
||||
ru = (u8)(ru_l | ru_h << 4);
|
||||
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
@ -349,14 +349,16 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
@ -400,7 +402,7 @@ static int mt7915_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
@ -638,6 +640,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
status->band = mphy->chandef.chan->band;
|
||||
if (status->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (status->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
@ -859,7 +863,7 @@ mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
u8 snr;
|
||||
int i;
|
||||
|
||||
band_idx = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1]));
|
||||
band_idx = le32_get_bits(rxv_hdr[1], MT_RXV_HDR_BAND_IDX);
|
||||
if (band_idx && !phy->band_idx)
|
||||
phy = mt7915_ext_phy(dev);
|
||||
|
||||
@ -1101,6 +1105,7 @@ mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
|
||||
if (ieee80211_is_beacon(fc)) {
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
|
||||
txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, 0x18));
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
@ -1215,8 +1220,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
||||
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
||||
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
||||
|
||||
if ((ext_phy || band_idx) &&
|
||||
q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
|
||||
if (ext_phy || band_idx)
|
||||
val |= MT_TXD1_TGID;
|
||||
|
||||
txwi[1] = cpu_to_le32(val);
|
||||
@ -1350,10 +1354,10 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
u16 fc, tid;
|
||||
u32 val;
|
||||
|
||||
if (!sta || !sta->ht_cap.ht_supported)
|
||||
if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
|
||||
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
|
||||
if (tid >= 6) /* skip VO queue */
|
||||
return;
|
||||
|
||||
@ -1401,7 +1405,7 @@ mt7915_txwi_free(struct mt7915_dev *dev, struct mt76_txwi_cache *t,
|
||||
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7915_tx_check_aggr(sta, txwi);
|
||||
} else {
|
||||
wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
}
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
@ -1435,12 +1439,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[MT_TXQ_BE], false);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
|
||||
* to the time ack is received or dropped by hw (air + hw queue time).
|
||||
* Should avoid accessing WTBL to get Tx airtime, and use it instead.
|
||||
*/
|
||||
total = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
|
||||
total = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
v3 = (FIELD_GET(MT_TX_FREE_VER, txd) == 0x4);
|
||||
if (WARN_ON_ONCE((void *)&free->info[total >> v3] > end))
|
||||
return;
|
||||
@ -1558,6 +1557,8 @@ mt7915_mac_add_txs_skb(struct mt7915_dev *dev, struct mt76_wcid *wcid, int pid,
|
||||
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
@ -1631,18 +1632,13 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u16 wcidx;
|
||||
u32 txs;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
pid = FIELD_GET(MT_TXS3_PID, txs);
|
||||
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)
|
||||
return;
|
||||
@ -1679,7 +1675,8 @@ bool mt7915_rx_check(struct mt76_dev *mdev, void *data, int len)
|
||||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7915_mac_tx_free(dev, data, len);
|
||||
@ -1704,7 +1701,7 @@ void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
__le32 *end = (__le32 *)&skb->data[skb->len];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
@ -1803,7 +1800,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
||||
u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
|
||||
FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
|
||||
int offset;
|
||||
bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ;
|
||||
bool a_band = !(phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ);
|
||||
|
||||
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
|
||||
return;
|
||||
@ -1823,7 +1820,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
||||
mt76_wr(dev, MT_TMAC_CDTR(phy->band_idx), cck + reg_offset);
|
||||
mt76_wr(dev, MT_TMAC_ODTR(phy->band_idx), ofdm + reg_offset);
|
||||
mt76_wr(dev, MT_TMAC_ICR0(phy->band_idx),
|
||||
FIELD_PREP(MT_IFS_EIFS_OFDM, is_5ghz ? 84 : 78) |
|
||||
FIELD_PREP(MT_IFS_EIFS_OFDM, a_band ? 84 : 78) |
|
||||
FIELD_PREP(MT_IFS_RIFS, 2) |
|
||||
FIELD_PREP(MT_IFS_SIFS, 10) |
|
||||
FIELD_PREP(MT_IFS_SLOT, phy->slottime));
|
||||
@ -1831,7 +1828,7 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy)
|
||||
mt76_wr(dev, MT_TMAC_ICR1(phy->band_idx),
|
||||
FIELD_PREP(MT_IFS_EIFS_CCK, 314));
|
||||
|
||||
if (phy->slottime < 20 || is_5ghz)
|
||||
if (phy->slottime < 20 || a_band)
|
||||
val = MT7915_CFEND_RATE_DEFAULT;
|
||||
else
|
||||
val = MT7915_CFEND_RATE_11B;
|
||||
@ -2190,15 +2187,6 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR31(phy->band_idx));
|
||||
mib->rx_ba_cnt += cnt;
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK, cnt);
|
||||
|
||||
if (is_mt7915(&dev->mt76))
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += is_mt7915(&dev->mt76) ?
|
||||
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK, cnt) :
|
||||
FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDRMUBF(phy->band_idx));
|
||||
mib->tx_bf_cnt += FIELD_GET(MT_MIB_MU_BF_TX_CNT, cnt);
|
||||
|
||||
@ -2211,24 +2199,10 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
||||
cnt = mt76_rr(dev, MT_MIB_DR11(phy->band_idx));
|
||||
mib->tx_su_acked_mpdu_cnt += cnt;
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx));
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CONT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_RX_FB_BW, cnt);
|
||||
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_RX_FB_NC, cnt);
|
||||
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_RX_FB_NR, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
|
||||
cnt = mt76_rr(dev, MT_ETBF_PAR_RPT0(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_bw = FIELD_GET(MT_ETBF_PAR_RPT0_FB_BW, cnt);
|
||||
mib->tx_bf_rx_fb_nc_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NC, cnt);
|
||||
mib->tx_bf_rx_fb_nr_cnt += FIELD_GET(MT_ETBF_PAR_RPT0_FB_NR, cnt);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
|
||||
cnt = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
|
||||
@ -2257,6 +2231,26 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
||||
dev->mt76.aggr_stats[aggr1++] += val & 0xffff;
|
||||
dev->mt76.aggr_stats[aggr1++] += val >> 16;
|
||||
}
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR33(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR33_TX_PKT_IBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_APP_CNT(phy->band_idx));
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_ETBF_TX_FB_CPL, cnt);
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_ETBF_TX_FB_TRI, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_ETBF_RX_FB_CNT(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, cnt);
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, cnt);
|
||||
} else {
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* rts count */
|
||||
@ -2285,6 +2279,28 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
|
||||
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(15, 0), val);
|
||||
dev->mt76.aggr_stats[aggr0++] += FIELD_GET(GENMASK(31, 16), val);
|
||||
}
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_SDR32(phy->band_idx));
|
||||
mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt);
|
||||
mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_IBF_CNT, cnt);
|
||||
mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_MIB_SDR32_TX_PKT_EBF_CNT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR7(phy->band_idx));
|
||||
mib->tx_bf_fb_cpl_cnt += FIELD_GET(MT_MIB_BFCR7_BFEE_TX_FB_CPL, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR2(phy->band_idx));
|
||||
mib->tx_bf_fb_trig_cnt += FIELD_GET(MT_MIB_BFCR2_BFEE_TX_FB_TRIG, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR0(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_VHT, cnt);
|
||||
mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR0_RX_FB_HT, cnt);
|
||||
|
||||
cnt = mt76_rr(dev, MT_MIB_BFCR1(phy->band_idx));
|
||||
mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt);
|
||||
mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_MIB_BFCR1_RX_FB_HE, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2364,10 +2380,23 @@ static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy)
|
||||
|
||||
static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
|
||||
{
|
||||
int err;
|
||||
int err, region;
|
||||
|
||||
switch (dev->mt76.region) {
|
||||
case NL80211_DFS_ETSI:
|
||||
region = 0;
|
||||
break;
|
||||
case NL80211_DFS_JP:
|
||||
region = 2;
|
||||
break;
|
||||
case NL80211_DFS_FCC:
|
||||
default:
|
||||
region = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain,
|
||||
MT_RX_SEL0, 0);
|
||||
MT_RX_SEL0, region);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
@ -821,8 +821,9 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
|
||||
cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
|
||||
|
||||
if (mvif->cap.ldpc && (elem->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
if (mvif->cap.he_ldpc &&
|
||||
(elem->phy_cap_info[1] &
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
|
||||
cap |= STA_REC_HE_CAP_LDPC;
|
||||
|
||||
if (elem->phy_cap_info[1] &
|
||||
@ -986,6 +987,9 @@ mt7915_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
struct sta_rec_ht *ht;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
|
||||
|
||||
ht = (struct sta_rec_ht *)tlv;
|
||||
@ -1073,7 +1077,8 @@ mt7915_mcu_sta_wtbl_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, tlv, wtbl_hdr);
|
||||
if (sta)
|
||||
mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, skb, sta, tlv,
|
||||
wtbl_hdr, mvif->cap.ldpc);
|
||||
wtbl_hdr, mvif->cap.ht_ldpc,
|
||||
mvif->cap.vht_ldpc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1265,6 +1270,9 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
};
|
||||
bool ebf;
|
||||
|
||||
if (!(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
ebf = mt7915_is_ebf_supported(phy, vif, sta, false);
|
||||
if (!ebf && !dev->ibf)
|
||||
return;
|
||||
@ -1325,6 +1333,9 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
|
||||
struct tlv *tlv;
|
||||
u8 nrow = 0;
|
||||
|
||||
if (!(sta->vht_cap.vht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
if (!mt7915_is_ebf_supported(phy, vif, sta, true))
|
||||
return;
|
||||
|
||||
@ -1582,7 +1593,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
||||
cap |= STA_CAP_TX_STBC;
|
||||
if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
|
||||
cap |= STA_CAP_RX_STBC;
|
||||
if (mvif->cap.ldpc &&
|
||||
if (mvif->cap.ht_ldpc &&
|
||||
(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
|
||||
cap |= STA_CAP_LDPC;
|
||||
|
||||
@ -1608,7 +1619,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
||||
cap |= STA_CAP_VHT_TX_STBC;
|
||||
if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
|
||||
cap |= STA_CAP_VHT_RX_STBC;
|
||||
if (mvif->cap.ldpc &&
|
||||
if (mvif->cap.vht_ldpc &&
|
||||
(sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
|
||||
cap |= STA_CAP_VHT_LDPC;
|
||||
|
||||
@ -1619,6 +1630,10 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
|
||||
if (sta->he_cap.has_he) {
|
||||
ra->supp_mode |= MODE_HE;
|
||||
cap |= STA_CAP_HE;
|
||||
|
||||
if (sta->he_6ghz_capa.capa)
|
||||
ra->af = le16_get_bits(sta->he_6ghz_capa.capa,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
|
||||
}
|
||||
|
||||
ra->sta_cap = cpu_to_le32(cap);
|
||||
@ -1641,7 +1656,7 @@ int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
* once dev->rc_work changes the settings driver should also
|
||||
* update sta_rec_he here.
|
||||
*/
|
||||
if (sta->he_cap.has_he && changed)
|
||||
if (changed)
|
||||
mt7915_mcu_sta_he_tlv(skb, sta, vif);
|
||||
|
||||
/* sta_rec_ra accommodates BW, NSS and only MCS range format
|
||||
@ -1710,7 +1725,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
|
||||
/* tag order is in accordance with firmware dependency. */
|
||||
if (sta && sta->ht_cap.ht_supported) {
|
||||
if (sta) {
|
||||
/* starec bfer */
|
||||
mt7915_mcu_sta_bfer_tlv(dev, skb, vif, sta);
|
||||
/* starec ht */
|
||||
@ -1727,7 +1742,7 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sta && sta->ht_cap.ht_supported) {
|
||||
if (sta) {
|
||||
/* starec amsdu */
|
||||
mt7915_mcu_sta_amsdu_tlv(dev, skb, vif, sta);
|
||||
/* starec he */
|
||||
@ -1810,6 +1825,55 @@ mt7915_mcu_beacon_cntdwn(struct ieee80211_vif *vif, struct sk_buff *rskb,
|
||||
info->cnt = skb->data[offs->cntdwn_counter_offs[0]];
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_mbss(struct sk_buff *rskb, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif, struct bss_info_bcn *bcn,
|
||||
struct ieee80211_mutable_offsets *offs)
|
||||
{
|
||||
struct bss_info_bcn_mbss *mbss;
|
||||
const struct element *elem;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!vif->bss_conf.bssid_indicator)
|
||||
return;
|
||||
|
||||
tlv = mt7915_mcu_add_nested_subtlv(rskb, BSS_INFO_BCN_MBSSID,
|
||||
sizeof(*mbss), &bcn->sub_ntlv,
|
||||
&bcn->len);
|
||||
|
||||
mbss = (struct bss_info_bcn_mbss *)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 u8 *data;
|
||||
|
||||
if (sub_elem->id || sub_elem->datalen < 4)
|
||||
continue; /* not a valid BSS profile */
|
||||
|
||||
/* Find WLAN_EID_MULTI_BSSID_IDX
|
||||
* in the merged nontransmitted profile
|
||||
*/
|
||||
data = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
|
||||
sub_elem->data,
|
||||
sub_elem->datalen);
|
||||
if (!data || data[1] < 1 || !data[2])
|
||||
continue;
|
||||
|
||||
mbss->offset[data[2]] = cpu_to_le16(data - skb->data);
|
||||
mbss->bitmap |= cpu_to_le32(BIT(data[2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_mcu_beacon_cont(struct mt7915_dev *dev, struct ieee80211_vif *vif,
|
||||
struct sk_buff *rskb, struct sk_buff *skb,
|
||||
@ -1872,8 +1936,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
len);
|
||||
if (ie && ie[1] >= sizeof(*ht)) {
|
||||
ht = (void *)(ie + 2);
|
||||
vc->ldpc |= !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
vc->ht_ldpc = !!(le16_to_cpu(ht->cap_info) &
|
||||
IEEE80211_HT_CAP_LDPC_CODING);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
|
||||
@ -1884,7 +1948,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
vht = (void *)(ie + 2);
|
||||
bc = le32_to_cpu(vht->vht_cap_info);
|
||||
|
||||
vc->ldpc |= !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_ldpc = !!(bc & IEEE80211_VHT_CAP_RXLDPC);
|
||||
vc->vht_su_ebfer =
|
||||
(bc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE) &&
|
||||
(pc & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
|
||||
@ -1908,6 +1972,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
|
||||
he = (void *)(ie + 3);
|
||||
|
||||
vc->he_ldpc =
|
||||
HE_PHY(CAP1_LDPC_CODING_IN_PAYLOAD, pe->phy_cap_info[1]);
|
||||
vc->he_su_ebfer =
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, he->phy_cap_info[3]) &&
|
||||
HE_PHY(CAP3_SU_BEAMFORMER, pe->phy_cap_info[3]);
|
||||
@ -1935,6 +2001,9 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
int len = MT7915_BEACON_UPDATE_SIZE + MAX_BEACON_SIZE;
|
||||
bool ext_phy = phy != &dev->phy;
|
||||
|
||||
if (vif->bss_conf.nontransmitted)
|
||||
return 0;
|
||||
|
||||
rskb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76,
|
||||
NULL, len);
|
||||
if (IS_ERR(rskb))
|
||||
@ -1964,8 +2033,8 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
|
||||
mt7915_mcu_beacon_check_caps(phy, vif, skb);
|
||||
|
||||
/* TODO: subtag - 11v MBSSID */
|
||||
mt7915_mcu_beacon_cntdwn(vif, rskb, skb, bcn, &offs);
|
||||
mt7915_mcu_beacon_mbss(rskb, skb, vif, bcn, &offs);
|
||||
mt7915_mcu_beacon_cont(dev, vif, rskb, skb, bcn, &offs);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
@ -2768,6 +2837,11 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
||||
|
||||
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
{
|
||||
static const u8 ch_band[] = {
|
||||
[NL80211_BAND_2GHZ] = 0,
|
||||
[NL80211_BAND_5GHZ] = 1,
|
||||
[NL80211_BAND_6GHZ] = 2,
|
||||
};
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
int freq1 = chandef->center_freq1;
|
||||
@ -2795,7 +2869,7 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
.tx_streams_num = hweight8(phy->mt76->antenna_mask),
|
||||
.rx_streams = phy->mt76->antenna_mask,
|
||||
.band_idx = phy->band_idx,
|
||||
.channel_band = chandef->chan->band,
|
||||
.channel_band = ch_band[chandef->chan->band],
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
@ -2811,7 +2885,8 @@ int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->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;
|
||||
@ -3457,6 +3532,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
case MT_PHY_TYPE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
|
@ -122,6 +122,7 @@ static const u32 mt7915_offs[] = {
|
||||
[PLE_PG_HIF_GROUP] = 0x110,
|
||||
[PLE_HIF_PG_INFO] = 0x114,
|
||||
[AC_OFFSET] = 0x040,
|
||||
[ETBF_PAR_RPT0] = 0x068,
|
||||
};
|
||||
|
||||
static const u32 mt7916_offs[] = {
|
||||
@ -194,6 +195,7 @@ static const u32 mt7916_offs[] = {
|
||||
[PLE_PG_HIF_GROUP] = 0x00c,
|
||||
[PLE_HIF_PG_INFO] = 0x388,
|
||||
[AC_OFFSET] = 0x080,
|
||||
[ETBF_PAR_RPT0] = 0x100,
|
||||
};
|
||||
|
||||
static const struct __map mt7915_reg_map[] = {
|
||||
|
@ -138,7 +138,9 @@ struct mt7915_sta {
|
||||
};
|
||||
|
||||
struct mt7915_vif_cap {
|
||||
bool ldpc:1;
|
||||
bool ht_ldpc:1;
|
||||
bool vht_ldpc:1;
|
||||
bool he_ldpc:1;
|
||||
bool vht_su_ebfer:1;
|
||||
bool vht_su_ebfee:1;
|
||||
bool vht_mu_ebfer:1;
|
||||
@ -225,7 +227,7 @@ struct mt7915_phy {
|
||||
struct mt76_phy *mt76;
|
||||
struct mt7915_dev *dev;
|
||||
|
||||
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
|
||||
struct ieee80211_sband_iftype_data iftype[NUM_NL80211_BANDS][NUM_NL80211_IFTYPES];
|
||||
|
||||
struct ieee80211_vif *monitor_vif;
|
||||
|
||||
|
@ -103,6 +103,7 @@ enum offs_rev {
|
||||
PLE_PG_HIF_GROUP,
|
||||
PLE_HIF_PG_INFO,
|
||||
AC_OFFSET,
|
||||
ETBF_PAR_RPT0,
|
||||
__MT_OFFS_MAX,
|
||||
};
|
||||
|
||||
@ -223,10 +224,10 @@ enum offs_rev {
|
||||
#define MT_ETBF_TX_FB_CPL GENMASK(31, 16)
|
||||
#define MT_ETBF_TX_FB_TRI GENMASK(15, 0)
|
||||
|
||||
#define MT_ETBF_RX_FB_CONT(_band) MT_WF_ETBF(_band, 0x068)
|
||||
#define MT_ETBF_RX_FB_BW GENMASK(7, 6)
|
||||
#define MT_ETBF_RX_FB_NC GENMASK(5, 3)
|
||||
#define MT_ETBF_RX_FB_NR GENMASK(2, 0)
|
||||
#define MT_ETBF_PAR_RPT0(_band) MT_WF_ETBF(_band, __OFFS(ETBF_PAR_RPT0))
|
||||
#define MT_ETBF_PAR_RPT0_FB_BW GENMASK(7, 6)
|
||||
#define MT_ETBF_PAR_RPT0_FB_NC GENMASK(5, 3)
|
||||
#define MT_ETBF_PAR_RPT0_FB_NR GENMASK(2, 0)
|
||||
|
||||
#define MT_ETBF_TX_APP_CNT(_band) MT_WF_ETBF(_band, 0x0f0)
|
||||
#define MT_ETBF_TX_IBF_CNT GENMASK(31, 16)
|
||||
@ -367,11 +368,11 @@ enum offs_rev {
|
||||
#define MT_MIB_SDR31(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR31))
|
||||
|
||||
#define MT_MIB_SDR32(_band) MT_WF_MIB(_band, __OFFS(MIB_SDR32))
|
||||
#define MT_MIB_SDR32_TX_PKT_EBF_CNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_EBF_CNT GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT GENMASK(31, 16)
|
||||
|
||||
#define MT_MIB_SDR33(_band) MT_WF_MIB(_band, 0x088)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK GENMASK(15, 0)
|
||||
#define MT_MIB_SDR32_TX_PKT_IBF_CNT_MASK_MT7916 GENMASK(31, 16)
|
||||
#define MT_MIB_SDR33_TX_PKT_IBF_CNT GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_SDRMUBF(_band) MT_WF_MIB(_band, __OFFS(MIB_SDRMUBF))
|
||||
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
|
||||
@ -401,6 +402,19 @@ enum offs_rev {
|
||||
((n) << 2))
|
||||
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0))
|
||||
|
||||
#define MT_MIB_BFCR0(_band) MT_WF_MIB(_band, 0x7b0)
|
||||
#define MT_MIB_BFCR0_RX_FB_HT GENMASK(15, 0)
|
||||
#define MT_MIB_BFCR0_RX_FB_VHT GENMASK(31, 16)
|
||||
|
||||
#define MT_MIB_BFCR1(_band) MT_WF_MIB(_band, 0x7b4)
|
||||
#define MT_MIB_BFCR1_RX_FB_HE GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_BFCR2(_band) MT_WF_MIB(_band, 0x7b8)
|
||||
#define MT_MIB_BFCR2_BFEE_TX_FB_TRIG GENMASK(15, 0)
|
||||
|
||||
#define MT_MIB_BFCR7(_band) MT_WF_MIB(_band, 0x7cc)
|
||||
#define MT_MIB_BFCR7_BFEE_TX_FB_CPL GENMASK(15, 0)
|
||||
|
||||
/* WTBLON TOP */
|
||||
#define MT_WTBLON_TOP_BASE 0x820d4000
|
||||
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
|
||||
|
@ -196,6 +196,8 @@ static int mt7986_wmac_gpio_setup(struct mt7915_dev *dev)
|
||||
|
||||
type = mt7986_wmac_check_adie_type(dev);
|
||||
pinctrl = devm_pinctrl_get(dev->mt76.dev);
|
||||
if (IS_ERR(pinctrl))
|
||||
return PTR_ERR(pinctrl);
|
||||
|
||||
switch (type) {
|
||||
case ADIE_SB:
|
||||
|
@ -271,6 +271,8 @@ mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
|
||||
case MT76_TM_TX_MODE_OFDM:
|
||||
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &mphy->sband_5g.sband;
|
||||
else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &mphy->sband_6g.sband;
|
||||
else
|
||||
sband = &mphy->sband_2g.sband;
|
||||
|
||||
@ -572,6 +574,8 @@ mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
|
||||
|
||||
if (chandef->chan->band == NL80211_BAND_5GHZ)
|
||||
sband = &phy->mt76->sband_5g.sband;
|
||||
else if (chandef->chan->band == NL80211_BAND_6GHZ)
|
||||
sband = &phy->mt76->sband_6g.sband;
|
||||
else
|
||||
sband = &phy->mt76->sband_2g.sband;
|
||||
|
||||
|
@ -24,3 +24,14 @@ config MT7921S
|
||||
This adds support for MT7921S 802.11ax 2x2:2SS wireless devices.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config MT7921U
|
||||
tristate "MediaTek MT7921U (USB) support"
|
||||
select MT76_USB
|
||||
select MT7921_COMMON
|
||||
depends on MAC80211
|
||||
depends on USB
|
||||
help
|
||||
This adds support for MT7921U 802.11ax 2x2:2SS wireless devices.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
@ -3,6 +3,7 @@
|
||||
obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o
|
||||
obj-$(CONFIG_MT7921E) += mt7921e.o
|
||||
obj-$(CONFIG_MT7921S) += mt7921s.o
|
||||
obj-$(CONFIG_MT7921U) += mt7921u.o
|
||||
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
@ -10,3 +11,4 @@ mt7921-common-y := mac.o mcu.o main.o init.o debugfs.o trace.o
|
||||
mt7921-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
mt7921e-y := pci.o pci_mac.o pci_mcu.o dma.o
|
||||
mt7921s-y := sdio.o sdio_mac.o sdio_mcu.o
|
||||
mt7921u-y := usb.o usb_mac.o
|
||||
|
@ -129,23 +129,22 @@ mt7921_queues_acq(struct seq_file *s, void *data)
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
int j, acs = i / 4, index = i % 4;
|
||||
for (i = 0; i < 4; i++) {
|
||||
u32 ctrl, val, qlen = 0;
|
||||
int j;
|
||||
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
|
||||
ctrl = BIT(31) | BIT(15) | (acs << 8);
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(i));
|
||||
ctrl = BIT(31) | BIT(11) | (i << 24);
|
||||
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (val & BIT(j))
|
||||
continue;
|
||||
|
||||
mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
|
||||
ctrl | (j + (index << 5)));
|
||||
mt76_wr(dev, MT_PLE_FL_Q0_CTRL, ctrl | j);
|
||||
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
|
||||
GENMASK(11, 0));
|
||||
}
|
||||
seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
|
||||
seq_printf(s, "AC%d: queued=%d\n", i, qlen);
|
||||
}
|
||||
|
||||
mt7921_mutex_release(dev);
|
||||
@ -268,6 +267,9 @@ mt7921_pm_set(void *data, u64 val)
|
||||
struct mt7921_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)
|
||||
@ -312,6 +314,9 @@ mt7921_deep_sleep_set(void *data, u64 val)
|
||||
bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
bool enable = !!val;
|
||||
|
||||
if (mt76_is_usb(&dev->mt76))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
if (pm->ds_enable_user == enable)
|
||||
goto out;
|
||||
@ -429,8 +434,13 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
|
||||
mt7921_queues_read);
|
||||
if (mt76_is_mmio(&dev->mt76))
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
dir, mt7921_queues_read);
|
||||
else
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
|
||||
dir, mt76_queues_read);
|
||||
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
|
||||
mt7921_queues_acq);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "../dma.h"
|
||||
#include "mac.h"
|
||||
|
||||
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
||||
static int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
|
@ -165,7 +165,7 @@ out:
|
||||
|
||||
static int mt7921_init_hardware(struct mt7921_dev *dev)
|
||||
{
|
||||
int ret, idx, i;
|
||||
int ret, i;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
|
||||
@ -182,6 +182,13 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7921_init_wcid(struct mt7921_dev *dev)
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* Beacon and mgmt frames should occupy wcid 0 */
|
||||
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
|
||||
if (idx)
|
||||
@ -195,6 +202,38 @@ static int mt7921_init_hardware(struct mt7921_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921_init_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
|
||||
init_work);
|
||||
int ret;
|
||||
|
||||
ret = mt7921_init_hardware(dev);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7921_set_stream_he_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 = mt7921_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;
|
||||
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
|
||||
}
|
||||
|
||||
int mt7921_register_device(struct mt7921_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
@ -222,19 +261,22 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
spin_lock_init(&dev->sta_poll_lock);
|
||||
|
||||
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
|
||||
INIT_WORK(&dev->init_work, mt7921_init_work);
|
||||
|
||||
dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
|
||||
dev->pm.stats.last_wake_event = jiffies;
|
||||
dev->pm.stats.last_doze_event = jiffies;
|
||||
dev->pm.enable_user = true;
|
||||
dev->pm.enable = true;
|
||||
dev->pm.ds_enable_user = true;
|
||||
dev->pm.ds_enable = true;
|
||||
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_sdio(&dev->mt76))
|
||||
if (!mt76_is_mmio(&dev->mt76))
|
||||
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
|
||||
ret = mt7921_init_hardware(dev);
|
||||
ret = mt7921_init_wcid(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -262,23 +304,7 @@ int mt7921_register_device(struct mt7921_dev *dev)
|
||||
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
|
||||
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
|
||||
|
||||
mt76_set_stream_caps(&dev->mphy, true);
|
||||
mt7921_set_stream_he_caps(&dev->phy);
|
||||
|
||||
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
|
||||
ARRAY_SIZE(mt76_rates));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt7921_init_debugfs(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_connac_mcu_set_deep_sleep(&dev->mt76, dev->pm.ds_enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->hw_init_done = true;
|
||||
queue_work(system_wq, &dev->init_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -176,8 +176,8 @@ mt7921_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
|
||||
u32 ru_h, ru_l;
|
||||
u8 ru, offs = 0;
|
||||
|
||||
ru_l = FIELD_GET(MT_PRXV_HE_RU_ALLOC_L, le32_to_cpu(rxv[0]));
|
||||
ru_h = FIELD_GET(MT_PRXV_HE_RU_ALLOC_H, le32_to_cpu(rxv[1]));
|
||||
ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
|
||||
ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
|
||||
ru = (u8)(ru_l | ru_h << 4);
|
||||
|
||||
status->bw = RATE_INFO_BW_HE_RU;
|
||||
@ -247,19 +247,19 @@ mt7921_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
|
||||
MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
|
||||
le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
|
||||
|
||||
he_mu->ru_ch1[0] = FIELD_GET(MT_CRXV_HE_RU0, le32_to_cpu(rxv[3]));
|
||||
he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_40) {
|
||||
he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
|
||||
he_mu->ru_ch2[0] =
|
||||
FIELD_GET(MT_CRXV_HE_RU1, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
|
||||
}
|
||||
|
||||
if (status->bw >= RATE_INFO_BW_80) {
|
||||
he_mu->ru_ch1[1] =
|
||||
FIELD_GET(MT_CRXV_HE_RU2, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
|
||||
he_mu->ru_ch2[1] =
|
||||
FIELD_GET(MT_CRXV_HE_RU3, le32_to_cpu(rxv[3]));
|
||||
le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,14 +304,16 @@ mt7921_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u32 mode)
|
||||
case MT_PHY_TYPE_HE_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN);
|
||||
HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
|
||||
HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
case MT_PHY_TYPE_HE_EXT_SU:
|
||||
he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
|
||||
HE_BITS(DATA1_UL_DL_KNOWN);
|
||||
HE_BITS(DATA1_UL_DL_KNOWN) |
|
||||
HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
|
||||
|
||||
he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
|
||||
break;
|
||||
@ -409,7 +411,7 @@ static int mt7921_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 frame_control;
|
||||
|
||||
if (FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, le32_to_cpu(rxd[3])) !=
|
||||
if (le32_get_bits(rxd[3], MT_RXD3_NORMAL_ADDR_TYPE) !=
|
||||
MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
@ -1024,7 +1026,7 @@ void mt7921_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
if (!sta || !(sta->ht_cap.ht_supported || sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = FIELD_GET(MT_TXD1_TID, le32_to_cpu(txwi[1]));
|
||||
tid = le32_get_bits(txwi[1], MT_TXD1_TID);
|
||||
if (tid >= 6) /* skip VO queue */
|
||||
return;
|
||||
|
||||
@ -1163,18 +1165,13 @@ void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data)
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u16 wcidx;
|
||||
u32 txs;
|
||||
u8 pid;
|
||||
|
||||
txs = le32_to_cpu(txs_data[0]);
|
||||
if (FIELD_GET(MT_TXS0_TXS_FORMAT, txs) > 1)
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
txs = le32_to_cpu(txs_data[2]);
|
||||
wcidx = FIELD_GET(MT_TXS2_WCID, txs);
|
||||
|
||||
txs = le32_to_cpu(txs_data[3]);
|
||||
pid = FIELD_GET(MT_TXS3_PID, txs);
|
||||
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)
|
||||
return;
|
||||
@ -1213,8 +1210,8 @@ void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
enum rx_pkt_type type;
|
||||
u16 flag;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);
|
||||
|
||||
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
|
||||
type = PKT_TYPE_NORMAL_MCU;
|
||||
@ -1627,3 +1624,94 @@ void mt7921_coredump_work(struct work_struct *work)
|
||||
|
||||
mt7921_reset(&dev->mt76);
|
||||
}
|
||||
|
||||
/* usb_sdio */
|
||||
static void
|
||||
mt7921_usb_sdio_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt76_txq_id qid, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
|
||||
|
||||
memset(txwi, 0, MT_SDIO_TXD_SIZE);
|
||||
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
|
||||
skb_push(skb, MT_SDIO_TXD_SIZE);
|
||||
}
|
||||
|
||||
int mt7921_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)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct sk_buff *skb = tx_info->skb;
|
||||
int err, pad, pktid, type;
|
||||
|
||||
if (unlikely(tx_info->skb->len <= ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
if (sta) {
|
||||
struct mt7921_sta *msta = (struct mt7921_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;
|
||||
}
|
||||
}
|
||||
|
||||
pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
|
||||
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);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
if (mt76_is_usb(mdev))
|
||||
pad += 4;
|
||||
|
||||
err = mt76_skb_adjust_pad(skb, pad);
|
||||
if (err)
|
||||
/* Release pktid in case of error. */
|
||||
idr_remove(&wcid->pktid, pktid);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_prepare_skb);
|
||||
|
||||
void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE);
|
||||
unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
u16 idx;
|
||||
|
||||
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7921_tx_check_aggr(sta, txwi);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_complete_skb);
|
||||
|
||||
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mac_sta_poll(dev);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_usb_sdio_tx_status_data);
|
||||
|
@ -202,6 +202,7 @@ enum tx_mcu_port_q_idx {
|
||||
#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
|
||||
#define MT_SDIO_TAIL_SIZE 8
|
||||
#define MT_SDIO_HDR_SIZE 4
|
||||
#define MT_USB_TAIL_SIZE 4
|
||||
|
||||
#define MT_TXD0_Q_IDX GENMASK(31, 25)
|
||||
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
|
||||
|
@ -264,7 +264,7 @@ static int mt7921_start(struct ieee80211_hw *hw)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mt7921_stop(struct ieee80211_hw *hw)
|
||||
void mt7921_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
@ -281,6 +281,7 @@ static void mt7921_stop(struct ieee80211_hw *hw)
|
||||
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_stop);
|
||||
|
||||
static int mt7921_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
@ -479,9 +480,27 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, dev->pm.enable);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921_sniffer_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt7921_dev *dev = priv;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
mt7921_mcu_set_sniffer(dev, vif, monitor);
|
||||
pm->enable = !monitor;
|
||||
pm->ds_enable = !monitor;
|
||||
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
|
||||
|
||||
if (monitor)
|
||||
mt7921_mcu_set_beacon_filter(dev, vif, false);
|
||||
}
|
||||
|
||||
void mt7921_set_runtime_pm(struct mt7921_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev->mphy.hw;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
bool monitor = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
@ -516,17 +535,10 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
bool enabled = !!(hw->conf.flags & IEEE80211_CONF_MONITOR);
|
||||
|
||||
if (!enabled)
|
||||
phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
|
||||
else
|
||||
phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
|
||||
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(0), MT_DMA_DCR0_RXD_G5_EN,
|
||||
enabled);
|
||||
mt76_wr(dev, MT_WF_RFCR(0), phy->rxfilter);
|
||||
mt7921_set_runtime_pm(dev);
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_sniffer_interface_iter, dev);
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0));
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -863,7 +863,8 @@ int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
|
||||
else
|
||||
req.channel_band = chandef->chan->band;
|
||||
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH))
|
||||
if (cmd == MCU_EXT_CMD(SET_RX_PATH) ||
|
||||
dev->mt76.hw->conf.flags & IEEE80211_CONF_MONITOR)
|
||||
req.switch_reason = CH_SWITCH_NORMAL;
|
||||
else if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
|
||||
req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD;
|
||||
@ -1135,3 +1136,33 @@ int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
|
||||
struct {
|
||||
struct {
|
||||
u8 band_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct sniffer_enable_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 enable;
|
||||
u8 pad[3];
|
||||
} __packed enable;
|
||||
} req = {
|
||||
.hdr = {
|
||||
.band_idx = mvif->band_idx,
|
||||
},
|
||||
.enable = {
|
||||
.tag = cpu_to_le16(0),
|
||||
.len = cpu_to_le16(sizeof(struct sniffer_enable_tlv)),
|
||||
.enable = enable,
|
||||
},
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),
|
||||
true);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#define MT7921_DRV_OWN_RETRY_COUNT 10
|
||||
#define MT7921_MCU_INIT_RETRY_COUNT 10
|
||||
#define MT7921_WFSYS_INIT_RETRY_COUNT 2
|
||||
|
||||
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
|
||||
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
|
||||
@ -204,6 +205,8 @@ struct mt7921_dev {
|
||||
struct list_head sta_poll_list;
|
||||
spinlock_t sta_poll_lock;
|
||||
|
||||
struct work_struct init_work;
|
||||
|
||||
u8 fw_debug;
|
||||
|
||||
struct mt76_connac_pm pm;
|
||||
@ -352,17 +355,20 @@ static inline void mt7921_mcu_tx_cleanup(struct mt7921_dev *dev)
|
||||
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);
|
||||
}
|
||||
|
||||
static inline void mt7921_skb_add_sdio_hdr(struct sk_buff *skb,
|
||||
enum mt7921_sdio_pkt_type type)
|
||||
static inline void
|
||||
mt7921_skb_add_usb_sdio_hdr(struct mt7921_dev *dev, struct sk_buff *skb,
|
||||
int type)
|
||||
{
|
||||
u32 hdr;
|
||||
u32 hdr, len;
|
||||
|
||||
hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, skb->len + sizeof(hdr)) |
|
||||
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 mt7921_dev *dev);
|
||||
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
|
||||
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
|
||||
@ -384,7 +390,6 @@ int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
|
||||
void mt7921_tx_worker(struct mt76_worker *w);
|
||||
void mt7921e_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc);
|
||||
void mt7921_tx_token_put(struct mt7921_dev *dev);
|
||||
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb);
|
||||
@ -409,7 +414,6 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
void mt7921_pm_wake_work(struct work_struct *work);
|
||||
void mt7921_pm_power_save_work(struct work_struct *work);
|
||||
bool mt7921_wait_for_mcu_init(struct mt7921_dev *dev);
|
||||
void mt7921_coredump_work(struct work_struct *work);
|
||||
int mt7921_wfsys_reset(struct mt7921_dev *dev);
|
||||
int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr);
|
||||
@ -444,12 +448,26 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921s_mcu_init(struct mt7921_dev *dev);
|
||||
int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev);
|
||||
int mt7921s_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 mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
void mt7921_mac_add_txs(struct mt7921_dev *dev, void *data);
|
||||
void mt7921_set_runtime_pm(struct mt7921_dev *dev);
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
|
||||
int mt7921_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 mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
struct mt76_queue_entry *e);
|
||||
bool mt7921_usb_sdio_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
|
||||
/* usb */
|
||||
#define MT_USB_TYPE_VENDOR (USB_TYPE_VENDOR | 0x1f)
|
||||
#define MT_USB_TYPE_UHW_VENDOR (USB_TYPE_VENDOR | 0x1e)
|
||||
|
||||
int mt7921u_mcu_power_on(struct mt7921_dev *dev);
|
||||
int mt7921u_wfsys_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev);
|
||||
int mt7921u_init_reset(struct mt7921_dev *dev);
|
||||
int mt7921u_mac_reset(struct mt7921_dev *dev);
|
||||
#endif
|
||||
|
@ -105,6 +105,7 @@ static void mt7921e_unregister_device(struct mt7921_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]);
|
||||
|
@ -137,7 +137,7 @@ mt7921_txwi_free(struct mt7921_dev *dev, struct mt76_txwi_cache *t,
|
||||
|
||||
wcid_idx = wcid->idx;
|
||||
} else {
|
||||
wcid_idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
}
|
||||
|
||||
__mt76_tx_complete_skb(mdev, wcid_idx, t->skb, free_list);
|
||||
@ -164,11 +164,7 @@ mt7921e_mac_tx_free(struct mt7921_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);
|
||||
|
||||
/* TODO: MT_TX_FREE_LATENCY is msdu time from the TXD is queued into PLE,
|
||||
* to the time ack is received or dropped by hw (air + hw queue time).
|
||||
* Should avoid accessing WTBL to get Tx airtime, and use it instead.
|
||||
*/
|
||||
count = FIELD_GET(MT_TX_FREE_MSDU_CNT, le16_to_cpu(free->ctrl));
|
||||
count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_CNT);
|
||||
if (WARN_ON_ONCE((void *)&free->info[count] > end))
|
||||
return;
|
||||
|
||||
@ -231,7 +227,8 @@ bool mt7921e_rx_check(struct mt76_dev *mdev, void *data, int len)
|
||||
__le32 *end = (__le32 *)&rxd[len / 4];
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
mt7921e_mac_tx_free(dev, data, len);
|
||||
@ -252,7 +249,7 @@ void mt7921e_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
__le32 *rxd = (__le32 *)skb->data;
|
||||
enum rx_pkt_type type;
|
||||
|
||||
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
|
||||
type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case PKT_TYPE_TXRX_NOTIFY:
|
||||
|
@ -17,13 +17,12 @@
|
||||
#define MT_PLE_BASE 0x820c0000
|
||||
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
|
||||
|
||||
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)
|
||||
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)
|
||||
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8)
|
||||
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc)
|
||||
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x3e0)
|
||||
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x3e4)
|
||||
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x3e8)
|
||||
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x3ec)
|
||||
|
||||
#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \
|
||||
((n) << 2))
|
||||
#define MT_PLE_AC_QEMPTY(_n) MT_PLE(0x500 + 0x40 * (_n))
|
||||
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
|
||||
|
||||
#define MT_MDP_BASE 0x820cd000
|
||||
@ -354,6 +353,7 @@
|
||||
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
|
||||
#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
|
||||
#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
|
||||
#define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9)
|
||||
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
|
||||
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
|
||||
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
|
||||
@ -378,6 +378,9 @@
|
||||
#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640)
|
||||
#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644)
|
||||
|
||||
#define MT_WPDMA0_MAX_CNT_MASK GENMASK(7, 0)
|
||||
#define MT_WPDMA0_BASE_PTR_MASK GENMASK(31, 16)
|
||||
|
||||
#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680)
|
||||
#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684)
|
||||
#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688)
|
||||
@ -426,6 +429,10 @@
|
||||
#define MT_WFDMA_DUMMY_CR MT_MCU_WPDMA0(0x120)
|
||||
#define MT_WFDMA_NEED_REINIT BIT(1)
|
||||
|
||||
#define MT_CBTOP_RGU(ofs) (0x70002000 + (ofs))
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST MT_CBTOP_RGU(0x600)
|
||||
#define MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH BIT(0)
|
||||
|
||||
#define MT_HW_BOUND 0x70010020
|
||||
#define MT_HW_CHIPID 0x70010200
|
||||
#define MT_HW_REV 0x70010204
|
||||
@ -434,12 +441,14 @@
|
||||
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
|
||||
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
|
||||
|
||||
#define MT_DMA_SHDL(ofs) (0xd6000 + (ofs))
|
||||
#define MT_DMA_SHDL(ofs) (0x7c026000 + (ofs))
|
||||
#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004)
|
||||
#define MT_DMASHDL_DMASHDL_BYPASS BIT(28)
|
||||
#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008)
|
||||
#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c)
|
||||
#define MT_DMASHDL_GROUP_SEQ_ORDER BIT(16)
|
||||
#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010)
|
||||
#define MT_DMASHDL_REFILL_MASK GENMASK(31, 16)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
|
||||
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)
|
||||
@ -454,6 +463,43 @@
|
||||
|
||||
#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2))
|
||||
|
||||
#define MT_WFDMA_HOST_CONFIG 0x7c027030
|
||||
#define MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN BIT(6)
|
||||
|
||||
#define MT_UMAC(ofs) (0x74000000 + (ofs))
|
||||
#define MT_UDMA_TX_QSEL MT_UMAC(0x008)
|
||||
#define MT_FW_DL_EN BIT(3)
|
||||
|
||||
#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c)
|
||||
#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0)
|
||||
#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8)
|
||||
|
||||
#define MT_UDMA_WLCFG_0 MT_UMAC(0x18)
|
||||
#define MT_WL_RX_AGG_TO GENMASK(7, 0)
|
||||
#define MT_WL_RX_AGG_LMT GENMASK(15, 8)
|
||||
#define MT_WL_TX_TMOUT_FUNC_EN BIT(16)
|
||||
#define MT_WL_TX_DPH_CHK_EN BIT(17)
|
||||
#define MT_WL_RX_MPSZ_PAD0 BIT(18)
|
||||
#define MT_WL_RX_FLUSH BIT(19)
|
||||
#define MT_TICK_1US_EN BIT(20)
|
||||
#define MT_WL_RX_AGG_EN BIT(21)
|
||||
#define MT_WL_RX_EN BIT(22)
|
||||
#define MT_WL_TX_EN BIT(23)
|
||||
#define MT_WL_RX_BUSY BIT(30)
|
||||
#define MT_WL_TX_BUSY BIT(31)
|
||||
|
||||
#define MT_UDMA_CONN_INFRA_STATUS MT_UMAC(0xa20)
|
||||
#define MT_UDMA_CONN_WFSYS_INIT_DONE BIT(22)
|
||||
#define MT_UDMA_CONN_INFRA_STATUS_SEL MT_UMAC(0xa24)
|
||||
|
||||
#define MT_SSUSB_EPCTL_CSR(ofs) (0x74011800 + (ofs))
|
||||
#define MT_SSUSB_EPCTL_CSR_EP_RST_OPT MT_SSUSB_EPCTL_CSR(0x090)
|
||||
|
||||
#define MT_UWFDMA0(ofs) (0x7c024000 + (ofs))
|
||||
#define MT_UWFDMA0_GLO_CFG MT_UWFDMA0(0x208)
|
||||
#define MT_UWFDMA0_GLO_CFG_EXT0 MT_UWFDMA0(0x2b0)
|
||||
#define MT_UWFDMA0_TX_RING_EXT_CTRL(_n) MT_UWFDMA0(0x600 + ((_n) << 2))
|
||||
|
||||
#define MT_CONN_STATUS 0x7c053c10
|
||||
#define MT_WIFI_PATCH_DL_STATE BIT(0)
|
||||
|
||||
@ -467,6 +513,7 @@
|
||||
#define WFSYS_SW_INIT_DONE BIT(4)
|
||||
|
||||
#define MT_CONN_ON_MISC 0x7c0600f0
|
||||
#define MT_TOP_MISC2_FW_PWR_ON BIT(0)
|
||||
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
|
||||
|
||||
#endif
|
||||
|
@ -41,6 +41,7 @@ static void mt7921s_unregister_device(struct mt7921_dev *dev)
|
||||
{
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
@ -91,9 +92,9 @@ static int mt7921s_probe(struct sdio_func *func,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.tx_prepare_skb = mt7921s_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921s_tx_complete_skb,
|
||||
.tx_status_data = mt7921s_tx_status_data,
|
||||
.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
|
||||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
|
@ -140,86 +140,3 @@ out:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
|
||||
enum mt76_txq_id qid, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
|
||||
|
||||
memset(txwi, 0, MT_SDIO_TXD_SIZE);
|
||||
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
|
||||
skb_push(skb, MT_SDIO_TXD_SIZE);
|
||||
}
|
||||
|
||||
int mt7921s_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 mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct sk_buff *skb = tx_info->skb;
|
||||
int err, pad, pktid;
|
||||
|
||||
if (unlikely(tx_info->skb->len <= ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!wcid)
|
||||
wcid = &dev->mt76.global_wcid;
|
||||
|
||||
if (sta) {
|
||||
struct mt7921_sta *msta = (struct mt7921_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;
|
||||
}
|
||||
}
|
||||
|
||||
pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
|
||||
mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
|
||||
|
||||
mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
|
||||
err = mt76_skb_adjust_pad(skb, pad);
|
||||
if (err)
|
||||
/* Release pktid in case of error. */
|
||||
idr_remove(&wcid->pktid, pktid);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
|
||||
{
|
||||
__le32 *txwi = (__le32 *)(e->skb->data + MT_SDIO_HDR_SIZE);
|
||||
unsigned int headroom = MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TXD1_WLAN_IDX, le32_to_cpu(txwi[1]));
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7921_tx_check_aggr(sta, txwi);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
|
||||
bool mt7921s_tx_status_data(struct mt76_dev *mdev, u8 *update)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_mac_sta_poll(dev);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -36,7 +36,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_sdio_hdr(skb, type);
|
||||
mt7921_skb_add_usb_sdio_hdr(dev, skb, type);
|
||||
pad = round_up(skb->len, 4) - skb->len;
|
||||
__skb_put_zero(skb, pad);
|
||||
|
||||
|
306
drivers/net/wireless/mediatek/mt76/mt7921/usb.c
Normal file
306
drivers/net/wireless/mediatek/mt76/mt7921/usb.c
Normal file
@ -0,0 +1,306 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2022 MediaTek Inc.
|
||||
*
|
||||
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static const struct usb_device_id mt7921u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff) },
|
||||
{ },
|
||||
};
|
||||
|
||||
static u32 mt7921u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt7921u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT,
|
||||
USB_DIR_IN | MT_USB_TYPE_VENDOR, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt7921u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
int mt7921u_mcu_power_on(struct mt7921_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | MT_USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
u32 pad, ep;
|
||||
int ret;
|
||||
|
||||
ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cmd != MCU_CMD(FW_SCATTER))
|
||||
ep = MT_EP_OUT_INBAND_CMD;
|
||||
else
|
||||
ep = MT_EP_OUT_AC_BE;
|
||||
|
||||
mt7921_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 mt7921u_mcu_init(struct mt7921_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mcu_ops = {
|
||||
.headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7921u_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mcu_ops;
|
||||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
ret = mt7921_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 void mt7921u_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
mt7921_stop(hw);
|
||||
}
|
||||
|
||||
static void mt7921u_cleanup(struct mt7921_dev *dev)
|
||||
{
|
||||
clear_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
|
||||
mt7921u_wfsys_reset(dev);
|
||||
mt7921_mcu_exit(dev);
|
||||
mt76u_queues_deinit(&dev->mt76);
|
||||
}
|
||||
|
||||
static int mt7921u_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,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
SURVEY_INFO_TIME_RX |
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
|
||||
.tx_status_data = mt7921_usb_sdio_tx_status_data,
|
||||
.rx_skb = mt7921_queue_rx_skb,
|
||||
.sta_ps = mt7921_sta_ps,
|
||||
.sta_add = mt7921_mac_sta_add,
|
||||
.sta_assoc = mt7921_mac_sta_assoc,
|
||||
.sta_remove = mt7921_mac_sta_remove,
|
||||
.update_survey = mt7921_update_channel,
|
||||
};
|
||||
static const struct mt7921_hif_ops hif_ops = {
|
||||
.mcu_init = mt7921u_mcu_init,
|
||||
.init_reset = mt7921u_init_reset,
|
||||
.reset = mt7921u_mac_reset,
|
||||
};
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt7921u_rr,
|
||||
.wr = mt7921u_wr,
|
||||
.rmw = mt7921u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt7921u_copy,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(usb_intf);
|
||||
struct ieee80211_ops *ops;
|
||||
struct ieee80211_hw *hw;
|
||||
struct mt7921_dev *dev;
|
||||
struct mt76_dev *mdev;
|
||||
int ret;
|
||||
|
||||
ops = devm_kmemdup(&usb_intf->dev, &mt7921_ops, sizeof(mt7921_ops),
|
||||
GFP_KERNEL);
|
||||
if (!ops)
|
||||
return -ENOMEM;
|
||||
|
||||
ops->stop = mt7921u_stop;
|
||||
|
||||
mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), ops, &drv_ops);
|
||||
if (!mdev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = container_of(mdev, struct mt7921_dev, mt76);
|
||||
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 = mt7921u_wfsys_reset(dev);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = mt7921u_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 = mt7921u_dma_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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 = mt7921_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;
|
||||
}
|
||||
|
||||
static void mt7921u_disconnect(struct usb_interface *usb_intf)
|
||||
{
|
||||
struct mt7921_dev *dev = usb_get_intfdata(usb_intf);
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
|
||||
return;
|
||||
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7921u_cleanup(dev);
|
||||
|
||||
usb_set_intfdata(usb_intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(usb_intf));
|
||||
|
||||
mt76_free_device(&dev->mt76);
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, mt7921u_device_table);
|
||||
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7921_ROM_PATCH);
|
||||
|
||||
static struct usb_driver mt7921u_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mt7921u_device_table,
|
||||
.probe = mt7921u_probe,
|
||||
.disconnect = mt7921u_disconnect,
|
||||
.soft_unbind = 1,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
module_usb_driver(mt7921u_driver);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
252
drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
Normal file
252
drivers/net/wireless/mediatek/mt76/mt7921/usb_mac.c
Normal file
@ -0,0 +1,252 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2022 MediaTek Inc.
|
||||
*
|
||||
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "mt7921.h"
|
||||
#include "mcu.h"
|
||||
#include "mac.h"
|
||||
|
||||
static u32 mt7921u_uhw_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_DEV_MODE,
|
||||
USB_DIR_IN | MT_USB_TYPE_UHW_VENDOR, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt7921u_uhw_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE,
|
||||
USB_DIR_OUT | MT_USB_TYPE_UHW_VENDOR, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt7921u_dma_prefetch(struct mt7921_dev *dev)
|
||||
{
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(0),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x80);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(1),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0xc0);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(2),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x100);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(3),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x140);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(4),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x180);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(16),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x280);
|
||||
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
|
||||
MT_WPDMA0_MAX_CNT_MASK, 4);
|
||||
mt76_rmw(dev, MT_UWFDMA0_TX_RING_EXT_CTRL(17),
|
||||
MT_WPDMA0_BASE_PTR_MASK, 0x2c0);
|
||||
}
|
||||
|
||||
static void mt7921u_wfdma_init(struct mt7921_dev *dev)
|
||||
{
|
||||
mt7921u_dma_prefetch(dev);
|
||||
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_OMIT_RX_INFO);
|
||||
mt76_set(dev, MT_UWFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
|
||||
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
|
||||
MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL |
|
||||
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
/* disable dmashdl */
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG_EXT0,
|
||||
MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
|
||||
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
|
||||
|
||||
mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
|
||||
}
|
||||
|
||||
static int mt7921u_dma_rx_evt_ep4(struct mt7921_dev *dev)
|
||||
{
|
||||
if (!mt76_poll(dev, MT_UWFDMA0_GLO_CFG,
|
||||
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
mt76_clear(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
|
||||
MT_WFDMA_HOST_CONFIG_USB_RXEVT_EP4_EN);
|
||||
mt76_set(dev, MT_UWFDMA0_GLO_CFG, MT_WFDMA0_GLO_CFG_RX_DMA_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7921u_epctl_rst_opt(struct mt7921_dev *dev, bool reset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* usb endpoint reset opt
|
||||
* bits[4,9]: out blk ep 4-9
|
||||
* bits[20,21]: in blk ep 4-5
|
||||
* bits[22]: in int ep 6
|
||||
*/
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT);
|
||||
if (reset)
|
||||
val |= GENMASK(9, 4) | GENMASK(22, 20);
|
||||
else
|
||||
val &= ~(GENMASK(9, 4) | GENMASK(22, 20));
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_SSUSB_EPCTL_CSR_EP_RST_OPT, val);
|
||||
}
|
||||
|
||||
int mt7921u_dma_init(struct mt7921_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt7921u_wfdma_init(dev);
|
||||
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
|
||||
|
||||
mt76_set(dev, MT_UDMA_WLCFG_0,
|
||||
MT_WL_RX_EN | MT_WL_TX_EN |
|
||||
MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN);
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_0,
|
||||
MT_WL_RX_AGG_TO | MT_WL_RX_AGG_LMT);
|
||||
mt76_clear(dev, MT_UDMA_WLCFG_1, MT_WL_RX_AGG_PKT_LMT);
|
||||
|
||||
err = mt7921u_dma_rx_evt_ep4(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt7921u_epctl_rst_opt(dev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921u_wfsys_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
mt7921u_epctl_rst_opt(dev, false);
|
||||
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val |= MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
|
||||
usleep_range(10, 20);
|
||||
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST);
|
||||
val &= ~MT_CBTOP_RGU_WF_SUBSYS_RST_WF_WHOLE_PATH;
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_CBTOP_RGU_WF_SUBSYS_RST, val);
|
||||
|
||||
mt7921u_uhw_wr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS_SEL, 0);
|
||||
for (i = 0; i < MT7921_WFSYS_INIT_RETRY_COUNT; i++) {
|
||||
val = mt7921u_uhw_rr(&dev->mt76, MT_UDMA_CONN_INFRA_STATUS);
|
||||
if (val & MT_UDMA_CONN_WFSYS_INIT_DONE)
|
||||
break;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (i == MT7921_WFSYS_INIT_RETRY_COUNT)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921u_init_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
mt7921_mcu_exit(dev);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
mt7921u_wfsys_reset(dev);
|
||||
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
return mt76u_resume_rx(&dev->mt76);
|
||||
}
|
||||
|
||||
int mt7921u_mac_reset(struct mt7921_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
|
||||
set_bit(MT76_RESET, &dev->mphy.state);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
mt7921_mcu_exit(dev);
|
||||
|
||||
mt76u_stop_rx(&dev->mt76);
|
||||
mt76u_stop_tx(&dev->mt76);
|
||||
|
||||
mt7921u_wfsys_reset(dev);
|
||||
|
||||
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
err = mt76u_resume_rx(&dev->mt76);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921u_mcu_power_on(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921u_dma_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7921_run_firmware(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
|
||||
err = mt7921_mcu_set_eeprom(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = mt7921_mac_init(dev);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = __mt7921_start(&dev->phy);
|
||||
out:
|
||||
clear_bit(MT76_RESET, &dev->mphy.state);
|
||||
|
||||
mt76_worker_enable(&dev->mt76.tx_worker);
|
||||
|
||||
return err;
|
||||
}
|
@ -118,7 +118,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
|
||||
__le32 *rxd = (__le32 *)buf;
|
||||
|
||||
/* parse rxd to get the actual packet length */
|
||||
len = FIELD_GET(GENMASK(15, 0), le32_to_cpu(rxd[0]));
|
||||
len = le32_get_bits(rxd[0], GENMASK(15, 0));
|
||||
e->skb = mt76s_build_rx_skb(buf, len, round_up(len + 4, 4));
|
||||
if (!e->skb)
|
||||
break;
|
||||
|
@ -15,9 +15,8 @@ static bool disable_usb_sg;
|
||||
module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644);
|
||||
MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support");
|
||||
|
||||
static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
void *buf, size_t len)
|
||||
int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u16 val, u16 offset, void *buf, size_t len)
|
||||
{
|
||||
struct usb_interface *uintf = to_usb_interface(dev->dev);
|
||||
struct usb_device *udev = interface_to_usbdev(uintf);
|
||||
@ -45,6 +44,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
req, offset, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76u_vendor_request);
|
||||
|
||||
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
u8 req_type, u16 val, u16 offset,
|
||||
@ -62,22 +62,21 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_vendor_request);
|
||||
|
||||
static u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u32 addr)
|
||||
u32 ___mt76u_rr(struct mt76_dev *dev, u8 req, u8 req_type, u32 addr)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
u32 data = ~0;
|
||||
int ret;
|
||||
|
||||
ret = __mt76u_vendor_request(dev, req,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
addr >> 16, addr, usb->data,
|
||||
sizeof(__le32));
|
||||
ret = __mt76u_vendor_request(dev, req, req_type, addr >> 16,
|
||||
addr, usb->data, sizeof(__le32));
|
||||
if (ret == sizeof(__le32))
|
||||
data = get_unaligned_le32(usb->data);
|
||||
trace_usb_reg_rr(dev, addr, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(___mt76u_rr);
|
||||
|
||||
static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
@ -95,7 +94,8 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
break;
|
||||
}
|
||||
|
||||
return ___mt76u_rr(dev, req, addr & ~MT_VEND_TYPE_MASK);
|
||||
return ___mt76u_rr(dev, req, USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
addr & ~MT_VEND_TYPE_MASK);
|
||||
}
|
||||
|
||||
static u32 mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
@ -109,29 +109,17 @@ static u32 mt76u_rr(struct mt76_dev *dev, u32 addr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 mt76u_rr_ext(struct mt76_dev *dev, u32 addr)
|
||||
{
|
||||
u32 ret;
|
||||
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
ret = ___mt76u_rr(dev, MT_VEND_READ_EXT, addr);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ___mt76u_wr(struct mt76_dev *dev, u8 req,
|
||||
u32 addr, u32 val)
|
||||
void ___mt76u_wr(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u32 addr, u32 val)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
|
||||
put_unaligned_le32(val, usb->data);
|
||||
__mt76u_vendor_request(dev, req,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
addr >> 16, addr, usb->data,
|
||||
sizeof(__le32));
|
||||
__mt76u_vendor_request(dev, req, req_type, addr >> 16,
|
||||
addr, usb->data, sizeof(__le32));
|
||||
trace_usb_reg_wr(dev, addr, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(___mt76u_wr);
|
||||
|
||||
static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
@ -145,7 +133,8 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
req = MT_VEND_MULTI_WRITE;
|
||||
break;
|
||||
}
|
||||
___mt76u_wr(dev, req, addr & ~MT_VEND_TYPE_MASK, val);
|
||||
___mt76u_wr(dev, req, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
addr & ~MT_VEND_TYPE_MASK, val);
|
||||
}
|
||||
|
||||
static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
@ -155,13 +144,6 @@ static void mt76u_wr(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt76u_wr_ext(struct mt76_dev *dev, u32 addr, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
@ -173,17 +155,6 @@ static u32 mt76u_rmw(struct mt76_dev *dev, u32 addr,
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 mt76u_rmw_ext(struct mt76_dev *dev, u32 addr,
|
||||
u32 mask, u32 val)
|
||||
{
|
||||
mutex_lock(&dev->usb.usb_ctrl_mtx);
|
||||
val |= ___mt76u_rr(dev, MT_VEND_READ_EXT, addr) & ~mask;
|
||||
___mt76u_wr(dev, MT_VEND_WRITE_EXT, addr, val);
|
||||
mutex_unlock(&dev->usb.usb_ctrl_mtx);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mt76u_copy(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
@ -216,33 +187,8 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void mt76u_copy_ext(struct mt76_dev *dev, u32 offset,
|
||||
const void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int ret, i = 0, batch_len;
|
||||
const u8 *val = data;
|
||||
|
||||
len = round_up(len, 4);
|
||||
mutex_lock(&usb->usb_ctrl_mtx);
|
||||
while (i < len) {
|
||||
batch_len = min_t(int, usb->data_len, len - i);
|
||||
memcpy(usb->data, val + i, batch_len);
|
||||
ret = __mt76u_vendor_request(dev, MT_VEND_WRITE_EXT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
(offset + i) >> 16, offset + i,
|
||||
usb->data, batch_len);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
i += batch_len;
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len)
|
||||
void mt76u_read_copy(struct mt76_dev *dev, u32 offset,
|
||||
void *data, int len)
|
||||
{
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int i = 0, batch_len, ret;
|
||||
@ -264,6 +210,7 @@ mt76u_read_copy_ext(struct mt76_dev *dev, u32 offset,
|
||||
}
|
||||
mutex_unlock(&usb->usb_ctrl_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_read_copy);
|
||||
|
||||
void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
|
||||
const u16 offset, const u32 val)
|
||||
@ -1112,24 +1059,13 @@ static const struct mt76_queue_ops usb_queue_ops = {
|
||||
.kick = mt76u_tx_kick,
|
||||
};
|
||||
|
||||
int mt76u_init(struct mt76_dev *dev,
|
||||
struct usb_interface *intf, bool ext)
|
||||
int __mt76u_init(struct mt76_dev *dev, struct usb_interface *intf,
|
||||
struct mt76_bus_ops *ops)
|
||||
{
|
||||
static struct mt76_bus_ops mt76u_ops = {
|
||||
.read_copy = mt76u_read_copy_ext,
|
||||
.wr_rp = mt76u_wr_rp,
|
||||
.rd_rp = mt76u_rd_rp,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct mt76_usb *usb = &dev->usb;
|
||||
int err;
|
||||
|
||||
mt76u_ops.rr = ext ? mt76u_rr_ext : mt76u_rr;
|
||||
mt76u_ops.wr = ext ? mt76u_wr_ext : mt76u_wr;
|
||||
mt76u_ops.rmw = ext ? mt76u_rmw_ext : mt76u_rmw;
|
||||
mt76u_ops.write_copy = ext ? mt76u_copy_ext : mt76u_copy;
|
||||
|
||||
INIT_WORK(&usb->stat_work, mt76u_tx_status_data);
|
||||
|
||||
usb->data_len = usb_maxpacket(udev, usb_sndctrlpipe(udev, 0), 1);
|
||||
@ -1141,7 +1077,7 @@ int mt76u_init(struct mt76_dev *dev,
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&usb->usb_ctrl_mtx);
|
||||
dev->bus = &mt76u_ops;
|
||||
dev->bus = ops;
|
||||
dev->queue_ops = &usb_queue_ops;
|
||||
|
||||
dev_set_drvdata(&udev->dev, dev);
|
||||
@ -1167,6 +1103,23 @@ int mt76u_init(struct mt76_dev *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76u_init);
|
||||
|
||||
int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf)
|
||||
{
|
||||
static struct mt76_bus_ops bus_ops = {
|
||||
.rr = mt76u_rr,
|
||||
.wr = mt76u_wr,
|
||||
.rmw = mt76u_rmw,
|
||||
.read_copy = mt76u_read_copy,
|
||||
.write_copy = mt76u_copy,
|
||||
.wr_rp = mt76u_wr_rp,
|
||||
.rd_rp = mt76u_rd_rp,
|
||||
.type = MT76_BUS_USB,
|
||||
};
|
||||
|
||||
return __mt76u_init(dev, intf, &bus_ops);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76u_init);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
|
||||
|
Loading…
x
Reference in New Issue
Block a user