mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Merge tag 'mt76-for-kvalo-2023-02-03' of https://github.com/nbd168/wireless
mt76 patches for 6.3 - fixes - mt7996 cleanups - switch to page pool allocator - mt7996 eht support - WED reset support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config MT76_CORE
|
||||
tristate
|
||||
select PAGE_POOL
|
||||
|
||||
config MT76_LEDS
|
||||
bool
|
||||
|
||||
@@ -165,7 +165,7 @@ mt76_free_pending_txwi(struct mt76_dev *dev)
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
mt76_free_pending_rxwi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t;
|
||||
@@ -173,11 +173,12 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
|
||||
local_bh_disable();
|
||||
while ((t = __mt76_get_rxwi(dev)) != NULL) {
|
||||
if (t->ptr)
|
||||
skb_free_frag(t->ptr);
|
||||
mt76_put_page_pool_buf(t->ptr, false);
|
||||
kfree(t);
|
||||
}
|
||||
local_bh_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_pending_rxwi);
|
||||
|
||||
static void
|
||||
mt76_dma_sync_idx(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
@@ -218,8 +219,7 @@ mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len);
|
||||
|
||||
if ((q->flags & MT_QFLAG_WED) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
|
||||
if (mt76_queue_is_wed_rx(q)) {
|
||||
txwi = mt76_get_rxwi(dev);
|
||||
if (!txwi)
|
||||
return -ENOMEM;
|
||||
@@ -401,8 +401,7 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
if (info)
|
||||
*info = le32_to_cpu(desc->info);
|
||||
|
||||
if ((q->flags & MT_QFLAG_WED) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) {
|
||||
if (mt76_queue_is_wed_rx(q)) {
|
||||
u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
|
||||
le32_to_cpu(desc->buf1));
|
||||
struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
|
||||
@@ -410,9 +409,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
dma_unmap_single(dev->dma_dev, t->dma_addr,
|
||||
SKB_WITH_OVERHEAD(q->buf_size),
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_for_cpu(dev->dma_dev, t->dma_addr,
|
||||
SKB_WITH_OVERHEAD(q->buf_size),
|
||||
page_pool_get_dma_dir(q->page_pool));
|
||||
|
||||
buf = t->ptr;
|
||||
t->dma_addr = 0;
|
||||
@@ -429,9 +428,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
|
||||
} else {
|
||||
buf = e->buf;
|
||||
e->buf = NULL;
|
||||
dma_unmap_single(dev->dma_dev, e->dma_addr[0],
|
||||
SKB_WITH_OVERHEAD(q->buf_size),
|
||||
DMA_FROM_DEVICE);
|
||||
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));
|
||||
}
|
||||
|
||||
return buf;
|
||||
@@ -583,11 +582,11 @@ free_skb:
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
bool allow_direct)
|
||||
{
|
||||
int len = SKB_WITH_OVERHEAD(q->buf_size);
|
||||
int frames = 0, offset = q->buf_offset;
|
||||
dma_addr_t addr;
|
||||
int frames = 0;
|
||||
|
||||
if (!q->ndesc)
|
||||
return 0;
|
||||
@@ -595,26 +594,25 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
while (q->queued < q->ndesc - 1) {
|
||||
enum dma_data_direction dir;
|
||||
struct mt76_queue_buf qbuf;
|
||||
void *buf = NULL;
|
||||
dma_addr_t addr;
|
||||
int offset;
|
||||
void *buf;
|
||||
|
||||
buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
|
||||
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
addr = dma_map_single(dev->dma_dev, buf, len, DMA_FROM_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->dma_dev, addr))) {
|
||||
skb_free_frag(buf);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
qbuf.addr = addr + offset;
|
||||
qbuf.len = len - offset;
|
||||
qbuf.addr = addr + q->buf_offset;
|
||||
qbuf.len = len - q->buf_offset;
|
||||
qbuf.skip_unmap = false;
|
||||
if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) {
|
||||
dma_unmap_single(dev->dma_dev, addr, len,
|
||||
DMA_FROM_DEVICE);
|
||||
skb_free_frag(buf);
|
||||
mt76_put_page_pool_buf(buf, allow_direct);
|
||||
break;
|
||||
}
|
||||
frames++;
|
||||
@@ -628,14 +626,17 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
return frames;
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_dma_wed_setup(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 = q->flags;
|
||||
u8 flags;
|
||||
|
||||
if (!q || !q->ndesc)
|
||||
return -EINVAL;
|
||||
|
||||
flags = q->flags;
|
||||
if (!mtk_wed_device_active(wed))
|
||||
q->flags &= ~MT_QFLAG_WED;
|
||||
|
||||
@@ -647,7 +648,7 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
|
||||
switch (type) {
|
||||
case MT76_WED_Q_TX:
|
||||
ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs, false);
|
||||
ret = mtk_wed_device_tx_ring_setup(wed, ring, q->regs, reset);
|
||||
if (!ret)
|
||||
q->wed_regs = wed->tx_ring[ring].reg_base;
|
||||
break;
|
||||
@@ -655,7 +656,7 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
/* 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);
|
||||
mt76_dma_rx_fill(dev, q, false);
|
||||
q->flags = flags;
|
||||
|
||||
ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
|
||||
@@ -663,7 +664,7 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
q->wed_regs = wed->txfree_ring.reg_base;
|
||||
break;
|
||||
case MT76_WED_Q_RX:
|
||||
ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, false);
|
||||
ret = mtk_wed_device_rx_ring_setup(wed, ring, q->regs, reset);
|
||||
if (!ret)
|
||||
q->wed_regs = wed->rx_ring[ring].reg_base;
|
||||
break;
|
||||
@@ -676,6 +677,7 @@ mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_dma_wed_setup);
|
||||
|
||||
static int
|
||||
mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
@@ -702,7 +704,11 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (!q->entry)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mt76_dma_wed_setup(dev, q);
|
||||
ret = mt76_create_page_pool(dev, q);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mt76_dma_wed_setup(dev, q, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -715,7 +721,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
static void
|
||||
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
struct page *page;
|
||||
void *buf;
|
||||
bool more;
|
||||
|
||||
@@ -723,21 +728,21 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
do {
|
||||
buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more, NULL);
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
skb_free_frag(buf);
|
||||
mt76_put_page_pool_buf(buf, false);
|
||||
} while (1);
|
||||
|
||||
if (q->rx_head) {
|
||||
dev_kfree_skb(q->rx_head);
|
||||
q->rx_head = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
|
||||
if (!q->rx_page.va)
|
||||
return;
|
||||
|
||||
page = virt_to_page(q->rx_page.va);
|
||||
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
|
||||
memset(&q->rx_page, 0, sizeof(q->rx_page));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -753,14 +758,13 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
q->desc[i].ctrl = cpu_to_le32(MT_DMA_CTL_DMA_DONE);
|
||||
|
||||
mt76_dma_rx_cleanup(dev, q);
|
||||
mt76_dma_sync_idx(dev, q);
|
||||
mt76_dma_rx_fill(dev, q);
|
||||
|
||||
if (!q->rx_head)
|
||||
return;
|
||||
|
||||
dev_kfree_skb(q->rx_head);
|
||||
q->rx_head = NULL;
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -777,7 +781,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
|
||||
|
||||
skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
|
||||
} else {
|
||||
skb_free_frag(data);
|
||||
mt76_put_page_pool_buf(data, true);
|
||||
}
|
||||
|
||||
if (more)
|
||||
@@ -850,6 +854,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
goto free_frag;
|
||||
|
||||
skb_reserve(skb, q->buf_offset);
|
||||
skb_mark_for_recycle(skb);
|
||||
|
||||
*(u32 *)skb->cb = info;
|
||||
|
||||
@@ -865,10 +870,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
|
||||
continue;
|
||||
|
||||
free_frag:
|
||||
skb_free_frag(data);
|
||||
mt76_put_page_pool_buf(data, true);
|
||||
}
|
||||
|
||||
mt76_dma_rx_fill(dev, q);
|
||||
mt76_dma_rx_fill(dev, q, true);
|
||||
return done;
|
||||
}
|
||||
|
||||
@@ -908,10 +913,12 @@ mt76_dma_init(struct mt76_dev *dev,
|
||||
snprintf(dev->napi_dev.name, sizeof(dev->napi_dev.name), "%s",
|
||||
wiphy_name(dev->hw->wiphy));
|
||||
dev->napi_dev.threaded = 1;
|
||||
init_completion(&dev->mmio.wed_reset);
|
||||
init_completion(&dev->mmio.wed_reset_complete);
|
||||
|
||||
mt76_for_each_q_rx(dev, i) {
|
||||
netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
|
||||
mt76_dma_rx_fill(dev, &dev->q_rx[i]);
|
||||
mt76_dma_rx_fill(dev, &dev->q_rx[i], false);
|
||||
napi_enable(&dev->napi[i]);
|
||||
}
|
||||
|
||||
@@ -961,8 +968,9 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
||||
struct mt76_queue *q = &dev->q_rx[i];
|
||||
|
||||
netif_napi_del(&dev->napi[i]);
|
||||
if (FIELD_GET(MT_QFLAG_WED_TYPE, q->flags))
|
||||
mt76_dma_rx_cleanup(dev, q);
|
||||
mt76_dma_rx_cleanup(dev, q);
|
||||
|
||||
page_pool_destroy(q->page_pool);
|
||||
}
|
||||
|
||||
mt76_free_pending_txwi(dev);
|
||||
|
||||
@@ -56,5 +56,6 @@ enum mt76_mcu_evt_type {
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -138,6 +138,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
|
||||
{
|
||||
struct device_node *np = dev->dev->of_node;
|
||||
const char *const region_names[] = {
|
||||
[NL80211_DFS_UNSET] = "ww",
|
||||
[NL80211_DFS_ETSI] = "etsi",
|
||||
[NL80211_DFS_FCC] = "fcc",
|
||||
[NL80211_DFS_JP] = "jp",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include <linux/sched.h>
|
||||
#include <linux/of.h>
|
||||
#include <net/page_pool.h>
|
||||
#include "mt76.h"
|
||||
|
||||
#define CHAN2G(_idx, _freq) { \
|
||||
@@ -556,6 +557,47 @@ void mt76_unregister_phy(struct mt76_phy *phy)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
|
||||
|
||||
int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
struct page_pool_params pp_params = {
|
||||
.order = 0,
|
||||
.flags = PP_FLAG_PAGE_FRAG,
|
||||
.nid = NUMA_NO_NODE,
|
||||
.dev = dev->dma_dev,
|
||||
};
|
||||
int idx = q - dev->q_rx;
|
||||
|
||||
switch (idx) {
|
||||
case MT_RXQ_MAIN:
|
||||
case MT_RXQ_BAND1:
|
||||
case MT_RXQ_BAND2:
|
||||
pp_params.pool_size = 256;
|
||||
break;
|
||||
default:
|
||||
pp_params.pool_size = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mt76_is_mmio(dev)) {
|
||||
/* rely on page_pool for DMA mapping */
|
||||
pp_params.flags |= PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
|
||||
pp_params.dma_dir = DMA_FROM_DEVICE;
|
||||
pp_params.max_len = PAGE_SIZE;
|
||||
pp_params.offset = 0;
|
||||
}
|
||||
|
||||
q->page_pool = page_pool_create(&pp_params);
|
||||
if (IS_ERR(q->page_pool)) {
|
||||
int err = PTR_ERR(q->page_pool);
|
||||
|
||||
q->page_pool = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_create_page_pool);
|
||||
|
||||
struct mt76_dev *
|
||||
mt76_alloc_device(struct device *pdev, unsigned int size,
|
||||
const struct ieee80211_ops *ops,
|
||||
@@ -1658,7 +1700,7 @@ u16 mt76_calculate_default_rate(struct mt76_phy *phy, int rateidx)
|
||||
EXPORT_SYMBOL_GPL(mt76_calculate_default_rate);
|
||||
|
||||
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
|
||||
struct mt76_sta_stats *stats)
|
||||
struct mt76_sta_stats *stats, bool eht)
|
||||
{
|
||||
int i, ei = wi->initial_stat_idx;
|
||||
u64 *data = wi->data;
|
||||
@@ -1674,17 +1716,37 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_EXT_SU];
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_TB];
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_HE_MU];
|
||||
if (eht) {
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_SU];
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_TRIG];
|
||||
data[ei++] += stats->tx_mode[MT_PHY_TYPE_EHT_MU];
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stats->tx_bw); i++)
|
||||
for (i = 0; i < (ARRAY_SIZE(stats->tx_bw) - !eht); i++)
|
||||
data[ei++] += stats->tx_bw[i];
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
for (i = 0; i < (eht ? 14 : 12); i++)
|
||||
data[ei++] += stats->tx_mcs[i];
|
||||
|
||||
wi->worker_stat_count = ei - wi->initial_stat_idx;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
|
||||
|
||||
void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index)
|
||||
{
|
||||
#ifdef CONFIG_PAGE_POOL_STATS
|
||||
struct page_pool_stats stats = {};
|
||||
int i;
|
||||
|
||||
mt76_for_each_q_rx(dev, i)
|
||||
page_pool_get_stats(dev->q_rx[i].page_pool, &stats);
|
||||
|
||||
page_pool_ethtool_stats_get(data, &stats);
|
||||
*index += page_pool_ethtool_stats_get_count();
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_ethtool_page_pool_stats);
|
||||
|
||||
enum mt76_dfs_state mt76_phy_dfs_state(struct mt76_phy *phy)
|
||||
{
|
||||
struct ieee80211_hw *hw = phy->hw;
|
||||
|
||||
@@ -202,7 +202,7 @@ struct mt76_queue {
|
||||
|
||||
dma_addr_t desc_dma;
|
||||
struct sk_buff *rx_head;
|
||||
struct page_frag_cache rx_page;
|
||||
struct page_pool *page_pool;
|
||||
};
|
||||
|
||||
struct mt76_mcu_ops {
|
||||
@@ -264,12 +264,15 @@ enum mt76_phy_type {
|
||||
MT_PHY_TYPE_HE_EXT_SU,
|
||||
MT_PHY_TYPE_HE_TB,
|
||||
MT_PHY_TYPE_HE_MU,
|
||||
__MT_PHY_TYPE_HE_MAX,
|
||||
MT_PHY_TYPE_EHT_SU = 13,
|
||||
MT_PHY_TYPE_EHT_TRIG,
|
||||
MT_PHY_TYPE_EHT_MU,
|
||||
__MT_PHY_TYPE_MAX,
|
||||
};
|
||||
|
||||
struct mt76_sta_stats {
|
||||
u64 tx_mode[__MT_PHY_TYPE_HE_MAX];
|
||||
u64 tx_bw[4]; /* 20, 40, 80, 160 */
|
||||
u64 tx_mode[__MT_PHY_TYPE_MAX];
|
||||
u64 tx_bw[5]; /* 20, 40, 80, 160, 320 */
|
||||
u64 tx_nss[4]; /* 1, 2, 3, 4 */
|
||||
u64 tx_mcs[16]; /* mcs idx */
|
||||
u64 tx_bytes;
|
||||
@@ -291,7 +294,7 @@ enum mt76_wcid_flags {
|
||||
MT_WCID_FLAG_HDR_TRANS,
|
||||
};
|
||||
|
||||
#define MT76_N_WCIDS 544
|
||||
#define MT76_N_WCIDS 1088
|
||||
|
||||
/* stored in ieee80211_tx_info::hw_queue */
|
||||
#define MT_TX_HW_QUEUE_PHY GENMASK(3, 2)
|
||||
@@ -413,6 +416,7 @@ enum {
|
||||
MT76_STATE_SUSPEND,
|
||||
MT76_STATE_ROC,
|
||||
MT76_STATE_PM,
|
||||
MT76_STATE_WED_RESET,
|
||||
};
|
||||
|
||||
struct mt76_hw_cap {
|
||||
@@ -591,6 +595,8 @@ struct mt76_mmio {
|
||||
u32 irqmask;
|
||||
|
||||
struct mtk_wed_device wed;
|
||||
struct completion wed_reset;
|
||||
struct completion wed_reset_complete;
|
||||
};
|
||||
|
||||
struct mt76_rx_status {
|
||||
@@ -888,7 +894,6 @@ extern struct ieee80211_rate mt76_rates[12];
|
||||
|
||||
|
||||
#define mt76_mcu_restart(dev, ...) (dev)->mt76.mcu_ops->mcu_restart(&((dev)->mt76))
|
||||
#define __mt76_mcu_restart(dev, ...) (dev)->mcu_ops->mcu_restart((dev))
|
||||
|
||||
#define mt76_set(dev, offset, val) mt76_rmw(dev, offset, 0, val)
|
||||
#define mt76_clear(dev, offset, val) mt76_rmw(dev, offset, val, 0)
|
||||
@@ -909,10 +914,11 @@ bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
|
||||
#define mt76_poll(dev, ...) __mt76_poll(&((dev)->mt76), __VA_ARGS__)
|
||||
|
||||
bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
int timeout);
|
||||
|
||||
#define mt76_poll_msec(dev, ...) __mt76_poll_msec(&((dev)->mt76), __VA_ARGS__)
|
||||
bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
int timeout, int kick);
|
||||
#define __mt76_poll_msec(...) ____mt76_poll_msec(__VA_ARGS__, 10)
|
||||
#define mt76_poll_msec(dev, ...) ____mt76_poll_msec(&((dev)->mt76), __VA_ARGS__, 10)
|
||||
#define mt76_poll_msec_tick(dev, ...) ____mt76_poll_msec(&((dev)->mt76), __VA_ARGS__)
|
||||
|
||||
void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs);
|
||||
void mt76_pci_disable_aspm(struct pci_dev *pdev);
|
||||
@@ -1269,6 +1275,7 @@ mt76_tx_status_get_hw(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
|
||||
void mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
|
||||
struct mt76_txwi_cache *mt76_get_rxwi(struct mt76_dev *dev);
|
||||
void mt76_free_pending_rxwi(struct mt76_dev *dev);
|
||||
void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
|
||||
struct napi_struct *napi);
|
||||
void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
|
||||
@@ -1311,8 +1318,9 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
|
||||
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
|
||||
}
|
||||
|
||||
void mt76_ethtool_page_pool_stats(struct mt76_dev *dev, u64 *data, int *index);
|
||||
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
|
||||
struct mt76_sta_stats *stats);
|
||||
struct mt76_sta_stats *stats, bool eht);
|
||||
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
|
||||
int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type,
|
||||
u16 val, u16 offset, void *buf, size_t len);
|
||||
@@ -1409,6 +1417,12 @@ 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)
|
||||
{
|
||||
return (q->flags & MT_QFLAG_WED) &&
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX;
|
||||
}
|
||||
|
||||
struct mt76_txwi_cache *
|
||||
mt76_token_release(struct mt76_dev *dev, int token, bool *wake);
|
||||
int mt76_token_consume(struct mt76_dev *dev, struct mt76_txwi_cache **ptxwi);
|
||||
@@ -1416,6 +1430,25 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
|
||||
struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
|
||||
int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
|
||||
struct mt76_txwi_cache *r, dma_addr_t phys);
|
||||
int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q);
|
||||
static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
|
||||
{
|
||||
struct page *page = virt_to_head_page(buf);
|
||||
|
||||
page_pool_put_full_page(page->pp, page, allow_direct);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
mt76_get_page_pool_buf(struct mt76_queue *q, u32 *offset, u32 size)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
page = page_pool_dev_alloc_frag(q->page_pool, offset, size);
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
||||
return page_address(page) + *offset;
|
||||
}
|
||||
|
||||
static inline void mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
|
||||
{
|
||||
|
||||
@@ -221,7 +221,6 @@ int mt7603_mcu_init(struct mt7603_dev *dev)
|
||||
.headroom = sizeof(struct mt7603_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7603_mcu_skb_send_msg,
|
||||
.mcu_parse_response = mt7603_mcu_parse_response,
|
||||
.mcu_restart = mt7603_mcu_restart,
|
||||
};
|
||||
|
||||
dev->mt76.mcu_ops = &mt7603_mcu_ops;
|
||||
@@ -230,7 +229,7 @@ int mt7603_mcu_init(struct mt7603_dev *dev)
|
||||
|
||||
void mt7603_mcu_exit(struct mt7603_dev *dev)
|
||||
{
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt7603_mcu_restart(&dev->mt76);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
|
||||
@@ -1692,7 +1692,6 @@ int mt7615_mcu_init(struct mt7615_dev *dev)
|
||||
.headroom = sizeof(struct mt7615_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7615_mcu_send_message,
|
||||
.mcu_parse_response = mt7615_mcu_parse_response,
|
||||
.mcu_restart = mt7615_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
@@ -1732,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt7615_mcu_init);
|
||||
|
||||
void mt7615_mcu_exit(struct mt7615_dev *dev)
|
||||
{
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt7615_mcu_restart(&dev->mt76);
|
||||
mt7615_mcu_set_fw_ctrl(dev);
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,6 @@ int mt7663s_mcu_init(struct mt7615_dev *dev)
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7663s_mcu_send_message,
|
||||
.mcu_parse_response = mt7615_mcu_parse_response,
|
||||
.mcu_restart = mt7615_mcu_restart,
|
||||
.mcu_rr = mt76_connac_mcu_reg_rr,
|
||||
.mcu_wr = mt76_connac_mcu_reg_wr,
|
||||
};
|
||||
|
||||
@@ -69,7 +69,6 @@ int mt7663u_mcu_init(struct mt7615_dev *dev)
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7663u_mcu_send_message,
|
||||
.mcu_parse_response = mt7615_mcu_parse_response,
|
||||
.mcu_restart = mt7615_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ enum {
|
||||
CMD_CBW_10MHZ,
|
||||
CMD_CBW_5MHZ,
|
||||
CMD_CBW_8080MHZ,
|
||||
CMD_CBW_320MHZ,
|
||||
|
||||
CMD_HE_MCS_BW80 = 0,
|
||||
CMD_HE_MCS_BW160,
|
||||
@@ -239,6 +240,7 @@ static inline u8 mt76_connac_chan_bw(struct cfg80211_chan_def *chandef)
|
||||
[NL80211_CHAN_WIDTH_10] = CMD_CBW_10MHZ,
|
||||
[NL80211_CHAN_WIDTH_20] = CMD_CBW_20MHZ,
|
||||
[NL80211_CHAN_WIDTH_20_NOHT] = CMD_CBW_20MHZ,
|
||||
[NL80211_CHAN_WIDTH_320] = CMD_CBW_320MHZ,
|
||||
};
|
||||
|
||||
if (chandef->width >= ARRAY_SIZE(width_to_bw))
|
||||
@@ -370,6 +372,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_key_conf *key, int pid,
|
||||
enum mt76_txq_id qid, u32 changed);
|
||||
u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast);
|
||||
bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
__le32 *txs_data);
|
||||
bool mt76_connac2_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
|
||||
@@ -267,9 +267,9 @@ int mt76_connac_init_tx_queues(struct mt76_phy *phy, int idx, int n_desc,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_init_tx_queues);
|
||||
|
||||
static u16
|
||||
mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
u16 mt76_connac2_mac_tx_rate_val(struct mt76_phy *mphy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
{
|
||||
u8 mode = 0, band = mphy->chandef.chan->band;
|
||||
int rateidx = 0, mcast_rate;
|
||||
@@ -319,6 +319,7 @@ out:
|
||||
return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
|
||||
FIELD_PREP(MT_TX_RATE_MODE, mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_mac_tx_rate_val);
|
||||
|
||||
static void
|
||||
mt76_connac2_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb,
|
||||
|
||||
@@ -1329,6 +1329,40 @@ u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode);
|
||||
|
||||
u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
const struct ieee80211_sta_eht_cap *eht_cap;
|
||||
struct ieee80211_supported_band *sband;
|
||||
u8 mode = 0;
|
||||
|
||||
if (band == NL80211_BAND_6GHZ)
|
||||
mode |= PHY_MODE_AX_6G;
|
||||
|
||||
sband = phy->hw->wiphy->bands[band];
|
||||
eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);
|
||||
|
||||
if (!eht_cap || !eht_cap->has_eht)
|
||||
return mode;
|
||||
|
||||
switch (band) {
|
||||
case NL80211_BAND_6GHZ:
|
||||
mode |= PHY_MODE_BE_6G;
|
||||
break;
|
||||
case NL80211_BAND_5GHZ:
|
||||
mode |= PHY_MODE_BE_5G;
|
||||
break;
|
||||
case NL80211_BAND_2GHZ:
|
||||
mode |= PHY_MODE_BE_24G;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext);
|
||||
|
||||
const struct ieee80211_sta_he_cap *
|
||||
mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)
|
||||
{
|
||||
@@ -1341,6 +1375,18 @@ mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_he_phy_cap);
|
||||
|
||||
const struct ieee80211_sta_eht_cap *
|
||||
mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)
|
||||
{
|
||||
enum nl80211_band band = phy->chandef.chan->band;
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = phy->hw->wiphy->bands[band];
|
||||
|
||||
return ieee80211_get_eht_iftype_cap(sband, vif->type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_get_eht_phy_cap);
|
||||
|
||||
#define DEFAULT_HE_PE_DURATION 4
|
||||
#define DEFAULT_HE_DURATION_RTS_THRES 1023
|
||||
static void
|
||||
|
||||
@@ -793,6 +793,7 @@ enum {
|
||||
STA_REC_PHY = 0x15,
|
||||
STA_REC_HE_6G = 0x17,
|
||||
STA_REC_HE_V2 = 0x19,
|
||||
STA_REC_EHT = 0x22,
|
||||
STA_REC_HDRT = 0x28,
|
||||
STA_REC_HDR_TRANS = 0x2B,
|
||||
STA_REC_MAX_NUM
|
||||
@@ -882,12 +883,16 @@ enum {
|
||||
#define PHY_MODE_AX_5G BIT(7)
|
||||
|
||||
#define PHY_MODE_AX_6G BIT(0) /* phymode_ext */
|
||||
#define PHY_MODE_BE_24G BIT(1)
|
||||
#define PHY_MODE_BE_5G BIT(2)
|
||||
#define PHY_MODE_BE_6G BIT(3)
|
||||
|
||||
#define MODE_CCK BIT(0)
|
||||
#define MODE_OFDM BIT(1)
|
||||
#define MODE_HT BIT(2)
|
||||
#define MODE_VHT BIT(3)
|
||||
#define MODE_HE BIT(4)
|
||||
#define MODE_EHT BIT(5)
|
||||
|
||||
#define STA_CAP_WMM BIT(0)
|
||||
#define STA_CAP_SGI_20 BIT(4)
|
||||
@@ -1171,6 +1176,7 @@ enum {
|
||||
MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
|
||||
MCU_EXT_CMD_TXDPD_CAL = 0x60,
|
||||
MCU_EXT_CMD_CAL_CACHE = 0x67,
|
||||
MCU_EXT_CMD_RED_ENABLE = 0x68,
|
||||
MCU_EXT_CMD_SET_RADAR_TH = 0x7c,
|
||||
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
|
||||
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
|
||||
@@ -1198,7 +1204,8 @@ enum {
|
||||
MCU_UNI_CMD_REPT_MUAR = 0x09,
|
||||
MCU_UNI_CMD_WSYS_CONFIG = 0x0b,
|
||||
MCU_UNI_CMD_REG_ACCESS = 0x0d,
|
||||
MCU_UNI_CMD_POWER_CREL = 0x0f,
|
||||
MCU_UNI_CMD_CHIP_CONFIG = 0x0e,
|
||||
MCU_UNI_CMD_POWER_CTRL = 0x0f,
|
||||
MCU_UNI_CMD_RX_HDR_TRANS = 0x12,
|
||||
MCU_UNI_CMD_SER = 0x13,
|
||||
MCU_UNI_CMD_TWT = 0x14,
|
||||
@@ -1238,6 +1245,7 @@ enum {
|
||||
MCU_CE_CMD_TEST_CTRL = 0x01,
|
||||
MCU_CE_CMD_START_HW_SCAN = 0x03,
|
||||
MCU_CE_CMD_SET_PS_PROFILE = 0x05,
|
||||
MCU_CE_CMD_SET_RX_FILTER = 0x0a,
|
||||
MCU_CE_CMD_SET_CHAN_DOMAIN = 0x0f,
|
||||
MCU_CE_CMD_SET_BSS_CONNECTED = 0x16,
|
||||
MCU_CE_CMD_SET_BSS_ABORT = 0x17,
|
||||
@@ -1730,7 +1738,7 @@ mt76_connac_mcu_gen_dl_mode(struct mt76_dev *dev, u8 feature_set, bool is_wa)
|
||||
}
|
||||
|
||||
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
|
||||
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
|
||||
#define to_wcid_hi(id) FIELD_GET(GENMASK(10, 8), (u16)id)
|
||||
|
||||
static inline void
|
||||
mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
||||
@@ -1866,8 +1874,12 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
|
||||
|
||||
const struct ieee80211_sta_he_cap *
|
||||
mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif);
|
||||
const struct ieee80211_sta_eht_cap *
|
||||
mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif);
|
||||
u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band, struct ieee80211_sta *sta);
|
||||
u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
enum nl80211_band band);
|
||||
|
||||
int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt76_connac_sta_key_conf *sta_key_conf,
|
||||
|
||||
@@ -148,6 +148,7 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
|
||||
mt76_wr(dev, MT_USB_DMA_CFG, val);
|
||||
|
||||
ret = mt76x0u_upload_firmware(dev, hdr);
|
||||
mt76x02_set_ethtool_fwver(dev, hdr);
|
||||
release_firmware(fw);
|
||||
|
||||
mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
|
||||
|
||||
@@ -559,9 +559,32 @@ 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];
|
||||
struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
|
||||
int i;
|
||||
|
||||
/* clean up hw queues */
|
||||
@@ -581,28 +604,40 @@ int mt7915_dma_reset(struct mt7915_dev *dev, bool force)
|
||||
if (force)
|
||||
mt7915_wfsys_reset(dev);
|
||||
|
||||
if (mtk_wed_device_active(wed))
|
||||
mtk_wed_device_dma_reset(wed);
|
||||
|
||||
mt7915_dma_disable(dev, force);
|
||||
mt7915_dma_wed_reset(dev);
|
||||
|
||||
/* reset hw queues */
|
||||
for (i = 0; i < __MT_TXQ_MAX; i++) {
|
||||
mt76_queue_reset(dev, dev->mphy.q_tx[i]);
|
||||
mt7915_dma_reset_tx_queue(dev, dev->mphy.q_tx[i]);
|
||||
if (mphy_ext)
|
||||
mt76_queue_reset(dev, mphy_ext->q_tx[i]);
|
||||
mt7915_dma_reset_tx_queue(dev, 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)
|
||||
mt76_for_each_q_rx(&dev->mt76, i) {
|
||||
if (dev->mt76.q_rx[i].flags == MT_WED_Q_TXFREE)
|
||||
continue;
|
||||
|
||||
mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
|
||||
}
|
||||
|
||||
mt76_tx_status_check(&dev->mt76, true);
|
||||
|
||||
mt7915_dma_enable(dev);
|
||||
|
||||
mt76_for_each_q_rx(&dev->mt76, i)
|
||||
mt76_queue_rx_reset(dev, i);
|
||||
|
||||
if (mtk_wed_device_active(wed) && is_mt7915(&dev->mt76))
|
||||
mt76_rmw(dev, MT_WFDMA0_EXT0_CFG, MT_WFDMA0_EXT0_RXWB_KEEP,
|
||||
MT_WFDMA0_EXT0_RXWB_KEEP);
|
||||
|
||||
mt7915_dma_enable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,14 @@ static int mt7915_check_eeprom(struct mt7915_dev *dev)
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
u16 val = get_unaligned_le16(eeprom);
|
||||
|
||||
#define CHECK_EEPROM_ERR(match) (match ? 0 : -EINVAL)
|
||||
switch (val) {
|
||||
case 0x7915:
|
||||
return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76));
|
||||
case 0x7916:
|
||||
return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76));
|
||||
case 0x7986:
|
||||
return 0;
|
||||
return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76));
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160) |
|
||||
BIT(NL80211_CHAN_WIDTH_80P80),
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,9 +82,23 @@ static ssize_t mt7915_thermal_temp_store(struct device *dev,
|
||||
|
||||
mutex_lock(&phy->dev->mt76.mutex);
|
||||
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 60, 130);
|
||||
|
||||
if ((i - 1 == MT7915_CRIT_TEMP_IDX &&
|
||||
val > phy->throttle_temp[MT7915_MAX_TEMP_IDX]) ||
|
||||
(i - 1 == MT7915_MAX_TEMP_IDX &&
|
||||
val < phy->throttle_temp[MT7915_CRIT_TEMP_IDX])) {
|
||||
dev_err(phy->dev->mt76.dev,
|
||||
"temp1_max shall be greater than temp1_crit.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phy->throttle_temp[i - 1] = val;
|
||||
mutex_unlock(&phy->dev->mt76.mutex);
|
||||
|
||||
ret = mt7915_mcu_set_thermal_protect(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -131,11 +144,11 @@ mt7915_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
|
||||
u8 throttling = MT7915_THERMAL_THROTTLE_MAX - state;
|
||||
int ret;
|
||||
|
||||
if (state > MT7915_CDEV_THROTTLE_MAX)
|
||||
if (state > MT7915_CDEV_THROTTLE_MAX) {
|
||||
dev_err(phy->dev->mt76.dev,
|
||||
"please specify a valid throttling state\n");
|
||||
return -EINVAL;
|
||||
|
||||
if (phy->throttle_temp[0] > phy->throttle_temp[1])
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state == phy->cdev_state)
|
||||
return 0;
|
||||
@@ -164,7 +177,7 @@ static void mt7915_unregister_thermal(struct mt7915_phy *phy)
|
||||
struct wiphy *wiphy = phy->mt76->hw->wiphy;
|
||||
|
||||
if (!phy->cdev)
|
||||
return;
|
||||
return;
|
||||
|
||||
sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
|
||||
thermal_cooling_device_unregister(phy->cdev);
|
||||
@@ -198,11 +211,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
|
||||
return PTR_ERR(hwmon);
|
||||
|
||||
/* initialize critical/maximum high temperature */
|
||||
phy->throttle_temp[0] = 110;
|
||||
phy->throttle_temp[1] = 120;
|
||||
phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
|
||||
phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
|
||||
|
||||
return mt7915_mcu_set_thermal_throttling(phy,
|
||||
MT7915_THERMAL_THROTTLE_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7915_led_set_config(struct led_classdev *led_cdev,
|
||||
@@ -394,11 +406,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
|
||||
|
||||
if (!dev->dbdc_support)
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_SHORT_GI_160 |
|
||||
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
|
||||
} else {
|
||||
phy->mt76->sband_5g.sband.vht_cap.cap |=
|
||||
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
|
||||
@@ -834,13 +841,9 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
|
||||
int sts = hweight8(phy->mt76->chainmask);
|
||||
u8 c, sts_160 = sts;
|
||||
|
||||
/* Can do 1/2 of STS in 160Mhz mode for mt7915 */
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
if (!dev->dbdc_support)
|
||||
sts_160 /= 2;
|
||||
else
|
||||
sts_160 = 0;
|
||||
}
|
||||
/* mt7915 doesn't support bw160 */
|
||||
if (is_mt7915(&dev->mt76))
|
||||
sts_160 = 0;
|
||||
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (vif == NL80211_IFTYPE_MESH_POINT)
|
||||
@@ -894,9 +897,6 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
|
||||
elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
|
||||
elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
|
||||
|
||||
/* num_snd_dim
|
||||
* for mt7915, max supported sts is 2 for bw > 80MHz and 0 if dbdc
|
||||
*/
|
||||
c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
|
||||
sts - 1);
|
||||
if (sts_160)
|
||||
@@ -944,15 +944,10 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
|
||||
u16 mcs_map = 0;
|
||||
u16 mcs_map_160 = 0;
|
||||
u8 nss_160;
|
||||
u8 nss_160 = nss;
|
||||
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
nss_160 = nss;
|
||||
else if (!dev->dbdc_support)
|
||||
/* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
|
||||
nss_160 = nss / 2;
|
||||
else
|
||||
/* Can't do 160MHz with mt7915 dbdc */
|
||||
/* Can't do 160MHz with mt7915 */
|
||||
if (is_mt7915(&dev->mt76))
|
||||
nss_160 = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
@@ -1002,8 +997,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
else if (nss_160)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
|
||||
@@ -1075,12 +1069,11 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
|
||||
break;
|
||||
}
|
||||
|
||||
memset(he_mcs, 0, sizeof(*he_mcs));
|
||||
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map_160);
|
||||
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map_160);
|
||||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map_160);
|
||||
|
||||
mt7915_set_stream_he_txbf_caps(phy, he_cap, i);
|
||||
|
||||
@@ -1172,7 +1165,6 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
|
||||
mt7986_wmac_disable(dev);
|
||||
}
|
||||
|
||||
|
||||
int mt7915_register_device(struct mt7915_dev *dev)
|
||||
{
|
||||
struct mt7915_phy *phy2;
|
||||
|
||||
@@ -256,8 +256,7 @@ mt7915_wed_check_ppe(struct mt7915_dev *dev, struct mt76_queue *q,
|
||||
if (!msta || !msta->vif)
|
||||
return;
|
||||
|
||||
if (!(q->flags & MT_QFLAG_WED) ||
|
||||
FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) != MT76_WED_Q_RX)
|
||||
if (!mt76_queue_is_wed_rx(q))
|
||||
return;
|
||||
|
||||
if (!(info & MT_DMA_INFO_PPE_VLD))
|
||||
@@ -1061,9 +1060,6 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
|
||||
u16 wcidx;
|
||||
u8 pid;
|
||||
|
||||
if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1)
|
||||
return;
|
||||
|
||||
wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);
|
||||
pid = le32_get_bits(txs_data[3], MT_TXS3_PID);
|
||||
|
||||
@@ -1582,6 +1578,12 @@ void mt7915_mac_reset_work(struct work_struct *work)
|
||||
if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
|
||||
return;
|
||||
|
||||
if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
|
||||
mtk_wed_device_stop(&dev->mt76.mmio.wed);
|
||||
if (!is_mt7986(&dev->mt76))
|
||||
mt76_wr(dev, MT_INT_WED_MASK_CSR, 0);
|
||||
}
|
||||
|
||||
ieee80211_stop_queues(mt76_hw(dev));
|
||||
if (ext_phy)
|
||||
ieee80211_stop_queues(ext_phy->hw);
|
||||
|
||||
@@ -57,6 +57,17 @@ int mt7915_run(struct ieee80211_hw *hw)
|
||||
mt7915_mac_enable_nf(dev, phy->mt76->band_idx);
|
||||
}
|
||||
|
||||
ret = mt7915_mcu_set_thermal_throttling(phy,
|
||||
MT7915_THERMAL_THROTTLE_MAX);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt7915_mcu_set_thermal_protect(phy);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b,
|
||||
phy->mt76->band_idx);
|
||||
if (ret)
|
||||
@@ -1280,19 +1291,22 @@ void mt7915_get_et_strings(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 sset, u8 *data)
|
||||
{
|
||||
if (sset == ETH_SS_STATS)
|
||||
memcpy(data, *mt7915_gstrings_stats,
|
||||
sizeof(mt7915_gstrings_stats));
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
memcpy(data, *mt7915_gstrings_stats, sizeof(mt7915_gstrings_stats));
|
||||
data += sizeof(mt7915_gstrings_stats);
|
||||
page_pool_ethtool_stats_get_strings(data);
|
||||
}
|
||||
|
||||
static
|
||||
int mt7915_get_et_sset_count(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int sset)
|
||||
{
|
||||
if (sset == ETH_SS_STATS)
|
||||
return MT7915_SSTATS_LEN;
|
||||
if (sset != ETH_SS_STATS)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
return MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();
|
||||
}
|
||||
|
||||
static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
|
||||
@@ -1303,7 +1317,7 @@ static void mt7915_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
|
||||
if (msta->vif->mt76.idx != wi->idx)
|
||||
return;
|
||||
|
||||
mt76_ethtool_worker(wi, &msta->wcid.stats);
|
||||
mt76_ethtool_worker(wi, &msta->wcid.stats, false);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -1320,7 +1334,7 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
|
||||
};
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
/* See mt7915_ampdu_stat_read_phy, etc */
|
||||
int i, ei = 0;
|
||||
int i, ei = 0, stats_size;
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
@@ -1401,9 +1415,12 @@ void mt7915_get_et_stats(struct ieee80211_hw *hw,
|
||||
return;
|
||||
|
||||
ei += wi.worker_stat_count;
|
||||
if (ei != MT7915_SSTATS_LEN)
|
||||
dev_err(dev->mt76.dev, "ei: %d MT7915_SSTATS_LEN: %d",
|
||||
ei, (int)MT7915_SSTATS_LEN);
|
||||
|
||||
mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);
|
||||
|
||||
stats_size = MT7915_SSTATS_LEN + page_pool_ethtool_stats_get_count();
|
||||
if (ei != stats_size)
|
||||
dev_err(dev->mt76.dev, "ei: %d size: %d", ei, stats_size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -2117,7 +2117,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
|
||||
/* make sure fw is download state */
|
||||
if (mt7915_firmware_state(dev, false)) {
|
||||
/* restart firmware once */
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt76_connac_mcu_restart(&dev->mt76);
|
||||
ret = mt7915_firmware_state(dev, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev,
|
||||
@@ -2291,6 +2291,53 @@ mt7915_mcu_init_rx_airtime(struct mt7915_dev *dev)
|
||||
sizeof(req), true);
|
||||
}
|
||||
|
||||
static int mt7915_red_set_watermark(struct mt7915_dev *dev)
|
||||
{
|
||||
#define RED_GLOBAL_TOKEN_WATERMARK 2
|
||||
struct {
|
||||
__le32 args[3];
|
||||
u8 cmd;
|
||||
u8 version;
|
||||
u8 __rsv1[4];
|
||||
__le16 len;
|
||||
__le16 high_mark;
|
||||
__le16 low_mark;
|
||||
u8 __rsv2[12];
|
||||
} __packed req = {
|
||||
.args[0] = cpu_to_le32(MCU_WA_PARAM_RED_SETTING),
|
||||
.cmd = RED_GLOBAL_TOKEN_WATERMARK,
|
||||
.len = cpu_to_le16(sizeof(req) - sizeof(req.args)),
|
||||
.high_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256),
|
||||
.low_mark = cpu_to_le16(MT7915_HW_TOKEN_SIZE - 256 - 1536),
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_WA_PARAM_CMD(SET), &req,
|
||||
sizeof(req), false);
|
||||
}
|
||||
|
||||
static int mt7915_mcu_set_red(struct mt7915_dev *dev, bool enabled)
|
||||
{
|
||||
#define RED_DISABLE 0
|
||||
#define RED_BY_WA_ENABLE 2
|
||||
int ret;
|
||||
u32 red_type = enabled ? RED_BY_WA_ENABLE : RED_DISABLE;
|
||||
__le32 req = cpu_to_le32(red_type);
|
||||
|
||||
if (enabled) {
|
||||
ret = mt7915_red_set_watermark(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RED_ENABLE), &req,
|
||||
sizeof(req), false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
|
||||
MCU_WA_PARAM_RED, enabled, 0);
|
||||
}
|
||||
|
||||
int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -2339,8 +2386,7 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET),
|
||||
MCU_WA_PARAM_RED, 0, 0);
|
||||
return mt7915_mcu_set_red(dev, mtk_wed_device_active(&dev->mt76.mmio.wed));
|
||||
}
|
||||
|
||||
int mt7915_mcu_init(struct mt7915_dev *dev)
|
||||
@@ -2349,7 +2395,6 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7915_mcu_send_message,
|
||||
.mcu_parse_response = mt7915_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
};
|
||||
|
||||
dev->mt76.mcu_ops = &mt7915_mcu_ops;
|
||||
@@ -2359,16 +2404,17 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
|
||||
|
||||
void mt7915_mcu_exit(struct mt7915_dev *dev)
|
||||
{
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt76_connac_mcu_restart(&dev->mt76);
|
||||
if (mt7915_firmware_state(dev, false)) {
|
||||
dev_err(dev->mt76.dev, "Failed to exit mcu\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1),
|
||||
MT_TOP_LPCR_HOST_FW_OWN);
|
||||
out:
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
@@ -3077,6 +3123,29 @@ int mt7915_mcu_get_temperature(struct mt7915_phy *phy)
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
struct mt7915_mcu_thermal_ctrl req = {
|
||||
.band_idx = phy->mt76->band_idx,
|
||||
.ctrl_id = THERMAL_PROTECT_DUTY_CONFIG,
|
||||
};
|
||||
int level, ret;
|
||||
|
||||
/* set duty cycle and level */
|
||||
for (level = 0; level < 4; level++) {
|
||||
req.duty.duty_level = level;
|
||||
req.duty.duty_cycle = state;
|
||||
state /= 2;
|
||||
|
||||
ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
|
||||
&req, sizeof(req), false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
struct {
|
||||
@@ -3089,29 +3158,18 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
|
||||
} __packed req = {
|
||||
.ctrl = {
|
||||
.band_idx = phy->mt76->band_idx,
|
||||
.type.protect_type = 1,
|
||||
.type.trigger_type = 1,
|
||||
},
|
||||
};
|
||||
int level;
|
||||
int ret;
|
||||
|
||||
if (!state) {
|
||||
req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;
|
||||
goto out;
|
||||
}
|
||||
req.ctrl.ctrl_id = THERMAL_PROTECT_DISABLE;
|
||||
ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
|
||||
&req, sizeof(req.ctrl), false);
|
||||
|
||||
/* set duty cycle and level */
|
||||
for (level = 0; level < 4; level++) {
|
||||
int ret;
|
||||
|
||||
req.ctrl.ctrl_id = THERMAL_PROTECT_DUTY_CONFIG;
|
||||
req.ctrl.duty.duty_level = level;
|
||||
req.ctrl.duty.duty_cycle = state;
|
||||
state /= 2;
|
||||
|
||||
ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
|
||||
&req, sizeof(req.ctrl), false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* set high-temperature trigger threshold */
|
||||
req.ctrl.ctrl_id = THERMAL_PROTECT_ENABLE;
|
||||
@@ -3120,10 +3178,6 @@ int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state)
|
||||
req.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
|
||||
req.sustain_time = cpu_to_le16(10);
|
||||
|
||||
out:
|
||||
req.ctrl.type.protect_type = 1;
|
||||
req.ctrl.type.trigger_type = 1;
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(THERMAL_PROT),
|
||||
&req, sizeof(req), false);
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@ enum {
|
||||
MCU_WA_PARAM_PDMA_RX = 0x04,
|
||||
MCU_WA_PARAM_CPU_UTIL = 0x0b,
|
||||
MCU_WA_PARAM_RED = 0x0e,
|
||||
MCU_WA_PARAM_RED_SETTING = 0x40,
|
||||
};
|
||||
|
||||
enum mcu_mmps_mode {
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "mt7915.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "../trace.h"
|
||||
#include "../dma.h"
|
||||
|
||||
@@ -594,13 +596,9 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
|
||||
static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
|
||||
{
|
||||
struct mt7915_dev *dev;
|
||||
u32 length;
|
||||
int i;
|
||||
|
||||
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
|
||||
length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
|
||||
sizeof(struct skb_shared_info));
|
||||
|
||||
for (i = 0; i < dev->mt76.rx_token_size; i++) {
|
||||
struct mt76_txwi_cache *t;
|
||||
|
||||
@@ -608,52 +606,50 @@ static void mt7915_mmio_wed_release_rx_buf(struct mtk_wed_device *wed)
|
||||
if (!t || !t->ptr)
|
||||
continue;
|
||||
|
||||
dma_unmap_single(dev->mt76.dma_dev, t->dma_addr,
|
||||
wed->wlan.rx_size, DMA_FROM_DEVICE);
|
||||
__free_pages(virt_to_page(t->ptr), get_order(length));
|
||||
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_rxbm_desc *desc = wed->rx_buf_ring.desc;
|
||||
struct mt76_txwi_cache *t = NULL;
|
||||
struct mt7915_dev *dev;
|
||||
u32 length;
|
||||
int i;
|
||||
struct mt76_queue *q;
|
||||
int i, len;
|
||||
|
||||
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
|
||||
length = SKB_DATA_ALIGN(NET_SKB_PAD + wed->wlan.rx_size +
|
||||
sizeof(struct skb_shared_info));
|
||||
q = &dev->mt76.q_rx[MT_RXQ_MAIN];
|
||||
len = SKB_WITH_OVERHEAD(q->buf_size);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
struct mt76_txwi_cache *t = mt76_get_rxwi(&dev->mt76);
|
||||
dma_addr_t phy_addr;
|
||||
struct page *page;
|
||||
enum dma_data_direction dir;
|
||||
dma_addr_t addr;
|
||||
u32 offset;
|
||||
int token;
|
||||
void *ptr;
|
||||
void *buf;
|
||||
|
||||
page = __dev_alloc_pages(GFP_KERNEL, get_order(length));
|
||||
if (!page)
|
||||
t = mt76_get_rxwi(&dev->mt76);
|
||||
if (!t)
|
||||
goto unmap;
|
||||
|
||||
ptr = page_address(page);
|
||||
phy_addr = dma_map_single(dev->mt76.dma_dev, ptr,
|
||||
wed->wlan.rx_size,
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev->mt76.dev, phy_addr))) {
|
||||
__free_pages(page, get_order(length));
|
||||
buf = mt76_get_page_pool_buf(q, &offset, q->buf_size);
|
||||
if (!buf)
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
desc->buf0 = cpu_to_le32(phy_addr);
|
||||
token = mt76_rx_token_consume(&dev->mt76, ptr, t, phy_addr);
|
||||
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) {
|
||||
dma_unmap_single(dev->mt76.dma_dev, phy_addr,
|
||||
wed->wlan.rx_size, DMA_TO_DEVICE);
|
||||
__free_pages(page, get_order(length));
|
||||
mt76_put_page_pool_buf(buf, false);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
@@ -665,6 +661,8 @@ static u32 mt7915_mmio_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
|
||||
return 0;
|
||||
|
||||
unmap:
|
||||
if (t)
|
||||
mt76_put_rxwi(&dev->mt76, t);
|
||||
mt7915_mmio_wed_release_rx_buf(wed);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -693,6 +691,42 @@ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed,
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int mt7915_mmio_wed_reset(struct mtk_wed_device *wed)
|
||||
{
|
||||
struct mt76_dev *mdev = container_of(wed, struct mt76_dev, mmio.wed);
|
||||
struct mt7915_dev *dev = container_of(mdev, struct mt7915_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 = mt7915_mcu_set_ser(dev, SER_RECOVER, 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;
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -748,7 +782,7 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.wpdma_rx_glo = res->start + MT_WPDMA_GLO_CFG;
|
||||
wed->wlan.wpdma_rx = res->start + MT_RXQ_WED_DATA_RING_BASE;
|
||||
}
|
||||
wed->wlan.nbuf = 4096;
|
||||
wed->wlan.nbuf = MT7915_HW_TOKEN_SIZE;
|
||||
wed->wlan.tx_tbit[0] = is_mt7915(&dev->mt76) ? 4 : 30;
|
||||
wed->wlan.tx_tbit[1] = is_mt7915(&dev->mt76) ? 5 : 31;
|
||||
wed->wlan.txfree_tbit = is_mt7986(&dev->mt76) ? 2 : 1;
|
||||
@@ -775,6 +809,8 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.init_rx_buf = mt7915_mmio_wed_init_rx_buf;
|
||||
wed->wlan.release_rx_buf = mt7915_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;
|
||||
|
||||
dev->mt76.rx_token_size = wed->wlan.rx_npkt;
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define MT7916_EEPROM_SIZE 4096
|
||||
|
||||
#define MT7915_EEPROM_BLOCK_SIZE 16
|
||||
#define MT7915_HW_TOKEN_SIZE 4096
|
||||
#define MT7915_TOKEN_SIZE 8192
|
||||
|
||||
#define MT7915_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
|
||||
@@ -70,6 +71,11 @@
|
||||
|
||||
#define MT7915_WED_RX_TOKEN_SIZE 12288
|
||||
|
||||
#define MT7915_CRIT_TEMP_IDX 0
|
||||
#define MT7915_MAX_TEMP_IDX 1
|
||||
#define MT7915_CRIT_TEMP 110
|
||||
#define MT7915_MAX_TEMP 120
|
||||
|
||||
struct mt7915_vif;
|
||||
struct mt7915_sta;
|
||||
struct mt7915_dfs_pulse;
|
||||
@@ -543,6 +549,7 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy);
|
||||
int mt7915_mcu_get_chan_mib_info(struct mt7915_phy *phy, bool chan_switch);
|
||||
int mt7915_mcu_get_temperature(struct mt7915_phy *phy);
|
||||
int mt7915_mcu_set_thermal_throttling(struct mt7915_phy *phy, u8 state);
|
||||
int mt7915_mcu_set_thermal_protect(struct mt7915_phy *phy);
|
||||
int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct rate_info *rate);
|
||||
int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
||||
|
||||
@@ -883,6 +883,8 @@ static int mt7986_wmac_wm_enable(struct mt7915_dev *dev, bool enable)
|
||||
{
|
||||
u32 cur;
|
||||
|
||||
mt76_wr(dev, MT_CONNINFRA_SKU_DEC_ADDR, 0);
|
||||
|
||||
mt76_rmw_field(dev, MT7986_TOP_WM_RESET,
|
||||
MT7986_TOP_WM_RESET_MASK, enable);
|
||||
if (!enable)
|
||||
|
||||
@@ -33,14 +33,17 @@ mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
|
||||
sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
|
||||
dev_err(mdev->dev, "sar cnt = %d\n",
|
||||
sar_root->package.count);
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (!*tbl) {
|
||||
*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
|
||||
GFP_KERNEL);
|
||||
if (!*tbl)
|
||||
if (!*tbl) {
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
if (len)
|
||||
*len = sar_root->package.count;
|
||||
@@ -52,9 +55,9 @@ mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
|
||||
break;
|
||||
*(*tbl + i) = (u8)sar_unit->integer.value;
|
||||
}
|
||||
free:
|
||||
ret = (i == sar_root->package.count) ? 0 : -EINVAL;
|
||||
|
||||
free:
|
||||
kfree(sar_root);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -120,6 +120,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
|
||||
|
||||
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
|
||||
@@ -142,6 +143,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
|
||||
static void
|
||||
mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
|
||||
{
|
||||
u32 mask, set;
|
||||
|
||||
mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
|
||||
MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
|
||||
mt76_set(dev, MT_TMAC_CTCR0(band),
|
||||
@@ -158,6 +161,12 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
|
||||
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
|
||||
/* disable rx rate report by default due to hw issues */
|
||||
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
|
||||
|
||||
/* filter out non-resp frames and get instantaneous signal reporting */
|
||||
mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
|
||||
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
|
||||
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
|
||||
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
|
||||
}
|
||||
|
||||
u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
|
||||
@@ -229,8 +238,6 @@ int mt7921_mac_init(struct mt7921_dev *dev)
|
||||
for (i = 0; i < 2; i++)
|
||||
mt7921_mac_init_band(dev, i);
|
||||
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0));
|
||||
|
||||
return mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mac_init);
|
||||
|
||||
@@ -59,6 +59,7 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
|
||||
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
|
||||
LIST_HEAD(sta_poll_list);
|
||||
struct rate_info *rate;
|
||||
s8 rssi[4];
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
@@ -160,6 +161,20 @@ void mt7921_mac_sta_poll(struct mt7921_dev *dev)
|
||||
else
|
||||
rate->flags &= ~RATE_INFO_FLAGS_SHORT_GI;
|
||||
}
|
||||
|
||||
/* get signal strength of resp frames (CTS/BA/ACK) */
|
||||
addr = mt7921_mac_wtbl_lmac_addr(idx, 30);
|
||||
val = mt76_rr(dev, addr);
|
||||
|
||||
rssi[0] = to_rssi(GENMASK(7, 0), val);
|
||||
rssi[1] = to_rssi(GENMASK(15, 8), val);
|
||||
rssi[2] = to_rssi(GENMASK(23, 16), val);
|
||||
rssi[3] = to_rssi(GENMASK(31, 14), val);
|
||||
|
||||
msta->ack_signal =
|
||||
mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
|
||||
|
||||
ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mac_sta_poll);
|
||||
|
||||
@@ -422,15 +422,15 @@ void mt7921_roc_timer(struct timer_list *timer)
|
||||
|
||||
static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return 0;
|
||||
int err = 0;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
|
||||
clear_bit(MT76_STATE_ROC, &phy->mt76->state);
|
||||
|
||||
mt7921_mutex_acquire(phy->dev);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
|
||||
mt7921_mutex_release(phy->dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -487,13 +487,8 @@ static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
int err;
|
||||
|
||||
mt7921_mutex_acquire(phy->dev);
|
||||
err = mt7921_abort_roc(phy, mvif);
|
||||
mt7921_mutex_release(phy->dev);
|
||||
|
||||
return err;
|
||||
return mt7921_abort_roc(phy, mvif);
|
||||
}
|
||||
|
||||
static int mt7921_set_channel(struct mt7921_phy *phy)
|
||||
@@ -681,7 +676,6 @@ static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7921_sniffer_interface_iter, dev);
|
||||
dev->mt76.rxfilter = mt76_rr(dev, MT_WF_RFCR(0));
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -710,53 +704,12 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
|
||||
u64 multicast)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
|
||||
MT_WF_RFCR1_DROP_BF_POLL |
|
||||
MT_WF_RFCR1_DROP_BA |
|
||||
MT_WF_RFCR1_DROP_CFEND |
|
||||
MT_WF_RFCR1_DROP_CFACK;
|
||||
u32 flags = 0;
|
||||
|
||||
#define MT76_FILTER(_flag, _hw) do { \
|
||||
flags |= *total_flags & FIF_##_flag; \
|
||||
dev->mt76.rxfilter &= ~(_hw); \
|
||||
dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \
|
||||
} while (0)
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
|
||||
dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON |
|
||||
MT_WF_RFCR_DROP_FRAME_REPORT |
|
||||
MT_WF_RFCR_DROP_PROBEREQ |
|
||||
MT_WF_RFCR_DROP_MCAST_FILTERED |
|
||||
MT_WF_RFCR_DROP_MCAST |
|
||||
MT_WF_RFCR_DROP_BCAST |
|
||||
MT_WF_RFCR_DROP_DUPLICATE |
|
||||
MT_WF_RFCR_DROP_A2_BSSID |
|
||||
MT_WF_RFCR_DROP_UNWANTED_CTL |
|
||||
MT_WF_RFCR_DROP_STBC_MULTI);
|
||||
|
||||
MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
|
||||
MT_WF_RFCR_DROP_A3_MAC |
|
||||
MT_WF_RFCR_DROP_A3_BSSID);
|
||||
|
||||
MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
|
||||
|
||||
MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
|
||||
MT_WF_RFCR_DROP_RTS |
|
||||
MT_WF_RFCR_DROP_CTL_RSV |
|
||||
MT_WF_RFCR_DROP_NDPA);
|
||||
|
||||
*total_flags = flags;
|
||||
mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter);
|
||||
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
mt76_clear(dev, MT_WF_RFCR1(0), ctl_flags);
|
||||
else
|
||||
mt76_set(dev, MT_WF_RFCR1(0), ctl_flags);
|
||||
|
||||
mt7921_mcu_set_rxfilter(dev, *total_flags, 0, 0);
|
||||
mt7921_mutex_release(dev);
|
||||
|
||||
*total_flags &= (FIF_OTHER_BSS | FIF_FCSFAIL | FIF_CONTROL);
|
||||
}
|
||||
|
||||
static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
|
||||
@@ -860,6 +813,8 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
|
||||
true, mvif->ctx);
|
||||
|
||||
ewma_avg_signal_init(&msta->avg_ack_signal);
|
||||
|
||||
mt7921_mac_wtbl_update(dev, msta->wcid.idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
|
||||
@@ -1135,17 +1090,34 @@ static void
|
||||
mt7921_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 sset, u8 *data)
|
||||
{
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
memcpy(data, *mt7921_gstrings_stats, sizeof(mt7921_gstrings_stats));
|
||||
|
||||
if (mt76_is_sdio(&dev->mt76))
|
||||
return;
|
||||
|
||||
data += sizeof(mt7921_gstrings_stats);
|
||||
page_pool_ethtool_stats_get_strings(data);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
int sset)
|
||||
{
|
||||
return sset == ETH_SS_STATS ? ARRAY_SIZE(mt7921_gstrings_stats) : 0;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
if (sset != ETH_SS_STATS)
|
||||
return 0;
|
||||
|
||||
if (mt76_is_sdio(&dev->mt76))
|
||||
return ARRAY_SIZE(mt7921_gstrings_stats);
|
||||
|
||||
return ARRAY_SIZE(mt7921_gstrings_stats) +
|
||||
page_pool_ethtool_stats_get_count();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1157,7 +1129,7 @@ mt7921_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
|
||||
if (msta->vif->mt76.idx != wi->idx)
|
||||
return;
|
||||
|
||||
mt76_ethtool_worker(wi, &msta->wcid.stats);
|
||||
mt76_ethtool_worker(wi, &msta->wcid.stats, false);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -1165,6 +1137,7 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
int stats_size = ARRAY_SIZE(mt7921_gstrings_stats);
|
||||
struct mt7921_phy *phy = mt7921_hw_phy(hw);
|
||||
struct mt7921_dev *dev = phy->dev;
|
||||
struct mib_stats *mib = &phy->mib;
|
||||
@@ -1220,9 +1193,14 @@ void mt7921_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
return;
|
||||
|
||||
ei += wi.worker_stat_count;
|
||||
if (ei != ARRAY_SIZE(mt7921_gstrings_stats))
|
||||
dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %zu",
|
||||
ei, ARRAY_SIZE(mt7921_gstrings_stats));
|
||||
|
||||
if (!mt76_is_sdio(&dev->mt76)) {
|
||||
mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);
|
||||
stats_size += page_pool_ethtool_stats_get_count();
|
||||
}
|
||||
|
||||
if (ei != stats_size)
|
||||
dev_err(dev->mt76.dev, "ei: %d SSTATS_LEN: %d", ei, stats_size);
|
||||
}
|
||||
|
||||
static u64
|
||||
@@ -1430,6 +1408,12 @@ static void mt7921_sta_statistics(struct ieee80211_hw *hw,
|
||||
}
|
||||
sinfo->txrate.flags = txrate->flags;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
|
||||
|
||||
sinfo->ack_signal = (s8)msta->ack_signal;
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
|
||||
|
||||
sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->avg_ack_signal);
|
||||
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -1711,7 +1695,10 @@ static void mt7921_ctx_iter(void *priv, u8 *mac,
|
||||
if (ctx != mvif->ctx)
|
||||
return;
|
||||
|
||||
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
|
||||
if (vif->type & NL80211_IFTYPE_MONITOR)
|
||||
mt7921_mcu_config_sniffer(mvif, ctx);
|
||||
else
|
||||
mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1778,11 +1765,8 @@ static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_prep_tx_info *info)
|
||||
{
|
||||
struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
|
||||
struct mt7921_dev *dev = mt7921_hw_dev(hw);
|
||||
|
||||
mt7921_mutex_acquire(dev);
|
||||
mt7921_abort_roc(mvif->phy, mvif);
|
||||
mt7921_mutex_release(dev);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7921_ops = {
|
||||
|
||||
@@ -174,7 +174,7 @@ mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb)
|
||||
wake_up(&dev->phy.roc_wait);
|
||||
duration = le32_to_cpu(grant->max_interval);
|
||||
mod_timer(&dev->phy.roc_timer,
|
||||
round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
|
||||
jiffies + msecs_to_jiffies(duration));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1019,6 +1019,8 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable)
|
||||
{
|
||||
#define MT7921_FIF_BIT_CLR BIT(1)
|
||||
#define MT7921_FIF_BIT_SET BIT(0)
|
||||
int err;
|
||||
|
||||
if (enable) {
|
||||
@@ -1026,7 +1028,11 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_set(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
err = mt7921_mcu_set_rxfilter(dev, 0,
|
||||
MT7921_FIF_BIT_SET,
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1035,7 +1041,11 @@ int mt7921_mcu_set_beacon_filter(struct mt7921_dev *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
err = mt7921_mcu_set_rxfilter(dev, 0,
|
||||
MT7921_FIF_BIT_CLR,
|
||||
MT_WF_RFCR_DROP_OTHER_BEACON);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1093,6 +1103,74 @@ int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
true);
|
||||
}
|
||||
|
||||
int mt7921_mcu_config_sniffer(struct mt7921_vif *vif,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &ctx->def;
|
||||
int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
|
||||
const u8 ch_band[] = {
|
||||
[NL80211_BAND_2GHZ] = 1,
|
||||
[NL80211_BAND_5GHZ] = 2,
|
||||
[NL80211_BAND_6GHZ] = 3,
|
||||
};
|
||||
const u8 ch_width[] = {
|
||||
[NL80211_CHAN_WIDTH_20_NOHT] = 0,
|
||||
[NL80211_CHAN_WIDTH_20] = 0,
|
||||
[NL80211_CHAN_WIDTH_40] = 0,
|
||||
[NL80211_CHAN_WIDTH_80] = 1,
|
||||
[NL80211_CHAN_WIDTH_160] = 2,
|
||||
[NL80211_CHAN_WIDTH_80P80] = 3,
|
||||
[NL80211_CHAN_WIDTH_5] = 4,
|
||||
[NL80211_CHAN_WIDTH_10] = 5,
|
||||
[NL80211_CHAN_WIDTH_320] = 6,
|
||||
};
|
||||
struct {
|
||||
struct {
|
||||
u8 band_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct config_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u16 aid;
|
||||
u8 ch_band;
|
||||
u8 bw;
|
||||
u8 control_ch;
|
||||
u8 sco;
|
||||
u8 center_ch;
|
||||
u8 center_ch2;
|
||||
u8 drop_err;
|
||||
u8 pad[3];
|
||||
} __packed tlv;
|
||||
} __packed req = {
|
||||
.hdr = {
|
||||
.band_idx = vif->mt76.band_idx,
|
||||
},
|
||||
.tlv = {
|
||||
.tag = cpu_to_le16(1),
|
||||
.len = cpu_to_le16(sizeof(req.tlv)),
|
||||
.control_ch = chandef->chan->hw_value,
|
||||
.center_ch = ieee80211_frequency_to_channel(freq1),
|
||||
.drop_err = 1,
|
||||
},
|
||||
};
|
||||
if (chandef->chan->band < ARRAY_SIZE(ch_band))
|
||||
req.tlv.ch_band = ch_band[chandef->chan->band];
|
||||
if (chandef->width < ARRAY_SIZE(ch_width))
|
||||
req.tlv.bw = ch_width[chandef->width];
|
||||
|
||||
if (freq2)
|
||||
req.tlv.center_ch2 = ieee80211_frequency_to_channel(freq2);
|
||||
|
||||
if (req.tlv.control_ch < req.tlv.center_ch)
|
||||
req.tlv.sco = 1; /* SCA */
|
||||
else if (req.tlv.control_ch > req.tlv.center_ch)
|
||||
req.tlv.sco = 3; /* SCB */
|
||||
|
||||
return mt76_mcu_send_msg(vif->phy->mt76->dev, MCU_UNI_CMD(SNIFFER),
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
int
|
||||
mt7921_mcu_uni_add_beacon_offload(struct mt7921_dev *dev,
|
||||
struct ieee80211_hw *hw,
|
||||
@@ -1255,3 +1333,25 @@ int mt7921_mcu_set_clc(struct mt7921_dev *dev, u8 *alpha2,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map)
|
||||
{
|
||||
struct {
|
||||
u8 rsv[4];
|
||||
u8 mode;
|
||||
u8 rsv2[3];
|
||||
__le32 fif;
|
||||
__le32 bit_map; /* bit_* for bitmap update */
|
||||
u8 bit_op;
|
||||
u8 pad[51];
|
||||
} __packed data = {
|
||||
.mode = fif ? 1 : 2,
|
||||
.fif = cpu_to_le32(fif),
|
||||
.bit_map = cpu_to_le32(bit_map),
|
||||
.bit_op = bit_op,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER),
|
||||
&data, sizeof(data), false);
|
||||
}
|
||||
|
||||
@@ -144,6 +144,8 @@ enum mt7921_rxq_id {
|
||||
MT7921_RXQ_MCU_WM = 0,
|
||||
};
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
|
||||
struct mt7921_sta {
|
||||
struct mt76_wcid wcid; /* must be first */
|
||||
|
||||
@@ -152,6 +154,9 @@ struct mt7921_sta {
|
||||
struct list_head poll_list;
|
||||
u32 airtime_ac[8];
|
||||
|
||||
int ack_signal;
|
||||
struct ewma_avg_signal avg_ack_signal;
|
||||
|
||||
unsigned long last_txs;
|
||||
unsigned long ampdu_state;
|
||||
|
||||
@@ -383,6 +388,8 @@ int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct rate_info *rate);
|
||||
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl);
|
||||
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
|
||||
int mt7921_mcu_set_rxfilter(struct mt7921_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map);
|
||||
|
||||
static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
|
||||
{
|
||||
@@ -529,6 +536,8 @@ void mt7921_set_ipv6_ns_work(struct work_struct *work);
|
||||
|
||||
int mt7921_mcu_set_sniffer(struct mt7921_dev *dev, struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7921_mcu_config_sniffer(struct mt7921_vif *vif,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
|
||||
int mt7921_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
|
||||
@@ -44,7 +44,6 @@ int mt7921e_mcu_init(struct mt7921_dev *dev)
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd),
|
||||
.mcu_skb_send_msg = mt7921_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
};
|
||||
int err;
|
||||
|
||||
@@ -69,8 +68,8 @@ int __mt7921e_mcu_drv_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
|
||||
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);
|
||||
if (mt76_poll_msec(dev, MT_CONN_ON_LPCTL,
|
||||
PCIE_LPCR_HOST_OWN_SYNC, 0, 50))
|
||||
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
|
||||
PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -110,8 +109,8 @@ int mt7921e_mcu_fw_pmctrl(struct mt7921_dev *dev)
|
||||
|
||||
for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
|
||||
mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);
|
||||
if (mt76_poll_msec(dev, MT_CONN_ON_LPCTL,
|
||||
PCIE_LPCR_HOST_OWN_SYNC, 4, 50))
|
||||
if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,
|
||||
PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,14 @@
|
||||
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3)
|
||||
#define MT_DMA_DCR0_RXD_G5_EN BIT(23)
|
||||
|
||||
/* WTBLOFF TOP: band 0(0x820e9000),band 1(0x820f9000) */
|
||||
#define MT_WTBLOFF_TOP_BASE(_band) ((_band) ? 0x820f9000 : 0x820e9000)
|
||||
#define MT_WTBLOFF_TOP(_band, ofs) (MT_WTBLOFF_TOP_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_WTBLOFF_TOP_RSCR(_band) MT_WTBLOFF_TOP(_band, 0x008)
|
||||
#define MT_WTBLOFF_TOP_RSCR_RCPI_MODE GENMASK(31, 30)
|
||||
#define MT_WTBLOFF_TOP_RSCR_RCPI_PARAM GENMASK(25, 24)
|
||||
|
||||
/* LPON: band 0(0x24200), band 1(0xa4200) */
|
||||
#define MT_WF_LPON_BASE(_band) ((_band) ? 0x820fb000 : 0x820eb000)
|
||||
#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs))
|
||||
|
||||
@@ -59,7 +59,6 @@ mt7921_tm_set(struct mt7921_dev *dev, struct mt7921_tm_cmd *req)
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
__mt7921_mcu_drv_pmctrl(dev);
|
||||
|
||||
mt76_wr(dev, MT_WF_RFCR(0), dev->mt76.rxfilter);
|
||||
phy->test.state = MT76_TM_STATE_ON;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
static const struct usb_device_id mt7921u_device_table[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x0e8d, 0x7961, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
/* Comfast CF-952AX */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3574, 0x6211, 0xff, 0xff, 0xff),
|
||||
.driver_info = (kernel_ulong_t)MT7921_FIRMWARE_WM },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -133,7 +136,6 @@ static int mt7921u_mcu_init(struct mt7921_dev *dev)
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7921u_mcu_send_message,
|
||||
.mcu_parse_response = mt7921_mcu_parse_response,
|
||||
.mcu_restart = mt76_connac_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -791,10 +791,10 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
|
||||
else
|
||||
buf[count] = '\0';
|
||||
|
||||
/* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9
|
||||
* bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3
|
||||
* nss - vht: 1~4, he: 1~4, others: ignore
|
||||
* mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2
|
||||
/* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9 EHT: 15
|
||||
* bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3, BW320: 4
|
||||
* nss - vht: 1~4, he: 1~4, eht: 1~4, others: ignore
|
||||
* mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2, eht: 0~13
|
||||
* gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2
|
||||
* preamble - short: 1, long: 0
|
||||
* ldpc - off: 0, on: 1
|
||||
|
||||
@@ -87,6 +87,28 @@ static int mt7996_eeprom_load(struct mt7996_dev *dev)
|
||||
return mt7996_check_eeprom(dev);
|
||||
}
|
||||
|
||||
static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
|
||||
{
|
||||
#define MODE_HE_ONLY BIT(0)
|
||||
#define WTBL_SIZE_GROUP GENMASK(31, 28)
|
||||
u32 cap = 0;
|
||||
int ret;
|
||||
|
||||
ret = mt7996_mcu_get_chip_config(dev, &cap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cap) {
|
||||
dev->has_eht = !(cap & MODE_HE_ONLY);
|
||||
dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
|
||||
}
|
||||
|
||||
if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4)
|
||||
dev->wtbl_size_group = 2; /* set default */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)
|
||||
{
|
||||
u8 *eeprom = phy->dev->mt76.eeprom.data;
|
||||
@@ -133,6 +155,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
|
||||
u8 path, nss, band_idx = phy->mt76->band_idx;
|
||||
u8 *eeprom = dev->mt76.eeprom.data;
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
int ret;
|
||||
|
||||
switch (band_idx) {
|
||||
case MT_BAND1:
|
||||
@@ -167,6 +190,10 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
|
||||
dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] +
|
||||
hweight16(mphy->chainmask);
|
||||
|
||||
ret = mt7996_eeprom_parse_efuse_hw_cap(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7996_eeprom_parse_band_config(phy);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160) |
|
||||
BIT(NL80211_CHAN_WIDTH_80P80),
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,10 +152,12 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
|
||||
struct mt7996_phy *phy = mt7996_hw_phy(hw);
|
||||
struct mt76_dev *mdev = &phy->dev->mt76;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
u16 max_subframes = phy->dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT :
|
||||
IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
|
||||
hw->queues = 4;
|
||||
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
hw->max_rx_aggregation_subframes = max_subframes;
|
||||
hw->max_tx_aggregation_subframes = max_subframes;
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
|
||||
hw->radiotap_timestamp.units_pos =
|
||||
@@ -214,7 +215,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_caps(phy);
|
||||
mt7996_set_stream_he_eht_caps(phy);
|
||||
|
||||
wiphy->available_antennas_rx = phy->mt76->antenna_mask;
|
||||
wiphy->available_antennas_tx = phy->mt76->antenna_mask;
|
||||
@@ -256,7 +257,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
|
||||
|
||||
mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
|
||||
|
||||
for (i = 0; i < MT7996_WTBL_SIZE; i++)
|
||||
for (i = 0; i < mt7996_wtbl_size(dev); i++)
|
||||
mt7996_mac_wtbl_update(dev, i,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
|
||||
@@ -465,7 +466,7 @@ void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy)
|
||||
|
||||
*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
||||
(3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
|
||||
FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, sts - 1);
|
||||
|
||||
*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
|
||||
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||
@@ -572,11 +573,15 @@ mt7996_gen_ppe_thresh(u8 *he_ppet, int nss)
|
||||
(0xff >> (8 - (ppet_bits - 1) % 8));
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data)
|
||||
struct ieee80211_sband_iftype_data *data,
|
||||
enum nl80211_iftype iftype)
|
||||
{
|
||||
int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
|
||||
struct ieee80211_sta_he_cap *he_cap = &data->he_cap;
|
||||
struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem;
|
||||
struct ieee80211_he_mcs_nss_supp *he_mcs = &he_cap->he_mcs_nss_supp;
|
||||
int i, nss = hweight8(phy->mt76->antenna_mask);
|
||||
u16 mcs_map = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
@@ -586,13 +591,219 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
mcs_map |= (IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2));
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
|
||||
struct ieee80211_sta_he_cap *he_cap = &data[idx].he_cap;
|
||||
struct ieee80211_he_cap_elem *he_cap_elem =
|
||||
&he_cap->he_cap_elem;
|
||||
struct ieee80211_he_mcs_nss_supp *he_mcs =
|
||||
&he_cap->he_mcs_nss_supp;
|
||||
he_cap->has_he = true;
|
||||
|
||||
he_cap_elem->mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;
|
||||
he_cap_elem->mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
|
||||
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;
|
||||
he_cap_elem->mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
|
||||
he_cap_elem->phy_cap_info[2] = IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
|
||||
|
||||
switch (iftype) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
he_cap_elem->mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_RES;
|
||||
he_cap_elem->mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_BSR;
|
||||
he_cap_elem->mac_cap_info[4] |= IEEE80211_HE_MAC_CAP4_BQR;
|
||||
he_cap_elem->mac_cap_info[5] |=
|
||||
IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
he_cap_elem->mac_cap_info[1] |=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] |=
|
||||
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
|
||||
IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
|
||||
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[7] |=
|
||||
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
|
||||
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
|
||||
he_cap_elem->phy_cap_info[8] |=
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
|
||||
IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
|
||||
mt7996_set_stream_he_txbf_caps(phy, he_cap, iftype);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
u8_encode_bits(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US,
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK);
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
|
||||
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
|
||||
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
|
||||
|
||||
data->he_6ghz_capa.capa = cpu_to_le16(cap);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
struct ieee80211_sband_iftype_data *data,
|
||||
enum nl80211_iftype iftype)
|
||||
{
|
||||
struct ieee80211_sta_eht_cap *eht_cap = &data->eht_cap;
|
||||
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
|
||||
struct ieee80211_eht_mcs_nss_supp *eht_nss = &eht_cap->eht_mcs_nss_supp;
|
||||
enum nl80211_chan_width width = phy->mt76->chandef.width;
|
||||
int nss = hweight8(phy->mt76->antenna_mask);
|
||||
int sts = hweight16(phy->mt76->chainmask);
|
||||
u8 val;
|
||||
|
||||
if (!phy->dev->has_eht)
|
||||
return;
|
||||
|
||||
eht_cap->has_eht = true;
|
||||
|
||||
eht_cap_elem->mac_cap_info[0] =
|
||||
IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
|
||||
IEEE80211_EHT_MAC_CAP0_OM_CONTROL;
|
||||
|
||||
eht_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ |
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE;
|
||||
|
||||
eht_cap_elem->phy_cap_info[0] |=
|
||||
u8_encode_bits(u8_get_bits(sts - 1, BIT(0)),
|
||||
IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[1] =
|
||||
u8_encode_bits(u8_get_bits(sts - 1, GENMASK(2, 1)),
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1,
|
||||
IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[2] =
|
||||
u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK) |
|
||||
u8_encode_bits(sts - 1, IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[3] =
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
|
||||
IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK;
|
||||
|
||||
eht_cap_elem->phy_cap_info[4] =
|
||||
u8_encode_bits(min_t(int, sts - 1, 2),
|
||||
IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[5] =
|
||||
IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
|
||||
u8_encode_bits(IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_16US,
|
||||
IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK) |
|
||||
u8_encode_bits(u8_get_bits(0x11, GENMASK(1, 0)),
|
||||
IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK);
|
||||
|
||||
val = width == NL80211_CHAN_WIDTH_320 ? 0xf :
|
||||
width == NL80211_CHAN_WIDTH_160 ? 0x7 :
|
||||
width == NL80211_CHAN_WIDTH_80 ? 0x3 : 0x1;
|
||||
eht_cap_elem->phy_cap_info[6] =
|
||||
u8_encode_bits(u8_get_bits(0x11, GENMASK(4, 2)),
|
||||
IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK) |
|
||||
u8_encode_bits(val, IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK);
|
||||
|
||||
eht_cap_elem->phy_cap_info[7] =
|
||||
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
|
||||
IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ;
|
||||
|
||||
val = u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_RX) |
|
||||
u8_encode_bits(nss, IEEE80211_EHT_MCS_NSS_TX);
|
||||
#define SET_EHT_MAX_NSS(_bw, _val) do { \
|
||||
eht_nss->bw._##_bw.rx_tx_mcs9_max_nss = _val; \
|
||||
eht_nss->bw._##_bw.rx_tx_mcs11_max_nss = _val; \
|
||||
eht_nss->bw._##_bw.rx_tx_mcs13_max_nss = _val; \
|
||||
} while (0)
|
||||
|
||||
SET_EHT_MAX_NSS(80, val);
|
||||
SET_EHT_MAX_NSS(160, val);
|
||||
SET_EHT_MAX_NSS(320, val);
|
||||
#undef SET_EHT_MAX_NSS
|
||||
}
|
||||
|
||||
static void
|
||||
__mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy,
|
||||
struct ieee80211_supported_band *sband,
|
||||
enum nl80211_band band)
|
||||
{
|
||||
struct ieee80211_sband_iftype_data *data = phy->iftype[band];
|
||||
int i, n = 0;
|
||||
|
||||
for (i = 0; i < NUM_NL80211_IFTYPES; i++) {
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_AP:
|
||||
@@ -604,161 +815,30 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
continue;
|
||||
}
|
||||
|
||||
data[idx].types_mask = BIT(i);
|
||||
he_cap->has_he = true;
|
||||
data[n].types_mask = BIT(i);
|
||||
mt7996_init_he_caps(phy, band, &data[n], i);
|
||||
mt7996_init_eht_caps(phy, band, &data[n], i);
|
||||
|
||||
he_cap_elem->mac_cap_info[0] =
|
||||
IEEE80211_HE_MAC_CAP0_HTC_HE;
|
||||
he_cap_elem->mac_cap_info[3] =
|
||||
IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
|
||||
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3;
|
||||
he_cap_elem->mac_cap_info[4] =
|
||||
IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] =
|
||||
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
|
||||
he_cap_elem->phy_cap_info[2] =
|
||||
IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
|
||||
IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
|
||||
|
||||
switch (i) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
he_cap_elem->mac_cap_info[0] |=
|
||||
IEEE80211_HE_MAC_CAP0_TWT_RES;
|
||||
he_cap_elem->mac_cap_info[2] |=
|
||||
IEEE80211_HE_MAC_CAP2_BSR;
|
||||
he_cap_elem->mac_cap_info[4] |=
|
||||
IEEE80211_HE_MAC_CAP4_BQR;
|
||||
he_cap_elem->mac_cap_info[5] |=
|
||||
IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU;
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
he_cap_elem->mac_cap_info[1] |=
|
||||
IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
|
||||
|
||||
if (band == NL80211_BAND_2GHZ)
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G;
|
||||
else
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G;
|
||||
|
||||
he_cap_elem->phy_cap_info[1] |=
|
||||
IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
|
||||
IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;
|
||||
he_cap_elem->phy_cap_info[3] |=
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_QPSK |
|
||||
IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_QPSK;
|
||||
he_cap_elem->phy_cap_info[6] |=
|
||||
IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB |
|
||||
IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE |
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT;
|
||||
he_cap_elem->phy_cap_info[7] |=
|
||||
IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_SUPP |
|
||||
IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
|
||||
he_cap_elem->phy_cap_info[8] |=
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
|
||||
IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU |
|
||||
IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM |
|
||||
IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK |
|
||||
IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
|
||||
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
|
||||
break;
|
||||
}
|
||||
|
||||
he_mcs->rx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_160 = cpu_to_le16(mcs_map);
|
||||
he_mcs->rx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
he_mcs->tx_mcs_80p80 = cpu_to_le16(mcs_map);
|
||||
|
||||
mt7996_set_stream_he_txbf_caps(phy, he_cap, i);
|
||||
|
||||
memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres));
|
||||
if (he_cap_elem->phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
mt7996_gen_ppe_thresh(he_cap->ppe_thres, nss);
|
||||
} else {
|
||||
he_cap_elem->phy_cap_info[9] |=
|
||||
IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US;
|
||||
}
|
||||
|
||||
if (band == NL80211_BAND_6GHZ) {
|
||||
u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
|
||||
IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
|
||||
|
||||
cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
|
||||
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
|
||||
u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
|
||||
u16_encode_bits(IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454,
|
||||
IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN);
|
||||
|
||||
data[idx].he_6ghz_capa.capa = cpu_to_le16(cap);
|
||||
}
|
||||
|
||||
idx++;
|
||||
n++;
|
||||
}
|
||||
|
||||
return idx;
|
||||
sband->iftype_data = data;
|
||||
sband->n_iftype_data = n;
|
||||
}
|
||||
|
||||
void mt7996_set_stream_he_caps(struct mt7996_phy *phy)
|
||||
void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy)
|
||||
{
|
||||
struct ieee80211_sband_iftype_data *data;
|
||||
struct ieee80211_supported_band *band;
|
||||
int n;
|
||||
if (phy->mt76->cap.has_2ghz)
|
||||
__mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_2g.sband,
|
||||
NL80211_BAND_2GHZ);
|
||||
|
||||
if (phy->mt76->cap.has_2ghz) {
|
||||
data = phy->iftype[NL80211_BAND_2GHZ];
|
||||
n = mt7996_init_he_caps(phy, NL80211_BAND_2GHZ, data);
|
||||
if (phy->mt76->cap.has_5ghz)
|
||||
__mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_5g.sband,
|
||||
NL80211_BAND_5GHZ);
|
||||
|
||||
band = &phy->mt76->sband_2g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_5ghz) {
|
||||
data = phy->iftype[NL80211_BAND_5GHZ];
|
||||
n = mt7996_init_he_caps(phy, NL80211_BAND_5GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_5g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
|
||||
if (phy->mt76->cap.has_6ghz) {
|
||||
data = phy->iftype[NL80211_BAND_6GHZ];
|
||||
n = mt7996_init_he_caps(phy, NL80211_BAND_6GHZ, data);
|
||||
|
||||
band = &phy->mt76->sband_6g.sband;
|
||||
band->iftype_data = data;
|
||||
band->n_iftype_data = n;
|
||||
}
|
||||
if (phy->mt76->cap.has_6ghz)
|
||||
__mt7996_set_stream_he_eht_caps(phy, &phy->mt76->sband_6g.sband,
|
||||
NL80211_BAND_6GHZ);
|
||||
}
|
||||
|
||||
int mt7996_register_device(struct mt7996_dev *dev)
|
||||
|
||||
@@ -189,6 +189,9 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
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;
|
||||
@@ -205,7 +208,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 6);
|
||||
val = mt76_rr(dev, addr);
|
||||
if (rate->flags & RATE_INFO_FLAGS_HE_MCS) {
|
||||
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;
|
||||
@@ -469,7 +476,7 @@ static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
ether_addr_copy(hdr.addr4, eth_hdr->h_source);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);
|
||||
@@ -560,6 +567,15 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
|
||||
|
||||
status->he_dcm = dcm;
|
||||
break;
|
||||
case MT_PHY_TYPE_EHT_SU:
|
||||
case MT_PHY_TYPE_EHT_TRIG:
|
||||
case MT_PHY_TYPE_EHT_MU:
|
||||
/* TODO: currently report rx rate with HE rate */
|
||||
status->nss = nss;
|
||||
status->encoding = RX_ENC_HE;
|
||||
bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
|
||||
i = min_t(int, i & 0xf, 11);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -584,6 +600,9 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
status->bw = RATE_INFO_BW_160;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
status->bw = RATE_INFO_BW_320;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -959,51 +978,6 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
}
|
||||
}
|
||||
|
||||
static u16
|
||||
mt7996_mac_tx_rate_val(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
bool beacon, bool mcast)
|
||||
{
|
||||
u8 mode = 0, band = mphy->chandef.chan->band;
|
||||
int rateidx = 0, mcast_rate;
|
||||
|
||||
if (beacon) {
|
||||
struct cfg80211_bitrate_mask *mask;
|
||||
|
||||
mask = &vif->bss_conf.beacon_tx_rate;
|
||||
if (hweight16(mask->control[band].he_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].he_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HE_SU;
|
||||
goto out;
|
||||
} else if (hweight16(mask->control[band].vht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].vht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_VHT;
|
||||
goto out;
|
||||
} else if (hweight8(mask->control[band].ht_mcs[0]) == 1) {
|
||||
rateidx = ffs(mask->control[band].ht_mcs[0]) - 1;
|
||||
mode = MT_PHY_TYPE_HT;
|
||||
goto out;
|
||||
} else if (hweight32(mask->control[band].legacy) == 1) {
|
||||
rateidx = ffs(mask->control[band].legacy) - 1;
|
||||
goto legacy;
|
||||
}
|
||||
}
|
||||
|
||||
mcast_rate = vif->bss_conf.mcast_rate[band];
|
||||
if (mcast && mcast_rate > 0)
|
||||
rateidx = mcast_rate - 1;
|
||||
else
|
||||
rateidx = ffs(vif->bss_conf.basic_rates) - 1;
|
||||
|
||||
legacy:
|
||||
rateidx = mt76_calculate_default_rate(mphy, rateidx);
|
||||
mode = rateidx >> 8;
|
||||
rateidx &= GENMASK(7, 0);
|
||||
|
||||
out:
|
||||
return FIELD_PREP(MT_TX_RATE_IDX, rateidx) |
|
||||
FIELD_PREP(MT_TX_RATE_MODE, mode);
|
||||
}
|
||||
|
||||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
|
||||
struct ieee80211_key_conf *key, u32 changed)
|
||||
@@ -1091,7 +1065,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
/* Fixed rata is available just for 802.11 txd */
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u16 rate = mt7996_mac_tx_rate_val(mphy, vif, beacon, multicast);
|
||||
u16 rate = mt76_connac2_mac_tx_rate_val(mphy, vif, beacon,
|
||||
multicast);
|
||||
|
||||
/* fix to bw 20 */
|
||||
val = MT_TXD6_FIXED_BW |
|
||||
@@ -1113,8 +1088,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt76_connac_txp_common *txp;
|
||||
struct mt76_txwi_cache *t;
|
||||
struct mt7996_txp *txp;
|
||||
int id, i, pid, nbuf = tx_info->nbuf - 1;
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
u8 *txwi = (u8 *)txwi_ptr;
|
||||
@@ -1148,35 +1123,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
|
||||
key, 0);
|
||||
|
||||
txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
|
||||
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
|
||||
txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
|
||||
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->nbuf = nbuf;
|
||||
txp->fw.nbuf = nbuf;
|
||||
|
||||
txp->flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
|
||||
txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
|
||||
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
txp->flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
|
||||
|
||||
if (!key)
|
||||
txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
|
||||
|
||||
if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control))
|
||||
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
|
||||
|
||||
if (vif) {
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
|
||||
txp->bss_idx = mvif->mt76.idx;
|
||||
txp->fw.bss_idx = mvif->mt76.idx;
|
||||
}
|
||||
|
||||
txp->token = cpu_to_le16(id);
|
||||
txp->fw.token = cpu_to_le16(id);
|
||||
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
|
||||
txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
|
||||
txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
|
||||
else
|
||||
txp->rept_wds_wcid = cpu_to_le16(0xfff);
|
||||
txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
|
||||
tx_info->skb = DMA_DUMMY_DATA;
|
||||
|
||||
/* pass partial skb header to fw */
|
||||
@@ -1212,18 +1187,6 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
|
||||
ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
struct mt7996_txp *txp;
|
||||
int i;
|
||||
|
||||
txp = mt7996_txwi_to_txp(dev, t);
|
||||
for (i = 0; i < txp->nbuf; i++)
|
||||
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
|
||||
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
|
||||
struct ieee80211_sta *sta, struct list_head *free_list)
|
||||
@@ -1233,7 +1196,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
|
||||
__le32 *txwi;
|
||||
u16 wcid_idx;
|
||||
|
||||
mt7996_txp_skb_unmap(mdev, t);
|
||||
mt76_connac_txp_skb_unmap(mdev, t);
|
||||
if (!t->skb)
|
||||
goto out;
|
||||
|
||||
@@ -1434,6 +1397,15 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid,
|
||||
rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate);
|
||||
rate.flags = RATE_INFO_FLAGS_HE_MCS;
|
||||
break;
|
||||
case MT_PHY_TYPE_EHT_SU:
|
||||
case MT_PHY_TYPE_EHT_TRIG:
|
||||
case MT_PHY_TYPE_EHT_MU:
|
||||
if (rate.mcs > 13)
|
||||
goto out;
|
||||
|
||||
rate.eht_gi = wcid->rate.eht_gi;
|
||||
rate.flags = RATE_INFO_FLAGS_EHT_MCS;
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
@@ -1441,6 +1413,10 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid, int pid,
|
||||
stats->tx_mode[mode]++;
|
||||
|
||||
switch (FIELD_GET(MT_TXS0_BW, txs)) {
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
rate.bw = RATE_INFO_BW_320;
|
||||
stats->tx_bw[4]++;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
rate.bw = RATE_INFO_BW_160;
|
||||
stats->tx_bw[3]++;
|
||||
@@ -1486,7 +1462,7 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
|
||||
if (pid < MT_PACKET_ID_FIRST)
|
||||
return;
|
||||
|
||||
if (wcidx >= MT7996_WTBL_SIZE)
|
||||
if (wcidx >= mt7996_wtbl_size(dev))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
@@ -1589,27 +1565,6 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
|
||||
{
|
||||
if (!e->txwi) {
|
||||
dev_kfree_skb_any(e->skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* error path */
|
||||
if (e->skb == DMA_DUMMY_DATA) {
|
||||
struct mt76_txwi_cache *t;
|
||||
struct mt7996_txp *txp;
|
||||
|
||||
txp = mt7996_txwi_to_txp(mdev, e->txwi);
|
||||
t = mt76_token_put(mdev, le16_to_cpu(txp->token));
|
||||
e->skb = t ? t->skb : NULL;
|
||||
}
|
||||
|
||||
if (e->skb)
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
}
|
||||
|
||||
void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
@@ -1690,7 +1645,7 @@ void mt7996_mac_set_timing(struct mt7996_phy *phy)
|
||||
else
|
||||
val = MT7996_CFEND_RATE_11B;
|
||||
|
||||
mt76_rmw_field(dev, MT_AGG_ACR0(band_idx), MT_AGG_ACR_CFEND_RATE, val);
|
||||
mt76_rmw_field(dev, MT_RATE_HRCR0(band_idx), MT_RATE_HRCR0_CFEND_RATE, val);
|
||||
mt76_clear(dev, MT_ARB_SCR(band_idx),
|
||||
MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
|
||||
}
|
||||
|
||||
@@ -268,17 +268,6 @@ enum tx_mgnt_type {
|
||||
/* VHT/HE only use bits 0-3 */
|
||||
#define MT_TX_RATE_IDX GENMASK(5, 0)
|
||||
|
||||
struct mt7996_txp {
|
||||
__le16 flags;
|
||||
__le16 token;
|
||||
u8 bss_idx;
|
||||
__le16 rept_wds_wcid;
|
||||
u8 nbuf;
|
||||
#define MT_TXP_MAX_BUF_NUM 6
|
||||
__le32 buf[MT_TXP_MAX_BUF_NUM];
|
||||
__le16 len[MT_TXP_MAX_BUF_NUM];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
|
||||
#define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
|
||||
#define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
|
||||
@@ -382,17 +371,4 @@ struct mt7996_dfs_radar_spec {
|
||||
struct mt7996_dfs_pattern radar_pattern[16];
|
||||
};
|
||||
|
||||
static inline struct mt7996_txp *
|
||||
mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
u8 *txwi;
|
||||
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
txwi = mt76_get_txwi_ptr(dev, t);
|
||||
|
||||
return (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -170,7 +170,7 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
|
||||
phy->monitor_vif = vif;
|
||||
|
||||
mvif->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mvif->mt76.idx >= (MT7996_MAX_INTERFACES << dev->dbdc_support)) {
|
||||
if (mvif->mt76.idx >= mt7996_max_interface_num(dev)) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
@@ -880,14 +880,17 @@ mt7996_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
phy->mt76->antenna_mask = tx_ant;
|
||||
|
||||
/* restore to the origin chainmask which might have auxiliary path */
|
||||
if (hweight8(tx_ant) == max_nss)
|
||||
if (hweight8(tx_ant) == max_nss && band_idx < MT_BAND2)
|
||||
phy->mt76->chainmask = ((dev->chainmask >> shift) &
|
||||
(BIT(dev->chainshift[band_idx + 1] - shift) - 1)) << shift;
|
||||
else if (hweight8(tx_ant) == max_nss)
|
||||
phy->mt76->chainmask = (dev->chainmask >> shift) << shift;
|
||||
else
|
||||
phy->mt76->chainmask = tx_ant << shift;
|
||||
|
||||
mt76_set_stream_caps(phy->mt76, true);
|
||||
mt7996_set_stream_vht_txbf_caps(phy);
|
||||
mt7996_set_stream_he_caps(phy);
|
||||
mt7996_set_stream_he_eht_caps(phy);
|
||||
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
@@ -1081,10 +1084,14 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||
"v_tx_mode_he_ext_su",
|
||||
"v_tx_mode_he_tb",
|
||||
"v_tx_mode_he_mu",
|
||||
"v_tx_mode_eht_su",
|
||||
"v_tx_mode_eht_trig",
|
||||
"v_tx_mode_eht_mu",
|
||||
"v_tx_bw_20",
|
||||
"v_tx_bw_40",
|
||||
"v_tx_bw_80",
|
||||
"v_tx_bw_160",
|
||||
"v_tx_bw_320",
|
||||
"v_tx_mcs_0",
|
||||
"v_tx_mcs_1",
|
||||
"v_tx_mcs_2",
|
||||
@@ -1097,6 +1104,8 @@ static const char mt7996_gstrings_stats[][ETH_GSTRING_LEN] = {
|
||||
"v_tx_mcs_9",
|
||||
"v_tx_mcs_10",
|
||||
"v_tx_mcs_11",
|
||||
"v_tx_mcs_12",
|
||||
"v_tx_mcs_13",
|
||||
};
|
||||
|
||||
#define MT7996_SSTATS_LEN ARRAY_SIZE(mt7996_gstrings_stats)
|
||||
@@ -1130,7 +1139,7 @@ static void mt7996_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)
|
||||
if (msta->vif->mt76.idx != wi->idx)
|
||||
return;
|
||||
|
||||
mt76_ethtool_worker(wi, &msta->stats);
|
||||
mt76_ethtool_worker(wi, &msta->stats, true);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -70,6 +70,7 @@ struct mt7996_fw_region {
|
||||
|
||||
#define HE_PHY(p, c) u8_get_bits(c, IEEE80211_HE_PHY_##p)
|
||||
#define HE_MAC(m, c) u8_get_bits(c, IEEE80211_HE_MAC_##m)
|
||||
#define EHT_PHY(p, c) u8_get_bits(c, IEEE80211_EHT_PHY_##p)
|
||||
|
||||
static bool sr_scene_detect = true;
|
||||
module_param(sr_scene_detect, bool, 0644);
|
||||
@@ -771,9 +772,8 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
|
||||
bss->dtim_period = vif->bss_conf.dtim_period;
|
||||
bss->phymode = mt76_connac_get_phy_mode(phy, vif,
|
||||
chandef->chan->band, NULL);
|
||||
|
||||
if (chandef->chan->band == NL80211_BAND_6GHZ)
|
||||
bss->phymode_ext |= PHY_MODE_AX_6G;
|
||||
bss->phymode_ext = mt76_connac_get_phy_mode_ext(phy, vif,
|
||||
chandef->chan->band);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -951,6 +951,35 @@ mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
he_6g->capa = sta->deflink.he_6ghz_capa.capa;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ieee80211_eht_mcs_nss_supp *mcs_map;
|
||||
struct ieee80211_eht_cap_elem_fixed *elem;
|
||||
struct sta_rec_eht *eht;
|
||||
struct tlv *tlv;
|
||||
|
||||
if (!sta->deflink.eht_cap.has_eht)
|
||||
return;
|
||||
|
||||
mcs_map = &sta->deflink.eht_cap.eht_mcs_nss_supp;
|
||||
elem = &sta->deflink.eht_cap.eht_cap_elem;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT, sizeof(*eht));
|
||||
|
||||
eht = (struct sta_rec_eht *)tlv;
|
||||
eht->tid_bitmap = 0xff;
|
||||
eht->mac_cap = cpu_to_le16(*(u16 *)elem->mac_cap_info);
|
||||
eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info);
|
||||
eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]);
|
||||
|
||||
if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
|
||||
memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20));
|
||||
memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
|
||||
memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
|
||||
memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
|
||||
{
|
||||
@@ -1025,15 +1054,27 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool bfee)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
int tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
|
||||
int sts = hweight16(phy->mt76->chainmask);
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION &&
|
||||
vif->type != NL80211_IFTYPE_AP)
|
||||
return false;
|
||||
|
||||
if (!bfee && tx_ant < 2)
|
||||
if (!bfee && sts < 2)
|
||||
return false;
|
||||
|
||||
if (sta->deflink.eht_cap.has_eht) {
|
||||
struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap;
|
||||
struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
|
||||
|
||||
if (bfee)
|
||||
return mvif->cap.eht_su_ebfee &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
|
||||
else
|
||||
return mvif->cap.eht_su_ebfer &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
|
||||
}
|
||||
|
||||
if (sta->deflink.he_cap.has_he) {
|
||||
struct ieee80211_he_cap_elem *pe = &sta->deflink.he_cap.he_cap_elem;
|
||||
|
||||
@@ -1190,13 +1231,69 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
|
||||
bf->nrow_gt_bw80 = min_t(int, snd_dim, sts);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
|
||||
struct mt7996_phy *phy, struct sta_rec_bf *bf)
|
||||
{
|
||||
struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap;
|
||||
struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
|
||||
struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp;
|
||||
const struct ieee80211_sta_eht_cap *vc =
|
||||
mt76_connac_get_eht_phy_cap(phy->mt76, vif);
|
||||
const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem;
|
||||
u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss,
|
||||
IEEE80211_EHT_MCS_NSS_RX) - 1;
|
||||
u8 snd_dim, sts;
|
||||
|
||||
bf->tx_mode = MT_PHY_TYPE_EHT_MU;
|
||||
|
||||
mt7996_mcu_sta_sounding_rate(bf);
|
||||
|
||||
bf->trigger_su = EHT_PHY(CAP3_TRIG_SU_BF_FDBK, pe->phy_cap_info[3]);
|
||||
bf->trigger_mu = EHT_PHY(CAP3_TRIG_MU_BF_PART_BW_FDBK, pe->phy_cap_info[3]);
|
||||
snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_80MHZ_MASK, ve->phy_cap_info[2]);
|
||||
sts = EHT_PHY(CAP0_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[0]) +
|
||||
(EHT_PHY(CAP1_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[1]) << 1);
|
||||
bf->nrow = min_t(u8, snd_dim, sts);
|
||||
bf->ncol = min_t(u8, nss_mcs, bf->nrow);
|
||||
bf->ibf_ncol = bf->ncol;
|
||||
|
||||
if (sta->deflink.bandwidth < IEEE80211_STA_RX_BW_160)
|
||||
return;
|
||||
|
||||
switch (sta->deflink.bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_160MHZ_MASK, ve->phy_cap_info[2]);
|
||||
sts = EHT_PHY(CAP1_BEAMFORMEE_SS_160MHZ_MASK, pe->phy_cap_info[1]);
|
||||
nss_mcs = u8_get_bits(eht_nss->bw._160.rx_tx_mcs9_max_nss,
|
||||
IEEE80211_EHT_MCS_NSS_RX) - 1;
|
||||
|
||||
bf->nrow_gt_bw80 = min_t(u8, snd_dim, sts);
|
||||
bf->ncol_gt_bw80 = nss_mcs;
|
||||
break;
|
||||
case IEEE80211_STA_RX_BW_320:
|
||||
snd_dim = EHT_PHY(CAP2_SOUNDING_DIM_320MHZ_MASK, ve->phy_cap_info[2]) +
|
||||
(EHT_PHY(CAP3_SOUNDING_DIM_320MHZ_MASK,
|
||||
ve->phy_cap_info[3]) << 1);
|
||||
sts = EHT_PHY(CAP1_BEAMFORMEE_SS_320MHZ_MASK, pe->phy_cap_info[1]);
|
||||
nss_mcs = u8_get_bits(eht_nss->bw._320.rx_tx_mcs9_max_nss,
|
||||
IEEE80211_EHT_MCS_NSS_RX) - 1;
|
||||
|
||||
bf->nrow_gt_bw80 = min_t(u8, snd_dim, sts) << 4;
|
||||
bf->ncol_gt_bw80 = nss_mcs << 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_phy *phy = mvif->phy;
|
||||
int tx_ant = hweight8(phy->mt76->antenna_mask) - 1;
|
||||
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
|
||||
struct sta_rec_bf *bf;
|
||||
struct tlv *tlv;
|
||||
const u8 matrix[4][4] = {
|
||||
@@ -1217,11 +1314,13 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
|
||||
bf = (struct sta_rec_bf *)tlv;
|
||||
|
||||
/* he: eBF only, in accordance with spec
|
||||
/* he/eht: eBF only, in accordance with spec
|
||||
* vht: support eBF and iBF
|
||||
* ht: iBF only, since mac80211 lacks of eBF support
|
||||
*/
|
||||
if (sta->deflink.he_cap.has_he && ebf)
|
||||
if (sta->deflink.eht_cap.has_eht && ebf)
|
||||
mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf);
|
||||
else if (sta->deflink.he_cap.has_he && ebf)
|
||||
mt7996_mcu_sta_bfer_he(sta, vif, phy, bf);
|
||||
else if (sta->deflink.vht_cap.vht_supported)
|
||||
mt7996_mcu_sta_bfer_vht(sta, phy, bf, ebf);
|
||||
@@ -1436,8 +1535,9 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
|
||||
ra->auto_rate = true;
|
||||
ra->phy_mode = mt76_connac_get_phy_mode(mphy, vif, band, sta);
|
||||
ra->channel = chandef->chan->hw_value;
|
||||
ra->bw = sta->deflink.bandwidth;
|
||||
ra->phy.bw = sta->deflink.bandwidth;
|
||||
ra->bw = (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320) ?
|
||||
CMD_CBW_320MHZ : sta->deflink.bandwidth;
|
||||
ra->phy.bw = ra->bw;
|
||||
ra->mmps_mode = mt7996_mcu_get_mmps_mode(sta->deflink.smps_mode);
|
||||
|
||||
if (supp_rate) {
|
||||
@@ -1619,6 +1719,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
mt7996_mcu_sta_he_tlv(skb, sta);
|
||||
/* starec he 6g*/
|
||||
mt7996_mcu_sta_he_6g_tlv(skb, sta);
|
||||
/* starec eht */
|
||||
mt7996_mcu_sta_eht_tlv(skb, sta);
|
||||
/* TODO: starec muru */
|
||||
/* starec bfee */
|
||||
mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
|
||||
@@ -1815,6 +1917,7 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt7996_vif_cap *vc = &mvif->cap;
|
||||
const struct ieee80211_eht_cap_elem_fixed *eht;
|
||||
const struct ieee80211_he_cap_elem *he;
|
||||
const struct ieee80211_vht_cap *vht;
|
||||
const struct ieee80211_ht_cap *ht;
|
||||
@@ -1885,6 +1988,23 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, he->phy_cap_info[4]) &&
|
||||
HE_PHY(CAP4_MU_BEAMFORMER, pe->phy_cap_info[4]);
|
||||
}
|
||||
|
||||
ie = cfg80211_find_ext_ie(WLAN_EID_EXT_EHT_CAPABILITY,
|
||||
mgmt->u.beacon.variable, len);
|
||||
if (ie && ie[1] >= sizeof(*eht) + 1) {
|
||||
const struct ieee80211_sta_eht_cap *pc =
|
||||
mt76_connac_get_eht_phy_cap(phy->mt76, vif);
|
||||
const struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
|
||||
|
||||
eht = (void *)(ie + 3);
|
||||
|
||||
vc->eht_su_ebfer =
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, eht->phy_cap_info[0]) &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMER, pe->phy_cap_info[0]);
|
||||
vc->eht_su_ebfee =
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) &&
|
||||
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
|
||||
}
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw,
|
||||
@@ -2247,6 +2367,26 @@ mt7996_firmware_state(struct mt7996_dev *dev, bool wa)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_restart(struct mt76_dev *dev)
|
||||
{
|
||||
struct {
|
||||
u8 __rsv1[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 power_mode;
|
||||
u8 __rsv2[3];
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(UNI_POWER_OFF),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
.power_mode = 1,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(POWER_CTRL), &req,
|
||||
sizeof(req), false);
|
||||
}
|
||||
|
||||
static int mt7996_load_firmware(struct mt7996_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -2254,7 +2394,7 @@ static int mt7996_load_firmware(struct mt7996_dev *dev)
|
||||
/* make sure fw is download state */
|
||||
if (mt7996_firmware_state(dev, false)) {
|
||||
/* restart firmware once */
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt7996_mcu_restart(&dev->mt76);
|
||||
ret = mt7996_firmware_state(dev, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev,
|
||||
@@ -2383,33 +2523,12 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
|
||||
MCU_WM_UNI_CMD(VOW), true);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7996_mcu_restart(struct mt76_dev *dev)
|
||||
{
|
||||
struct {
|
||||
u8 __rsv1[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 power_mode;
|
||||
u8 __rsv2[3];
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(UNI_POWER_OFF),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
.power_mode = 1,
|
||||
};
|
||||
|
||||
return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(POWER_CREL), &req,
|
||||
sizeof(req), false);
|
||||
}
|
||||
|
||||
int mt7996_mcu_init(struct mt7996_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7996_mcu_ops = {
|
||||
.headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
|
||||
.mcu_skb_send_msg = mt7996_mcu_send_message,
|
||||
.mcu_parse_response = mt7996_mcu_parse_response,
|
||||
.mcu_restart = mt7996_mcu_restart,
|
||||
};
|
||||
int ret;
|
||||
|
||||
@@ -2457,16 +2576,17 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
|
||||
|
||||
void mt7996_mcu_exit(struct mt7996_dev *dev)
|
||||
{
|
||||
__mt76_mcu_restart(&dev->mt76);
|
||||
mt7996_mcu_restart(&dev->mt76);
|
||||
if (mt7996_firmware_state(dev, false)) {
|
||||
dev_err(dev->mt76.dev, "Failed to exit mcu\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN);
|
||||
if (dev->hif2)
|
||||
mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1),
|
||||
MT_TOP_LPCR_HOST_FW_OWN);
|
||||
out:
|
||||
skb_queue_purge(&dev->mt76.mcu.res_q);
|
||||
}
|
||||
|
||||
@@ -2977,6 +3097,52 @@ int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
|
||||
{
|
||||
#define NIC_CAP 3
|
||||
#define UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION 0x21
|
||||
struct {
|
||||
u8 _rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(NIC_CAP),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76,
|
||||
MCU_WM_UNI_CMD_QUERY(CHIP_CONFIG), &req,
|
||||
sizeof(req), true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* fixed field */
|
||||
skb_pull(skb, 4);
|
||||
|
||||
buf = skb->data;
|
||||
while (buf - skb->data < skb->len) {
|
||||
struct tlv *tlv = (struct tlv *)buf;
|
||||
|
||||
switch (le16_to_cpu(tlv->tag)) {
|
||||
case UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION:
|
||||
*cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
buf += le16_to_cpu(tlv->len);
|
||||
}
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch)
|
||||
{
|
||||
struct {
|
||||
|
||||
@@ -347,6 +347,21 @@ struct sta_rec_ba_uni {
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_eht {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 tid_bitmap;
|
||||
u8 _rsv;
|
||||
__le16 mac_cap;
|
||||
__le64 phy_cap;
|
||||
__le64 phy_cap_ext;
|
||||
u8 mcs_map_bw20[4];
|
||||
u8 mcs_map_bw80[3];
|
||||
u8 mcs_map_bw160[3];
|
||||
u8 mcs_map_bw320[3];
|
||||
u8 _rsv2[3];
|
||||
} __packed;
|
||||
|
||||
struct sec_key_uni {
|
||||
__le16 wlan_idx;
|
||||
u8 mgmt_prot;
|
||||
@@ -554,6 +569,7 @@ enum {
|
||||
sizeof(struct sta_rec_sec) + \
|
||||
sizeof(struct sta_rec_ra_fixed) + \
|
||||
sizeof(struct sta_rec_he_6g_capa) + \
|
||||
sizeof(struct sta_rec_eht) + \
|
||||
sizeof(struct sta_rec_hdrt) + \
|
||||
sizeof(struct sta_rec_hdr_trans) + \
|
||||
sizeof(struct tlv))
|
||||
|
||||
@@ -21,6 +21,7 @@ static const struct __base mt7996_reg_base[] = {
|
||||
[WF_ETBF_BASE] = { { 0x820ea000, 0x820fa000, 0x830ea000 } },
|
||||
[WF_LPON_BASE] = { { 0x820eb000, 0x820fb000, 0x830eb000 } },
|
||||
[WF_MIB_BASE] = { { 0x820ed000, 0x820fd000, 0x830ed000 } },
|
||||
[WF_RATE_BASE] = { { 0x820ee000, 0x820fe000, 0x830ee000 } },
|
||||
};
|
||||
|
||||
static const struct __map mt7996_reg_map[] = {
|
||||
@@ -317,7 +318,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
/* txwi_size = txd size + txp size */
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
|
||||
.txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
|
||||
.drv_flags = MT_DRV_TXWI_NO_FREE |
|
||||
MT_DRV_HW_MGMT_TXQ,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX |
|
||||
@@ -325,7 +326,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
SURVEY_INFO_TIME_BSS_RX,
|
||||
.token_size = MT7996_TOKEN_SIZE,
|
||||
.tx_prepare_skb = mt7996_tx_prepare_skb,
|
||||
.tx_complete_skb = mt7996_tx_complete_skb,
|
||||
.tx_complete_skb = mt76_connac_tx_complete_skb,
|
||||
.rx_skb = mt7996_queue_rx_skb,
|
||||
.rx_check = mt7996_rx_check,
|
||||
.rx_poll_complete = mt7996_rx_poll_complete,
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
#include "../mt76_connac.h"
|
||||
#include "regs.h"
|
||||
|
||||
#define MT7996_MAX_INTERFACES 19
|
||||
#define MT7996_MAX_INTERFACES 19 /* per-band */
|
||||
#define MT7996_MAX_WMM_SETS 4
|
||||
#define MT7996_WTBL_SIZE 544
|
||||
#define MT7996_WTBL_RESERVED (MT7996_WTBL_SIZE - 1)
|
||||
#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
|
||||
#define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
|
||||
MT7996_MAX_INTERFACES)
|
||||
mt7996_max_interface_num(dev))
|
||||
|
||||
#define MT7996_WATCHDOG_TIME (HZ / 10)
|
||||
#define MT7996_RESET_TIMEOUT (30 * HZ)
|
||||
@@ -124,6 +123,8 @@ struct mt7996_vif_cap {
|
||||
bool he_su_ebfer:1;
|
||||
bool he_su_ebfee:1;
|
||||
bool he_mu_ebfer:1;
|
||||
bool eht_su_ebfer:1;
|
||||
bool eht_su_ebfee:1;
|
||||
};
|
||||
|
||||
struct mt7996_vif {
|
||||
@@ -264,6 +265,7 @@ struct mt7996_dev {
|
||||
bool dbdc_support:1;
|
||||
bool tbtc_support:1;
|
||||
bool flash_mode:1;
|
||||
bool has_eht:1;
|
||||
|
||||
bool ibf;
|
||||
u8 fw_debug_wm;
|
||||
@@ -281,6 +283,8 @@ struct mt7996_dev {
|
||||
|
||||
u32 reg_l1_backup;
|
||||
u32 reg_l2_backup;
|
||||
|
||||
u8 wtbl_size_group;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -419,6 +423,7 @@ int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
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);
|
||||
int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap);
|
||||
int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 set, u8 band);
|
||||
int mt7996_mcu_set_txbf(struct mt7996_dev *dev, u8 action);
|
||||
int mt7996_mcu_set_fcc5_lpn(struct mt7996_dev *dev, int val);
|
||||
@@ -443,6 +448,16 @@ int mt7996_mcu_fw_dbg_ctrl(struct mt7996_dev *dev, u32 module, u8 level);
|
||||
void mt7996_mcu_rx_event(struct mt7996_dev *dev, struct sk_buff *skb);
|
||||
void mt7996_mcu_exit(struct mt7996_dev *dev);
|
||||
|
||||
static inline u8 mt7996_max_interface_num(struct mt7996_dev *dev)
|
||||
{
|
||||
return MT7996_MAX_INTERFACES * (1 + dev->dbdc_support + dev->tbtc_support);
|
||||
}
|
||||
|
||||
static inline u16 mt7996_wtbl_size(struct mt7996_dev *dev)
|
||||
{
|
||||
return (dev->wtbl_size_group << 8) + 64;
|
||||
}
|
||||
|
||||
void mt7996_dual_hif_set_irq_mask(struct mt7996_dev *dev, bool write_reg,
|
||||
u32 clear, u32 set);
|
||||
|
||||
@@ -493,7 +508,6 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
enum mt76_txq_id qid, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta,
|
||||
struct mt76_tx_info *tx_info);
|
||||
void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev);
|
||||
void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
struct sk_buff *skb, u32 *info);
|
||||
@@ -502,7 +516,7 @@ void mt7996_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
|
||||
void mt7996_stats_work(struct work_struct *work);
|
||||
int mt76_dfs_start_rdd(struct mt7996_dev *dev, bool force);
|
||||
int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy);
|
||||
void mt7996_set_stream_he_caps(struct mt7996_phy *phy);
|
||||
void mt7996_set_stream_he_eht_caps(struct mt7996_phy *phy);
|
||||
void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy);
|
||||
void mt7996_update_channel(struct mt76_phy *mphy);
|
||||
int mt7996_init_debugfs(struct mt7996_phy *phy);
|
||||
|
||||
@@ -33,6 +33,7 @@ enum base_rev {
|
||||
WF_ETBF_BASE,
|
||||
WF_LPON_BASE,
|
||||
WF_MIB_BASE,
|
||||
WF_RATE_BASE,
|
||||
__MT_REG_BASE_MAX,
|
||||
};
|
||||
|
||||
@@ -235,13 +236,6 @@ enum base_rev {
|
||||
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
|
||||
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
|
||||
|
||||
/* AGG: band 0(0x820e2000), band 1(0x820f2000), band 2(0x830e2000) */
|
||||
#define MT_WF_AGG_BASE(_band) __BASE(WF_AGG_BASE, (_band))
|
||||
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x054)
|
||||
#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0)
|
||||
|
||||
/* ARB: band 0(0x820e3000), band 1(0x820f3000), band 2(0x830e3000) */
|
||||
#define MT_WF_ARB_BASE(_band) __BASE(WF_ARB_BASE, (_band))
|
||||
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
|
||||
@@ -300,6 +294,13 @@ enum base_rev {
|
||||
#define MT_WF_RMAC_RSVD0(_band) MT_WF_RMAC(_band, 0x03e0)
|
||||
#define MT_WF_RMAC_RSVD0_EIFS_CLR BIT(21)
|
||||
|
||||
/* RATE: band 0(0x820ee000), band 1(0x820fe000), band 2(0x830ee000) */
|
||||
#define MT_WF_RATE_BASE(_band) __BASE(WF_RATE_BASE, (_band))
|
||||
#define MT_WF_RATE(_band, ofs) (MT_WF_RATE_BASE(_band) + (ofs))
|
||||
|
||||
#define MT_RATE_HRCR0(_band) MT_WF_RATE(_band, 0x050)
|
||||
#define MT_RATE_HRCR0_CFEND_RATE GENMASK(14, 0)
|
||||
|
||||
/* WFDMA0 */
|
||||
#define MT_WFDMA0_BASE 0xd4000
|
||||
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
|
||||
|
||||
@@ -562,6 +562,10 @@ mt76s_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
q->entry[q->head].buf_sz = len;
|
||||
q->entry[q->head].skb = skb;
|
||||
|
||||
/* ensure the entry fully updated before bus access */
|
||||
smp_wmb();
|
||||
|
||||
q->head = (q->head + 1) % q->ndesc;
|
||||
q->queued++;
|
||||
|
||||
|
||||
@@ -319,29 +319,27 @@ mt76u_set_endpoints(struct usb_interface *intf,
|
||||
|
||||
static int
|
||||
mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
|
||||
int nsgs, gfp_t gfp)
|
||||
int nsgs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nsgs; i++) {
|
||||
struct page *page;
|
||||
void *data;
|
||||
int offset;
|
||||
|
||||
data = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
|
||||
data = mt76_get_page_pool_buf(q, &offset, q->buf_size);
|
||||
if (!data)
|
||||
break;
|
||||
|
||||
page = virt_to_head_page(data);
|
||||
offset = data - page_address(page);
|
||||
sg_set_page(&urb->sg[i], page, q->buf_size, offset);
|
||||
sg_set_page(&urb->sg[i], virt_to_head_page(data), q->buf_size,
|
||||
offset);
|
||||
}
|
||||
|
||||
if (i < nsgs) {
|
||||
int j;
|
||||
|
||||
for (j = nsgs; j < urb->num_sgs; j++)
|
||||
skb_free_frag(sg_virt(&urb->sg[j]));
|
||||
mt76_put_page_pool_buf(sg_virt(&urb->sg[j]), false);
|
||||
urb->num_sgs = i;
|
||||
}
|
||||
|
||||
@@ -354,15 +352,16 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
|
||||
|
||||
static int
|
||||
mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct urb *urb, int nsgs, gfp_t gfp)
|
||||
struct urb *urb, int nsgs)
|
||||
{
|
||||
enum mt76_rxq_id qid = q - &dev->q_rx[MT_RXQ_MAIN];
|
||||
int offset;
|
||||
|
||||
if (qid == MT_RXQ_MAIN && dev->usb.sg_en)
|
||||
return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp);
|
||||
return mt76u_fill_rx_sg(dev, q, urb, nsgs);
|
||||
|
||||
urb->transfer_buffer_length = q->buf_size;
|
||||
urb->transfer_buffer = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
|
||||
urb->transfer_buffer = mt76_get_page_pool_buf(q, &offset, q->buf_size);
|
||||
|
||||
return urb->transfer_buffer ? 0 : -ENOMEM;
|
||||
}
|
||||
@@ -400,7 +399,7 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mt76u_refill_rx(dev, q, e->urb, sg_size, GFP_KERNEL);
|
||||
return mt76u_refill_rx(dev, q, e->urb, sg_size);
|
||||
}
|
||||
|
||||
static void mt76u_urb_free(struct urb *urb)
|
||||
@@ -408,10 +407,10 @@ static void mt76u_urb_free(struct urb *urb)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < urb->num_sgs; i++)
|
||||
skb_free_frag(sg_virt(&urb->sg[i]));
|
||||
mt76_put_page_pool_buf(sg_virt(&urb->sg[i]), false);
|
||||
|
||||
if (urb->transfer_buffer)
|
||||
skb_free_frag(urb->transfer_buffer);
|
||||
mt76_put_page_pool_buf(urb->transfer_buffer, false);
|
||||
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
@@ -547,6 +546,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb,
|
||||
len -= data_len;
|
||||
nsgs++;
|
||||
}
|
||||
|
||||
skb_mark_for_recycle(skb);
|
||||
dev->drv->rx_skb(dev, MT_RXQ_MAIN, skb, NULL);
|
||||
|
||||
return nsgs;
|
||||
@@ -612,7 +613,7 @@ mt76u_process_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
|
||||
count = mt76u_process_rx_entry(dev, urb, q->buf_size);
|
||||
if (count > 0) {
|
||||
err = mt76u_refill_rx(dev, q, urb, count, GFP_ATOMIC);
|
||||
err = mt76u_refill_rx(dev, q, urb, count);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
@@ -663,6 +664,10 @@ mt76u_alloc_rx_queue(struct mt76_dev *dev, enum mt76_rxq_id qid)
|
||||
struct mt76_queue *q = &dev->q_rx[qid];
|
||||
int i, err;
|
||||
|
||||
err = mt76_create_page_pool(dev, q);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
q->entry = devm_kcalloc(dev->dev,
|
||||
MT_NUM_RX_ENTRIES, sizeof(*q->entry),
|
||||
@@ -691,7 +696,6 @@ EXPORT_SYMBOL_GPL(mt76u_alloc_mcu_queue);
|
||||
static void
|
||||
mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
{
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < q->ndesc; i++) {
|
||||
@@ -701,13 +705,7 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
|
||||
mt76u_urb_free(q->entry[i].urb);
|
||||
q->entry[i].urb = NULL;
|
||||
}
|
||||
|
||||
if (!q->rx_page.va)
|
||||
return;
|
||||
|
||||
page = virt_to_page(q->rx_page.va);
|
||||
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
|
||||
memset(&q->rx_page, 0, sizeof(q->rx_page));
|
||||
page_pool_destroy(q->page_pool);
|
||||
}
|
||||
|
||||
static void mt76u_free_rx(struct mt76_dev *dev)
|
||||
|
||||
@@ -24,23 +24,23 @@ bool __mt76_poll(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76_poll);
|
||||
|
||||
bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
int timeout)
|
||||
bool ____mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val,
|
||||
int timeout, int tick)
|
||||
{
|
||||
u32 cur;
|
||||
|
||||
timeout /= 10;
|
||||
timeout /= tick;
|
||||
do {
|
||||
cur = __mt76_rr(dev, offset) & mask;
|
||||
if (cur == val)
|
||||
return true;
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
usleep_range(1000 * tick, 2000 * tick);
|
||||
} while (timeout-- > 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt76_poll_msec);
|
||||
EXPORT_SYMBOL_GPL(____mt76_poll_msec);
|
||||
|
||||
int mt76_wcid_alloc(u32 *mask, int size)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user