Commit a93ccb5c authored by Kalle Valo's avatar Kalle Valo

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
parents de7ba639 24e69f6b
......@@ -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 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
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);
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, 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 = mt7663u_mcu_power_on(dev);
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");
return -EIO;
}
}
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];
} 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;
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];
index = power + chain_idx * 12;
target_power = eeprom[index + group];
if (!tssi_on)
target_power += eeprom[index + 8];
}
} else {
int group = mt7915_get_channel_group_6g(chan->hw_value);
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;
val = eeprom[offs];
if (!(val & MT_EE_RATE_DELTA_EN))
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)
......
......@@ -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 @@ static int __mt7921_init_hardware(struct mt7921_dev *dev)
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 @@ int mt7921s_mac_reset(struct mt7921_dev *dev)
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);
......
// 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");
// 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>");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment