mt76 patches for 6.8

* fixes
 * nvmem eeprom improvements
 * mt7996 eht improvements
 * mt7996 wed support
 * mt7996 36-bit DMA support
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iF0EABECAB0WIQR10Rp9kadxD0kAQu/XfRQdAqdu9QUCZXb8lwAKCRDXfRQdAqdu
 9XQLAJsENZCwHLlYaQjn0EpReGLqZpcdcgCgl781dYOwpANZs56itUWaDyusEhY=
 =fM49
 -----END PGP SIGNATURE-----

Merge tag 'mt76-for-kvalo-2023-12-06' of https://github.com/nbd168/wireless

mt76 patches for 6.8

* fixes
* nvmem eeprom improvements
* mt7996 eht improvements
* mt7996 wed support
* mt7996 36-bit DMA support
This commit is contained in:
Kalle Valo 2023-12-12 17:03:55 +02:00
commit 379872288f
57 changed files with 3271 additions and 748 deletions

View File

@ -9,11 +9,11 @@
#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
#define Q_READ(_dev, _q, _field) ({ \
#define Q_READ(_q, _field) ({ \
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
u32 _val; \
if ((_q)->flags & MT_QFLAG_WED) \
_val = mtk_wed_device_reg_read(&(_dev)->mmio.wed, \
_val = mtk_wed_device_reg_read((_q)->wed, \
((_q)->wed_regs + \
_offset)); \
else \
@ -21,10 +21,10 @@
_val; \
})
#define Q_WRITE(_dev, _q, _field, _val) do { \
#define Q_WRITE(_q, _field, _val) do { \
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
if ((_q)->flags & MT_QFLAG_WED) \
mtk_wed_device_reg_write(&(_dev)->mmio.wed, \
mtk_wed_device_reg_write((_q)->wed, \
((_q)->wed_regs + _offset), \
_val); \
else \
@ -33,8 +33,8 @@
#else
#define Q_READ(_dev, _q, _field) readl(&(_q)->regs->_field)
#define Q_WRITE(_dev, _q, _field, _val) writel(_val, &(_q)->regs->_field)
#define Q_READ(_q, _field) readl(&(_q)->regs->_field)
#define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field)
#endif
@ -188,41 +188,67 @@ EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
static void
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
{
Q_WRITE(dev, q, desc_base, q->desc_dma);
Q_WRITE(dev, q, ring_size, q->ndesc);
q->head = Q_READ(dev, q, dma_idx);
Q_WRITE(q, desc_base, q->desc_dma);
if (q->flags & MT_QFLAG_WED_RRO_EN)
Q_WRITE(q, ring_size, MT_DMA_RRO_EN | q->ndesc);
else
Q_WRITE(q, ring_size, q->ndesc);
q->head = Q_READ(q, dma_idx);
q->tail = q->head;
}
static void
__mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q,
bool reset_idx)
{
if (!q || !q->ndesc)
return;
if (!mt76_queue_is_wed_rro_ind(q)) {
int i;
/* clear descriptors */
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
}
if (reset_idx) {
Q_WRITE(q, cpu_idx, 0);
Q_WRITE(q, dma_idx, 0);
}
mt76_dma_sync_idx(dev, q);
}
static void
mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q)
{
int i;
if (!q || !q->ndesc)
return;
/* clear descriptors */
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
Q_WRITE(dev, q, cpu_idx, 0);
Q_WRITE(dev, q, dma_idx, 0);
mt76_dma_sync_idx(dev, q);
__mt76_dma_queue_reset(dev, q, true);
}
static int
mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_buf *buf, void *data)
{
struct mt76_desc *desc = &q->desc[q->head];
struct mt76_queue_entry *entry = &q->entry[q->head];
struct mt76_txwi_cache *txwi = NULL;
u32 buf1 = 0, ctrl;
struct mt76_desc *desc;
int idx = q->head;
u32 buf1 = 0, ctrl;
int rx_token;
if (mt76_queue_is_wed_rro_ind(q)) {
struct mt76_wed_rro_desc *rro_desc;
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
data = &rro_desc[q->head];
goto done;
}
desc = &q->desc[q->head];
ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
buf1 = FIELD_PREP(MT_DMA_CTL_SDP0_H, buf->addr >> 32);
#endif
if (mt76_queue_is_wed_rx(q)) {
txwi = mt76_get_rxwi(dev);
@ -244,6 +270,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl));
WRITE_ONCE(desc->info, 0);
done:
entry->dma_addr[0] = buf->addr;
entry->dma_len[0] = buf->len;
entry->txwi = txwi;
@ -288,11 +315,18 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q,
entry->dma_len[0] = buf[0].len;
ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
info |= FIELD_PREP(MT_DMA_CTL_SDP0_H, buf[0].addr >> 32);
#endif
if (i < nbufs - 1) {
entry->dma_addr[1] = buf[1].addr;
entry->dma_len[1] = buf[1].len;
buf1 = buf[1].addr;
ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
info |= FIELD_PREP(MT_DMA_CTL_SDP1_H,
buf[1].addr >> 32);
#endif
if (buf[1].skip_unmap)
entry->skip_buf1 = true;
}
@ -343,7 +377,7 @@ static void
mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
wmb();
Q_WRITE(dev, q, cpu_idx, q->head);
Q_WRITE(q, cpu_idx, q->head);
}
static void
@ -359,7 +393,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
if (flush)
last = -1;
else
last = Q_READ(dev, q, dma_idx);
last = Q_READ(q, dma_idx);
while (q->queued > 0 && q->tail != last) {
mt76_dma_tx_cleanup_idx(dev, q, q->tail, &entry);
@ -371,7 +405,7 @@ mt76_dma_tx_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush)
}
if (!flush && q->tail == last)
last = Q_READ(dev, q, dma_idx);
last = Q_READ(q, dma_idx);
}
spin_unlock_bh(&q->cleanup_lock);
@ -392,19 +426,26 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
{
struct mt76_queue_entry *e = &q->entry[idx];
struct mt76_desc *desc = &q->desc[idx];
void *buf;
u32 ctrl, desc_info, buf1;
void *buf = e->buf;
if (mt76_queue_is_wed_rro_ind(q))
goto done;
ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
if (len) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
*len = FIELD_GET(MT_DMA_CTL_SD_LEN0, ctrl);
*more = !(ctrl & MT_DMA_CTL_LAST_SEC0);
}
desc_info = le32_to_cpu(desc->info);
if (info)
*info = le32_to_cpu(desc->info);
*info = desc_info;
buf1 = le32_to_cpu(desc->buf1);
mt76_dma_should_drop_buf(drop, ctrl, buf1, desc_info);
if (mt76_queue_is_wed_rx(q)) {
u32 buf1 = le32_to_cpu(desc->buf1);
u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
@ -420,23 +461,16 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
t->ptr = NULL;
mt76_put_rxwi(dev, t);
if (drop) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
MT_DMA_CTL_DROP));
if (drop)
*drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
}
} else {
buf = e->buf;
e->buf = NULL;
dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
SKB_WITH_OVERHEAD(q->buf_size),
page_pool_get_dma_dir(q->page_pool));
}
done:
e->buf = NULL;
return buf;
}
@ -450,11 +484,16 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
if (!q->queued)
return NULL;
if (flush)
q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
if (mt76_queue_is_wed_rro_data(q))
return NULL;
if (!mt76_queue_is_wed_rro_ind(q)) {
if (flush)
q->desc[idx].ctrl |= cpu_to_le32(MT_DMA_CTL_DMA_DONE);
else if (!(q->desc[idx].ctrl & cpu_to_le32(MT_DMA_CTL_DMA_DONE)))
return NULL;
}
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
@ -606,11 +645,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
spin_lock_bh(&q->lock);
while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf = {};
enum dma_data_direction dir;
struct mt76_queue_buf qbuf;
dma_addr_t addr;
int offset;
void *buf;
void *buf = NULL;
if (mt76_queue_is_wed_rro_ind(q))
goto done;
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
if (!buf)
@ -621,6 +663,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
qbuf.addr = addr + q->buf_offset;
done:
qbuf.len = len - q->buf_offset;
qbuf.skip_unmap = false;
if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
@ -630,7 +673,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
frames++;
}
if (frames)
if (frames || mt76_queue_is_wed_rx(q))
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
@ -641,15 +684,14 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mtk_wed_device *wed = &dev->mmio.wed;
int ret, type, ring;
u8 flags;
int ret = 0, type, ring;
u16 flags;
if (!q || !q->ndesc)
return -EINVAL;
flags = q->flags;
if (!mtk_wed_device_active(wed))
if (!q->wed || !mtk_wed_device_active(q->wed))
q->flags &= ~MT_QFLAG_WED;
if (!(q->flags & MT_QFLAG_WED))
@ -660,29 +702,52 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
switch (type) {
case MT76_WED_Q_TX:
ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs, reset);
ret = mtk_wed_device_tx_ring_setup(q->wed, ring, q->regs,
reset);
if (!ret)
q->wed_regs = wed->tx_ring[ring].reg_base;
q->wed_regs = q->wed->tx_ring[ring].reg_base;
break;
case MT76_WED_Q_TXFREE:
/* WED txfree queue needs ring to be initialized before setup */
q->flags = 0;
mt76_dma_queue_reset(dev, q);
mt76_dma_rx_fill(dev, q, false);
q->flags = flags;
ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
ret = mtk_wed_device_txfree_ring_setup(q->wed, q->regs);
if (!ret)
q->wed_regs = wed->txfree_ring.reg_base;
q->wed_regs = q->wed->txfree_ring.reg_base;
break;
case MT76_WED_Q_RX:
ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
ret = mtk_wed_device_rx_ring_setup(q->wed, ring, q->regs,
reset);
if (!ret)
q->wed_regs = wed->rx_ring[ring].reg_base;
q->wed_regs = q->wed->rx_ring[ring].reg_base;
break;
case MT76_WED_RRO_Q_DATA:
q->flags &= ~MT_QFLAG_WED;
__mt76_dma_queue_reset(dev, q, false);
mtk_wed_device_rro_rx_ring_setup(q->wed, ring, q->regs);
q->head = q->ndesc - 1;
q->queued = q->head;
break;
case MT76_WED_RRO_Q_MSDU_PG:
q->flags &= ~MT_QFLAG_WED;
__mt76_dma_queue_reset(dev, q, false);
mtk_wed_device_msdu_pg_rx_ring_setup(q->wed, ring, q->regs);
q->head = q->ndesc - 1;
q->queued = q->head;
break;
case MT76_WED_RRO_Q_IND:
q->flags &= ~MT_QFLAG_WED;
mt76_dma_queue_reset(dev, q);
mt76_dma_rx_fill(dev, q, false);
mtk_wed_device_ind_rx_ring_setup(q->wed, q->regs);
break;
default:
ret = -EINVAL;
break;
}
q->flags = flags;
return ret;
#else
@ -706,11 +771,26 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
q->buf_size = bufsize;
q->hw_idx = idx;
size = q->ndesc * sizeof(struct mt76_desc);
q->desc = dmam_alloc_coherent(dev->dma_dev, size, &q->desc_dma, GFP_KERNEL);
size = mt76_queue_is_wed_rro_ind(q) ? sizeof(struct mt76_wed_rro_desc)
: sizeof(struct mt76_desc);
q->desc = dmam_alloc_coherent(dev->dma_dev, q->ndesc * size,
&q->desc_dma, GFP_KERNEL);
if (!q->desc)
return -ENOMEM;
if (mt76_queue_is_wed_rro_ind(q)) {
struct mt76_wed_rro_desc *rro_desc;
int i;
rro_desc = (struct mt76_wed_rro_desc *)q->desc;
for (i = 0; i < q->ndesc; i++) {
struct mt76_wed_rro_ind *cmd;
cmd = (struct mt76_wed_rro_ind *)&rro_desc[i];
cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1;
}
}
size = q->ndesc * sizeof(*q->entry);
q->entry = devm_kzalloc(dev->dev, size, GFP_KERNEL);
if (!q->entry)
@ -724,8 +804,13 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (ret)
return ret;
if (q->flags != MT_WED_Q_TXFREE)
mt76_dma_queue_reset(dev, q);
if (mtk_wed_device_active(&dev->mmio.wed)) {
if ((mtk_wed_get_rx_capa(&dev->mmio.wed) && mt76_queue_is_wed_rro(q)) ||
mt76_queue_is_wed_tx_free(q))
return 0;
}
mt76_dma_queue_reset(dev, q);
return 0;
}
@ -747,7 +832,8 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
if (!buf)
break;
mt76_put_page_pool_buf(buf, false);
if (!mt76_queue_is_wed_rro(q))
mt76_put_page_pool_buf(buf, false);
} while (1);
spin_lock_bh(&q->lock);
@ -763,22 +849,31 @@ static void
mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
{
struct mt76_queue *q = &dev->q_rx[qid];
int i;
if (!q->ndesc)
return;
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
if (!mt76_queue_is_wed_rro_ind(q)) {
int i;
for (i = 0; i < q->ndesc; i++)
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
}
mt76_dma_rx_cleanup(dev, q);
/* reset WED rx queues */
mt76_dma_wed_setup(dev, q, true);
if (q->flags != MT_WED_Q_TXFREE) {
mt76_dma_sync_idx(dev, q);
mt76_dma_rx_fill(dev, q, false);
}
if (mt76_queue_is_wed_tx_free(q))
return;
if (mtk_wed_device_active(&dev->mmio.wed) &&
mt76_queue_is_wed_rro(q))
return;
mt76_dma_sync_idx(dev, q);
mt76_dma_rx_fill(dev, q, false);
}
static void
@ -818,8 +913,8 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
bool more;
if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) &&
q->flags == MT_WED_Q_TXFREE) {
dma_idx = Q_READ(dev, q, dma_idx);
mt76_queue_is_wed_tx_free(q)) {
dma_idx = Q_READ(q, dma_idx);
check_ddone = true;
}
@ -829,7 +924,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
if (check_ddone) {
if (q->tail == dma_idx)
dma_idx = Q_READ(dev, q, dma_idx);
dma_idx = Q_READ(q, dma_idx);
if (q->tail == dma_idx)
break;
@ -957,6 +1052,20 @@ void mt76_dma_attach(struct mt76_dev *dev)
}
EXPORT_SYMBOL_GPL(mt76_dma_attach);
void mt76_dma_wed_reset(struct mt76_dev *dev)
{
struct mt76_mmio *mmio = &dev->mmio;
if (!test_bit(MT76_STATE_WED_RESET, &dev->phy.state))
return;
complete(&mmio->wed_reset);
if (!wait_for_completion_timeout(&mmio->wed_reset_complete, 3 * HZ))
dev_err(dev->dev, "wed reset complete timeout\n");
}
EXPORT_SYMBOL_GPL(mt76_dma_wed_reset);
void mt76_dma_cleanup(struct mt76_dev *dev)
{
int i;
@ -981,16 +1090,23 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i];
if (mtk_wed_device_active(&dev->mmio.wed) &&
mt76_queue_is_wed_rro(q))
continue;
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q);
page_pool_destroy(q->page_pool);
}
mt76_free_pending_txwi(dev);
mt76_free_pending_rxwi(dev);
if (mtk_wed_device_active(&dev->mmio.wed))
mtk_wed_device_detach(&dev->mmio.wed);
if (mtk_wed_device_active(&dev->mmio.wed_hif2))
mtk_wed_device_detach(&dev->mmio.wed_hif2);
mt76_free_pending_txwi(dev);
mt76_free_pending_rxwi(dev);
}
EXPORT_SYMBOL_GPL(mt76_dma_cleanup);

View File

@ -19,12 +19,23 @@
#define MT_DMA_CTL_TO_HOST_A BIT(12)
#define MT_DMA_CTL_DROP BIT(14)
#define MT_DMA_CTL_TOKEN GENMASK(31, 16)
#define MT_DMA_CTL_SDP1_H GENMASK(19, 16)
#define MT_DMA_CTL_SDP0_H GENMASK(3, 0)
#define MT_DMA_CTL_WO_DROP BIT(8)
#define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
#define MT_DMA_PPE_ENTRY GENMASK(30, 16)
#define MT_DMA_INFO_DMA_FRAG BIT(9)
#define MT_DMA_INFO_PPE_VLD BIT(31)
#define MT_DMA_CTL_PN_CHK_FAIL BIT(13)
#define MT_DMA_CTL_VER_MASK BIT(7)
#define MT_DMA_RRO_EN BIT(13)
#define MT_DMA_WED_IND_CMD_CNT 8
#define MT_DMA_WED_IND_REASON GENMASK(15, 12)
#define MT_DMA_HDR_LEN 4
#define MT_RX_INFO_LEN 4
#define MT_FCE_INFO_LEN 4
@ -37,6 +48,11 @@ struct mt76_desc {
__le32 info;
} __packed __aligned(4);
struct mt76_wed_rro_desc {
__le32 buf0;
__le32 buf1;
} __packed __aligned(4);
enum mt76_qsel {
MT_QSEL_MGMT,
MT_QSEL_HCCA,
@ -54,9 +70,47 @@ enum mt76_mcu_evt_type {
EVT_EVENT_DFS_DETECT_RSP,
};
enum mt76_dma_wed_ind_reason {
MT_DMA_WED_IND_REASON_NORMAL,
MT_DMA_WED_IND_REASON_REPEAT,
MT_DMA_WED_IND_REASON_OLDPKT,
};
int mt76_dma_rx_poll(struct napi_struct *napi, int budget);
void mt76_dma_attach(struct mt76_dev *dev);
void mt76_dma_cleanup(struct mt76_dev *dev);
int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset);
void mt76_dma_wed_reset(struct mt76_dev *dev);
static inline void
mt76_dma_reset_tx_queue(struct mt76_dev *dev, struct mt76_queue *q)
{
dev->queue_ops->reset_q(dev, q);
if (mtk_wed_device_active(&dev->mmio.wed))
mt76_dma_wed_setup(dev, q, true);
}
static inline void
mt76_dma_should_drop_buf(bool *drop, u32 ctrl, u32 buf1, u32 info)
{
if (!drop)
return;
*drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A | MT_DMA_CTL_DROP));
if (!(ctrl & MT_DMA_CTL_VER_MASK))
return;
switch (FIELD_GET(MT_DMA_WED_IND_REASON, buf1)) {
case MT_DMA_WED_IND_REASON_REPEAT:
*drop = true;
break;
case MT_DMA_WED_IND_REASON_OLDPKT:
*drop = !(info & MT_DMA_INFO_DMA_FRAG);
break;
default:
*drop = !!(ctrl & MT_DMA_CTL_PN_CHK_FAIL);
break;
}
}
#endif

View File

@ -28,7 +28,7 @@ static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len)
return 0;
}
static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len)
int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len)
{
#ifdef CONFIG_MTD
struct device_node *np = dev->dev->of_node;
@ -67,7 +67,7 @@ static int mt76_get_of_epprom_from_mtd(struct mt76_dev *dev, void *eep, int offs
goto out_put_node;
}
offset = be32_to_cpup(list);
offset += be32_to_cpup(list);
ret = mtd_read(mtd, offset, len, &retlen, eep);
put_mtd_device(mtd);
if (mtd_is_bitflip(ret))
@ -105,8 +105,10 @@ out_put_node:
return -ENOENT;
#endif
}
EXPORT_SYMBOL_GPL(mt76_get_of_data_from_mtd);
static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int len)
int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep,
const char *cell_name, int len)
{
struct device_node *np = dev->dev->of_node;
struct nvmem_cell *cell;
@ -114,7 +116,7 @@ static int mt76_get_of_epprom_from_nvmem(struct mt76_dev *dev, void *eep, int le
size_t retlen;
int ret = 0;
cell = of_nvmem_cell_get(np, "eeprom");
cell = of_nvmem_cell_get(np, cell_name);
if (IS_ERR(cell))
return PTR_ERR(cell);
@ -136,8 +138,9 @@ exit:
return ret;
}
EXPORT_SYMBOL_GPL(mt76_get_of_data_from_nvmem);
int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len)
{
struct device_node *np = dev->dev->of_node;
int ret;
@ -149,13 +152,12 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
if (!ret)
return 0;
ret = mt76_get_of_epprom_from_mtd(dev, eep, offset, len);
ret = mt76_get_of_data_from_mtd(dev, eep, 0, len);
if (!ret)
return 0;
return mt76_get_of_epprom_from_nvmem(dev, eep, len);
return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len);
}
EXPORT_SYMBOL_GPL(mt76_get_of_eeprom);
void
mt76_eeprom_override(struct mt76_phy *phy)
@ -379,7 +381,7 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
if (!np)
return target_power;
txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask));
val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
@ -412,6 +414,6 @@ mt76_eeprom_init(struct mt76_dev *dev, int len)
if (!dev->eeprom.data)
return -ENOMEM;
return !mt76_get_of_eeprom(dev, dev->eeprom.data, 0, len);
return !mt76_get_of_eeprom(dev, dev->eeprom.data, len);
}
EXPORT_SYMBOL_GPL(mt76_eeprom_init);

View File

@ -197,10 +197,33 @@ static int mt76_led_init(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
struct ieee80211_hw *hw = phy->hw;
struct device_node *np = dev->dev->of_node;
if (!phy->leds.cdev.brightness_set && !phy->leds.cdev.blink_set)
return 0;
np = of_get_child_by_name(np, "led");
if (np) {
if (!of_device_is_available(np)) {
of_node_put(np);
dev_info(dev->dev,
"led registration was explicitly disabled by dts\n");
return 0;
}
if (phy == &dev->phy) {
int led_pin;
if (!of_property_read_u32(np, "led-sources", &led_pin))
phy->leds.pin = led_pin;
phy->leds.al =
of_property_read_bool(np, "led-active-low");
}
of_node_put(np);
}
snprintf(phy->leds.name, sizeof(phy->leds.name), "mt76-%s",
wiphy_name(hw->wiphy));
@ -211,20 +234,8 @@ static int mt76_led_init(struct mt76_phy *phy)
mt76_tpt_blink,
ARRAY_SIZE(mt76_tpt_blink));
if (phy == &dev->phy) {
struct device_node *np = dev->dev->of_node;
np = of_get_child_by_name(np, "led");
if (np) {
int led_pin;
if (!of_property_read_u32(np, "led-sources", &led_pin))
phy->leds.pin = led_pin;
phy->leds.al = of_property_read_bool(np,
"led-active-low");
of_node_put(np);
}
}
dev_info(dev->dev,
"registering led '%s'\n", phy->leds.name);
return led_classdev_register(dev->dev, &phy->leds.cdev);
}
@ -1537,7 +1548,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int *dbm)
{
struct mt76_phy *phy = hw->priv;
int n_chains = hweight8(phy->antenna_mask);
int n_chains = hweight16(phy->chainmask);
int delta = mt76_tx_power_nss_delta(n_chains);
*dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2);
@ -1725,7 +1736,7 @@ EXPORT_SYMBOL_GPL(mt76_get_antenna);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
int ring_base, u32 flags)
int ring_base, void *wed, u32 flags)
{
struct mt76_queue *hwq;
int err;
@ -1735,6 +1746,7 @@ mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
return ERR_PTR(-ENOMEM);
hwq->flags = flags;
hwq->wed = wed;
err = dev->queue_ops->alloc(dev, hwq, idx, n_desc, 0, ring_base);
if (err < 0)
@ -1842,3 +1854,19 @@ enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
return MT_DFS_STATE_ACTIVE;
}
EXPORT_SYMBOL_GPL(mt76_phy_dfs_state);
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct mt76_phy *phy = hw->priv;
struct mtk_wed_device *wed = &phy->dev->mmio.wed;
if (!mtk_wed_device_active(wed))
return -EOPNOTSUPP;
return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
}
EXPORT_SYMBOL_GPL(mt76_net_setup_tc);
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */

View File

@ -4,6 +4,7 @@
*/
#include "mt76.h"
#include "dma.h"
#include "trace.h"
static u32 mt76_mmio_rr(struct mt76_dev *dev, u32 offset)
@ -84,6 +85,113 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
}
EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
int i;
for (i = 0; i < dev->rx_token_size; i++) {
struct mt76_txwi_cache *t;
t = mt76_rx_token_release(dev, i);
if (!t || !t->ptr)
continue;
mt76_put_page_pool_buf(t->ptr, false);
t->ptr = NULL;
mt76_put_rxwi(dev, t);
}
mt76_free_pending_rxwi(dev);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_release_rx_buf);
u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, len = SKB_WITH_OVERHEAD(q->buf_size);
struct mt76_txwi_cache *t = NULL;
for (i = 0; i < size; i++) {
enum dma_data_direction dir;
dma_addr_t addr;
u32 offset;
int token;
void *buf;
t = mt76_get_rxwi(dev);
if (!t)
goto unmap;
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
if (!buf)
goto unmap;
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dir = page_pool_get_dma_dir(q->page_pool);
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
desc->buf0 = cpu_to_le32(addr);
token = mt76_rx_token_consume(dev, buf, t, addr);
if (token < 0) {
mt76_put_page_pool_buf(buf, false);
goto unmap;
}
token = FIELD_PREP(MT_DMA_CTL_TOKEN, token);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
token |= FIELD_PREP(MT_DMA_CTL_SDP0_H, addr >> 32);
#endif
desc->token |= cpu_to_le32(token);
desc++;
}
return 0;
unmap:
if (t)
mt76_put_rxwi(dev, t);
mt76_mmio_wed_release_rx_buf(wed);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_init_rx_buf);
int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
spin_lock_bh(&dev->token_lock);
dev->token_size = wed->wlan.token_start;
spin_unlock_bh(&dev->token_lock);
return !wait_event_timeout(dev->tx_wait, !dev->wed_token_count, HZ);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_enable);
void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
spin_lock_bh(&dev->token_lock);
dev->token_size = dev->drv->token_size;
spin_unlock_bh(&dev->token_lock);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_offload_disable);
void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
complete(&dev->mmio.wed_reset_complete);
}
EXPORT_SYMBOL_GPL(mt76_mmio_wed_reset_complete);
#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
{
static const struct mt76_bus_ops mt76_mmio_ops = {

View File

@ -29,15 +29,22 @@
#define MT76_TOKEN_FREE_THR 64
#define MT_QFLAG_WED_RING GENMASK(1, 0)
#define MT_QFLAG_WED_TYPE GENMASK(3, 2)
#define MT_QFLAG_WED BIT(4)
#define MT_QFLAG_WED_TYPE GENMASK(4, 2)
#define MT_QFLAG_WED BIT(5)
#define MT_QFLAG_WED_RRO BIT(6)
#define MT_QFLAG_WED_RRO_EN BIT(7)
#define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
FIELD_PREP(MT_QFLAG_WED_RING, _n))
#define __MT_WED_RRO_Q(_type, _n) (MT_QFLAG_WED_RRO | __MT_WED_Q(_type, _n))
#define MT_WED_Q_TX(_n) __MT_WED_Q(MT76_WED_Q_TX, _n)
#define MT_WED_Q_RX(_n) __MT_WED_Q(MT76_WED_Q_RX, _n)
#define MT_WED_Q_TXFREE __MT_WED_Q(MT76_WED_Q_TXFREE, 0)
#define MT_WED_RRO_Q_DATA(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_DATA, _n)
#define MT_WED_RRO_Q_MSDU_PG(_n) __MT_WED_RRO_Q(MT76_WED_RRO_Q_MSDU_PG, _n)
#define MT_WED_RRO_Q_IND __MT_WED_RRO_Q(MT76_WED_RRO_Q_IND, 0)
struct mt76_dev;
struct mt76_phy;
@ -59,6 +66,9 @@ enum mt76_wed_type {
MT76_WED_Q_TX,
MT76_WED_Q_TXFREE,
MT76_WED_Q_RX,
MT76_WED_RRO_Q_DATA,
MT76_WED_RRO_Q_MSDU_PG,
MT76_WED_RRO_Q_IND,
};
struct mt76_bus_ops {
@ -107,6 +117,16 @@ enum mt76_rxq_id {
MT_RXQ_MAIN_WA,
MT_RXQ_BAND2,
MT_RXQ_BAND2_WA,
MT_RXQ_RRO_BAND0,
MT_RXQ_RRO_BAND1,
MT_RXQ_RRO_BAND2,
MT_RXQ_MSDU_PAGE_BAND0,
MT_RXQ_MSDU_PAGE_BAND1,
MT_RXQ_MSDU_PAGE_BAND2,
MT_RXQ_TXFREE_BAND0,
MT_RXQ_TXFREE_BAND1,
MT_RXQ_TXFREE_BAND2,
MT_RXQ_RRO_IND,
__MT_RXQ_MAX
};
@ -163,7 +183,7 @@ struct mt76_queue_entry {
struct urb *urb;
int buf_sz;
};
u32 dma_addr[2];
dma_addr_t dma_addr[2];
u16 dma_len[2];
u16 wcid;
bool skip_buf0:1;
@ -184,6 +204,7 @@ struct mt76_queue {
spinlock_t lock;
spinlock_t cleanup_lock;
struct mt76_queue_entry *entry;
struct mt76_rro_desc *rro_desc;
struct mt76_desc *desc;
u16 first;
@ -197,8 +218,9 @@ struct mt76_queue {
u8 buf_offset;
u8 hw_idx;
u8 flags;
u16 flags;
struct mtk_wed_device *wed;
u32 wed_regs;
dma_addr_t desc_dma;
@ -353,6 +375,17 @@ struct mt76_txq {
bool aggr;
};
struct mt76_wed_rro_ind {
u32 se_id : 12;
u32 rsv : 4;
u32 start_sn : 12;
u32 ind_reason : 4;
u32 ind_cnt : 13;
u32 win_sz : 3;
u32 rsv2 : 13;
u32 magic_cnt : 3;
};
struct mt76_txwi_cache {
struct list_head list;
dma_addr_t dma_addr;
@ -371,6 +404,7 @@ struct mt76_rx_tid {
spinlock_t lock;
struct delayed_work reorder_work;
u16 id;
u16 head;
u16 size;
u16 nframes;
@ -575,8 +609,7 @@ struct mt76_sdio {
struct mt76_worker txrx_worker;
struct mt76_worker status_worker;
struct mt76_worker net_worker;
struct work_struct stat_work;
struct mt76_worker stat_worker;
u8 *xmit_buf;
u32 xmit_buf_sz;
@ -603,6 +636,7 @@ struct mt76_mmio {
u32 irqmask;
struct mtk_wed_device wed;
struct mtk_wed_device wed_hif2;
struct completion wed_reset;
struct completion wed_reset_complete;
};
@ -1047,6 +1081,12 @@ bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
void mt76_pci_disable_aspm(struct pci_dev *pdev);
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt76_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct net_device *netdev, enum tc_setup_type type,
void *type_data);
#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
static inline u16 mt76_chip(struct mt76_dev *dev)
{
return dev->rev >> 16;
@ -1057,6 +1097,14 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
return dev->rev & 0xffff;
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
u32 mt76_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size);
void mt76_mmio_wed_release_rx_buf(struct mtk_wed_device *wed);
int mt76_mmio_wed_offload_enable(struct mtk_wed_device *wed);
void mt76_mmio_wed_offload_disable(struct mtk_wed_device *wed);
void mt76_mmio_wed_reset_complete(struct mtk_wed_device *wed);
#endif /*CONFIG_NET_MEDIATEK_SOC_WED */
#define mt76xx_chip(dev) mt76_chip(&((dev)->mt76))
#define mt76xx_rev(dev) mt76_rev(&((dev)->mt76))
@ -1102,19 +1150,22 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
int mt76_eeprom_init(struct mt76_dev *dev, int len);
void mt76_eeprom_override(struct mt76_phy *phy);
int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len);
int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep,
const char *cell_name, int len);
struct mt76_queue *
mt76_init_queue(struct mt76_dev *dev, int qid, int idx, int n_desc,
int ring_base, u32 flags);
int ring_base, void *wed, u32 flags);
u16 mt76_calculate_default_rate(struct mt76_phy *phy,
struct ieee80211_vif *vif, int rateidx);
static inline int mt76_init_tx_queue(struct mt76_phy *phy, int qid, int idx,
int n_desc, int ring_base, u32 flags)
int n_desc, int ring_base, void *wed,
u32 flags)
{
struct mt76_queue *q;
q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, flags);
q = mt76_init_queue(phy->dev, qid, idx, n_desc, ring_base, wed, flags);
if (IS_ERR(q))
return PTR_ERR(q);
@ -1128,7 +1179,7 @@ static inline int mt76_init_mcu_queue(struct mt76_dev *dev, int qid, int idx,
{
struct mt76_queue *q;
q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, 0);
q = mt76_init_queue(dev, qid, idx, n_desc, ring_base, NULL, 0);
if (IS_ERR(q))
return PTR_ERR(q);
@ -1547,10 +1598,38 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
struct mt76_power_limits *dest,
s8 target_power);
static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
static inline bool mt76_queue_is_wed_tx_free(struct mt76_queue *q)
{
return (q->flags & MT_QFLAG_WED) &&
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_TXFREE;
}
static inline bool mt76_queue_is_wed_rro(struct mt76_queue *q)
{
return q->flags & MT_QFLAG_WED_RRO;
}
static inline bool mt76_queue_is_wed_rro_ind(struct mt76_queue *q)
{
return mt76_queue_is_wed_rro(q) &&
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_IND;
}
static inline bool mt76_queue_is_wed_rro_data(struct mt76_queue *q)
{
return mt76_queue_is_wed_rro(q) &&
(FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_DATA ||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_RRO_Q_MSDU_PG);
}
static inline bool mt76_queue_is_wed_rx(struct mt76_queue *q)
{
if (!(q->flags & MT_QFLAG_WED))
return false;
return FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX ||
mt76_queue_is_wed_rro_ind(q) || mt76_queue_is_wed_rro_data(q);
}
struct mt76_txwi_cache *

View File

@ -173,13 +173,14 @@ int mt7603_dma_init(struct mt7603_dev *dev)
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
MT7603_TX_RING_SIZE, MT_TX_RING_BASE, 0);
MT7603_TX_RING_SIZE, MT_TX_RING_BASE,
NULL, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
MT7603_PSD_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
@ -189,12 +190,12 @@ int mt7603_dma_init(struct mt7603_dev *dev)
return ret;
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_BEACON, MT_TX_HW_QUEUE_BCN,
MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_CAB, MT_TX_HW_QUEUE_BMC,
MT_MCU_RING_SIZE, MT_TX_RING_BASE, 0);
MT_MCU_RING_SIZE, MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;

View File

@ -52,15 +52,12 @@ error:
return ret;
}
static int
mt76_wmac_remove(struct platform_device *pdev)
static void mt76_wmac_remove(struct platform_device *pdev)
{
struct mt76_dev *mdev = platform_get_drvdata(pdev);
struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
mt7603_unregister_device(dev);
return 0;
}
static const struct of_device_id of_wmac_match[] = {
@ -74,7 +71,7 @@ MODULE_FIRMWARE(MT7628_FIRMWARE_E2);
struct platform_driver mt76_wmac_driver = {
.probe = mt76_wmac_probe,
.remove = mt76_wmac_remove,
.remove_new = mt76_wmac_remove,
.driver = {
.name = "mt76_wmac",
.of_match_table = of_wmac_match,

View File

@ -26,14 +26,14 @@ mt7622_init_tx_queues_multi(struct mt7615_dev *dev)
for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, wmm_queue_map[i],
MT7615_TX_RING_SIZE / 2,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT7622_TXQ_MGMT,
MT7615_TX_MGMT_RING_SIZE,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
@ -55,7 +55,7 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
return mt7622_init_tx_queues_multi(dev);
ret = mt76_connac_init_tx_queues(&dev->mphy, 0, MT7615_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;

View File

@ -453,7 +453,7 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb)
else
mphy = &dev->mt76.phy;
phy = (struct mt7615_phy *)mphy->priv;
phy = mphy->priv;
spin_lock_bh(&dev->mt76.lock);
__skb_queue_tail(&phy->scan_event_list, skb);
@ -481,7 +481,7 @@ mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb)
ieee80211_ready_on_channel(mphy->hw);
phy = (struct mt7615_phy *)mphy->priv;
phy = mphy->priv;
phy->roc_grant = true;
wake_up(&phy->roc_wait);

View File

@ -204,8 +204,8 @@ static int mt7663s_suspend(struct device *dev)
mt76_worker_disable(&mdev->mt76.sdio.txrx_worker);
mt76_worker_disable(&mdev->mt76.sdio.status_worker);
mt76_worker_disable(&mdev->mt76.sdio.net_worker);
mt76_worker_disable(&mdev->mt76.sdio.stat_worker);
cancel_work_sync(&mdev->mt76.sdio.stat_work);
clear_bit(MT76_READING_STATS, &mdev->mphy.state);
mt76_tx_status_check(&mdev->mt76, true);

View File

@ -45,13 +45,11 @@ static int mt7622_wmac_probe(struct platform_device *pdev)
return mt7615_mmio_probe(&pdev->dev, mem_base, irq, mt7615e_reg_map);
}
static int mt7622_wmac_remove(struct platform_device *pdev)
static void mt7622_wmac_remove(struct platform_device *pdev)
{
struct mt7615_dev *dev = platform_get_drvdata(pdev);
mt7615_unregister_device(dev);
return 0;
}
static const struct of_device_id mt7622_wmac_of_match[] = {
@ -65,7 +63,7 @@ struct platform_driver mt7622_wmac_driver = {
.of_match_table = mt7622_wmac_of_match,
},
.probe = mt7622_wmac_probe,
.remove = mt7622_wmac_remove,
.remove_new = mt7622_wmac_remove,
};
MODULE_FIRMWARE(MT7622_FIRMWARE_N9);

View File

@ -222,6 +222,11 @@ static inline bool is_mt7996(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7990;
}
static inline bool is_mt7992(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7992;
}
static inline bool is_mt7622(struct mt76_dev *dev)
{
if (!IS_ENABLED(CONFIG_MT7622_WMAC))
@ -391,7 +396,8 @@ mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
void mt76_connac_gen_ppe_thresh(u8 *he_ppet, int nss);
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
int ring_base, u32 flags);
int ring_base, void *wed, u32 flags);
void mt76_connac_write_hw_txp(struct mt76_dev *dev,
struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id);

View File

@ -239,11 +239,13 @@ enum tx_mgnt_type {
#define MT_TXD6_TX_SRC GENMASK(31, 30)
#define MT_TXD6_VTA BIT(28)
#define MT_TXD6_BW GENMASK(25, 22)
#define MT_TXD6_FIXED_BW BIT(25)
#define MT_TXD6_BW GENMASK(24, 22)
#define MT_TXD6_TX_RATE GENMASK(21, 16)
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
#define MT_TXD6_MSDU_CNT_V2 GENMASK(15, 10)
#define MT_TXD6_DIS_MAT BIT(3)
#define MT_TXD6_DAS BIT(2)
#define MT_TXD6_AMSDU_CAP BIT(1)
@ -259,6 +261,9 @@ enum tx_mgnt_type {
#define MT_TXD9_WLAN_IDX GENMASK(23, 8)
#define MT_TXP_BUF_LEN GENMASK(11, 0)
#define MT_TXP_DMA_ADDR_H GENMASK(15, 12)
#define MT_TX_RATE_STBC BIT(14)
#define MT_TX_RATE_NSS GENMASK(13, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)

View File

@ -256,11 +256,12 @@ void mt76_connac_txp_skb_unmap(struct mt76_dev *dev,
EXPORT_SYMBOL_GPL(mt76_connac_txp_skb_unmap);
int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
int ring_base, u32 flags)
int ring_base, void *wed, u32 flags)
{
int i, err;
err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base, flags);
err = mt76_init_tx_queue(phy, 0, idx, n_desc, ring_base,
wed, flags);
if (err < 0)
return err;

View File

@ -67,7 +67,8 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
(is_mt7921(dev) && addr == 0x900000) ||
(is_mt7925(dev) && addr == 0x900000) ||
(is_mt7996(dev) && addr == 0x900000))
(is_mt7996(dev) && addr == 0x900000) ||
(is_mt7992(dev) && addr == 0x900000))
cmd = MCU_CMD(PATCH_START_REQ);
else
cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ);
@ -1359,7 +1360,7 @@ u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,
sband = phy->hw->wiphy->bands[band];
eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);
if (!eht_cap || !eht_cap->has_eht)
if (!eht_cap || !eht_cap->has_eht || !vif->bss_conf.eht_support)
return mode;
switch (band) {

View File

@ -416,6 +416,14 @@ struct sta_rec_he_6g_capa {
u8 rsv[2];
} __packed;
struct sta_rec_pn_info {
__le16 tag;
__le16 len;
u8 pn[6];
u8 tsc_type;
u8 rsv;
} __packed;
struct sec_key {
u8 cipher_id;
u8 cipher_len;
@ -768,6 +776,7 @@ struct wtbl_raw {
sizeof(struct sta_rec_sec) + \
sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct sta_rec_pn_info) + \
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
@ -798,6 +807,7 @@ enum {
STA_REC_HE_V2 = 0x19,
STA_REC_MLD = 0x20,
STA_REC_EHT = 0x22,
STA_REC_PN_INFO = 0x26,
STA_REC_HDRT = 0x28,
STA_REC_HDR_TRANS = 0x2B,
STA_REC_MAX_NUM
@ -1021,7 +1031,9 @@ enum {
MCU_UNI_EVENT_RDD_REPORT = 0x11,
MCU_UNI_EVENT_ROC = 0x27,
MCU_UNI_EVENT_TX_DONE = 0x2d,
MCU_UNI_EVENT_THERMAL = 0x35,
MCU_UNI_EVENT_NIC_CAPAB = 0x43,
MCU_UNI_EVENT_WED_RRO = 0x57,
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
};
@ -1088,6 +1100,13 @@ enum mcu_cipher_type {
MCU_CIPHER_GCMP_256,
MCU_CIPHER_WAPI,
MCU_CIPHER_BIP_CMAC_128,
MCU_CIPHER_BIP_CMAC_256,
MCU_CIPHER_BCN_PROT_CMAC_128,
MCU_CIPHER_BCN_PROT_CMAC_256,
MCU_CIPHER_BCN_PROT_GMAC_128,
MCU_CIPHER_BCN_PROT_GMAC_256,
MCU_CIPHER_BIP_GMAC_128,
MCU_CIPHER_BIP_GMAC_256,
};
enum {
@ -1240,6 +1259,7 @@ enum {
MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
MCU_UNI_CMD_THERMAL = 0x35,
MCU_UNI_CMD_VOW = 0x37,
MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
@ -1307,6 +1327,7 @@ enum {
UNI_BSS_INFO_RATE = 11,
UNI_BSS_INFO_QBSS = 15,
UNI_BSS_INFO_SEC = 16,
UNI_BSS_INFO_BCN_PROT = 17,
UNI_BSS_INFO_TXCMD = 18,
UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21,
@ -1325,7 +1346,7 @@ enum {
};
enum UNI_ALL_STA_INFO_TAG {
UNI_ALL_STA_TX_RATE,
UNI_ALL_STA_TXRX_RATE,
UNI_ALL_STA_TX_STAT,
UNI_ALL_STA_TXRX_ADM_STAT,
UNI_ALL_STA_TXRX_AIR_TIME,
@ -1768,6 +1789,12 @@ mt76_connac_mcu_get_cipher(int cipher)
return MCU_CIPHER_GCMP;
case WLAN_CIPHER_SUITE_GCMP_256:
return MCU_CIPHER_GCMP_256;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
return MCU_CIPHER_BIP_GMAC_128;
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
return MCU_CIPHER_BIP_GMAC_256;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
return MCU_CIPHER_BIP_CMAC_256;
case WLAN_CIPHER_SUITE_SMS4:
return MCU_CIPHER_WAPI;
default:

View File

@ -199,13 +199,14 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
ret = mt76_init_tx_queue(&dev->mphy, i, mt76_ac_to_hwq(i),
MT76x02_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
}
ret = mt76_init_tx_queue(&dev->mphy, MT_TXQ_PSD, MT_TX_HW_QUEUE_MGMT,
MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE, 0);
MT76x02_PSD_RING_SIZE, MT_TX_RING_BASE,
NULL, 0);
if (ret)
return ret;

View File

@ -9,18 +9,20 @@ static int
mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc, int ring_base)
{
struct mt7915_dev *dev = phy->dev;
struct mtk_wed_device *wed = NULL;
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
if (is_mt798x(&dev->mt76))
ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
else
ring_base = MT_WED_TX_RING_BASE;
idx -= MT_TXQ_ID(0);
wed = &dev->mt76.mmio.wed;
}
return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc, ring_base,
MT_WED_Q_TX(idx));
wed, MT_WED_Q_TX(idx));
}
static int mt7915_poll_tx(struct napi_struct *napi, int budget)
@ -492,7 +494,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (mtk_wed_device_active(&mdev->mmio.wed) && is_mt7915(mdev)) {
wa_rx_base = MT_WED_RX_RING_BASE;
wa_rx_idx = MT7915_RXQ_MCU_WA;
dev->mt76.q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
mdev->q_rx[MT_RXQ_MCU_WA].flags = MT_WED_Q_TXFREE;
mdev->q_rx[MT_RXQ_MCU_WA].wed = &mdev->mmio.wed;
} else {
wa_rx_base = MT_RXQ_RING_BASE(MT_RXQ_MCU_WA);
wa_rx_idx = MT_RXQ_ID(MT_RXQ_MCU_WA);
@ -507,9 +510,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (!dev->phy.mt76->band_idx) {
if (mtk_wed_device_active(&mdev->mmio.wed) &&
mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
dev->mt76.q_rx[MT_RXQ_MAIN].flags =
mdev->q_rx[MT_RXQ_MAIN].flags =
MT_WED_Q_RX(MT7915_RXQ_BAND0);
dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
mdev->q_rx[MT_RXQ_MAIN].wed = &mdev->mmio.wed;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
@ -528,6 +532,7 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (mtk_wed_device_active(&mdev->mmio.wed)) {
mdev->q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
mdev->q_rx[MT_RXQ_MAIN_WA].wed = &mdev->mmio.wed;
if (is_mt7916(mdev)) {
wa_rx_base = MT_WED_RX_RING_BASE;
wa_rx_idx = MT7915_RXQ_MCU_WA;
@ -544,9 +549,10 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (dev->dbdc_support || dev->phy.mt76->band_idx) {
if (mtk_wed_device_active(&mdev->mmio.wed) &&
mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
dev->mt76.q_rx[MT_RXQ_BAND1].flags =
mdev->q_rx[MT_RXQ_BAND1].flags =
MT_WED_Q_RX(MT7915_RXQ_BAND1);
dev->mt76.rx_token_size += MT7915_RX_RING_SIZE;
mdev->q_rx[MT_RXQ_BAND1].wed = &mdev->mmio.wed;
}
/* rx data queue for band1 */
@ -581,28 +587,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
return 0;
}
static void mt7915_dma_wed_reset(struct mt7915_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
if (!test_bit(MT76_STATE_WED_RESET, &dev->mphy.state))
return;
complete(&mdev->mmio.wed_reset);
if (!wait_for_completion_timeout(&dev->mt76.mmio.wed_reset_complete,
3 * HZ))
dev_err(dev->mt76.dev, "wed reset complete timeout\n");
}
static void
mt7915_dma_reset_tx_queue(struct mt7915_dev *dev, struct mt76_queue *q)
{
mt76_queue_reset(dev, q);
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mt76_dma_wed_setup(&dev->mt76, q, true);
}
int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
{
struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
@ -630,20 +614,20 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
mtk_wed_device_dma_reset(wed);
mt7915_dma_disable(dev, force);
mt7915_dma_wed_reset(dev);
mt76_dma_wed_reset(&dev->mt76);
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++) {
mt7915_dma_reset_tx_queue(dev, dev->mphy.q_tx[i]);
mt76_dma_reset_tx_queue(&dev->mt76, dev->mphy.q_tx[i]);
if (mphy_ext)
mt7915_dma_reset_tx_queue(dev, mphy_ext->q_tx[i]);
mt76_dma_reset_tx_queue(&dev->mt76, mphy_ext->q_tx[i]);
}
for (i = 0; i < __MT_MCUQ_MAX; i++)
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
mt76_for_each_q_rx(&dev->mt76, i) {
if (dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE)
if (mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
continue;
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);

View File

@ -11,6 +11,7 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
u8 *eeprom = mdev->eeprom.data;
u32 val = eeprom[MT_EE_DO_PRE_CAL];
u32 offs;
int ret;
if (!dev->flash_mode)
return 0;
@ -25,7 +26,11 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
return mt76_get_of_eeprom(mdev, dev->cal, offs, val);
ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, val);
if (!ret)
return ret;
return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", val);
}
static int mt7915_check_eeprom(struct mt7915_dev *dev)

View File

@ -144,7 +144,8 @@ static inline bool
mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
{
u8 *eep = dev->mt76.eeprom.data;
u8 val = eep[MT_EE_WIFI_CONF + 7];
u8 offs = is_mt7981(&dev->mt76) ? 8 : 7;
u8 val = eep[MT_EE_WIFI_CONF + offs];
if (band == NL80211_BAND_2GHZ)
return val & MT_EE_WIFI_CONF7_TSSI0_2G;

View File

@ -275,10 +275,11 @@ static void mt7915_led_set_brightness(struct led_classdev *led_cdev,
mt7915_led_set_config(led_cdev, 0xff, 0);
}
void mt7915_init_txpower(struct mt7915_dev *dev,
struct ieee80211_supported_band *sband)
static void __mt7915_init_txpower(struct mt7915_phy *phy,
struct ieee80211_supported_band *sband)
{
int i, n_chains = hweight8(dev->mphy.antenna_mask);
struct mt7915_dev *dev = phy->dev;
int i, n_chains = hweight16(phy->mt76->chainmask);
int nss_delta = mt76_tx_power_nss_delta(n_chains);
int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
struct mt76_power_limits limits;
@ -296,7 +297,7 @@ void mt7915_init_txpower(struct mt7915_dev *dev,
}
target_power += pwr_delta;
target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
target_power = mt76_get_rate_power_limits(phy->mt76, chan,
&limits,
target_power);
target_power += nss_delta;
@ -307,6 +308,19 @@ void mt7915_init_txpower(struct mt7915_dev *dev,
}
}
void mt7915_init_txpower(struct mt7915_phy *phy)
{
if (!phy)
return;
if (phy->mt76->cap.has_2ghz)
__mt7915_init_txpower(phy, &phy->mt76->sband_2g.sband);
if (phy->mt76->cap.has_5ghz)
__mt7915_init_txpower(phy, &phy->mt76->sband_5g.sband);
if (phy->mt76->cap.has_6ghz)
__mt7915_init_txpower(phy, &phy->mt76->sband_6g.sband);
}
static void
mt7915_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
@ -322,9 +336,7 @@ mt7915_regd_notifier(struct wiphy *wiphy,
if (dev->mt76.region == NL80211_DFS_UNSET)
mt7915_mcu_rdd_background_enable(phy, NULL);
mt7915_init_txpower(dev, &mphy->sband_2g.sband);
mt7915_init_txpower(dev, &mphy->sband_5g.sband);
mt7915_init_txpower(dev, &mphy->sband_6g.sband);
mt7915_init_txpower(phy);
mphy->dfs_state = MT_DFS_STATE_UNKNOWN;
mt7915_dfs_init_radar_detector(phy);
@ -442,6 +454,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
mt76_set_stream_caps(phy->mt76, true);
mt7915_set_stream_vht_txbf_caps(phy);
mt7915_set_stream_he_caps(phy);
mt7915_init_txpower(phy);
wiphy->available_antennas_rx = phy->mt76->antenna_mask;
wiphy->available_antennas_tx = phy->mt76->antenna_mask;
@ -703,9 +716,6 @@ static void mt7915_init_work(struct work_struct *work)
mt7915_mcu_set_eeprom(dev);
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);
}

View File

@ -1247,7 +1247,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
void mt7915_update_channel(struct mt76_phy *mphy)
{
struct mt7915_phy *phy = (struct mt7915_phy *)mphy->priv;
struct mt7915_phy *phy = mphy->priv;
struct mt76_channel_state *state = mphy->chan_state;
int nf;
@ -1401,8 +1401,8 @@ mt7915_mac_restart(struct mt7915_dev *dev)
goto out;
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->phy);
mt7915_init_txpower(phy2);
ret = mt7915_txbf_init(dev);
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {

View File

@ -1059,8 +1059,9 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
phy->mt76->antenna_mask = tx_ant;
/* handle a variant of mt7916 which has 3T3R but nss2 on 5 GHz band */
if (is_mt7916(&dev->mt76) && band && hweight8(tx_ant) == max_nss)
/* handle a variant of mt7916/mt7981 which has 3T3R but nss2 on 5 GHz band */
if ((is_mt7916(&dev->mt76) || is_mt7981(&dev->mt76)) &&
band && hweight8(tx_ant) == max_nss)
phy->mt76->chainmask = (dev->chainmask >> chainshift) << chainshift;
else
phy->mt76->chainmask = tx_ant << (chainshift * band);
@ -1653,20 +1654,6 @@ mt7915_net_fill_forward_path(struct ieee80211_hw *hw,
return 0;
}
static int
mt7915_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
if (!mtk_wed_device_active(wed))
return -EOPNOTSUPP;
return mtk_wed_device_setup_tc(wed, netdev, type, type_data);
}
#endif
const struct ieee80211_ops mt7915_ops = {
@ -1721,6 +1708,6 @@ const struct ieee80211_ops mt7915_ops = {
.set_radar_background = mt7915_set_radar_background,
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
.net_fill_forward_path = mt7915_net_fill_forward_path,
.net_setup_tc = mt7915_net_setup_tc,
.net_setup_tc = mt76_net_setup_tc,
#endif
};

View File

@ -269,7 +269,7 @@ mt7915_mcu_rx_thermal_notify(struct mt7915_dev *dev, struct sk_buff *skb)
dev->mt76.phys[MT_BAND1])
mphy = dev->mt76.phys[MT_BAND1];
phy = (struct mt7915_phy *)mphy->priv;
phy = mphy->priv;
phy->throttle_state = t->ctrl.duty.duty_cycle;
}

View File

@ -519,7 +519,7 @@ static inline s8
mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
{
struct mt76_phy *mphy = phy->mt76;
int n_chains = hweight8(mphy->antenna_mask);
int n_chains = hweight16(mphy->chainmask);
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
txpower -= mt76_tx_power_nss_delta(n_chains);

View File

@ -542,105 +542,6 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
static int mt7915_mmio_wed_offload_enable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
spin_lock_bh(&dev->mt76.token_lock);
dev->mt76.token_size = wed->wlan.token_start;
spin_unlock_bh(&dev->mt76.token_lock);
return !wait_event_timeout(dev->mt76.tx_wait,
!dev->mt76.wed_token_count, HZ);
}
static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
spin_lock_bh(&dev->mt76.token_lock);
dev->mt76.token_size = MT7915_TOKEN_SIZE;
spin_unlock_bh(&dev->mt76.token_lock);
}
static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
{
struct mt7915_dev *dev;
int i;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
for (i = 0; i < dev->mt76.rx_token_size; i++) {
struct mt76_txwi_cache *t;
t = mt76_rx_token_release(&dev->mt76, i);
if (!t || !t->ptr)
continue;
mt76_put_page_pool_buf(t->ptr, false);
t->ptr = NULL;
mt76_put_rxwi(&dev->mt76, t);
}
mt76_free_pending_rxwi(&dev->mt76);
}
static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
{
struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
struct mt76_txwi_cache *t = NULL;
struct mt7915_dev *dev;
struct mt76_queue *q;
int i, len;
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
q = &dev->mt76.q_rx[MT_RXQ_MAIN];
len = SKB_WITH_OVERHEAD(q->buf_size);
for (i = 0; i < size; i++) {
enum dma_data_direction dir;
dma_addr_t addr;
u32 offset;
int token;
void *buf;
t = mt76_get_rxwi(&dev->mt76);
if (!t)
goto unmap;
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
if (!buf)
goto unmap;
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
dir = page_pool_get_dma_dir(q->page_pool);
dma_sync_single_for_device(dev->mt76.dma_dev, addr, len, dir);
desc->buf0 = cpu_to_le32(addr);
token = mt76_rx_token_consume(&dev->mt76, buf, t, addr);
if (token < 0) {
mt76_put_page_pool_buf(buf, false);
goto unmap;
}
desc->token |= cpu_to_le32(FIELD_PREP(MT_DMA_CTL_TOKEN,
token));
desc++;
}
return 0;
unmap:
if (t)
mt76_put_rxwi(&dev->mt76, t);
mt7915_mmio_wed_release_rx_buf(wed);
return -ENOMEM;
}
static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed,
struct mtk_wed_wo_rx_stats *stats)
{
@ -694,13 +595,6 @@ out:
return ret;
}
static void mt7915_mmio_wed_reset_complete(struct mtk_wed_device *wed)
{
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
complete(&dev->mmio.wed_reset_complete);
}
#endif
int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
@ -742,7 +636,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
if (!res)
return -ENOMEM;
return 0;
wed->wlan.platform_dev = plat_dev;
wed->wlan.bus_type = MTK_WED_BUS_AXI;
@ -778,13 +672,13 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
}
wed->wlan.init_buf = mt7915_wed_init_buf;
wed->wlan.offload_enable = mt7915_mmio_wed_offload_enable;
wed->wlan.offload_disable = mt7915_mmio_wed_offload_disable;
wed->wlan.init_rx_buf = mt7915_mmio_wed_init_rx_buf;
wed->wlan.release_rx_buf = mt7915_mmio_wed_release_rx_buf;
wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
wed->wlan.update_wo_rx_stats = mt7915_mmio_wed_update_rx_stats;
wed->wlan.reset = mt7915_mmio_wed_reset;
wed->wlan.reset_complete = mt7915_mmio_wed_reset_complete;
wed->wlan.reset_complete = mt76_mmio_wed_reset_complete;
dev->mt76.rx_token_size = wed->wlan.rx_npkt;

View File

@ -425,8 +425,7 @@ void mt7915_dma_cleanup(struct mt7915_dev *dev);
int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
int mt7915_dma_start(struct mt7915_dev *dev, bool reset, bool wed_reset);
int mt7915_txbf_init(struct mt7915_dev *dev);
void mt7915_init_txpower(struct mt7915_dev *dev,
struct ieee80211_supported_band *sband);
void mt7915_init_txpower(struct mt7915_phy *phy);
void mt7915_reset(struct mt7915_dev *dev);
int mt7915_run(struct ieee80211_hw *hw);
int mt7915_mcu_init(struct mt7915_dev *dev);

View File

@ -1282,13 +1282,11 @@ free_device:
return ret;
}
static int mt798x_wmac_remove(struct platform_device *pdev)
static void mt798x_wmac_remove(struct platform_device *pdev)
{
struct mt7915_dev *dev = platform_get_drvdata(pdev);
mt7915_unregister_device(dev);
return 0;
}
static const struct of_device_id mt798x_wmac_of_match[] = {
@ -1305,7 +1303,7 @@ struct platform_driver mt798x_wmac_driver = {
.of_match_table = mt798x_wmac_of_match,
},
.probe = mt798x_wmac_probe,
.remove = mt798x_wmac_remove,
.remove_new = mt798x_wmac_remove,
};
MODULE_FIRMWARE(MT7986_FIRMWARE_WA);

View File

@ -110,24 +110,37 @@ mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
}
}
void mt7921_regd_update(struct mt792x_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
mt7921_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env);
mt7921_regd_channel_update(wiphy, dev);
mt76_connac_mcu_set_channel_domain(hw->priv);
mt7921_set_tx_sar_pwr(hw, NULL);
}
EXPORT_SYMBOL_GPL(mt7921_regd_update);
static void
mt7921_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt792x_dev *dev = mt792x_hw_dev(hw);
struct mt76_connac_pm *pm = &dev->pm;
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;
dev->country_ie_env = request->country_ie_env;
mt792x_mutex_acquire(dev);
mt7921_mcu_set_clc(dev, request->alpha2, request->country_ie_env);
mt76_connac_mcu_set_channel_domain(hw->priv);
mt7921_set_tx_sar_pwr(hw, NULL);
mt792x_mutex_release(dev);
if (pm->suspended)
return;
mt7921_regd_channel_update(wiphy, dev);
mt792x_mutex_acquire(dev);
mt7921_regd_update(dev);
mt792x_mutex_release(dev);
}
int mt7921_mac_init(struct mt792x_dev *dev)

View File

@ -683,17 +683,45 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
}
static void
mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif)
mt7921_calc_vif_num(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
u32 *num = priv;
if (!priv)
return;
switch (vif->type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
*num += 1;
break;
default:
break;
}
}
static void
mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add)
{
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
struct mt792x_phy *phy = mvif->phy;
struct mt792x_dev *dev = phy->dev;
u32 valid_vif_num = 0;
if (hweight64(dev->mt76.vif_mask) > 1) {
ieee80211_iterate_active_interfaces(mt76_hw(dev),
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7921_calc_vif_num, &valid_vif_num);
if (valid_vif_num > 1) {
phy->power_type = MT_AP_DEFAULT;
goto out;
}
if (!is_add)
vif->bss_conf.power_type = IEEE80211_REG_UNSET_AP;
switch (vif->bss_conf.power_type) {
case IEEE80211_REG_SP_AP:
phy->power_type = MT_AP_SP;
@ -705,6 +733,8 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif)
phy->power_type = MT_AP_LPI;
break;
case IEEE80211_REG_UNSET_AP:
phy->power_type = MT_AP_UNSET;
break;
default:
phy->power_type = MT_AP_DEFAULT;
break;
@ -749,7 +779,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
if (ret)
return ret;
mt7921_regd_set_6ghz_power_type(vif);
mt7921_regd_set_6ghz_power_type(vif, true);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
@ -811,6 +841,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
list_del_init(&msta->wcid.poll_list);
spin_unlock_bh(&dev->mt76.sta_poll_lock);
mt7921_regd_set_6ghz_power_type(vif, false);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove);

View File

@ -160,7 +160,7 @@ static void
mt7921_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
struct mt792x_phy *phy = mphy->priv;
spin_lock_bh(&dev->mt76.lock);
__skb_queue_tail(&phy->scan_event_list, skb);
@ -1260,15 +1260,19 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
u8 alpha2[2];
u8 type[2];
u8 env_6g;
u8 rsvd[63];
u8 mtcl_conf;
u8 rsvd[62];
} __packed req = {
.ver = 1,
.idx = idx,
.env = env_cap,
.env_6g = dev->phy.power_type,
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
.mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2),
};
int ret, valid_cnt = 0;
u8 i, *pos;
u16 buf_len = 0;
u8 *pos;
if (!clc)
return 0;
@ -1278,12 +1282,15 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
if (mt76_find_power_limits_node(&dev->mt76))
req.cap |= CLC_CAP_DTS_EN;
buf_len = le16_to_cpu(clc->len) - sizeof(*clc);
pos = clc->data;
for (i = 0; i < clc->nr_country; i++) {
while (buf_len > 16) {
struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;
u16 len = le16_to_cpu(rule->len);
u16 offset = len + sizeof(*rule);
pos += len + sizeof(*rule);
pos += offset;
buf_len -= offset;
if (rule->alpha2[0] != alpha2[0] ||
rule->alpha2[1] != alpha2[1])
continue;

View File

@ -12,7 +12,8 @@
#define MT7921_TX_FWDL_RING_SIZE 128
#define MT7921_RX_RING_SIZE 1536
#define MT7921_RX_MCU_RING_SIZE 512
#define MT7921_RX_MCU_RING_SIZE 8
#define MT7921_RX_MCU_WA_RING_SIZE 512
#define MT7921_EEPROM_SIZE 3584
#define MT7921_TOKEN_SIZE 8192
@ -233,6 +234,7 @@ mt7921_l1_rmw(struct mt792x_dev *dev, u32 addr, u32 mask, u32 val)
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
void mt7921_regd_update(struct mt792x_dev *dev);
int mt7921_mac_init(struct mt792x_dev *dev);
bool mt7921_mac_wtbl_update(struct mt792x_dev *dev, int idx, u32 mask);
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,

View File

@ -171,7 +171,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev)
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;
@ -200,7 +200,7 @@ static int mt7921_dma_init(struct mt792x_dev *dev)
/* Change mcu queue after firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
MT7921_RX_MCU_WA_RING_SIZE,
MT_RX_BUF_SIZE, MT_WFDMA0(0x540));
if (ret)
return ret;
@ -507,6 +507,9 @@ static int mt7921_pci_resume(struct device *device)
mt76_connac_mcu_set_deep_sleep(&dev->mt76, false);
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
mt7921_regd_update(dev);
failed:
pm->suspended = false;

View File

@ -228,7 +228,7 @@ static int mt7921s_suspend(struct device *__dev)
mt76_txq_schedule_all(&dev->mphy);
mt76_worker_disable(&mdev->tx_worker);
mt76_worker_disable(&mdev->sdio.status_worker);
cancel_work_sync(&mdev->sdio.stat_work);
mt76_worker_disable(&mdev->sdio.stat_worker);
clear_bit(MT76_READING_STATS, &dev->mphy.state);
mt76_tx_status_check(mdev, true);
@ -260,6 +260,7 @@ restore_txrx_worker:
restore_worker:
mt76_worker_enable(&mdev->tx_worker);
mt76_worker_enable(&mdev->sdio.status_worker);
mt76_worker_enable(&mdev->sdio.stat_worker);
if (!pm->ds_enable)
mt76_connac_mcu_set_deep_sleep(mdev, false);
@ -292,6 +293,7 @@ static int mt7921s_resume(struct device *__dev)
mt76_worker_enable(&mdev->sdio.txrx_worker);
mt76_worker_enable(&mdev->sdio.status_worker);
mt76_worker_enable(&mdev->sdio.net_worker);
mt76_worker_enable(&mdev->sdio.stat_worker);
/* restore previous ds setting */
if (!pm->ds_enable)

View File

@ -107,7 +107,7 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)
mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
mt76_worker_disable(&dev->mt76.sdio.status_worker);
mt76_worker_disable(&dev->mt76.sdio.net_worker);
cancel_work_sync(&dev->mt76.sdio.stat_work);
mt76_worker_disable(&dev->mt76.sdio.stat_worker);
mt7921s_disable_irq(&dev->mt76);
mt7921s_wfsys_reset(dev);
@ -115,6 +115,7 @@ int mt7921s_mac_reset(struct mt792x_dev *dev)
mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
mt76_worker_enable(&dev->mt76.sdio.status_worker);
mt76_worker_enable(&dev->mt76.sdio.net_worker);
mt76_worker_enable(&dev->mt76.sdio.stat_worker);
dev->fw_assert = false;
clear_bit(MT76_MCU_RESET, &dev->mphy.state);

View File

@ -154,8 +154,7 @@ mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,
static void
mt7925_init_eht_caps(struct mt792x_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data,
enum nl80211_iftype iftype)
struct ieee80211_sband_iftype_data *data)
{
struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap;
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
@ -256,7 +255,7 @@ __mt7925_set_stream_he_eht_caps(struct mt792x_phy *phy,
data[n].types_mask = BIT(i);
mt7925_init_he_caps(phy, band, &data[n], i);
mt7925_init_eht_caps(phy, band, &data[n], i);
mt7925_init_eht_caps(phy, band, &data[n]);
n++;
}

View File

@ -345,7 +345,7 @@ static void
mt7925_mcu_scan_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
struct mt792x_phy *phy = mphy->priv;
spin_lock_bh(&dev->mt76.lock);
__skb_queue_tail(&phy->scan_event_list, skb);

View File

@ -218,7 +218,7 @@ static int mt7925_dma_init(struct mt792x_dev *dev)
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7925_TXQ_BAND0,
MT7925_TX_RING_SIZE,
MT_TX_RING_BASE, 0);
MT_TX_RING_BASE, NULL, 0);
if (ret)
return ret;

View File

@ -382,6 +382,7 @@ int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev);
int mt792x_init_acpi_sar(struct mt792x_dev *dev);
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default);
u8 mt792x_acpi_get_flags(struct mt792x_phy *phy);
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2);
#else
static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev)
{
@ -398,6 +399,11 @@ static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
{
return 0;
}
static inline u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
{
return 0xf;
}
#endif
#endif /* __MT7925_H */

View File

@ -348,3 +348,56 @@ u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
return flags;
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
static u8
mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
{
u8 config = 0;
if (cl->cl6g[row] & BIT(column))
config |= (cl->mode_6g & 0x3) << 2;
if (cl->version > 1 && cl->cl5g9[row] & BIT(column))
config |= (cl->mode_5g9 & 0x3);
return config;
}
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
{
static const char * const cc_list_all[] = {
"00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
"CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
"MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
"TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
};
static const char * const cc_list_eu[] = {
"AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE",
"FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT",
"LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL",
"PT", "RO", "MT", "SK", "SI", "ES", "CH",
};
struct mt792x_acpi_sar *sar = phy->acpisar;
struct mt792x_asar_cl *cl;
int col, row, i;
if (!sar)
return 0xf;
cl = sar->countrylist;
if (!cl)
return 0xc;
for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) {
col = 7 - i % 8;
row = i / 8;
if (!memcmp(cc_list_all[i], alpha2, 2))
return mt792x_acpi_get_mtcl_map(row, col, cl);
}
for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++)
if (!memcmp(cc_list_eu[i], alpha2, 2))
return mt792x_acpi_get_mtcl_map(0, 6, cl);
return mt792x_acpi_get_mtcl_map(0, 7, cl);
}
EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf);

View File

@ -77,6 +77,8 @@ struct mt792x_asar_cl {
u8 version;
u8 mode_6g;
u8 cl6g[6];
u8 mode_5g9;
u8 cl5g9[6];
} __packed;
struct mt792x_asar_fg {

View File

@ -223,7 +223,7 @@ static void
mt792x_phy_update_channel(struct mt76_phy *mphy, int idx)
{
struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
struct mt792x_phy *phy = mphy->priv;
struct mt76_channel_state *state;
u64 busy_time, tx_time, rx_time, obss_time;
int nf;

View File

@ -476,7 +476,7 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
{
struct mt76_mib_stats *mib = &phy->mib;
static const char * const bw[] = {
"BW20", "BW40", "BW80", "BW160"
"BW20", "BW40", "BW80", "BW160", "BW320"
};
/* Tx Beamformer monitor */
@ -489,8 +489,9 @@ mt7996_txbf_stat_read_phy(struct mt7996_phy *phy, struct seq_file *s)
/* Tx Beamformer Rx feedback monitor */
seq_puts(s, "Tx Beamformer Rx feedback statistics: ");
seq_printf(s, "All: %d, HE: %d, VHT: %d, HT: %d, ",
seq_printf(s, "All: %d, EHT: %d, HE: %d, VHT: %d, HT: %d, ",
mib->tx_bf_rx_fb_all_cnt,
mib->tx_bf_rx_fb_eht_cnt,
mib->tx_bf_rx_fb_he_cnt,
mib->tx_bf_rx_fb_vht_cnt,
mib->tx_bf_rx_fb_ht_cnt);

View File

@ -7,6 +7,26 @@
#include "../dma.h"
#include "mac.h"
int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx, int n_desc,
int ring_base, struct mtk_wed_device *wed)
{
struct mt7996_dev *dev = phy->dev;
u32 flags = 0;
if (mtk_wed_device_active(wed)) {
ring_base += MT_TXQ_ID(0) * MT_RING_SIZE;
idx -= MT_TXQ_ID(0);
if (phy->mt76->band_idx == MT_BAND2)
flags = MT_WED_Q_TX(0);
else
flags = MT_WED_Q_TX(idx);
}
return mt76_connac_init_tx_queues(phy->mt76, idx, n_desc,
ring_base, wed, flags);
}
static int mt7996_poll_tx(struct napi_struct *napi, int budget)
{
struct mt7996_dev *dev;
@ -37,18 +57,51 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7996_RXQ_MCU_WM);
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7996_RXQ_MCU_WA);
/* band0/band1 */
/* mt7996: band0 and band1, mt7992: band0 */
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7996_RXQ_BAND0);
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN, MT7996_RXQ_MCU_WA_MAIN);
/* band2 */
RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
if (is_mt7996(&dev->mt76)) {
/* mt7996 band2 */
RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
} else {
/* mt7992 band1 */
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1);
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT, MT7996_RXQ_MCU_WA_EXT);
}
if (dev->has_rro) {
/* band0 */
RXQ_CONFIG(MT_RXQ_RRO_BAND0, WFDMA0, MT_INT_RX_DONE_RRO_BAND0,
MT7996_RXQ_RRO_BAND0);
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND0, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND0,
MT7996_RXQ_MSDU_PG_BAND0);
RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0, MT_INT_RX_TXFREE_MAIN,
MT7996_RXQ_TXFREE0);
/* band1 */
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND1, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND1,
MT7996_RXQ_MSDU_PG_BAND1);
/* band2 */
RXQ_CONFIG(MT_RXQ_RRO_BAND2, WFDMA0, MT_INT_RX_DONE_RRO_BAND2,
MT7996_RXQ_RRO_BAND2);
RXQ_CONFIG(MT_RXQ_MSDU_PAGE_BAND2, WFDMA0, MT_INT_RX_DONE_MSDU_PG_BAND2,
MT7996_RXQ_MSDU_PG_BAND2);
RXQ_CONFIG(MT_RXQ_TXFREE_BAND2, WFDMA0, MT_INT_RX_TXFREE_TRI,
MT7996_RXQ_TXFREE2);
RXQ_CONFIG(MT_RXQ_RRO_IND, WFDMA0, MT_INT_RX_DONE_RRO_IND,
MT7996_RXQ_RRO_IND);
}
/* data tx queue */
TXQ_CONFIG(0, WFDMA0, MT_INT_TX_DONE_BAND0, MT7996_TXQ_BAND0);
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
if (is_mt7996(&dev->mt76)) {
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
TXQ_CONFIG(2, WFDMA0, MT_INT_TX_DONE_BAND2, MT7996_TXQ_BAND2);
} else {
TXQ_CONFIG(1, WFDMA0, MT_INT_TX_DONE_BAND1, MT7996_TXQ_BAND1);
}
/* mcu tx queue */
MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM);
@ -56,22 +109,57 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7996_TXQ_FWDL);
}
static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth)
{
u32 ret = *base << 16 | depth;
*base = *base + (depth << 4);
return ret;
}
static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
{
#define PREFETCH(_base, _depth) ((_base) << 16 | (_depth))
u16 base = 0;
u8 queue;
#define PREFETCH(_depth) (__mt7996_dma_prefetch_base(&base, (_depth)))
/* prefetch SRAM wrapping boundary for tx/rx ring. */
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x0, 0x2));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x20, 0x2));
mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0xc0, 0x2));
mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0xe0, 0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x120, 0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x140, 0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x160, 0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2_WA) + ofs, PREFETCH(0x180, 0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x1a0, 0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_BAND2) + ofs, PREFETCH(0x2a0, 0x10));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x8));
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8));
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x2));
queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2_WA : MT_RXQ_BAND1_WA;
mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x2));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2 : MT_RXQ_BAND1;
mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x10));
if (dev->has_rro) {
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
PREFETCH(0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
PREFETCH(0x10));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
PREFETCH(0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
PREFETCH(0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
PREFETCH(0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
PREFETCH(0x4));
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
PREFETCH(0x4));
}
#undef PREFETCH
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1 + ofs, WF_WFDMA0_GLO_CFG_EXT1_CALC_MODE);
}
@ -128,8 +216,9 @@ static void mt7996_dma_disable(struct mt7996_dev *dev, bool reset)
}
}
void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
{
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 hif1_ofs = 0;
u32 irq_mask;
@ -138,37 +227,49 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset)
/* enable WFDMA Tx/Rx */
if (!reset) {
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed))
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_EXT_EN);
else
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
if (dev->hif2)
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
MT_WFDMA0_GLO_CFG_EXT_EN);
}
/* enable interrupts for TX/RX rings */
irq_mask = MT_INT_MCU_CMD;
if (reset)
goto done;
irq_mask = MT_INT_MCU_CMD | MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
irq_mask = MT_INT_RX_DONE_MCU | MT_INT_TX_DONE_MCU;
if (!dev->mphy.band_idx)
if (mt7996_band_valid(dev, MT_BAND0))
irq_mask |= MT_INT_BAND0_RX_DONE;
if (dev->dbdc_support)
if (mt7996_band_valid(dev, MT_BAND1))
irq_mask |= MT_INT_BAND1_RX_DONE;
if (dev->tbtc_support)
if (mt7996_band_valid(dev, MT_BAND2))
irq_mask |= MT_INT_BAND2_RX_DONE;
done:
if (mtk_wed_device_active(wed) && wed_reset) {
u32 wed_irq_mask = irq_mask;
wed_irq_mask |= MT_INT_TX_DONE_BAND0 | MT_INT_TX_DONE_BAND1;
mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
mtk_wed_device_start(wed, wed_irq_mask);
}
irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
mt7996_irq_enable(dev, irq_mask);
mt7996_irq_disable(dev, 0);
}
@ -223,6 +324,12 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT1,
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
/* WFDMA rx threshold */
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH, 0xc000c);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH, 0x10008);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_89_TH, 0x10008);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_RRO_TH, 0x20);
if (dev->hif2) {
/* GLO_CFG_EXT0 */
mt76_set(dev, WF_WFDMA0_GLO_CFG_EXT0 + hif1_ofs,
@ -234,24 +341,108 @@ static void mt7996_dma_enable(struct mt7996_dev *dev, bool reset)
WF_WFDMA0_GLO_CFG_EXT1_TX_FCTRL_MODE);
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_PDMA_BAND);
MT_WFDMA_HOST_CONFIG_PDMA_BAND |
MT_WFDMA_HOST_CONFIG_BAND2_PCIE1);
/* AXI read outstanding number */
mt76_rmw(dev, MT_WFDMA_AXI_R2A_CTRL,
MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK, 0x14);
/* WFDMA rx threshold */
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_45_TH + hif1_ofs, 0xc000c);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_67_TH + hif1_ofs, 0x10008);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_89_TH + hif1_ofs, 0x10008);
mt76_wr(dev, MT_WFDMA0_PAUSE_RX_Q_RRO_TH + hif1_ofs, 0x20);
}
if (dev->hif2) {
/* fix hardware limitation, pcie1's rx ring3 is not available
* so, redirect pcie0 rx ring3 interrupt to pcie1
*/
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
MT_WFDMA0_RX_INT_SEL_RING3);
/* TODO: redirect rx ring6 interrupt to pcie0 for wed function */
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
dev->has_rro)
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL + hif1_ofs,
MT_WFDMA0_RX_INT_SEL_RING6);
else
mt76_set(dev, MT_WFDMA0_RX_INT_PCIE_SEL,
MT_WFDMA0_RX_INT_SEL_RING3);
}
mt7996_dma_start(dev, reset);
mt7996_dma_start(dev, reset, true);
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt7996_dma_rro_init(struct mt7996_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
u32 irq_mask;
int ret;
/* ind cmd */
mdev->q_rx[MT_RXQ_RRO_IND].flags = MT_WED_RRO_Q_IND;
mdev->q_rx[MT_RXQ_RRO_IND].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_RRO_IND],
MT_RXQ_ID(MT_RXQ_RRO_IND),
MT7996_RX_RING_SIZE,
0, MT_RXQ_RRO_IND_RING_BASE);
if (ret)
return ret;
/* rx msdu page queue for band0 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].flags =
MT_WED_RRO_Q_MSDU_PG(0) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND0],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND0),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND0));
if (ret)
return ret;
if (mt7996_band_valid(dev, MT_BAND1)) {
/* rx msdu page queue for band1 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].flags =
MT_WED_RRO_Q_MSDU_PG(1) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND1],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND1),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND1));
if (ret)
return ret;
}
if (mt7996_band_valid(dev, MT_BAND2)) {
/* rx msdu page queue for band2 */
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].flags =
MT_WED_RRO_Q_MSDU_PG(2) | MT_QFLAG_WED_RRO_EN;
mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2].wed = &mdev->mmio.wed;
ret = mt76_queue_alloc(dev, &mdev->q_rx[MT_RXQ_MSDU_PAGE_BAND2],
MT_RXQ_ID(MT_RXQ_MSDU_PAGE_BAND2),
MT7996_RX_RING_SIZE,
MT7996_RX_MSDU_PAGE_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_MSDU_PAGE_BAND2));
if (ret)
return ret;
}
irq_mask = mdev->mmio.irqmask | MT_INT_RRO_RX_DONE |
MT_INT_TX_DONE_BAND2;
mt76_wr(dev, MT_INT_MASK_CSR, irq_mask);
mtk_wed_device_start_hw_rro(&mdev->mmio.wed, irq_mask, false);
mt7996_irq_enable(dev, irq_mask);
return 0;
}
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
int mt7996_dma_init(struct mt7996_dev *dev)
{
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
u32 rx_base;
u32 hif1_ofs = 0;
int ret;
@ -265,10 +456,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
mt7996_dma_disable(dev, true);
/* init tx queue */
ret = mt76_connac_init_tx_queues(dev->phy.mt76,
MT_TXQ_ID(dev->mphy.band_idx),
MT7996_TX_RING_SIZE,
MT_TXQ_RING_BASE(0), 0);
ret = mt7996_init_tx_queues(&dev->phy,
MT_TXQ_ID(dev->mphy.band_idx),
MT7996_TX_RING_SIZE,
MT_TXQ_RING_BASE(0),
wed);
if (ret)
return ret;
@ -314,7 +506,12 @@ int mt7996_dma_init(struct mt7996_dev *dev)
if (ret)
return ret;
/* rx data queue for band0 and band1 */
/* rx data queue for band0 and mt7996 band1 */
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed)) {
dev->mt76.q_rx[MT_RXQ_MAIN].flags = MT_WED_Q_RX(0);
dev->mt76.q_rx[MT_RXQ_MAIN].wed = wed;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT_RXQ_ID(MT_RXQ_MAIN),
MT7996_RX_RING_SIZE,
@ -324,6 +521,11 @@ int mt7996_dma_init(struct mt7996_dev *dev)
return ret;
/* tx free notify event from WA for band0 */
if (mtk_wed_device_active(wed) && !dev->has_rro) {
dev->mt76.q_rx[MT_RXQ_MAIN_WA].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
MT_RXQ_ID(MT_RXQ_MAIN_WA),
MT7996_RX_MCU_RING_SIZE,
@ -332,19 +534,25 @@ int mt7996_dma_init(struct mt7996_dev *dev)
if (ret)
return ret;
if (dev->tbtc_support || dev->mphy.band_idx == MT_BAND2) {
/* rx data queue for band2 */
if (mt7996_band_valid(dev, MT_BAND2)) {
/* rx data queue for mt7996 band2 */
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2],
MT_RXQ_ID(MT_RXQ_BAND2),
MT7996_RX_RING_SIZE,
MT_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_BAND2) + hif1_ofs);
rx_base);
if (ret)
return ret;
/* tx free notify event from WA for band2
/* tx free notify event from WA for mt7996 band2
* use pcie0's rx ring3, but, redirect pcie0 rx ring3 interrupt to pcie1
*/
if (mtk_wed_device_active(wed_hif2) && !dev->has_rro) {
dev->mt76.q_rx[MT_RXQ_BAND2_WA].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_BAND2_WA].wed = wed_hif2;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND2_WA],
MT_RXQ_ID(MT_RXQ_BAND2_WA),
MT7996_RX_MCU_RING_SIZE,
@ -352,6 +560,80 @@ int mt7996_dma_init(struct mt7996_dev *dev)
MT_RXQ_RING_BASE(MT_RXQ_BAND2_WA));
if (ret)
return ret;
} else if (mt7996_band_valid(dev, MT_BAND1)) {
/* rx data queue for mt7992 band1 */
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1) + hif1_ofs;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1],
MT_RXQ_ID(MT_RXQ_BAND1),
MT7996_RX_RING_SIZE,
MT_RX_BUF_SIZE,
rx_base);
if (ret)
return ret;
/* tx free notify event from WA for mt7992 band1 */
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
MT_RXQ_ID(MT_RXQ_BAND1_WA),
MT7996_RX_MCU_RING_SIZE,
MT_RX_BUF_SIZE,
rx_base);
if (ret)
return ret;
}
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
dev->has_rro) {
/* rx rro data queue for band0 */
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].flags =
MT_WED_RRO_Q_DATA(0) | MT_QFLAG_WED_RRO_EN;
dev->mt76.q_rx[MT_RXQ_RRO_BAND0].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND0],
MT_RXQ_ID(MT_RXQ_RRO_BAND0),
MT7996_RX_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND0));
if (ret)
return ret;
/* tx free notify event from WA for band0 */
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
MT7996_RX_MCU_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
if (ret)
return ret;
if (mt7996_band_valid(dev, MT_BAND2)) {
/* rx rro data queue for band2 */
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].flags =
MT_WED_RRO_Q_DATA(1) | MT_QFLAG_WED_RRO_EN;
dev->mt76.q_rx[MT_RXQ_RRO_BAND2].wed = wed;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_RRO_BAND2],
MT_RXQ_ID(MT_RXQ_RRO_BAND2),
MT7996_RX_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_RRO_BAND2) + hif1_ofs);
if (ret)
return ret;
/* tx free notify event from MAC for band2 */
if (mtk_wed_device_active(wed_hif2)) {
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].flags = MT_WED_Q_TXFREE;
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2].wed = wed_hif2;
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND2],
MT_RXQ_ID(MT_RXQ_TXFREE_BAND2),
MT7996_RX_MCU_RING_SIZE,
MT7996_RX_BUF_SIZE,
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND2) + hif1_ofs);
if (ret)
return ret;
}
}
ret = mt76_init_queues(dev, mt76_dma_rx_poll);
@ -405,21 +687,33 @@ void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
if (force)
mt7996_wfsys_reset(dev);
if (dev->hif2 && mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_dma_reset(&dev->mt76.mmio.wed_hif2);
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_dma_reset(&dev->mt76.mmio.wed);
mt7996_dma_disable(dev, force);
mt76_dma_wed_reset(&dev->mt76);
/* reset hw queues */
for (i = 0; i < __MT_TXQ_MAX; i++) {
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
mt76_dma_reset_tx_queue(&dev->mt76, dev->mphy.q_tx[i]);
if (phy2)
mt76_queue_reset(dev, phy2->q_tx[i]);
mt76_dma_reset_tx_queue(&dev->mt76, phy2->q_tx[i]);
if (phy3)
mt76_queue_reset(dev, phy3->q_tx[i]);
mt76_dma_reset_tx_queue(&dev->mt76, phy3->q_tx[i]);
}
for (i = 0; i < __MT_MCUQ_MAX; i++)
mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
mt76_for_each_q_rx(&dev->mt76, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
if (mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]) ||
mt76_queue_is_wed_tx_free(&dev->mt76.q_rx[i]))
continue;
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
}

View File

@ -14,7 +14,9 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
switch (val) {
case 0x7990:
return 0;
return is_mt7996(&dev->mt76) ? 0 : -EINVAL;
case 0x7992:
return is_mt7992(&dev->mt76) ? 0 : -EINVAL;
default:
return -EINVAL;
}
@ -22,8 +24,14 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
static char *mt7996_eeprom_name(struct mt7996_dev *dev)
{
/* reserve for future variants */
return MT7996_EEPROM_DEFAULT;
switch (mt76_chip(&dev->mt76)) {
case 0x7990:
return MT7996_EEPROM_DEFAULT;
case 0x7992:
return MT7992_EEPROM_DEFAULT;
default:
return MT7996_EEPROM_DEFAULT;
}
}
static int
@ -103,7 +111,8 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
}
if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4)
if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4 ||
is_mt7992(&dev->mt76))
dev->wtbl_size_group = 2; /* set default */
return 0;
@ -148,36 +157,49 @@ static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
{
u8 path, nss, band_idx = phy->mt76->band_idx;
u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;
u8 *eeprom = dev->mt76.eeprom.data;
struct mt76_phy *mphy = phy->mt76;
int max_path = 5, max_nss = 4;
int ret;
switch (band_idx) {
case MT_BAND1:
path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,
eeprom[MT_EE_WIFI_CONF + 2]);
rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,
eeprom[MT_EE_WIFI_CONF + 3]);
nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,
eeprom[MT_EE_WIFI_CONF + 5]);
break;
case MT_BAND2:
path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,
eeprom[MT_EE_WIFI_CONF + 2]);
rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,
eeprom[MT_EE_WIFI_CONF + 4]);
nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,
eeprom[MT_EE_WIFI_CONF + 5]);
break;
default:
path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,
eeprom[MT_EE_WIFI_CONF + 1]);
rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,
eeprom[MT_EE_WIFI_CONF + 3]);
nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,
eeprom[MT_EE_WIFI_CONF + 4]);
break;
}
if (!path || path > 4)
path = 4;
if (!path || path > max_path)
path = max_path;
nss = min_t(u8, min_t(u8, 4, nss), path);
if (!nss || nss > max_nss)
nss = max_nss;
nss = min_t(u8, nss, path);
if (path != rx_path)
phy->has_aux_rx = true;
mphy->antenna_mask = BIT(nss) - 1;
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];

View File

@ -33,6 +33,9 @@ enum mt7996_eeprom_field {
#define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
#define MT_EE_WIFI_CONF3_RX_PATH_BAND0 GENMASK(2, 0)
#define MT_EE_WIFI_CONF3_RX_PATH_BAND1 GENMASK(5, 3)
#define MT_EE_WIFI_CONF4_RX_PATH_BAND2 GENMASK(2, 0)
#define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3)
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)

View File

@ -5,6 +5,8 @@
#include <linux/etherdevice.h>
#include <linux/of.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/thermal.h>
#include "mt7996.h"
#include "mac.h"
@ -43,6 +45,183 @@ static const struct ieee80211_iface_combination if_comb[] = {
}
};
static ssize_t mt7996_thermal_temp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct mt7996_phy *phy = dev_get_drvdata(dev);
int i = to_sensor_dev_attr(attr)->index;
int temperature;
switch (i) {
case 0:
temperature = mt7996_mcu_get_temperature(phy);
if (temperature < 0)
return temperature;
/* display in millidegree celcius */
return sprintf(buf, "%u\n", temperature * 1000);
case 1:
case 2:
return sprintf(buf, "%u\n",
phy->throttle_temp[i - 1] * 1000);
case 3:
return sprintf(buf, "%hhu\n", phy->throttle_state);
default:
return -EINVAL;
}
}
static ssize_t mt7996_thermal_temp_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct mt7996_phy *phy = dev_get_drvdata(dev);
int ret, i = to_sensor_dev_attr(attr)->index;
long val;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
mutex_lock(&phy->dev->mt76.mutex);
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130);
/* add a safety margin ~10 */
if ((i - 1 == MT7996_CRIT_TEMP_IDX &&
val > phy->throttle_temp[MT7996_MAX_TEMP_IDX] - 10) ||
(i - 1 == MT7996_MAX_TEMP_IDX &&
val - 10 < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
dev_err(phy->dev->mt76.dev,
"temp1_max shall be 10 degrees higher than temp1_crit.");
mutex_unlock(&phy->dev->mt76.mutex);
return -EINVAL;
}
phy->throttle_temp[i - 1] = val;
mutex_unlock(&phy->dev->mt76.mutex);
ret = mt7996_mcu_set_thermal_protect(phy, true);
if (ret)
return ret;
return count;
}
static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7996_thermal_temp, 0);
static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7996_thermal_temp, 1);
static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7996_thermal_temp, 2);
static SENSOR_DEVICE_ATTR_RO(throttle1, mt7996_thermal_temp, 3);
static struct attribute *mt7996_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_throttle1.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(mt7996_hwmon);
static int
mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
*state = MT7996_CDEV_THROTTLE_MAX;
return 0;
}
static int
mt7996_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct mt7996_phy *phy = cdev->devdata;
*state = phy->cdev_state;
return 0;
}
static int
mt7996_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
unsigned long state)
{
struct mt7996_phy *phy = cdev->devdata;
u8 throttling = MT7996_THERMAL_THROTTLE_MAX - state;
int ret;
if (state > MT7996_CDEV_THROTTLE_MAX) {
dev_err(phy->dev->mt76.dev,
"please specify a valid throttling state\n");
return -EINVAL;
}
if (state == phy->cdev_state)
return 0;
/* cooling_device convention: 0 = no cooling, more = more cooling
* mcu convention: 1 = max cooling, more = less cooling
*/
ret = mt7996_mcu_set_thermal_throttling(phy, throttling);
if (ret)
return ret;
phy->cdev_state = state;
return 0;
}
static const struct thermal_cooling_device_ops mt7996_thermal_ops = {
.get_max_state = mt7996_thermal_get_max_throttle_state,
.get_cur_state = mt7996_thermal_get_cur_throttle_state,
.set_cur_state = mt7996_thermal_set_cur_throttle_state,
};
static void mt7996_unregister_thermal(struct mt7996_phy *phy)
{
struct wiphy *wiphy = phy->mt76->hw->wiphy;
if (!phy->cdev)
return;
sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
thermal_cooling_device_unregister(phy->cdev);
}
static int mt7996_thermal_init(struct mt7996_phy *phy)
{
struct wiphy *wiphy = phy->mt76->hw->wiphy;
struct thermal_cooling_device *cdev;
struct device *hwmon;
const char *name;
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
wiphy_name(wiphy));
cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
if (!IS_ERR(cdev)) {
if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
"cooling_device") < 0)
thermal_cooling_device_unregister(cdev);
else
phy->cdev = cdev;
}
/* initialize critical/maximum high temperature */
phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
if (!IS_REACHABLE(CONFIG_HWMON))
return 0;
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
mt7996_hwmon_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
return 0;
}
static void mt7996_led_set_config(struct led_classdev *led_cdev,
u8 delay_on, u8 delay_off)
{
@ -109,10 +288,11 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
mt7996_led_set_config(led_cdev, 0xff, 0);
}
void mt7996_init_txpower(struct mt7996_dev *dev,
struct ieee80211_supported_band *sband)
static void __mt7996_init_txpower(struct mt7996_phy *phy,
struct ieee80211_supported_band *sband)
{
int i, nss = hweight8(dev->mphy.antenna_mask);
struct mt7996_dev *dev = phy->dev;
int i, nss = hweight16(phy->mt76->chainmask);
int nss_delta = mt76_tx_power_nss_delta(nss);
int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
struct mt76_power_limits limits;
@ -122,7 +302,7 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
int target_power = mt7996_eeprom_get_target_power(dev, chan);
target_power += pwr_delta;
target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
target_power = mt76_get_rate_power_limits(phy->mt76, chan,
&limits,
target_power);
target_power += nss_delta;
@ -133,6 +313,19 @@ void mt7996_init_txpower(struct mt7996_dev *dev,
}
}
void mt7996_init_txpower(struct mt7996_phy *phy)
{
if (!phy)
return;
if (phy->mt76->cap.has_2ghz)
__mt7996_init_txpower(phy, &phy->mt76->sband_2g.sband);
if (phy->mt76->cap.has_5ghz)
__mt7996_init_txpower(phy, &phy->mt76->sband_5g.sband);
if (phy->mt76->cap.has_6ghz)
__mt7996_init_txpower(phy, &phy->mt76->sband_6g.sband);
}
static void
mt7996_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
@ -147,16 +340,14 @@ mt7996_regd_notifier(struct wiphy *wiphy,
if (dev->mt76.region == NL80211_DFS_UNSET)
mt7996_mcu_rdd_background_enable(phy, NULL);
mt7996_init_txpower(dev, &phy->mt76->sband_2g.sband);
mt7996_init_txpower(dev, &phy->mt76->sband_5g.sband);
mt7996_init_txpower(dev, &phy->mt76->sband_6g.sband);
mt7996_init_txpower(phy);
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
mt7996_dfs_init_radar_detector(phy);
}
static void
mt7996_init_wiphy(struct ieee80211_hw *hw)
mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
{
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mt76_dev *mdev = &phy->dev->mt76;
@ -168,11 +359,14 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
hw->max_rx_aggregation_subframes = max_subframes;
hw->max_tx_aggregation_subframes = max_subframes;
hw->netdev_features = NETIF_F_RXCSUM;
if (mtk_wed_device_active(wed))
hw->netdev_features |= NETIF_F_HW_TC;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
phy->slottime = 9;
phy->beacon_rate = -1;
hw->sta_data_size = sizeof(struct mt7996_sta);
hw->vif_data_size = sizeof(struct mt7996_vif);
@ -242,6 +436,7 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
mt76_set_stream_caps(phy->mt76, true);
mt7996_set_stream_vht_txbf_caps(phy);
mt7996_set_stream_he_eht_caps(phy);
mt7996_init_txpower(phy);
wiphy->available_antennas_rx = phy->mt76->antenna_mask;
wiphy->available_antennas_tx = phy->mt76->antenna_mask;
@ -287,11 +482,12 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) {
u16 rate = mt76_rates[i].hw_value;
u16 idx = MT7996_BASIC_RATES_TBL + i;
/* odd index for driver, even index for firmware */
u16 idx = MT7996_BASIC_RATES_TBL + 2 * i;
rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) |
FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0));
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
mt7996_mcu_set_fixed_rate_table(&dev->phy, idx, rate, false);
}
}
@ -317,9 +513,23 @@ void mt7996_mac_init(struct mt7996_dev *dev)
mt76_rmw_field(dev, MT_DMA_TCRF1(2), MT_DMA_TCRF1_QIDX, 0);
/* rro module init */
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
if (is_mt7996(&dev->mt76))
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE, 2);
else
mt7996_mcu_set_rro(dev, UNI_RRO_SET_PLATFORM_TYPE,
dev->hif2 ? 7 : 0);
if (dev->has_rro) {
u16 timeout;
timeout = mt76_rr(dev, MT_HW_REV) == MT_HW_REV1 ? 512 : 128;
mt7996_mcu_set_rro(dev, UNI_RRO_SET_FLUSH_TIMEOUT, timeout);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 1);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 0);
} else {
mt7996_mcu_set_rro(dev, UNI_RRO_SET_BYPASS_MODE, 3);
mt7996_mcu_set_rro(dev, UNI_RRO_SET_TXFREE_PATH, 1);
}
mt7996_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
MCU_WA_PARAM_HW_PATH_HIF_VER,
@ -335,7 +545,8 @@ int mt7996_txbf_init(struct mt7996_dev *dev)
{
int ret;
if (dev->dbdc_support) {
if (mt7996_band_valid(dev, MT_BAND1) ||
mt7996_band_valid(dev, MT_BAND2)) {
ret = mt7996_mcu_set_txbf(dev, BF_MOD_EN_CTRL);
if (ret)
return ret;
@ -356,19 +567,18 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
struct mt76_phy *mphy;
u32 mac_ofs, hif1_ofs = 0;
int ret;
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
if (band != MT_BAND1 && band != MT_BAND2)
return 0;
if ((band == MT_BAND1 && !dev->dbdc_support) ||
(band == MT_BAND2 && !dev->tbtc_support))
if (!mt7996_band_valid(dev, band) || band == MT_BAND0)
return 0;
if (phy)
return 0;
if (band == MT_BAND2 && dev->hif2)
if (is_mt7996(&dev->mt76) && band == MT_BAND2 && dev->hif2) {
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
wed = &dev->mt76.mmio.wed_hif2;
}
mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7996_ops, band);
if (!mphy)
@ -401,11 +611,12 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
mt76_eeprom_override(mphy);
/* init wiphy according to mphy and phy */
mt7996_init_wiphy(mphy->hw);
ret = mt76_connac_init_tx_queues(phy->mt76,
MT_TXQ_ID(band),
MT7996_TX_RING_SIZE,
MT_TXQ_RING_BASE(band) + hif1_ofs, 0);
mt7996_init_wiphy(mphy->hw, wed);
ret = mt7996_init_tx_queues(mphy->priv,
MT_TXQ_ID(band),
MT7996_TX_RING_SIZE,
MT_TXQ_RING_BASE(band) + hif1_ofs,
wed);
if (ret)
goto error;
@ -414,10 +625,21 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
if (ret)
goto error;
ret = mt7996_thermal_init(phy);
if (ret)
goto error;
ret = mt7996_init_debugfs(phy);
if (ret)
goto error;
if (wed == &dev->mt76.mmio.wed_hif2 && mtk_wed_device_active(wed)) {
u32 irq_mask = dev->mt76.mmio.irqmask | MT_INT_TX_DONE_BAND2;
mt76_wr(dev, MT_INT1_MASK_CSR, irq_mask);
mtk_wed_device_start(&dev->mt76.mmio.wed_hif2, irq_mask);
}
return 0;
error:
@ -434,6 +656,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
if (!phy)
return;
mt7996_unregister_thermal(phy);
mphy = phy->dev->mt76.phys[band];
mt76_unregister_phy(mphy);
ieee80211_free_hw(mphy->hw);
@ -447,9 +671,6 @@ static void mt7996_init_work(struct work_struct *work)
mt7996_mcu_set_eeprom(dev);
mt7996_mac_init(dev);
mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
mt7996_txbf_init(dev);
}
@ -462,16 +683,225 @@ void mt7996_wfsys_reset(struct mt7996_dev *dev)
msleep(20);
}
static int mt7996_wed_rro_init(struct mt7996_dev *dev)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
u32 reg = MT_RRO_ADDR_ELEM_SEG_ADDR0;
struct mt7996_wed_rro_addr *addr;
void *ptr;
int i;
if (!dev->has_rro)
return 0;
if (!mtk_wed_device_active(wed))
return 0;
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_BA_BITMAP_CR_SIZE,
&dev->wed_rro.ba_bitmap[i].phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.ba_bitmap[i].ptr = ptr;
}
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
int j;
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr),
&dev->wed_rro.addr_elem[i].phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.addr_elem[i].ptr = ptr;
memset(dev->wed_rro.addr_elem[i].ptr, 0,
MT7996_RRO_WINDOW_MAX_SIZE * sizeof(*addr));
addr = dev->wed_rro.addr_elem[i].ptr;
for (j = 0; j < MT7996_RRO_WINDOW_MAX_SIZE; j++) {
addr->signature = 0xff;
addr++;
}
wed->wlan.ind_cmd.addr_elem_phys[i] =
dev->wed_rro.addr_elem[i].phy_addr;
}
ptr = dmam_alloc_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_LEN * sizeof(*addr),
&dev->wed_rro.session.phy_addr,
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
dev->wed_rro.session.ptr = ptr;
addr = dev->wed_rro.session.ptr;
for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
addr->signature = 0xff;
addr++;
}
/* rro hw init */
/* TODO: remove line after WM has set */
mt76_clear(dev, WF_RRO_AXI_MST_CFG, WF_RRO_AXI_MST_CFG_DIDX_OK);
/* setup BA bitmap cache address */
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE0,
dev->wed_rro.ba_bitmap[0].phy_addr);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE1, 0);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT0,
dev->wed_rro.ba_bitmap[1].phy_addr);
mt76_wr(dev, MT_RRO_BA_BITMAP_BASE_EXT1, 0);
/* setup Address element address */
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
mt76_wr(dev, reg, dev->wed_rro.addr_elem[i].phy_addr >> 4);
reg += 4;
}
/* setup Address element address - separate address segment mode */
mt76_wr(dev, MT_RRO_ADDR_ARRAY_BASE1,
MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE);
wed->wlan.ind_cmd.win_size = ffs(MT7996_RRO_WINDOW_MAX_LEN) - 6;
wed->wlan.ind_cmd.particular_sid = MT7996_RRO_MAX_SESSION;
wed->wlan.ind_cmd.particular_se_phys = dev->wed_rro.session.phy_addr;
wed->wlan.ind_cmd.se_group_nums = MT7996_RRO_ADDR_ELEM_LEN;
wed->wlan.ind_cmd.ack_sn_addr = MT_RRO_ACK_SN_CTRL;
mt76_wr(dev, MT_RRO_IND_CMD_SIGNATURE_BASE0, 0x15010e00);
mt76_set(dev, MT_RRO_IND_CMD_SIGNATURE_BASE1,
MT_RRO_IND_CMD_SIGNATURE_BASE1_EN);
/* particular session configure */
/* use max session idx + 1 as particular session id */
mt76_wr(dev, MT_RRO_PARTICULAR_CFG0, dev->wed_rro.session.phy_addr);
mt76_wr(dev, MT_RRO_PARTICULAR_CFG1,
MT_RRO_PARTICULAR_CONFG_EN |
FIELD_PREP(MT_RRO_PARTICULAR_SID, MT7996_RRO_MAX_SESSION));
/* interrupt enable */
mt76_wr(dev, MT_RRO_HOST_INT_ENA,
MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA);
/* rro ind cmd queue init */
return mt7996_dma_rro_init(dev);
#else
return 0;
#endif
}
static void mt7996_wed_rro_free(struct mt7996_dev *dev)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int i;
if (!dev->has_rro)
return;
if (!mtk_wed_device_active(&dev->mt76.mmio.wed))
return;
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.ba_bitmap); i++) {
if (!dev->wed_rro.ba_bitmap[i].ptr)
continue;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_BA_BITMAP_CR_SIZE,
dev->wed_rro.ba_bitmap[i].ptr,
dev->wed_rro.ba_bitmap[i].phy_addr);
}
for (i = 0; i < ARRAY_SIZE(dev->wed_rro.addr_elem); i++) {
if (!dev->wed_rro.addr_elem[i].ptr)
continue;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_SIZE *
sizeof(struct mt7996_wed_rro_addr),
dev->wed_rro.addr_elem[i].ptr,
dev->wed_rro.addr_elem[i].phy_addr);
}
if (!dev->wed_rro.session.ptr)
return;
dmam_free_coherent(dev->mt76.dma_dev,
MT7996_RRO_WINDOW_MAX_LEN *
sizeof(struct mt7996_wed_rro_addr),
dev->wed_rro.session.ptr,
dev->wed_rro.session.phy_addr);
#endif
}
static void mt7996_wed_rro_work(struct work_struct *work)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mt7996_dev *dev;
LIST_HEAD(list);
dev = (struct mt7996_dev *)container_of(work, struct mt7996_dev,
wed_rro.work);
spin_lock_bh(&dev->wed_rro.lock);
list_splice_init(&dev->wed_rro.poll_list, &list);
spin_unlock_bh(&dev->wed_rro.lock);
while (!list_empty(&list)) {
struct mt7996_wed_rro_session_id *e;
int i;
e = list_first_entry(&list, struct mt7996_wed_rro_session_id,
list);
list_del_init(&e->list);
for (i = 0; i < MT7996_RRO_WINDOW_MAX_LEN; i++) {
void *ptr = dev->wed_rro.session.ptr;
struct mt7996_wed_rro_addr *elem;
u32 idx, elem_id = i;
if (e->id == MT7996_RRO_MAX_SESSION)
goto reset;
idx = e->id / MT7996_RRO_BA_BITMAP_SESSION_SIZE;
if (idx >= ARRAY_SIZE(dev->wed_rro.addr_elem))
goto out;
ptr = dev->wed_rro.addr_elem[idx].ptr;
elem_id +=
(e->id % MT7996_RRO_BA_BITMAP_SESSION_SIZE) *
MT7996_RRO_WINDOW_MAX_LEN;
reset:
elem = ptr + elem_id * sizeof(*elem);
elem->signature = 0xff;
}
mt7996_mcu_wed_rro_reset_sessions(dev, e->id);
out:
kfree(e);
}
#endif
}
static int mt7996_init_hardware(struct mt7996_dev *dev)
{
int ret, idx;
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
if (is_mt7992(&dev->mt76)) {
mt76_rmw(dev, MT_AFE_CTL_BAND_PLL_03(MT_BAND0), MT_AFE_CTL_BAND_PLL_03_MSB_EN, 0);
mt76_rmw(dev, MT_AFE_CTL_BAND_PLL_03(MT_BAND1), MT_AFE_CTL_BAND_PLL_03_MSB_EN, 0);
}
INIT_WORK(&dev->init_work, mt7996_init_work);
dev->dbdc_support = true;
dev->tbtc_support = true;
INIT_WORK(&dev->wed_rro.work, mt7996_wed_rro_work);
INIT_LIST_HEAD(&dev->wed_rro.poll_list);
spin_lock_init(&dev->wed_rro.lock);
ret = mt7996_dma_init(dev);
if (ret)
@ -483,6 +913,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
if (ret)
return ret;
ret = mt7996_wed_rro_init(dev);
if (ret)
return ret;
ret = mt7996_eeprom_init(dev);
if (ret < 0)
return ret;
@ -889,14 +1323,16 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
mt7996_init_wiphy(hw);
mt7996_init_wiphy(hw, &dev->mt76.mmio.wed);
ret = mt76_register_device(&dev->mt76, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
return ret;
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
ret = mt7996_thermal_init(&dev->phy);
if (ret)
return ret;
ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
if (ret)
@ -906,21 +1342,35 @@ int mt7996_register_device(struct mt7996_dev *dev)
if (ret)
return ret;
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
dev->recovery.hw_init_done = true;
ret = mt7996_init_debugfs(&dev->phy);
if (ret)
return ret;
goto error;
return mt7996_coredump_register(dev);
ret = mt7996_coredump_register(dev);
if (ret)
goto error;
return 0;
error:
cancel_work_sync(&dev->init_work);
return ret;
}
void mt7996_unregister_device(struct mt7996_dev *dev)
{
cancel_work_sync(&dev->wed_rro.work);
mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
mt7996_unregister_thermal(&dev->phy);
mt7996_coredump_unregister(dev);
mt76_unregister_device(&dev->mt76);
mt7996_wed_rro_free(dev);
mt7996_mcu_exit(dev);
mt7996_tx_token_put(dev);
mt7996_dma_cleanup(dev);

View File

@ -102,7 +102,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
};
struct ieee80211_sta *sta;
struct mt7996_sta *msta;
struct rate_info *rate;
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
LIST_HEAD(sta_poll_list);
int i;
@ -118,7 +117,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
u32 addr, val;
u16 idx;
s8 rssi[4];
u8 bw;
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&sta_poll_list)) {
@ -174,49 +172,6 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
ieee80211_sta_register_airtime(sta, tid, tx_cur, rx_cur);
}
/* We don't support reading GI info from txs packets.
* For accurate tx status reporting and AQL improvement,
* we need to make sure that flags match so polling GI
* from per-sta counters directly.
*/
rate = &msta->wcid.rate;
switch (rate->bw) {
case RATE_INFO_BW_320:
bw = IEEE80211_STA_RX_BW_320;
break;
case RATE_INFO_BW_160:
bw = IEEE80211_STA_RX_BW_160;
break;
case RATE_INFO_BW_80:
bw = IEEE80211_STA_RX_BW_80;
break;
case RATE_INFO_BW_40:
bw = IEEE80211_STA_RX_BW_40;
break;
default:
bw = IEEE80211_STA_RX_BW_20;
break;
}
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6);
val = mt76_rr(dev, addr);
if (rate->flags & RATE_INFO_FLAGS_EHT_MCS) {
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 5);
val = mt76_rr(dev, addr);
rate->eht_gi = FIELD_GET(GENMASK(25, 24), val);
} else if (rate->flags & RATE_INFO_FLAGS_HE_MCS) {
u8 offs = 24 + 2 * bw;
rate->he_gi = (val & (0x3 << offs)) >> offs;
} else if (rate->flags &
(RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_MCS)) {
if (val & BIT(12 + bw))
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
else
rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
}
/* get signal strength of resp frames (CTS/BA/ACK) */
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 34);
val = mt76_rr(dev, addr);
@ -248,17 +203,6 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
mt76_clear(dev, addr, BIT(5));
}
void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
u8 tbl_idx, u16 rate_idx)
{
u32 ctrl = MT_WTBL_ITCR_WR | MT_WTBL_ITCR_EXEC | tbl_idx;
mt76_wr(dev, MT_WTBL_ITDR0, rate_idx);
/* use wtbl spe idx */
mt76_wr(dev, MT_WTBL_ITDR1, MT_WTBL_SPE_IDX_SEL);
mt76_wr(dev, MT_WTBL_ITCR, ctrl);
}
/* The HW does not translate the mac header to 802.3 for mesh point */
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
{
@ -449,8 +393,36 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
return 0;
}
static void
mt7996_wed_check_ppe(struct mt7996_dev *dev, struct mt76_queue *q,
struct mt7996_sta *msta, struct sk_buff *skb,
u32 info)
{
struct ieee80211_vif *vif;
struct wireless_dev *wdev;
if (!msta || !msta->vif)
return;
if (!mt76_queue_is_wed_rx(q))
return;
if (!(info & MT_DMA_INFO_PPE_VLD))
return;
vif = container_of((void *)msta->vif, struct ieee80211_vif,
drv_priv);
wdev = ieee80211_vif_to_wdev(vif);
skb->dev = wdev->netdev;
mtk_wed_device_ppe_check(&dev->mt76.mmio.wed, skb,
FIELD_GET(MT_DMA_PPE_CPU_REASON, info),
FIELD_GET(MT_DMA_PPE_ENTRY, info));
}
static int
mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
struct sk_buff *skb, u32 *info)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_phy *mphy = &dev->mt76.phy;
@ -475,7 +447,10 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
u16 seq_ctrl = 0;
__le16 fc = 0;
int idx;
u8 hw_aggr = false;
struct mt7996_sta *msta = NULL;
hw_aggr = status->aggr;
memset(status, 0, sizeof(*status));
band_idx = FIELD_GET(MT_RXD1_NORMAL_BAND_IDX, rxd1);
@ -502,8 +477,6 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
if (status->wcid) {
struct mt7996_sta *msta;
msta = container_of(status->wcid, struct mt7996_sta, wcid);
spin_lock_bh(&dev->mt76.sta_poll_lock);
if (list_empty(&msta->wcid.poll_list))
@ -708,12 +681,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
}
} else {
status->flag |= RX_FLAG_8023;
mt7996_wed_check_ppe(dev, &dev->mt76.q_rx[q], msta, skb,
*info);
}
if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
mt76_connac3_mac_decode_he_radiotap(skb, rxv, mode);
if (!status->wcid || !ieee80211_is_data_qos(fc))
if (!status->wcid || !ieee80211_is_data_qos(fc) || hw_aggr)
return 0;
status->aggr = unicast &&
@ -840,10 +815,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct mt76_vif *mvif;
u16 tx_count = 15;
u32 val;
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED));
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
BSS_CHANGED_FILS_DISCOVERY));
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL;
if (mvif) {
@ -898,8 +873,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
val |= MT_TXD5_TX_STATUS_HOST;
txwi[5] = cpu_to_le32(val);
val = MT_TXD6_DIS_MAT | MT_TXD6_DAS |
FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
if (is_mt7996(&dev->mt76))
val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
else
val |= FIELD_PREP(MT_TXD6_MSDU_CNT_V2, 1);
txwi[6] = cpu_to_le32(val);
txwi[7] = 0;
@ -923,7 +901,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
idx = mvif->basic_rates_idx;
}
txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx));
val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
txwi[6] |= cpu_to_le32(val);
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
}
@ -963,8 +942,16 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
for (i = 0; i < nbuf; i++) {
u16 len;
len = FIELD_PREP(MT_TXP_BUF_LEN, tx_info->buf[i + 1].len);
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
len |= FIELD_PREP(MT_TXP_DMA_ADDR_H,
tx_info->buf[i + 1].addr >> 32);
#endif
txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
txp->fw.len[i] = cpu_to_le16(len);
}
txp->fw.nbuf = nbuf;
@ -996,6 +983,29 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
return 0;
}
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
{
struct mt76_connac_fw_txp *txp = ptr + MT_TXD_SIZE;
__le32 *txwi = ptr;
u32 val;
memset(ptr, 0, MT_TXD_SIZE + sizeof(*txp));
val = FIELD_PREP(MT_TXD0_TX_BYTES, MT_TXD_SIZE) |
FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CT);
txwi[0] = cpu_to_le32(val);
val = BIT(31) |
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3);
txwi[1] = cpu_to_le32(val);
txp->token = cpu_to_le16(token_id);
txp->nbuf = 1;
txp->buf[0] = cpu_to_le32(phys + MT_TXD_SIZE + sizeof(*txp));
return MT_TXD_SIZE + sizeof(*txp);
}
static void
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
{
@ -1074,7 +1084,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
struct mt76_txwi_cache *txwi;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid;
struct mt76_wcid *wcid = NULL;
LIST_HEAD(free_list);
struct sk_buff *skb, *tmp;
void *end = data + len;
@ -1254,6 +1264,8 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
goto out;
rate.flags = RATE_INFO_FLAGS_VHT_MCS;
if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI)
rate.flags |= RATE_INFO_FLAGS_SHORT_GI;
break;
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
@ -1403,6 +1415,12 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2) &&
q == MT_RXQ_TXFREE_BAND2) {
dev_kfree_skb(skb);
break;
}
mt7996_mac_tx_free(dev, skb->data, skb->len);
napi_consume_skb(skb, 1);
break;
@ -1419,7 +1437,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
dev_kfree_skb(skb);
break;
case PKT_TYPE_NORMAL:
if (!mt7996_mac_fill_rx(dev, skb)) {
if (!mt7996_mac_fill_rx(dev, q, skb, info)) {
mt76_rx(&dev->mt76, q, skb);
return;
}
@ -1525,7 +1543,7 @@ mt7996_phy_get_nf(struct mt7996_phy *phy, u8 band_idx)
void mt7996_update_channel(struct mt76_phy *mphy)
{
struct mt7996_phy *phy = (struct mt7996_phy *)mphy->priv;
struct mt7996_phy *phy = mphy->priv;
struct mt76_channel_state *state = mphy->chan_state;
int nf;
@ -1652,6 +1670,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
/* disable all tx/rx napi */
mt76_worker_disable(&dev->mt76.tx_worker);
mt76_for_each_q_rx(mdev, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&mdev->q_rx[i]))
continue;
if (mdev->q_rx[i].ndesc)
napi_disable(&dev->mt76.napi[i]);
}
@ -1665,6 +1687,10 @@ mt7996_mac_restart(struct mt7996_dev *dev)
local_bh_disable();
mt76_for_each_q_rx(mdev, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&mdev->q_rx[i]))
continue;
if (mdev->q_rx[i].ndesc) {
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
@ -1697,9 +1723,9 @@ mt7996_mac_restart(struct mt7996_dev *dev)
goto out;
mt7996_mac_init(dev);
mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
mt7996_init_txpower(&dev->phy);
mt7996_init_txpower(phy2);
mt7996_init_txpower(phy3);
ret = mt7996_txbf_init(dev);
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
@ -1754,6 +1780,7 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
if (phy3)
ieee80211_stop_queues(phy3->mt76->hw);
cancel_work_sync(&dev->wed_rro.work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
if (phy2)
cancel_delayed_work_sync(&phy2->mt76->mac_work);
@ -1836,6 +1863,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
wiphy_name(dev->mt76.hw->wiphy));
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_stop(&dev->mt76.mmio.wed_hif2);
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_stop(&dev->mt76.mmio.wed);
ieee80211_stop_queues(mt76_hw(dev));
if (phy2)
ieee80211_stop_queues(phy2->mt76->hw);
@ -1845,6 +1879,8 @@ void mt7996_mac_reset_work(struct work_struct *work)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_work_sync(&dev->wed_rro.work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
if (phy2) {
set_bit(MT76_RESET, &phy2->mt76->state);
@ -1855,8 +1891,13 @@ void mt7996_mac_reset_work(struct work_struct *work)
cancel_delayed_work_sync(&phy3->mt76->mac_work);
}
mt76_worker_disable(&dev->mt76.tx_worker);
mt76_for_each_q_rx(&dev->mt76, i)
mt76_for_each_q_rx(&dev->mt76, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
continue;
napi_disable(&dev->mt76.napi[i]);
}
napi_disable(&dev->mt76.tx_napi);
mutex_lock(&dev->mt76.mutex);
@ -1877,7 +1918,28 @@ void mt7996_mac_reset_work(struct work_struct *work)
mt7996_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE);
/* enable DMA Tx/Tx and interrupt */
mt7996_dma_start(dev, false);
mt7996_dma_start(dev, false, false);
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
u32 wed_irq_mask = MT_INT_RRO_RX_DONE | MT_INT_TX_DONE_BAND2 |
dev->mt76.mmio.irqmask;
if (mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
wed_irq_mask &= ~MT_INT_RX_DONE_RRO_IND;
mt76_wr(dev, MT_INT_MASK_CSR, wed_irq_mask);
mtk_wed_device_start_hw_rro(&dev->mt76.mmio.wed, wed_irq_mask,
true);
mt7996_irq_enable(dev, wed_irq_mask);
mt7996_irq_disable(dev, 0);
}
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2)) {
mt76_wr(dev, MT_INT_PCIE1_MASK_CSR, MT_INT_TX_RX_DONE_EXT);
mtk_wed_device_start(&dev->mt76.mmio.wed_hif2,
MT_INT_TX_RX_DONE_EXT);
}
clear_bit(MT76_MCU_RESET, &dev->mphy.state);
clear_bit(MT76_RESET, &dev->mphy.state);
@ -1888,6 +1950,10 @@ void mt7996_mac_reset_work(struct work_struct *work)
local_bh_disable();
mt76_for_each_q_rx(&dev->mt76, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
mt76_queue_is_wed_rro(&dev->mt76.q_rx[i]))
continue;
napi_enable(&dev->mt76.napi[i]);
napi_schedule(&dev->mt76.napi[i]);
}
@ -2187,7 +2253,9 @@ void mt7996_mac_sta_rc_work(struct work_struct *work)
IEEE80211_RC_BW_CHANGED))
mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
/* TODO: smps change */
if (changed & IEEE80211_RC_SMPS_CHANGED)
mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
RATE_PARAM_MMPS_UPDATE);
spin_lock_bh(&dev->mt76.sta_poll_lock);
}
@ -2212,6 +2280,7 @@ void mt7996_mac_work(struct work_struct *work)
mt7996_mac_update_stats(phy);
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_RATE);
if (mtk_wed_device_active(&phy->dev->mt76.mmio.wed)) {
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_ADM_STAT);
mt7996_mcu_get_all_sta_info(phy, UNI_ALL_STA_TXRX_MSDU_COUNT);

View File

@ -51,6 +51,14 @@ int mt7996_run(struct ieee80211_hw *hw)
if (ret)
goto out;
ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);
if (ret)
goto out;
ret = mt7996_mcu_set_thermal_protect(phy, true);
if (ret)
goto out;
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
@ -342,6 +350,8 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256:
case WLAN_CIPHER_SUITE_SMS4:
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
@ -365,9 +375,13 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
mt76_wcid_key_setup(&dev->mt76, wcid, key);
err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
if (key->keyidx == 6 || key->keyidx == 7)
err = mt7996_mcu_bcn_prot_enable(dev, vif, key);
else
err = mt7996_mcu_add_key(&dev->mt76, vif, key,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
&msta->wcid, cmd);
out:
mutex_unlock(&dev->mt76.mutex);
@ -388,6 +402,13 @@ static int mt7996_config(struct ieee80211_hw *hw, u32 changed)
ieee80211_wake_queues(hw);
}
if (changed & (IEEE80211_CONF_CHANGE_POWER |
IEEE80211_CONF_CHANGE_CHANNEL)) {
ret = mt7996_mcu_set_txpower_sku(phy);
if (ret)
return ret;
}
mutex_lock(&dev->mt76.mutex);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
@ -514,24 +535,25 @@ mt7996_get_rates_table(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt76_phy *mphy = hw->priv;
u16 rate;
u8 i, idx, ht;
u8 i, idx;
rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon, mcast);
ht = FIELD_GET(MT_TX_RATE_MODE, rate) > MT_PHY_TYPE_OFDM;
if (beacon && ht) {
struct mt7996_dev *dev = mt7996_hw_dev(hw);
if (beacon) {
struct mt7996_phy *phy = mphy->priv;
/* odd index for driver, even index for firmware */
idx = MT7996_BEACON_RATES_TBL + 2 * phy->mt76->band_idx;
if (phy->beacon_rate != rate)
mt7996_mcu_set_fixed_rate_table(phy, idx, rate, beacon);
/* must odd index */
idx = MT7996_BEACON_RATES_TBL + 2 * (mvif->idx % 20);
mt7996_mac_set_fixed_rate_table(dev, idx, rate);
return idx;
}
idx = FIELD_GET(MT_TX_RATE_IDX, rate);
for (i = 0; i < ARRAY_SIZE(mt76_rates); i++)
if ((mt76_rates[i].hw_value & GENMASK(7, 0)) == idx)
return MT7996_BASIC_RATES_TBL + i;
return MT7996_BASIC_RATES_TBL + 2 * i;
return mvif->basic_rates_idx;
}
@ -956,8 +978,8 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
mt76_set_stream_caps(phy->mt76, true);
mt7996_set_stream_vht_txbf_caps(phy);
mt7996_set_stream_he_eht_caps(phy);
mt7996_mcu_set_txpower_sku(phy);
/* TODO: update bmc_wtbl spe_idx when antenna changes */
mutex_unlock(&dev->mt76.mutex);
return 0;
@ -982,6 +1004,7 @@ static void mt7996_sta_statistics(struct ieee80211_hw *hw,
sinfo->txrate.he_gi = txrate->he_gi;
sinfo->txrate.he_dcm = txrate->he_dcm;
sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;
sinfo->txrate.eht_gi = txrate->eht_gi;
}
sinfo->txrate.flags = txrate->flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
@ -1388,6 +1411,44 @@ out:
return ret;
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
static int
mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct mt7996_dev *dev = mt7996_hw_dev(hw);
struct mt7996_phy *phy = mt7996_hw_phy(hw);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
if (phy != &dev->phy && phy->mt76->band_idx == MT_BAND2)
wed = &dev->mt76.mmio.wed_hif2;
if (!mtk_wed_device_active(wed))
return -ENODEV;
if (msta->wcid.idx > MT7996_WTBL_STA)
return -EIO;
path->type = DEV_PATH_MTK_WDMA;
path->dev = ctx->dev;
path->mtk_wdma.wdma_idx = wed->wdma_idx;
path->mtk_wdma.bss = mvif->mt76.idx;
path->mtk_wdma.queue = 0;
path->mtk_wdma.wcid = msta->wcid.idx;
path->mtk_wdma.amsdu = mtk_wed_is_amsdu_supported(wed);
ctx->dev = NULL;
return 0;
}
#endif
const struct ieee80211_ops mt7996_ops = {
.tx = mt7996_tx,
.start = mt7996_start,
@ -1432,4 +1493,8 @@ const struct ieee80211_ops mt7996_ops = {
.sta_add_debugfs = mt7996_sta_add_debugfs,
#endif
.set_radar_background = mt7996_set_radar_background,
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
.net_fill_forward_path = mt7996_net_fill_forward_path,
.net_setup_tc = mt76_net_setup_tc,
#endif
};

View File

@ -10,6 +10,20 @@
#include "mac.h"
#include "eeprom.h"
#define fw_name(_dev, name, ...) ({ \
char *_fw; \
switch (mt76_chip(&(_dev)->mt76)) { \
case 0x7992: \
_fw = MT7992_##name; \
break; \
case 0x7990: \
default: \
_fw = MT7996_##name; \
break; \
} \
_fw; \
})
struct mt7996_patch_hdr {
char build_date[16];
char platform[4];
@ -449,6 +463,43 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
static int
mt7996_mcu_update_tx_gi(struct rate_info *rate, struct all_sta_trx_rate *mcu_rate)
{
switch (mcu_rate->tx_mode) {
case MT_PHY_TYPE_CCK:
case MT_PHY_TYPE_OFDM:
break;
case MT_PHY_TYPE_HT:
case MT_PHY_TYPE_HT_GF:
case MT_PHY_TYPE_VHT:
if (mcu_rate->tx_gi)
rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
else
rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
break;
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
case MT_PHY_TYPE_HE_MU:
if (mcu_rate->tx_gi > NL80211_RATE_INFO_HE_GI_3_2)
return -EINVAL;
rate->he_gi = mcu_rate->tx_gi;
break;
case MT_PHY_TYPE_EHT_SU:
case MT_PHY_TYPE_EHT_TRIG:
case MT_PHY_TYPE_EHT_MU:
if (mcu_rate->tx_gi > NL80211_RATE_INFO_EHT_GI_3_2)
return -EINVAL;
rate->eht_gi = mcu_rate->tx_gi;
break;
default:
return -EINVAL;
}
return 0;
}
static void
mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -465,6 +516,16 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
struct mt76_wcid *wcid;
switch (le16_to_cpu(res->tag)) {
case UNI_ALL_STA_TXRX_RATE:
wlan_idx = le16_to_cpu(res->rate[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
if (!wcid)
break;
if (mt7996_mcu_update_tx_gi(&wcid->rate, &res->rate[i]))
dev_err(dev->mt76.dev, "Failed to update TX GI\n");
break;
case UNI_ALL_STA_TXRX_ADM_STAT:
wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx);
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
@ -497,6 +558,34 @@ mt7996_mcu_rx_all_sta_info_event(struct mt7996_dev *dev, struct sk_buff *skb)
}
}
static void
mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
{
#define THERMAL_NOTIFY_TAG 0x4
#define THERMAL_NOTIFY 0x2
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7996_mcu_thermal_notify *n;
struct mt7996_phy *phy;
n = (struct mt7996_mcu_thermal_notify *)skb->data;
if (le16_to_cpu(n->tag) != THERMAL_NOTIFY_TAG)
return;
if (n->event_id != THERMAL_NOTIFY)
return;
if (n->band_idx > MT_BAND2)
return;
mphy = dev->mt76.phys[n->band_idx];
if (!mphy)
return;
phy = (struct mt7996_phy *)mphy->priv;
phy->throttle_state = n->duty_percent;
}
static void
mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -520,12 +609,82 @@ mt7996_mcu_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_EVENT_EXT:
mt7996_mcu_rx_ext_event(dev, skb);
break;
case MCU_UNI_EVENT_THERMAL:
mt7996_mcu_rx_thermal_notify(dev, skb);
break;
default:
break;
}
dev_kfree_skb(skb);
}
static void
mt7996_mcu_wed_rro_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
struct mt7996_mcu_wed_rro_event *event = (void *)skb->data;
if (!dev->has_rro)
return;
skb_pull(skb, sizeof(struct mt7996_mcu_rxd) + 4);
switch (le16_to_cpu(event->tag)) {
case UNI_WED_RRO_BA_SESSION_STATUS: {
struct mt7996_mcu_wed_rro_ba_event *e;
while (skb->len >= sizeof(*e)) {
struct mt76_rx_tid *tid;
struct mt76_wcid *wcid;
u16 idx;
e = (void *)skb->data;
idx = le16_to_cpu(e->wlan_id);
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
break;
wcid = rcu_dereference(dev->mt76.wcid[idx]);
if (!wcid || !wcid->sta)
break;
if (e->tid >= ARRAY_SIZE(wcid->aggr))
break;
tid = rcu_dereference(wcid->aggr[e->tid]);
if (!tid)
break;
tid->id = le16_to_cpu(e->id);
skb_pull(skb, sizeof(*e));
}
break;
}
case UNI_WED_RRO_BA_SESSION_DELETE: {
struct mt7996_mcu_wed_rro_ba_delete_event *e;
while (skb->len >= sizeof(*e)) {
struct mt7996_wed_rro_session_id *session;
e = (void *)skb->data;
session = kzalloc(sizeof(*session), GFP_ATOMIC);
if (!session)
break;
session->id = le16_to_cpu(e->session_id);
spin_lock_bh(&dev->wed_rro.lock);
list_add_tail(&session->list, &dev->wed_rro.poll_list);
spin_unlock_bh(&dev->wed_rro.lock);
ieee80211_queue_work(mt76_hw(dev), &dev->wed_rro.work);
skb_pull(skb, sizeof(*e));
}
break;
}
default:
break;
}
}
static void
mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -544,6 +703,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
case MCU_UNI_EVENT_ALL_STA_INFO:
mt7996_mcu_rx_all_sta_info_event(dev, skb);
break;
case MCU_UNI_EVENT_WED_RRO:
mt7996_mcu_wed_rro_event(dev, skb);
break;
default:
break;
}
@ -963,7 +1125,7 @@ int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif)
}
static int
mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
mt7996_mcu_sta_ba(struct mt7996_dev *dev, struct mt76_vif *mvif,
struct ieee80211_ampdu_params *params,
bool enable, bool tx)
{
@ -972,7 +1134,7 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
struct sk_buff *skb;
struct tlv *tlv;
skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid,
skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mvif, wcid,
MT7996_STA_UPDATE_MAX_SIZE);
if (IS_ERR(skb))
return PTR_ERR(skb);
@ -986,8 +1148,9 @@ mt7996_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
ba->ba_en = enable << params->tid;
ba->amsdu = params->amsdu;
ba->tid = params->tid;
ba->ba_rdd_rro = !tx && enable && dev->has_rro;
return mt76_mcu_skb_send_msg(dev, skb,
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
@ -1002,8 +1165,7 @@ int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
if (enable && !params->amsdu)
msta->wcid.amsdu = false;
return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
enable, true);
return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, true);
}
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
@ -1013,8 +1175,7 @@ int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
struct mt7996_sta *msta = (struct mt7996_sta *)params->sta->drv_priv;
struct mt7996_vif *mvif = msta->vif;
return mt7996_mcu_sta_ba(&dev->mt76, &mvif->mt76, params,
enable, false);
return mt7996_mcu_sta_ba(dev, &mvif->mt76, params, enable, false);
}
static void
@ -1108,7 +1269,7 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
static void
mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
{
struct sta_rec_ht *ht;
struct sta_rec_ht_uni *ht;
struct tlv *tlv;
if (!sta->deflink.ht_cap.ht_supported)
@ -1116,8 +1277,12 @@ mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));
ht = (struct sta_rec_ht *)tlv;
ht = (struct sta_rec_ht_uni *)tlv;
ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);
ht->ampdu_param = u8_encode_bits(sta->deflink.ht_cap.ampdu_factor,
IEEE80211_HT_AMPDU_PARM_FACTOR) |
u8_encode_bits(sta->deflink.ht_cap.ampdu_density,
IEEE80211_HT_AMPDU_PARM_DENSITY);
}
static void
@ -1574,44 +1739,6 @@ mt7996_mcu_sta_bfee_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
}
static void
mt7996_mcu_sta_phy_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
struct sta_rec_phy *phy;
struct tlv *tlv;
u8 af = 0, mm = 0;
if (!sta->deflink.ht_cap.ht_supported && !sta->deflink.he_6ghz_capa.capa)
return;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy));
phy = (struct sta_rec_phy *)tlv;
if (sta->deflink.ht_cap.ht_supported) {
af = sta->deflink.ht_cap.ampdu_factor;
mm = sta->deflink.ht_cap.ampdu_density;
}
if (sta->deflink.vht_cap.vht_supported) {
u8 vht_af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
sta->deflink.vht_cap.cap);
af = max_t(u8, af, vht_af);
}
if (sta->deflink.he_6ghz_capa.capa) {
af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);
mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
}
phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR, af) |
FIELD_PREP(IEEE80211_HT_AMPDU_PARM_DENSITY, mm);
phy->max_ampdu_len = af;
}
static void
mt7996_mcu_sta_hdrt_tlv(struct mt7996_dev *dev, struct sk_buff *skb)
{
@ -1700,14 +1827,13 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
MCU_WM_UNI_CMD(RA), true);
}
static int
mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *data, u32 field)
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *data, u32 field)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
struct sta_phy *phy = data;
struct sta_rec_ra_fixed *ra;
struct sta_phy_uni *phy = data;
struct sta_rec_ra_fixed_uni *ra;
struct sk_buff *skb;
struct tlv *tlv;
@ -1718,7 +1844,7 @@ mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
return PTR_ERR(skb);
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
ra = (struct sta_rec_ra_fixed *)tlv;
ra = (struct sta_rec_ra_fixed_uni *)tlv;
switch (field) {
case RATE_PARAM_AUTO:
@ -1730,6 +1856,9 @@ mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
if (phy)
ra->phy = *phy;
break;
case RATE_PARAM_MMPS_UPDATE:
ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
break;
default:
break;
}
@ -1747,7 +1876,7 @@ mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct ieee80211_vif *vif
struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
enum nl80211_band band = chandef->chan->band;
struct sta_phy phy = {};
struct sta_phy_uni phy = {};
int ret, nrates = 0;
#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \
@ -1835,13 +1964,13 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
struct cfg80211_chan_def *chandef = &mphy->chandef;
struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
enum nl80211_band band = chandef->chan->band;
struct sta_rec_ra *ra;
struct sta_rec_ra_uni *ra;
struct tlv *tlv;
u32 supp_rate = sta->deflink.supp_rates[band];
u32 cap = sta->wme ? STA_CAP_WMM : 0;
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra));
ra = (struct sta_rec_ra *)tlv;
ra = (struct sta_rec_ra_uni *)tlv;
ra->valid = true;
ra->auto_rate = true;
@ -2018,8 +2147,6 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
/* tag order is in accordance with firmware dependency. */
if (sta) {
/* starec phy */
mt7996_mcu_sta_phy_tlv(dev, skb, vif, sta);
/* starec hdrt mode */
mt7996_mcu_sta_hdrt_tlv(dev, skb);
/* starec bfer */
@ -2058,7 +2185,6 @@ out:
static int
mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
struct mt76_connac_sta_key_conf *sta_key_conf,
struct sk_buff *skb,
struct ieee80211_key_conf *key,
enum set_key_cmd cmd)
@ -2079,43 +2205,22 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
return -EOPNOTSUPP;
sec_key = &sec->key[0];
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
sec_key->mgmt_prot = 0;
sec_key->cipher_id = cipher;
sec_key->cipher_len = sizeof(*sec_key);
sec_key->key_id = key->keyidx;
sec_key->key_len = key->keylen;
sec_key->need_resp = 0;
memcpy(sec_key->key, key->key, key->keylen);
if (cipher == MCU_CIPHER_BIP_CMAC_128) {
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
sec_key->key_id = sta_key_conf->keyidx;
sec_key->key_len = 16;
memcpy(sec_key->key, sta_key_conf->key, 16);
sec_key = &sec->key[1];
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
sec_key->cipher_len = sizeof(*sec_key);
sec_key->key_len = 16;
memcpy(sec_key->key, key->key, 16);
sec->n_cipher = 2;
} else {
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
sec_key->cipher_id = cipher;
sec_key->key_id = key->keyidx;
sec_key->key_len = key->keylen;
memcpy(sec_key->key, key->key, key->keylen);
if (cipher == MCU_CIPHER_TKIP) {
/* Rx/Tx MIC keys are swapped */
memcpy(sec_key->key + 16, key->key + 24, 8);
memcpy(sec_key->key + 24, key->key + 16, 8);
}
/* store key_conf for BIP batch update */
if (cipher == MCU_CIPHER_AES_CCMP) {
memcpy(sta_key_conf->key, key->key, key->keylen);
sta_key_conf->keyidx = key->keyidx;
}
sec->n_cipher = 1;
if (cipher == MCU_CIPHER_TKIP) {
/* Rx/Tx MIC keys are swapped */
memcpy(sec_key->key + 16, key->key + 24, 8);
memcpy(sec_key->key + 24, key->key + 16, 8);
}
sec->n_cipher = 1;
} else {
sec->n_cipher = 0;
}
@ -2124,7 +2229,6 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
}
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct mt76_connac_sta_key_conf *sta_key_conf,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd)
{
@ -2137,13 +2241,99 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
if (IS_ERR(skb))
return PTR_ERR(skb);
ret = mt7996_mcu_sta_key_tlv(wcid, sta_key_conf, skb, key, cmd);
ret = mt7996_mcu_sta_key_tlv(wcid, skb, key, cmd);
if (ret)
return ret;
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
}
static int mt7996_mcu_get_pn(struct mt7996_dev *dev, struct ieee80211_vif *vif,
u8 *pn)
{
#define TSC_TYPE_BIGTK_PN 2
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct sta_rec_pn_info *pn_info;
struct sk_buff *skb, *rskb;
struct tlv *tlv;
int ret;
skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &mvif->mt76, &mvif->sta.wcid);
if (IS_ERR(skb))
return PTR_ERR(skb);
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
pn_info = (struct sta_rec_pn_info *)tlv;
pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE),
true, &rskb);
if (ret)
return ret;
skb_pull(rskb, 4);
pn_info = (struct sta_rec_pn_info *)rskb->data;
if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
memcpy(pn, pn_info->pn, 6);
dev_kfree_skb(rskb);
return 0;
}
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_key_conf *key)
{
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
struct sk_buff *skb;
struct tlv *tlv;
u8 pn[6] = {};
int len = sizeof(struct bss_req_hdr) +
sizeof(struct mt7996_mcu_bcn_prot_tlv);
int ret;
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76, len);
if (IS_ERR(skb))
return PTR_ERR(skb);
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT, sizeof(*bcn_prot));
bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
ret = mt7996_mcu_get_pn(dev, vif, pn);
if (ret) {
dev_kfree_skb(skb);
return ret;
}
switch (key->cipher) {
case WLAN_CIPHER_SUITE_AES_CMAC:
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
break;
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
break;
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
default:
dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
dev_kfree_skb(skb);
return -EOPNOTSUPP;
}
pn[0]++;
memcpy(bcn_prot->pn, pn, 6);
bcn_prot->enable = BP_SW_MODE;
memcpy(bcn_prot->key, key->key, WLAN_MAX_KEY_LEN);
bcn_prot->key_id = key->keyidx;
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
}
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy,
struct ieee80211_vif *vif, bool enable)
{
@ -2463,7 +2653,7 @@ static int mt7996_load_patch(struct mt7996_dev *dev)
return -EAGAIN;
}
ret = request_firmware(&fw, MT7996_ROM_PATCH, dev->mt76.dev);
ret = request_firmware(&fw, fw_name(dev, ROM_PATCH), dev->mt76.dev);
if (ret)
goto out;
@ -2626,17 +2816,17 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
{
int ret;
ret = __mt7996_load_ram(dev, "WM", MT7996_FIRMWARE_WM,
ret = __mt7996_load_ram(dev, "WM", fw_name(dev, FIRMWARE_WM),
MT7996_RAM_TYPE_WM);
if (ret)
return ret;
ret = __mt7996_load_ram(dev, "DSP", MT7996_FIRMWARE_DSP,
ret = __mt7996_load_ram(dev, "DSP", fw_name(dev, FIRMWARE_DSP),
MT7996_RAM_TYPE_DSP);
if (ret)
return ret;
return __mt7996_load_ram(dev, "WA", MT7996_FIRMWARE_WA,
return __mt7996_load_ram(dev, "WA", fw_name(dev, FIRMWARE_WA),
MT7996_RAM_TYPE_WA);
}
@ -2788,9 +2978,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
{
struct uni_header hdr = {};
struct sk_buff *skb;
int len, num;
int len, num, i;
num = 2 + 2 * (dev->dbdc_support + dev->tbtc_support);
num = 2 + 2 * (mt7996_band_valid(dev, MT_BAND1) +
mt7996_band_valid(dev, MT_BAND2));
len = sizeof(hdr) + num * sizeof(struct vow_rx_airtime);
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, len);
if (!skb)
@ -2798,13 +2989,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
skb_put_data(skb, &hdr, sizeof(hdr));
mt7996_add_rx_airtime_tlv(skb, dev->mt76.phy.band_idx);
if (dev->dbdc_support)
mt7996_add_rx_airtime_tlv(skb, MT_BAND1);
if (dev->tbtc_support)
mt7996_add_rx_airtime_tlv(skb, MT_BAND2);
for (i = 0; i < __MT_MAX_BAND; i++) {
if (mt7996_band_valid(dev, i))
mt7996_add_rx_airtime_tlv(skb, i);
}
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WM_UNI_CMD(VOW), true);
@ -3230,7 +3418,7 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
.center_ch = ieee80211_frequency_to_channel(freq1),
.bw = mt76_connac_chan_bw(chandef),
.tx_path_num = hweight16(phy->mt76->chainmask),
.rx_path = phy->mt76->chainmask >> dev->chainshift[band_idx],
.rx_path = mt7996_rx_chainmask(phy) >> dev->chainshift[band_idx],
.band_idx = band_idx,
.channel_band = ch_band[chandef->chan->band],
};
@ -3502,6 +3690,121 @@ out:
return 0;
}
int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
{
#define TEMPERATURE_QUERY 0
#define GET_TEMPERATURE 0
struct {
u8 _rsv[4];
__le16 tag;
__le16 len;
u8 rsv1;
u8 action;
u8 band_idx;
u8 rsv2;
} req = {
.tag = cpu_to_le16(TEMPERATURE_QUERY),
.len = cpu_to_le16(sizeof(req) - 4),
.action = GET_TEMPERATURE,
.band_idx = phy->mt76->band_idx,
};
struct mt7996_mcu_thermal {
u8 _rsv[4];
__le16 tag;
__le16 len;
__le32 rsv;
__le32 temperature;
} __packed * res;
struct sk_buff *skb;
int ret;
ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
&req, sizeof(req), true, &skb);
if (ret)
return ret;
res = (void *)skb->data;
return le32_to_cpu(res->temperature);
}
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
{
struct {
u8 _rsv[4];
__le16 tag;
__le16 len;
struct mt7996_mcu_thermal_ctrl ctrl;
} __packed req = {
.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG),
.len = cpu_to_le16(sizeof(req) - 4),
.ctrl = {
.band_idx = phy->mt76->band_idx,
},
};
int level, ret;
/* set duty cycle and level */
for (level = 0; level < 4; level++) {
req.ctrl.duty.duty_level = level;
req.ctrl.duty.duty_cycle = state;
state /= 2;
ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
&req, sizeof(req), false);
if (ret)
return ret;
}
return 0;
}
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable)
{
#define SUSTAIN_PERIOD 10
struct {
u8 _rsv[4];
__le16 tag;
__le16 len;
struct mt7996_mcu_thermal_ctrl ctrl;
struct mt7996_mcu_thermal_enable enable;
} __packed req = {
.len = cpu_to_le16(sizeof(req) - 4 - sizeof(req.enable)),
.ctrl = {
.band_idx = phy->mt76->band_idx,
.type.protect_type = 1,
.type.trigger_type = 1,
},
};
int ret;
req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DISABLE);
ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
&req, sizeof(req) - sizeof(req.enable), false);
if (ret || !enable)
return ret;
/* set high-temperature trigger threshold */
req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_ENABLE);
req.enable.restore_temp = cpu_to_le32(phy->throttle_temp[0]);
req.enable.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
req.enable.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
req.len = cpu_to_le16(sizeof(req) - 4);
return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
&req, sizeof(req), false);
}
int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
{
struct {
@ -3964,6 +4267,35 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
u16 rate_idx, bool beacon)
{
#define UNI_FIXED_RATE_TABLE_SET 0
#define SPE_IXD_SELECT_TXD 0
#define SPE_IXD_SELECT_BMC_WTBL 1
struct mt7996_dev *dev = phy->dev;
struct fixed_rate_table_ctrl req = {
.tag = cpu_to_le16(UNI_FIXED_RATE_TABLE_SET),
.len = cpu_to_le16(sizeof(req) - 4),
.table_idx = table_idx,
.rate_idx = cpu_to_le16(rate_idx),
.gi = 1,
.he_ltf = 1,
};
u8 band_idx = phy->mt76->band_idx;
if (beacon) {
req.spe_idx_sel = SPE_IXD_SELECT_TXD;
req.spe_idx = 24 + band_idx;
phy->beacon_rate = rate_idx;
} else {
req.spe_idx_sel = SPE_IXD_SELECT_BMC_WTBL;
}
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(FIXED_RATE_TABLE),
&req, sizeof(req), false);
}
int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set)
{
struct {
@ -4019,14 +4351,12 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev)
&req, sizeof(req), false);
}
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val)
{
struct {
u8 __rsv1[4];
__le16 tag;
__le16 len;
union {
struct {
u8 type;
@ -4041,6 +4371,11 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
u8 path;
u8 __rsv2[3];
} __packed txfree_path;
struct {
__le16 flush_one;
__le16 flush_all;
u8 __rsv2[4];
} __packed timeout;
};
} __packed req = {
.tag = cpu_to_le16(tag),
@ -4057,6 +4392,10 @@ int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val)
case UNI_RRO_SET_TXFREE_PATH:
req.txfree_path.path = val;
break;
case UNI_RRO_SET_FLUSH_TIMEOUT:
req.timeout.flush_one = cpu_to_le16(val);
req.timeout.flush_all = cpu_to_le16(2 * val);
break;
default:
return -EINVAL;
}
@ -4081,3 +4420,80 @@ int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag)
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(ALL_STA_INFO),
&req, sizeof(req), false);
}
int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id)
{
struct {
u8 __rsv[4];
__le16 tag;
__le16 len;
__le16 session_id;
u8 pad[4];
} __packed req = {
.tag = cpu_to_le16(UNI_RRO_DEL_BA_SESSION),
.len = cpu_to_le16(sizeof(req) - 4),
.session_id = cpu_to_le16(id),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(RRO), &req,
sizeof(req), true);
}
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
{
#define TX_POWER_LIMIT_TABLE_RATE 0
struct mt7996_dev *dev = phy->dev;
struct mt76_phy *mphy = phy->mt76;
struct ieee80211_hw *hw = mphy->hw;
struct tx_power_limit_table_ctrl {
u8 __rsv1[4];
__le16 tag;
__le16 len;
u8 power_ctrl_id;
u8 power_limit_type;
u8 band_idx;
} __packed req = {
.tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
.len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4),
.power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
.power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
.band_idx = phy->mt76->band_idx,
};
struct mt76_power_limits la = {};
struct sk_buff *skb;
int i, tx_power;
tx_power = mt7996_get_power_bound(phy, hw->conf.power_level);
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
&la, tx_power);
mphy->txpower_cur = tx_power;
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
sizeof(req) + MT7996_SKU_RATE_NUM);
if (!skb)
return -ENOMEM;
skb_put_data(skb, &req, sizeof(req));
/* cck and ofdm */
skb_put_data(skb, &la.cck, sizeof(la.cck) + sizeof(la.ofdm));
/* ht20 */
skb_put_data(skb, &la.mcs[0], 8);
/* ht40 */
skb_put_data(skb, &la.mcs[1], 9);
/* vht */
for (i = 0; i < 4; i++) {
skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i]));
skb_put_zero(skb, 2); /* padding */
}
/* he */
skb_put_data(skb, &la.ru[0], sizeof(la.ru));
/* eht */
skb_put_data(skb, &la.eht[0], sizeof(la.eht));
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_WM_UNI_CMD(TXPOWER), true);
}

View File

@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
__le32 status; /* 0: success, others: fail */
} __packed;
struct mt7996_mcu_thermal_ctrl {
u8 ctrl_id;
u8 band_idx;
union {
struct {
u8 protect_type; /* 1: duty admit, 2: radio off */
u8 trigger_type; /* 0: low, 1: high */
} __packed type;
struct {
u8 duty_level; /* level 0~3 */
u8 duty_cycle;
} __packed duty;
};
} __packed;
struct mt7996_mcu_thermal_enable {
__le32 trigger_temp;
__le32 restore_temp;
__le16 sustain_time;
u8 rsv[2];
} __packed;
struct mt7996_mcu_csa_notify {
struct mt7996_mcu_rxd rxd;
@ -153,6 +175,27 @@ struct mt7996_mcu_mib {
__le64 data;
} __packed;
struct all_sta_trx_rate {
__le16 wlan_idx;
u8 __rsv1[2];
u8 tx_mode;
u8 flags;
u8 tx_stbc;
u8 tx_gi;
u8 tx_bw;
u8 tx_ldpc;
u8 tx_mcs;
u8 tx_nss;
u8 rx_rate;
u8 rx_mode;
u8 rx_nsts;
u8 rx_gi;
u8 rx_coding;
u8 rx_stbc;
u8 rx_bw;
u8 __rsv2;
} __packed;
struct mt7996_mcu_all_sta_info_event {
u8 rsv[4];
__le16 tag;
@ -160,23 +203,75 @@ struct mt7996_mcu_all_sta_info_event {
u8 more;
u8 rsv2;
__le16 sta_num;
u8 rsv3[2];
u8 rsv3[4];
union {
struct all_sta_trx_rate rate[0];
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_bytes[IEEE80211_NUM_ACS];
__le32 rx_bytes[IEEE80211_NUM_ACS];
} adm_stat[0];
} adm_stat[0] __packed;
struct {
__le16 wlan_idx;
u8 rsv[2];
__le32 tx_msdu_cnt;
__le32 rx_msdu_cnt;
} msdu_cnt[0];
};
} msdu_cnt[0] __packed;
} __packed;
} __packed;
struct mt7996_mcu_wed_rro_event {
struct mt7996_mcu_rxd rxd;
u8 __rsv1[4];
__le16 tag;
__le16 len;
} __packed;
struct mt7996_mcu_wed_rro_ba_event {
__le16 tag;
__le16 len;
__le16 wlan_id;
u8 tid;
u8 __rsv1;
__le32 status;
__le16 id;
u8 __rsv2[2];
} __packed;
struct mt7996_mcu_wed_rro_ba_delete_event {
__le16 tag;
__le16 len;
__le16 session_id;
u8 __rsv2[2];
} __packed;
enum {
UNI_WED_RRO_BA_SESSION_STATUS,
UNI_WED_RRO_BA_SESSION_TBL,
UNI_WED_RRO_BA_SESSION_DELETE,
};
struct mt7996_mcu_thermal_notify {
struct mt7996_mcu_rxd rxd;
u8 __rsv1[4];
__le16 tag;
__le16 len;
u8 event_id;
u8 band_idx;
u8 level_idx;
u8 duty_percent;
__le32 restore_temp;
u8 __rsv2[4];
} __packed;
enum mt7996_chan_mib_offs {
@ -247,7 +342,24 @@ struct bss_rate_tlv {
u8 short_preamble;
u8 bc_fixed_rate;
u8 mc_fixed_rate;
u8 __rsv2[1];
u8 __rsv2[9];
} __packed;
enum {
BP_DISABLE,
BP_SW_MODE,
BP_HW_MODE,
};
struct mt7996_mcu_bcn_prot_tlv {
__le16 tag;
__le16 len;
u8 pn[6];
u8 enable;
u8 cipher_id;
u8 key[WLAN_MAX_KEY_LEN];
u8 key_id;
u8 __rsv[3];
} __packed;
struct bss_ra_tlv {
@ -372,6 +484,15 @@ struct bss_mld_tlv {
u8 __rsv[3];
} __packed;
struct sta_rec_ht_uni {
__le16 tag;
__le16 len;
__le16 ht_cap;
__le16 ht_cap_ext;
u8 ampdu_param;
u8 _rsv[3];
} __packed;
struct sta_rec_ba_uni {
__le16 tag;
__le16 len;
@ -421,6 +542,73 @@ struct sta_rec_sec_uni {
struct sec_key_uni key[2];
} __packed;
struct sta_phy_uni {
u8 type;
u8 flag;
u8 stbc;
u8 sgi;
u8 bw;
u8 ldpc;
u8 mcs;
u8 nss;
u8 he_ltf;
u8 rsv[3];
};
struct sta_rec_ra_uni {
__le16 tag;
__le16 len;
u8 valid;
u8 auto_rate;
u8 phy_mode;
u8 channel;
u8 bw;
u8 disable_cck;
u8 ht_mcs32;
u8 ht_gf;
u8 ht_mcs[4];
u8 mmps_mode;
u8 gband_256;
u8 af;
u8 auth_wapi_mode;
u8 rate_len;
u8 supp_mode;
u8 supp_cck_rate;
u8 supp_ofdm_rate;
__le32 supp_ht_mcs;
__le16 supp_vht_mcs[4];
u8 op_mode;
u8 op_vht_chan_width;
u8 op_vht_rx_nss;
u8 op_vht_rx_nss_type;
__le32 sta_cap;
struct sta_phy_uni phy;
u8 rx_rcpi[4];
} __packed;
struct sta_rec_ra_fixed_uni {
__le16 tag;
__le16 len;
__le32 field;
u8 op_mode;
u8 op_vht_chan_width;
u8 op_vht_rx_nss;
u8 op_vht_rx_nss_type;
struct sta_phy_uni phy;
u8 spe_idx;
u8 short_preamble;
u8 is_5g;
u8 mmps_mode;
} __packed;
struct sta_rec_hdrt {
__le16 tag;
__le16 len;
@ -596,17 +784,16 @@ enum {
#define MT7996_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_bf) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_ht_uni) + \
sizeof(struct sta_rec_he_v2) + \
sizeof(struct sta_rec_ba_uni) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct sta_rec_bfee) + \
sizeof(struct sta_rec_phy) + \
sizeof(struct sta_rec_ra) + \
sizeof(struct sta_rec_ra_uni) + \
sizeof(struct sta_rec_sec) + \
sizeof(struct sta_rec_ra_fixed) + \
sizeof(struct sta_rec_ra_fixed_uni) + \
sizeof(struct sta_rec_he_6g_capa) + \
sizeof(struct sta_rec_eht) + \
sizeof(struct sta_rec_hdrt) + \
@ -622,6 +809,18 @@ enum {
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
MT7996_BEACON_UPDATE_SIZE)
static inline s8
mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
{
struct mt76_phy *mphy = phy->mt76;
int n_chains = hweight16(mphy->chainmask);
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
txpower -= mt76_tx_power_nss_delta(n_chains);
return txpower;
}
enum {
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
@ -669,6 +868,8 @@ enum {
UNI_RRO_GET_BA_SESSION_TABLE,
UNI_RRO_SET_BYPASS_MODE,
UNI_RRO_SET_TXFREE_PATH,
UNI_RRO_DEL_BA_SESSION,
UNI_RRO_SET_FLUSH_TIMEOUT
};
enum{
@ -682,6 +883,16 @@ enum{
UNI_CMD_SR_SET_SIGA = 0xd0,
};
enum {
UNI_CMD_THERMAL_PROTECT_ENABLE = 0x6,
UNI_CMD_THERMAL_PROTECT_DISABLE,
UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
};
enum {
UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
};
enum {
UNI_CMD_ACCESS_REG_BASIC = 0x0,
UNI_CMD_ACCESS_RF_REG_BASIC,
@ -720,4 +931,24 @@ enum {
#define MT7996_SEC_KEY_IDX GENMASK(2, 1)
#define MT7996_SEC_IV BIT(3)
struct fixed_rate_table_ctrl {
u8 _rsv[4];
__le16 tag;
__le16 len;
u8 table_idx;
u8 antenna_idx;
__le16 rate_idx;
u8 spe_idx_sel;
u8 spe_idx;
u8 gi;
u8 he_ltf;
bool ldpc;
bool txbf;
bool dynamic_bw;
u8 _rsv2;
} __packed;
#endif

View File

@ -6,10 +6,16 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/rtnetlink.h>
#include "mt7996.h"
#include "mac.h"
#include "mcu.h"
#include "../trace.h"
#include "../dma.h"
static bool wed_enable;
module_param(wed_enable, bool, 0644);
static const struct __base mt7996_reg_base[] = {
[WF_AGG_BASE] = { { 0x820e2000, 0x820f2000, 0x830e2000 } },
@ -24,6 +30,58 @@ static const struct __base mt7996_reg_base[] = {
[WF_RATE_BASE] = { { 0x820ee000, 0x820fe000, 0x830ee000 } },
};
static const u32 mt7996_offs[] = {
[MIB_RVSR0] = 0x720,
[MIB_RVSR1] = 0x724,
[MIB_BTSCR5] = 0x788,
[MIB_BTSCR6] = 0x798,
[MIB_RSCR1] = 0x7ac,
[MIB_RSCR27] = 0x954,
[MIB_RSCR28] = 0x958,
[MIB_RSCR29] = 0x95c,
[MIB_RSCR30] = 0x960,
[MIB_RSCR31] = 0x964,
[MIB_RSCR33] = 0x96c,
[MIB_RSCR35] = 0x974,
[MIB_RSCR36] = 0x978,
[MIB_BSCR0] = 0x9cc,
[MIB_BSCR1] = 0x9d0,
[MIB_BSCR2] = 0x9d4,
[MIB_BSCR3] = 0x9d8,
[MIB_BSCR4] = 0x9dc,
[MIB_BSCR5] = 0x9e0,
[MIB_BSCR6] = 0x9e4,
[MIB_BSCR7] = 0x9e8,
[MIB_BSCR17] = 0xa10,
[MIB_TRDR1] = 0xa28,
};
static const u32 mt7992_offs[] = {
[MIB_RVSR0] = 0x760,
[MIB_RVSR1] = 0x764,
[MIB_BTSCR5] = 0x7c8,
[MIB_BTSCR6] = 0x7d8,
[MIB_RSCR1] = 0x7f0,
[MIB_RSCR27] = 0x998,
[MIB_RSCR28] = 0x99c,
[MIB_RSCR29] = 0x9a0,
[MIB_RSCR30] = 0x9a4,
[MIB_RSCR31] = 0x9a8,
[MIB_RSCR33] = 0x9b0,
[MIB_RSCR35] = 0x9b8,
[MIB_RSCR36] = 0x9bc,
[MIB_BSCR0] = 0xac8,
[MIB_BSCR1] = 0xacc,
[MIB_BSCR2] = 0xad0,
[MIB_BSCR3] = 0xad4,
[MIB_BSCR4] = 0xad8,
[MIB_BSCR5] = 0xadc,
[MIB_BSCR6] = 0xae0,
[MIB_BSCR7] = 0xae4,
[MIB_BSCR17] = 0xb0c,
[MIB_TRDR1] = 0xb24,
};
static const struct __map mt7996_reg_map[] = {
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA_0 (PCIE0 MCU DMA0) */
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA_1 (PCIE0 MCU DMA1) */
@ -191,6 +249,169 @@ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
}
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
{
struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed);
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
struct mt76_phy *mphy = &dev->mphy;
int ret;
ASSERT_RTNL();
if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
return -EBUSY;
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
mphy->band_idx);
if (ret)
goto out;
rtnl_unlock();
if (!wait_for_completion_timeout(&mdev->mmio.wed_reset, 20 * HZ)) {
dev_err(mdev->dev, "wed reset timeout\n");
ret = -ETIMEDOUT;
}
rtnl_lock();
out:
clear_bit(MT76_STATE_WED_RESET, &mphy->state);
return ret;
}
#endif
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq)
{
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct pci_dev *pci_dev = pdev_ptr;
u32 hif1_ofs = 0;
if (!wed_enable)
return 0;
dev->has_rro = true;
hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
if (hif2)
wed = &dev->mt76.mmio.wed_hif2;
wed->wlan.pci_dev = pci_dev;
wed->wlan.bus_type = MTK_WED_BUS_PCIE;
wed->wlan.base = devm_ioremap(dev->mt76.dev,
pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
if (hif2) {
wed->wlan.wpdma_int = wed->wlan.phy_base +
MT_INT_PCIE1_SOURCE_CSR_EXT;
wed->wlan.wpdma_mask = wed->wlan.phy_base +
MT_INT_PCIE1_MASK_CSR;
wed->wlan.wpdma_tx = wed->wlan.phy_base + hif1_ofs +
MT_TXQ_RING_BASE(0) +
MT7996_TXQ_BAND2 * MT_RING_SIZE;
if (dev->has_rro) {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_TXFREE2 * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_EXT) - 1;
} else {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_TRI * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_TRI) - 1;
}
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + hif1_ofs + MT_WFDMA0_GLO_CFG;
wed->wlan.wpdma_rx = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
MT7996_RXQ_BAND0 * MT_RING_SIZE;
wed->wlan.id = 0x7991;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
} else {
wed->wlan.hw_rro = dev->has_rro; /* default on */
wed->wlan.wpdma_int = wed->wlan.phy_base + MT_INT_SOURCE_CSR;
wed->wlan.wpdma_mask = wed->wlan.phy_base + MT_INT_MASK_CSR;
wed->wlan.wpdma_tx = wed->wlan.phy_base + MT_TXQ_RING_BASE(0) +
MT7996_TXQ_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_glo = wed->wlan.phy_base + MT_WFDMA0_GLO_CFG;
wed->wlan.wpdma_rx = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
MT7996_RXQ_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_rro[0] = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND0) +
MT7996_RXQ_RRO_BAND0 * MT_RING_SIZE;
wed->wlan.wpdma_rx_rro[1] = wed->wlan.phy_base + hif1_ofs +
MT_RXQ_RING_BASE(MT7996_RXQ_RRO_BAND2) +
MT7996_RXQ_RRO_BAND2 * MT_RING_SIZE;
wed->wlan.wpdma_rx_pg = wed->wlan.phy_base +
MT_RXQ_RING_BASE(MT7996_RXQ_MSDU_PG_BAND0) +
MT7996_RXQ_MSDU_PG_BAND0 * MT_RING_SIZE;
wed->wlan.rx_nbuf = 65536;
wed->wlan.rx_npkt = dev->hif2 ? 32768 : 24576;
wed->wlan.rx_size = SKB_WITH_OVERHEAD(MT_RX_BUF_SIZE);
wed->wlan.rx_tbit[0] = ffs(MT_INT_RX_DONE_BAND0) - 1;
wed->wlan.rx_tbit[1] = ffs(MT_INT_RX_DONE_BAND2) - 1;
wed->wlan.rro_rx_tbit[0] = ffs(MT_INT_RX_DONE_RRO_BAND0) - 1;
wed->wlan.rro_rx_tbit[1] = ffs(MT_INT_RX_DONE_RRO_BAND2) - 1;
wed->wlan.rx_pg_tbit[0] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND0) - 1;
wed->wlan.rx_pg_tbit[1] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND1) - 1;
wed->wlan.rx_pg_tbit[2] = ffs(MT_INT_RX_DONE_MSDU_PG_BAND2) - 1;
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND0) - 1;
wed->wlan.tx_tbit[1] = ffs(MT_INT_TX_DONE_BAND1) - 1;
if (dev->has_rro) {
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
MT7996_RXQ_TXFREE0 * MT_RING_SIZE;
wed->wlan.txfree_tbit = ffs(MT_INT_RX_TXFREE_MAIN) - 1;
} else {
wed->wlan.txfree_tbit = ffs(MT_INT_RX_DONE_WA_MAIN) - 1;
wed->wlan.wpdma_txfree = wed->wlan.phy_base + MT_RXQ_RING_BASE(0) +
MT7996_RXQ_MCU_WA_MAIN * MT_RING_SIZE;
}
dev->mt76.rx_token_size = MT7996_TOKEN_SIZE + wed->wlan.rx_npkt;
}
wed->wlan.nbuf = MT7996_HW_TOKEN_SIZE;
wed->wlan.token_start = MT7996_TOKEN_SIZE - wed->wlan.nbuf;
wed->wlan.amsdu_max_subframes = 8;
wed->wlan.amsdu_max_len = 1536;
wed->wlan.init_buf = mt7996_wed_init_buf;
wed->wlan.init_rx_buf = mt76_mmio_wed_init_rx_buf;
wed->wlan.release_rx_buf = mt76_mmio_wed_release_rx_buf;
wed->wlan.offload_enable = mt76_mmio_wed_offload_enable;
wed->wlan.offload_disable = mt76_mmio_wed_offload_disable;
if (!hif2) {
wed->wlan.reset = mt7996_mmio_wed_reset;
wed->wlan.reset_complete = mt76_mmio_wed_reset_complete;
}
if (mtk_wed_device_attach(wed))
return 0;
*irq = wed->irq;
dev->mt76.dma_dev = wed->dev;
return 1;
#else
return 0;
#endif
}
static int mt7996_mmio_init(struct mt76_dev *mdev,
void __iomem *mem_base,
u32 device_id)
@ -204,6 +425,13 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
switch (device_id) {
case 0x7990:
dev->reg.base = mt7996_reg_base;
dev->reg.offs_rev = mt7996_offs;
dev->reg.map = mt7996_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
break;
case 0x7992:
dev->reg.base = mt7996_reg_base;
dev->reg.offs_rev = mt7992_offs;
dev->reg.map = mt7996_reg_map;
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
break;
@ -241,8 +469,17 @@ void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
mdev->mmio.irqmask |= set;
if (write_reg) {
mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
if (mtk_wed_device_active(&mdev->mmio.wed)) {
mtk_wed_device_irq_set_mask(&mdev->mmio.wed,
mdev->mmio.irqmask);
if (mtk_wed_device_active(&mdev->mmio.wed_hif2)) {
mtk_wed_device_irq_set_mask(&mdev->mmio.wed_hif2,
mdev->mmio.irqmask);
}
} else {
mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
}
}
spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
@ -260,22 +497,36 @@ static void mt7996_rx_poll_complete(struct mt76_dev *mdev,
static void mt7996_irq_tasklet(struct tasklet_struct *t)
{
struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
u32 i, intr, mask, intr1;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2)
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
if (dev->hif2 && mtk_wed_device_active(wed_hif2)) {
mtk_wed_device_irq_set_mask(wed_hif2, 0);
intr1 = mtk_wed_device_irq_get(wed_hif2,
dev->mt76.mmio.irqmask);
if (intr1 & MT_INT_RX_TXFREE_EXT)
napi_schedule(&dev->mt76.napi[MT_RXQ_TXFREE_BAND2]);
}
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (mtk_wed_device_active(wed)) {
mtk_wed_device_irq_set_mask(wed, 0);
intr = mtk_wed_device_irq_get(wed, dev->mt76.mmio.irqmask);
intr |= (intr1 & ~MT_INT_RX_TXFREE_EXT);
} else {
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2)
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
intr1 &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
intr |= intr1;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
intr1 &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
intr |= intr1;
}
}
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
@ -308,9 +559,17 @@ irqreturn_t mt7996_irq_handler(int irq, void *dev_instance)
{
struct mt7996_dev *dev = dev_instance;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2)
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed, 0);
else
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (dev->hif2) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_irq_set_mask(&dev->mt76.mmio.wed_hif2, 0);
else
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
}
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;

View File

@ -13,6 +13,7 @@
#define MT7996_MAX_INTERFACES 19 /* per-band */
#define MT7996_MAX_WMM_SETS 4
#define MT7996_WTBL_BMC_SIZE (is_mt7992(&dev->mt76) ? 32 : 64)
#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
#define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
mt7996_max_interface_num(dev))
@ -33,22 +34,54 @@
#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
#define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
#define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin"
#define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin"
#define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin"
#define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
#define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
#define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin"
#define MT7996_EEPROM_SIZE 7680
#define MT7996_EEPROM_BLOCK_SIZE 16
#define MT7996_TOKEN_SIZE 16384
#define MT7996_HW_TOKEN_SIZE 8192
#define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7996_SKU_RATE_NUM 417
#define MT7996_MAX_TWT_AGRT 16
#define MT7996_MAX_STA_TWT_AGRT 8
#define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT7996_BASIC_RATES_TBL 11
#define MT7996_BASIC_RATES_TBL 31
#define MT7996_BEACON_RATES_TBL 25
#define MT7996_THERMAL_THROTTLE_MAX 100
#define MT7996_CDEV_THROTTLE_MAX 99
#define MT7996_CRIT_TEMP_IDX 0
#define MT7996_MAX_TEMP_IDX 1
#define MT7996_CRIT_TEMP 110
#define MT7996_MAX_TEMP 120
#define MT7996_RRO_MAX_SESSION 1024
#define MT7996_RRO_WINDOW_MAX_LEN 1024
#define MT7996_RRO_ADDR_ELEM_LEN 128
#define MT7996_RRO_BA_BITMAP_LEN 2
#define MT7996_RRO_BA_BITMAP_CR_SIZE ((MT7996_RRO_MAX_SESSION * 128) / \
MT7996_RRO_BA_BITMAP_LEN)
#define MT7996_RRO_BA_BITMAP_SESSION_SIZE (MT7996_RRO_MAX_SESSION / \
MT7996_RRO_ADDR_ELEM_LEN)
#define MT7996_RRO_WINDOW_MAX_SIZE (MT7996_RRO_WINDOW_MAX_LEN * \
MT7996_RRO_BA_BITMAP_SESSION_SIZE)
#define MT7996_RX_BUF_SIZE (1800 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
#define MT7996_RX_MSDU_PAGE_SIZE (128 + \
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
struct mt7996_vif;
struct mt7996_sta;
struct mt7996_dfs_pulse;
@ -73,11 +106,21 @@ enum mt7996_rxq_id {
MT7996_RXQ_MCU_WM = 0,
MT7996_RXQ_MCU_WA,
MT7996_RXQ_MCU_WA_MAIN = 2,
MT7996_RXQ_MCU_WA_EXT = 2,/* unused */
MT7996_RXQ_MCU_WA_EXT = 3, /* for mt7992 */
MT7996_RXQ_MCU_WA_TRI = 3,
MT7996_RXQ_BAND0 = 4,
MT7996_RXQ_BAND1 = 4,/* unused */
MT7996_RXQ_BAND1 = 5, /* for mt7992 */
MT7996_RXQ_BAND2 = 5,
MT7996_RXQ_RRO_BAND0 = 8,
MT7996_RXQ_RRO_BAND1 = 8,/* unused */
MT7996_RXQ_RRO_BAND2 = 6,
MT7996_RXQ_MSDU_PG_BAND0 = 10,
MT7996_RXQ_MSDU_PG_BAND1 = 11,
MT7996_RXQ_MSDU_PG_BAND2 = 12,
MT7996_RXQ_TXFREE0 = 9,
MT7996_RXQ_TXFREE1 = 9,
MT7996_RXQ_TXFREE2 = 7,
MT7996_RXQ_RRO_IND = 0,
};
struct mt7996_twt_flow {
@ -146,6 +189,20 @@ struct mt7996_hif {
int irq;
};
struct mt7996_wed_rro_addr {
u32 head_low;
u32 head_high : 4;
u32 count: 11;
u32 oor: 1;
u32 rsv : 8;
u32 signature : 8;
};
struct mt7996_wed_rro_session_id {
struct list_head list;
u16 id;
};
struct mt7996_phy {
struct mt76_phy *mt76;
struct mt7996_dev *dev;
@ -154,6 +211,11 @@ struct mt7996_phy {
struct ieee80211_vif *monitor_vif;
struct thermal_cooling_device *cdev;
u8 cdev_state;
u8 throttle_state;
u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
u32 rxfilter;
u64 omac_mask;
@ -164,11 +226,15 @@ struct mt7996_phy {
u8 rdd_state;
u16 beacon_rate;
u32 rx_ampdu_ts;
u32 ampdu_ref;
struct mt76_mib_stats mib;
struct mt76_channel_state state_ts;
bool has_aux_rx;
};
struct mt7996_dev {
@ -221,10 +287,28 @@ struct mt7996_dev {
u32 hw_pattern;
bool dbdc_support:1;
bool tbtc_support:1;
bool flash_mode:1;
bool has_eht:1;
bool has_rro:1;
struct {
struct {
void *ptr;
dma_addr_t phy_addr;
} ba_bitmap[MT7996_RRO_BA_BITMAP_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} addr_elem[MT7996_RRO_ADDR_ELEM_LEN];
struct {
void *ptr;
dma_addr_t phy_addr;
} session;
struct work_struct work;
struct list_head poll_list;
spinlock_t lock;
} wed_rro;
bool ibf;
u8 fw_debug_wm;
@ -314,6 +398,20 @@ mt7996_phy3(struct mt7996_dev *dev)
return __mt7996_phy(dev, MT_BAND2);
}
static inline bool
mt7996_band_valid(struct mt7996_dev *dev, u8 band)
{
if (is_mt7992(&dev->mt76))
return band <= MT_BAND1;
/* tri-band support */
if (band <= MT_BAND2 &&
mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
return true;
return band == MT_BAND0 || band == MT_BAND2;
}
extern const struct ieee80211_ops mt7996_ops;
extern struct pci_driver mt7996_pci_driver;
extern struct pci_driver mt7996_hif_driver;
@ -334,9 +432,10 @@ int mt7996_dma_init(struct mt7996_dev *dev);
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
void mt7996_dma_prefetch(struct mt7996_dev *dev);
void mt7996_dma_cleanup(struct mt7996_dev *dev);
void mt7996_dma_start(struct mt7996_dev *dev, bool reset);
void mt7996_init_txpower(struct mt7996_dev *dev,
struct ieee80211_supported_band *sband);
void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset);
int mt7996_init_tx_queues(struct mt7996_phy *phy, int idx,
int n_desc, int ring_base, struct mtk_wed_device *wed);
void mt7996_init_txpower(struct mt7996_phy *phy);
int mt7996_txbf_init(struct mt7996_dev *dev);
void mt7996_reset(struct mt7996_dev *dev);
int mt7996_run(struct ieee80211_hw *hw);
@ -373,6 +472,8 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif);
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
void *data, u16 version);
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *data, u32 field);
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset);
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
@ -388,13 +489,19 @@ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
u8 rx_sel, u8 val);
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
struct cfg80211_chan_def *chandef);
int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
u16 rate_idx, bool beacon);
int mt7996_mcu_rf_regval(struct mt7996_dev *dev, u32 regidx, u32 *val, bool set);
int mt7996_mcu_set_hdr_trans(struct mt7996_dev *dev, bool hdr_trans);
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u8 val);
int mt7996_mcu_set_rro(struct mt7996_dev *dev, u16 tag, u16 val);
int mt7996_mcu_wa_cmd(struct mt7996_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
int mt7996_mcu_fw_log_2_host(struct mt7996_dev *dev, u8 type, u8 ctrl);
int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
@ -402,15 +509,18 @@ int mt7996_mcu_trigger_assert(struct mt7996_dev *dev);
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
void mt7996_mcu_exit(struct mt7996_dev *dev);
int mt7996_mcu_get_all_sta_info(struct mt7996_phy *phy, u16 tag);
int mt7996_mcu_wed_rro_reset_sessions(struct mt7996_dev *dev, u16 id);
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
{
return MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support);
return min(MT7996_MAX_INTERFACES * (1 + mt7996_band_valid(dev, MT_BAND1) +
mt7996_band_valid(dev, MT_BAND2)),
MT7996_WTBL_BMC_SIZE);
}
static inline u16 mt7996_wtbl_size(struct mt7996_dev *dev)
{
return (dev->wtbl_size_group << 8) + 64;
return (dev->wtbl_size_group << 8) + MT7996_WTBL_BMC_SIZE;
}
void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
@ -437,6 +547,18 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
size_t len);
static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
{
int max_nss = hweight8(phy->mt76->hw->wiphy->available_antennas_tx);
int cur_nss = hweight8(phy->mt76->antenna_mask);
u16 tx_chainmask = phy->mt76->chainmask;
if (cur_nss != max_nss)
return tx_chainmask;
return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
}
void mt7996_mac_init(struct mt7996_dev *dev);
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
@ -445,8 +567,6 @@ void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
struct ieee80211_vif *vif, bool enable);
void mt7996_mac_set_fixed_rate_table(struct mt7996_dev *dev,
u8 tbl_idx, u16 rate_idx);
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, int pid,
@ -485,9 +605,10 @@ int mt7996_init_debugfs(struct mt7996_phy *phy);
void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len);
bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
struct mt76_connac_sta_key_conf *sta_key_conf,
struct ieee80211_key_conf *key, int mcu_cmd,
struct mt76_wcid *wcid, enum set_key_cmd cmd);
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
struct ieee80211_key_conf *key);
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
@ -495,5 +616,16 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct dentry *dir);
#endif
int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
bool hif2, int *irq);
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
#ifdef CONFIG_MTK_DEBUG
int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir);
#endif
#ifdef CONFIG_NET_MEDIATEK_SOC_WED
int mt7996_dma_rro_init(struct mt7996_dev *dev);
#endif /* CONFIG_NET_MEDIATEK_SOC_WED */
#endif

View File

@ -17,11 +17,13 @@ static u32 hif_idx;
static const struct pci_device_id mt7996_pci_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) },
{ },
};
static const struct pci_device_id mt7996_hif_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) },
{ },
};
@ -60,7 +62,9 @@ static void mt7996_put_hif2(struct mt7996_hif *hif)
static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
{
hif_idx++;
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL))
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))
return NULL;
writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
@ -92,10 +96,10 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct pci_dev *hif2_dev;
struct mt7996_dev *dev;
struct mt76_dev *mdev;
struct mt7996_hif *hif2;
int irq, ret;
struct mt7996_dev *dev;
int irq, hif2_irq, ret;
struct mt76_dev *mdev;
ret = pcim_enable_device(pdev);
if (ret)
@ -107,13 +111,17 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
if (ret)
return ret;
ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
mt76_pci_disable_aspm(pdev);
if (id->device == 0x7991)
if (id->device == 0x7991 || id->device == 0x799a)
return mt7996_pci_hif2_probe(pdev);
dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
@ -125,15 +133,22 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
mt7996_wfsys_reset(dev);
hif2 = mt7996_pci_init_hif2(pdev);
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
ret = mt7996_mmio_wed_init(dev, pdev, false, &irq);
if (ret < 0)
goto free_device;
goto free_wed_or_irq_vector;
if (!ret) {
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
goto free_device;
irq = pdev->irq;
}
irq = pdev->irq;
ret = devm_request_irq(mdev->dev, irq, mt7996_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto free_irq_vector;
goto free_wed_or_irq_vector;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
/* master switch of PCIe tnterrupt enable */
@ -143,16 +158,25 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
hif2_dev = container_of(hif2->dev, struct pci_dev, dev);
dev->hif2 = hif2;
ret = pci_alloc_irq_vectors(hif2_dev, 1, 1, PCI_IRQ_ALL_TYPES);
ret = mt7996_mmio_wed_init(dev, hif2_dev, true, &hif2_irq);
if (ret < 0)
goto free_hif2;
goto free_hif2_wed_irq_vector;
dev->hif2->irq = hif2_dev->irq;
ret = devm_request_irq(mdev->dev, dev->hif2->irq,
mt7996_irq_handler, IRQF_SHARED,
KBUILD_MODNAME "-hif", dev);
if (!ret) {
ret = pci_alloc_irq_vectors(hif2_dev, 1, 1,
PCI_IRQ_ALL_TYPES);
if (ret < 0)
goto free_hif2;
dev->hif2->irq = hif2_dev->irq;
hif2_irq = dev->hif2->irq;
}
ret = devm_request_irq(mdev->dev, hif2_irq, mt7996_irq_handler,
IRQF_SHARED, KBUILD_MODNAME "-hif",
dev);
if (ret)
goto free_hif2_irq_vector;
goto free_hif2_wed_irq_vector;
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
/* master switch of PCIe tnterrupt enable */
@ -167,16 +191,23 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
free_hif2_irq:
if (dev->hif2)
devm_free_irq(mdev->dev, dev->hif2->irq, dev);
free_hif2_irq_vector:
if (dev->hif2)
pci_free_irq_vectors(hif2_dev);
devm_free_irq(mdev->dev, hif2_irq, dev);
free_hif2_wed_irq_vector:
if (dev->hif2) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed_hif2))
mtk_wed_device_detach(&dev->mt76.mmio.wed_hif2);
else
pci_free_irq_vectors(hif2_dev);
}
free_hif2:
if (dev->hif2)
put_device(dev->hif2->dev);
devm_free_irq(mdev->dev, irq, dev);
free_irq_vector:
pci_free_irq_vectors(pdev);
free_wed_or_irq_vector:
if (mtk_wed_device_active(&dev->mt76.mmio.wed))
mtk_wed_device_detach(&dev->mt76.mmio.wed);
else
pci_free_irq_vectors(pdev);
free_device:
mt76_free_device(&dev->mt76);
@ -221,3 +252,7 @@ MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
MODULE_FIRMWARE(MT7996_ROM_PATCH);
MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
MODULE_FIRMWARE(MT7992_ROM_PATCH);

View File

@ -19,6 +19,7 @@ struct __base {
/* used to differentiate between generations */
struct mt7996_reg_desc {
const struct __base *base;
const u32 *offs_rev;
const struct __map *map;
u32 map_size;
};
@ -39,6 +40,73 @@ enum base_rev {
#define __BASE(_id, _band) (dev->reg.base[(_id)].band_base[(_band)])
enum offs_rev {
MIB_RVSR0,
MIB_RVSR1,
MIB_BTSCR5,
MIB_BTSCR6,
MIB_RSCR1,
MIB_RSCR27,
MIB_RSCR28,
MIB_RSCR29,
MIB_RSCR30,
MIB_RSCR31,
MIB_RSCR33,
MIB_RSCR35,
MIB_RSCR36,
MIB_BSCR0,
MIB_BSCR1,
MIB_BSCR2,
MIB_BSCR3,
MIB_BSCR4,
MIB_BSCR5,
MIB_BSCR6,
MIB_BSCR7,
MIB_BSCR17,
MIB_TRDR1,
__MT_OFFS_MAX,
};
#define __OFFS(id) (dev->reg.offs_rev[(id)])
/* RRO TOP */
#define MT_RRO_TOP_BASE 0xA000
#define MT_RRO_TOP(ofs) (MT_RRO_TOP_BASE + (ofs))
#define MT_RRO_BA_BITMAP_BASE0 MT_RRO_TOP(0x8)
#define MT_RRO_BA_BITMAP_BASE1 MT_RRO_TOP(0xC)
#define WF_RRO_AXI_MST_CFG MT_RRO_TOP(0xB8)
#define WF_RRO_AXI_MST_CFG_DIDX_OK BIT(12)
#define MT_RRO_ADDR_ARRAY_BASE1 MT_RRO_TOP(0x34)
#define MT_RRO_ADDR_ARRAY_ELEM_ADDR_SEG_MODE BIT(31)
#define MT_RRO_IND_CMD_SIGNATURE_BASE0 MT_RRO_TOP(0x38)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1 MT_RRO_TOP(0x3C)
#define MT_RRO_IND_CMD_0_CTRL0 MT_RRO_TOP(0x40)
#define MT_RRO_IND_CMD_SIGNATURE_BASE1_EN BIT(31)
#define MT_RRO_PARTICULAR_CFG0 MT_RRO_TOP(0x5C)
#define MT_RRO_PARTICULAR_CFG1 MT_RRO_TOP(0x60)
#define MT_RRO_PARTICULAR_CONFG_EN BIT(31)
#define MT_RRO_PARTICULAR_SID GENMASK(30, 16)
#define MT_RRO_BA_BITMAP_BASE_EXT0 MT_RRO_TOP(0x70)
#define MT_RRO_BA_BITMAP_BASE_EXT1 MT_RRO_TOP(0x74)
#define MT_RRO_HOST_INT_ENA MT_RRO_TOP(0x204)
#define MT_RRO_HOST_INT_ENA_HOST_RRO_DONE_ENA BIT(0)
#define MT_RRO_ADDR_ELEM_SEG_ADDR0 MT_RRO_TOP(0x400)
#define MT_RRO_ACK_SN_CTRL MT_RRO_TOP(0x50)
#define MT_RRO_ACK_SN_CTRL_SN_MASK GENMASK(27, 16)
#define MT_RRO_ACK_SN_CTRL_SESSION_MASK GENMASK(11, 0)
#define MT_RRO_DBG_RD_CTRL MT_RRO_TOP(0xe0)
#define MT_RRO_DBG_RD_ADDR GENMASK(15, 0)
#define MT_RRO_DBG_RD_EXEC BIT(31)
#define MT_RRO_DBG_RDAT_DW(_n) MT_RRO_TOP(0xf0 + (_n) * 0x4)
#define MT_MCU_INT_EVENT 0x2108
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
@ -140,32 +208,32 @@ enum base_rev {
#define MT_WF_MIB_BASE(_band) __BASE(WF_MIB_BASE, (_band))
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
#define MT_MIB_BSCR0(_band) MT_WF_MIB(_band, 0x9cc)
#define MT_MIB_BSCR1(_band) MT_WF_MIB(_band, 0x9d0)
#define MT_MIB_BSCR2(_band) MT_WF_MIB(_band, 0x9d4)
#define MT_MIB_BSCR3(_band) MT_WF_MIB(_band, 0x9d8)
#define MT_MIB_BSCR4(_band) MT_WF_MIB(_band, 0x9dc)
#define MT_MIB_BSCR5(_band) MT_WF_MIB(_band, 0x9e0)
#define MT_MIB_BSCR6(_band) MT_WF_MIB(_band, 0x9e4)
#define MT_MIB_BSCR7(_band) MT_WF_MIB(_band, 0x9e8)
#define MT_MIB_BSCR17(_band) MT_WF_MIB(_band, 0xa10)
#define MT_MIB_BSCR0(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR0))
#define MT_MIB_BSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR1))
#define MT_MIB_BSCR2(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR2))
#define MT_MIB_BSCR3(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR3))
#define MT_MIB_BSCR4(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR4))
#define MT_MIB_BSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR5))
#define MT_MIB_BSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR6))
#define MT_MIB_BSCR7(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR7))
#define MT_MIB_BSCR17(_band) MT_WF_MIB(_band, __OFFS(MIB_BSCR17))
#define MT_MIB_TSCR5(_band) MT_WF_MIB(_band, 0x6c4)
#define MT_MIB_TSCR6(_band) MT_WF_MIB(_band, 0x6c8)
#define MT_MIB_TSCR7(_band) MT_WF_MIB(_band, 0x6d0)
#define MT_MIB_RSCR1(_band) MT_WF_MIB(_band, 0x7ac)
#define MT_MIB_RSCR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR1))
/* rx mpdu counter, full 32 bits */
#define MT_MIB_RSCR31(_band) MT_WF_MIB(_band, 0x964)
#define MT_MIB_RSCR33(_band) MT_WF_MIB(_band, 0x96c)
#define MT_MIB_RSCR31(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR31))
#define MT_MIB_RSCR33(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR33))
#define MT_MIB_SDR6(_band) MT_WF_MIB(_band, 0x020)
#define MT_MIB_SDR6_CHANNEL_IDL_CNT_MASK GENMASK(15, 0)
#define MT_MIB_RVSR0(_band) MT_WF_MIB(_band, 0x720)
#define MT_MIB_RVSR0(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR0))
#define MT_MIB_RSCR35(_band) MT_WF_MIB(_band, 0x974)
#define MT_MIB_RSCR36(_band) MT_WF_MIB(_band, 0x978)
#define MT_MIB_RSCR35(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR35))
#define MT_MIB_RSCR36(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR36))
/* tx ampdu cnt, full 32 bits */
#define MT_MIB_TSCR0(_band) MT_WF_MIB(_band, 0x6b0)
@ -178,16 +246,16 @@ enum base_rev {
#define MT_MIB_TSCR4(_band) MT_WF_MIB(_band, 0x6c0)
/* rx ampdu count, 32-bit */
#define MT_MIB_RSCR27(_band) MT_WF_MIB(_band, 0x954)
#define MT_MIB_RSCR27(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR27))
/* rx ampdu bytes count, 32-bit */
#define MT_MIB_RSCR28(_band) MT_WF_MIB(_band, 0x958)
#define MT_MIB_RSCR28(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR28))
/* rx ampdu valid subframe count */
#define MT_MIB_RSCR29(_band) MT_WF_MIB(_band, 0x95c)
#define MT_MIB_RSCR29(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR29))
/* rx ampdu valid subframe bytes count, 32bits */
#define MT_MIB_RSCR30(_band) MT_WF_MIB(_band, 0x960)
#define MT_MIB_RSCR30(_band) MT_WF_MIB(_band, __OFFS(MIB_RSCR30))
/* remaining windows protected stats */
#define MT_MIB_SDR27(_band) MT_WF_MIB(_band, 0x080)
@ -196,18 +264,18 @@ enum base_rev {
#define MT_MIB_SDR28(_band) MT_WF_MIB(_band, 0x084)
#define MT_MIB_SDR28_TX_RWP_NEED_CNT GENMASK(15, 0)
#define MT_MIB_RVSR1(_band) MT_WF_MIB(_band, 0x724)
#define MT_MIB_RVSR1(_band) MT_WF_MIB(_band, __OFFS(MIB_RVSR1))
/* rx blockack count, 32 bits */
#define MT_MIB_TSCR1(_band) MT_WF_MIB(_band, 0x6b4)
#define MT_MIB_BTSCR0(_band) MT_WF_MIB(_band, 0x5e0)
#define MT_MIB_BTSCR5(_band) MT_WF_MIB(_band, 0x788)
#define MT_MIB_BTSCR6(_band) MT_WF_MIB(_band, 0x798)
#define MT_MIB_BTSCR5(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR5))
#define MT_MIB_BTSCR6(_band) MT_WF_MIB(_band, __OFFS(MIB_BTSCR6))
#define MT_MIB_BFTFCR(_band) MT_WF_MIB(_band, 0x5d0)
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0xa28 + ((n) << 2))
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, __OFFS(MIB_TRDR1) + ((n) << 2))
#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x0b0 + ((n) << 2))
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 4)) & GENMASK(9, 0))
@ -330,15 +398,22 @@ enum base_rev {
#define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
#define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
#define MT_WFDMA0_RX_INT_SEL_RING6 BIT(6)
#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
#define MT_WFDMA0_GLO_CFG_EXT_EN BIT(26)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_PAUSE_RX_Q_45_TH MT_WFDMA0(0x268)
#define MT_WFDMA0_PAUSE_RX_Q_67_TH MT_WFDMA0(0x26c)
#define MT_WFDMA0_PAUSE_RX_Q_89_TH MT_WFDMA0(0x270)
#define MT_WFDMA0_PAUSE_RX_Q_RRO_TH MT_WFDMA0(0x27c)
#define WF_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define WF_WFDMA0_GLO_CFG_EXT0_RX_WB_RXD BIT(18)
@ -362,10 +437,14 @@ enum base_rev {
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
#define MT_WFDMA_HOST_CONFIG_BAND2_PCIE1 BIT(22)
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_WFDMA_AXI_R2A_CTRL MT_WFDMA_EXT_CSR(0x500)
#define MT_WFDMA_AXI_R2A_CTRL_OUTSTAND_MASK GENMASK(4, 0)
#define MT_PCIE_RECOG_ID 0xd7090
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
#define MT_PCIE_RECOG_ID_SEM BIT(31)
@ -374,6 +453,9 @@ enum base_rev {
#define MT_WFDMA0_PCIE1_BASE 0xd8000
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
#define MT_INT_PCIE1_SOURCE_CSR_EXT MT_WFDMA0_PCIE1(0x118)
#define MT_INT_PCIE1_MASK_CSR MT_WFDMA0_PCIE1(0x11c)
#define MT_WFDMA0_PCIE1_BUSY_ENA MT_WFDMA0_PCIE1(0x13c)
#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
@ -394,6 +476,7 @@ enum base_rev {
#define MT_MCUQ_RING_BASE(q) (MT_Q_BASE(q) + 0x300)
#define MT_TXQ_RING_BASE(q) (MT_Q_BASE(__TXQ(q)) + 0x300)
#define MT_RXQ_RING_BASE(q) (MT_Q_BASE(__RXQ(q)) + 0x500)
#define MT_RXQ_RRO_IND_RING_BASE MT_RRO_TOP(0x40)
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
MT_MCUQ_ID(q) * 0x4)
@ -409,17 +492,27 @@ enum base_rev {
#define MT_INT1_MASK_CSR MT_WFDMA0_PCIE1(0x204)
#define MT_INT_RX_DONE_BAND0 BIT(12)
#define MT_INT_RX_DONE_BAND1 BIT(12)
#define MT_INT_RX_DONE_BAND1 BIT(13) /* for mt7992 */
#define MT_INT_RX_DONE_BAND2 BIT(13)
#define MT_INT_RX_DONE_WM BIT(0)
#define MT_INT_RX_DONE_WA BIT(1)
#define MT_INT_RX_DONE_WA_MAIN BIT(2)
#define MT_INT_RX_DONE_WA_EXT BIT(2)
#define MT_INT_RX_DONE_WA_EXT BIT(3) /* for mt7992 */
#define MT_INT_RX_DONE_WA_TRI BIT(3)
#define MT_INT_RX_TXFREE_MAIN BIT(17)
#define MT_INT_RX_TXFREE_TRI BIT(15)
#define MT_INT_RX_DONE_BAND2_EXT BIT(23)
#define MT_INT_RX_TXFREE_EXT BIT(26)
#define MT_INT_MCU_CMD BIT(29)
#define MT_INT_RX_DONE_RRO_BAND0 BIT(16)
#define MT_INT_RX_DONE_RRO_BAND1 BIT(16)
#define MT_INT_RX_DONE_RRO_BAND2 BIT(14)
#define MT_INT_RX_DONE_RRO_IND BIT(11)
#define MT_INT_RX_DONE_MSDU_PG_BAND0 BIT(18)
#define MT_INT_RX_DONE_MSDU_PG_BAND1 BIT(19)
#define MT_INT_RX_DONE_MSDU_PG_BAND2 BIT(23)
#define MT_INT_RX(q) (dev->q_int_mask[__RXQ(q)])
#define MT_INT_TX_MCU(q) (dev->q_int_mask[(q)])
@ -427,20 +520,31 @@ enum base_rev {
MT_INT_RX(MT_RXQ_MCU_WA))
#define MT_INT_BAND0_RX_DONE (MT_INT_RX(MT_RXQ_MAIN) | \
MT_INT_RX(MT_RXQ_MAIN_WA))
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND1_RX_DONE (MT_INT_RX(MT_RXQ_BAND1) | \
MT_INT_RX(MT_RXQ_BAND1_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA))
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_BAND2_RX_DONE (MT_INT_RX(MT_RXQ_BAND2) | \
MT_INT_RX(MT_RXQ_BAND2_WA) | \
MT_INT_RX(MT_RXQ_MAIN_WA))
MT_INT_RX(MT_RXQ_MAIN_WA) | \
MT_INT_RX(MT_RXQ_TXFREE_BAND0))
#define MT_INT_RRO_RX_DONE (MT_INT_RX(MT_RXQ_RRO_BAND0) | \
MT_INT_RX(MT_RXQ_RRO_BAND1) | \
MT_INT_RX(MT_RXQ_RRO_BAND2) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND0) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND1) | \
MT_INT_RX(MT_RXQ_MSDU_PAGE_BAND2))
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_MCU | \
MT_INT_BAND0_RX_DONE | \
MT_INT_BAND1_RX_DONE | \
MT_INT_BAND2_RX_DONE)
MT_INT_BAND2_RX_DONE | \
MT_INT_RRO_RX_DONE)
#define MT_INT_TX_DONE_FWDL BIT(26)
#define MT_INT_TX_DONE_MCU_WM BIT(27)
@ -449,6 +553,10 @@ enum base_rev {
#define MT_INT_TX_DONE_BAND1 BIT(31)
#define MT_INT_TX_DONE_BAND2 BIT(15)
#define MT_INT_TX_RX_DONE_EXT (MT_INT_TX_DONE_BAND2 | \
MT_INT_RX_DONE_BAND2_EXT | \
MT_INT_RX_TXFREE_EXT)
#define MT_INT_TX_DONE_MCU (MT_INT_TX_MCU(MT_MCUQ_WA) | \
MT_INT_TX_MCU(MT_MCUQ_WM) | \
MT_INT_TX_MCU(MT_MCUQ_FWDL))
@ -552,7 +660,12 @@ enum base_rev {
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
#define MT_PAD_GPIO 0x700056f0
#define MT_PAD_GPIO_ADIE_COMB GENMASK(16, 15)
#define MT_HW_REV 0x70010204
#define MT_HW_REV1 0x8a00
#define MT_WF_SUBSYS_RST 0x70028600
/* PCIE MAC */
@ -601,4 +714,11 @@ enum base_rev {
#define MT_MCU_WM_EXCP_LR_CTRL MT_MCU_WM_EXCP(0x200)
#define MT_MCU_WM_EXCP_LR_LOG MT_MCU_WM_EXCP(0x204)
/* CONN AFE CTL CON */
#define MT_AFE_CTL_BASE 0x18043000
#define MT_AFE_CTL_BAND(_band, ofs) (MT_AFE_CTL_BASE + \
((_band) * 0x1000) + (ofs))
#define MT_AFE_CTL_BAND_PLL_03(_band) MT_AFE_CTL_BAND(_band, 0x2c)
#define MT_AFE_CTL_BAND_PLL_03_MSB_EN BIT(1)
#endif

View File

@ -481,21 +481,21 @@ static void mt76s_status_worker(struct mt76_worker *w)
if (dev->drv->tx_status_data && ndata_frames > 0 &&
!test_and_set_bit(MT76_READING_STATS, &dev->phy.state) &&
!test_bit(MT76_STATE_SUSPEND, &dev->phy.state))
ieee80211_queue_work(dev->hw, &dev->sdio.stat_work);
mt76_worker_schedule(&sdio->stat_worker);
} while (nframes > 0);
if (resched)
mt76_worker_schedule(&dev->tx_worker);
}
static void mt76s_tx_status_data(struct work_struct *work)
static void mt76s_tx_status_data(struct mt76_worker *worker)
{
struct mt76_sdio *sdio;
struct mt76_dev *dev;
u8 update = 1;
u16 count = 0;
sdio = container_of(work, struct mt76_sdio, stat_work);
sdio = container_of(worker, struct mt76_sdio, stat_worker);
dev = container_of(sdio, struct mt76_dev, sdio);
while (true) {
@ -508,7 +508,7 @@ static void mt76s_tx_status_data(struct work_struct *work)
}
if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state))
ieee80211_queue_work(dev->hw, &sdio->stat_work);
mt76_worker_schedule(&sdio->status_worker);
else
clear_bit(MT76_READING_STATS, &dev->phy.state);
}
@ -600,8 +600,8 @@ void mt76s_deinit(struct mt76_dev *dev)
mt76_worker_teardown(&sdio->txrx_worker);
mt76_worker_teardown(&sdio->status_worker);
mt76_worker_teardown(&sdio->net_worker);
mt76_worker_teardown(&sdio->stat_worker);
cancel_work_sync(&sdio->stat_work);
clear_bit(MT76_READING_STATS, &dev->phy.state);
mt76_tx_status_check(dev, true);
@ -644,10 +644,14 @@ int mt76s_init(struct mt76_dev *dev, struct sdio_func *func,
if (err)
return err;
err = mt76_worker_setup(dev->hw, &sdio->stat_worker, mt76s_tx_status_data,
"sdio-sta");
if (err)
return err;
sched_set_fifo_low(sdio->status_worker.task);
sched_set_fifo_low(sdio->net_worker.task);
INIT_WORK(&sdio->stat_work, mt76s_tx_status_data);
sched_set_fifo_low(sdio->stat_worker.task);
dev->queue_ops = &sdio_queue_ops;
dev->bus = bus_ops;