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:
commit
379872288f
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 = {
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user