mt76: update Mediatek's mt76 driver
This version is based on git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git e5f0a698b34ed76002dc5cff3804a61c80233a7a ( tag: v6.17 ). MFC after: 3 days
This commit is contained in:
@@ -173,13 +173,13 @@ void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
if (!mlink)
|
||||
goto out;
|
||||
|
||||
if (link_conf != &vif->bss_conf)
|
||||
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
|
||||
rcu_assign_pointer(mvif->link[link_id], NULL);
|
||||
|
||||
dev->drv->vif_link_remove(phy, vif, link_conf, mlink);
|
||||
mlink->ctx = NULL;
|
||||
|
||||
if (link_conf != &vif->bss_conf)
|
||||
if (mlink != (struct mt76_vif_link *)vif->drv_priv)
|
||||
kfree_rcu(mlink, rcu_head);
|
||||
|
||||
out:
|
||||
@@ -293,6 +293,7 @@ struct mt76_vif_link *mt76_get_vif_phy_link(struct mt76_phy *phy,
|
||||
kfree(mlink);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
rcu_assign_pointer(mvif->offchannel_link, mlink);
|
||||
|
||||
return mlink;
|
||||
}
|
||||
@@ -301,10 +302,14 @@ void mt76_put_vif_phy_link(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct mt76_vif_link *mlink)
|
||||
{
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt76_vif_data *mvif;
|
||||
|
||||
if (IS_ERR_OR_NULL(mlink) || !mlink->offchannel)
|
||||
return;
|
||||
|
||||
mvif = mlink->mvif;
|
||||
|
||||
rcu_assign_pointer(mvif->offchannel_link, NULL);
|
||||
dev->drv->vif_link_remove(phy, vif, &vif->bss_conf, mlink);
|
||||
kfree(mlink);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#if defined(__FreeBSD__)
|
||||
#include <linux/cache.h>
|
||||
#include <net/page_pool.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
#endif
|
||||
#include "mt76.h"
|
||||
#include "dma.h"
|
||||
@@ -647,10 +647,8 @@ mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
|
||||
while (q->queued < q->ndesc - 1) {
|
||||
struct mt76_queue_buf qbuf = {};
|
||||
enum dma_data_direction dir;
|
||||
dma_addr_t addr;
|
||||
int offset;
|
||||
void *buf = NULL;
|
||||
int offset;
|
||||
|
||||
if (mt76_queue_is_wed_rro_ind(q))
|
||||
goto done;
|
||||
@@ -659,11 +657,8 @@ mt76_dma_rx_fill_buf(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
if (!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 + q->buf_offset;
|
||||
qbuf.addr = page_pool_get_dma_addr(virt_to_head_page(buf)) +
|
||||
offset + q->buf_offset;
|
||||
done:
|
||||
qbuf.len = len - q->buf_offset;
|
||||
qbuf.skip_unmap = false;
|
||||
@@ -1023,6 +1018,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
|
||||
int i;
|
||||
|
||||
mt76_worker_disable(&dev->tx_worker);
|
||||
napi_disable(&dev->tx_napi);
|
||||
netif_napi_del(&dev->tx_napi);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
|
||||
|
||||
@@ -101,6 +101,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
|
||||
if (!dev->test_mtd.name) {
|
||||
ret = -ENOMEM;
|
||||
goto out_put_node;
|
||||
}
|
||||
dev->test_mtd.offset = offset;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -459,8 +459,10 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AQL);
|
||||
|
||||
wiphy->available_antennas_tx = phy->antenna_mask;
|
||||
wiphy->available_antennas_rx = phy->antenna_mask;
|
||||
if (!wiphy->available_antennas_tx)
|
||||
wiphy->available_antennas_tx = phy->antenna_mask;
|
||||
if (!wiphy->available_antennas_rx)
|
||||
wiphy->available_antennas_rx = phy->antenna_mask;
|
||||
|
||||
wiphy->sar_capa = &mt76_sar_capa;
|
||||
phy->frp = devm_kcalloc(dev->dev, wiphy->sar_capa->num_freq_ranges,
|
||||
@@ -848,8 +850,45 @@ void mt76_free_device(struct mt76_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_free_device);
|
||||
|
||||
static struct mt76_phy *
|
||||
mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
static void mt76_reset_phy(struct mt76_phy *phy)
|
||||
{
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
INIT_LIST_HEAD(&phy->tx_list);
|
||||
}
|
||||
|
||||
void mt76_reset_device(struct mt76_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[i]);
|
||||
if (!wcid)
|
||||
continue;
|
||||
|
||||
wcid->sta = 0;
|
||||
mt76_wcid_cleanup(dev, wcid);
|
||||
rcu_assign_pointer(dev->wcid[i], NULL);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
INIT_LIST_HEAD(&dev->wcid_list);
|
||||
INIT_LIST_HEAD(&dev->sta_poll_list);
|
||||
dev->vif_mask = 0;
|
||||
memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask));
|
||||
|
||||
mt76_reset_phy(&dev->phy);
|
||||
for (i = 0; i < ARRAY_SIZE(dev->phys); i++)
|
||||
mt76_reset_phy(dev->phys[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_reset_device);
|
||||
|
||||
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_chanctx *ctx;
|
||||
@@ -863,6 +902,7 @@ mt76_vif_phy(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
ctx = (struct mt76_chanctx *)mlink->ctx->drv_priv;
|
||||
return ctx->phy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_vif_phy);
|
||||
|
||||
static void mt76_rx_release_amsdu(struct mt76_phy *phy, enum mt76_rxq_id q)
|
||||
{
|
||||
@@ -1712,6 +1752,10 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
skb_queue_splice_tail_init(&wcid->tx_pending, &list);
|
||||
spin_unlock(&wcid->tx_pending.lock);
|
||||
|
||||
spin_lock(&wcid->tx_offchannel.lock);
|
||||
skb_queue_splice_tail_init(&wcid->tx_offchannel, &list);
|
||||
spin_unlock(&wcid->tx_offchannel.lock);
|
||||
|
||||
spin_unlock_bh(&phy->tx_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&list)) != NULL) {
|
||||
@@ -1723,7 +1767,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
|
||||
|
||||
void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
{
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state))
|
||||
if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->sta_poll_lock);
|
||||
@@ -1733,6 +1777,17 @@ void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_wcid_add_poll);
|
||||
|
||||
s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower)
|
||||
{
|
||||
int n_chains = hweight16(phy->chainmask);
|
||||
|
||||
txpower = mt76_get_sar_power(phy, phy->chandef.chan, txpower * 2);
|
||||
txpower -= mt76_tx_power_path_delta(n_chains);
|
||||
|
||||
return txpower;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_get_power_bound);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm)
|
||||
{
|
||||
@@ -1743,7 +1798,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
return -EINVAL;
|
||||
|
||||
n_chains = hweight16(phy->chainmask);
|
||||
delta = mt76_tx_power_nss_delta(n_chains);
|
||||
delta = mt76_tx_power_path_delta(n_chains);
|
||||
*dbm = DIV_ROUND_UP(phy->txpower_cur + delta, 2);
|
||||
|
||||
return 0;
|
||||
@@ -1914,7 +1969,8 @@ void mt76_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_sw_scan_complete);
|
||||
|
||||
int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
|
||||
int mt76_get_antenna(struct ieee80211_hw *hw, int radio_idx, u32 *tx_ant,
|
||||
u32 *rx_ant)
|
||||
{
|
||||
struct mt76_phy *phy = hw->priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
|
||||
@@ -78,6 +78,10 @@ int mt76_mcu_skb_send_and_get_msg(struct mt76_dev *dev, struct sk_buff *skb,
|
||||
unsigned long expires;
|
||||
int ret, seq;
|
||||
|
||||
if (mt76_is_sdio(dev))
|
||||
if (test_bit(MT76_RESET, &dev->phy.state) && atomic_read(&dev->bus_hung))
|
||||
return -EIO;
|
||||
|
||||
if (ret_skb)
|
||||
*ret_skb = NULL;
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <net/page_pool.h>
|
||||
#endif
|
||||
#include <net/mac80211.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
@@ -170,6 +169,16 @@ enum mt76_dfs_state {
|
||||
MT_DFS_STATE_ACTIVE,
|
||||
};
|
||||
|
||||
#define MT76_RNR_SCAN_MAX_BSSIDS 16
|
||||
struct mt76_scan_rnr_param {
|
||||
u8 bssid[MT76_RNR_SCAN_MAX_BSSIDS][ETH_ALEN];
|
||||
u8 channel[MT76_RNR_SCAN_MAX_BSSIDS];
|
||||
u8 random_mac[ETH_ALEN];
|
||||
u8 seq_num;
|
||||
u8 bssid_num;
|
||||
u32 sreq_flag;
|
||||
};
|
||||
|
||||
struct mt76_queue_buf {
|
||||
dma_addr_t addr;
|
||||
u16 len:15,
|
||||
@@ -359,6 +368,7 @@ struct mt76_wcid {
|
||||
u8 hw_key_idx;
|
||||
u8 hw_key_idx2;
|
||||
|
||||
u8 offchannel:1;
|
||||
u8 sta:1;
|
||||
u8 sta_disabled:1;
|
||||
u8 amsdu:1;
|
||||
@@ -499,6 +509,7 @@ struct mt76_hw_cap {
|
||||
#define MT_DRV_RX_DMA_HDR BIT(3)
|
||||
#define MT_DRV_HW_MGMT_TXQ BIT(4)
|
||||
#define MT_DRV_AMSDU_OFFLOAD BIT(5)
|
||||
#define MT_DRV_IGNORE_TXS_FAILED BIT(6)
|
||||
|
||||
struct mt76_driver_ops {
|
||||
u32 drv_flags;
|
||||
@@ -777,6 +788,7 @@ struct mt76_testmode_data {
|
||||
|
||||
struct mt76_vif_link {
|
||||
u8 idx;
|
||||
u8 link_idx;
|
||||
u8 omac_idx;
|
||||
u8 band_idx;
|
||||
u8 wmm_idx;
|
||||
@@ -794,6 +806,7 @@ struct mt76_vif_link {
|
||||
|
||||
struct mt76_vif_data {
|
||||
struct mt76_vif_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
struct mt76_vif_link __rcu *offchannel_link;
|
||||
|
||||
struct mt76_phy *roc_phy;
|
||||
u16 valid_links;
|
||||
@@ -945,6 +958,8 @@ struct mt76_dev {
|
||||
char alpha2[3];
|
||||
enum nl80211_dfs_regions region;
|
||||
|
||||
struct mt76_scan_rnr_param rnr;
|
||||
|
||||
u32 debugfs_reg;
|
||||
|
||||
u8 csa_complete;
|
||||
@@ -975,6 +990,8 @@ struct mt76_dev {
|
||||
struct mt76_usb usb;
|
||||
struct mt76_sdio sdio;
|
||||
};
|
||||
|
||||
atomic_t bus_hung;
|
||||
};
|
||||
|
||||
/* per-phy stats. */
|
||||
@@ -1216,6 +1233,16 @@ static inline int mt76_wed_dma_setup(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
#define mt76_dereference(p, dev) \
|
||||
rcu_dereference_protected(p, lockdep_is_held(&(dev)->mutex))
|
||||
|
||||
static inline struct mt76_wcid *
|
||||
__mt76_wcid_ptr(struct mt76_dev *dev, u16 idx)
|
||||
{
|
||||
if (idx >= ARRAY_SIZE(dev->wcid))
|
||||
return NULL;
|
||||
return rcu_dereference(dev->wcid[idx]);
|
||||
}
|
||||
|
||||
#define mt76_wcid_ptr(dev, idx) __mt76_wcid_ptr(&(dev)->mt76, idx)
|
||||
|
||||
struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size,
|
||||
const struct ieee80211_ops *ops,
|
||||
const struct mt76_driver_ops *drv_ops);
|
||||
@@ -1223,6 +1250,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
struct ieee80211_rate *rates, int n_rates);
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
void mt76_free_device(struct mt76_dev *dev);
|
||||
void mt76_reset_device(struct mt76_dev *dev);
|
||||
void mt76_unregister_phy(struct mt76_phy *phy);
|
||||
|
||||
struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size,
|
||||
@@ -1232,6 +1260,8 @@ struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
|
||||
u8 band_idx);
|
||||
int mt76_register_phy(struct mt76_phy *phy, bool vht,
|
||||
struct ieee80211_rate *rates, int n_rates);
|
||||
struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
struct dentry *mt76_register_debugfs_fops(struct mt76_phy *phy,
|
||||
const struct file_operations *ops);
|
||||
@@ -1388,12 +1418,12 @@ static inline bool mt76_is_skb_pktid(u8 pktid)
|
||||
return pktid >= MT_PACKET_ID_FIRST;
|
||||
}
|
||||
|
||||
static inline u8 mt76_tx_power_nss_delta(u8 nss)
|
||||
static inline u8 mt76_tx_power_path_delta(u8 path)
|
||||
{
|
||||
static const u8 nss_delta[4] = { 0, 6, 9, 12 };
|
||||
u8 idx = nss - 1;
|
||||
static const u8 path_delta[5] = { 0, 6, 9, 12, 14 };
|
||||
u8 idx = path - 1;
|
||||
|
||||
return (idx < ARRAY_SIZE(nss_delta)) ? nss_delta[idx] : 0;
|
||||
return (idx < ARRAY_SIZE(path_delta)) ? path_delta[idx] : 0;
|
||||
}
|
||||
|
||||
static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
|
||||
@@ -1490,6 +1520,8 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx);
|
||||
|
||||
s8 mt76_get_power_bound(struct mt76_phy *phy, s8 txpower);
|
||||
|
||||
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
unsigned int link_id, int *dbm);
|
||||
int mt76_init_sar_power(struct ieee80211_hw *hw,
|
||||
@@ -1501,7 +1533,8 @@ int mt76_get_sar_power(struct mt76_phy *phy,
|
||||
void mt76_csa_check(struct mt76_dev *dev);
|
||||
void mt76_csa_finish(struct mt76_dev *dev);
|
||||
|
||||
int mt76_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
|
||||
int mt76_get_antenna(struct ieee80211_hw *hw, int radio_idx, u32 *tx_ant,
|
||||
u32 *rx_ant);
|
||||
int mt76_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set);
|
||||
void mt76_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id);
|
||||
int mt76_get_rate(struct mt76_dev *dev,
|
||||
@@ -1793,7 +1826,8 @@ 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);
|
||||
page_pool_put_full_page(pp_page_to_nmdesc(page)->pp, page,
|
||||
allow_direct);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
@@ -1864,6 +1898,9 @@ mt76_vif_link(struct mt76_dev *dev, struct ieee80211_vif *vif, int link_id)
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_vif_data *mvif = mlink->mvif;
|
||||
|
||||
if (!link_id)
|
||||
return mlink;
|
||||
|
||||
return mt76_dereference(mvif->link[link_id], dev);
|
||||
}
|
||||
|
||||
@@ -1874,7 +1911,7 @@ mt76_vif_conf_link(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct mt76_vif_data *mvif = mlink->mvif;
|
||||
|
||||
if (link_conf == &vif->bss_conf)
|
||||
if (link_conf == &vif->bss_conf || !link_conf->link_id)
|
||||
return mlink;
|
||||
|
||||
return mt76_dereference(mvif->link[link_conf->link_id], dev);
|
||||
|
||||
@@ -44,7 +44,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
|
||||
if (idx >= MT7603_WTBL_STA - 1)
|
||||
goto free;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (!wcid)
|
||||
goto free;
|
||||
|
||||
|
||||
@@ -487,10 +487,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast)
|
||||
struct mt7603_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (idx >= MT7603_WTBL_SIZE)
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (unicast || !wcid)
|
||||
return wcid;
|
||||
|
||||
@@ -1266,12 +1263,9 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data)
|
||||
if (pid == MT_PACKET_ID_NO_ACK)
|
||||
return;
|
||||
|
||||
if (wcidx >= MT7603_WTBL_SIZE)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ static int mt7603_set_sar_specs(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static int
|
||||
mt7603_config(struct ieee80211_hw *hw, u32 changed)
|
||||
mt7603_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt7603_dev *dev = hw->priv;
|
||||
int ret = 0;
|
||||
@@ -657,7 +657,8 @@ mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
static void
|
||||
mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
mt7603_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class)
|
||||
{
|
||||
struct mt7603_dev *dev = hw->priv;
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ void mt7615_init_txpower(struct mt7615_dev *dev,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains;
|
||||
int delta_idx, delta = mt76_tx_power_nss_delta(n_chains);
|
||||
int delta_idx, delta = mt76_tx_power_path_delta(n_chains);
|
||||
u8 *eep = (u8 *)dev->mt76.eeprom.data;
|
||||
enum nl80211_band band = sband->band;
|
||||
struct mt76_power_limits limits;
|
||||
|
||||
@@ -93,10 +93,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
|
||||
struct mt7615_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (idx >= MT7615_WTBL_SIZE)
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (unicast || !wcid)
|
||||
return wcid;
|
||||
|
||||
@@ -1507,7 +1504,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ static void mt7615_stop(struct ieee80211_hw *hw, bool suspend)
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
|
||||
cancel_delayed_work_sync(&phy->mt76->mac_work);
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
|
||||
cancel_delayed_work_sync(&dev->pm.ps_work);
|
||||
@@ -420,7 +420,7 @@ static int mt7615_set_sar_specs(struct ieee80211_hw *hw,
|
||||
return mt76_update_channel(phy->mt76);
|
||||
}
|
||||
|
||||
static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static int mt7615_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
@@ -784,7 +784,8 @@ static void mt7615_tx(struct ieee80211_hw *hw,
|
||||
mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);
|
||||
}
|
||||
|
||||
static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 val)
|
||||
{
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
@@ -972,7 +973,8 @@ mt7615_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
static void
|
||||
mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
mt7615_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class)
|
||||
{
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
struct mt7615_dev *dev = phy->dev;
|
||||
@@ -984,7 +986,8 @@ mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
mt7615_set_antenna(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct mt7615_dev *dev = mt7615_hw_dev(hw);
|
||||
struct mt7615_phy *phy = mt7615_hw_phy(hw);
|
||||
@@ -1043,7 +1046,7 @@ void mt7615_roc_work(struct work_struct *work)
|
||||
|
||||
void mt7615_roc_timer(struct timer_list *timer)
|
||||
{
|
||||
struct mt7615_phy *phy = from_timer(phy, timer, roc_timer);
|
||||
struct mt7615_phy *phy = timer_container_of(phy, timer, roc_timer);
|
||||
|
||||
ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
|
||||
}
|
||||
@@ -1194,7 +1197,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
|
||||
if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
return 0;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
|
||||
mt7615_mutex_acquire(phy->dev);
|
||||
|
||||
@@ -2071,7 +2071,7 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
|
||||
};
|
||||
|
||||
tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan, tx_power);
|
||||
tx_power -= mt76_tx_power_nss_delta(n_chains);
|
||||
tx_power -= mt76_tx_power_path_delta(n_chains);
|
||||
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
|
||||
&limits, tx_power);
|
||||
mphy->txpower_cur = tx_power;
|
||||
@@ -2088,8 +2088,8 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
|
||||
int delta = 0;
|
||||
|
||||
if (i < n_chains - 1)
|
||||
delta = mt76_tx_power_nss_delta(n_chains) -
|
||||
mt76_tx_power_nss_delta(i + 1);
|
||||
delta = mt76_tx_power_path_delta(n_chains) -
|
||||
mt76_tx_power_path_delta(i + 1);
|
||||
sku[MT_SKU_1SS_DELTA + i] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,12 +223,12 @@ void mt7615_mac_reset_work(struct work_struct *work)
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
wake_up(&dev->mt76.mcu.wait);
|
||||
cancel_delayed_work_sync(&dev->mphy.mac_work);
|
||||
del_timer_sync(&dev->phy.roc_timer);
|
||||
timer_delete_sync(&dev->phy.roc_timer);
|
||||
cancel_work_sync(&dev->phy.roc_work);
|
||||
if (phy2) {
|
||||
set_bit(MT76_RESET, &phy2->mt76->state);
|
||||
cancel_delayed_work_sync(&phy2->mt76->mac_work);
|
||||
del_timer_sync(&phy2->roc_timer);
|
||||
timer_delete_sync(&phy2->roc_timer);
|
||||
cancel_work_sync(&phy2->roc_work);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2020 MediaTek Inc.
|
||||
*
|
||||
* Author: Felix Fietkau <nbd@nbd.name>
|
||||
* Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "../sdio.h"
|
||||
#include "mt7615.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "regs.h"
|
||||
|
||||
static int mt7663s_mcu_init_sched(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_sdio *sdio = &dev->mt76.sdio;
|
||||
u32 txdwcnt;
|
||||
|
||||
sdio->sched.pse_data_quota = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP,
|
||||
MT_HIF0_MIN_QUOTA);
|
||||
sdio->sched.pse_mcu_quota = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP,
|
||||
MT_HIF1_MIN_QUOTA);
|
||||
sdio->sched.ple_data_quota = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP,
|
||||
MT_HIF0_MIN_QUOTA);
|
||||
sdio->sched.pse_page_size = MT_PSE_PAGE_SZ;
|
||||
txdwcnt = mt76_get_field(dev, MT_PP_TXDWCNT,
|
||||
MT_PP_TXDWCNT_TX1_ADD_DW_CNT);
|
||||
sdio->sched.deficit = txdwcnt << 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
int ret;
|
||||
|
||||
mt7615_mcu_fill_msg(dev, skb, cmd, seq);
|
||||
ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[MT_MCUQ_WM], skb, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76_queue_kick(dev, mdev->q_mcu[MT_MCUQ_WM]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
|
||||
{
|
||||
struct sdio_func *func = dev->mt76.sdio.func;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
u32 status;
|
||||
int ret;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL);
|
||||
|
||||
ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
|
||||
status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->mt76.dev, "Cannot get ownership from device");
|
||||
} else {
|
||||
clear_bit(MT76_STATE_PM, &mphy->state);
|
||||
|
||||
pm->stats.last_wake_event = jiffies;
|
||||
pm->stats.doze_time += pm->stats.last_wake_event -
|
||||
pm->stats.last_doze_event;
|
||||
}
|
||||
sdio_release_host(func);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7663s_mcu_drv_pmctrl(struct mt7615_dev *dev)
|
||||
{
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->pm.mutex);
|
||||
|
||||
if (test_bit(MT76_STATE_PM, &mphy->state))
|
||||
ret = __mt7663s_mcu_drv_pmctrl(dev);
|
||||
|
||||
mutex_unlock(&dev->pm.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)
|
||||
{
|
||||
struct sdio_func *func = dev->mt76.sdio.func;
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
int ret = 0;
|
||||
u32 status;
|
||||
|
||||
mutex_lock(&pm->mutex);
|
||||
|
||||
if (mt76_connac_skip_fw_pmctrl(mphy, pm))
|
||||
goto out;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL);
|
||||
|
||||
ret = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status,
|
||||
!(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->mt76.dev, "Cannot set ownership to device");
|
||||
clear_bit(MT76_STATE_PM, &mphy->state);
|
||||
} else {
|
||||
pm->stats.last_doze_event = jiffies;
|
||||
pm->stats.awake_time += pm->stats.last_doze_event -
|
||||
pm->stats.last_wake_event;
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
out:
|
||||
mutex_unlock(&pm->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7663s_mcu_init(struct mt7615_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7663s_mcu_ops = {
|
||||
.headroom = sizeof(struct mt7615_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7663s_mcu_send_message,
|
||||
.mcu_parse_response = mt7615_mcu_parse_response,
|
||||
.mcu_rr = mt76_connac_mcu_reg_rr,
|
||||
.mcu_wr = mt76_connac_mcu_reg_wr,
|
||||
};
|
||||
struct mt7615_mcu_ops *mcu_ops;
|
||||
int ret;
|
||||
|
||||
ret = __mt7663s_mcu_drv_pmctrl(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mt7663s_mcu_ops;
|
||||
|
||||
ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
|
||||
if (ret) {
|
||||
mt7615_mcu_restart(&dev->mt76);
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_N9_RDY, 0, 500))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = __mt7663_load_firmware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mcu_ops = devm_kmemdup(dev->mt76.dev, dev->mcu_ops, sizeof(*mcu_ops),
|
||||
GFP_KERNEL);
|
||||
if (!mcu_ops)
|
||||
return -ENOMEM;
|
||||
|
||||
mcu_ops->set_drv_ctrl = mt7663s_mcu_drv_pmctrl;
|
||||
mcu_ops->set_fw_ctrl = mt7663s_mcu_fw_pmctrl;
|
||||
dev->mcu_ops = mcu_ops;
|
||||
|
||||
ret = mt7663s_mcu_init_sched(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ static void mt7663u_stop(struct ieee80211_hw *hw, bool suspend)
|
||||
struct mt7615_dev *dev = hw->priv;
|
||||
|
||||
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
cancel_delayed_work_sync(&phy->scan_work);
|
||||
cancel_delayed_work_sync(&phy->mt76->mac_work);
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2019 MediaTek Inc.
|
||||
*
|
||||
* Author: Felix Fietkau <nbd@nbd.name>
|
||||
* Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "mt7615.h"
|
||||
#include "mac.h"
|
||||
#include "mcu.h"
|
||||
#include "regs.h"
|
||||
|
||||
static int
|
||||
mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
int cmd, int *seq)
|
||||
{
|
||||
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
|
||||
int ret, ep, len, pad;
|
||||
|
||||
mt7615_mcu_fill_msg(dev, skb, cmd, seq);
|
||||
if (cmd != MCU_CMD(FW_SCATTER))
|
||||
ep = MT_EP_OUT_INBAND_CMD;
|
||||
else
|
||||
ep = MT_EP_OUT_AC_BE;
|
||||
|
||||
len = skb->len;
|
||||
put_unaligned_le32(len, skb_push(skb, sizeof(len)));
|
||||
pad = round_up(skb->len, 4) + 4 - skb->len;
|
||||
ret = mt76_skb_adjust_pad(skb, pad);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
|
||||
1000, ep);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_power_on(struct mt7615_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0x0, 0x1, NULL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON,
|
||||
FW_STATE_PWR_ON << 1, 500)) {
|
||||
dev_err(dev->mt76.dev, "Timeout for power on\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7663u_mcu_init(struct mt7615_dev *dev)
|
||||
{
|
||||
static const struct mt76_mcu_ops mt7663u_mcu_ops = {
|
||||
.headroom = MT_USB_HDR_SIZE + sizeof(struct mt7615_mcu_txd),
|
||||
.tailroom = MT_USB_TAIL_SIZE,
|
||||
.mcu_skb_send_msg = mt7663u_mcu_send_message,
|
||||
.mcu_parse_response = mt7615_mcu_parse_response,
|
||||
};
|
||||
int ret;
|
||||
|
||||
dev->mt76.mcu_ops = &mt7663u_mcu_ops;
|
||||
|
||||
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) {
|
||||
ret = mt7615_mcu_restart(&dev->mt76);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
|
||||
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
|
||||
return -EIO;
|
||||
|
||||
ret = mt7663u_mcu_power_on(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = __mt7663_load_firmware(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
|
||||
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -232,9 +232,14 @@ static inline bool is_mt7992(struct mt76_dev *dev)
|
||||
return mt76_chip(dev) == 0x7992;
|
||||
}
|
||||
|
||||
static inline bool is_mt7990(struct mt76_dev *dev)
|
||||
{
|
||||
return mt76_chip(dev) == 0x7993;
|
||||
}
|
||||
|
||||
static inline bool is_mt799x(struct mt76_dev *dev)
|
||||
{
|
||||
return is_mt7996(dev) || is_mt7992(dev);
|
||||
return is_mt7996(dev) || is_mt7992(dev) || is_mt7990(dev);
|
||||
}
|
||||
|
||||
static inline bool is_mt7622(struct mt76_dev *dev)
|
||||
|
||||
@@ -273,6 +273,7 @@ enum tx_frag_idx {
|
||||
#define MT_TXD6_TX_RATE GENMASK(21, 16)
|
||||
#define MT_TXD6_TIMESTAMP_OFS_EN BIT(15)
|
||||
#define MT_TXD6_TIMESTAMP_OFS_IDX GENMASK(14, 10)
|
||||
#define MT_TXD6_TID_ADDBA GENMASK(10, 8)
|
||||
#define MT_TXD6_MSDU_CNT GENMASK(9, 4)
|
||||
#define MT_TXD6_MSDU_CNT_V2 GENMASK(15, 10)
|
||||
#define MT_TXD6_DIS_MAT BIT(3)
|
||||
@@ -314,6 +315,9 @@ enum tx_frag_idx {
|
||||
#define MT_TXFREE_INFO_COUNT GENMASK(27, 24)
|
||||
#define MT_TXFREE_INFO_STAT GENMASK(29, 28)
|
||||
|
||||
#define MT_TXS_HDR_SIZE 4 /* Unit: DW */
|
||||
#define MT_TXS_SIZE 12 /* Unit: DW */
|
||||
|
||||
#define MT_TXS0_BW GENMASK(31, 29)
|
||||
#define MT_TXS0_TID GENMASK(28, 26)
|
||||
#define MT_TXS0_AMPDU BIT(25)
|
||||
|
||||
@@ -1172,7 +1172,7 @@ void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
|
||||
wcid_idx = wcid->idx;
|
||||
} else {
|
||||
wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(dev->wcid[wcid_idx]);
|
||||
wcid = __mt76_wcid_ptr(dev, wcid_idx);
|
||||
|
||||
if (wcid && wcid->sta) {
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta,
|
||||
|
||||
@@ -67,8 +67,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
|
||||
if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
|
||||
(is_mt7921(dev) && addr == 0x900000) ||
|
||||
(is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
|
||||
(is_mt7996(dev) && addr == 0x900000) ||
|
||||
(is_mt7992(dev) && addr == 0x900000))
|
||||
(is_mt799x(dev) && addr == 0x900000))
|
||||
cmd = MCU_CMD(PATCH_START_REQ);
|
||||
else
|
||||
cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ);
|
||||
@@ -288,7 +287,7 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif_link *mvif
|
||||
|
||||
mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,
|
||||
&hdr.wlan_idx_hi);
|
||||
skb = mt76_mcu_msg_alloc(dev, NULL, len);
|
||||
skb = __mt76_mcu_msg_alloc(dev, NULL, len, len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@@ -1168,7 +1167,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
|
||||
.len = cpu_to_le16(sizeof(struct req_tlv)),
|
||||
.active = enable,
|
||||
.link_idx = mvif->idx,
|
||||
.link_idx = mvif->link_idx,
|
||||
},
|
||||
};
|
||||
struct {
|
||||
@@ -1191,7 +1190,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
|
||||
.bmc_tx_wlan_idx = cpu_to_le16(wcid->idx),
|
||||
.sta_idx = cpu_to_le16(wcid->idx),
|
||||
.conn_state = 1,
|
||||
.link_idx = mvif->idx,
|
||||
.link_idx = mvif->link_idx,
|
||||
},
|
||||
};
|
||||
int err, idx, cmd, len;
|
||||
@@ -1667,6 +1666,44 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
|
||||
|
||||
void mt76_connac_mcu_build_rnr_scan_param(struct mt76_dev *mdev,
|
||||
struct cfg80211_scan_request *sreq)
|
||||
{
|
||||
struct ieee80211_channel **scan_list = sreq->channels;
|
||||
int i, bssid_index = 0;
|
||||
|
||||
/* clear 6G active Scan BSSID table */
|
||||
memset(&mdev->rnr, 0, sizeof(mdev->rnr));
|
||||
|
||||
for (i = 0; i < sreq->n_6ghz_params; i++) {
|
||||
u8 ch_idx = sreq->scan_6ghz_params[i].channel_idx;
|
||||
int k = 0;
|
||||
|
||||
/* Remove the duplicated BSSID */
|
||||
for (k = 0; k < bssid_index; k++) {
|
||||
if (!memcmp(&mdev->rnr.bssid[k],
|
||||
sreq->scan_6ghz_params[i].bssid,
|
||||
ETH_ALEN))
|
||||
break;
|
||||
}
|
||||
|
||||
if (k == bssid_index &&
|
||||
bssid_index < MT76_RNR_SCAN_MAX_BSSIDS) {
|
||||
memcpy(&mdev->rnr.bssid[bssid_index++],
|
||||
sreq->scan_6ghz_params[i].bssid, ETH_ALEN);
|
||||
mdev->rnr.channel[k] = scan_list[ch_idx]->hw_value;
|
||||
}
|
||||
}
|
||||
|
||||
mdev->rnr.bssid_num = bssid_index;
|
||||
|
||||
if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
memcpy(mdev->rnr.random_mac, sreq->mac_addr, ETH_ALEN);
|
||||
mdev->rnr.sreq_flag = sreq->flags;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac_mcu_build_rnr_scan_param);
|
||||
|
||||
#define MT76_CONNAC_SCAN_CHANNEL_TIME 60
|
||||
int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req)
|
||||
@@ -1703,8 +1740,8 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
if (!sreq->ssids[i].ssid_len)
|
||||
continue;
|
||||
|
||||
req->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
|
||||
memcpy(req->ssids[i].ssid, sreq->ssids[i].ssid,
|
||||
req->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
|
||||
memcpy(req->ssids[n_ssids].ssid, sreq->ssids[i].ssid,
|
||||
sreq->ssids[i].ssid_len);
|
||||
n_ssids++;
|
||||
}
|
||||
|
||||
@@ -873,6 +873,7 @@ enum {
|
||||
#define NETWORK_WDS BIT(21)
|
||||
|
||||
#define SCAN_FUNC_RANDOM_MAC BIT(0)
|
||||
#define SCAN_FUNC_RNR_SCAN BIT(3)
|
||||
#define SCAN_FUNC_SPLIT_SCAN BIT(5)
|
||||
|
||||
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
|
||||
@@ -1069,6 +1070,7 @@ enum {
|
||||
MCU_UNI_EVENT_WED_RRO = 0x57,
|
||||
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
|
||||
MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
|
||||
MCU_UNI_EVENT_SDO = 0x83,
|
||||
};
|
||||
|
||||
#define MCU_UNI_CMD_EVENT BIT(1)
|
||||
@@ -1186,6 +1188,11 @@ enum {
|
||||
#define MCU_UNI_CMD(_t) (__MCU_CMD_FIELD_UNI | \
|
||||
FIELD_PREP(__MCU_CMD_FIELD_ID, \
|
||||
MCU_UNI_CMD_##_t))
|
||||
|
||||
#define MCU_UNI_QUERY(_t) (__MCU_CMD_FIELD_UNI | __MCU_CMD_FIELD_QUERY | \
|
||||
FIELD_PREP(__MCU_CMD_FIELD_ID, \
|
||||
MCU_UNI_CMD_##_t))
|
||||
|
||||
#define MCU_CE_CMD(_t) (__MCU_CMD_FIELD_CE | \
|
||||
FIELD_PREP(__MCU_CMD_FIELD_ID, \
|
||||
MCU_CE_CMD_##_t))
|
||||
@@ -1291,16 +1298,20 @@ enum {
|
||||
MCU_UNI_CMD_EFUSE_CTRL = 0x2d,
|
||||
MCU_UNI_CMD_RA = 0x2f,
|
||||
MCU_UNI_CMD_MURU = 0x31,
|
||||
MCU_UNI_CMD_TESTMODE_RX_STAT = 0x32,
|
||||
MCU_UNI_CMD_BF = 0x33,
|
||||
MCU_UNI_CMD_CHANNEL_SWITCH = 0x34,
|
||||
MCU_UNI_CMD_THERMAL = 0x35,
|
||||
MCU_UNI_CMD_VOW = 0x37,
|
||||
MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
|
||||
MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
|
||||
MCU_UNI_CMD_RRO = 0x57,
|
||||
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
|
||||
MCU_UNI_CMD_PER_STA_INFO = 0x6d,
|
||||
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
|
||||
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
|
||||
MCU_UNI_CMD_RADIO_STATUS = 0x80,
|
||||
MCU_UNI_CMD_SDO = 0x88,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1373,6 +1384,7 @@ enum {
|
||||
UNI_BSS_INFO_OFFLOAD = 25,
|
||||
UNI_BSS_INFO_MLD = 26,
|
||||
UNI_BSS_INFO_PM_DISABLE = 27,
|
||||
UNI_BSS_INFO_EHT = 30,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -1973,6 +1985,8 @@ int mt76_connac_mcu_start_patch(struct mt76_dev *dev);
|
||||
int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get);
|
||||
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option);
|
||||
|
||||
void mt76_connac_mcu_build_rnr_scan_param(struct mt76_dev *mdev,
|
||||
struct cfg80211_scan_request *sreq);
|
||||
int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req);
|
||||
int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy,
|
||||
|
||||
@@ -156,7 +156,8 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.txwi_size = sizeof(struct mt76x02_txwi),
|
||||
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
|
||||
MT_DRV_SW_RX_AIRTIME,
|
||||
MT_DRV_SW_RX_AIRTIME |
|
||||
MT_DRV_IGNORE_TXS_FAILED,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX,
|
||||
.update_survey = mt76x02_update_channel,
|
||||
.set_channel = mt76x0_set_channel,
|
||||
|
||||
@@ -183,8 +183,8 @@ void mt76x02_wdt_work(struct work_struct *work);
|
||||
void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
|
||||
void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
|
||||
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
|
||||
s16 coverage_class);
|
||||
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
|
||||
int radio_idx, s16 coverage_class);
|
||||
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, u32 val);
|
||||
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
|
||||
bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
|
||||
void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
@@ -262,10 +262,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
|
||||
{
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (idx >= MT76x02_N_WCIDS)
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[idx]);
|
||||
wcid = __mt76_wcid_ptr(dev, idx);
|
||||
if (!wcid)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -564,9 +564,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (stat->wcid < MT76x02_N_WCIDS)
|
||||
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
|
||||
|
||||
wcid = mt76_wcid_ptr(dev, stat->wcid);
|
||||
if (wcid && wcid->sta) {
|
||||
void *priv;
|
||||
|
||||
|
||||
@@ -174,7 +174,6 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int budget)
|
||||
|
||||
int mt76x02_dma_init(struct mt76x02_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache __maybe_unused *t;
|
||||
int i, ret, fifo_size;
|
||||
struct mt76_queue *q;
|
||||
void *status_fifo;
|
||||
|
||||
@@ -264,8 +264,8 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
|
||||
};
|
||||
dev->beacon_ops = &beacon_ops;
|
||||
|
||||
hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt;
|
||||
hrtimer_setup(&dev->pre_tbtt_timer, mt76x02u_pre_tbtt_interrupt, CLOCK_MONOTONIC,
|
||||
HRTIMER_MODE_REL);
|
||||
INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work);
|
||||
|
||||
mt76x02_init_beacon_config(dev);
|
||||
|
||||
@@ -548,7 +548,7 @@ void mt76x02_set_tx_ackto(struct mt76x02_dev *dev)
|
||||
EXPORT_SYMBOL_GPL(mt76x02_set_tx_ackto);
|
||||
|
||||
void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
|
||||
s16 coverage_class)
|
||||
int radio_idx, s16 coverage_class)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
|
||||
@@ -559,7 +559,7 @@ void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76x02_set_coverage_class);
|
||||
|
||||
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, u32 val)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ mt76x2e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.txwi_size = sizeof(struct mt76x02_txwi),
|
||||
.drv_flags = MT_DRV_TX_ALIGNED4_SKBS |
|
||||
MT_DRV_SW_RX_AIRTIME,
|
||||
MT_DRV_SW_RX_AIRTIME |
|
||||
MT_DRV_IGNORE_TXS_FAILED,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX,
|
||||
.update_survey = mt76x02_update_channel,
|
||||
.set_channel = mt76x2e_set_channel,
|
||||
|
||||
@@ -54,7 +54,7 @@ int mt76x2e_set_channel(struct mt76_phy *phy)
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2_config(struct ieee80211_hw *hw, u32 changed)
|
||||
mt76x2_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
|
||||
@@ -99,8 +99,8 @@ mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
{
|
||||
}
|
||||
|
||||
static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
|
||||
u32 rx_ant)
|
||||
static int mt76x2_set_antenna(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ static const struct usb_device_id mt76x2u_device_table[] = {
|
||||
{ USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */
|
||||
{ USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */
|
||||
{ USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */
|
||||
{ USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */
|
||||
{ USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
|
||||
{ USB_DEVICE(0x2c4e, 0x0103) }, /* Mercury UD13 */
|
||||
{ USB_DEVICE(0x0846, 0x9014) }, /* Netgear WNDA3100v3 */
|
||||
{ USB_DEVICE(0x0846, 0x9053) }, /* Netgear A6210 */
|
||||
{ USB_DEVICE(0x045e, 0x02e6) }, /* XBox One Wireless Adapter */
|
||||
{ USB_DEVICE(0x045e, 0x02fe) }, /* XBox One Wireless Adapter */
|
||||
{ USB_DEVICE(0x2357, 0x0137) }, /* TP-Link TL-WDN6200 */
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -29,7 +32,8 @@ static int mt76x2u_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.drv_flags = MT_DRV_SW_RX_AIRTIME,
|
||||
.drv_flags = MT_DRV_SW_RX_AIRTIME |
|
||||
MT_DRV_IGNORE_TXS_FAILED,
|
||||
.survey_flags = SURVEY_INFO_TIME_TX,
|
||||
.update_survey = mt76x02_update_channel,
|
||||
.set_channel = mt76x2u_set_channel,
|
||||
|
||||
@@ -191,6 +191,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
struct mt76_usb *usb = &dev->mt76.usb;
|
||||
bool vht;
|
||||
int err;
|
||||
|
||||
INIT_DELAYED_WORK(&dev->cal_work, mt76x2u_phy_calibrate);
|
||||
@@ -217,7 +218,17 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
|
||||
|
||||
/* check hw sg support in order to enable AMSDU */
|
||||
hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_TX_SG_MAX_SIZE : 1;
|
||||
err = mt76_register_device(&dev->mt76, true, mt76x02_rates,
|
||||
switch (dev->mt76.rev) {
|
||||
case 0x76320044:
|
||||
/* these ASIC revisions do not support VHT */
|
||||
vht = false;
|
||||
break;
|
||||
default:
|
||||
vht = true;
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt76_register_device(&dev->mt76, vht, mt76x02_rates,
|
||||
ARRAY_SIZE(mt76x02_rates));
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
@@ -50,7 +50,7 @@ int mt76x2u_set_channel(struct mt76_phy *mphy)
|
||||
}
|
||||
|
||||
static int
|
||||
mt76x2u_config(struct ieee80211_hw *hw, u32 changed)
|
||||
mt76x2u_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt76x02_dev *dev = hw->priv;
|
||||
int err = 0;
|
||||
|
||||
@@ -211,13 +211,28 @@ static const struct file_operations mt7915_sys_recovery_ops = {
|
||||
static int
|
||||
mt7915_radar_trigger(void *data, u64 val)
|
||||
{
|
||||
struct mt7915_dev *dev = data;
|
||||
#define RADAR_MAIN_CHAIN 1
|
||||
#define RADAR_BACKGROUND 2
|
||||
struct mt7915_phy *phy = data;
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int rdd_idx;
|
||||
|
||||
if (val > MT_RX_SEL2)
|
||||
if (!val || val > RADAR_BACKGROUND)
|
||||
return -EINVAL;
|
||||
|
||||
if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {
|
||||
dev_err(dev->mt76.dev, "Background radar is not enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rdd_idx = mt7915_get_rdd_idx(phy, val == RADAR_BACKGROUND);
|
||||
if (rdd_idx < 0) {
|
||||
dev_err(dev->mt76.dev, "No RDD found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_RADAR_EMULATE,
|
||||
val, 0, 0);
|
||||
rdd_idx, 0, 0);
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
|
||||
@@ -303,9 +318,9 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
|
||||
phy->mib.dl_vht_3mu_cnt,
|
||||
phy->mib.dl_vht_4mu_cnt);
|
||||
|
||||
sub_total_cnt = phy->mib.dl_vht_2mu_cnt +
|
||||
phy->mib.dl_vht_3mu_cnt +
|
||||
phy->mib.dl_vht_4mu_cnt;
|
||||
sub_total_cnt = (u64)phy->mib.dl_vht_2mu_cnt +
|
||||
phy->mib.dl_vht_3mu_cnt +
|
||||
phy->mib.dl_vht_4mu_cnt;
|
||||
|
||||
seq_printf(file, "\nTotal non-HE MU-MIMO DL PPDU count: %lld",
|
||||
sub_total_cnt);
|
||||
@@ -353,26 +368,27 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
|
||||
phy->mib.dl_he_9to16ru_cnt,
|
||||
phy->mib.dl_he_gtr16ru_cnt);
|
||||
|
||||
sub_total_cnt = phy->mib.dl_he_2mu_cnt +
|
||||
phy->mib.dl_he_3mu_cnt +
|
||||
phy->mib.dl_he_4mu_cnt;
|
||||
sub_total_cnt = (u64)phy->mib.dl_he_2mu_cnt +
|
||||
phy->mib.dl_he_3mu_cnt +
|
||||
phy->mib.dl_he_4mu_cnt;
|
||||
total_ppdu_cnt = sub_total_cnt;
|
||||
|
||||
seq_printf(file, "\nTotal HE MU-MIMO DL PPDU count: %lld",
|
||||
sub_total_cnt);
|
||||
|
||||
sub_total_cnt = phy->mib.dl_he_2ru_cnt +
|
||||
phy->mib.dl_he_3ru_cnt +
|
||||
phy->mib.dl_he_4ru_cnt +
|
||||
phy->mib.dl_he_5to8ru_cnt +
|
||||
phy->mib.dl_he_9to16ru_cnt +
|
||||
phy->mib.dl_he_gtr16ru_cnt;
|
||||
sub_total_cnt = (u64)phy->mib.dl_he_2ru_cnt +
|
||||
phy->mib.dl_he_3ru_cnt +
|
||||
phy->mib.dl_he_4ru_cnt +
|
||||
phy->mib.dl_he_5to8ru_cnt +
|
||||
phy->mib.dl_he_9to16ru_cnt +
|
||||
phy->mib.dl_he_gtr16ru_cnt;
|
||||
total_ppdu_cnt += sub_total_cnt;
|
||||
|
||||
seq_printf(file, "\nTotal HE OFDMA DL PPDU count: %lld",
|
||||
sub_total_cnt);
|
||||
|
||||
total_ppdu_cnt += phy->mib.dl_he_su_cnt + phy->mib.dl_he_ext_su_cnt;
|
||||
total_ppdu_cnt += (u64)phy->mib.dl_he_su_cnt +
|
||||
phy->mib.dl_he_ext_su_cnt;
|
||||
|
||||
seq_printf(file, "\nAll HE DL PPDU count: %lld", total_ppdu_cnt);
|
||||
|
||||
@@ -404,20 +420,20 @@ static int mt7915_muru_stats_show(struct seq_file *file, void *data)
|
||||
phy->mib.ul_hetrig_9to16ru_cnt,
|
||||
phy->mib.ul_hetrig_gtr16ru_cnt);
|
||||
|
||||
sub_total_cnt = phy->mib.ul_hetrig_2mu_cnt +
|
||||
phy->mib.ul_hetrig_3mu_cnt +
|
||||
phy->mib.ul_hetrig_4mu_cnt;
|
||||
sub_total_cnt = (u64)phy->mib.ul_hetrig_2mu_cnt +
|
||||
phy->mib.ul_hetrig_3mu_cnt +
|
||||
phy->mib.ul_hetrig_4mu_cnt;
|
||||
total_ppdu_cnt = sub_total_cnt;
|
||||
|
||||
seq_printf(file, "\nTotal HE MU-MIMO UL TB PPDU count: %lld",
|
||||
sub_total_cnt);
|
||||
|
||||
sub_total_cnt = phy->mib.ul_hetrig_2ru_cnt +
|
||||
phy->mib.ul_hetrig_3ru_cnt +
|
||||
phy->mib.ul_hetrig_4ru_cnt +
|
||||
phy->mib.ul_hetrig_5to8ru_cnt +
|
||||
phy->mib.ul_hetrig_9to16ru_cnt +
|
||||
phy->mib.ul_hetrig_gtr16ru_cnt;
|
||||
sub_total_cnt = (u64)phy->mib.ul_hetrig_2ru_cnt +
|
||||
phy->mib.ul_hetrig_3ru_cnt +
|
||||
phy->mib.ul_hetrig_4ru_cnt +
|
||||
phy->mib.ul_hetrig_5to8ru_cnt +
|
||||
phy->mib.ul_hetrig_9to16ru_cnt +
|
||||
phy->mib.ul_hetrig_gtr16ru_cnt;
|
||||
total_ppdu_cnt += sub_total_cnt;
|
||||
|
||||
seq_printf(file, "\nTotal HE OFDMA UL TB PPDU count: %lld",
|
||||
@@ -444,6 +460,11 @@ mt7915_rdd_monitor(struct seq_file *s, void *data)
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (!mt7915_eeprom_has_background_radar(dev)) {
|
||||
seq_puts(s, "no background radar capability\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!cfg80211_chandef_valid(chandef)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
@@ -1084,13 +1105,13 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
|
||||
return -EINVAL;
|
||||
|
||||
if (pwr160)
|
||||
pwr160 = mt7915_get_power_bound(phy, pwr160);
|
||||
pwr160 = mt76_get_power_bound(mphy, pwr160);
|
||||
if (pwr80)
|
||||
pwr80 = mt7915_get_power_bound(phy, pwr80);
|
||||
pwr80 = mt76_get_power_bound(mphy, pwr80);
|
||||
if (pwr40)
|
||||
pwr40 = mt7915_get_power_bound(phy, pwr40);
|
||||
pwr40 = mt76_get_power_bound(mphy, pwr40);
|
||||
if (pwr20)
|
||||
pwr20 = mt7915_get_power_bound(phy, pwr20);
|
||||
pwr20 = mt76_get_power_bound(mphy, pwr20);
|
||||
|
||||
if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0)
|
||||
return -EINVAL;
|
||||
@@ -1241,7 +1262,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
|
||||
if (!dev->dbdc_support || phy->mt76->band_idx) {
|
||||
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
|
||||
&dev->hw_pattern);
|
||||
debugfs_create_file("radar_trigger", 0200, dir, dev,
|
||||
debugfs_create_file("radar_trigger", 0200, dir, phy,
|
||||
&fops_radar_trigger);
|
||||
debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
|
||||
mt7915_rdd_monitor);
|
||||
|
||||
@@ -147,7 +147,7 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
|
||||
/* read eeprom data from efuse */
|
||||
block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);
|
||||
for (i = 0; i < block_num; i++) {
|
||||
ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size);
|
||||
ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -365,6 +365,37 @@ s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
|
||||
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
|
||||
}
|
||||
|
||||
bool
|
||||
mt7915_eeprom_has_background_radar(struct mt7915_dev *dev)
|
||||
{
|
||||
u8 val, buf[MT7915_EEPROM_BLOCK_SIZE];
|
||||
u8 band_sel, tx_path, rx_path;
|
||||
int offs = MT_EE_WIFI_CONF + 1;
|
||||
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7915:
|
||||
return true;
|
||||
case 0x7906:
|
||||
/* read efuse to check background radar capability */
|
||||
if (mt7915_mcu_get_eeprom(dev, offs, buf))
|
||||
break;
|
||||
|
||||
val = buf[offs % MT7915_EEPROM_BLOCK_SIZE];
|
||||
band_sel = u8_get_bits(val, MT_EE_WIFI_CONF0_BAND_SEL);
|
||||
tx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_TX_PATH);
|
||||
rx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_RX_PATH);
|
||||
|
||||
return (band_sel == MT_EE_V2_BAND_SEL_5GHZ &&
|
||||
tx_path == rx_path && rx_path == 2);
|
||||
case 0x7981:
|
||||
case 0x7986:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const u8 mt7915_sku_group_len[] = {
|
||||
[SKU_CCK] = 4,
|
||||
[SKU_OFDM] = 8,
|
||||
|
||||
@@ -55,6 +55,7 @@ enum mt7915_eeprom_field {
|
||||
#define MT_EE_CAL_DPD_SIZE_V2_7981 (102 * MT_EE_CAL_UNIT) /* no 6g dpd data */
|
||||
|
||||
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
|
||||
#define MT_EE_WIFI_CONF0_RX_PATH GENMASK(5, 3)
|
||||
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
|
||||
#define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(7, 6)
|
||||
#define MT_EE_WIFI_CONF_STREAM_NUM GENMASK(7, 5)
|
||||
|
||||
@@ -300,7 +300,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy,
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int i, n_chains = hweight16(phy->mt76->chainmask);
|
||||
int nss_delta = mt76_tx_power_nss_delta(n_chains);
|
||||
int path_delta = mt76_tx_power_path_delta(n_chains);
|
||||
int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
|
||||
struct mt76_power_limits limits;
|
||||
|
||||
@@ -320,7 +320,7 @@ static void __mt7915_init_txpower(struct mt7915_phy *phy,
|
||||
target_power = mt76_get_rate_power_limits(phy->mt76, chan,
|
||||
&limits,
|
||||
target_power);
|
||||
target_power += nss_delta;
|
||||
target_power += path_delta;
|
||||
target_power = DIV_ROUND_UP(target_power, 2);
|
||||
chan->max_power = min_t(int, chan->max_reg_power,
|
||||
target_power);
|
||||
@@ -407,10 +407,13 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
|
||||
|
||||
if (mt7915_eeprom_has_background_radar(phy->dev) &&
|
||||
#if defined(CONFIG_OF)
|
||||
if (!mdev->dev->of_node ||
|
||||
!of_property_read_bool(mdev->dev->of_node,
|
||||
"mediatek,disable-radar-background"))
|
||||
(!mdev->dev->of_node ||
|
||||
!of_property_read_bool(mdev->dev->of_node,
|
||||
"mediatek,disable-radar-background")))
|
||||
#else
|
||||
1)
|
||||
#endif
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND);
|
||||
@@ -951,8 +954,7 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US;
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
|
||||
c |= IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
|
||||
elem->phy_cap_info[2] |= c;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
|
||||
|
||||
@@ -60,10 +60,7 @@ static struct mt76_wcid *mt7915_rx_get_wcid(struct mt7915_dev *dev,
|
||||
struct mt7915_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (unicast || !wcid)
|
||||
return wcid;
|
||||
|
||||
@@ -938,7 +935,7 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len)
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
continue;
|
||||
@@ -1043,12 +1040,9 @@ static void mt7915_mac_add_txs(struct mt7915_dev *dev, void *data)
|
||||
if (pid < MT_PACKET_ID_WED)
|
||||
return;
|
||||
|
||||
if (wcidx >= mt7915_wtbl_size(dev))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
@@ -1500,17 +1494,15 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip full reset failed\n");
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
while (!list_empty(&dev->mt76.sta_poll_list))
|
||||
list_del_init(dev->mt76.sta_poll_list.next);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask));
|
||||
dev->mt76.vif_mask = 0;
|
||||
dev->phy.omac_mask = 0;
|
||||
if (phy2)
|
||||
phy2->omac_mask = 0;
|
||||
|
||||
mt76_reset_device(&dev->mt76);
|
||||
|
||||
INIT_LIST_HEAD(&dev->sta_rc_list);
|
||||
INIT_LIST_HEAD(&dev->twt_list);
|
||||
|
||||
i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA);
|
||||
dev->mt76.global_wcid.idx = i;
|
||||
dev->recovery.hw_full_reset = false;
|
||||
@@ -2073,16 +2065,15 @@ void mt7915_mac_work(struct work_struct *work)
|
||||
static void mt7915_dfs_stop_radar_detector(struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int rdd_idx = mt7915_get_rdd_idx(phy, false);
|
||||
|
||||
if (phy->rdd_state & BIT(0))
|
||||
mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0,
|
||||
MT_RX_SEL0, 0);
|
||||
if (phy->rdd_state & BIT(1))
|
||||
mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1,
|
||||
MT_RX_SEL0, 0);
|
||||
if (rdd_idx < 0)
|
||||
return;
|
||||
|
||||
mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0);
|
||||
}
|
||||
|
||||
static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
|
||||
static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int rdd_idx)
|
||||
{
|
||||
int err, region;
|
||||
|
||||
@@ -2099,52 +2090,38 @@ static int mt7915_dfs_start_rdd(struct mt7915_dev *dev, int chain)
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain,
|
||||
MT_RX_SEL0, region);
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, chain,
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT, rdd_idx,
|
||||
0, dev->dbdc_support ? 2 : 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain,
|
||||
MT_RX_SEL0, 1);
|
||||
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, rdd_idx, 0, 1);
|
||||
}
|
||||
|
||||
static int mt7915_dfs_start_radar_detector(struct mt7915_phy *phy)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int err;
|
||||
int err, rdd_idx;
|
||||
|
||||
rdd_idx = mt7915_get_rdd_idx(phy, false);
|
||||
if (rdd_idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* start CAC */
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START,
|
||||
phy->mt76->band_idx, MT_RX_SEL0, 0);
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, rdd_idx, 0, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt7915_dfs_start_rdd(dev, phy->mt76->band_idx);
|
||||
err = mt7915_dfs_start_rdd(dev, rdd_idx);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
phy->rdd_state |= BIT(phy->mt76->band_idx);
|
||||
|
||||
if (!is_mt7915(&dev->mt76))
|
||||
return 0;
|
||||
|
||||
if (chandef->width == NL80211_CHAN_WIDTH_160 ||
|
||||
chandef->width == NL80211_CHAN_WIDTH_80P80) {
|
||||
err = mt7915_dfs_start_rdd(dev, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
phy->rdd_state |= BIT(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2186,12 +2163,12 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
enum mt76_dfs_state dfs_state, prev_state;
|
||||
int err;
|
||||
int err, rdd_idx = mt7915_get_rdd_idx(phy, false);
|
||||
|
||||
prev_state = phy->mt76->dfs_state;
|
||||
dfs_state = mt76_phy_dfs_state(phy->mt76);
|
||||
|
||||
if (prev_state == dfs_state)
|
||||
if (prev_state == dfs_state || rdd_idx < 0)
|
||||
return 0;
|
||||
|
||||
if (prev_state == MT_DFS_STATE_UNKNOWN)
|
||||
@@ -2215,8 +2192,7 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
|
||||
if (dfs_state == MT_DFS_STATE_CAC)
|
||||
return 0;
|
||||
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END,
|
||||
phy->mt76->band_idx, MT_RX_SEL0, 0);
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END, rdd_idx, 0, 0);
|
||||
if (err < 0) {
|
||||
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||
return err;
|
||||
@@ -2226,15 +2202,13 @@ int mt7915_dfs_init_radar_detector(struct mt7915_phy *phy)
|
||||
return 0;
|
||||
|
||||
stop:
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START,
|
||||
phy->mt76->band_idx, MT_RX_SEL0, 0);
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, rdd_idx, 0, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (is_mt7915(&dev->mt76)) {
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_SET_WF_ANT,
|
||||
phy->mt76->band_idx, 0,
|
||||
dev->dbdc_support ? 2 : 0);
|
||||
rdd_idx, 0, dev->dbdc_support ? 2 : 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -449,7 +449,8 @@ static int mt7915_set_sar_specs(struct ieee80211_hw *hw,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static int mt7915_config(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 changed)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
@@ -906,7 +907,8 @@ static void mt7915_tx(struct ieee80211_hw *hw,
|
||||
mt76_tx(mphy, control->sta, wcid, skb);
|
||||
}
|
||||
|
||||
static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 val)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
@@ -1102,7 +1104,8 @@ mt7915_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
static void
|
||||
mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
mt7915_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class)
|
||||
{
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
@@ -1114,7 +1117,7 @@ mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
mt7915_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct mt7915_dev *dev = mt7915_hw_dev(hw);
|
||||
struct mt7915_phy *phy = mt7915_hw_phy(hw);
|
||||
@@ -1655,7 +1658,7 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_set_frag_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
mt7915_set_frag_threshold(struct ieee80211_hw *hw, int radio_idx, u32 val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -197,6 +197,8 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
|
||||
static void
|
||||
mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
|
||||
{
|
||||
mdev->mcu.timeout = 5 * HZ;
|
||||
|
||||
if ((cmd & __MCU_CMD_FIELD_ID) != MCU_CMD_EXT_CID)
|
||||
return;
|
||||
|
||||
@@ -208,6 +210,9 @@ mt7915_mcu_set_timeout(struct mt76_dev *mdev, int cmd)
|
||||
case MCU_EXT_CMD_BSS_INFO_UPDATE:
|
||||
mdev->mcu.timeout = 2 * HZ;
|
||||
return;
|
||||
case MCU_EXT_CMD_EFUSE_BUFFER_MODE:
|
||||
mdev->mcu.timeout = 10 * HZ;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -303,17 +308,35 @@ mt7915_mcu_rx_radar_detected(struct mt7915_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_phy *mphy = &dev->mt76.phy;
|
||||
struct mt7915_mcu_rdd_report *r;
|
||||
u32 sku;
|
||||
|
||||
r = (struct mt7915_mcu_rdd_report *)skb->data;
|
||||
|
||||
if (r->band_idx > MT_RX_SEL2)
|
||||
switch (r->rdd_idx) {
|
||||
case MT_RDD_IDX_BAND0:
|
||||
break;
|
||||
case MT_RDD_IDX_BAND1:
|
||||
sku = mt7915_check_adie(dev, true);
|
||||
/* the main phy is bound to band 1 for this sku */
|
||||
if (is_mt7986(&dev->mt76) &&
|
||||
(sku == MT7975_ONE_ADIE || sku == MT7976_ONE_ADIE))
|
||||
break;
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
break;
|
||||
case MT_RDD_IDX_BACKGROUND:
|
||||
if (!dev->rdd2_phy)
|
||||
return;
|
||||
mphy = dev->rdd2_phy->mt76;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Unknown RDD idx %d\n", r->rdd_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mphy)
|
||||
return;
|
||||
|
||||
if ((r->band_idx && !dev->phy.mt76->band_idx) &&
|
||||
dev->mt76.phys[MT_BAND1])
|
||||
mphy = dev->mt76.phys[MT_BAND1];
|
||||
|
||||
if (r->band_idx == MT_RX_SEL2)
|
||||
if (r->rdd_idx == MT_RDD_IDX_BACKGROUND)
|
||||
cfg80211_background_radar_event(mphy->hw->wiphy,
|
||||
&dev->rdd2_chandef,
|
||||
GFP_ATOMIC);
|
||||
@@ -2098,16 +2121,21 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* make sure fw is download state */
|
||||
if (mt7915_firmware_state(dev, false)) {
|
||||
/* restart firmware once */
|
||||
mt76_connac_mcu_restart(&dev->mt76);
|
||||
ret = mt7915_firmware_state(dev, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev,
|
||||
"Firmware is not ready for download\n");
|
||||
return ret;
|
||||
}
|
||||
/* Release Semaphore if taken by previous failed attempt */
|
||||
ret = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
|
||||
if (ret != PATCH_REL_SEM_SUCCESS) {
|
||||
dev_err(dev->mt76.dev, "Could not release semaphore\n");
|
||||
/* Continue anyways */
|
||||
}
|
||||
|
||||
/* Always restart MCU firmware */
|
||||
mt76_connac_mcu_restart(&dev->mt76);
|
||||
|
||||
/* Check if MCU is ready */
|
||||
ret = mt7915_firmware_state(dev, false);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Firmware did not enter download state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));
|
||||
@@ -2703,11 +2731,14 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct mt7915_dev *dev = phy->dev;
|
||||
int err, region;
|
||||
int err, region, rdd_idx;
|
||||
|
||||
rdd_idx = mt7915_get_rdd_idx(phy, true);
|
||||
if (rdd_idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!chandef) { /* disable offchain */
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, MT_RX_SEL2,
|
||||
0, 0);
|
||||
err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, rdd_idx, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -2733,8 +2764,7 @@ int mt7915_mcu_rdd_background_enable(struct mt7915_phy *phy,
|
||||
break;
|
||||
}
|
||||
|
||||
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, MT_RX_SEL2,
|
||||
0, region);
|
||||
return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, rdd_idx, 0, region);
|
||||
}
|
||||
|
||||
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd)
|
||||
@@ -2865,7 +2895,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev)
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
|
||||
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
|
||||
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
|
||||
{
|
||||
struct mt7915_mcu_eeprom_info req = {
|
||||
.addr = cpu_to_le32(round_down(offset,
|
||||
@@ -2873,8 +2903,8 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
|
||||
};
|
||||
struct mt7915_mcu_eeprom_info *res;
|
||||
struct sk_buff *skb;
|
||||
u8 *buf = read_buf;
|
||||
int ret;
|
||||
u8 *buf;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76,
|
||||
MCU_EXT_QUERY(EFUSE_ACCESS),
|
||||
@@ -2883,12 +2913,14 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
|
||||
return ret;
|
||||
|
||||
res = (struct mt7915_mcu_eeprom_info *)skb->data;
|
||||
if (!buf)
|
||||
#if defined(__linux__)
|
||||
buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
|
||||
buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
|
||||
#elif defined(__FreeBSD__)
|
||||
buf = (u8 *)dev->mt76.eeprom.data + le32_to_cpu(res->addr);
|
||||
buf = (u8 *)dev->mt76.eeprom.data + le32_to_cpu(res->addr);
|
||||
#endif
|
||||
memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
@@ -3333,7 +3365,7 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
txpower = mt7915_get_power_bound(phy, txpower);
|
||||
txpower = mt76_get_power_bound(mphy, txpower);
|
||||
if (txpower > mphy->txpower_cur || txpower < 0)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -3383,7 +3415,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
|
||||
int i, idx;
|
||||
int tx_power;
|
||||
|
||||
tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
|
||||
tx_power = mt76_get_power_bound(mphy, hw->conf.power_level);
|
||||
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
|
||||
&limits_array, tx_power);
|
||||
mphy->txpower_cur = tx_power;
|
||||
@@ -3974,7 +4006,7 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt7915_dev *dev, u16 wlan_idx)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]);
|
||||
wcid = mt76_wcid_ptr(dev, wlan_idx);
|
||||
if (wcid)
|
||||
wcid->stats.tx_packets += le32_to_cpu(res->tx_packets);
|
||||
else
|
||||
|
||||
@@ -57,7 +57,7 @@ struct mt7915_mcu_bcc_notify {
|
||||
struct mt7915_mcu_rdd_report {
|
||||
struct mt76_connac2_mcu_rxd_hdr rxd;
|
||||
|
||||
u8 band_idx;
|
||||
u8 rdd_idx;
|
||||
u8 long_detected;
|
||||
u8 constant_prf_detected;
|
||||
u8 staggered_prf_detected;
|
||||
@@ -515,16 +515,4 @@ enum {
|
||||
sizeof(struct bss_info_bmc_rate) +\
|
||||
sizeof(struct bss_info_ext_bss))
|
||||
|
||||
static inline s8
|
||||
mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
|
||||
{
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
int n_chains = hweight16(mphy->chainmask);
|
||||
|
||||
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
|
||||
txpower -= mt76_tx_power_nss_delta(n_chains);
|
||||
|
||||
return txpower;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -595,12 +595,9 @@ static void mt7915_mmio_wed_update_rx_stats(struct mtk_wed_device *wed,
|
||||
|
||||
dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
|
||||
|
||||
if (idx >= mt7915_wtbl_size(dev))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (wcid) {
|
||||
wcid->stats.rx_bytes += le32_to_cpu(stats->rx_byte_cnt);
|
||||
wcid->stats.rx_packets += le32_to_cpu(stats->rx_pkt_cnt);
|
||||
@@ -659,6 +656,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.base = devm_ioremap(dev->mt76.dev,
|
||||
pci_resource_start(pci_dev, 0),
|
||||
pci_resource_len(pci_dev, 0));
|
||||
if (!wed->wlan.base)
|
||||
return -ENOMEM;
|
||||
|
||||
wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
|
||||
wed->wlan.wpdma_int = pci_resource_start(pci_dev, 0) +
|
||||
MT_INT_WED_SOURCE_CSR;
|
||||
@@ -686,6 +686,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.bus_type = MTK_WED_BUS_AXI;
|
||||
wed->wlan.base = devm_ioremap(dev->mt76.dev, res->start,
|
||||
resource_size(res));
|
||||
if (!wed->wlan.base)
|
||||
return -ENOMEM;
|
||||
|
||||
wed->wlan.phy_base = res->start;
|
||||
wed->wlan.wpdma_int = res->start + MT_INT_SOURCE_CSR;
|
||||
wed->wlan.wpdma_mask = res->start + MT_INT_MASK_CSR;
|
||||
|
||||
@@ -218,8 +218,6 @@ struct mt7915_phy {
|
||||
s16 coverage_class;
|
||||
u8 slottime;
|
||||
|
||||
u8 rdd_state;
|
||||
|
||||
u32 trb_ts;
|
||||
|
||||
u32 rx_ampdu_ts;
|
||||
@@ -334,10 +332,10 @@ enum {
|
||||
__MT_WFDMA_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_RX_SEL0,
|
||||
MT_RX_SEL1,
|
||||
MT_RX_SEL2, /* monitor chain */
|
||||
enum rdd_idx {
|
||||
MT_RDD_IDX_BAND0, /* RDD idx for band idx 0 (single-band) */
|
||||
MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */
|
||||
MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */
|
||||
};
|
||||
|
||||
enum mt7915_rdd_cmd {
|
||||
@@ -357,6 +355,18 @@ enum mt7915_rdd_cmd {
|
||||
RDD_IRQ_OFF,
|
||||
};
|
||||
|
||||
static inline int
|
||||
mt7915_get_rdd_idx(struct mt7915_phy *phy, bool is_background)
|
||||
{
|
||||
if (!phy->mt76->cap.has_5ghz)
|
||||
return -1;
|
||||
|
||||
if (is_background)
|
||||
return MT_RDD_IDX_BACKGROUND;
|
||||
|
||||
return phy->mt76->band_idx;
|
||||
}
|
||||
|
||||
static inline struct mt7915_phy *
|
||||
mt7915_hw_phy(struct ieee80211_hw *hw)
|
||||
{
|
||||
@@ -428,6 +438,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
u8 chain_idx);
|
||||
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band);
|
||||
bool mt7915_eeprom_has_background_radar(struct mt7915_dev *dev);
|
||||
int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2);
|
||||
void mt7915_dma_prefetch(struct mt7915_dev *dev);
|
||||
void mt7915_dma_cleanup(struct mt7915_dev *dev);
|
||||
@@ -476,7 +487,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
|
||||
struct ieee80211_sta *sta,
|
||||
void *data, u32 field);
|
||||
int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
|
||||
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
|
||||
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf);
|
||||
int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
|
||||
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
|
||||
bool hdr_trans);
|
||||
|
||||
@@ -472,7 +472,7 @@ void mt7921_mac_add_txs(struct mt792x_dev *dev, void *data)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
@@ -531,7 +531,7 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
||||
|
||||
count++;
|
||||
idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
continue;
|
||||
@@ -690,6 +690,8 @@ void mt7921_mac_reset_work(struct work_struct *work)
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
if (mt76_is_sdio(&dev->mt76) && atomic_read(&dev->mt76.bus_hung))
|
||||
return;
|
||||
|
||||
if (i == 10)
|
||||
dev_err(dev->mt76.dev, "chip reset failed\n");
|
||||
@@ -831,7 +833,7 @@ void mt7921_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
u16 idx;
|
||||
|
||||
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
wcid = __mt76_wcid_ptr(mdev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
|
||||
@@ -83,6 +83,11 @@ mt7921_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,
|
||||
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;
|
||||
|
||||
if (is_mt7922(phy->mt76->dev)) {
|
||||
he_cap_elem->phy_cap_info[0] |=
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
he_cap_elem->mac_cap_info[1] |=
|
||||
@@ -364,7 +369,7 @@ void mt7921_roc_abort_sync(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
@@ -395,7 +400,7 @@ static int mt7921_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
|
||||
mt792x_mutex_acquire(phy->dev);
|
||||
@@ -619,7 +624,7 @@ void mt7921_set_runtime_pm(struct mt792x_dev *dev)
|
||||
mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable);
|
||||
}
|
||||
|
||||
static int mt7921_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static int mt7921_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
@@ -811,6 +816,7 @@ int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
msta->deflink.wcid.phy_idx = mvif->bss_conf.mt76.band_idx;
|
||||
msta->deflink.wcid.tx_info |= MT_WCID_TX_INFO_SET;
|
||||
msta->deflink.last_txs = jiffies;
|
||||
msta->deflink.sta = msta;
|
||||
|
||||
ret = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
|
||||
if (ret)
|
||||
@@ -901,7 +907,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7921_mac_sta_remove);
|
||||
|
||||
static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
static int mt7921_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 val)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
@@ -1082,7 +1089,8 @@ mt7921_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7921_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
mt7921_set_antenna(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
@@ -1174,6 +1182,9 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
if (!msta->deflink.wcid.sta)
|
||||
return;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
if (enabled)
|
||||
@@ -1448,11 +1459,8 @@ static int mt7921_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Avoid beacon loss due to the CAC(Channel Availability Check) time
|
||||
* of the AP.
|
||||
*/
|
||||
if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef,
|
||||
IEEE80211_CHAN_RADAR))
|
||||
IEEE80211_CHAN_DISABLED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
@@ -1475,7 +1483,7 @@ static void mt7921_abort_channel_switch(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
del_timer_sync(&mvif->csa_timer);
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,8 @@ static int mt7921s_probe(struct sdio_func *func,
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
atomic_set(&mdev->bus_hung, false);
|
||||
|
||||
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
|
||||
(mt76_rr(dev, MT_HW_REV) & 0xff);
|
||||
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "mt7921.h"
|
||||
#include "../mt76_connac2_mac.h"
|
||||
#include "../sdio.h"
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
static void mt7921s_enable_irq(struct mt76_dev *dev)
|
||||
{
|
||||
@@ -35,6 +37,9 @@ int mt7921s_wfsys_reset(struct mt792x_dev *dev)
|
||||
struct mt76_sdio *sdio = &dev->mt76.sdio;
|
||||
u32 val, status;
|
||||
|
||||
if (atomic_read(&dev->mt76.bus_hung))
|
||||
return 0;
|
||||
|
||||
mt7921s_mcu_drv_pmctrl(dev);
|
||||
|
||||
sdio_claim_host(sdio->func);
|
||||
@@ -91,11 +96,64 @@ int mt7921s_init_reset(struct mt792x_dev *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mt76_sdio *msdio;
|
||||
static void mt7921s_card_reset(struct work_struct *work)
|
||||
{
|
||||
struct mmc_host *sdio_host = msdio->func->card->host;
|
||||
|
||||
sdio_claim_host(msdio->func);
|
||||
sdio_release_irq(msdio->func);
|
||||
sdio_release_host(msdio->func);
|
||||
|
||||
mmc_remove_host(sdio_host);
|
||||
msleep(50);
|
||||
mmc_add_host(sdio_host);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(sdio_reset_work, mt7921s_card_reset);
|
||||
static int mt7921s_check_bus(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_sdio *sdio = &dev->sdio;
|
||||
int err;
|
||||
|
||||
sdio_claim_host(sdio->func);
|
||||
sdio_readl(dev->sdio.func, MCR_WHCR, &err);
|
||||
sdio_release_host(sdio->func);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mt7921s_host_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
int err = -1;
|
||||
|
||||
if (!atomic_read(&mdev->bus_hung))
|
||||
err = mt7921s_check_bus(&dev->mt76);
|
||||
|
||||
if (err) {
|
||||
atomic_set(&mdev->bus_hung, true);
|
||||
msdio = &dev->mt76.sdio;
|
||||
dev_err(mdev->dev, "SDIO bus problem detected(%d), resetting card!!\n", err);
|
||||
schedule_work(&sdio_reset_work);
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_set(&mdev->bus_hung, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7921s_mac_reset(struct mt792x_dev *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
|
||||
|
||||
mt7921s_host_reset(dev);
|
||||
if (atomic_read(&dev->mt76.bus_hung))
|
||||
return 0;
|
||||
|
||||
mt76_txq_schedule_all(&dev->mphy);
|
||||
mt76_worker_disable(&dev->mt76.tx_worker);
|
||||
set_bit(MT76_MCU_RESET, &dev->mphy.state);
|
||||
|
||||
@@ -5,5 +5,6 @@ obj-$(CONFIG_MT7925E) += mt7925e.o
|
||||
obj-$(CONFIG_MT7925U) += mt7925u.o
|
||||
|
||||
mt7925-common-y := mac.o mcu.o main.o init.o debugfs.o
|
||||
mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
mt7925e-y := pci.o pci_mac.o pci_mcu.o
|
||||
mt7925u-y := usb.o
|
||||
|
||||
@@ -53,6 +53,8 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
|
||||
|
||||
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7925_%s",
|
||||
wiphy_name(wiphy));
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
|
||||
mt7925_hwmon_groups);
|
||||
@@ -60,15 +62,110 @@ static int mt7925_thermal_init(struct mt792x_phy *phy)
|
||||
}
|
||||
#endif
|
||||
|
||||
void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2)
|
||||
{
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
struct mt7925_clc_rule_v2 *rule;
|
||||
struct mt7925_clc *clc;
|
||||
bool old = dev->has_eht, new = true;
|
||||
u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2);
|
||||
u8 *pos;
|
||||
|
||||
if (mtcl_conf != MT792X_ACPI_MTCL_INVALID &&
|
||||
(((mtcl_conf >> 4) & 0x3) == 0)) {
|
||||
new = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!phy->clc[MT792x_CLC_BE_CTRL])
|
||||
goto out;
|
||||
|
||||
clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL];
|
||||
pos = clc->data;
|
||||
|
||||
while (1) {
|
||||
rule = (struct mt7925_clc_rule_v2 *)pos;
|
||||
|
||||
if (rule->alpha2[0] == alpha2[0] &&
|
||||
rule->alpha2[1] == alpha2[1]) {
|
||||
new = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the last one */
|
||||
if (rule->flag & BIT(0))
|
||||
break;
|
||||
|
||||
pos += sizeof(*rule);
|
||||
}
|
||||
|
||||
out:
|
||||
if (old == new)
|
||||
return;
|
||||
|
||||
dev->has_eht = new;
|
||||
mt7925_set_stream_he_eht_caps(phy);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
|
||||
{
|
||||
#define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \
|
||||
(!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq))
|
||||
#define MT7925_UNII_59G_IS_VALID 0x1
|
||||
#define MT7925_UNII_6G_IS_VALID 0x1e
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_channel *ch;
|
||||
u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, mdev->alpha2);
|
||||
int i;
|
||||
|
||||
if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) {
|
||||
if ((mtcl_conf & 0x3) == 0)
|
||||
dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID;
|
||||
if (((mtcl_conf >> 2) & 0x3) == 0)
|
||||
dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID;
|
||||
}
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_5GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
|
||||
/* UNII-4 */
|
||||
if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
|
||||
sband = wiphy->bands[NL80211_BAND_6GHZ];
|
||||
if (!sband)
|
||||
return;
|
||||
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
ch = &sband->channels[i];
|
||||
|
||||
/* UNII-5/6/7/8 */
|
||||
if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) ||
|
||||
IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) ||
|
||||
IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) ||
|
||||
IS_UNII_INVALID(4, 6875, 7125, ch->center_freq))
|
||||
ch->flags |= IEEE80211_CHAN_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
void mt7925_regd_update(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct ieee80211_hw *hw = mdev->hw;
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
|
||||
if (!dev->regd_change)
|
||||
return;
|
||||
|
||||
mt7925_mcu_set_clc(dev, mdev->alpha2, dev->country_ie_env);
|
||||
mt7925_regd_channel_update(wiphy, dev);
|
||||
mt7925_mcu_set_channel_domain(hw->priv);
|
||||
mt7925_set_tx_sar_pwr(hw, NULL);
|
||||
dev->regd_change = false;
|
||||
@@ -233,6 +330,12 @@ static void mt7925_init_work(struct work_struct *work)
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = mt7925_mcu_set_thermal_protect(dev);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "thermal protection enable failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* we support chip reset now */
|
||||
dev->hw_init_done = true;
|
||||
|
||||
@@ -250,6 +353,7 @@ int mt7925_register_device(struct mt792x_dev *dev)
|
||||
dev->mt76.tx_worker.fn = mt792x_tx_worker;
|
||||
|
||||
INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work);
|
||||
INIT_DELAYED_WORK(&dev->mlo_pm_work, mt7925_mlo_pm_work);
|
||||
INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work);
|
||||
spin_lock_init(&dev->pm.wake.lock);
|
||||
mutex_init(&dev->pm.mutex);
|
||||
|
||||
@@ -1040,7 +1040,7 @@ void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
@@ -1126,7 +1126,7 @@ mt7925_mac_tx_free(struct mt792x_dev *dev, void *data, int len)
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
continue;
|
||||
@@ -1449,11 +1449,11 @@ void mt7925_usb_sdio_tx_complete_skb(struct mt76_dev *mdev,
|
||||
u16 idx;
|
||||
|
||||
idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX);
|
||||
wcid = rcu_dereference(mdev->wcid[idx]);
|
||||
wcid = __mt76_wcid_ptr(mdev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
|
||||
if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt76_connac2_tx_check_aggr(sta, txwi);
|
||||
mt7925_tx_check_aggr(sta, e->skb, wcid);
|
||||
|
||||
skb_pull(e->skb, headroom);
|
||||
mt76_tx_complete_skb(mdev, e->wcid, e->skb);
|
||||
|
||||
@@ -251,12 +251,12 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)
|
||||
},
|
||||
};
|
||||
|
||||
if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EVT_EN))
|
||||
if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EN))
|
||||
return 0;
|
||||
|
||||
ext_capab[0].eml_capabilities = phy->eml_cap;
|
||||
ext_capab[0].mld_capa_and_ops =
|
||||
u16_encode_bits(1, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
|
||||
u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);
|
||||
|
||||
wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
|
||||
wiphy->iftype_ext_capab = ext_capab;
|
||||
@@ -334,6 +334,9 @@ int __mt7925_start(struct mt792x_phy *phy)
|
||||
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
|
||||
MT792x_WATCHDOG_TIME);
|
||||
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN)
|
||||
wiphy_rfkill_start_polling(mphy->hw->wiphy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__mt7925_start);
|
||||
@@ -360,10 +363,15 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
struct mt76_txq *mtxq;
|
||||
int idx, ret = 0;
|
||||
|
||||
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
mconf->mt76.idx = MT792x_MAX_INTERFACES;
|
||||
} else {
|
||||
mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask);
|
||||
|
||||
if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) {
|
||||
ret = -ENOSPC;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ?
|
||||
@@ -371,6 +379,7 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,
|
||||
mconf->mt76.band_idx = 0xff;
|
||||
mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?
|
||||
0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS;
|
||||
mconf->mt76.link_idx = hweight16(mvif->valid_links);
|
||||
|
||||
if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)
|
||||
mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4;
|
||||
@@ -421,6 +430,7 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
mvif->bss_conf.vif = mvif;
|
||||
mvif->sta.vif = mvif;
|
||||
mvif->deflink_id = IEEE80211_LINK_UNSPECIFIED;
|
||||
mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;
|
||||
|
||||
ret = mt7925_mac_link_bss_add(dev, &vif->bss_conf, &mvif->sta.deflink);
|
||||
if (ret < 0)
|
||||
@@ -446,7 +456,7 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev)
|
||||
{
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
|
||||
ieee80211_iterate_interfaces(mt76_hw(dev),
|
||||
@@ -478,7 +488,7 @@ static int mt7925_abort_roc(struct mt792x_phy *phy,
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
del_timer_sync(&phy->roc_timer);
|
||||
timer_delete_sync(&phy->roc_timer);
|
||||
cancel_work_sync(&phy->roc_work);
|
||||
|
||||
mt792x_mutex_acquire(phy->dev);
|
||||
@@ -747,7 +757,7 @@ void mt7925_set_runtime_pm(struct mt792x_dev *dev)
|
||||
mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
|
||||
}
|
||||
|
||||
static int mt7925_config(struct ieee80211_hw *hw, u32 changed)
|
||||
static int mt7925_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
int ret = 0;
|
||||
@@ -1149,7 +1159,12 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,
|
||||
struct mt792x_bss_conf *mconf;
|
||||
|
||||
mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
mt792x_mac_link_bss_remove(dev, mconf, mlink);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
mt792x_mac_link_bss_remove(dev, mconf, mlink);
|
||||
else
|
||||
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,
|
||||
link_sta, false);
|
||||
}
|
||||
|
||||
spin_lock_bh(&mdev->sta_poll_lock);
|
||||
@@ -1169,6 +1184,34 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt76_wcid *wcid;
|
||||
unsigned int link_id;
|
||||
|
||||
/* clean up bss before starec */
|
||||
for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct mt792x_link_sta *mlink;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
break;
|
||||
|
||||
link_sta = mt792x_sta_to_link_sta(vif, sta, link_id);
|
||||
if (!link_sta)
|
||||
continue;
|
||||
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, link_id);
|
||||
if (!link_conf)
|
||||
continue;
|
||||
|
||||
mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
|
||||
mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf,
|
||||
link_sta, false);
|
||||
}
|
||||
|
||||
for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
@@ -1206,55 +1249,27 @@ void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;
|
||||
struct {
|
||||
struct {
|
||||
u8 omac_idx;
|
||||
u8 band_idx;
|
||||
__le16 pad;
|
||||
} __packed hdr;
|
||||
struct req_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 active;
|
||||
u8 link_idx; /* hw link idx */
|
||||
u8 omac_addr[ETH_ALEN];
|
||||
} __packed tlv;
|
||||
} dev_req = {
|
||||
.hdr = {
|
||||
.omac_idx = 0,
|
||||
.band_idx = 0,
|
||||
},
|
||||
.tlv = {
|
||||
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
|
||||
.len = cpu_to_le16(sizeof(struct req_tlv)),
|
||||
.active = true,
|
||||
},
|
||||
};
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
unsigned long rem;
|
||||
|
||||
rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0);
|
||||
|
||||
mt7925_mac_sta_remove_links(dev, vif, sta, rem);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif)) {
|
||||
mt7925_mcu_set_dbdc(&dev->mphy, false);
|
||||
|
||||
/* recovery omac address for the legacy interface */
|
||||
memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN);
|
||||
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE),
|
||||
&dev_req, sizeof(dev_req), true);
|
||||
}
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
mt7925_mcu_del_dev(mdev, vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
|
||||
mvif->wep_sta = NULL;
|
||||
ewma_rssi_init(&mvif->bss_conf.rssi);
|
||||
}
|
||||
|
||||
mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove);
|
||||
|
||||
static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
|
||||
static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 val)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
|
||||
@@ -1289,22 +1304,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,
|
||||
params->buf_size);
|
||||
mt7925_mcu_uni_rx_ba(dev, vif, params, true);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid);
|
||||
mt7925_mcu_uni_rx_ba(dev, vif, params, false);
|
||||
mt7925_mcu_uni_rx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, true);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, true);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
set_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
@@ -1313,7 +1328,7 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
clear_bit(tid, &msta->deflink.wcid.ampdu_state);
|
||||
mt7925_mcu_uni_tx_ba(dev, vif, params, false);
|
||||
mt7925_mcu_uni_tx_ba(dev, params, false);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
@@ -1322,6 +1337,38 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt792x_dev *dev = priv;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
unsigned long valid = ieee80211_vif_is_mld(vif) ?
|
||||
mvif->valid_links : BIT(0);
|
||||
struct ieee80211_bss_conf *bss_conf;
|
||||
int i;
|
||||
|
||||
if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS)
|
||||
return;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
bss_conf = mt792x_vif_to_bss_conf(vif, i);
|
||||
mt7925_mcu_uni_bss_ps(dev, bss_conf);
|
||||
}
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
void mt7925_mlo_pm_work(struct work_struct *work)
|
||||
{
|
||||
struct mt792x_dev *dev = container_of(work, struct mt792x_dev,
|
||||
mlo_pm_work.work);
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
|
||||
ieee80211_iterate_active_interfaces(hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7925_mlo_pm_iter, dev);
|
||||
}
|
||||
|
||||
static bool is_valid_alpha2(const char *alpha2)
|
||||
{
|
||||
if (!alpha2)
|
||||
@@ -1378,6 +1425,8 @@ void mt7925_scan_work(struct work_struct *work)
|
||||
if (!is_valid_alpha2(evt->alpha2))
|
||||
break;
|
||||
|
||||
mt7925_regd_be_ctrl(phy->dev, evt->alpha2);
|
||||
|
||||
if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')
|
||||
break;
|
||||
|
||||
@@ -1436,7 +1485,7 @@ mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
err = mt7925_mcu_sched_scan_req(mphy, vif, req);
|
||||
err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
@@ -1462,7 +1511,8 @@ mt7925_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
||||
mt7925_set_antenna(struct ieee80211_hw *hw, int radio_idx,
|
||||
u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
@@ -1558,6 +1608,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
unsigned long valid = mvif->valid_links;
|
||||
u8 i;
|
||||
|
||||
if (!msta->vif)
|
||||
return;
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0);
|
||||
@@ -1572,6 +1625,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
|
||||
else
|
||||
clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);
|
||||
|
||||
if (!mlink->wcid.sta)
|
||||
continue;
|
||||
|
||||
mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);
|
||||
}
|
||||
|
||||
@@ -1823,6 +1879,10 @@ mt7925_change_chanctx(struct ieee80211_hw *hw,
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);
|
||||
mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76,
|
||||
link_conf, ctx);
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
|
||||
mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
|
||||
link_conf, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1871,6 +1931,9 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
|
||||
mt7925_mcu_sta_update(dev, NULL, vif, true,
|
||||
MT76_STA_INFO_STATE_ASSOC);
|
||||
mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc);
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
mvif->mlo_pm_state = MT792x_MLO_LINK_ASSOC;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ARP_FILTER) {
|
||||
@@ -1881,9 +1944,19 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_PS) {
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
bss_conf = mt792x_vif_to_bss_conf(vif, i);
|
||||
if (hweight16(mvif->valid_links) < 2) {
|
||||
/* legacy */
|
||||
bss_conf = &vif->bss_conf;
|
||||
mt7925_mcu_uni_bss_ps(dev, bss_conf);
|
||||
} else {
|
||||
if (mvif->mlo_pm_state == MT792x_MLO_LINK_ASSOC) {
|
||||
mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS_PENDING;
|
||||
} else if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS) {
|
||||
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
bss_conf = mt792x_vif_to_bss_conf(vif, i);
|
||||
mt7925_mcu_uni_bss_ps(dev, bss_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1899,8 +1972,10 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
struct mt792x_dev *dev = mt792x_hw_dev(hw);
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->link_id);
|
||||
link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);
|
||||
|
||||
mt792x_mutex_acquire(dev);
|
||||
|
||||
@@ -1934,13 +2009,18 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
|
||||
mt7925_mcu_set_tx(dev, info);
|
||||
|
||||
if (changed & BSS_CHANGED_BSSID) {
|
||||
if (ieee80211_vif_is_mld(vif) &&
|
||||
hweight16(mvif->valid_links) == 2)
|
||||
/* Indicate the secondary setup done */
|
||||
mt7925_mcu_uni_bss_bcnft(dev, info, true);
|
||||
if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS_PENDING) {
|
||||
/* Indicate the secondary setup done */
|
||||
mt7925_mcu_uni_bss_bcnft(dev, info, true);
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &dev->mlo_pm_work, 5 * HZ);
|
||||
mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
|
||||
mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
|
||||
link_conf, NULL);
|
||||
|
||||
mt792x_mutex_release(dev);
|
||||
}
|
||||
|
||||
@@ -1992,8 +2072,10 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
GFP_KERNEL);
|
||||
mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),
|
||||
GFP_KERNEL);
|
||||
if (!mconf || !mlink)
|
||||
if (!mconf || !mlink) {
|
||||
mt792x_mutex_release(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
mconfs[link_id] = mconf;
|
||||
@@ -2022,8 +2104,6 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
goto free;
|
||||
|
||||
if (mconf != &mvif->bss_conf) {
|
||||
mt7925_mcu_set_bss_pm(dev, link_conf, true);
|
||||
|
||||
err = mt7925_set_mlo_roc(phy, &mvif->bss_conf,
|
||||
vif->active_links);
|
||||
if (err < 0)
|
||||
@@ -2141,6 +2221,18 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
}
|
||||
|
||||
static void mt7925_rfkill_poll(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
int ret;
|
||||
|
||||
mt792x_mutex_acquire(phy->dev);
|
||||
ret = mt7925_mcu_wf_rf_pin_ctrl(phy);
|
||||
mt792x_mutex_release(phy->dev);
|
||||
|
||||
wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0);
|
||||
}
|
||||
|
||||
const struct ieee80211_ops mt7925_ops = {
|
||||
.tx = mt792x_tx,
|
||||
.start = mt7925_start,
|
||||
@@ -2180,6 +2272,8 @@ const struct ieee80211_ops mt7925_ops = {
|
||||
.sta_statistics = mt792x_sta_statistics,
|
||||
.sched_scan_start = mt7925_start_sched_scan,
|
||||
.sched_scan_stop = mt7925_stop_sched_scan,
|
||||
CFG80211_TESTMODE_CMD(mt7925_testmode_cmd)
|
||||
CFG80211_TESTMODE_DUMP(mt7925_testmode_dump)
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = mt7925_suspend,
|
||||
.resume = mt7925_resume,
|
||||
@@ -2201,6 +2295,7 @@ const struct ieee80211_ops mt7925_ops = {
|
||||
.link_info_changed = mt7925_link_info_changed,
|
||||
.change_vif_links = mt7925_change_vif_links,
|
||||
.change_sta_links = mt7925_change_sta_links,
|
||||
.rfkill_poll = mt7925_rfkill_poll,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt7925_ops);
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
bool suspend, struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct ieee80211_scan_ies ies = {};
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct {
|
||||
struct {
|
||||
@@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |
|
||||
UNI_WOW_DETECT_TYPE_BCN_LOST);
|
||||
if (wowlan->nd_config) {
|
||||
mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config);
|
||||
mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies);
|
||||
req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;
|
||||
mt7925_mcu_sched_scan_enable(phy, vif, suspend);
|
||||
}
|
||||
@@ -348,14 +349,10 @@ mt7925_mcu_handle_hif_ctrl_basic(struct mt792x_dev *dev, struct tlv *tlv)
|
||||
basic = (struct mt7925_mcu_hif_ctrl_basic_tlv *)tlv;
|
||||
|
||||
if (basic->hifsuspend) {
|
||||
if (basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE &&
|
||||
basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)
|
||||
/* success */
|
||||
dev->hif_idle = true;
|
||||
else
|
||||
/* busy */
|
||||
/* invalid */
|
||||
dev->hif_idle = false;
|
||||
dev->hif_idle = true;
|
||||
if (!(basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE &&
|
||||
basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE))
|
||||
dev_info(dev->mt76.dev, "Hif traffic not idle.\n");
|
||||
} else {
|
||||
dev->hif_resumed = true;
|
||||
}
|
||||
@@ -576,10 +573,10 @@ void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
|
||||
|
||||
static int
|
||||
mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
struct mt76_wcid *wcid,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable, bool tx)
|
||||
{
|
||||
struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;
|
||||
struct sta_rec_ba_uni *ba;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
@@ -607,60 +604,76 @@ mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,
|
||||
|
||||
/** starec & wtbl **/
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct mt76_wcid *wcid;
|
||||
u8 link_id, ret;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
wcid = &mlink->wcid;
|
||||
if (enable && !params->amsdu)
|
||||
msta->deflink.wcid.amsdu = false;
|
||||
|
||||
if (enable && !params->amsdu)
|
||||
mlink->wcid.amsdu = false;
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
|
||||
enable, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable)
|
||||
{
|
||||
struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv;
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
|
||||
struct mt792x_link_sta *mlink;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
unsigned long usable_links = ieee80211_vif_usable_links(vif);
|
||||
struct mt76_wcid *wcid;
|
||||
u8 link_id, ret;
|
||||
struct mt792x_vif *mvif = msta->vif;
|
||||
|
||||
for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
mconf = mt792x_vif_to_link(mvif, link_id);
|
||||
mlink = mt792x_sta_to_link(msta, link_id);
|
||||
wcid = &mlink->wcid;
|
||||
return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params,
|
||||
enable, false);
|
||||
}
|
||||
|
||||
ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params,
|
||||
enable, false);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val)
|
||||
{
|
||||
struct {
|
||||
u8 rsv[4];
|
||||
|
||||
return ret;
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
u8 data[MT7925_EEPROM_BLOCK_SIZE];
|
||||
} __packed req = {
|
||||
.tag = cpu_to_le16(1),
|
||||
.len = cpu_to_le16(sizeof(req) - 4),
|
||||
.addr = cpu_to_le32(round_down(offset,
|
||||
MT7925_EEPROM_BLOCK_SIZE)),
|
||||
};
|
||||
struct evt {
|
||||
u8 rsv[4];
|
||||
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
__le32 ver;
|
||||
__le32 addr;
|
||||
__le32 valid;
|
||||
__le32 size;
|
||||
__le32 magic_num;
|
||||
__le32 type;
|
||||
__le32 rsv1[4];
|
||||
u8 data[32];
|
||||
} __packed *res;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL),
|
||||
&req, sizeof(req), true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
res = (struct evt *)skb->data;
|
||||
*val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE];
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
||||
@@ -671,17 +684,26 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt792x_phy *phy = &dev->phy;
|
||||
const struct firmware *fw;
|
||||
int ret, i, len, offset = 0;
|
||||
#if defined(__linux__)
|
||||
u8 *clc_base = NULL;
|
||||
u8 *clc_base = NULL, hw_encap = 0;
|
||||
#elif defined(__FreeBSD__)
|
||||
const u8 *clc_base = NULL;
|
||||
u8 hw_encap = 0;
|
||||
#endif
|
||||
int ret, i, len, offset = 0;
|
||||
|
||||
dev->phy.clc_chan_conf = 0xff;
|
||||
if (mt7925_disable_clc ||
|
||||
mt76_is_usb(&dev->mt76))
|
||||
return 0;
|
||||
|
||||
if (mt76_is_mmio(&dev->mt76)) {
|
||||
ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap);
|
||||
if (ret)
|
||||
return ret;
|
||||
hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP);
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, fw_name, mdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -730,6 +752,12 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)
|
||||
if (phy->clc[clc->idx])
|
||||
continue;
|
||||
|
||||
/* header content sanity */
|
||||
if ((clc->idx == MT792x_CLC_BE_CTRL &&
|
||||
u8_get_bits(clc->t2.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) ||
|
||||
u8_get_bits(clc->t0.type, MT_EE_HW_TYPE_ENCAP) != hw_encap)
|
||||
continue;
|
||||
|
||||
phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,
|
||||
le32_to_cpu(clc->len),
|
||||
GFP_KERNEL);
|
||||
@@ -765,7 +793,7 @@ int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)
|
||||
int ret;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(WSYS_CONFIG),
|
||||
&req, sizeof(req), false, NULL);
|
||||
&req, sizeof(req), true, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -836,7 +864,6 @@ mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data)
|
||||
mdev->phy.chainmask = mdev->phy.antenna_mask;
|
||||
mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);
|
||||
mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G);
|
||||
dev->has_eht = cap->eht;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -957,6 +984,23 @@ int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_set_deep_sleep);
|
||||
|
||||
int mt7925_mcu_set_thermal_protect(struct mt792x_dev *dev)
|
||||
{
|
||||
char cmd[64];
|
||||
int ret = 0;
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "ThermalProtGband %d %d %d %d %d %d %d %d %d %d",
|
||||
0, 100, 90, 80, 30, 1, 1, 115, 105, 5);
|
||||
ret = mt7925_mcu_chip_config(dev, cmd);
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "ThermalProtAband %d %d %d %d %d %d %d %d %d %d",
|
||||
1, 100, 90, 80, 30, 1, 1, 115, 105, 5);
|
||||
ret |= mt7925_mcu_chip_config(dev, cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_set_thermal_protect);
|
||||
|
||||
int mt7925_run_firmware(struct mt792x_dev *dev)
|
||||
{
|
||||
int err;
|
||||
@@ -1407,7 +1451,7 @@ int mt7925_mcu_set_eeprom(struct mt792x_dev *dev)
|
||||
};
|
||||
|
||||
return mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(EFUSE_CTRL),
|
||||
&req, sizeof(req), false, NULL);
|
||||
&req, sizeof(req), true, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_set_eeprom);
|
||||
|
||||
@@ -1799,13 +1843,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,
|
||||
struct tlv *tlv;
|
||||
u16 eml_cap;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));
|
||||
eht_mld = (struct sta_rec_eht_mld *)tlv;
|
||||
eht_mld->mld_type = 0xff;
|
||||
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
return;
|
||||
|
||||
ext_capa = cfg80211_get_iftype_ext_capa(wiphy,
|
||||
ieee80211_vif_type_p2p(vif));
|
||||
if (!ext_capa)
|
||||
@@ -1858,49 +1902,6 @@ mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
struct mt76_sta_cmd_info *info)
|
||||
{
|
||||
struct mt76_vif_link *mvif = (struct mt76_vif_link *)info->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
|
||||
skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid,
|
||||
MT7925_STA_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
|
||||
CONN_STATE_DISCONNECT;
|
||||
if (info->link_sta)
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
conn_state, info->newly);
|
||||
if (info->link_sta && info->enable) {
|
||||
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
|
||||
mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta);
|
||||
mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_he_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_eht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif,
|
||||
info->link_sta);
|
||||
mt7925_mcu_sta_state_v2_tlv(phy, skb, info->link_sta,
|
||||
info->vif, info->rcpi,
|
||||
info->state);
|
||||
mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);
|
||||
}
|
||||
|
||||
if (info->enable)
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)
|
||||
{
|
||||
@@ -1913,13 +1914,14 @@ mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
|
||||
struct mt76_sta_cmd_info *info)
|
||||
mt7925_mcu_sta_cmd(struct mt76_phy *phy,
|
||||
struct mt76_sta_cmd_info *info)
|
||||
{
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;
|
||||
struct mt76_dev *dev = phy->dev;
|
||||
struct mt792x_bss_conf *mconf;
|
||||
struct sk_buff *skb;
|
||||
int conn_state;
|
||||
|
||||
mconf = mt792x_vif_to_link(mvif, info->wcid->link_id);
|
||||
|
||||
@@ -1928,12 +1930,13 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
if (info->enable)
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
info->enable, info->newly);
|
||||
conn_state = info->enable ? CONN_STATE_PORT_SECURE :
|
||||
CONN_STATE_DISCONNECT;
|
||||
|
||||
if (info->enable && info->link_sta) {
|
||||
mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf,
|
||||
info->link_sta,
|
||||
conn_state, info->newly);
|
||||
mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);
|
||||
mt7925_mcu_sta_ht_tlv(skb, info->link_sta);
|
||||
mt7925_mcu_sta_vht_tlv(skb, info->link_sta);
|
||||
@@ -1952,14 +1955,14 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,
|
||||
mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);
|
||||
mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);
|
||||
}
|
||||
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
|
||||
}
|
||||
|
||||
if (!info->enable) {
|
||||
mt7925_mcu_sta_remove_tlv(skb);
|
||||
mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,
|
||||
sizeof(struct tlv));
|
||||
} else {
|
||||
mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);
|
||||
}
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
|
||||
@@ -1984,25 +1987,15 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,
|
||||
};
|
||||
struct mt792x_sta *msta;
|
||||
struct mt792x_link_sta *mlink;
|
||||
int err;
|
||||
|
||||
if (link_sta) {
|
||||
msta = (struct mt792x_sta *)link_sta->sta->drv_priv;
|
||||
mlink = mt792x_sta_to_link(msta, link_sta->link_id);
|
||||
}
|
||||
info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid;
|
||||
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
|
||||
|
||||
if (link_sta)
|
||||
info.newly = state != MT76_STA_INFO_STATE_ASSOC;
|
||||
else
|
||||
info.newly = state == MT76_STA_INFO_STATE_ASSOC ? false : true;
|
||||
|
||||
if (ieee80211_vif_is_mld(vif))
|
||||
err = mt7925_mcu_mlo_sta_cmd(&dev->mphy, &info);
|
||||
else
|
||||
err = mt7925_mcu_sta_cmd(&dev->mphy, &info);
|
||||
|
||||
return err;
|
||||
return mt7925_mcu_sta_cmd(&dev->mphy, &info);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
||||
@@ -2084,8 +2077,6 @@ int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,
|
||||
},
|
||||
};
|
||||
|
||||
mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true);
|
||||
|
||||
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),
|
||||
true);
|
||||
}
|
||||
@@ -2336,6 +2327,40 @@ __mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int
|
||||
return skb;
|
||||
}
|
||||
|
||||
static
|
||||
void mt7925_mcu_bss_eht_tlv(struct sk_buff *skb, struct mt76_phy *phy,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = ctx ? &ctx->def :
|
||||
&link_conf->chanreq.oper;
|
||||
|
||||
struct bss_eht_tlv *req;
|
||||
struct tlv *tlv;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_EHT, sizeof(*req));
|
||||
req = (struct bss_eht_tlv *)tlv;
|
||||
req->is_eth_dscb_present = chandef->punctured ? 1 : 0;
|
||||
req->eht_dis_sub_chan_bitmap = cpu_to_le16(chandef->punctured);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_eht_pp(struct mt76_phy *phy, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = __mt7925_mcu_alloc_bss_req(phy->dev, mvif,
|
||||
MT7925_BSS_UPDATE_MAX_SIZE);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
mt7925_mcu_bss_eht_tlv(skb, phy, link_conf, ctx);
|
||||
|
||||
return mt76_mcu_skb_send_msg(phy->dev, skb,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx)
|
||||
@@ -2567,6 +2592,7 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
|
||||
struct ieee80211_vif *vif = link_conf->vif;
|
||||
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);
|
||||
struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv;
|
||||
struct mt792x_phy *phy = mvif->phy;
|
||||
struct bss_mld_tlv *mld;
|
||||
struct tlv *tlv;
|
||||
bool is_mld;
|
||||
@@ -2582,8 +2608,13 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,
|
||||
mld->group_mld_id = is_mld ? mvif->bss_conf.mt76.idx : 0xff;
|
||||
mld->own_mld_id = mconf->mt76.idx + 32;
|
||||
mld->remap_idx = 0xff;
|
||||
mld->eml_enable = !!(link_conf->vif->cfg.eml_cap &
|
||||
IEEE80211_EML_CAP_EMLSR_SUPP);
|
||||
|
||||
if (phy->chip_cap & MT792x_CHIP_CAP_MLO_EML_EN) {
|
||||
mld->eml_enable = !!(link_conf->vif->cfg.eml_cap &
|
||||
IEEE80211_EML_CAP_EMLSR_SUPP);
|
||||
} else {
|
||||
mld->eml_enable = 0;
|
||||
}
|
||||
|
||||
memcpy(mld->mac_addr, vif->addr, ETH_ALEN);
|
||||
}
|
||||
@@ -2676,6 +2707,62 @@ int mt7925_mcu_set_timing(struct mt792x_phy *phy,
|
||||
MCU_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
void mt7925_mcu_del_dev(struct mt76_dev *mdev,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct {
|
||||
struct {
|
||||
u8 omac_idx;
|
||||
u8 band_idx;
|
||||
__le16 pad;
|
||||
} __packed hdr;
|
||||
struct req_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 active;
|
||||
u8 link_idx; /* hw link idx */
|
||||
u8 omac_addr[ETH_ALEN];
|
||||
} __packed tlv;
|
||||
} dev_req = {
|
||||
.tlv = {
|
||||
.tag = cpu_to_le16(DEV_INFO_ACTIVE),
|
||||
.len = cpu_to_le16(sizeof(struct req_tlv)),
|
||||
.active = true,
|
||||
},
|
||||
};
|
||||
struct {
|
||||
struct {
|
||||
u8 bss_idx;
|
||||
u8 pad[3];
|
||||
} __packed hdr;
|
||||
struct mt76_connac_bss_basic_tlv basic;
|
||||
} basic_req = {
|
||||
.basic = {
|
||||
.tag = cpu_to_le16(UNI_BSS_INFO_BASIC),
|
||||
.len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)),
|
||||
.active = true,
|
||||
.conn_state = 1,
|
||||
},
|
||||
};
|
||||
|
||||
dev_req.hdr.omac_idx = mvif->omac_idx;
|
||||
dev_req.hdr.band_idx = mvif->band_idx;
|
||||
|
||||
basic_req.hdr.bss_idx = mvif->idx;
|
||||
basic_req.basic.omac_idx = mvif->omac_idx;
|
||||
basic_req.basic.band_idx = mvif->band_idx;
|
||||
basic_req.basic.link_idx = mvif->link_idx;
|
||||
|
||||
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE),
|
||||
&basic_req, sizeof(basic_req), true);
|
||||
|
||||
/* recovery omac address for the legacy interface */
|
||||
memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN);
|
||||
mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE),
|
||||
&dev_req, sizeof(dev_req), true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
@@ -2740,11 +2827,59 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)
|
||||
conf->band = 0; /* unused */
|
||||
|
||||
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SET_DBDC_PARMS),
|
||||
false);
|
||||
true);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_scan_ies *scan_ies)
|
||||
{
|
||||
u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN;
|
||||
struct scan_ie_tlv *ie;
|
||||
enum nl80211_band i;
|
||||
struct tlv *tlv;
|
||||
const u8 *ies;
|
||||
u16 ies_len;
|
||||
|
||||
for (i = 0; i <= NL80211_BAND_6GHZ; i++) {
|
||||
if (i == NL80211_BAND_60GHZ)
|
||||
continue;
|
||||
|
||||
ies = scan_ies->ies[i];
|
||||
ies_len = scan_ies->len[i];
|
||||
|
||||
if (!ies || !ies_len)
|
||||
continue;
|
||||
|
||||
if (ies_len > max_len)
|
||||
return;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE,
|
||||
sizeof(*ie) + ies_len);
|
||||
ie = (struct scan_ie_tlv *)tlv;
|
||||
|
||||
memcpy(ie->ies, ies, ies_len);
|
||||
ie->ies_len = cpu_to_le16(ies_len);
|
||||
|
||||
switch (i) {
|
||||
case NL80211_BAND_2GHZ:
|
||||
ie->band = 1;
|
||||
break;
|
||||
case NL80211_BAND_6GHZ:
|
||||
ie->band = 3;
|
||||
break;
|
||||
default:
|
||||
ie->band = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
max_len -= (sizeof(*ie) + ies_len);
|
||||
}
|
||||
}
|
||||
|
||||
int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_scan_request *scan_req)
|
||||
{
|
||||
@@ -2755,7 +2890,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct mt76_dev *mdev = phy->dev;
|
||||
struct mt76_connac_mcu_scan_channel *chan;
|
||||
struct sk_buff *skb;
|
||||
|
||||
struct scan_hdr_tlv *hdr;
|
||||
struct scan_req_tlv *req;
|
||||
struct scan_ssid_tlv *ssid;
|
||||
@@ -2766,9 +2900,13 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
struct tlv *tlv;
|
||||
int max_len;
|
||||
|
||||
if (test_bit(MT76_HW_SCANNING, &phy->state))
|
||||
return -EBUSY;
|
||||
|
||||
max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) +
|
||||
sizeof(*bssid) + sizeof(*chan_info) +
|
||||
sizeof(*misc) + sizeof(*ie);
|
||||
sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS +
|
||||
sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) +
|
||||
MT76_CONNAC_SCAN_IE_LEN;
|
||||
|
||||
skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);
|
||||
if (!skb)
|
||||
@@ -2791,19 +2929,42 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
for (i = 0; i < sreq->n_ssids; i++) {
|
||||
if (!sreq->ssids[i].ssid_len)
|
||||
continue;
|
||||
if (i >= MT7925_RNR_SCAN_MAX_BSSIDS)
|
||||
break;
|
||||
|
||||
ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
|
||||
memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid,
|
||||
ssid->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);
|
||||
memcpy(ssid->ssids[n_ssids].ssid, sreq->ssids[i].ssid,
|
||||
sreq->ssids[i].ssid_len);
|
||||
n_ssids++;
|
||||
}
|
||||
ssid->ssid_type = n_ssids ? BIT(2) : BIT(0);
|
||||
ssid->ssids_num = n_ssids;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid));
|
||||
bssid = (struct scan_bssid_tlv *)tlv;
|
||||
if (sreq->n_6ghz_params) {
|
||||
u8 j;
|
||||
|
||||
memcpy(bssid->bssid, sreq->bssid, ETH_ALEN);
|
||||
mt76_connac_mcu_build_rnr_scan_param(mdev, sreq);
|
||||
|
||||
for (j = 0; j < mdev->rnr.bssid_num; j++) {
|
||||
if (j >= MT7925_RNR_SCAN_MAX_BSSIDS)
|
||||
break;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID,
|
||||
sizeof(*bssid));
|
||||
bssid = (struct scan_bssid_tlv *)tlv;
|
||||
|
||||
ether_addr_copy(bssid->bssid, mdev->rnr.bssid[j]);
|
||||
bssid->match_ch = mdev->rnr.channel[j];
|
||||
bssid->match_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS;
|
||||
bssid->match_short_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS;
|
||||
}
|
||||
req->scan_func |= SCAN_FUNC_RNR_SCAN;
|
||||
} else {
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid));
|
||||
bssid = (struct scan_bssid_tlv *)tlv;
|
||||
|
||||
ether_addr_copy(bssid->bssid, sreq->bssid);
|
||||
}
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_CHANNEL, sizeof(*chan_info));
|
||||
chan_info = (struct scan_chan_info_tlv *)tlv;
|
||||
@@ -2827,13 +2988,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
}
|
||||
chan_info->channel_type = sreq->n_channels ? 4 : 0;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
|
||||
ie = (struct scan_ie_tlv *)tlv;
|
||||
if (sreq->ie_len > 0) {
|
||||
memcpy(ie->ies, sreq->ie, sreq->ie_len);
|
||||
ie->ies_len = cpu_to_le16(sreq->ie_len);
|
||||
}
|
||||
|
||||
req->scan_func |= SCAN_FUNC_SPLIT_SCAN;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc));
|
||||
@@ -2844,8 +2998,11 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
|
||||
req->scan_func |= SCAN_FUNC_RANDOM_MAC;
|
||||
}
|
||||
|
||||
/* Append scan probe IEs as the last tlv */
|
||||
mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies);
|
||||
|
||||
err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
|
||||
false);
|
||||
true);
|
||||
if (err < 0)
|
||||
clear_bit(MT76_HW_SCANNING, &phy->state);
|
||||
|
||||
@@ -2855,7 +3012,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan);
|
||||
|
||||
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_sched_scan_request *sreq)
|
||||
struct cfg80211_sched_scan_request *sreq,
|
||||
struct ieee80211_scan_ies *ies)
|
||||
{
|
||||
struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;
|
||||
struct ieee80211_channel **scan_list = sreq->channels;
|
||||
@@ -2943,15 +3101,11 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
}
|
||||
chan_info->channel_type = sreq->n_channels ? 4 : 0;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie));
|
||||
ie = (struct scan_ie_tlv *)tlv;
|
||||
if (sreq->ie_len > 0) {
|
||||
memcpy(ie->ies, sreq->ie, sreq->ie_len);
|
||||
ie->ies_len = cpu_to_le16(sreq->ie_len);
|
||||
}
|
||||
/* Append scan probe IEs as the last tlv */
|
||||
mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies);
|
||||
|
||||
return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
|
||||
false);
|
||||
true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_sched_scan_req);
|
||||
|
||||
@@ -2987,7 +3141,7 @@ mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
|
||||
clear_bit(MT76_HW_SCHED_SCANNING, &phy->state);
|
||||
|
||||
return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ),
|
||||
false);
|
||||
true);
|
||||
}
|
||||
|
||||
int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
|
||||
@@ -3026,7 +3180,7 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
|
||||
}
|
||||
|
||||
return mt76_mcu_send_msg(phy->dev, MCU_UNI_CMD(SCAN_REQ),
|
||||
&req, sizeof(req), false);
|
||||
&req, sizeof(req), true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_cancel_hw_scan);
|
||||
|
||||
@@ -3131,7 +3285,7 @@ int mt7925_mcu_set_channel_domain(struct mt76_phy *phy)
|
||||
memcpy(__skb_push(skb, sizeof(req)), &req, sizeof(req));
|
||||
|
||||
return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SET_DOMAIN_INFO),
|
||||
false);
|
||||
true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7925_mcu_set_channel_domain);
|
||||
|
||||
@@ -3163,16 +3317,17 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
|
||||
.idx = idx,
|
||||
.env = env_cap,
|
||||
.acpi_conf = mt792x_acpi_get_flags(&dev->phy),
|
||||
};
|
||||
int ret, valid_cnt = 0;
|
||||
u8 i, *pos;
|
||||
u8 *pos, *last_pos;
|
||||
|
||||
if (!clc)
|
||||
return 0;
|
||||
|
||||
pos = clc->data + sizeof(*seg) * clc->nr_seg;
|
||||
for (i = 0; i < clc->nr_country; i++) {
|
||||
req.ver = clc->ver;
|
||||
pos = clc->data + sizeof(*seg) * clc->t0.nr_seg;
|
||||
last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4));
|
||||
while (pos < last_pos) {
|
||||
struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos;
|
||||
|
||||
pos += sizeof(*rule);
|
||||
@@ -3187,6 +3342,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
memcpy(req.type, rule->type, 2);
|
||||
|
||||
req.size = cpu_to_le16(seg->len);
|
||||
dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;
|
||||
skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,
|
||||
le16_to_cpu(req.size) + sizeof(req),
|
||||
sizeof(req), GFP_KERNEL);
|
||||
@@ -3202,8 +3358,10 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
valid_cnt++;
|
||||
}
|
||||
|
||||
if (!valid_cnt)
|
||||
if (!valid_cnt) {
|
||||
dev->phy.clc_chan_conf = 0xff;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3216,6 +3374,9 @@ int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
|
||||
|
||||
/* submit all clc config */
|
||||
for (i = 0; i < ARRAY_SIZE(phy->clc); i++) {
|
||||
if (i == MT792x_CLC_BE_CTRL)
|
||||
continue;
|
||||
|
||||
ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap,
|
||||
phy->clc[i], i);
|
||||
|
||||
@@ -3274,6 +3435,18 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
|
||||
else
|
||||
uni_txd->option = MCU_CMD_UNI_EXT_ACK;
|
||||
|
||||
if (cmd == MCU_UNI_CMD(HIF_CTRL) ||
|
||||
cmd == MCU_UNI_CMD(CHIP_CONFIG))
|
||||
uni_txd->option &= ~MCU_CMD_ACK;
|
||||
|
||||
if (mcu_cmd == MCU_UNI_CMD_TESTMODE_CTRL ||
|
||||
mcu_cmd == MCU_UNI_CMD_TESTMODE_RX_STAT) {
|
||||
if (cmd & __MCU_CMD_FIELD_QUERY)
|
||||
uni_txd->option = 0x2;
|
||||
else
|
||||
uni_txd->option = 0x6;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -3565,6 +3738,43 @@ int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy)
|
||||
{
|
||||
#define UNI_CMD_RADIO_STATUS_GET 0
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
struct {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 rsv[4];
|
||||
} __packed req = {
|
||||
.tag = UNI_CMD_RADIO_STATUS_GET,
|
||||
.len = cpu_to_le16(sizeof(req)),
|
||||
};
|
||||
struct mt7925_radio_status_event {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 data;
|
||||
u8 rsv[3];
|
||||
} __packed *status;
|
||||
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76,
|
||||
MCU_UNI_CMD(RADIO_STATUS),
|
||||
&req, sizeof(req), true, &skb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
skb_pull(skb, sizeof(struct tlv));
|
||||
status = (struct mt7925_radio_status_event *)skb->data;
|
||||
ret = status->data;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map)
|
||||
{
|
||||
|
||||
@@ -104,13 +104,6 @@ enum {
|
||||
MT7925_TM_WIFISPECTRUM,
|
||||
};
|
||||
|
||||
struct mt7925_rftest_cmd {
|
||||
u8 action;
|
||||
u8 rsv[3];
|
||||
__le32 param0;
|
||||
__le32 param1;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_rftest_evt {
|
||||
__le32 param0;
|
||||
__le32 param1;
|
||||
@@ -196,6 +189,7 @@ enum {
|
||||
UNI_SNIFFER_CONFIG,
|
||||
};
|
||||
|
||||
#define MT7925_RNR_SCAN_MAX_BSSIDS 10
|
||||
struct scan_hdr_tlv {
|
||||
/* fixed field */
|
||||
u8 seq_num;
|
||||
@@ -223,7 +217,7 @@ struct scan_req_tlv {
|
||||
__le16 timeout_value;
|
||||
__le16 probe_delay_time;
|
||||
__le32 func_mask_ext;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct scan_ssid_tlv {
|
||||
__le16 tag;
|
||||
@@ -235,9 +229,10 @@ struct scan_ssid_tlv {
|
||||
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
|
||||
*/
|
||||
u8 ssids_num;
|
||||
u8 pad[2];
|
||||
struct mt76_connac_mcu_scan_ssid ssids[4];
|
||||
};
|
||||
u8 is_short_ssid;
|
||||
u8 pad;
|
||||
struct mt76_connac_mcu_scan_ssid ssids[MT7925_RNR_SCAN_MAX_BSSIDS];
|
||||
} __packed;
|
||||
|
||||
struct scan_bssid_tlv {
|
||||
__le16 tag;
|
||||
@@ -247,8 +242,9 @@ struct scan_bssid_tlv {
|
||||
u8 match_ch;
|
||||
u8 match_ssid_ind;
|
||||
u8 rcpi;
|
||||
u8 pad[3];
|
||||
};
|
||||
u8 match_short_ssid_ind;
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
struct scan_chan_info_tlv {
|
||||
__le16 tag;
|
||||
@@ -264,7 +260,7 @@ struct scan_chan_info_tlv {
|
||||
u8 channels_num; /* valid when channel_type is 4 */
|
||||
u8 pad[2];
|
||||
struct mt76_connac_mcu_scan_channel channels[64];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct scan_ie_tlv {
|
||||
__le16 tag;
|
||||
@@ -273,7 +269,7 @@ struct scan_ie_tlv {
|
||||
__le16 ies_len;
|
||||
u8 band;
|
||||
u8 pad;
|
||||
u8 ies[MT76_CONNAC_SCAN_IE_LEN];
|
||||
u8 ies[];
|
||||
};
|
||||
|
||||
struct scan_misc_tlv {
|
||||
@@ -372,6 +368,19 @@ struct bss_mld_tlv {
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct bss_eht_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 is_eht_op_present;
|
||||
u8 is_eth_dscb_present;
|
||||
u8 eht_ctrl;
|
||||
u8 eht_ccfs0;
|
||||
u8 eht_ccfs1;
|
||||
u8 pad1;
|
||||
__le16 eht_dis_sub_chan_bitmap;
|
||||
u8 pad2[4];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_ba_uni {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -566,8 +575,8 @@ struct mt7925_wow_pattern_tlv {
|
||||
u8 offset;
|
||||
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
|
||||
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
|
||||
u8 rsv[7];
|
||||
} __packed;
|
||||
u8 rsv[4];
|
||||
};
|
||||
|
||||
struct roc_acquire_tlv {
|
||||
__le16 tag;
|
||||
@@ -589,6 +598,47 @@ struct roc_acquire_tlv {
|
||||
u8 rsv[3];
|
||||
} __packed;
|
||||
|
||||
enum ENUM_CMD_TEST_CTRL_ACT {
|
||||
CMD_TEST_CTRL_ACT_SWITCH_MODE = 0,
|
||||
CMD_TEST_CTRL_ACT_SET_AT = 1,
|
||||
CMD_TEST_CTRL_ACT_GET_AT = 2,
|
||||
CMD_TEST_CTRL_ACT_SET_AT_ENG = 3,
|
||||
CMD_TEST_CTRL_ACT_GET_AT_ENG = 4,
|
||||
CMD_TEST_CTRL_ACT_NUM
|
||||
};
|
||||
|
||||
enum ENUM_CMD_TEST_CTRL_ACT_SWITCH_MODE_OP {
|
||||
CMD_TEST_CTRL_ACT_SWITCH_MODE_NORMAL = 0,
|
||||
CMD_TEST_CTRL_ACT_SWITCH_MODE_RF_TEST = 1,
|
||||
CMD_TEST_CTRL_ACT_SWITCH_MODE_ICAP = 2,
|
||||
CMD_TEST_CTRL_ACT_SWITCH_MODE_NUM
|
||||
};
|
||||
|
||||
union testmode_data {
|
||||
__le32 op_mode;
|
||||
__le32 channel_freq;
|
||||
u8 rf_at_info[84];
|
||||
};
|
||||
|
||||
union testmode_evt {
|
||||
__le32 op_mode;
|
||||
__le32 channel_freq;
|
||||
u8 rf_at_info[1024];
|
||||
};
|
||||
|
||||
struct uni_cmd_testmode_ctrl {
|
||||
u16 tag;
|
||||
u16 length;
|
||||
u8 action;
|
||||
u8 reserved[3];
|
||||
union testmode_data data;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_rftest_cmd {
|
||||
u8 padding[4];
|
||||
struct uni_cmd_testmode_ctrl ctrl;
|
||||
} __packed;
|
||||
|
||||
static inline enum connac3_mcu_cipher_type
|
||||
mt7925_mcu_get_cipher(int cipher)
|
||||
{
|
||||
@@ -623,10 +673,13 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_sched_scan_request *sreq);
|
||||
struct cfg80211_sched_scan_request *sreq,
|
||||
struct ieee80211_scan_ies *ies);
|
||||
int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
void mt7925_mcu_del_dev(struct mt76_dev *mdev,
|
||||
struct ieee80211_vif *vif);
|
||||
int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
struct ieee80211_chanctx_conf *ctx,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
@@ -635,11 +688,15 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
|
||||
int mt7925_mcu_set_timing(struct mt792x_phy *phy,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
|
||||
int mt7925_mcu_set_thermal_protect(struct mt792x_dev *dev);
|
||||
int mt7925_mcu_set_channel_domain(struct mt76_phy *phy);
|
||||
int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable);
|
||||
int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
int mt7925_mcu_set_eht_pp(struct mt76_phy *phy, struct mt76_vif_link *mvif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_chanctx_conf *ctx);
|
||||
int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy);
|
||||
int mt7925_mcu_update_arp_filter(struct mt76_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
|
||||
@@ -137,11 +137,18 @@ enum {
|
||||
MT7925_CLC_MAX_NUM,
|
||||
};
|
||||
|
||||
struct mt7925_clc_rule_v2 {
|
||||
u32 flag;
|
||||
u8 alpha2[2];
|
||||
u8 rsv[10];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc_rule {
|
||||
u8 alpha2[2];
|
||||
u8 type[2];
|
||||
u8 seg_idx;
|
||||
u8 rsv[3];
|
||||
u8 flag; /* UNII4~8 ctrl flag */
|
||||
u8 rsv[2];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc_segment {
|
||||
@@ -152,14 +159,26 @@ struct mt7925_clc_segment {
|
||||
u8 rsv2[4];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc {
|
||||
__le32 len;
|
||||
u8 idx;
|
||||
u8 ver;
|
||||
struct mt7925_clc_type0 {
|
||||
u8 nr_country;
|
||||
u8 type;
|
||||
u8 nr_seg;
|
||||
u8 rsv[7];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc_type2 {
|
||||
u8 type;
|
||||
u8 rsv[9];
|
||||
} __packed;
|
||||
|
||||
struct mt7925_clc {
|
||||
__le32 len;
|
||||
u8 idx;
|
||||
u8 ver;
|
||||
union {
|
||||
struct mt7925_clc_type0 t0;
|
||||
struct mt7925_clc_type2 t2;
|
||||
};
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
@@ -167,9 +186,12 @@ enum mt7925_eeprom_field {
|
||||
MT_EE_CHIP_ID = 0x000,
|
||||
MT_EE_VERSION = 0x002,
|
||||
MT_EE_MAC_ADDR = 0x004,
|
||||
MT_EE_HW_TYPE = 0xa71,
|
||||
__MT_EE_MAX = 0x9ff
|
||||
};
|
||||
|
||||
#define MT_EE_HW_TYPE_ENCAP GENMASK(1, 0)
|
||||
|
||||
enum {
|
||||
TXPWR_USER,
|
||||
TXPWR_EEPROM,
|
||||
@@ -235,6 +257,7 @@ int mt7925_mcu_chip_config(struct mt792x_dev *dev, const char *cmd);
|
||||
int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
|
||||
u8 bit_op, u32 bit_map);
|
||||
|
||||
void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2);
|
||||
void mt7925_regd_update(struct mt792x_dev *dev);
|
||||
int mt7925_mac_init(struct mt792x_dev *dev);
|
||||
int mt7925_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
@@ -263,13 +286,12 @@ int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool enable);
|
||||
void mt7925_mlo_pm_work(struct work_struct *work);
|
||||
void mt7925_scan_work(struct work_struct *work);
|
||||
void mt7925_roc_work(struct work_struct *work);
|
||||
int mt7925_mcu_uni_bss_ps(struct mt792x_dev *dev,
|
||||
@@ -343,5 +365,11 @@ int mt7925_mcu_wtbl_update_hdr_trans(struct mt792x_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
int link_id);
|
||||
int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy);
|
||||
|
||||
int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
void *data, int len);
|
||||
int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
|
||||
struct netlink_callback *cb, void *data, int len);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,10 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev)
|
||||
{
|
||||
int i;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
struct ieee80211_hw *hw = mt76_hw(dev);
|
||||
|
||||
if (dev->phy.chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN)
|
||||
wiphy_rfkill_stop_polling(hw->wiphy);
|
||||
|
||||
cancel_work_sync(&dev->init_work);
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
@@ -491,9 +495,6 @@ static int mt7925_pci_suspend(struct device *device)
|
||||
|
||||
/* disable interrupt */
|
||||
mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
|
||||
mt76_wr(dev, MT_WFDMA0_HOST_INT_DIS,
|
||||
dev->irq_map->tx.all_complete_mask |
|
||||
MT_INT_RX_DONE_ALL | MT_INT_MCU_CMD);
|
||||
|
||||
mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define MT_MDP_TO_HIF 0
|
||||
#define MT_MDP_TO_WM 1
|
||||
|
||||
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x228)
|
||||
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204)
|
||||
#define MT_WFDMA0_HOST_INT_DIS MT_WFDMA0(0x22c)
|
||||
#define HOST_RX_DONE_INT_ENA4 BIT(12)
|
||||
#define HOST_RX_DONE_INT_ENA5 BIT(13)
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \
|
||||
MT_INT_TX_DONE_FWDL)
|
||||
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \
|
||||
#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU | \
|
||||
MT_INT_TX_DONE_BAND0 | \
|
||||
GENMASK(18, 4))
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
// SPDX-License-Identifier: ISC
|
||||
|
||||
#include "mt7925.h"
|
||||
#include "mcu.h"
|
||||
|
||||
#define MT7925_EVT_RSP_LEN 512
|
||||
|
||||
enum mt7925_testmode_attr {
|
||||
MT7925_TM_ATTR_UNSPEC,
|
||||
MT7925_TM_ATTR_SET,
|
||||
MT7925_TM_ATTR_QUERY,
|
||||
MT7925_TM_ATTR_RSP,
|
||||
|
||||
/* keep last */
|
||||
NUM_MT7925_TM_ATTRS,
|
||||
MT7925_TM_ATTR_MAX = NUM_MT7925_TM_ATTRS - 1,
|
||||
};
|
||||
|
||||
struct mt7925_tm_cmd {
|
||||
u8 padding[4];
|
||||
struct uni_cmd_testmode_ctrl c;
|
||||
} __packed;
|
||||
|
||||
struct mt7925_tm_evt {
|
||||
u32 param0;
|
||||
u32 param1;
|
||||
} __packed;
|
||||
|
||||
static const struct nla_policy mt7925_tm_policy[NUM_MT7925_TM_ATTRS] = {
|
||||
[MT7925_TM_ATTR_SET] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7925_tm_cmd)),
|
||||
[MT7925_TM_ATTR_QUERY] = NLA_POLICY_EXACT_LEN(sizeof(struct mt7925_tm_cmd)),
|
||||
};
|
||||
|
||||
static int
|
||||
mt7925_tm_set(struct mt792x_dev *dev, struct mt7925_tm_cmd *req)
|
||||
{
|
||||
struct mt7925_rftest_cmd cmd;
|
||||
struct mt7925_rftest_cmd *pcmd = &cmd;
|
||||
bool testmode = false, normal = false;
|
||||
struct mt76_connac_pm *pm = &dev->pm;
|
||||
struct mt76_phy *phy = &dev->mphy;
|
||||
int ret = -ENOTCONN;
|
||||
|
||||
memset(pcmd, 0, sizeof(*pcmd));
|
||||
memcpy(pcmd, req, sizeof(struct mt7925_tm_cmd));
|
||||
|
||||
mutex_lock(&dev->mt76.mutex);
|
||||
|
||||
if (pcmd->ctrl.action == CMD_TEST_CTRL_ACT_SWITCH_MODE) {
|
||||
if (pcmd->ctrl.data.op_mode == CMD_TEST_CTRL_ACT_SWITCH_MODE_NORMAL)
|
||||
normal = true;
|
||||
else
|
||||
testmode = true;
|
||||
}
|
||||
|
||||
if (testmode) {
|
||||
/* Make sure testmode running on full power mode */
|
||||
pm->enable = false;
|
||||
cancel_delayed_work_sync(&pm->ps_work);
|
||||
cancel_work_sync(&pm->wake_work);
|
||||
__mt792x_mcu_drv_pmctrl(dev);
|
||||
|
||||
phy->test.state = MT76_TM_STATE_ON;
|
||||
}
|
||||
|
||||
if (!mt76_testmode_enabled(phy))
|
||||
goto out;
|
||||
|
||||
ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(TESTMODE_CTRL), &cmd,
|
||||
sizeof(cmd), false);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (normal) {
|
||||
/* Switch back to the normal world */
|
||||
phy->test.state = MT76_TM_STATE_OFF;
|
||||
pm->enable = true;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7925_tm_query(struct mt792x_dev *dev, struct mt7925_tm_cmd *req,
|
||||
char *evt_resp)
|
||||
{
|
||||
struct mt7925_rftest_cmd cmd;
|
||||
char *pcmd = (char *)&cmd;
|
||||
struct sk_buff *skb = NULL;
|
||||
int ret = 1;
|
||||
|
||||
memset(pcmd, 0, sizeof(*pcmd));
|
||||
memcpy(pcmd + 4, (char *)&req->c, sizeof(struct uni_cmd_testmode_ctrl));
|
||||
|
||||
if (*((uint16_t *)req->padding) == MCU_UNI_CMD_TESTMODE_CTRL)
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_QUERY(TESTMODE_CTRL),
|
||||
&cmd, sizeof(cmd), true, &skb);
|
||||
else if (*((uint16_t *)req->padding) == MCU_UNI_CMD_TESTMODE_RX_STAT)
|
||||
ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_QUERY(TESTMODE_RX_STAT),
|
||||
&cmd, sizeof(cmd), true, &skb);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
memcpy((char *)evt_resp, (char *)skb->data + 8, MT7925_EVT_RSP_LEN);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
void *data, int len)
|
||||
{
|
||||
struct nlattr *tb[NUM_MT76_TM_ATTRS];
|
||||
struct mt76_phy *mphy = hw->priv;
|
||||
struct mt792x_phy *phy = mphy->priv;
|
||||
int err;
|
||||
|
||||
if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||
|
||||
!(hw->conf.flags & IEEE80211_CONF_MONITOR))
|
||||
return -ENOTCONN;
|
||||
|
||||
err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len,
|
||||
mt76_tm_policy, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tb[MT76_TM_ATTR_DRV_DATA]) {
|
||||
struct nlattr *drv_tb[NUM_MT7925_TM_ATTRS], *data;
|
||||
int ret;
|
||||
|
||||
data = tb[MT76_TM_ATTR_DRV_DATA];
|
||||
ret = nla_parse_nested_deprecated(drv_tb,
|
||||
MT7925_TM_ATTR_MAX,
|
||||
data, mt7925_tm_policy,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = drv_tb[MT7925_TM_ATTR_SET];
|
||||
if (data)
|
||||
return mt7925_tm_set(phy->dev, nla_data(data));
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
|
||||
struct netlink_callback *cb, void *data, int len)
|
||||
{
|
||||
struct nlattr *tb[NUM_MT76_TM_ATTRS];
|
||||
struct mt76_phy *mphy = hw->priv;
|
||||
struct mt792x_phy *phy = mphy->priv;
|
||||
int err;
|
||||
|
||||
if (!test_bit(MT76_STATE_RUNNING, &mphy->state) ||
|
||||
!(hw->conf.flags & IEEE80211_CONF_MONITOR) ||
|
||||
!mt76_testmode_enabled(mphy))
|
||||
return -ENOTCONN;
|
||||
|
||||
if (cb->args[2]++ > 0)
|
||||
return -ENOENT;
|
||||
|
||||
err = nla_parse_deprecated(tb, MT76_TM_ATTR_MAX, data, len,
|
||||
mt76_tm_policy, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tb[MT76_TM_ATTR_DRV_DATA]) {
|
||||
struct nlattr *drv_tb[NUM_MT7925_TM_ATTRS], *data;
|
||||
int ret;
|
||||
|
||||
data = tb[MT76_TM_ATTR_DRV_DATA];
|
||||
ret = nla_parse_nested_deprecated(drv_tb,
|
||||
MT7925_TM_ATTR_MAX,
|
||||
data, mt7925_tm_policy,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = drv_tb[MT7925_TM_ATTR_QUERY];
|
||||
if (data) {
|
||||
char evt_resp[MT7925_EVT_RSP_LEN];
|
||||
|
||||
err = mt7925_tm_query(phy->dev, nla_data(data),
|
||||
evt_resp);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return nla_put(msg, MT7925_TM_ATTR_RSP,
|
||||
sizeof(evt_resp), evt_resp);
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -27,8 +27,9 @@
|
||||
|
||||
#define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
|
||||
#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
|
||||
#define MT792x_CHIP_CAP_MLO_EVT_EN BIT(2)
|
||||
#define MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN BIT(3)
|
||||
#define MT792x_CHIP_CAP_MLO_EN BIT(8)
|
||||
#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)
|
||||
|
||||
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
|
||||
#define MT792x_BASIC_RATES_TBL 11
|
||||
@@ -70,6 +71,7 @@ struct mt792x_fw_features {
|
||||
enum {
|
||||
MT792x_CLC_POWER,
|
||||
MT792x_CLC_POWER_EXT,
|
||||
MT792x_CLC_BE_CTRL,
|
||||
MT792x_CLC_MAX_NUM,
|
||||
};
|
||||
|
||||
@@ -81,6 +83,13 @@ enum mt792x_reg_power_type {
|
||||
MT_AP_VLP,
|
||||
};
|
||||
|
||||
enum mt792x_mlo_pm_state {
|
||||
MT792x_MLO_LINK_DISASSOC,
|
||||
MT792x_MLO_LINK_ASSOC,
|
||||
MT792x_MLO_CHANGED_PS_PENDING,
|
||||
MT792x_MLO_CHANGED_PS,
|
||||
};
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
|
||||
struct mt792x_link_sta {
|
||||
@@ -134,6 +143,7 @@ struct mt792x_vif {
|
||||
struct mt792x_phy *phy;
|
||||
u16 valid_links;
|
||||
u8 deflink_id;
|
||||
enum mt792x_mlo_pm_state mlo_pm_state;
|
||||
|
||||
struct work_struct csa_work;
|
||||
struct timer_list csa_timer;
|
||||
@@ -239,6 +249,7 @@ struct mt792x_dev {
|
||||
const struct mt792x_irq_map *irq_map;
|
||||
|
||||
struct work_struct ipv6_ns_work;
|
||||
struct delayed_work mlo_pm_work;
|
||||
/* IPv6 addresses for WoWLAN */
|
||||
struct sk_buff_head ipv6_ns_list;
|
||||
|
||||
@@ -401,7 +412,8 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo);
|
||||
void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class);
|
||||
void mt792x_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class);
|
||||
void mt792x_dma_cleanup(struct mt792x_dev *dev);
|
||||
int mt792x_dma_enable(struct mt792x_dev *dev);
|
||||
int mt792x_wpdma_reset(struct mt792x_dev *dev, bool force);
|
||||
@@ -497,7 +509,7 @@ int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev);
|
||||
int mt792x_init_acpi_sar(struct mt792x_dev *dev);
|
||||
int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default);
|
||||
u8 mt792x_acpi_get_flags(struct mt792x_phy *phy);
|
||||
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2);
|
||||
u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2);
|
||||
#else
|
||||
static inline int mt792x_init_acpi_sar(struct mt792x_dev *dev)
|
||||
{
|
||||
@@ -515,9 +527,9 @@ static inline u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
|
||||
static inline u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
|
||||
{
|
||||
return 0xf;
|
||||
return MT792X_ACPI_MTCL_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,6 +4,28 @@
|
||||
#include <linux/acpi.h>
|
||||
#include "mt792x.h"
|
||||
|
||||
static const char * const cc_list_all[] = {
|
||||
"00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
|
||||
"CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
|
||||
"MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
|
||||
"TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
|
||||
};
|
||||
|
||||
static const char * const cc_list_eu[] = {
|
||||
"AD", "AT", "BE", "BG", "CY", "CZ", "HR", "DK",
|
||||
"EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE",
|
||||
"IT", "LV", "LI", "LT", "LU", "MC", "MT", "NL",
|
||||
"NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE",
|
||||
"CH",
|
||||
};
|
||||
|
||||
static const char * const cc_list_be[] = {
|
||||
"AR", "BR", "BY", "CL", "IQ", "MX", "OM", "RU",
|
||||
"RW", "VN", "KR", "UA", "", "", "", "",
|
||||
"EU", "AT", "CN", "CA", "TW", "NZ", "PH", "UK",
|
||||
"US",
|
||||
};
|
||||
|
||||
static int
|
||||
mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
|
||||
{
|
||||
@@ -66,13 +88,22 @@ mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
|
||||
}
|
||||
|
||||
/* MTCL : Country List Table for 6G band */
|
||||
/* MTCL : Country List Table for 6G band and 11BE */
|
||||
static int
|
||||
mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
|
||||
{
|
||||
int ret;
|
||||
int len, ret;
|
||||
|
||||
*version = ((ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL)) < 0)
|
||||
? 1 : 2;
|
||||
ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, &len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (len == sizeof(struct mt792x_asar_cl))
|
||||
*version = ((struct mt792x_asar_cl *)*table)->version;
|
||||
else if (len == sizeof(struct mt792x_asar_cl_v3))
|
||||
*version = ((struct mt792x_asar_cl_v3 *)*table)->version;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -351,10 +382,24 @@ u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
|
||||
|
||||
static u8
|
||||
static u32
|
||||
mt792x_acpi_get_mtcl_map_v3(int row, int column, struct mt792x_asar_cl_v3 *cl)
|
||||
{
|
||||
u32 config = 0;
|
||||
u8 mode_be = 0;
|
||||
|
||||
mode_be = (cl->mode_be > 0x02) ? 0 : cl->mode_be;
|
||||
|
||||
if (cl->version > 2 && cl->clbe[row] & BIT(column))
|
||||
config |= (mode_be & 0x3) << 4;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static u32
|
||||
mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
|
||||
{
|
||||
u8 config = 0;
|
||||
u32 config = 0;
|
||||
u8 mode_6g, mode_5g9;
|
||||
|
||||
mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g;
|
||||
@@ -368,30 +413,44 @@ mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
|
||||
return config;
|
||||
}
|
||||
|
||||
u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
|
||||
static u32
|
||||
mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy *phy, char *alpha2)
|
||||
{
|
||||
static const char * const cc_list_all[] = {
|
||||
"00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
|
||||
"CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
|
||||
"MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
|
||||
"TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
|
||||
};
|
||||
static const char * const cc_list_eu[] = {
|
||||
"AT", "BE", "BG", "CY", "CZ", "HR", "DK", "EE",
|
||||
"FI", "FR", "DE", "GR", "HU", "IS", "IE", "IT",
|
||||
"LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL",
|
||||
"PT", "RO", "SK", "SI", "ES", "SE", "CH",
|
||||
};
|
||||
struct mt792x_acpi_sar *sar = phy->acpisar;
|
||||
struct mt792x_asar_cl *cl;
|
||||
struct mt792x_asar_cl_v3 *cl = sar->countrylist_v3;
|
||||
int col, row, i;
|
||||
|
||||
if (!sar)
|
||||
return 0xf;
|
||||
if (sar->ver != 3)
|
||||
goto out;
|
||||
|
||||
cl = sar->countrylist;
|
||||
if (!cl)
|
||||
return 0xc;
|
||||
return MT792X_ACPI_MTCL_INVALID;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cc_list_be); i++) {
|
||||
col = 7 - i % 8;
|
||||
row = i / 8;
|
||||
if (!memcmp(cc_list_be[i], alpha2, 2))
|
||||
return mt792x_acpi_get_mtcl_map_v3(row, col, cl);
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++) {
|
||||
if (!memcmp(cc_list_eu[i], alpha2, 2))
|
||||
return mt792x_acpi_get_mtcl_map_v3(3, 7, cl);
|
||||
}
|
||||
|
||||
out:
|
||||
/* Depends on driver */
|
||||
return 0x20;
|
||||
}
|
||||
|
||||
static u32
|
||||
mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy *phy, char *alpha2)
|
||||
{
|
||||
struct mt792x_acpi_sar *sar = phy->acpisar;
|
||||
struct mt792x_asar_cl *cl = sar->countrylist;
|
||||
int col, row, i;
|
||||
|
||||
if (!cl)
|
||||
return MT792X_ACPI_MTCL_INVALID;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) {
|
||||
col = 7 - i % 8;
|
||||
@@ -406,4 +465,22 @@ u8 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
|
||||
|
||||
return mt792x_acpi_get_mtcl_map(0, 7, cl);
|
||||
}
|
||||
|
||||
u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
|
||||
{
|
||||
struct mt792x_acpi_sar *sar = phy->acpisar;
|
||||
u32 config = 0;
|
||||
|
||||
if (!sar)
|
||||
return MT792X_ACPI_MTCL_INVALID;
|
||||
|
||||
config = mt792x_acpi_parse_mtcl_tbl_v3(phy, alpha2);
|
||||
|
||||
if (config == MT792X_ACPI_MTCL_INVALID)
|
||||
return MT792X_ACPI_MTCL_INVALID;
|
||||
|
||||
config |= mt792x_acpi_parse_mtcl_tbl(phy, alpha2);
|
||||
|
||||
return config;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#define MT792x_ACPI_MTGS "MTGS"
|
||||
#define MT792x_ACPI_MTFG "MTFG"
|
||||
|
||||
#define MT792X_ACPI_MTCL_INVALID 0xffffffff
|
||||
|
||||
struct mt792x_asar_dyn_limit {
|
||||
u8 idx;
|
||||
u8 frp[5];
|
||||
@@ -72,6 +74,17 @@ struct mt792x_asar_geo_v2 {
|
||||
DECLARE_FLEX_ARRAY(struct mt792x_asar_geo_limit_v2, tbl);
|
||||
} __packed;
|
||||
|
||||
struct mt792x_asar_cl_v3 {
|
||||
u8 names[4];
|
||||
u8 version;
|
||||
u8 mode_6g;
|
||||
u8 cl6g[6];
|
||||
u8 mode_5g9;
|
||||
u8 cl5g9[6];
|
||||
u8 mode_be;
|
||||
u8 clbe[6];
|
||||
} __packed;
|
||||
|
||||
struct mt792x_asar_cl {
|
||||
u8 names[4];
|
||||
u8 version;
|
||||
@@ -100,7 +113,10 @@ struct mt792x_acpi_sar {
|
||||
struct mt792x_asar_geo *geo;
|
||||
struct mt792x_asar_geo_v2 *geo_v2;
|
||||
};
|
||||
struct mt792x_asar_cl *countrylist;
|
||||
union {
|
||||
struct mt792x_asar_cl *countrylist;
|
||||
struct mt792x_asar_cl_v3 *countrylist_v3;
|
||||
};
|
||||
struct mt792x_asar_fg *fg;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ static const struct ieee80211_iface_combination if_comb[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits_chanctx[] = {
|
||||
static const struct ieee80211_iface_limit if_limits_chanctx_mcc[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
@@ -39,8 +39,23 @@ static const struct ieee80211_iface_limit if_limits_chanctx[] = {
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO)
|
||||
.types = BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
}
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit if_limits_chanctx_scc[] = {
|
||||
{
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
@@ -50,11 +65,18 @@ static const struct ieee80211_iface_limit if_limits_chanctx[] = {
|
||||
|
||||
static const struct ieee80211_iface_combination if_comb_chanctx[] = {
|
||||
{
|
||||
.limits = if_limits_chanctx,
|
||||
.n_limits = ARRAY_SIZE(if_limits_chanctx),
|
||||
.limits = if_limits_chanctx_mcc,
|
||||
.n_limits = ARRAY_SIZE(if_limits_chanctx_mcc),
|
||||
.max_interfaces = 3,
|
||||
.num_different_channels = 2,
|
||||
.beacon_int_infra_match = false,
|
||||
},
|
||||
{
|
||||
.limits = if_limits_chanctx_scc,
|
||||
.n_limits = ARRAY_SIZE(if_limits_chanctx_scc),
|
||||
.max_interfaces = 3,
|
||||
.num_different_channels = 1,
|
||||
.beacon_int_infra_match = false,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -286,7 +308,7 @@ EXPORT_SYMBOL_GPL(mt792x_tx_worker);
|
||||
|
||||
void mt792x_roc_timer(struct timer_list *timer)
|
||||
{
|
||||
struct mt792x_phy *phy = from_timer(phy, timer, roc_timer);
|
||||
struct mt792x_phy *phy = timer_container_of(phy, timer, roc_timer);
|
||||
|
||||
ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
|
||||
}
|
||||
@@ -294,7 +316,7 @@ EXPORT_SYMBOL_GPL(mt792x_roc_timer);
|
||||
|
||||
void mt792x_csa_timer(struct timer_list *timer)
|
||||
{
|
||||
struct mt792x_vif *mvif = from_timer(mvif, timer, csa_timer);
|
||||
struct mt792x_vif *mvif = timer_container_of(mvif, timer, csa_timer);
|
||||
|
||||
ieee80211_queue_work(mvif->phy->mt76->hw, &mvif->csa_work);
|
||||
}
|
||||
@@ -343,7 +365,7 @@ void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&dev->mt76.mutex);
|
||||
|
||||
if (vif->bss_conf.csa_active) {
|
||||
del_timer_sync(&mvif->csa_timer);
|
||||
timer_delete_sync(&mvif->csa_timer);
|
||||
cancel_work_sync(&mvif->csa_work);
|
||||
}
|
||||
}
|
||||
@@ -582,7 +604,8 @@ void mt792x_sta_statistics(struct ieee80211_hw *hw,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt792x_sta_statistics);
|
||||
|
||||
void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
|
||||
void mt792x_set_coverage_class(struct ieee80211_hw *hw, int radio_idx,
|
||||
s16 coverage_class)
|
||||
{
|
||||
struct mt792x_phy *phy = mt792x_hw_phy(hw);
|
||||
struct mt792x_dev *dev = phy->dev;
|
||||
@@ -668,7 +691,9 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
|
||||
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
|
||||
ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
ieee80211_hw_set(hw, NO_VIRTUAL_MONITOR);
|
||||
if (is_mt7921(&dev->mt76))
|
||||
ieee80211_hw_set(hw, CHANCTX_STA_CSA);
|
||||
|
||||
if (dev->pm.enable)
|
||||
ieee80211_hw_set(hw, CONNECTION_MONITOR);
|
||||
|
||||
@@ -145,10 +145,7 @@ struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
|
||||
struct mt792x_sta *sta;
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (unicast || !wcid)
|
||||
return wcid;
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ const struct mt7996_mem_region*
|
||||
mt7996_coredump_get_mem_layout(struct mt7996_dev *dev, u32 *num)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7990:
|
||||
case 0x7991:
|
||||
case MT7996_DEVICE_ID:
|
||||
case MT7996_DEVICE_ID_2:
|
||||
*num = ARRAY_SIZE(mt7996_mem_regions);
|
||||
return &mt7996_mem_regions[0];
|
||||
default:
|
||||
|
||||
@@ -222,18 +222,27 @@ static const struct file_operations mt7996_sys_recovery_ops = {
|
||||
static int
|
||||
mt7996_radar_trigger(void *data, u64 val)
|
||||
{
|
||||
#define RADAR_MAIN_CHAIN 1
|
||||
#define RADAR_BACKGROUND 2
|
||||
struct mt7996_dev *dev = data;
|
||||
struct mt7996_phy *phy = mt7996_band_phy(dev, NL80211_BAND_5GHZ);
|
||||
int rdd_idx;
|
||||
|
||||
if (val > MT_RX_SEL2)
|
||||
if (!phy || !val || val > RADAR_BACKGROUND)
|
||||
return -EINVAL;
|
||||
|
||||
if (val == MT_RX_SEL2 && !dev->rdd2_phy) {
|
||||
if (val == RADAR_BACKGROUND && !dev->rdd2_phy) {
|
||||
dev_err(dev->mt76.dev, "Background radar is not enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE,
|
||||
val, 0, 0);
|
||||
rdd_idx = mt7996_get_rdd_idx(phy, val == RADAR_BACKGROUND);
|
||||
if (rdd_idx < 0) {
|
||||
dev_err(dev->mt76.dev, "No RDD found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_RADAR_EMULATE, rdd_idx, 0);
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
|
||||
@@ -616,28 +625,51 @@ static void
|
||||
mt7996_sta_hw_queue_read(void *data, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct mt7996_vif *mvif = msta->vif;
|
||||
struct mt7996_dev *dev = mvif->deflink.phy->dev;
|
||||
struct ieee80211_link_sta *link_sta;
|
||||
struct seq_file *s = data;
|
||||
u8 ac;
|
||||
struct ieee80211_vif *vif;
|
||||
unsigned int link_id;
|
||||
|
||||
for (ac = 0; ac < 4; ac++) {
|
||||
u32 qlen, ctrl, val;
|
||||
u32 idx = msta->wcid.idx >> 5;
|
||||
u8 offs = msta->wcid.idx & GENMASK(4, 0);
|
||||
vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
|
||||
|
||||
ctrl = BIT(31) | BIT(11) | (ac << 24);
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
|
||||
rcu_read_lock();
|
||||
|
||||
if (val & BIT(offs))
|
||||
for_each_sta_active_link(vif, sta, link_sta, link_id) {
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt76_vif_link *mlink;
|
||||
u8 ac;
|
||||
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
mt76_wr(dev, MT_FL_Q0_CTRL, ctrl | msta->wcid.idx);
|
||||
qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
|
||||
GENMASK(11, 0));
|
||||
seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
|
||||
sta->addr, msta->wcid.idx,
|
||||
msta->vif->deflink.mt76.wmm_idx, ac, qlen);
|
||||
msta_link = rcu_dereference(msta->link[link_id]);
|
||||
if (!msta_link)
|
||||
continue;
|
||||
|
||||
for (ac = 0; ac < 4; ac++) {
|
||||
u32 idx = msta_link->wcid.idx >> 5, qlen, ctrl, val;
|
||||
u8 offs = msta_link->wcid.idx & GENMASK(4, 0);
|
||||
|
||||
ctrl = BIT(31) | BIT(11) | (ac << 24);
|
||||
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(ac, idx));
|
||||
|
||||
if (val & BIT(offs))
|
||||
continue;
|
||||
|
||||
mt76_wr(dev,
|
||||
MT_FL_Q0_CTRL, ctrl | msta_link->wcid.idx);
|
||||
qlen = mt76_get_field(dev, MT_FL_Q3_CTRL,
|
||||
GENMASK(11, 0));
|
||||
seq_printf(s, "\tSTA %pM wcid %d: AC%d%d queued:%d\n",
|
||||
sta->addr, msta_link->wcid.idx,
|
||||
mlink->wmm_idx, ac, qlen);
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -930,6 +962,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct mt7996_dev *dev = msta->vif->deflink.phy->dev;
|
||||
struct mt7996_sta_link *msta_link = &msta->deflink;
|
||||
struct ra_rate phy = {};
|
||||
char buf[100];
|
||||
int ret;
|
||||
@@ -964,7 +997,7 @@ static ssize_t mt7996_sta_fixed_rate_set(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
phy.wlan_idx = cpu_to_le16(msta->wcid.idx);
|
||||
phy.wlan_idx = cpu_to_le16(msta_link->wcid.idx);
|
||||
phy.gi = cpu_to_le16(gi);
|
||||
phy.ltf = cpu_to_le16(ltf);
|
||||
phy.ldpc = phy.ldpc ? 7 : 0;
|
||||
|
||||
@@ -58,20 +58,32 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
|
||||
|
||||
/* rx queue */
|
||||
RXQ_CONFIG(MT_RXQ_MCU, WFDMA0, MT_INT_RX_DONE_WM, MT7996_RXQ_MCU_WM);
|
||||
/* for mt7990, RX ring 1 is for SDO instead */
|
||||
RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_RX_DONE_WA, MT7996_RXQ_MCU_WA);
|
||||
|
||||
/* mt7996: band0 and band1, mt7992: band0 */
|
||||
RXQ_CONFIG(MT_RXQ_MAIN, WFDMA0, MT_INT_RX_DONE_BAND0, MT7996_RXQ_BAND0);
|
||||
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN, MT7996_RXQ_MCU_WA_MAIN);
|
||||
if (mt7996_has_wa(dev))
|
||||
RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_RX_DONE_WA_MAIN,
|
||||
MT7996_RXQ_MCU_WA_MAIN);
|
||||
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
/* mt7996 band2 */
|
||||
RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
|
||||
RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
|
||||
} else {
|
||||
/* mt7992 band1 */
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1);
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case MT7992_DEVICE_ID:
|
||||
RXQ_CONFIG(MT_RXQ_BAND1_WA, WFDMA0, MT_INT_RX_DONE_WA_EXT, MT7996_RXQ_MCU_WA_EXT);
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1);
|
||||
break;
|
||||
case MT7990_DEVICE_ID:
|
||||
RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1, MT7996_RXQ_BAND1);
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND0, WFDMA0,
|
||||
MT_INT_RX_TXFREE_BAND0_MT7990, MT7990_RXQ_TXFREE0);
|
||||
if (dev->hif2)
|
||||
RXQ_CONFIG(MT_RXQ_TXFREE_BAND1, WFDMA0,
|
||||
MT_INT_RX_TXFREE_BAND1_MT7990, MT7990_RXQ_TXFREE1);
|
||||
break;
|
||||
case MT7996_DEVICE_ID:
|
||||
default:
|
||||
/* mt7996 band2 */
|
||||
RXQ_CONFIG(MT_RXQ_BAND2_WA, WFDMA0, MT_INT_RX_DONE_WA_TRI, MT7996_RXQ_MCU_WA_TRI);
|
||||
RXQ_CONFIG(MT_RXQ_BAND2, WFDMA0, MT_INT_RX_DONE_BAND2, MT7996_RXQ_BAND2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->has_rro) {
|
||||
@@ -107,9 +119,11 @@ static void mt7996_dma_config(struct mt7996_dev *dev)
|
||||
}
|
||||
|
||||
/* mcu tx queue */
|
||||
MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM);
|
||||
MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA, MT7996_TXQ_MCU_WA);
|
||||
MCUQ_CONFIG(MT_MCUQ_FWDL, WFDMA0, MT_INT_TX_DONE_FWDL, MT7996_TXQ_FWDL);
|
||||
MCUQ_CONFIG(MT_MCUQ_WM, WFDMA0, MT_INT_TX_DONE_MCU_WM, MT7996_TXQ_MCU_WM);
|
||||
if (mt7996_has_wa(dev))
|
||||
MCUQ_CONFIG(MT_MCUQ_WA, WFDMA0, MT_INT_TX_DONE_MCU_WA,
|
||||
MT7996_TXQ_MCU_WA);
|
||||
}
|
||||
|
||||
static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth)
|
||||
@@ -124,43 +138,62 @@ static u32 __mt7996_dma_prefetch_base(u16 *base, u8 depth)
|
||||
static void __mt7996_dma_prefetch(struct mt7996_dev *dev, u32 ofs)
|
||||
{
|
||||
u16 base = 0;
|
||||
u8 queue;
|
||||
u8 queue, val;
|
||||
|
||||
#define PREFETCH(_depth) (__mt7996_dma_prefetch_base(&base, (_depth)))
|
||||
/* prefetch SRAM wrapping boundary for tx/rx ring. */
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(0x2));
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(0x2));
|
||||
/* Tx Command Rings */
|
||||
val = is_mt7996(&dev->mt76) ? 2 : 4;
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_FWDL) + ofs, PREFETCH(val));
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WM) + ofs, PREFETCH(val));
|
||||
if (mt7996_has_wa(dev))
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(val));
|
||||
|
||||
/* Tx Data Rings */
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(0) + ofs, PREFETCH(0x8));
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8));
|
||||
mt76_wr(dev, MT_MCUQ_EXT_CTRL(MT_MCUQ_WA) + ofs, PREFETCH(0x2));
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(0x2));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(0x2));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(0x2));
|
||||
if (!is_mt7996(&dev->mt76) || dev->hif2)
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(1) + ofs, PREFETCH(0x8));
|
||||
if (is_mt7996(&dev->mt76))
|
||||
mt76_wr(dev, MT_TXQ_EXT_CTRL(2) + ofs, PREFETCH(0x8));
|
||||
|
||||
queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2_WA : MT_RXQ_BAND1_WA;
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x2));
|
||||
/* Rx Event Rings */
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU) + ofs, PREFETCH(val));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MCU_WA) + ofs, PREFETCH(val));
|
||||
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
|
||||
/* Rx TxFreeDone From WA Rings */
|
||||
if (mt7996_has_wa(dev)) {
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN_WA) + ofs, PREFETCH(val));
|
||||
queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2_WA : MT_RXQ_BAND1_WA;
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(val));
|
||||
}
|
||||
|
||||
/* Rx TxFreeDone From MAC Rings */
|
||||
val = is_mt7996(&dev->mt76) ? 4 : 8;
|
||||
if (is_mt7990(&dev->mt76) || (is_mt7996(&dev->mt76) && dev->has_rro))
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND0) + ofs, PREFETCH(val));
|
||||
if (is_mt7990(&dev->mt76) && dev->hif2)
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND1) + ofs, PREFETCH(val));
|
||||
else if (is_mt7996(&dev->mt76) && dev->has_rro)
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_TXFREE_BAND2) + ofs, PREFETCH(val));
|
||||
|
||||
/* Rx Data Rings */
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MAIN) + ofs, PREFETCH(0x10));
|
||||
queue = is_mt7996(&dev->mt76) ? MT_RXQ_BAND2 : MT_RXQ_BAND1;
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(queue) + ofs, PREFETCH(0x10));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10));
|
||||
|
||||
/* Rx RRO Rings */
|
||||
if (dev->has_rro) {
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND0) + ofs,
|
||||
PREFETCH(0x10));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_RRO_BAND2) + ofs,
|
||||
PREFETCH(0x10));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs,
|
||||
PREFETCH(0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
|
||||
PREFETCH(0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
|
||||
PREFETCH(0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND0) + ofs,
|
||||
PREFETCH(0x4));
|
||||
mt76_wr(dev, MT_RXQ_BAND1_CTRL(MT_RXQ_TXFREE_BAND2) + ofs,
|
||||
PREFETCH(0x4));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_RRO_BAND0) + ofs, PREFETCH(0x10));
|
||||
queue = is_mt7996(&dev->mt76) ? MT_RXQ_RRO_BAND2 : MT_RXQ_RRO_BAND1;
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(queue) + ofs, PREFETCH(0x10));
|
||||
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND0) + ofs, PREFETCH(val));
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND1) + ofs,
|
||||
PREFETCH(val));
|
||||
mt76_wr(dev, MT_RXQ_EXT_CTRL(MT_RXQ_MSDU_PAGE_BAND2) + ofs,
|
||||
PREFETCH(val));
|
||||
}
|
||||
}
|
||||
#undef PREFETCH
|
||||
|
||||
@@ -272,6 +305,9 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
|
||||
mtk_wed_device_start(wed, wed_irq_mask);
|
||||
}
|
||||
|
||||
if (!mt7996_has_wa(dev))
|
||||
irq_mask &= ~(MT_INT_RX(MT_RXQ_MAIN_WA) |
|
||||
MT_INT_RX(MT_RXQ_BAND1_WA));
|
||||
irq_mask = reset ? MT_INT_MCU_CMD : irq_mask;
|
||||
|
||||
mt7996_irq_enable(dev, irq_mask);
|
||||
@@ -477,12 +513,14 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
return ret;
|
||||
|
||||
/* command to WA */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA,
|
||||
MT_MCUQ_ID(MT_MCUQ_WA),
|
||||
MT7996_TX_MCU_RING_SIZE,
|
||||
MT_MCUQ_RING_BASE(MT_MCUQ_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (mt7996_has_wa(dev)) {
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WA,
|
||||
MT_MCUQ_ID(MT_MCUQ_WA),
|
||||
MT7996_TX_MCU_RING_SIZE,
|
||||
MT_MCUQ_RING_BASE(MT_MCUQ_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* firmware download */
|
||||
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL,
|
||||
@@ -496,16 +534,16 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
|
||||
MT_RXQ_ID(MT_RXQ_MCU),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT7996_RX_MCU_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MCU));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* event from WA */
|
||||
/* event from WA, or SDO event for mt7990 */
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
|
||||
MT_RXQ_ID(MT_RXQ_MCU_WA),
|
||||
MT7996_RX_MCU_RING_SIZE_WA,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT7996_RX_MCU_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MCU_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -530,13 +568,41 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
dev->mt76.q_rx[MT_RXQ_MAIN_WA].wed = wed;
|
||||
}
|
||||
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
|
||||
MT_RXQ_ID(MT_RXQ_MAIN_WA),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (mt7996_has_wa(dev)) {
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN_WA],
|
||||
MT_RXQ_ID(MT_RXQ_MAIN_WA),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_MAIN_WA));
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].flags = MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0].wed = wed;
|
||||
}
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND0],
|
||||
MT_RXQ_ID(MT_RXQ_TXFREE_BAND0),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND0));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!mt7996_has_wa(dev) && dev->hif2) {
|
||||
if (mtk_wed_device_active(wed)) {
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1].flags = MT_WED_Q_TXFREE;
|
||||
dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1].wed = wed;
|
||||
}
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_TXFREE_BAND1],
|
||||
MT_RXQ_ID(MT_RXQ_TXFREE_BAND1),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT7996_RX_BUF_SIZE,
|
||||
MT_RXQ_RING_BASE(MT_RXQ_TXFREE_BAND1));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mt7996_band_valid(dev, MT_BAND2)) {
|
||||
/* rx data queue for mt7996 band2 */
|
||||
@@ -576,14 +642,16 @@ int mt7996_dma_init(struct mt7996_dev *dev)
|
||||
return ret;
|
||||
|
||||
/* tx free notify event from WA for mt7992 band1 */
|
||||
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs;
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1_WA),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
rx_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (mt7996_has_wa(dev)) {
|
||||
rx_base = MT_RXQ_RING_BASE(MT_RXQ_BAND1_WA) + hif1_ofs;
|
||||
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_BAND1_WA],
|
||||
MT_RXQ_ID(MT_RXQ_BAND1_WA),
|
||||
MT7996_RX_MCU_RING_SIZE,
|
||||
MT_RX_BUF_SIZE,
|
||||
rx_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (mtk_wed_device_active(wed) && mtk_wed_get_rx_capa(wed) &&
|
||||
|
||||
@@ -13,10 +13,12 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
|
||||
u16 val = get_unaligned_le16(eeprom);
|
||||
|
||||
switch (val) {
|
||||
case 0x7990:
|
||||
case MT7996_DEVICE_ID:
|
||||
return is_mt7996(&dev->mt76) ? 0 : -EINVAL;
|
||||
case 0x7992:
|
||||
case MT7992_DEVICE_ID:
|
||||
return is_mt7992(&dev->mt76) ? 0 : -EINVAL;
|
||||
case MT7990_DEVICE_ID:
|
||||
return is_mt7990(&dev->mt76) ? 0 : -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -25,7 +27,7 @@ static int mt7996_check_eeprom(struct mt7996_dev *dev)
|
||||
static char *mt7996_eeprom_name(struct mt7996_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7992:
|
||||
case MT7992_DEVICE_ID:
|
||||
switch (dev->var.type) {
|
||||
case MT7992_VAR_TYPE_23:
|
||||
if (dev->var.fem == MT7996_FEM_INT)
|
||||
@@ -39,7 +41,11 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
|
||||
return MT7992_EEPROM_DEFAULT_MIX;
|
||||
return MT7992_EEPROM_DEFAULT;
|
||||
}
|
||||
case 0x7990:
|
||||
case MT7990_DEVICE_ID:
|
||||
if (dev->var.fem == MT7996_FEM_INT)
|
||||
return MT7990_EEPROM_DEFAULT_INT;
|
||||
return MT7990_EEPROM_DEFAULT;
|
||||
case MT7996_DEVICE_ID:
|
||||
default:
|
||||
switch (dev->var.type) {
|
||||
case MT7996_VAR_TYPE_233:
|
||||
@@ -304,6 +310,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)
|
||||
phy->has_aux_rx = true;
|
||||
|
||||
mphy->antenna_mask = BIT(nss) - 1;
|
||||
phy->orig_antenna_mask = mphy->antenna_mask;
|
||||
mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];
|
||||
phy->orig_chainmask = mphy->chainmask;
|
||||
dev->chainmask |= mphy->chainmask;
|
||||
@@ -374,3 +381,30 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
|
||||
|
||||
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
|
||||
}
|
||||
|
||||
bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case MT7996_DEVICE_ID:
|
||||
if (dev->var.type == MT7996_VAR_TYPE_233)
|
||||
return false;
|
||||
break;
|
||||
case MT7992_DEVICE_ID:
|
||||
if (dev->var.type == MT7992_VAR_TYPE_23)
|
||||
return false;
|
||||
break;
|
||||
case MT7990_DEVICE_ID: {
|
||||
u8 path, rx_path, nss, *eeprom = dev->mt76.eeprom.data;
|
||||
|
||||
mt7996_eeprom_parse_stream(eeprom, MT_BAND1, &path, &rx_path, &nss);
|
||||
/* Disable background radar capability in 3T3R */
|
||||
if (path == 3 || rx_path == 3)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -221,6 +221,9 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
|
||||
|
||||
name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s.%d",
|
||||
wiphy_name(wiphy), phy->mt76->band_idx);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(cname, sizeof(cname), "cooling_device%d", phy->mt76->band_idx);
|
||||
|
||||
cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
|
||||
@@ -319,8 +322,8 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
|
||||
struct ieee80211_supported_band *sband)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
int i, nss = hweight16(phy->mt76->chainmask);
|
||||
int nss_delta = mt76_tx_power_nss_delta(nss);
|
||||
int i, n_chains = hweight16(phy->mt76->chainmask);
|
||||
int path_delta = mt76_tx_power_path_delta(n_chains);
|
||||
int pwr_delta = mt7996_eeprom_get_power_delta(dev, sband->band);
|
||||
struct mt76_power_limits limits;
|
||||
|
||||
@@ -332,7 +335,7 @@ static void __mt7996_init_txpower(struct mt7996_phy *phy,
|
||||
target_power = mt76_get_rate_power_limits(phy->mt76, chan,
|
||||
&limits,
|
||||
target_power);
|
||||
target_power += nss_delta;
|
||||
target_power += path_delta;
|
||||
target_power = DIV_ROUND_UP(target_power, 2);
|
||||
chan->max_power = min_t(int, chan->max_reg_power,
|
||||
target_power);
|
||||
@@ -437,9 +440,7 @@ static void
|
||||
mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
{
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
#if defined(CONFIG_OF)
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
#endif
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
u16 max_subframes = dev->has_eht ? IEEE80211_MAX_AMPDU_BUF_EHT :
|
||||
IEEE80211_MAX_AMPDU_BUF_HE;
|
||||
@@ -447,6 +448,9 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
hw->queues = 4;
|
||||
hw->max_rx_aggregation_subframes = max_subframes;
|
||||
hw->max_tx_aggregation_subframes = max_subframes;
|
||||
if (is_mt7990(mdev) && dev->has_eht)
|
||||
hw->max_tx_aggregation_subframes = 512;
|
||||
|
||||
hw->netdev_features = NETIF_F_RXCSUM;
|
||||
if (mtk_wed_device_active(wed))
|
||||
hw->netdev_features |= NETIF_F_HW_TC;
|
||||
@@ -479,13 +483,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw, struct mtk_wed_device *wed)
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
|
||||
|
||||
if (mt7996_has_background_radar(dev) &&
|
||||
if (mt7996_eeprom_has_background_radar(dev) &&
|
||||
#if defined(CONFIG_OF)
|
||||
(!mdev->dev->of_node ||
|
||||
!of_property_read_bool(mdev->dev->of_node,
|
||||
"mediatek,disable-radar-background")))
|
||||
#else
|
||||
1)
|
||||
1)
|
||||
#endif
|
||||
wiphy_ext_feature_set(wiphy,
|
||||
NL80211_EXT_FEATURE_RADAR_BACKGROUND);
|
||||
@@ -950,13 +954,13 @@ static int mt7996_variant_type_init(struct mt7996_dev *dev)
|
||||
u8 var_type;
|
||||
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7990:
|
||||
case MT7996_DEVICE_ID:
|
||||
if (val & MT_PAD_GPIO_2ADIE_TBTC)
|
||||
var_type = MT7996_VAR_TYPE_233;
|
||||
else
|
||||
var_type = MT7996_VAR_TYPE_444;
|
||||
break;
|
||||
case 0x7992:
|
||||
case MT7992_DEVICE_ID:
|
||||
if (val & MT_PAD_GPIO_ADIE_SINGLE)
|
||||
var_type = MT7992_VAR_TYPE_23;
|
||||
else if (u32_get_bits(val, MT_PAD_GPIO_ADIE_COMB_7992))
|
||||
@@ -964,6 +968,9 @@ static int mt7996_variant_type_init(struct mt7996_dev *dev)
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
case MT7990_DEVICE_ID:
|
||||
var_type = MT7990_VAR_TYPE_23;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1082,10 +1089,10 @@ void mt7996_set_stream_vht_txbf_caps(struct mt7996_phy *phy)
|
||||
*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
|
||||
|
||||
if (is_mt7996(phy->mt76->dev))
|
||||
*cap |= FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, 3);
|
||||
else
|
||||
if (is_mt7992(phy->mt76->dev))
|
||||
*cap |= FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, 4);
|
||||
else
|
||||
*cap |= FIELD_PREP(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, 3);
|
||||
|
||||
*cap &= ~(IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK |
|
||||
IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||
@@ -1128,18 +1135,17 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
|
||||
elem->phy_cap_info[7] &= ~IEEE80211_HE_PHY_CAP7_MAX_NC_MASK;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO;
|
||||
IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
|
||||
elem->phy_cap_info[2] |= c;
|
||||
|
||||
c = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
|
||||
|
||||
if (is_mt7996(phy->mt76->dev))
|
||||
c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
|
||||
(IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 * non_2g);
|
||||
else
|
||||
if (is_mt7992(phy->mt76->dev))
|
||||
c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_5 |
|
||||
(IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_5 * non_2g);
|
||||
else
|
||||
c |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 |
|
||||
(IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4 * non_2g);
|
||||
|
||||
elem->phy_cap_info[4] |= c;
|
||||
|
||||
@@ -1339,6 +1345,9 @@ mt7996_init_eht_caps(struct mt7996_phy *phy, enum nl80211_band band,
|
||||
u8_encode_bits(IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_11454,
|
||||
IEEE80211_EHT_MAC_CAP0_MAX_MPDU_LEN_MASK);
|
||||
|
||||
eht_cap_elem->mac_cap_info[1] |=
|
||||
IEEE80211_EHT_MAC_CAP1_MAX_AMPDU_LEN_MASK;
|
||||
|
||||
eht_cap_elem->phy_cap_info[0] =
|
||||
IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
|
||||
IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
|
||||
|
||||
@@ -56,26 +56,45 @@ static const struct mt7996_dfs_radar_spec jp_radar_specs = {
|
||||
};
|
||||
|
||||
static struct mt76_wcid *mt7996_rx_get_wcid(struct mt7996_dev *dev,
|
||||
u16 idx, bool unicast)
|
||||
u16 idx, u8 band_idx)
|
||||
{
|
||||
struct mt7996_sta *sta;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt7996_sta *msta;
|
||||
struct mt7996_vif *mvif;
|
||||
struct mt76_wcid *wcid;
|
||||
int i;
|
||||
|
||||
if (idx >= ARRAY_SIZE(dev->mt76.wcid))
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
if (!wcid || !wcid->sta)
|
||||
return NULL;
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
if (unicast || !wcid)
|
||||
if (!mt7996_band_valid(dev, band_idx))
|
||||
return NULL;
|
||||
|
||||
if (wcid->phy_idx == band_idx)
|
||||
return wcid;
|
||||
|
||||
if (!wcid->sta)
|
||||
msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
|
||||
msta = msta_link->sta;
|
||||
if (!msta || !msta->vif)
|
||||
return NULL;
|
||||
|
||||
sta = container_of(wcid, struct mt7996_sta, wcid);
|
||||
if (!sta->vif)
|
||||
return NULL;
|
||||
mvif = msta->vif;
|
||||
for (i = 0; i < ARRAY_SIZE(mvif->mt76.link); i++) {
|
||||
struct mt76_vif_link *mlink;
|
||||
|
||||
return &sta->vif->deflink.sta.wcid;
|
||||
mlink = rcu_dereference(mvif->mt76.link[i]);
|
||||
if (!mlink)
|
||||
continue;
|
||||
|
||||
if (mlink->band_idx != band_idx)
|
||||
continue;
|
||||
|
||||
msta_link = rcu_dereference(msta->link[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
return &msta_link->wcid;
|
||||
}
|
||||
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask)
|
||||
@@ -103,10 +122,13 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
[IEEE80211_AC_VI] = 4,
|
||||
[IEEE80211_AC_VO] = 6
|
||||
};
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt76_vif_link *mlink;
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt7996_sta *msta;
|
||||
u32 tx_time[IEEE80211_NUM_ACS], rx_time[IEEE80211_NUM_ACS];
|
||||
LIST_HEAD(sta_poll_list);
|
||||
struct mt76_wcid *wcid;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
@@ -126,25 +148,28 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
break;
|
||||
}
|
||||
msta = list_first_entry(&sta_poll_list,
|
||||
struct mt7996_sta, wcid.poll_list);
|
||||
list_del_init(&msta->wcid.poll_list);
|
||||
msta_link = list_first_entry(&sta_poll_list,
|
||||
struct mt7996_sta_link,
|
||||
wcid.poll_list);
|
||||
msta = msta_link->sta;
|
||||
wcid = &msta_link->wcid;
|
||||
list_del_init(&wcid->poll_list);
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
idx = msta->wcid.idx;
|
||||
idx = wcid->idx;
|
||||
|
||||
/* refresh peer's airtime reporting */
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 20);
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||
u32 tx_last = msta->airtime_ac[i];
|
||||
u32 rx_last = msta->airtime_ac[i + 4];
|
||||
u32 tx_last = msta_link->airtime_ac[i];
|
||||
u32 rx_last = msta_link->airtime_ac[i + 4];
|
||||
|
||||
msta->airtime_ac[i] = mt76_rr(dev, addr);
|
||||
msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
|
||||
msta_link->airtime_ac[i] = mt76_rr(dev, addr);
|
||||
msta_link->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);
|
||||
|
||||
tx_time[i] = msta->airtime_ac[i] - tx_last;
|
||||
rx_time[i] = msta->airtime_ac[i + 4] - rx_last;
|
||||
tx_time[i] = msta_link->airtime_ac[i] - tx_last;
|
||||
rx_time[i] = msta_link->airtime_ac[i + 4] - rx_last;
|
||||
|
||||
if ((tx_last | rx_last) & BIT(30))
|
||||
clear = true;
|
||||
@@ -155,10 +180,11 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
if (clear) {
|
||||
mt7996_mac_wtbl_update(dev, idx,
|
||||
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
|
||||
memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));
|
||||
memset(msta_link->airtime_ac, 0,
|
||||
sizeof(msta_link->airtime_ac));
|
||||
}
|
||||
|
||||
if (!msta->wcid.sta)
|
||||
if (!wcid->sta)
|
||||
continue;
|
||||
|
||||
sta = container_of((void *)msta, struct ieee80211_sta,
|
||||
@@ -184,28 +210,23 @@ static void mt7996_mac_sta_poll(struct mt7996_dev *dev)
|
||||
rssi[2] = to_rssi(GENMASK(23, 16), val);
|
||||
rssi[3] = to_rssi(GENMASK(31, 14), val);
|
||||
|
||||
msta->ack_signal =
|
||||
mt76_rx_signal(msta->vif->deflink.phy->mt76->antenna_mask, rssi);
|
||||
mlink = rcu_dereference(msta->vif->mt76.link[wcid->link_id]);
|
||||
if (mlink) {
|
||||
struct mt76_phy *mphy = mt76_vif_link_phy(mlink);
|
||||
|
||||
ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
|
||||
if (mphy)
|
||||
msta_link->ack_signal =
|
||||
mt76_rx_signal(mphy->antenna_mask,
|
||||
rssi);
|
||||
}
|
||||
|
||||
ewma_avg_signal_add(&msta_link->avg_ack_signal,
|
||||
-msta_link->ack_signal);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable)
|
||||
{
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
u32 addr;
|
||||
|
||||
addr = mt7996_mac_wtbl_lmac_addr(dev, mvif->deflink.sta.wcid.idx, 5);
|
||||
if (enable)
|
||||
mt76_set(dev, addr, BIT(5));
|
||||
else
|
||||
mt76_clear(dev, addr, BIT(5));
|
||||
}
|
||||
|
||||
/* The HW does not translate the mac header to 802.3 for mesh point */
|
||||
static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
|
||||
{
|
||||
@@ -477,11 +498,15 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
|
||||
|
||||
unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
|
||||
idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
|
||||
status->wcid = mt7996_rx_get_wcid(dev, idx, unicast);
|
||||
status->wcid = mt7996_rx_get_wcid(dev, idx, band_idx);
|
||||
|
||||
if (status->wcid) {
|
||||
msta = container_of(status->wcid, struct mt7996_sta, wcid);
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
|
||||
struct mt7996_sta_link *msta_link;
|
||||
|
||||
msta_link = container_of(status->wcid, struct mt7996_sta_link,
|
||||
wcid);
|
||||
msta = msta_link->sta;
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
|
||||
}
|
||||
|
||||
status->freq = mphy->chandef.chan->center_freq;
|
||||
@@ -622,6 +647,14 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, enum mt76_rxq_id q,
|
||||
status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME;
|
||||
}
|
||||
|
||||
/* IEEE 802.11 fragmentation can only be applied to unicast frames.
|
||||
* Hence, drop fragments with multicast/broadcast RA.
|
||||
* This check fixes vulnerabilities, like CVE-2020-26145.
|
||||
*/
|
||||
if ((ieee80211_has_morefrags(fc) || seq_ctrl & IEEE80211_SCTL_FRAG) &&
|
||||
FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) != MT_RXD3_NORMAL_U2M)
|
||||
return -EINVAL;
|
||||
|
||||
hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;
|
||||
if (hdr_trans && ieee80211_has_morefrags(fc)) {
|
||||
if (mt7996_reverse_frag0_hdr_trans(skb, hdr_gap))
|
||||
@@ -720,9 +753,8 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
|
||||
u32 val;
|
||||
|
||||
if (wcid->sta) {
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_sta *sta = wcid_to_sta(wcid);
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
wmm = sta->wme;
|
||||
}
|
||||
|
||||
@@ -749,7 +781,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
|
||||
|
||||
static void
|
||||
mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct ieee80211_key_conf *key)
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct mt76_wcid *wcid)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
@@ -757,15 +791,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
|
||||
u16 seqno = le16_to_cpu(sc);
|
||||
u8 fc_type, fc_stype;
|
||||
u32 val;
|
||||
|
||||
if (ieee80211_is_action(fc) &&
|
||||
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
|
||||
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)
|
||||
mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ) {
|
||||
if (is_mt7990(&dev->mt76))
|
||||
txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TID_ADDBA, tid));
|
||||
tid = MT_TX_ADDBA;
|
||||
else if (ieee80211_is_mgmt(hdr->frame_control))
|
||||
} else if (ieee80211_is_mgmt(hdr->frame_control)) {
|
||||
tid = MT_TX_NORMAL;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
||||
FIELD_PREP(MT_TXD1_HDR_INFO,
|
||||
@@ -776,8 +814,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
info->flags & IEEE80211_TX_CTL_USE_MINRATE)
|
||||
val |= MT_TXD1_FIXED_RATE;
|
||||
|
||||
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
|
||||
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
|
||||
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb)) {
|
||||
val |= MT_TXD1_BIP;
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
||||
}
|
||||
@@ -807,9 +844,13 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
u16 seqno = le16_to_cpu(sc);
|
||||
if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
|
||||
val = MT_TXD3_SN_VALID |
|
||||
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
||||
txwi[3] |= cpu_to_le32(val);
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
struct ieee80211_bar *bar;
|
||||
|
||||
@@ -822,6 +863,19 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
|
||||
txwi[3] |= cpu_to_le32(val);
|
||||
txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mld(info->control.vif) &&
|
||||
(multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
|
||||
|
||||
if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
|
||||
ieee80211_vif_is_mld(info->control.vif)) {
|
||||
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
|
||||
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
|
||||
}
|
||||
|
||||
if (!wcid->sta && ieee80211_is_mgmt(fc))
|
||||
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
|
||||
}
|
||||
|
||||
void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
@@ -835,7 +889,9 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;
|
||||
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
struct mt76_vif_link *mvif;
|
||||
struct mt76_vif_link *mlink = NULL;
|
||||
struct mt7996_vif *mvif;
|
||||
unsigned int link_id;
|
||||
u16 tx_count = 15;
|
||||
u32 val;
|
||||
bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
|
||||
@@ -843,11 +899,24 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
bool beacon = !!(changed & (BSS_CHANGED_BEACON |
|
||||
BSS_CHANGED_BEACON_ENABLED)) && (!inband_disc);
|
||||
|
||||
mvif = vif ? (struct mt76_vif_link *)vif->drv_priv : NULL;
|
||||
if (wcid != &dev->mt76.global_wcid)
|
||||
link_id = wcid->link_id;
|
||||
else
|
||||
link_id = u32_get_bits(info->control.flags,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
|
||||
if (mvif) {
|
||||
omac_idx = mvif->omac_idx;
|
||||
wmm_idx = mvif->wmm_idx;
|
||||
band_idx = mvif->band_idx;
|
||||
if (wcid->offchannel)
|
||||
mlink = rcu_dereference(mvif->mt76.offchannel_link);
|
||||
if (!mlink)
|
||||
mlink = rcu_dereference(mvif->mt76.link[link_id]);
|
||||
}
|
||||
|
||||
if (mlink) {
|
||||
omac_idx = mlink->omac_idx;
|
||||
wmm_idx = mlink->wmm_idx;
|
||||
band_idx = mlink->band_idx;
|
||||
}
|
||||
|
||||
if (inband_disc) {
|
||||
@@ -894,7 +963,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
val |= MT_TXD5_TX_STATUS_HOST;
|
||||
txwi[5] = cpu_to_le32(val);
|
||||
|
||||
val = MT_TXD6_DIS_MAT | MT_TXD6_DAS;
|
||||
val = MT_TXD6_DAS;
|
||||
if (q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
|
||||
val |= MT_TXD6_DIS_MAT;
|
||||
|
||||
if (is_mt7996(&dev->mt76))
|
||||
val |= FIELD_PREP(MT_TXD6_MSDU_CNT, 1);
|
||||
else if (is_8023 || !ieee80211_is_mgmt(hdr->frame_control))
|
||||
@@ -906,34 +978,56 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
|
||||
if (is_8023)
|
||||
mt7996_mac_write_txwi_8023(dev, txwi, skb, wcid);
|
||||
else
|
||||
mt7996_mac_write_txwi_80211(dev, txwi, skb, key);
|
||||
mt7996_mac_write_txwi_80211(dev, txwi, skb, key, wcid);
|
||||
|
||||
if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) {
|
||||
bool mcast = ieee80211_is_data(hdr->frame_control) &&
|
||||
is_multicast_ether_addr(hdr->addr1);
|
||||
u8 idx = MT7996_BASIC_RATES_TBL;
|
||||
|
||||
if (mvif) {
|
||||
if (mcast && mvif->mcast_rates_idx)
|
||||
idx = mvif->mcast_rates_idx;
|
||||
else if (beacon && mvif->beacon_rates_idx)
|
||||
idx = mvif->beacon_rates_idx;
|
||||
if (mlink) {
|
||||
if (mcast && mlink->mcast_rates_idx)
|
||||
idx = mlink->mcast_rates_idx;
|
||||
else if (beacon && mlink->beacon_rates_idx)
|
||||
idx = mlink->beacon_rates_idx;
|
||||
else
|
||||
idx = mvif->basic_rates_idx;
|
||||
idx = mlink->basic_rates_idx;
|
||||
}
|
||||
|
||||
val = FIELD_PREP(MT_TXD6_TX_RATE, idx) | MT_TXD6_FIXED_BW;
|
||||
if (mcast)
|
||||
val |= MT_TXD6_DIS_MAT;
|
||||
txwi[6] |= cpu_to_le32(val);
|
||||
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7996_tx_use_mgmt(struct mt7996_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (ieee80211_is_mgmt(hdr->frame_control))
|
||||
return true;
|
||||
|
||||
/* for SDO to bypass specific data frame */
|
||||
if (!mt7996_has_wa(dev)) {
|
||||
if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
|
||||
return true;
|
||||
|
||||
if (ieee80211_has_a4(hdr->frame_control) &&
|
||||
!ieee80211_is_data_present(hdr->frame_control))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
|
||||
struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
@@ -958,8 +1052,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
return id;
|
||||
|
||||
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
memset(txwi_ptr, 0, MT_TXD_SIZE);
|
||||
/* Transmit non qos data by 802.11 header and need to fill txd by host*/
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
||||
pid, qid, 0);
|
||||
|
||||
txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
|
||||
for (i = 0; i < nbuf; i++) {
|
||||
@@ -976,19 +1073,27 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
}
|
||||
txp->fw.nbuf = nbuf;
|
||||
|
||||
txp->fw.flags =
|
||||
cpu_to_le16(MT_CT_INFO_FROM_HOST | MT_CT_INFO_APPLY_TXD);
|
||||
txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
|
||||
|
||||
if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
|
||||
|
||||
if (!key)
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
|
||||
|
||||
if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control))
|
||||
if (!is_8023 && mt7996_tx_use_mgmt(dev, tx_info->skb))
|
||||
txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
|
||||
|
||||
if (vif) {
|
||||
struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
|
||||
struct mt76_vif_link *mlink = NULL;
|
||||
|
||||
txp->fw.bss_idx = mvif->deflink.mt76.idx;
|
||||
if (wcid->offchannel)
|
||||
mlink = rcu_dereference(mvif->mt76.offchannel_link);
|
||||
if (!mlink)
|
||||
mlink = rcu_dereference(mvif->mt76.link[wcid->link_id]);
|
||||
|
||||
txp->fw.bss_idx = mlink ? mlink->idx : mvif->deflink.mt76.idx;
|
||||
}
|
||||
|
||||
txp->fw.token = cpu_to_le16(id);
|
||||
@@ -1032,14 +1137,14 @@ u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
mt7996_tx_check_aggr(struct ieee80211_link_sta *link_sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct mt7996_sta *msta;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
||||
u16 fc, tid;
|
||||
|
||||
if (!sta || !(sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he))
|
||||
if (!(link_sta->ht_cap.ht_supported || link_sta->he_cap.has_he))
|
||||
return;
|
||||
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
@@ -1048,7 +1153,8 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
|
||||
if (is_8023) {
|
||||
fc = IEEE80211_FTYPE_DATA |
|
||||
(sta->wme ? IEEE80211_STYPE_QOS_DATA : IEEE80211_STYPE_DATA);
|
||||
(link_sta->sta->wme ? IEEE80211_STYPE_QOS_DATA
|
||||
: IEEE80211_STYPE_DATA);
|
||||
} else {
|
||||
/* No need to get precise TID for Action/Management Frame,
|
||||
* since it will not meet the following Frame Control
|
||||
@@ -1064,17 +1170,16 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
if (unlikely(fc != (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)))
|
||||
return;
|
||||
|
||||
msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
if (!test_and_set_bit(tid, &msta->wcid.ampdu_state))
|
||||
ieee80211_start_tx_ba_session(sta, tid, 0);
|
||||
if (!test_and_set_bit(tid, &wcid->ampdu_state))
|
||||
ieee80211_start_tx_ba_session(link_sta->sta, tid, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
|
||||
struct ieee80211_sta *sta, struct list_head *free_list)
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt76_wcid *wcid, struct list_head *free_list)
|
||||
{
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txwi;
|
||||
u16 wcid_idx;
|
||||
|
||||
@@ -1083,12 +1188,10 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
|
||||
goto out;
|
||||
|
||||
txwi = (__le32 *)mt76_get_txwi_ptr(mdev, t);
|
||||
if (sta) {
|
||||
wcid = (struct mt76_wcid *)sta->drv_priv;
|
||||
if (link_sta) {
|
||||
wcid_idx = wcid->idx;
|
||||
|
||||
if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE)))
|
||||
mt7996_tx_check_aggr(sta, t->skb);
|
||||
mt7996_tx_check_aggr(link_sta, wcid, t->skb);
|
||||
} else {
|
||||
wcid_idx = le32_get_bits(txwi[9], MT_TXD9_WLAN_IDX);
|
||||
}
|
||||
@@ -1107,8 +1210,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
struct mt76_dev *mdev = &dev->mt76;
|
||||
struct mt76_phy *phy2 = mdev->phys[MT_BAND1];
|
||||
struct mt76_phy *phy3 = mdev->phys[MT_BAND2];
|
||||
struct ieee80211_link_sta *link_sta = NULL;
|
||||
struct mt76_txwi_cache *txwi;
|
||||
struct ieee80211_sta *sta = NULL;
|
||||
struct mt76_wcid *wcid = NULL;
|
||||
LIST_HEAD(free_list);
|
||||
struct sk_buff *skb, *tmp;
|
||||
@@ -1119,6 +1222,7 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
#endif
|
||||
bool wake = false;
|
||||
u16 total, count = 0;
|
||||
u8 ver;
|
||||
|
||||
/* clean DMA queues and unmap buffers first */
|
||||
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
|
||||
@@ -1132,7 +1236,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
mt76_queue_tx_cleanup(dev, phy3->q_tx[MT_TXQ_BE], false);
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(le32_get_bits(tx_free[1], MT_TXFREE1_VER) < 5))
|
||||
ver = le32_get_bits(tx_free[1], MT_TXFREE1_VER);
|
||||
if (WARN_ON_ONCE(ver < 5))
|
||||
return;
|
||||
|
||||
total = le32_get_bits(tx_free[0], MT_TXFREE0_MSDU_CNT);
|
||||
@@ -1147,17 +1252,27 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
*/
|
||||
info = le32_to_cpu(*cur_info);
|
||||
if (info & MT_TXFREE_INFO_PAIR) {
|
||||
struct mt7996_sta *msta;
|
||||
struct ieee80211_sta *sta;
|
||||
u16 idx;
|
||||
|
||||
idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info);
|
||||
wcid = rcu_dereference(dev->mt76.wcid[idx]);
|
||||
wcid = mt76_wcid_ptr(dev, idx);
|
||||
sta = wcid_to_sta(wcid);
|
||||
if (!sta)
|
||||
continue;
|
||||
if (!sta) {
|
||||
link_sta = NULL;
|
||||
goto next;
|
||||
}
|
||||
|
||||
msta = container_of(wcid, struct mt7996_sta, wcid);
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
|
||||
link_sta = rcu_dereference(sta->link[wcid->link_id]);
|
||||
if (!link_sta)
|
||||
goto next;
|
||||
|
||||
mt76_wcid_add_poll(&dev->mt76, wcid);
|
||||
next:
|
||||
/* ver 7 has a new DW with pair = 1, skip it */
|
||||
if (ver == 7 && ((void *)(cur_info + 1) < end) &&
|
||||
(le32_to_cpu(*(cur_info + 1)) & MT_TXFREE_INFO_PAIR))
|
||||
cur_info++;
|
||||
continue;
|
||||
} else if (info & MT_TXFREE_INFO_HEADER) {
|
||||
u32 tx_retries = 0, tx_failed = 0;
|
||||
@@ -1185,7 +1300,8 @@ mt7996_mac_tx_free(struct mt7996_dev *dev, void *data, int len)
|
||||
if (!txwi)
|
||||
continue;
|
||||
|
||||
mt7996_txwi_free(dev, txwi, sta, &free_list);
|
||||
mt7996_txwi_free(dev, txwi, link_sta, wcid,
|
||||
&free_list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1241,7 +1357,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta;
|
||||
u8 tid;
|
||||
|
||||
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
||||
sta = wcid_to_sta(wcid);
|
||||
tid = FIELD_GET(MT_TXS0_TID, txs);
|
||||
ieee80211_refresh_tx_agg_session_timer(sta, tid);
|
||||
}
|
||||
@@ -1355,7 +1471,7 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
|
||||
|
||||
static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
|
||||
{
|
||||
struct mt7996_sta *msta = NULL;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct mt76_wcid *wcid;
|
||||
__le32 *txs_data = data;
|
||||
u16 wcidx;
|
||||
@@ -1367,23 +1483,19 @@ static void mt7996_mac_add_txs(struct mt7996_dev *dev, void *data)
|
||||
if (pid < MT_PACKET_ID_NO_SKB)
|
||||
return;
|
||||
|
||||
if (wcidx >= mt7996_wtbl_size(dev))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
wcid = rcu_dereference(dev->mt76.wcid[wcidx]);
|
||||
wcid = mt76_wcid_ptr(dev, wcidx);
|
||||
if (!wcid)
|
||||
goto out;
|
||||
|
||||
msta = container_of(wcid, struct mt7996_sta, wcid);
|
||||
|
||||
mt7996_mac_add_txs_skb(dev, wcid, pid, txs_data);
|
||||
|
||||
if (!wcid->sta)
|
||||
goto out;
|
||||
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta->wcid);
|
||||
msta_link = container_of(wcid, struct mt7996_sta_link, wcid);
|
||||
mt76_wcid_add_poll(&dev->mt76, &msta_link->wcid);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
@@ -1410,7 +1522,7 @@ bool mt7996_rx_check(struct mt76_dev *mdev, void *data, int len)
|
||||
mt7996_mac_tx_free(dev, data, len);
|
||||
return false;
|
||||
case PKT_TYPE_TXS:
|
||||
for (rxd += 4; rxd + 8 <= end; rxd += 8)
|
||||
for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
|
||||
mt7996_mac_add_txs(dev, rxd);
|
||||
return false;
|
||||
case PKT_TYPE_RX_FW_MONITOR:
|
||||
@@ -1455,7 +1567,7 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
|
||||
mt7996_mcu_rx_event(dev, skb);
|
||||
break;
|
||||
case PKT_TYPE_TXS:
|
||||
for (rxd += 4; rxd + 8 <= end; rxd += 8)
|
||||
for (rxd += MT_TXS_HDR_SIZE; rxd + MT_TXS_SIZE <= end; rxd += MT_TXS_SIZE)
|
||||
mt7996_mac_add_txs(dev, rxd);
|
||||
dev_kfree_skb(skb);
|
||||
break;
|
||||
@@ -1603,17 +1715,37 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
|
||||
static void
|
||||
mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct mt7996_phy *phy = priv;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
unsigned int link_id;
|
||||
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_AP:
|
||||
mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_vif_active_link(vif, link_conf, link_id) {
|
||||
struct mt7996_vif_link *link;
|
||||
|
||||
link = mt7996_vif_link(dev, vif, link_id);
|
||||
if (!link || link->phy != phy)
|
||||
continue;
|
||||
|
||||
mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf);
|
||||
}
|
||||
}
|
||||
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy)
|
||||
{
|
||||
ieee80211_iterate_active_interfaces(phy->mt76->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1621,25 +1753,15 @@ mt7996_update_beacons(struct mt7996_dev *dev)
|
||||
{
|
||||
struct mt76_phy *phy2, *phy3;
|
||||
|
||||
ieee80211_iterate_active_interfaces(dev->mt76.hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, dev->mt76.hw);
|
||||
mt7996_mac_update_beacons(&dev->phy);
|
||||
|
||||
phy2 = dev->mt76.phys[MT_BAND1];
|
||||
if (!phy2)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy2->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy2->hw);
|
||||
if (phy2)
|
||||
mt7996_mac_update_beacons(phy2->priv);
|
||||
|
||||
phy3 = dev->mt76.phys[MT_BAND2];
|
||||
if (!phy3)
|
||||
return;
|
||||
|
||||
ieee80211_iterate_active_interfaces(phy3->hw,
|
||||
IEEE80211_IFACE_ITER_RESUME_ALL,
|
||||
mt7996_update_vif_beacon, phy3->hw);
|
||||
if (phy3)
|
||||
mt7996_mac_update_beacons(phy3->priv);
|
||||
}
|
||||
|
||||
void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
@@ -1649,7 +1771,7 @@ void mt7996_tx_token_put(struct mt7996_dev *dev)
|
||||
|
||||
spin_lock_bh(&dev->mt76.token_lock);
|
||||
idr_for_each_entry(&dev->mt76.token, txwi, id) {
|
||||
mt7996_txwi_free(dev, txwi, NULL, NULL);
|
||||
mt7996_txwi_free(dev, txwi, NULL, NULL, NULL);
|
||||
dev->mt76.token_count--;
|
||||
}
|
||||
spin_unlock_bh(&dev->mt76.token_lock);
|
||||
@@ -2254,32 +2376,38 @@ void mt7996_mac_update_stats(struct mt7996_phy *phy)
|
||||
void mt7996_mac_sta_rc_work(struct work_struct *work)
|
||||
{
|
||||
struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work);
|
||||
struct ieee80211_sta *sta;
|
||||
struct mt7996_sta_link *msta_link;
|
||||
struct ieee80211_vif *vif;
|
||||
struct mt7996_sta *msta;
|
||||
u32 changed;
|
||||
struct mt7996_vif *mvif;
|
||||
LIST_HEAD(list);
|
||||
u32 changed;
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
list_splice_init(&dev->sta_rc_list, &list);
|
||||
|
||||
while (!list_empty(&list)) {
|
||||
msta = list_first_entry(&list, struct mt7996_sta, rc_list);
|
||||
list_del_init(&msta->rc_list);
|
||||
changed = msta->changed;
|
||||
msta->changed = 0;
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
msta_link = list_first_entry(&list, struct mt7996_sta_link,
|
||||
rc_list);
|
||||
list_del_init(&msta_link->rc_list);
|
||||
|
||||
sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);
|
||||
vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
|
||||
changed = msta_link->changed;
|
||||
msta_link->changed = 0;
|
||||
mvif = msta_link->sta->vif;
|
||||
vif = container_of((void *)mvif, struct ieee80211_vif,
|
||||
drv_priv);
|
||||
|
||||
spin_unlock_bh(&dev->mt76.sta_poll_lock);
|
||||
|
||||
if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
|
||||
IEEE80211_RC_NSS_CHANGED |
|
||||
IEEE80211_RC_BW_CHANGED))
|
||||
mt7996_mcu_add_rate_ctrl(dev, vif, sta, true);
|
||||
mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif,
|
||||
msta_link->wcid.link_id,
|
||||
true);
|
||||
|
||||
if (changed & IEEE80211_RC_SMPS_CHANGED)
|
||||
mt7996_mcu_set_fixed_field(dev, vif, sta, NULL,
|
||||
mt7996_mcu_set_fixed_field(dev, msta_link->sta, NULL,
|
||||
msta_link->wcid.link_id,
|
||||
RATE_PARAM_MMPS_UPDATE);
|
||||
|
||||
spin_lock_bh(&dev->mt76.sta_poll_lock);
|
||||
@@ -2323,16 +2451,15 @@ void mt7996_mac_work(struct work_struct *work)
|
||||
static void mt7996_dfs_stop_radar_detector(struct mt7996_phy *phy)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
int rdd_idx = mt7996_get_rdd_idx(phy, false);
|
||||
|
||||
if (phy->rdd_state & BIT(0))
|
||||
mt7996_mcu_rdd_cmd(dev, RDD_STOP, 0,
|
||||
MT_RX_SEL0, 0);
|
||||
if (phy->rdd_state & BIT(1))
|
||||
mt7996_mcu_rdd_cmd(dev, RDD_STOP, 1,
|
||||
MT_RX_SEL0, 0);
|
||||
if (rdd_idx < 0)
|
||||
return;
|
||||
|
||||
mt7996_mcu_rdd_cmd(dev, RDD_STOP, rdd_idx, 0);
|
||||
}
|
||||
|
||||
static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain)
|
||||
static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int rdd_idx)
|
||||
{
|
||||
int err, region;
|
||||
|
||||
@@ -2349,44 +2476,30 @@ static int mt7996_dfs_start_rdd(struct mt7996_dev *dev, int chain)
|
||||
break;
|
||||
}
|
||||
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_START, chain,
|
||||
MT_RX_SEL0, region);
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_START, rdd_idx, region);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, chain,
|
||||
MT_RX_SEL0, 1);
|
||||
return mt7996_mcu_rdd_cmd(dev, RDD_DET_MODE, rdd_idx, 1);
|
||||
}
|
||||
|
||||
static int mt7996_dfs_start_radar_detector(struct mt7996_phy *phy)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
u8 band_idx = phy->mt76->band_idx;
|
||||
int err;
|
||||
int err, rdd_idx;
|
||||
|
||||
rdd_idx = mt7996_get_rdd_idx(phy, false);
|
||||
if (rdd_idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* start CAC */
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, band_idx,
|
||||
MT_RX_SEL0, 0);
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_START, rdd_idx, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mt7996_dfs_start_rdd(dev, band_idx);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = mt7996_dfs_start_rdd(dev, rdd_idx);
|
||||
|
||||
phy->rdd_state |= BIT(band_idx);
|
||||
|
||||
if (chandef->width == NL80211_CHAN_WIDTH_160 ||
|
||||
chandef->width == NL80211_CHAN_WIDTH_80P80) {
|
||||
err = mt7996_dfs_start_rdd(dev, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
phy->rdd_state |= BIT(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2427,12 +2540,12 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
|
||||
{
|
||||
struct mt7996_dev *dev = phy->dev;
|
||||
enum mt76_dfs_state dfs_state, prev_state;
|
||||
int err;
|
||||
int err, rdd_idx = mt7996_get_rdd_idx(phy, false);
|
||||
|
||||
prev_state = phy->mt76->dfs_state;
|
||||
dfs_state = mt76_phy_dfs_state(phy->mt76);
|
||||
|
||||
if (prev_state == dfs_state)
|
||||
if (prev_state == dfs_state || rdd_idx < 0)
|
||||
return 0;
|
||||
|
||||
if (prev_state == MT_DFS_STATE_UNKNOWN)
|
||||
@@ -2456,8 +2569,7 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
|
||||
if (dfs_state == MT_DFS_STATE_CAC)
|
||||
return 0;
|
||||
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END,
|
||||
phy->mt76->band_idx, MT_RX_SEL0, 0);
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_CAC_END, rdd_idx, 0);
|
||||
if (err < 0) {
|
||||
phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;
|
||||
return err;
|
||||
@@ -2467,8 +2579,7 @@ int mt7996_dfs_init_radar_detector(struct mt7996_phy *phy)
|
||||
return 0;
|
||||
|
||||
stop:
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START,
|
||||
phy->mt76->band_idx, MT_RX_SEL0, 0);
|
||||
err = mt7996_mcu_rdd_cmd(dev, RDD_NORMAL_START, rdd_idx, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -2553,7 +2664,7 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
|
||||
}
|
||||
|
||||
static bool
|
||||
mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
|
||||
mt7996_mac_twt_param_equal(struct mt7996_sta_link *msta_link,
|
||||
struct ieee80211_twt_params *twt_agrt)
|
||||
{
|
||||
u16 type = le16_to_cpu(twt_agrt->req_type);
|
||||
@@ -2564,10 +2675,10 @@ mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
|
||||
for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
|
||||
struct mt7996_twt_flow *f;
|
||||
|
||||
if (!(msta->twt.flowid_mask & BIT(i)))
|
||||
if (!(msta_link->twt.flowid_mask & BIT(i)))
|
||||
continue;
|
||||
|
||||
f = &msta->twt.flow[i];
|
||||
f = &msta_link->twt.flow[i];
|
||||
if (f->duration == twt_agrt->min_twt_dur &&
|
||||
f->mantissa == twt_agrt->mantissa &&
|
||||
f->exp == exp &&
|
||||
@@ -2587,6 +2698,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
enum ieee80211_twt_setup_cmd setup_cmd = TWT_SETUP_CMD_REJECT;
|
||||
struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
|
||||
struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
|
||||
struct mt7996_sta_link *msta_link = &msta->deflink;
|
||||
u16 req_type = le16_to_cpu(twt_agrt->req_type);
|
||||
enum ieee80211_twt_setup_cmd sta_setup_cmd;
|
||||
struct mt7996_dev *dev = mt7996_hw_dev(hw);
|
||||
@@ -2601,7 +2713,8 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
if (dev->twt.n_agrt == MT7996_MAX_TWT_AGRT)
|
||||
goto unlock;
|
||||
|
||||
if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
|
||||
if (hweight8(msta_link->twt.flowid_mask) ==
|
||||
ARRAY_SIZE(msta_link->twt.flow))
|
||||
goto unlock;
|
||||
|
||||
if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
|
||||
@@ -2610,10 +2723,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mt7996_mac_twt_param_equal(msta, twt_agrt))
|
||||
if (mt7996_mac_twt_param_equal(msta_link, twt_agrt))
|
||||
goto unlock;
|
||||
|
||||
flowid = ffs(~msta->twt.flowid_mask) - 1;
|
||||
flowid = ffs(~msta_link->twt.flowid_mask) - 1;
|
||||
twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
|
||||
twt_agrt->req_type |= le16_encode_bits(flowid,
|
||||
IEEE80211_TWT_REQTYPE_FLOWID);
|
||||
@@ -2622,10 +2735,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
|
||||
sta_setup_cmd = FIELD_GET(IEEE80211_TWT_REQTYPE_SETUP_CMD, req_type);
|
||||
|
||||
flow = &msta->twt.flow[flowid];
|
||||
flow = &msta_link->twt.flow[flowid];
|
||||
memset(flow, 0, sizeof(*flow));
|
||||
INIT_LIST_HEAD(&flow->list);
|
||||
flow->wcid = msta->wcid.idx;
|
||||
flow->wcid = msta_link->wcid.idx;
|
||||
flow->table_id = table_id;
|
||||
flow->id = flowid;
|
||||
flow->duration = twt_agrt->min_twt_dur;
|
||||
@@ -2643,7 +2756,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
|
||||
flow->sched = true;
|
||||
flow->start_tsf = mt7996_mac_twt_sched_list_add(dev, flow);
|
||||
curr_tsf = __mt7996_get_tsf(hw, msta->vif);
|
||||
curr_tsf = __mt7996_get_tsf(hw, &msta->vif->deflink);
|
||||
div_u64_rem(curr_tsf - flow->start_tsf, interval, &rem);
|
||||
flow_tsf = curr_tsf + interval - rem;
|
||||
twt_agrt->twt = cpu_to_le64(flow_tsf);
|
||||
@@ -2652,12 +2765,13 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
}
|
||||
flow->tsf = le64_to_cpu(twt_agrt->twt);
|
||||
|
||||
if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
|
||||
if (mt7996_mcu_twt_agrt_update(dev, &msta->vif->deflink, flow,
|
||||
MCU_TWT_AGRT_ADD))
|
||||
goto unlock;
|
||||
|
||||
setup_cmd = TWT_SETUP_CMD_ACCEPT;
|
||||
dev->twt.table_mask |= BIT(table_id);
|
||||
msta->twt.flowid_mask |= BIT(flowid);
|
||||
msta_link->twt.flowid_mask |= BIT(flowid);
|
||||
dev->twt.n_agrt++;
|
||||
|
||||
unlock:
|
||||
@@ -2670,26 +2784,26 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
|
||||
struct mt7996_sta *msta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
u8 flowid)
|
||||
{
|
||||
struct mt7996_twt_flow *flow;
|
||||
|
||||
lockdep_assert_held(&dev->mt76.mutex);
|
||||
|
||||
if (flowid >= ARRAY_SIZE(msta->twt.flow))
|
||||
if (flowid >= ARRAY_SIZE(msta_link->twt.flow))
|
||||
return;
|
||||
|
||||
if (!(msta->twt.flowid_mask & BIT(flowid)))
|
||||
if (!(msta_link->twt.flowid_mask & BIT(flowid)))
|
||||
return;
|
||||
|
||||
flow = &msta->twt.flow[flowid];
|
||||
if (mt7996_mcu_twt_agrt_update(dev, msta->vif, flow,
|
||||
MCU_TWT_AGRT_DELETE))
|
||||
flow = &msta_link->twt.flow[flowid];
|
||||
if (mt7996_mcu_twt_agrt_update(dev, link, flow, MCU_TWT_AGRT_DELETE))
|
||||
return;
|
||||
|
||||
list_del_init(&flow->list);
|
||||
msta->twt.flowid_mask &= ~BIT(flowid);
|
||||
msta_link->twt.flowid_mask &= ~BIT(flowid);
|
||||
dev->twt.table_mask &= ~BIT(flow->table_id);
|
||||
dev->twt.n_agrt--;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,7 @@ struct mt7996_mcu_rdd_report {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
|
||||
u8 band_idx;
|
||||
u8 rdd_idx;
|
||||
u8 long_detected;
|
||||
u8 constant_prf_detected;
|
||||
u8 staggered_prf_detected;
|
||||
@@ -625,6 +625,35 @@ struct sta_rec_hdr_trans {
|
||||
u8 mesh;
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_mld_setup {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 mld_addr[ETH_ALEN];
|
||||
__le16 primary_id;
|
||||
__le16 seconed_id;
|
||||
__le16 setup_wcid;
|
||||
u8 link_num;
|
||||
u8 info;
|
||||
u8 __rsv[2];
|
||||
u8 link_info[];
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_eht_mld {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 nsep;
|
||||
u8 __rsv1[2];
|
||||
u8 str_cap[__MT_MAX_BAND];
|
||||
__le16 eml_cap;
|
||||
u8 __rsv2[4];
|
||||
} __packed;
|
||||
|
||||
struct mld_setup_link {
|
||||
__le16 wcid;
|
||||
u8 bss_idx;
|
||||
u8 __rsv;
|
||||
} __packed;
|
||||
|
||||
struct hdr_trans_en {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -798,29 +827,20 @@ enum {
|
||||
sizeof(struct sta_rec_eht) + \
|
||||
sizeof(struct sta_rec_hdrt) + \
|
||||
sizeof(struct sta_rec_hdr_trans) + \
|
||||
sizeof(struct sta_rec_mld_setup) + \
|
||||
sizeof(struct mld_setup_link) * 3 + \
|
||||
sizeof(struct sta_rec_eht_mld) + \
|
||||
sizeof(struct tlv))
|
||||
|
||||
#define MT7996_MAX_BEACON_SIZE 1338
|
||||
#define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \
|
||||
sizeof(struct bss_bcn_content_tlv) + \
|
||||
4 + MT_TXD_SIZE + \
|
||||
sizeof(struct bss_bcn_cntdwn_tlv) + \
|
||||
sizeof(struct bss_bcn_mbss_tlv))
|
||||
#define MT7996_MAX_BSS_OFFLOAD_SIZE (MT7996_MAX_BEACON_SIZE + \
|
||||
#define MT7996_MAX_BSS_OFFLOAD_SIZE 2048
|
||||
#define MT7996_MAX_BEACON_SIZE (MT7996_MAX_BSS_OFFLOAD_SIZE - \
|
||||
MT7996_BEACON_UPDATE_SIZE)
|
||||
|
||||
static inline s8
|
||||
mt7996_get_power_bound(struct mt7996_phy *phy, s8 txpower)
|
||||
{
|
||||
struct mt76_phy *mphy = phy->mt76;
|
||||
int n_chains = hweight16(mphy->chainmask);
|
||||
|
||||
txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
|
||||
txpower -= mt76_tx_power_nss_delta(n_chains);
|
||||
|
||||
return txpower;
|
||||
}
|
||||
|
||||
enum {
|
||||
UNI_BAND_CONFIG_RADIO_ENABLE,
|
||||
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
|
||||
@@ -908,7 +928,8 @@ enum {
|
||||
UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
|
||||
UNI_CMD_SER_SET_RECOVER_L3_BF,
|
||||
UNI_CMD_SER_SET_RECOVER_L4_MDP,
|
||||
UNI_CMD_SER_SET_RECOVER_FULL,
|
||||
UNI_CMD_SER_SET_RECOVER_FROM_ETH,
|
||||
UNI_CMD_SER_SET_RECOVER_FULL = 8,
|
||||
UNI_CMD_SER_SET_SYSTEM_ASSERT,
|
||||
/* action */
|
||||
UNI_CMD_SER_ENABLE = 1,
|
||||
@@ -916,6 +937,12 @@ enum {
|
||||
UNI_CMD_SER_TRIGGER
|
||||
};
|
||||
|
||||
enum {
|
||||
UNI_CMD_SDO_SET = 1,
|
||||
UNI_CMD_SDO_QUERY,
|
||||
UNI_CMD_SDO_CP_MODE = 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT7996_SEC_MODE_PLAIN,
|
||||
MT7996_SEC_MODE_AES,
|
||||
|
||||
@@ -57,6 +57,17 @@ static const u32 mt7996_offs[] = {
|
||||
[MIB_BSCR7] = 0x9e8,
|
||||
[MIB_BSCR17] = 0xa10,
|
||||
[MIB_TRDR1] = 0xa28,
|
||||
[HIF_REMAP_L1] = 0x24,
|
||||
[HIF_REMAP_BASE_L1] = 0x130000,
|
||||
[HIF_REMAP_L2] = 0x1b4,
|
||||
[HIF_REMAP_BASE_L2] = 0x1000,
|
||||
[CBTOP1_PHY_END] = 0x77ffffff,
|
||||
[INFRA_MCU_END] = 0x7c3fffff,
|
||||
[WTBLON_WDUCR] = 0x370,
|
||||
[WTBL_UPDATE] = 0x380,
|
||||
[WTBL_ITCR] = 0x3b0,
|
||||
[WTBL_ITCR0] = 0x3b8,
|
||||
[WTBL_ITCR1] = 0x3bc,
|
||||
};
|
||||
|
||||
static const u32 mt7992_offs[] = {
|
||||
@@ -83,6 +94,54 @@ static const u32 mt7992_offs[] = {
|
||||
[MIB_BSCR7] = 0xae4,
|
||||
[MIB_BSCR17] = 0xb0c,
|
||||
[MIB_TRDR1] = 0xb24,
|
||||
[HIF_REMAP_L1] = 0x8,
|
||||
[HIF_REMAP_BASE_L1] = 0x40000,
|
||||
[HIF_REMAP_L2] = 0x1b4,
|
||||
[HIF_REMAP_BASE_L2] = 0x1000,
|
||||
[CBTOP1_PHY_END] = 0x77ffffff,
|
||||
[INFRA_MCU_END] = 0x7c3fffff,
|
||||
[WTBLON_WDUCR] = 0x370,
|
||||
[WTBL_UPDATE] = 0x380,
|
||||
[WTBL_ITCR] = 0x3b0,
|
||||
[WTBL_ITCR0] = 0x3b8,
|
||||
[WTBL_ITCR1] = 0x3bc,
|
||||
};
|
||||
|
||||
static const u32 mt7990_offs[] = {
|
||||
[MIB_RVSR0] = 0x800,
|
||||
[MIB_RVSR1] = 0x804,
|
||||
[MIB_BTSCR5] = 0x868,
|
||||
[MIB_BTSCR6] = 0x878,
|
||||
[MIB_RSCR1] = 0x890,
|
||||
[MIB_RSCR27] = 0xa38,
|
||||
[MIB_RSCR28] = 0xa3c,
|
||||
[MIB_RSCR29] = 0xa40,
|
||||
[MIB_RSCR30] = 0xa44,
|
||||
[MIB_RSCR31] = 0xa48,
|
||||
[MIB_RSCR33] = 0xa50,
|
||||
[MIB_RSCR35] = 0xa58,
|
||||
[MIB_RSCR36] = 0xa5c,
|
||||
[MIB_BSCR0] = 0xbb8,
|
||||
[MIB_BSCR1] = 0xbbc,
|
||||
[MIB_BSCR2] = 0xbc0,
|
||||
[MIB_BSCR3] = 0xbc4,
|
||||
[MIB_BSCR4] = 0xbc8,
|
||||
[MIB_BSCR5] = 0xbcc,
|
||||
[MIB_BSCR6] = 0xbd0,
|
||||
[MIB_BSCR7] = 0xbd4,
|
||||
[MIB_BSCR17] = 0xbfc,
|
||||
[MIB_TRDR1] = 0xc14,
|
||||
[HIF_REMAP_L1] = 0x8,
|
||||
[HIF_REMAP_BASE_L1] = 0x40000,
|
||||
[HIF_REMAP_L2] = 0x1b8,
|
||||
[HIF_REMAP_BASE_L2] = 0x110000,
|
||||
[CBTOP1_PHY_END] = 0x7fffffff,
|
||||
[INFRA_MCU_END] = 0x7cffffff,
|
||||
[WTBLON_WDUCR] = 0x400,
|
||||
[WTBL_UPDATE] = 0x410,
|
||||
[WTBL_ITCR] = 0x440,
|
||||
[WTBL_ITCR0] = 0x448,
|
||||
[WTBL_ITCR1] = 0x44c,
|
||||
};
|
||||
|
||||
static const struct __map mt7996_reg_map[] = {
|
||||
@@ -138,14 +197,83 @@ static const struct __map mt7996_reg_map[] = {
|
||||
{ 0x0, 0x0, 0x0 }, /* imply end of search */
|
||||
};
|
||||
|
||||
static const struct __map mt7990_reg_map[] = {
|
||||
{0x54000000, 0x02000, 0x1000}, /* WFDMA_0 (PCIE0 MCU DMA0) */
|
||||
{0x55000000, 0x03000, 0x1000}, /* WFDMA_1 (PCIE0 MCU DMA1) */
|
||||
{0x56000000, 0x04000, 0x1000}, /* WFDMA_2 (Reserved) */
|
||||
{0x57000000, 0x05000, 0x1000}, /* WFDMA_3 (MCU wrap CR) */
|
||||
{0x58000000, 0x06000, 0x1000}, /* WFDMA_4 (PCIE1 MCU DMA0 (MEM_DMA)) */
|
||||
{0x59000000, 0x07000, 0x1000}, /* WFDMA_5 (PCIE1 MCU DMA1) */
|
||||
{0x820c0000, 0x08000, 0x4000}, /* WF_UMAC_TOP (PLE) */
|
||||
{0x820c8000, 0x0c000, 0x2000}, /* WF_UMAC_TOP (PSE) */
|
||||
{0x820cc000, 0x0e000, 0x2000}, /* WF_UMAC_TOP (PP) */
|
||||
{0x820e0000, 0x20000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_CFG) */
|
||||
{0x820e1000, 0x20400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_TRB) */
|
||||
{0x820e2000, 0x20800, 0x0400}, /* WF_LMAC_TOP BN0 (WF_AGG) */
|
||||
{0x820e3000, 0x20c00, 0x0400}, /* WF_LMAC_TOP BN0 (WF_ARB) */
|
||||
{0x820e4000, 0x21000, 0x0400}, /* WF_LMAC_TOP BN0 (WF_TMAC) */
|
||||
{0x820e5000, 0x21400, 0x0800}, /* WF_LMAC_TOP BN0 (WF_RMAC) */
|
||||
{0x820ce000, 0x21c00, 0x0200}, /* WF_LMAC_TOP (WF_SEC) */
|
||||
{0x820e7000, 0x21e00, 0x0200}, /* WF_LMAC_TOP BN0 (WF_DMA) */
|
||||
{0x820cf000, 0x22000, 0x1000}, /* WF_LMAC_TOP (WF_PF) */
|
||||
{0x820e9000, 0x23400, 0x0200}, /* WF_LMAC_TOP BN0 (WF_WTBLOFF) */
|
||||
{0x820ea000, 0x24000, 0x0200}, /* WF_LMAC_TOP BN0 (WF_ETBF) */
|
||||
{0x820eb000, 0x24200, 0x0400}, /* WF_LMAC_TOP BN0 (WF_LPON) */
|
||||
{0x820ec000, 0x24600, 0x0200}, /* WF_LMAC_TOP BN0 (WF_INT) */
|
||||
{0x820ed000, 0x24800, 0x0800}, /* WF_LMAC_TOP BN0 (WF_MIB) */
|
||||
{0x820ca000, 0x26000, 0x2000}, /* WF_LMAC_TOP BN0 (WF_MUCOP) */
|
||||
{0x820d0000, 0x30000, 0x10000}, /* WF_LMAC_TOP (WF_WTBLON) */
|
||||
{0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */
|
||||
{0x820f0000, 0xa0000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_CFG) */
|
||||
{0x820f1000, 0xa0600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_TRB) */
|
||||
{0x820f2000, 0xa0800, 0x0400}, /* WF_LMAC_TOP BN1 (WF_AGG) */
|
||||
{0x820f3000, 0xa0c00, 0x0400}, /* WF_LMAC_TOP BN1 (WF_ARB) */
|
||||
{0x820f4000, 0xa1000, 0x0400}, /* WF_LMAC_TOP BN1 (WF_TMAC) */
|
||||
{0x820f5000, 0xa1400, 0x0800}, /* WF_LMAC_TOP BN1 (WF_RMAC) */
|
||||
{0x820f7000, 0xa1e00, 0x0200}, /* WF_LMAC_TOP BN1 (WF_DMA) */
|
||||
{0x820f9000, 0xa3400, 0x0200}, /* WF_LMAC_TOP BN1 (WF_WTBLOFF) */
|
||||
{0x820fa000, 0xa4000, 0x0200}, /* WF_LMAC_TOP BN1 (WF_ETBF) */
|
||||
{0x820fb000, 0xa4200, 0x0400}, /* WF_LMAC_TOP BN1 (WF_LPON) */
|
||||
{0x820fc000, 0xa4600, 0x0200}, /* WF_LMAC_TOP BN1 (WF_INT) */
|
||||
{0x820fd000, 0xa4800, 0x0800}, /* WF_LMAC_TOP BN1 (WF_MIB) */
|
||||
{0x820cc000, 0xa5000, 0x2000}, /* WF_LMAC_TOP BN1 (WF_MUCOP) */
|
||||
{0x820c4000, 0xa8000, 0x4000}, /* WF_LMAC_TOP (WF_UWTBL) */
|
||||
{0x81030000, 0xae000, 0x100}, /* WFSYS_AON part 1 */
|
||||
{0x81031000, 0xae100, 0x100}, /* WFSYS_AON part 2 */
|
||||
{0x81032000, 0xae200, 0x100}, /* WFSYS_AON part 3 */
|
||||
{0x81033000, 0xae300, 0x100}, /* WFSYS_AON part 4 */
|
||||
{0x81034000, 0xae400, 0x100}, /* WFSYS_AON part 5 */
|
||||
{0x80020000, 0xb0000, 0x10000}, /* WF_TOP_MISC_OFF */
|
||||
{0x81020000, 0xc0000, 0x10000}, /* WF_TOP_MISC_ON */
|
||||
{0x81040000, 0x120000, 0x1000}, /* WF_MCU_CFG_ON */
|
||||
{0x81050000, 0x121000, 0x1000}, /* WF_MCU_EINT */
|
||||
{0x81060000, 0x122000, 0x1000}, /* WF_MCU_GPT */
|
||||
{0x81070000, 0x123000, 0x1000}, /* WF_MCU_WDT */
|
||||
{0x80010000, 0x124000, 0x1000}, /* WF_AXIDMA */
|
||||
{0x7c020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma for from CODA flow use */
|
||||
{0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top for from CODA flow use */
|
||||
{0x20020000, 0xd0000, 0x10000}, /* CONN_INFRA, wfdma */
|
||||
{0x20060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */
|
||||
{0x7c000000, 0xf0000, 0x10000}, /* CONN_INFRA */
|
||||
{0x70020000, 0x1f0000, 0x9000}, /* PCIE remapping (AP2CONN) */
|
||||
{0x0, 0x0, 0x0}, /* imply end of search */
|
||||
};
|
||||
|
||||
static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
|
||||
u32 l1_mask, val;
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
|
||||
MT_HIF_REMAP_L1_MASK,
|
||||
FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
|
||||
if (is_mt7996(&dev->mt76)) {
|
||||
l1_mask = MT_HIF_REMAP_L1_MASK_7996;
|
||||
val = FIELD_PREP(MT_HIF_REMAP_L1_MASK_7996, base);
|
||||
} else {
|
||||
l1_mask = MT_HIF_REMAP_L1_MASK;
|
||||
val = FIELD_PREP(MT_HIF_REMAP_L1_MASK, base);
|
||||
}
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1, l1_mask, val);
|
||||
/* use read to push write */
|
||||
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
|
||||
|
||||
@@ -154,18 +282,41 @@ static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr)
|
||||
|
||||
static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
|
||||
u32 offset, base, l2_mask, val;
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2,
|
||||
MT_HIF_REMAP_L2_MASK,
|
||||
FIELD_PREP(MT_HIF_REMAP_L2_MASK, base));
|
||||
if (is_mt7990(&dev->mt76)) {
|
||||
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET_7990, addr);
|
||||
base = FIELD_GET(MT_HIF_REMAP_L2_BASE_7990, addr);
|
||||
l2_mask = MT_HIF_REMAP_L2_MASK_7990;
|
||||
val = FIELD_PREP(MT_HIF_REMAP_L2_MASK_7990, base);
|
||||
} else {
|
||||
offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
|
||||
base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
|
||||
l2_mask = MT_HIF_REMAP_L2_MASK;
|
||||
val = FIELD_PREP(MT_HIF_REMAP_L2_MASK, base);
|
||||
}
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2, l2_mask, val);
|
||||
/* use read to push write */
|
||||
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
|
||||
|
||||
return MT_HIF_REMAP_BASE_L2 + offset;
|
||||
}
|
||||
|
||||
static u32 mt7996_reg_map_cbtop(struct mt7996_dev *dev, u32 addr)
|
||||
{
|
||||
u32 offset = FIELD_GET(MT_HIF_REMAP_CBTOP_OFFSET, addr);
|
||||
u32 base = FIELD_GET(MT_HIF_REMAP_CBTOP_BASE, addr);
|
||||
|
||||
dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_CBTOP,
|
||||
MT_HIF_REMAP_CBTOP_MASK,
|
||||
FIELD_PREP(MT_HIF_REMAP_CBTOP_MASK, base));
|
||||
/* use read to push write */
|
||||
dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_CBTOP);
|
||||
|
||||
return MT_HIF_REMAP_BASE_CBTOP + offset;
|
||||
}
|
||||
|
||||
static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
|
||||
{
|
||||
int i;
|
||||
@@ -196,17 +347,20 @@ static u32 __mt7996_reg_remap_addr(struct mt7996_dev *dev, u32 addr)
|
||||
(addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
|
||||
return mt7996_reg_map_l1(dev, addr);
|
||||
|
||||
if (dev_is_pci(dev->mt76.dev) &&
|
||||
((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) ||
|
||||
addr >= MT_CBTOP2_PHY_START))
|
||||
return mt7996_reg_map_l1(dev, addr);
|
||||
|
||||
/* CONN_INFRA: covert to phyiscal addr and use layer 1 remap */
|
||||
if (addr >= MT_INFRA_MCU_START && addr <= MT_INFRA_MCU_END) {
|
||||
addr = addr - MT_INFRA_MCU_START + MT_INFRA_BASE;
|
||||
return mt7996_reg_map_l1(dev, addr);
|
||||
}
|
||||
|
||||
if (dev_is_pci(dev->mt76.dev) &&
|
||||
((addr >= MT_CBTOP1_PHY_START && addr <= MT_CBTOP1_PHY_END) ||
|
||||
addr >= MT_CBTOP2_PHY_START)) {
|
||||
if (is_mt7990(&dev->mt76))
|
||||
return mt7996_reg_map_cbtop(dev, addr);
|
||||
return mt7996_reg_map_l1(dev, addr);
|
||||
}
|
||||
|
||||
return mt7996_reg_map_l2(dev, addr);
|
||||
}
|
||||
|
||||
@@ -292,7 +446,7 @@ static int mt7996_mmio_wed_reset(struct mtk_wed_device *wed)
|
||||
if (test_and_set_bit(MT76_STATE_WED_RESET, &mphy->state))
|
||||
return -EBUSY;
|
||||
|
||||
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_L1,
|
||||
ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, UNI_CMD_SER_SET_RECOVER_FROM_ETH,
|
||||
mphy->band_idx);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -334,6 +488,9 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
wed->wlan.base = devm_ioremap(dev->mt76.dev,
|
||||
pci_resource_start(pci_dev, 0),
|
||||
pci_resource_len(pci_dev, 0));
|
||||
if (!wed->wlan.base)
|
||||
return -ENOMEM;
|
||||
|
||||
wed->wlan.phy_base = pci_resource_start(pci_dev, 0);
|
||||
|
||||
if (hif2) {
|
||||
@@ -361,7 +518,7 @@ int mt7996_mmio_wed_init(struct mt7996_dev *dev, void *pdev_ptr,
|
||||
MT_RXQ_RING_BASE(MT7996_RXQ_BAND0) +
|
||||
MT7996_RXQ_BAND0 * MT_RING_SIZE;
|
||||
|
||||
wed->wlan.id = 0x7991;
|
||||
wed->wlan.id = MT7996_DEVICE_ID_2;
|
||||
wed->wlan.tx_tbit[0] = ffs(MT_INT_TX_DONE_BAND2) - 1;
|
||||
} else {
|
||||
wed->wlan.hw_rro = dev->has_rro; /* default on */
|
||||
@@ -454,18 +611,24 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
|
||||
spin_lock_init(&dev->reg_lock);
|
||||
|
||||
switch (device_id) {
|
||||
case 0x7990:
|
||||
case MT7996_DEVICE_ID:
|
||||
dev->reg.base = mt7996_reg_base;
|
||||
dev->reg.offs_rev = mt7996_offs;
|
||||
dev->reg.map = mt7996_reg_map;
|
||||
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
|
||||
break;
|
||||
case 0x7992:
|
||||
case MT7992_DEVICE_ID:
|
||||
dev->reg.base = mt7996_reg_base;
|
||||
dev->reg.offs_rev = mt7992_offs;
|
||||
dev->reg.map = mt7996_reg_map;
|
||||
dev->reg.map_size = ARRAY_SIZE(mt7996_reg_map);
|
||||
break;
|
||||
case MT7990_DEVICE_ID:
|
||||
dev->reg.base = mt7996_reg_base;
|
||||
dev->reg.offs_rev = mt7990_offs;
|
||||
dev->reg.map = mt7990_reg_map;
|
||||
dev->reg.map_size = ARRAY_SIZE(mt7990_reg_map);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -629,9 +792,6 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
.rx_skb = mt7996_queue_rx_skb,
|
||||
.rx_check = mt7996_rx_check,
|
||||
.rx_poll_complete = mt7996_rx_poll_complete,
|
||||
.sta_add = mt7996_mac_sta_add,
|
||||
.sta_event = mt7996_mac_sta_event,
|
||||
.sta_remove = mt7996_mac_sta_remove,
|
||||
.update_survey = mt7996_update_channel,
|
||||
.set_channel = mt7996_set_channel,
|
||||
.vif_link_add = mt7996_vif_link_add,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define MT7996_MAX_RADIOS 3
|
||||
#define MT7996_MAX_INTERFACES 19 /* per-band */
|
||||
#define MT7996_MAX_WMM_SETS 4
|
||||
#define MT7996_WTBL_BMC_SIZE (is_mt7992(&dev->mt76) ? 32 : 64)
|
||||
#define MT7996_WTBL_BMC_SIZE (is_mt7996(&dev->mt76) ? 64 : 32)
|
||||
#define MT7996_WTBL_RESERVED (mt7996_wtbl_size(dev) - 1)
|
||||
#define MT7996_WTBL_STA (MT7996_WTBL_RESERVED - \
|
||||
mt7996_max_interface_num(dev))
|
||||
@@ -32,6 +32,16 @@
|
||||
#define MT7996_RX_RING_SIZE 1536
|
||||
#define MT7996_RX_MCU_RING_SIZE 512
|
||||
#define MT7996_RX_MCU_RING_SIZE_WA 1024
|
||||
/* scatter-gather of mcu event is not supported in connac3 */
|
||||
#define MT7996_RX_MCU_BUF_SIZE (2048 + \
|
||||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
|
||||
|
||||
#define MT7996_DEVICE_ID 0x7990
|
||||
#define MT7996_DEVICE_ID_2 0x7991
|
||||
#define MT7992_DEVICE_ID 0x7992
|
||||
#define MT7992_DEVICE_ID_2 0x799a
|
||||
#define MT7990_DEVICE_ID 0x7993
|
||||
#define MT7990_DEVICE_ID_2 0x799b
|
||||
|
||||
#define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
|
||||
#define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
|
||||
@@ -53,6 +63,11 @@
|
||||
#define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
|
||||
#define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
|
||||
|
||||
#define MT7990_FIRMWARE_WA ""
|
||||
#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
|
||||
#define MT7990_FIRMWARE_DSP ""
|
||||
#define MT7990_ROM_PATCH "mediatek/mt7996/mt7990_rom_patch.bin"
|
||||
|
||||
#define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
|
||||
#define MT7996_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7996_eeprom_2i5i6i.bin"
|
||||
#define MT7996_EEPROM_DEFAULT_233 "mediatek/mt7996/mt7996_eeprom_233.bin"
|
||||
@@ -64,6 +79,9 @@
|
||||
#define MT7992_EEPROM_DEFAULT_23 "mediatek/mt7996/mt7992_eeprom_23.bin"
|
||||
#define MT7992_EEPROM_DEFAULT_23_INT "mediatek/mt7996/mt7992_eeprom_23_2i5i.bin"
|
||||
|
||||
#define MT7990_EEPROM_DEFAULT "mediatek/mt7996/mt7990_eeprom.bin"
|
||||
#define MT7990_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7990_eeprom_2i5i.bin"
|
||||
|
||||
#define MT7996_EEPROM_SIZE 7680
|
||||
#define MT7996_EEPROM_BLOCK_SIZE 16
|
||||
#define MT7996_TOKEN_SIZE 16384
|
||||
@@ -134,6 +152,10 @@ enum mt7992_var_type {
|
||||
MT7992_VAR_TYPE_23,
|
||||
};
|
||||
|
||||
enum mt7990_var_type {
|
||||
MT7990_VAR_TYPE_23,
|
||||
};
|
||||
|
||||
enum mt7996_fem_type {
|
||||
MT7996_FEM_EXT,
|
||||
MT7996_FEM_INT,
|
||||
@@ -168,6 +190,8 @@ enum mt7996_rxq_id {
|
||||
MT7996_RXQ_TXFREE1 = 9,
|
||||
MT7996_RXQ_TXFREE2 = 7,
|
||||
MT7996_RXQ_RRO_IND = 0,
|
||||
MT7990_RXQ_TXFREE0 = 6,
|
||||
MT7990_RXQ_TXFREE1 = 7,
|
||||
};
|
||||
|
||||
struct mt7996_twt_flow {
|
||||
@@ -188,10 +212,10 @@ struct mt7996_twt_flow {
|
||||
|
||||
DECLARE_EWMA(avg_signal, 10, 8)
|
||||
|
||||
struct mt7996_sta {
|
||||
struct mt7996_sta_link {
|
||||
struct mt76_wcid wcid; /* must be first */
|
||||
|
||||
struct mt7996_vif *vif;
|
||||
struct mt7996_sta *sta;
|
||||
|
||||
struct list_head rc_list;
|
||||
u32 airtime_ac[8];
|
||||
@@ -207,12 +231,22 @@ struct mt7996_sta {
|
||||
u8 flowid_mask;
|
||||
struct mt7996_twt_flow flow[MT7996_MAX_STA_TWT_AGRT];
|
||||
} twt;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
struct mt7996_sta {
|
||||
struct mt7996_sta_link deflink; /* must be first */
|
||||
struct mt7996_sta_link __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
|
||||
u8 deflink_id;
|
||||
|
||||
struct mt7996_vif *vif;
|
||||
};
|
||||
|
||||
struct mt7996_vif_link {
|
||||
struct mt76_vif_link mt76; /* must be first */
|
||||
|
||||
struct mt7996_sta sta;
|
||||
struct mt7996_sta_link msta_link;
|
||||
struct mt7996_phy *phy;
|
||||
|
||||
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
|
||||
@@ -274,8 +308,6 @@ struct mt7996_phy {
|
||||
s16 coverage_class;
|
||||
u8 slottime;
|
||||
|
||||
u8 rdd_state;
|
||||
|
||||
u16 beacon_rate;
|
||||
|
||||
u32 rx_ampdu_ts;
|
||||
@@ -286,6 +318,7 @@ struct mt7996_phy {
|
||||
struct mt76_channel_state state_ts;
|
||||
|
||||
u16 orig_chainmask;
|
||||
u16 orig_antenna_mask;
|
||||
|
||||
bool has_aux_rx;
|
||||
bool counter_reset;
|
||||
@@ -398,10 +431,10 @@ enum {
|
||||
__MT_WFDMA_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT_RX_SEL0,
|
||||
MT_RX_SEL1,
|
||||
MT_RX_SEL2, /* monitor chain */
|
||||
enum rdd_idx {
|
||||
MT_RDD_IDX_BAND2, /* RDD idx for band idx 2 */
|
||||
MT_RDD_IDX_BAND1, /* RDD idx for band idx 1 */
|
||||
MT_RDD_IDX_BACKGROUND, /* RDD idx for background chain */
|
||||
};
|
||||
|
||||
enum mt7996_rdd_cmd {
|
||||
@@ -420,6 +453,21 @@ enum mt7996_rdd_cmd {
|
||||
RDD_IRQ_OFF,
|
||||
};
|
||||
|
||||
static inline int
|
||||
mt7996_get_rdd_idx(struct mt7996_phy *phy, bool is_background)
|
||||
{
|
||||
if (!phy->mt76->cap.has_5ghz)
|
||||
return -1;
|
||||
|
||||
if (is_background)
|
||||
return MT_RDD_IDX_BACKGROUND;
|
||||
|
||||
if (phy->mt76->band_idx == MT_BAND2)
|
||||
return MT_RDD_IDX_BAND2;
|
||||
|
||||
return MT_RDD_IDX_BAND1;
|
||||
}
|
||||
|
||||
static inline struct mt7996_dev *
|
||||
mt7996_hw_dev(struct ieee80211_hw *hw)
|
||||
{
|
||||
@@ -454,31 +502,12 @@ mt7996_phy3(struct mt7996_dev *dev)
|
||||
static inline bool
|
||||
mt7996_band_valid(struct mt7996_dev *dev, u8 band)
|
||||
{
|
||||
if (is_mt7992(&dev->mt76))
|
||||
if (!is_mt7996(&dev->mt76))
|
||||
return band <= MT_BAND1;
|
||||
|
||||
return band <= MT_BAND2;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mt7996_has_background_radar(struct mt7996_dev *dev)
|
||||
{
|
||||
switch (mt76_chip(&dev->mt76)) {
|
||||
case 0x7990:
|
||||
if (dev->var.type == MT7996_VAR_TYPE_233)
|
||||
return false;
|
||||
break;
|
||||
case 0x7992:
|
||||
if (dev->var.type == MT7992_VAR_TYPE_23)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline struct mt7996_phy *
|
||||
mt7996_band_phy(struct mt7996_dev *dev, enum nl80211_band band)
|
||||
{
|
||||
@@ -528,7 +557,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
|
||||
void __iomem *mem_base, u32 device_id);
|
||||
void mt7996_wfsys_reset(struct mt7996_dev *dev);
|
||||
irqreturn_t mt7996_irq_handler(int irq, void *dev_instance);
|
||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif *mvif);
|
||||
u64 __mt7996_get_tsf(struct ieee80211_hw *hw, struct mt7996_vif_link *link);
|
||||
int mt7996_register_device(struct mt7996_dev *dev);
|
||||
void mt7996_unregister_device(struct mt7996_dev *dev);
|
||||
int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
|
||||
@@ -542,6 +571,7 @@ int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy);
|
||||
int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
|
||||
struct ieee80211_channel *chan);
|
||||
s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
|
||||
bool mt7996_eeprom_has_background_radar(struct mt7996_dev *dev);
|
||||
int mt7996_dma_init(struct mt7996_dev *dev);
|
||||
void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
|
||||
void mt7996_dma_prefetch(struct mt7996_dev *dev);
|
||||
@@ -556,7 +586,7 @@ int mt7996_run(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_init(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
|
||||
struct mt7996_vif *mvif,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_twt_flow *flow,
|
||||
int cmd);
|
||||
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
@@ -564,35 +594,46 @@ int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct mt76_vif_link *mlink, bool enable);
|
||||
int mt7996_mcu_add_bss_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt76_vif_link *mlink, int enable);
|
||||
int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct mt76_vif_link *mlink,
|
||||
struct ieee80211_sta *sta, int conn_state, bool newly);
|
||||
struct mt76_vif_link *mlink,
|
||||
struct mt7996_sta_link *msta_link, int enable);
|
||||
int mt7996_mcu_add_sta(struct mt7996_dev *dev,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct ieee80211_link_sta *link_sta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
int conn_state, bool newly);
|
||||
int mt7996_mcu_teardown_mld_sta(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
int mt7996_mcu_add_tx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool add);
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, bool enable);
|
||||
int mt7996_mcu_add_rx_ba(struct mt7996_dev *dev,
|
||||
struct ieee80211_ampdu_params *params,
|
||||
bool add);
|
||||
struct mt7996_vif_link *link, bool enable);
|
||||
int mt7996_mcu_update_bss_color(struct mt7996_dev *dev,
|
||||
struct mt76_vif_link *mlink,
|
||||
struct cfg80211_he_bss_color *he_bss_color);
|
||||
int mt7996_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif, u32 changed);
|
||||
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt7996_vif_link *link, u32 changed);
|
||||
int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy,
|
||||
struct mt7996_vif_link *link,
|
||||
struct ieee80211_he_obss_pd *he_obss_pd);
|
||||
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, bool changed);
|
||||
int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
struct ieee80211_vif *vif, u8 link_id,
|
||||
bool changed);
|
||||
int mt7996_set_channel(struct mt76_phy *mphy);
|
||||
int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag);
|
||||
int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf);
|
||||
int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev,
|
||||
void *data, u16 version);
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, void *data, u32 field);
|
||||
int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta,
|
||||
void *data, u8 link_id, u32 field);
|
||||
int mt7996_mcu_set_eeprom(struct mt7996_dev *dev);
|
||||
int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len);
|
||||
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num);
|
||||
@@ -613,8 +654,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
|
||||
int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy, bool enable);
|
||||
int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy);
|
||||
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
|
||||
u8 rx_sel, u8 val);
|
||||
int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 rdd_idx, u8 val);
|
||||
int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
|
||||
@@ -680,32 +720,31 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
|
||||
return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
|
||||
}
|
||||
|
||||
static inline bool mt7996_has_wa(struct mt7996_dev *dev)
|
||||
{
|
||||
return !is_mt7990(&dev->mt76);
|
||||
}
|
||||
|
||||
void mt7996_mac_init(struct mt7996_dev *dev);
|
||||
u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
|
||||
bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
|
||||
void mt7996_mac_reset_counters(struct mt7996_phy *phy);
|
||||
void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy);
|
||||
void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
|
||||
void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif, bool enable);
|
||||
void mt7996_mac_write_txwi(struct mt7996_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);
|
||||
void mt7996_mac_update_beacons(struct mt7996_phy *phy);
|
||||
void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
|
||||
int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int mt7996_mac_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, enum mt76_sta_event ev);
|
||||
void mt7996_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt7996_mac_work(struct work_struct *work);
|
||||
void mt7996_mac_reset_work(struct work_struct *work);
|
||||
void mt7996_mac_dump_work(struct work_struct *work);
|
||||
void mt7996_mac_sta_rc_work(struct work_struct *work);
|
||||
void mt7996_mac_update_stats(struct mt7996_phy *phy);
|
||||
void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
|
||||
struct mt7996_sta *msta,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
u8 flowid);
|
||||
void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta,
|
||||
@@ -730,11 +769,14 @@ bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len);
|
||||
int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *key, int mcu_cmd,
|
||||
struct mt76_wcid *wcid, enum set_key_cmd cmd);
|
||||
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev, struct ieee80211_vif *vif,
|
||||
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
struct ieee80211_key_conf *key);
|
||||
int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link);
|
||||
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void mt7996_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
||||
@@ -20,14 +20,16 @@ static DEFINE_SPINLOCK(hif_lock);
|
||||
static u32 hif_idx;
|
||||
|
||||
static const struct pci_device_id mt7996_pci_device_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7990) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7992) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID) },
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct pci_device_id mt7996_hif_device_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7991) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x799a) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2) },
|
||||
{ },
|
||||
};
|
||||
|
||||
@@ -72,11 +74,13 @@ static struct mt7996_hif *mt7996_pci_init_hif2(struct pci_dev *pdev)
|
||||
hif_idx++;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&
|
||||
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))
|
||||
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2, NULL) &&
|
||||
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2, NULL) &&
|
||||
!pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2, NULL))
|
||||
#elif defined(__FreeBSD__)
|
||||
if (!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7991, NULL) &&
|
||||
!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x799a, NULL))
|
||||
if (!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7996_DEVICE_ID_2, NULL) &&
|
||||
!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7992_DEVICE_ID_2, NULL) &&
|
||||
!linuxkpi_pci_get_device(PCI_VENDOR_ID_MEDIATEK, MT7990_DEVICE_ID_2, NULL))
|
||||
#endif
|
||||
return NULL;
|
||||
|
||||
@@ -138,7 +142,9 @@ static int mt7996_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
mt76_pci_disable_aspm(pdev);
|
||||
|
||||
if (id->device == 0x7991 || id->device == 0x799a)
|
||||
if (id->device == MT7996_DEVICE_ID_2 ||
|
||||
id->device == MT7992_DEVICE_ID_2 ||
|
||||
id->device == MT7990_DEVICE_ID_2)
|
||||
return mt7996_pci_hif2_probe(pdev);
|
||||
|
||||
dev = mt7996_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
|
||||
@@ -273,6 +279,8 @@ MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
|
||||
MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
|
||||
MODULE_FIRMWARE(MT7992_ROM_PATCH);
|
||||
MODULE_FIRMWARE(MT7990_FIRMWARE_WM);
|
||||
MODULE_FIRMWARE(MT7990_ROM_PATCH);
|
||||
#if defined(__FreeBSD__)
|
||||
MODULE_VERSION(mt7996_pci, 1);
|
||||
MODULE_DEPEND(mt7996_pci, linuxkpi, 1, 1, 1);
|
||||
|
||||
@@ -64,6 +64,17 @@ enum offs_rev {
|
||||
MIB_BSCR7,
|
||||
MIB_BSCR17,
|
||||
MIB_TRDR1,
|
||||
HIF_REMAP_L1,
|
||||
HIF_REMAP_BASE_L1,
|
||||
HIF_REMAP_L2,
|
||||
HIF_REMAP_BASE_L2,
|
||||
CBTOP1_PHY_END,
|
||||
INFRA_MCU_END,
|
||||
WTBLON_WDUCR,
|
||||
WTBL_UPDATE,
|
||||
WTBL_ITCR,
|
||||
WTBL_ITCR0,
|
||||
WTBL_ITCR1,
|
||||
__MT_OFFS_MAX,
|
||||
};
|
||||
|
||||
@@ -291,19 +302,19 @@ enum offs_rev {
|
||||
/* WTBLON TOP */
|
||||
#define MT_WTBLON_TOP_BASE 0x820d4000
|
||||
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
|
||||
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x370)
|
||||
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(__OFFS(WTBLON_WDUCR))
|
||||
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(4, 0)
|
||||
|
||||
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x380)
|
||||
#define MT_WTBL_UPDATE MT_WTBLON_TOP(__OFFS(WTBL_UPDATE))
|
||||
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(11, 0)
|
||||
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(14)
|
||||
#define MT_WTBL_UPDATE_BUSY BIT(31)
|
||||
|
||||
#define MT_WTBL_ITCR MT_WTBLON_TOP(0x3b0)
|
||||
#define MT_WTBL_ITCR MT_WTBLON_TOP(__OFFS(WTBL_ITCR))
|
||||
#define MT_WTBL_ITCR_WR BIT(16)
|
||||
#define MT_WTBL_ITCR_EXEC BIT(31)
|
||||
#define MT_WTBL_ITDR0 MT_WTBLON_TOP(0x3b8)
|
||||
#define MT_WTBL_ITDR1 MT_WTBLON_TOP(0x3bc)
|
||||
#define MT_WTBL_ITDR0 MT_WTBLON_TOP(__OFFS(WTBL_ITCR0))
|
||||
#define MT_WTBL_ITDR1 MT_WTBLON_TOP(__OFFS(WTBL_ITCR1))
|
||||
#define MT_WTBL_SPE_IDX_SEL BIT(6)
|
||||
|
||||
/* WTBL */
|
||||
@@ -483,7 +494,7 @@ enum offs_rev {
|
||||
|
||||
#define MT_MCUQ_EXT_CTRL(q) (MT_Q_BASE(q) + 0x600 + \
|
||||
MT_MCUQ_ID(q) * 0x4)
|
||||
#define MT_RXQ_BAND1_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
|
||||
#define MT_RXQ_EXT_CTRL(q) (MT_Q_BASE(__RXQ(q)) + 0x680 + \
|
||||
MT_RXQ_ID(q) * 0x4)
|
||||
#define MT_TXQ_EXT_CTRL(q) (MT_Q_BASE(__TXQ(q)) + 0x600 + \
|
||||
MT_TXQ_ID(q) * 0x4)
|
||||
@@ -504,6 +515,8 @@ enum offs_rev {
|
||||
#define MT_INT_RX_DONE_WA_TRI BIT(3)
|
||||
#define MT_INT_RX_TXFREE_MAIN BIT(17)
|
||||
#define MT_INT_RX_TXFREE_TRI BIT(15)
|
||||
#define MT_INT_RX_TXFREE_BAND0_MT7990 BIT(14)
|
||||
#define MT_INT_RX_TXFREE_BAND1_MT7990 BIT(15)
|
||||
#define MT_INT_RX_DONE_BAND2_EXT BIT(23)
|
||||
#define MT_INT_RX_TXFREE_EXT BIT(26)
|
||||
#define MT_INT_MCU_CMD BIT(29)
|
||||
@@ -576,27 +589,39 @@ enum offs_rev {
|
||||
#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
|
||||
|
||||
/* l1/l2 remap */
|
||||
#define MT_HIF_REMAP_L1 0x155024
|
||||
#define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
|
||||
#define CONN_BUS_CR_VON_BASE 0x155000
|
||||
#define MT_HIF_REMAP_L1 (CONN_BUS_CR_VON_BASE + __OFFS(HIF_REMAP_L1))
|
||||
#define MT_HIF_REMAP_L1_MASK_7996 GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_L1_MASK GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L1_OFFSET GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L1_BASE GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_BASE_L1 0x130000
|
||||
#define MT_HIF_REMAP_BASE_L1 __OFFS(HIF_REMAP_BASE_L1)
|
||||
|
||||
#define MT_HIF_REMAP_L2 0x1b4
|
||||
#define MT_HIF_REMAP_L2 __OFFS(HIF_REMAP_L2)
|
||||
#define MT_HIF_REMAP_L2_MASK GENMASK(19, 0)
|
||||
#define MT_HIF_REMAP_L2_OFFSET GENMASK(11, 0)
|
||||
#define MT_HIF_REMAP_L2_BASE GENMASK(31, 12)
|
||||
#define MT_HIF_REMAP_BASE_L2 0x1000
|
||||
#define MT_HIF_REMAP_L2_MASK_7990 GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L2_OFFSET_7990 GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_L2_BASE_7990 GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_BASE_L2 __OFFS(HIF_REMAP_BASE_L2)
|
||||
|
||||
/* for mt7990 only */
|
||||
#define MT_HIF_REMAP_CBTOP 0x1f6554
|
||||
#define MT_HIF_REMAP_CBTOP_MASK GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_CBTOP_OFFSET GENMASK(15, 0)
|
||||
#define MT_HIF_REMAP_CBTOP_BASE GENMASK(31, 16)
|
||||
#define MT_HIF_REMAP_BASE_CBTOP 0x1c0000
|
||||
|
||||
#define MT_INFRA_BASE 0x18000000
|
||||
#define MT_WFSYS0_PHY_START 0x18400000
|
||||
#define MT_WFSYS1_PHY_START 0x18800000
|
||||
#define MT_WFSYS1_PHY_END 0x18bfffff
|
||||
#define MT_CBTOP1_PHY_START 0x70000000
|
||||
#define MT_CBTOP1_PHY_END 0x77ffffff
|
||||
#define MT_CBTOP1_PHY_END __OFFS(CBTOP1_PHY_END)
|
||||
#define MT_CBTOP2_PHY_START 0xf0000000
|
||||
#define MT_INFRA_MCU_START 0x7c000000
|
||||
#define MT_INFRA_MCU_END 0x7c3fffff
|
||||
#define MT_INFRA_MCU_END __OFFS(INFRA_MCU_END)
|
||||
|
||||
/* FW MODE SYNC */
|
||||
#define MT_FW_ASSERT_CNT 0x02208274
|
||||
|
||||
@@ -52,11 +52,6 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
|
||||
ether_addr_copy(hdr->addr3, req->bssid);
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (req->no_cck)
|
||||
info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
|
||||
info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
|
||||
|
||||
if (req->ie_len)
|
||||
skb_put_data(skb, req->ie, req->ie_len);
|
||||
|
||||
@@ -64,10 +59,20 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
|
||||
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
|
||||
|
||||
rcu_read_lock();
|
||||
if (ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL))
|
||||
mt76_tx(phy, NULL, mvif->wcid, skb);
|
||||
else
|
||||
|
||||
if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) {
|
||||
ieee80211_free_txskb(phy->hw, skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
if (req->no_cck)
|
||||
info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
|
||||
info->control.flags |= IEEE80211_TX_CTRL_DONT_USE_RATE_MASK;
|
||||
|
||||
mt76_tx(phy, NULL, mvif->wcid, skb);
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ mt76s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
|
||||
|
||||
if (err < 0) {
|
||||
dev_err(dev->dev, "sdio read data failed:%d\n", err);
|
||||
atomic_set(&dev->bus_hung, true);
|
||||
put_page(page);
|
||||
return err;
|
||||
}
|
||||
@@ -234,9 +235,10 @@ static int __mt76s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)
|
||||
err = sdio_writesb(sdio->func, MCR_WTDR1, data, len);
|
||||
sdio_release_host(sdio->func);
|
||||
|
||||
if (err)
|
||||
if (err) {
|
||||
dev_err(dev->dev, "sdio write failed: %d\n", err);
|
||||
|
||||
atomic_set(&dev->bus_hung, true);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ mt76_tx_status_unlock(struct mt76_dev *dev, struct sk_buff_head *list)
|
||||
struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb);
|
||||
struct mt76_wcid *wcid;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[cb->wcid]);
|
||||
wcid = __mt76_wcid_ptr(dev, cb->wcid);
|
||||
if (wcid) {
|
||||
status.sta = wcid_to_sta(wcid);
|
||||
if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) {
|
||||
@@ -100,7 +100,8 @@ __mt76_tx_status_skb_done(struct mt76_dev *dev, struct sk_buff *skb, u8 flags,
|
||||
return;
|
||||
|
||||
/* Tx status can be unreliable. if it fails, mark the frame as ACKed */
|
||||
if (flags & MT_TX_CB_TXS_FAILED) {
|
||||
if (flags & MT_TX_CB_TXS_FAILED &&
|
||||
(dev->drv->drv_flags & MT_DRV_IGNORE_TXS_FAILED)) {
|
||||
info->status.rates[0].count = 0;
|
||||
info->status.rates[0].idx = -1;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
@@ -250,9 +251,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (wcid_idx < ARRAY_SIZE(dev->wcid))
|
||||
wcid = rcu_dereference(dev->wcid[wcid_idx]);
|
||||
|
||||
wcid = __mt76_wcid_ptr(dev, wcid_idx);
|
||||
mt76_tx_check_non_aql(dev, wcid, skb);
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
@@ -333,6 +332,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct sk_buff_head *head;
|
||||
|
||||
if (mt76_testmode_enabled(phy)) {
|
||||
@@ -350,7 +350,8 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
||||
info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx);
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
|
||||
(info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK))
|
||||
((info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK) &&
|
||||
ieee80211_is_probe_req(hdr->frame_control)))
|
||||
head = &wcid->tx_offchannel;
|
||||
else
|
||||
head = &wcid->tx_pending;
|
||||
@@ -537,7 +538,7 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
|
||||
break;
|
||||
|
||||
mtxq = (struct mt76_txq *)txq->drv_priv;
|
||||
wcid = rcu_dereference(dev->wcid[mtxq->wcid]);
|
||||
wcid = __mt76_wcid_ptr(dev, mtxq->wcid);
|
||||
if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags))
|
||||
continue;
|
||||
|
||||
@@ -616,7 +617,8 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
||||
if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
||||
!ieee80211_is_data(hdr->frame_control) &&
|
||||
!ieee80211_is_bufferable_mmpdu(skb))
|
||||
(!ieee80211_is_bufferable_mmpdu(skb) ||
|
||||
ieee80211_is_deauth(hdr->frame_control)))
|
||||
qid = MT_TXQ_PSD;
|
||||
|
||||
q = phy->q_tx[qid];
|
||||
@@ -644,6 +646,7 @@ mt76_txq_schedule_pending_wcid(struct mt76_phy *phy, struct mt76_wcid *wcid,
|
||||
static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
{
|
||||
LIST_HEAD(tx_list);
|
||||
int ret = 0;
|
||||
|
||||
if (list_empty(&phy->tx_list))
|
||||
return;
|
||||
@@ -655,13 +658,13 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
list_splice_init(&phy->tx_list, &tx_list);
|
||||
while (!list_empty(&tx_list)) {
|
||||
struct mt76_wcid *wcid;
|
||||
int ret;
|
||||
|
||||
wcid = list_first_entry(&tx_list, struct mt76_wcid, tx_list);
|
||||
list_del_init(&wcid->tx_list);
|
||||
|
||||
spin_unlock(&phy->tx_lock);
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel);
|
||||
if (ret >= 0 && !phy->offchannel)
|
||||
ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending);
|
||||
spin_lock(&phy->tx_lock);
|
||||
@@ -670,9 +673,6 @@ static void mt76_txq_schedule_pending(struct mt76_phy *phy)
|
||||
!skb_queue_empty(&wcid->tx_offchannel) &&
|
||||
list_empty(&wcid->tx_list))
|
||||
list_add_tail(&wcid->tx_list, &phy->tx_list);
|
||||
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&phy->tx_lock);
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, u8 phy_idx)
|
||||
if (!(mask & 1))
|
||||
continue;
|
||||
|
||||
wcid = rcu_dereference(dev->wcid[j]);
|
||||
wcid = __mt76_wcid_ptr(dev, j);
|
||||
if (!wcid || wcid->phy_idx != phy_idx)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -34,11 +34,10 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
|
||||
struct mt76_dev *dev = container_of(wed, struct mt76_dev, mmio.wed);
|
||||
struct mtk_wed_bm_desc *desc = wed->rx_buf_ring.desc;
|
||||
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
||||
int i, len = SKB_WITH_OVERHEAD(q->buf_size);
|
||||
struct mt76_txwi_cache *t = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
enum dma_data_direction dir;
|
||||
dma_addr_t addr;
|
||||
u32 offset;
|
||||
int token;
|
||||
@@ -53,9 +52,6 @@ u32 mt76_wed_init_rx_buf(struct mtk_wed_device *wed, int size)
|
||||
goto unmap;
|
||||
|
||||
addr = page_pool_get_dma_addr(virt_to_head_page(buf)) + offset;
|
||||
dir = page_pool_get_dma_dir(q->page_pool);
|
||||
dma_sync_single_for_device(dev->dma_dev, addr, len, dir);
|
||||
|
||||
desc->buf0 = cpu_to_le32(addr);
|
||||
token = mt76_rx_token_consume(dev, buf, t, addr);
|
||||
if (token < 0) {
|
||||
|
||||
@@ -24,5 +24,6 @@ CFLAGS+= -DCONFIG_MAC80211_DEBUGFS=${WITH_DEBUGFS}
|
||||
|
||||
CFLAGS+= -I${COMMONDIR}
|
||||
CFLAGS+= ${LINUXKPI_INCLUDES}
|
||||
CFLAGS+= -DLINUXKPI_VERSION=61700
|
||||
|
||||
# end
|
||||
|
||||
Reference in New Issue
Block a user