Skip to content

Commit

Permalink
mt76: mt7615: add dma and tx queue initialization for MT7622
Browse files Browse the repository at this point in the history
MT7622 queue mapping is different from MT7615 and requires an extra dma
scheduler init and a few register tweaks

Co-developed-by: Shayne Chen <shayne.chen@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
Felix Fietkau committed Feb 14, 2020
1 parent 853fb35 commit cdad487
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 51 deletions.
168 changes: 117 additions & 51 deletions drivers/net/wireless/mediatek/mt76/mt7615/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,85 @@
#include "mac.h"

static int
mt7615_init_tx_queues(struct mt7615_dev *dev, int n_desc)
mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
{
struct mt76_sw_queue *q;
struct mt76_queue *hwq;
int err, i;
int err;

hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL);
if (!hwq)
return -ENOMEM;

err = mt76_queue_alloc(dev, hwq, 0, n_desc, 0, MT_TX_RING_BASE);
err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE);
if (err < 0)
return err;

for (i = 0; i < MT_TXQ_MCU; i++) {
q = &dev->mt76.q_tx[i];
INIT_LIST_HEAD(&q->swq);
q->q = hwq;
}
INIT_LIST_HEAD(&q->swq);
q->q = hwq;

return 0;
}

static int
mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q,
int idx, int n_desc)
mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
{
struct mt76_queue *hwq;
int err;
static const u8 wmm_queue_map[] = {
MT7622_TXQ_AC0,
MT7622_TXQ_AC1,
MT7622_TXQ_AC2,
MT7622_TXQ_AC3,
};
int ret;
int i;

hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL);
if (!hwq)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[i],
wmm_queue_map[i],
MT7615_TX_RING_SIZE / 2);
if (ret)
return ret;
}

err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE);
if (err < 0)
return err;
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD],
MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE);
if (ret)
return ret;

INIT_LIST_HEAD(&q->swq);
q->q = hwq;
ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE);
return ret;
}

static int
mt7615_init_tx_queues(struct mt7615_dev *dev)
{
struct mt76_sw_queue *q;
int ret, i;

ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL],
MT7615_TXQ_FWDL,
MT7615_TX_FWDL_RING_SIZE);
if (ret)
return ret;

if (!is_mt7615(&dev->mt76))
return mt7622_init_tx_queues_multi(dev);

ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[0], 0,
MT7615_TX_RING_SIZE);
if (ret)
return ret;

for (i = 1; i < MT_TXQ_MCU; i++) {
q = &dev->mt76.q_tx[i];
INIT_LIST_HEAD(&q->swq);
q->q = dev->mt76.q_tx[0].q;
}

ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT7615_TXQ_MCU,
MT7615_TX_MCU_RING_SIZE);
return 0;
}

Expand Down Expand Up @@ -90,25 +128,32 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
}
}

static void
mt7615_tx_cleanup(struct mt7615_dev *dev)
{
int i;

mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false);
if (is_mt7615(&dev->mt76)) {
mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false);
} else {
for (i = 0; i < IEEE80211_NUM_ACS; i++)
mt76_queue_tx_cleanup(dev, i, false);
}
}

static int mt7615_poll_tx(struct napi_struct *napi, int budget)
{
static const u8 queue_map[] = {
MT_TXQ_MCU,
MT_TXQ_BE
};
struct mt7615_dev *dev;
int i;

dev = container_of(napi, struct mt7615_dev, mt76.tx_napi);

for (i = 0; i < ARRAY_SIZE(queue_map); i++)
mt76_queue_tx_cleanup(dev, queue_map[i], false);
mt7615_tx_cleanup(dev);

if (napi_complete_done(napi, 0))
mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL);

for (i = 0; i < ARRAY_SIZE(queue_map); i++)
mt76_queue_tx_cleanup(dev, queue_map[i], false);
mt7615_tx_cleanup(dev);

mt7615_mac_sta_poll(dev);

Expand All @@ -117,6 +162,30 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
return 0;
}

static void mt7622_dma_sched_init(struct mt7615_dev *dev)
{
u32 reg = mt7615_reg_map(dev, MT_DMASHDL_BASE);
int i;

mt76_rmw(dev, reg + MT_DMASHDL_PKT_MAX_SIZE,
MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE,
FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) |
FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8));

for (i = 0; i <= 5; i++)
mt76_wr(dev, reg + MT_DMASHDL_GROUP_QUOTA(i),
FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x10) |
FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800));

mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(0), 0x42104210);
mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(1), 0x42104210);
mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(2), 0x5);
mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(3), 0);

mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET0, 0x6012345f);
mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET1, 0xedcba987);
}

int mt7615_dma_init(struct mt7615_dev *dev)
{
int ret;
Expand All @@ -126,9 +195,12 @@ int mt7615_dma_init(struct mt7615_dev *dev)
mt76_wr(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE |
MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN |
MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY |
MT_WPDMA_GLO_CFG_OMIT_TX_INFO);

if (!is_mt7622(&dev->mt76))
mt76_set(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY);

mt76_rmw_field(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0, 0x1);

Expand All @@ -141,28 +213,19 @@ int mt7615_dma_init(struct mt7615_dev *dev)
mt76_rmw_field(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3);

mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1);
mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000);
mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000);
mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026);
mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881);
mt76_set(dev, 0x7158, BIT(16));
mt76_clear(dev, 0x7000, BIT(23));
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);

ret = mt7615_init_tx_queues(dev, MT7615_TX_RING_SIZE);
if (ret)
return ret;
if (is_mt7615(&dev->mt76)) {
mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1);
mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000);
mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000);
mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026);
mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881);
mt76_set(dev, 0x7158, BIT(16));
mt76_clear(dev, 0x7000, BIT(23));
}

ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU],
MT7615_TXQ_MCU,
MT7615_TX_MCU_RING_SIZE);
if (ret)
return ret;
mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);

ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL],
MT7615_TXQ_FWDL,
MT7615_TX_FWDL_RING_SIZE);
ret = mt7615_init_tx_queues(dev);
if (ret)
return ret;

Expand Down Expand Up @@ -201,6 +264,9 @@ int mt7615_dma_init(struct mt7615_dev *dev)
/* enable interrupts for TX/RX rings */
mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL);

if (is_mt7622(&dev->mt76))
mt7622_dma_sched_init(dev);

return 0;
}

Expand Down
16 changes: 16 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define MT7615_RATE_RETRY 2

#define MT7615_TX_RING_SIZE 1024
#define MT7615_TX_MGMT_RING_SIZE 128
#define MT7615_TX_MCU_RING_SIZE 128
#define MT7615_TX_FWDL_RING_SIZE 128

Expand Down Expand Up @@ -56,6 +57,16 @@ enum mt7615_hw_txq_id {
MT7615_TXQ_FWDL,
};

enum mt7622_hw_txq_id {
MT7622_TXQ_AC0,
MT7622_TXQ_AC1,
MT7622_TXQ_AC2,
MT7622_TXQ_FWDL = MT7615_TXQ_FWDL,
MT7622_TXQ_AC3,
MT7622_TXQ_MGMT,
MT7622_TXQ_MCU = 15,
};

struct mt7615_rate_set {
struct ieee80211_tx_rate probe_rate;
struct ieee80211_tx_rate rates[4];
Expand Down Expand Up @@ -287,6 +298,11 @@ static inline bool is_mt7622(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7622;
}

static inline bool is_mt7615(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7615;
}

static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask)
{
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
Expand Down
21 changes: 21 additions & 0 deletions drivers/net/wireless/mediatek/mt76/mt7615/regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,27 @@

#define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2))

#define MT_DMASHDL_BASE 0x5000a000
#define MT_DMASHDL_OPTIONAL 0x008
#define MT_DMASHDL_PAGE 0x00c

#define MT_DMASHDL_REFILL 0x010

#define MT_DMASHDL_PKT_MAX_SIZE 0x01c
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)

#define MT_DMASHDL_GROUP_QUOTA(_n) (0x020 + ((_n) << 2))
#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0)
#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16)

#define MT_DMASHDL_SCHED_SET0 0x0b0
#define MT_DMASHDL_SCHED_SET1 0x0b4

#define MT_DMASHDL_Q_MAP(_n) (0x0d0 + ((_n) << 2))
#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0)
#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8))

#define MT_LED_BASE_PHYS 0x80024000
#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n))

Expand Down

0 comments on commit cdad487

Please sign in to comment.