Skip to content

Commit

Permalink
mt76: mt7921: introduce mt7921s support
Browse files Browse the repository at this point in the history
Introduce support for mt7921s 802.11ax (Wi-Fi 6) 2x2:2SS chipset.

Tested-by: Deren Wu <deren.wu@mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
Sean Wang authored and Felix Fietkau committed Oct 20, 2021
1 parent fe0195f commit 48fab5b
Show file tree
Hide file tree
Showing 11 changed files with 637 additions and 15 deletions.
10 changes: 10 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7921/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,13 @@ config MT7921E
This adds support for MT7921E 802.11ax 2x2:2SS wireless devices.

To compile this driver as a module, choose M here.

config MT7921S
tristate "MediaTek MT7921S (SDIO) support"
select MT76_SDIO
select MT7921_COMMON
depends on MAC80211
help
This adds support for MT7921S 802.11ax 2x2:2SS wireless devices.

To compile this driver as a module, choose M here.
2 changes: 2 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7921/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

obj-$(CONFIG_MT7921_COMMON) += mt7921-common.o
obj-$(CONFIG_MT7921E) += mt7921e.o
obj-$(CONFIG_MT7921S) += mt7921s.o

CFLAGS_trace.o := -I$(src)

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
18 changes: 17 additions & 1 deletion drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,20 @@ static int mt7921_chip_reset(void *data, u64 val)

DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n");

static int
mt7921s_sched_quota_read(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct mt76_sdio *sdio = &dev->mt76.sdio;

seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);
seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);
seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);
seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);

return 0;
}

int mt7921_init_debugfs(struct mt7921_dev *dev)
{
struct dentry *dir;
Expand All @@ -436,6 +450,8 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
mt7921_pm_stats);
debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);

if (mt76_is_sdio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
mt7921s_sched_quota_read);
return 0;
}
11 changes: 9 additions & 2 deletions drivers/net/wireless/mediatek/mt76/mt7921/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,15 @@ int mt7921_register_device(struct mt7921_dev *dev)
dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
dev->pm.stats.last_wake_event = jiffies;
dev->pm.stats.last_doze_event = jiffies;
dev->pm.enable = true;
dev->pm.ds_enable = true;

/* TODO: mt7921s run sleep mode on default */
if (mt76_is_mmio(&dev->mt76)) {
dev->pm.enable = true;
dev->pm.ds_enable = true;
}

if (mt76_is_sdio(&dev->mt76))
hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE;

ret = mt7921_init_hardware(dev);
if (ret)
Expand Down
22 changes: 15 additions & 7 deletions drivers/net/wireless/mediatek/mt76/mt7921/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,8 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
struct ieee80211_vif *vif = info->control.vif;
struct mt76_phy *mphy = &dev->mphy;
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
bool is_mmio = mt76_is_mmio(&dev->mt76);
u32 sz_txd = is_mmio ? MT_TXD_SIZE : MT_SDIO_TXD_SIZE;
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
u16 tx_count = 15;
u32 val;
Expand All @@ -858,15 +860,15 @@ void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
p_fmt = MT_TX_TYPE_FW;
q_idx = MT_LMAC_BCN0;
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
p_fmt = MT_TX_TYPE_CT;
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = MT_LMAC_ALTX0;
} else {
p_fmt = MT_TX_TYPE_CT;
p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;
q_idx = wmm_idx * MT7921_MAX_WMM_SETS +
mt7921_lmac_mapping(dev, skb_get_queue_mapping(skb));
}

val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |
FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
txwi[0] = cpu_to_le32(val);
Expand Down Expand Up @@ -1384,12 +1386,18 @@ void mt7921_pm_wake_work(struct work_struct *work)
mphy = dev->phy.mt76;

if (!mt7921_mcu_drv_pmctrl(dev)) {
struct mt76_dev *mdev = &dev->mt76;
int i;

mt76_for_each_q_rx(&dev->mt76, i)
napi_schedule(&dev->mt76.napi[i]);
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt7921_mcu_tx_cleanup(dev);
if (mt76_is_sdio(mdev)) {
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt76_worker_schedule(&mdev->sdio.txrx_worker);
} else {
mt76_for_each_q_rx(mdev, i)
napi_schedule(&mdev->napi[i]);
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
mt7921_mcu_tx_cleanup(dev);
}
if (test_bit(MT76_STATE_RUNNING, &mphy->state))
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7921_WATCHDOG_TIME);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7921/mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ enum tx_mcu_port_q_idx {

#define MT_TXD_SIZE (8 * 4)

#define MT_SDIO_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_SDIO_TAIL_SIZE 8
#define MT_SDIO_HDR_SIZE 4

#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
Expand Down
14 changes: 9 additions & 5 deletions drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,9 @@ static int mt7921_load_patch(struct mt7921_dev *dev)
{
const struct mt7921_patch_hdr *hdr;
const struct firmware *fw = NULL;
int i, ret, sem;
int i, ret, sem, max_len;

max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;

sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);
switch (sem) {
Expand Down Expand Up @@ -706,7 +708,7 @@ static int mt7921_load_patch(struct mt7921_dev *dev)
}

ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER,
dl, len, 4096);
dl, len, max_len);
if (ret) {
dev_err(dev->mt76.dev, "Failed to send patch\n");
goto out;
Expand Down Expand Up @@ -753,9 +755,11 @@ mt7921_mcu_send_ram_firmware(struct mt7921_dev *dev,
const struct mt7921_fw_trailer *hdr,
const u8 *data, bool is_wa)
{
int i, offset = 0;
int i, offset = 0, max_len;
u32 override = 0, option = 0;

max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;

for (i = 0; i < hdr->n_region; i++) {
const struct mt7921_fw_region *region;
int err;
Expand All @@ -778,7 +782,7 @@ mt7921_mcu_send_ram_firmware(struct mt7921_dev *dev,
}

err = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD_FW_SCATTER,
data + offset, len, 4096);
data + offset, len, max_len);
if (err) {
dev_err(dev->mt76.dev, "Failed to send firmware.\n");
return err;
Expand Down Expand Up @@ -851,7 +855,7 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
int ret;

ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
if (ret) {
if (ret && mt76_is_mmio(&dev->mt76)) {
dev_dbg(dev->mt76.dev, "Firmware is already download\n");
goto fw_loaded;
}
Expand Down
43 changes: 43 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)

#define MT7921_SDIO_HDR_TX_BYTES GENMASK(15, 0)
#define MT7921_SDIO_HDR_PKT_TYPE GENMASK(17, 16)

enum mt7921_sdio_pkt_type {
MT7921_SDIO_TXD,
MT7921_SDIO_DATA,
MT7921_SDIO_CMD,
MT7921_SDIO_FWDL,
};

struct mt7921_sdio_intr {
u32 isr;
struct {
u32 wtqcr[16];
} tx;
struct {
u16 num[2];
u16 len0[16];
u16 len1[128];
} rx;
u32 rec_mb[2];
} __packed;

#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
#define to_rcpi(rssi) (2 * (rssi) + 220)

Expand Down Expand Up @@ -321,6 +344,17 @@ 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)
{
u32 hdr;

hdr = FIELD_PREP(MT7921_SDIO_HDR_TX_BYTES, skb->len + sizeof(hdr)) |
FIELD_PREP(MT7921_SDIO_HDR_PKT_TYPE, type);

put_unaligned_le32(hdr, skb_push(skb, sizeof(hdr)));
}

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);
Expand Down Expand Up @@ -394,4 +428,13 @@ int mt7921e_mcu_init(struct mt7921_dev *dev);
int mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev);
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);
#endif
Loading

0 comments on commit 48fab5b

Please sign in to comment.