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:
Bjoern A. Zeeb
2025-10-17 21:22:52 +00:00
81 changed files with 3983 additions and 1864 deletions
+7 -2
View File
@@ -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);
}
+5 -9
View File
@@ -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++) {
+4
View File
@@ -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
+63 -7
View File
@@ -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;
+4
View File
@@ -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;
+45 -8
View File
@@ -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);
+1 -1
View File
@@ -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;
+2 -8
View File
@@ -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;
+3 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -5
View File
@@ -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;
+10 -7
View File
@@ -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);
+3 -3
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
+6 -1
View File
@@ -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,
+2 -1
View File
@@ -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,
+3 -6
View File
@@ -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;
+1 -3
View File
@@ -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);
+2 -2
View File
@@ -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;
+2 -1
View File
@@ -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;
+5 -1
View File
@@ -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;
+51 -30
View File
@@ -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);
+32 -1
View File
@@ -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)
+9 -7
View File
@@ -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 |
+29 -55
View File
@@ -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;
}
+8 -5
View File
@@ -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;
}
+60 -28
View File
@@ -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
+1 -13
View File
@@ -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
+7 -4
View File
@@ -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;
+18 -7
View File
@@ -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);
+5 -3
View File
@@ -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)))
+18 -10
View File
@@ -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
+104
View File
@@ -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);
+4 -4
View File
@@ -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);
+157 -62
View File
@@ -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);
+366 -156
View File
@@ -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)
{
+75 -18
View File
@@ -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);
+35 -7
View File
@@ -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
+4 -3
View File
@@ -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);
+2 -2
View File
@@ -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;
}
+17 -5
View File
@@ -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
+100 -23
View File
@@ -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;
};
+35 -10
View File
@@ -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);
+1 -4
View File
@@ -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:
+53 -20
View File
@@ -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;
+131 -63
View File
@@ -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) &&
+38 -4
View File
@@ -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;
}
+27 -18
View File
@@ -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 |
+303 -189
View File
@@ -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
+43 -16
View File
@@ -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,
+180 -20
View File
@@ -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,
+99 -57
View File
@@ -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,
+17 -9
View File
@@ -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);
+38 -13
View File
@@ -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
+13 -8
View File
@@ -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();
}
+4 -2
View File
@@ -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;
}
+13 -13
View File
@@ -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);
+1 -1
View File
@@ -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;
+1 -5
View File
@@ -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) {
+1
View File
@@ -24,5 +24,6 @@ CFLAGS+= -DCONFIG_MAC80211_DEBUGFS=${WITH_DEBUGFS}
CFLAGS+= -I${COMMONDIR}
CFLAGS+= ${LINUXKPI_INCLUDES}
CFLAGS+= -DLINUXKPI_VERSION=61700
# end