mt76 patches for 5.12

* add new mt7921e driver
 * factor out common code shared between 7615/7663 and 7921
 * performance optimizations
 * 7915 dbdc fixes
 * 802.11 encap offload support
 * support for multiple pcie gen1 host interfaces on 7915
 * 7915 testmode support
 * bugfixes
 * testmode support enhancements
 * endian fixes
 * 7915 txbf support
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - http://gpgtools.org
 
 iEYEABECAAYFAmAURZcACgkQ130UHQKnbvX3xACePCxN0DX5vTv+4Z79sTpnc4ZY
 acwAn2iE9ObgXOWlSx3+QTz8fM4f5vGd
 =JCVv
 -----END PGP SIGNATURE-----

Merge tag 'mt76-for-kvalo-2021-01-29' of https://github.com/nbd168/wireless

mt76 patches for 5.12

* add new mt7921e driver
* factor out common code shared between 7615/7663 and 7921
* performance optimizations
* 7915 dbdc fixes
* 802.11 encap offload support
* support for multiple pcie gen1 host interfaces on 7915
* 7915 testmode support
* bugfixes
* testmode support enhancements
* endian fixes
* 7915 txbf support
This commit is contained in:
Kalle Valo 2021-02-08 19:04:02 +02:00
commit 1299616023
75 changed files with 12019 additions and 3210 deletions

View File

@ -24,8 +24,13 @@ config MT76x02_USB
tristate
select MT76_USB
config MT76_CONNAC_LIB
tristate
select MT76_CORE
source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7915/Kconfig"
source "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"

View File

@ -4,6 +4,7 @@ obj-$(CONFIG_MT76_USB) += mt76-usb.o
obj-$(CONFIG_MT76_SDIO) += mt76-sdio.o
obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o
obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o
mt76-y := \
mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \
@ -26,8 +27,11 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
obj-$(CONFIG_MT7603E) += mt7603/
obj-$(CONFIG_MT7615_COMMON) += mt7615/
obj-$(CONFIG_MT7915E) += mt7915/
obj-$(CONFIG_MT7921E) += mt7921/

View File

@ -411,8 +411,12 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
free:
#ifdef CONFIG_NL80211_TESTMODE
/* fix tx_done accounting on queue overflow */
if (tx_info.skb == dev->test.tx_skb)
dev->test.tx_done--;
if (mt76_is_testmode_skb(dev, skb, &hw)) {
struct mt76_phy *phy = hw->priv;
if (tx_info.skb == phy->test.tx_skb)
phy->test.tx_done--;
}
#endif
e.skb = tx_info.skb;

View File

@ -75,8 +75,8 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len)
}
#ifdef CONFIG_NL80211_TESTMODE
dev->test.mtd_name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
dev->test.mtd_offset = offset;
dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL);
dev->test_mtd.offset = offset;
#endif
out_put_node:

View File

@ -387,9 +387,9 @@ void mt76_unregister_phy(struct mt76_phy *phy)
{
struct mt76_dev *dev = phy->dev;
dev->phy2 = NULL;
mt76_tx_status_check(dev, NULL, true);
ieee80211_unregister_hw(phy->hw);
dev->phy2 = NULL;
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
@ -519,10 +519,10 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
}
#ifdef CONFIG_NL80211_TESTMODE
if (dev->test.state == MT76_TM_STATE_RX_FRAMES) {
dev->test.rx_stats.packets[q]++;
if (phy->test.state == MT76_TM_STATE_RX_FRAMES) {
phy->test.rx_stats.packets[q]++;
if (status->flag & RX_FLAG_FAILED_FCS_CRC)
dev->test.rx_stats.fcs_error[q]++;
phy->test.rx_stats.fcs_error[q]++;
}
#endif
__skb_queue_tail(&dev->rx_skb[q], skb);

View File

@ -81,6 +81,7 @@ enum mt76_rxq_id {
MT_RXQ_MCU,
MT_RXQ_MCU_WA,
MT_RXQ_EXT,
MT_RXQ_EXT_WA,
__MT_RXQ_MAX
};
@ -515,10 +516,10 @@ struct mt76_rx_status {
};
struct mt76_testmode_ops {
int (*set_state)(struct mt76_dev *dev, enum mt76_testmode_state state);
int (*set_params)(struct mt76_dev *dev, struct nlattr **tb,
int (*set_state)(struct mt76_phy *phy, enum mt76_testmode_state state);
int (*set_params)(struct mt76_phy *phy, struct nlattr **tb,
enum mt76_testmode_state new_state);
int (*dump_stats)(struct mt76_dev *dev, struct sk_buff *msg);
int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
};
struct mt76_testmode_data {
@ -539,17 +540,20 @@ struct mt76_testmode_data {
u8 tx_ltf;
u8 tx_antenna_mask;
u8 tx_spe_idx;
u8 tx_duty_cycle;
u32 tx_time;
u32 tx_ipg;
u32 freq_offset;
u8 tx_power[4];
u8 tx_power_control;
const char *mtd_name;
u32 mtd_offset;
u32 tx_pending;
u32 tx_queued;
u16 tx_queued_limit;
u32 tx_done;
struct {
u64 packets[__MT_RXQ_MAX];
@ -557,6 +561,14 @@ struct mt76_testmode_data {
} rx_stats;
};
struct mt76_vif {
u8 idx;
u8 omac_idx;
u8 band_idx;
u8 wmm_idx;
u8 scan_seq_num;
};
struct mt76_phy {
struct ieee80211_hw *hw;
struct mt76_dev *dev;
@ -578,10 +590,16 @@ struct mt76_phy {
u8 macaddr[ETH_ALEN];
u32 vif_mask;
int txpower_cur;
u8 antenna_mask;
u16 chainmask;
#ifdef CONFIG_NL80211_TESTMODE
struct mt76_testmode_data test;
#endif
struct delayed_work mac_work;
u8 mac_work_count;
};
struct mt76_dev {
@ -622,7 +640,6 @@ struct mt76_dev {
struct mt76_worker tx_worker;
struct napi_struct tx_napi;
struct delayed_work mac_work;
wait_queue_head_t tx_wait;
struct sk_buff_head status_list;
@ -630,6 +647,8 @@ struct mt76_dev {
u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)];
u32 vif_mask;
struct mt76_wcid global_wcid;
struct mt76_wcid __rcu *wcid[MT76_N_WCIDS];
@ -646,6 +665,7 @@ struct mt76_dev {
struct mt76_rate_power rate_power;
char alpha2[3];
enum nl80211_dfs_regions region;
u32 debugfs_reg;
@ -661,9 +681,11 @@ struct mt76_dev {
#ifdef CONFIG_NL80211_TESTMODE
const struct mt76_testmode_ops *test_ops;
struct mt76_testmode_data test;
struct {
const char *name;
u32 offset;
} test_mtd;
#endif
struct workqueue_struct *wq;
union {
@ -931,10 +953,27 @@ static inline u8 mt76_tx_power_nss_delta(u8 nss)
return nss_delta[nss - 1];
}
static inline bool mt76_testmode_enabled(struct mt76_dev *dev)
static inline bool mt76_testmode_enabled(struct mt76_phy *phy)
{
#ifdef CONFIG_NL80211_TESTMODE
return dev->test.state != MT76_TM_STATE_OFF;
return phy->test.state != MT76_TM_STATE_OFF;
#else
return false;
#endif
}
static inline bool mt76_is_testmode_skb(struct mt76_dev *dev,
struct sk_buff *skb,
struct ieee80211_hw **hw)
{
#ifdef CONFIG_NL80211_TESTMODE
if (skb == dev->phy.test.tx_skb)
*hw = dev->phy.hw;
else if (dev->phy2 && skb == dev->phy2->test.tx_skb)
*hw = dev->phy2->hw;
else
return false;
return true;
#else
return false;
#endif
@ -1016,17 +1055,17 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
struct netlink_callback *cb, void *data, int len);
int mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state);
int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state);
static inline void mt76_testmode_reset(struct mt76_dev *dev, bool disable)
static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
{
#ifdef CONFIG_NL80211_TESTMODE
enum mt76_testmode_state state = MT76_TM_STATE_IDLE;
if (disable || dev->test.state == MT76_TM_STATE_OFF)
if (disable || phy->test.state == MT76_TM_STATE_OFF)
state = MT76_TM_STATE_OFF;
mt76_testmode_set_state(dev, state);
mt76_testmode_set_state(phy, state);
#endif
}
@ -1052,7 +1091,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames,
void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q,
struct napi_struct *napi);
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames);
void mt76_testmode_tx_pending(struct mt76_dev *dev);
void mt76_testmode_tx_pending(struct mt76_phy *phy);
void mt76_queue_tx_complete(struct mt76_dev *dev, struct mt76_queue *q,
struct mt76_queue_entry *e);

View File

@ -532,7 +532,7 @@ int mt7603_register_device(struct mt7603_dev *dev)
spin_lock_init(&dev->sta_poll_lock);
spin_lock_init(&dev->ps_lock);
INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7603_mac_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7603_mac_work);
tasklet_setup(&dev->mt76.pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet);
dev->slottime = 9;

View File

@ -1631,9 +1631,13 @@ mt7603_edcca_check(struct mt7603_dev *dev)
if (rssi0 > 128)
rssi0 -= 256;
rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val);
if (rssi1 > 128)
rssi1 -= 256;
if (dev->mphy.antenna_mask & BIT(1)) {
rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val);
if (rssi1 > 128)
rssi1 -= 256;
} else {
rssi1 = rssi0;
}
if (max(rssi0, rssi1) >= -40 &&
dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH)
@ -1788,7 +1792,7 @@ mt7603_false_cca_check(struct mt7603_dev *dev)
void mt7603_mac_work(struct work_struct *work)
{
struct mt7603_dev *dev = container_of(work, struct mt7603_dev,
mt76.mac_work.work);
mphy.mac_work.work);
bool reset = false;
int i, idx;
@ -1796,7 +1800,7 @@ void mt7603_mac_work(struct work_struct *work)
mutex_lock(&dev->mt76.mutex);
dev->mac_work_count++;
dev->mphy.mac_work_count++;
mt76_update_survey(&dev->mt76);
mt7603_edcca_check(dev);
@ -1807,7 +1811,7 @@ void mt7603_mac_work(struct work_struct *work)
dev->mt76.aggr_stats[idx++] += val >> 16;
}
if (dev->mac_work_count == 10)
if (dev->mphy.mac_work_count == 10)
mt7603_false_cca_check(dev);
if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
@ -1838,17 +1842,17 @@ void mt7603_mac_work(struct work_struct *work)
dev->rx_dma_idx = ~0;
memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx));
reset = true;
dev->mac_work_count = 0;
dev->mphy.mac_work_count = 0;
}
if (dev->mac_work_count >= 10)
dev->mac_work_count = 0;
if (dev->mphy.mac_work_count >= 10)
dev->mphy.mac_work_count = 0;
mutex_unlock(&dev->mt76.mutex);
if (reset)
mt7603_mac_watchdog_reset(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
msecs_to_jiffies(MT7603_WATCHDOG_TIME));
}

View File

@ -17,7 +17,7 @@ mt7603_start(struct ieee80211_hw *hw)
mt7603_mac_start(dev);
dev->mphy.survey_time = ktime_get_boottime();
set_bit(MT76_STATE_RUNNING, &dev->mphy.state);
mt7603_mac_work(&dev->mt76.mac_work.work);
mt7603_mac_work(&dev->mphy.mac_work.work);
return 0;
}
@ -28,7 +28,7 @@ mt7603_stop(struct ieee80211_hw *hw)
struct mt7603_dev *dev = hw->priv;
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
mt7603_mac_stop(dev);
}
@ -44,7 +44,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mutex_lock(&dev->mt76.mutex);
mvif->idx = ffs(~dev->mphy.vif_mask) - 1;
mvif->idx = ffs(~dev->mt76.vif_mask) - 1;
if (mvif->idx >= MT7603_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
@ -65,7 +65,7 @@ mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
}
idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;
dev->mphy.vif_mask |= BIT(mvif->idx);
dev->mt76.vif_mask |= BIT(mvif->idx);
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.hw_key_idx = -1;
@ -105,7 +105,7 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
spin_unlock_bh(&dev->sta_poll_lock);
mutex_lock(&dev->mt76.mutex);
dev->mphy.vif_mask &= ~BIT(mvif->idx);
dev->mt76.vif_mask &= ~BIT(mvif->idx);
mutex_unlock(&dev->mt76.mutex);
}
@ -137,7 +137,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
u8 bw = MT_BW_20;
bool failed = false;
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
tasklet_disable(&dev->mt76.pre_tbtt_tasklet);
mutex_lock(&dev->mt76.mutex);
@ -178,7 +178,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
mt76_txq_schedule_all(&dev->mphy);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
msecs_to_jiffies(MT7603_WATCHDOG_TIME));
/* reset channel stats */
@ -200,7 +200,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
if (failed)
mt7603_mac_work(&dev->mt76.mac_work.work);
mt7603_mac_work(&dev->mphy.mac_work.work);
return ret;
}

View File

@ -132,8 +132,6 @@ struct mt7603_dev {
spinlock_t ps_lock;
u8 mac_work_count;
u8 mcu_running;
u8 ed_monitor_enabled;

View File

@ -2,7 +2,8 @@
config MT7615_COMMON
tristate
select MT76_CORE
select WANT_DEV_COREDUMP
select MT76_CONNAC_LIB
config MT7615E
tristate "MediaTek MT7615E and MT7663E (PCIe) support"

View File

@ -21,6 +21,20 @@ mt7615_radar_pattern_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,
mt7615_radar_pattern_set, "%lld\n");
static int mt7615_config(void *data, u64 val)
{
struct mt7615_dev *dev = data;
int ret;
mt7615_mutex_acquire(dev);
ret = mt76_connac_mcu_chip_config(&dev->mt76);
mt7615_mutex_release(dev);
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_config, NULL, mt7615_config, "%lld\n");
static int
mt7615_scs_set(void *data, u64 val)
{
@ -525,6 +539,9 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);
debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,
&fops_rf_reg);
if (is_mt7663(&dev->mt76))
debugfs_create_file("chip_config", 0600, dir, dev,
&fops_config);
if (mt76_is_sdio(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
mt7663s_sched_quota_read);

View File

@ -161,7 +161,7 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
dev->chainmask = BIT(tx_mask) - 1;
dev->mphy.antenna_mask = dev->chainmask;
dev->phy.chainmask = dev->chainmask;
dev->mphy.chainmask = dev->chainmask;
}
static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,

View File

@ -10,15 +10,16 @@
#include <linux/etherdevice.h>
#include "mt7615.h"
#include "mac.h"
#include "mcu.h"
#include "eeprom.h"
void mt7615_phy_init(struct mt7615_dev *dev)
static void
mt7615_phy_init(struct mt7615_dev *dev)
{
/* disable rf low power beacon mode */
mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(0), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN);
mt76_set(dev, MT_WF_PHY_WF2_RFCTRL0(1), MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN);
}
EXPORT_SYMBOL_GPL(mt7615_phy_init);
static void
mt7615_init_mac_chain(struct mt7615_dev *dev, int chain)
@ -79,7 +80,8 @@ mt7615_init_mac_chain(struct mt7615_dev *dev, int chain)
}
}
void mt7615_mac_init(struct mt7615_dev *dev)
static void
mt7615_mac_init(struct mt7615_dev *dev)
{
int i;
@ -95,7 +97,7 @@ void mt7615_mac_init(struct mt7615_dev *dev)
MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
MT_TMAC_CTCR0_INS_DDLMT_EN);
mt7615_mcu_set_rts_thresh(&dev->phy, 0x92b);
mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
mt7615_mac_set_scs(&dev->phy, true);
mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS,
@ -128,9 +130,9 @@ void mt7615_mac_init(struct mt7615_dev *dev)
mt7615_init_mac_chain(dev, 1);
}
}
EXPORT_SYMBOL_GPL(mt7615_mac_init);
void mt7615_check_offload_capability(struct mt7615_dev *dev)
static void
mt7615_check_offload_capability(struct mt7615_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
struct wiphy *wiphy = hw->wiphy;
@ -162,7 +164,6 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
wiphy->max_sched_scan_reqs = 0;
}
}
EXPORT_SYMBOL_GPL(mt7615_check_offload_capability);
bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)
{
@ -286,6 +287,16 @@ void mt7615_init_txpower(struct mt7615_dev *dev,
}
EXPORT_SYMBOL_GPL(mt7615_init_txpower);
void mt7615_init_work(struct mt7615_dev *dev)
{
mt7615_mcu_set_eeprom(dev);
mt7615_mac_init(dev);
mt7615_phy_init(dev);
mt7615_mcu_del_wtbl_all(dev);
mt7615_check_offload_capability(dev);
}
EXPORT_SYMBOL_GPL(mt7615_init_work);
static void
mt7615_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
@ -296,13 +307,16 @@ mt7615_regd_notifier(struct wiphy *wiphy,
struct mt7615_phy *phy = mphy->priv;
struct cfg80211_chan_def *chandef = &mphy->chandef;
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;
if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
return;
mt7615_mutex_acquire(dev);
mt7615_dfs_init_radar_detector(phy);
if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
mt7615_dfs_init_radar_detector(phy);
if (mt7615_firmware_offload(phy->dev))
mt76_connac_mcu_set_channel_domain(mphy);
mt7615_mutex_release(dev);
}
@ -331,11 +345,12 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
}
wiphy->reg_notifier = mt7615_regd_notifier;
wiphy->max_sched_scan_plan_interval = MT7615_MAX_SCHED_SCAN_INTERVAL;
wiphy->max_sched_scan_plan_interval =
MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL;
wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
wiphy->max_scan_ie_len = MT7615_SCAN_IE_LEN;
wiphy->max_sched_scan_ssids = MT7615_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT7615_MAX_SCAN_MATCH;
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
wiphy->max_sched_scan_reqs = 1;
wiphy->max_scan_ssids = 4;
@ -362,9 +377,9 @@ mt7615_cap_dbdc_enable(struct mt7615_dev *dev)
dev->mphy.antenna_mask = dev->chainmask >> 2;
else
dev->mphy.antenna_mask = dev->chainmask >> 1;
dev->phy.chainmask = dev->mphy.antenna_mask;
dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
dev->mphy.chainmask = dev->mphy.antenna_mask;
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
mt76_set_stream_caps(&dev->mphy, true);
}
@ -375,7 +390,7 @@ mt7615_cap_dbdc_disable(struct mt7615_dev *dev)
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
dev->mphy.antenna_mask = dev->chainmask;
dev->phy.chainmask = dev->chainmask;
dev->mphy.chainmask = dev->chainmask;
dev->mphy.hw->wiphy->available_antennas_rx = dev->chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->chainmask;
mt76_set_stream_caps(&dev->mphy, true);
@ -404,11 +419,11 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev)
phy = mphy->priv;
phy->dev = dev;
phy->mt76 = mphy;
phy->chainmask = dev->chainmask & ~dev->phy.chainmask;
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask;
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
mt7615_init_wiphy(mphy->hw);
INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&mphy->mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work);
skb_queue_head_init(&phy->scan_event_list);
@ -471,9 +486,11 @@ void mt7615_init_device(struct mt7615_dev *dev)
init_completion(&dev->pm.wake_cmpl);
spin_lock_init(&dev->pm.txq_lock);
set_bit(MT76_STATE_PM, &dev->mphy.state);
INIT_DELAYED_WORK(&dev->phy.mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7615_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7615_scan_work);
INIT_DELAYED_WORK(&dev->coredump.work, mt7615_coredump_work);
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
@ -488,7 +505,6 @@ void mt7615_init_device(struct mt7615_dev *dev)
dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
dev->mphy.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
mt7615_cap_dbdc_disable(dev);
dev->phy.dfs_state = -1;

View File

@ -7,6 +7,7 @@
* Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/devcoredump.h>
#include <linux/etherdevice.h>
#include <linux/timekeeping.h>
#include "mt7615.h"
@ -14,6 +15,7 @@
#include "../dma.h"
#include "mt7615_trace.h"
#include "mac.h"
#include "mcu.h"
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
@ -186,7 +188,7 @@ mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy,
status->freq = ieee80211_channel_to_frequency(chfreq, status->band);
}
static void mt7615_mac_fill_tm_rx(struct mt7615_dev *dev, __le32 *rxv)
static void mt7615_mac_fill_tm_rx(struct mt7615_phy *phy, __le32 *rxv)
{
#ifdef CONFIG_NL80211_TESTMODE
u32 rxv1 = le32_to_cpu(rxv[0]);
@ -210,13 +212,13 @@ static void mt7615_mac_fill_tm_rx(struct mt7615_dev *dev, __le32 *rxv)
foe = (foe * foe_const) >> 15;
}
dev->test.last_freq_offset = foe;
dev->test.last_rcpi[0] = FIELD_GET(MT_RXV4_RCPI0, rxv4);
dev->test.last_rcpi[1] = FIELD_GET(MT_RXV4_RCPI1, rxv4);
dev->test.last_rcpi[2] = FIELD_GET(MT_RXV4_RCPI2, rxv4);
dev->test.last_rcpi[3] = FIELD_GET(MT_RXV4_RCPI3, rxv4);
dev->test.last_ib_rssi[0] = FIELD_GET(MT_RXV3_IB_RSSI, rxv3);
dev->test.last_wb_rssi[0] = FIELD_GET(MT_RXV3_WB_RSSI, rxv3);
phy->test.last_freq_offset = foe;
phy->test.last_rcpi[0] = FIELD_GET(MT_RXV4_RCPI0, rxv4);
phy->test.last_rcpi[1] = FIELD_GET(MT_RXV4_RCPI1, rxv4);
phy->test.last_rcpi[2] = FIELD_GET(MT_RXV4_RCPI2, rxv4);
phy->test.last_rcpi[3] = FIELD_GET(MT_RXV4_RCPI3, rxv4);
phy->test.last_ib_rssi[0] = FIELD_GET(MT_RXV3_IB_RSSI, rxv3);
phy->test.last_wb_rssi[0] = FIELD_GET(MT_RXV3_WB_RSSI, rxv3);
#endif
}
@ -326,7 +328,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
* that PHY.
*/
if (phy_idx < 0) {
int first_chain = ffs(phy2->chainmask) - 1;
int first_chain = ffs(phy2->mt76->chainmask) - 1;
phy_idx = ((rxdg5 >> (first_chain * 8)) & 0xff) == 0;
}
@ -435,7 +437,7 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
status->chain_signal[i]);
}
mt7615_mac_fill_tm_rx(dev, rxd);
mt7615_mac_fill_tm_rx(mphy->priv, rxd);
rxd += 6;
if ((u8 *)rxd - skb->data >= skb->len)
@ -544,7 +546,7 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
u16 seqno = 0;
if (vif) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
omac_idx = mvif->omac_idx;
wmm_idx = mvif->wmm_idx;
@ -1465,7 +1467,7 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
mt7615_mac_sta_poll(dev);
rcu_read_unlock();
mt7615_pm_power_save_sched(dev);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
mt76_worker_schedule(&dev->mt76.tx_worker);
}
@ -1789,11 +1791,11 @@ void mt7615_update_channel(struct mt76_dev *mdev)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
if (mt7615_pm_wake(dev))
if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))
return;
__mt7615_update_channel(dev);
mt7615_pm_power_save_sched(dev);
mt76_connac_power_save_sched(&dev->mphy, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt7615_update_channel);
@ -1862,97 +1864,20 @@ void mt7615_pm_wake_work(struct work_struct *work)
{
struct mt7615_dev *dev;
struct mt76_phy *mphy;
int i;
dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,
pm.wake_work);
mphy = dev->phy.mt76;
if (mt7615_mcu_set_drv_ctrl(dev)) {
if (!mt7615_mcu_set_drv_ctrl(dev))
mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
else
dev_err(mphy->dev->dev, "failed to wake device\n");
goto out;
}
spin_lock_bh(&dev->pm.txq_lock);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
struct mt7615_sta *msta = dev->pm.tx_q[i].msta;
struct ieee80211_sta *sta = NULL;
struct mt76_wcid *wcid;
if (!dev->pm.tx_q[i].skb)
continue;
wcid = msta ? &msta->wcid : &dev->mt76.global_wcid;
if (msta && wcid->sta)
sta = container_of((void *)msta, struct ieee80211_sta,
drv_priv);
mt76_tx(mphy, sta, wcid, dev->pm.tx_q[i].skb);
dev->pm.tx_q[i].skb = NULL;
}
spin_unlock_bh(&dev->pm.txq_lock);
mt76_worker_schedule(&dev->mt76.tx_worker);
out:
ieee80211_wake_queues(mphy->hw);
complete_all(&dev->pm.wake_cmpl);
}
int mt7615_pm_wake(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = dev->phy.mt76;
if (!mt7615_firmware_offload(dev))
return 0;
if (!mt76_is_mmio(mphy->dev))
return 0;
if (!test_bit(MT76_STATE_PM, &mphy->state))
return 0;
if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
return 0;
if (queue_work(dev->mt76.wq, &dev->pm.wake_work))
reinit_completion(&dev->pm.wake_cmpl);
if (!wait_for_completion_timeout(&dev->pm.wake_cmpl, 3 * HZ)) {
ieee80211_wake_queues(mphy->hw);
return -ETIMEDOUT;
}
return 0;
}
EXPORT_SYMBOL_GPL(mt7615_pm_wake);
void mt7615_pm_power_save_sched(struct mt7615_dev *dev)
{
struct mt76_phy *mphy = dev->phy.mt76;
if (!mt7615_firmware_offload(dev))
return;
if (!mt76_is_mmio(mphy->dev))
return;
if (!dev->pm.enable || !test_bit(MT76_STATE_RUNNING, &mphy->state))
return;
dev->pm.last_activity = jiffies;
if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &mphy->state))
return;
if (!test_bit(MT76_STATE_PM, &mphy->state))
queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work,
dev->pm.idle_timeout);
}
EXPORT_SYMBOL_GPL(mt7615_pm_power_save_sched);
void mt7615_pm_power_save_work(struct work_struct *work)
{
struct mt7615_dev *dev;
@ -1976,17 +1901,17 @@ void mt7615_pm_power_save_work(struct work_struct *work)
void mt7615_mac_work(struct work_struct *work)
{
struct mt7615_phy *phy;
struct mt76_dev *mdev;
struct mt76_phy *mphy;
phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy,
mac_work.work);
mdev = &phy->dev->mt76;
mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
mac_work.work);
phy = mphy->priv;
mt7615_mutex_acquire(phy->dev);
mt7615_update_survey(phy->dev);
if (++phy->mac_work_count == 5) {
phy->mac_work_count = 0;
if (++mphy->mac_work_count == 5) {
mphy->mac_work_count = 0;
mt7615_mac_update_mib_stats(phy);
mt7615_mac_scs_check(phy);
@ -1994,8 +1919,8 @@ void mt7615_mac_work(struct work_struct *work)
mt7615_mutex_release(phy->dev);
mt76_tx_status_check(mdev, NULL, false);
ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
mt76_tx_status_check(mphy->dev, NULL, false);
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7615_WATCHDOG_TIME);
}
@ -2017,7 +1942,16 @@ mt7615_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
struct ieee80211_hw *hw = priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
mt7615_mcu_add_beacon(dev, hw, vif, vif->bss_conf.enable_beacon);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
mt7615_mcu_add_beacon(dev, hw, vif,
vif->bss_conf.enable_beacon);
break;
default:
break;
}
}
static void
@ -2058,6 +1992,23 @@ void mt7615_dma_reset(struct mt7615_dev *dev)
}
EXPORT_SYMBOL_GPL(mt7615_dma_reset);
void mt7615_tx_token_put(struct mt7615_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->token_lock);
idr_for_each_entry(&dev->token, txwi, id) {
mt7615_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb)
dev_kfree_skb_any(txwi->skb);
mt76_put_txwi(&dev->mt76, txwi);
}
spin_unlock_bh(&dev->token_lock);
idr_destroy(&dev->token);
}
EXPORT_SYMBOL_GPL(mt7615_tx_token_put);
void mt7615_mac_reset_work(struct work_struct *work)
{
struct mt7615_phy *phy2;
@ -2078,11 +2029,11 @@ void mt7615_mac_reset_work(struct work_struct *work)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->phy.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
del_timer_sync(&dev->phy.roc_timer);
cancel_work_sync(&dev->phy.roc_work);
if (phy2) {
cancel_delayed_work_sync(&phy2->mac_work);
cancel_delayed_work_sync(&phy2->mt76->mac_work);
del_timer_sync(&phy2->roc_timer);
cancel_work_sync(&phy2->roc_work);
}
@ -2101,6 +2052,9 @@ void mt7615_mac_reset_work(struct work_struct *work)
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED);
mt7615_tx_token_put(dev);
idr_init(&dev->token);
if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7615_dma_reset(dev);
@ -2134,10 +2088,11 @@ void mt7615_mac_reset_work(struct work_struct *work)
mt7615_mutex_release(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->phy.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT7615_WATCHDOG_TIME);
if (phy2)
ieee80211_queue_delayed_work(ext_phy->hw, &phy2->mac_work,
ieee80211_queue_delayed_work(ext_phy->hw,
&phy2->mt76->mac_work,
MT7615_WATCHDOG_TIME);
}
@ -2319,3 +2274,44 @@ int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,
return 0;
}
void mt7615_coredump_work(struct work_struct *work)
{
struct mt7615_dev *dev;
char *dump, *data;
dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,
coredump.work.work);
if (time_is_after_jiffies(dev->coredump.last_activity +
4 * MT76_CONNAC_COREDUMP_TIMEOUT)) {
queue_delayed_work(dev->mt76.wq, &dev->coredump.work,
MT76_CONNAC_COREDUMP_TIMEOUT);
return;
}
dump = vzalloc(MT76_CONNAC_COREDUMP_SZ);
data = dump;
while (true) {
struct sk_buff *skb;
spin_lock_bh(&dev->mt76.lock);
skb = __skb_dequeue(&dev->coredump.msg_list);
spin_unlock_bh(&dev->mt76.lock);
if (!skb)
break;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ)
break;
memcpy(data, skb->data, skb->len);
data += skb->len;
dev_kfree_skb(skb);
}
dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,
GFP_KERNEL);
}

View File

@ -24,22 +24,6 @@ static bool mt7615_dev_running(struct mt7615_dev *dev)
return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
}
static void mt7615_free_pending_tx_skbs(struct mt7615_dev *dev,
struct mt7615_sta *msta)
{
int i;
spin_lock_bh(&dev->pm.txq_lock);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
if (msta && dev->pm.tx_q[i].msta != msta)
continue;
dev_kfree_skb(dev->pm.tx_q[i].skb);
dev->pm.tx_q[i].skb = NULL;
}
spin_unlock_bh(&dev->pm.txq_lock);
}
static int mt7615_start(struct ieee80211_hw *hw)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
@ -55,22 +39,24 @@ static int mt7615_start(struct ieee80211_hw *hw)
if (!running) {
mt7615_mcu_set_pm(dev, 0, 0);
mt7615_mcu_set_mac_enable(dev, 0, true);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false);
mt7615_mac_enable_nf(dev, 0);
}
if (phy != &dev->phy) {
mt7615_mcu_set_pm(dev, 1, 0);
mt7615_mcu_set_mac_enable(dev, 1, true);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false);
mt7615_mac_enable_nf(dev, 1);
}
mt7615_mcu_set_channel_domain(phy);
if (mt7615_firmware_offload(dev))
mt76_connac_mcu_set_channel_domain(phy->mt76);
mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
ieee80211_queue_delayed_work(hw, &phy->mac_work,
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
MT7615_WATCHDOG_TIME);
if (!running)
@ -86,30 +72,30 @@ static void mt7615_stop(struct ieee80211_hw *hw)
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
cancel_delayed_work_sync(&dev->pm.ps_work);
cancel_work_sync(&dev->pm.wake_work);
mt7615_free_pending_tx_skbs(dev, NULL);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt7615_mutex_acquire(dev);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
cancel_delayed_work_sync(&phy->scan_work);
if (phy != &dev->phy) {
mt7615_mcu_set_pm(dev, 1, 1);
mt7615_mcu_set_mac_enable(dev, 1, false);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, false, false);
}
if (!mt7615_dev_running(dev)) {
mt7615_mcu_set_pm(dev, 0, 1);
mt7615_mcu_set_mac_enable(dev, 0, false);
mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);
}
mt7615_mutex_release(dev);
@ -181,14 +167,14 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
mt7615_mutex_acquire(dev);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
if (vif->type == NL80211_IFTYPE_MONITOR &&
is_zero_ether_addr(vif->addr))
phy->monitor_vif = vif;
mvif->idx = ffs(~dev->mphy.vif_mask) - 1;
if (mvif->idx >= MT7615_MAX_INTERFACES) {
mvif->mt76.idx = ffs(~dev->mt76.vif_mask) - 1;
if (mvif->mt76.idx >= MT7615_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
}
@ -198,26 +184,26 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
ret = -ENOSPC;
goto out;
}
mvif->omac_idx = idx;
mvif->mt76.omac_idx = idx;
mvif->band_idx = ext_phy;
mvif->mt76.band_idx = ext_phy;
if (mt7615_ext_phy(dev))
mvif->wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) +
mvif->idx % (MT7615_MAX_WMM_SETS / 2);
mvif->mt76.wmm_idx = ext_phy * (MT7615_MAX_WMM_SETS / 2) +
mvif->mt76.idx % (MT7615_MAX_WMM_SETS / 2);
else
mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS;
mvif->mt76.wmm_idx = mvif->mt76.idx % MT7615_MAX_WMM_SETS;
dev->mphy.vif_mask |= BIT(mvif->idx);
dev->omac_mask |= BIT_ULL(mvif->omac_idx);
phy->omac_mask |= BIT_ULL(mvif->omac_idx);
dev->mt76.vif_mask |= BIT(mvif->mt76.idx);
dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
mt7615_mcu_set_dbdc(dev);
idx = MT7615_WTBL_RESERVED - mvif->idx;
idx = MT7615_WTBL_RESERVED - mvif->mt76.idx;
INIT_LIST_HEAD(&mvif->sta.poll_list);
mvif->sta.wcid.idx = idx;
mvif->sta.wcid.ext_phy = mvif->band_idx;
mvif->sta.wcid.ext_phy = mvif->mt76.band_idx;
mvif->sta.wcid.hw_key_idx = -1;
mt7615_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@ -228,7 +214,7 @@ static int mt7615_add_interface(struct ieee80211_hw *hw,
mtxq->wcid = &mvif->sta.wcid;
}
ret = mt7615_mcu_add_dev_info(dev, vif, true);
ret = mt7615_mcu_add_dev_info(phy, vif, true);
if (ret)
goto out;
@ -252,20 +238,20 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw,
mt7615_mutex_acquire(dev);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
if (vif == phy->monitor_vif)
phy->monitor_vif = NULL;
mt7615_free_pending_tx_skbs(dev, msta);
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
mt7615_mac_set_beacon_filter(phy, vif, false);
mt7615_mcu_add_dev_info(dev, vif, false);
mt7615_mcu_add_dev_info(phy, vif, false);
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
dev->mphy.vif_mask &= ~BIT(mvif->idx);
dev->omac_mask &= ~BIT_ULL(mvif->omac_idx);
phy->omac_mask &= ~BIT_ULL(mvif->omac_idx);
dev->mt76.vif_mask &= ~BIT(mvif->mt76.idx);
dev->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
mt7615_mutex_release(dev);
@ -300,7 +286,7 @@ int mt7615_set_channel(struct mt7615_phy *phy)
bool ext_phy = phy != &dev->phy;
int ret;
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
mt7615_mutex_acquire(dev);
@ -321,7 +307,7 @@ int mt7615_set_channel(struct mt7615_phy *phy)
mt7615_mac_set_timing(phy);
ret = mt7615_dfs_init_radar_detector(phy);
mt7615_mac_cca_stats_reset(phy);
mt7615_mcu_set_sku_en(phy, !mt76_testmode_enabled(&dev->mt76));
mt7615_mcu_set_sku_en(phy, true);
mt7615_mac_reset_counters(dev);
phy->noise = 0;
@ -334,8 +320,9 @@ int mt7615_set_channel(struct mt7615_phy *phy)
mt76_txq_schedule_all(phy->mt76);
if (!mt76_testmode_enabled(&dev->mt76))
ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
if (!mt76_testmode_enabled(phy->mt76))
ieee80211_queue_delayed_work(phy->mt76->hw,
&phy->mt76->mac_work,
MT7615_WATCHDOG_TIME);
return ret;
@ -411,9 +398,9 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
if (changed & (IEEE80211_CONF_CHANGE_CHANNEL |
IEEE80211_CONF_CHANGE_POWER)) {
#ifdef CONFIG_NL80211_TESTMODE
if (dev->mt76.test.state != MT76_TM_STATE_OFF) {
if (phy->mt76->test.state != MT76_TM_STATE_OFF) {
mt7615_mutex_acquire(dev);
mt76_testmode_reset(&dev->mt76, false);
mt76_testmode_reset(phy->mt76, false);
mt7615_mutex_release(dev);
}
#endif
@ -425,7 +412,7 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed)
mt7615_mutex_acquire(dev);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
@ -444,7 +431,7 @@ static int
mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
int err;
@ -480,7 +467,7 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw,
#define MT76_FILTER(_flag, _hw) do { \
flags |= *total_flags & FIF_##_flag; \
phy->rxfilter &= ~(_hw); \
if (!mt76_testmode_enabled(&dev->mt76)) \
if (!mt76_testmode_enabled(phy->mt76)) \
phy->rxfilter |= !(flags & FIF_##_flag) * (_hw);\
} while (0)
@ -541,7 +528,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON_ENABLED) {
mt7615_mcu_add_bss_info(phy, vif, NULL, info->enable_beacon);
mt7615_mcu_sta_add(dev, vif, NULL, info->enable_beacon);
mt7615_mcu_sta_add(phy, vif, NULL, info->enable_beacon);
if (vif->p2p && info->enable_beacon)
mt7615_mcu_set_p2p_oppps(hw, vif);
@ -552,7 +539,7 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon);
if (changed & BSS_CHANGED_PS)
mt7615_mcu_set_vif_ps(dev, vif);
mt76_connac_mcu_set_vif_ps(&dev->mt76, vif);
if (changed & BSS_CHANGED_ARP_FILTER)
mt7615_mcu_update_arp_filter(hw, vif, info);
@ -578,6 +565,7 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_phy *phy;
int idx, err;
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
@ -588,23 +576,20 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
msta->vif = mvif;
msta->wcid.sta = 1;
msta->wcid.idx = idx;
msta->wcid.ext_phy = mvif->band_idx;
msta->wcid.ext_phy = mvif->mt76.band_idx;
err = mt7615_pm_wake(dev);
phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
err = mt76_connac_pm_wake(phy->mt76, &dev->pm);
if (err)
return err;
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
struct mt7615_phy *phy;
phy = mvif->band_idx ? mt7615_ext_phy(dev) : &dev->phy;
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt7615_mcu_add_bss_info(phy, vif, sta, true);
}
mt7615_mac_wtbl_update(dev, idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
mt7615_mcu_sta_add(dev, vif, sta, true);
mt7615_mcu_sta_add(&dev->phy, vif, sta, true);
mt7615_pm_power_save_sched(dev);
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
return 0;
}
@ -615,27 +600,26 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_phy *phy;
mt7615_free_pending_tx_skbs(dev, msta);
mt7615_pm_wake(dev);
mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid);
mt7615_mcu_sta_add(dev, vif, sta, false);
phy = mvif->mt76.band_idx ? mt7615_ext_phy(dev) : &dev->phy;
mt76_connac_pm_wake(phy->mt76, &dev->pm);
mt7615_mcu_sta_add(&dev->phy, vif, sta, false);
mt7615_mac_wtbl_update(dev, msta->wcid.idx,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_phy *phy;
phy = mvif->band_idx ? mt7615_ext_phy(dev) : &dev->phy;
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
mt7615_mcu_add_bss_info(phy, vif, sta, false);
}
spin_lock_bh(&dev->sta_poll_lock);
if (!list_empty(&msta->poll_list))
list_del_init(&msta->poll_list);
spin_unlock_bh(&dev->sta_poll_lock);
mt7615_pm_power_save_sched(dev);
mt76_connac_power_save_sched(phy->mt76, &dev->pm);
}
EXPORT_SYMBOL_GPL(mt7615_mac_sta_remove);
@ -720,25 +704,17 @@ static void mt7615_tx(struct ieee80211_hw *hw,
skb_set_queue_mapping(skb, qid);
}
spin_lock_bh(&dev->pm.txq_lock);
if (!dev->pm.tx_q[qid].skb) {
ieee80211_stop_queues(hw);
dev->pm.tx_q[qid].msta = msta;
dev->pm.tx_q[qid].skb = skb;
queue_work(dev->mt76.wq, &dev->pm.wake_work);
} else {
dev_kfree_skb(skb);
}
spin_unlock_bh(&dev->pm.txq_lock);
mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);
}
static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
int band = phy != &dev->phy;
mt7615_mutex_acquire(dev);
mt7615_mcu_set_rts_thresh(phy, val);
mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band);
mt7615_mutex_release(dev);
return 0;
@ -910,7 +886,7 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
else
tx_ant <<= 1;
}
phy->chainmask = tx_ant;
phy->mt76->chainmask = tx_ant;
mt76_set_stream_caps(phy->mt76, true);
@ -993,8 +969,12 @@ mt7615_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76_phy *mphy = hw->priv;
int err;
/* fall-back to sw-scan */
if (!mt7615_firmware_offload(dev))
return 1;
mt7615_mutex_acquire(dev);
err = mt7615_mcu_hw_scan(mphy->priv, vif, req);
err = mt76_connac_mcu_hw_scan(mphy, vif, req);
mt7615_mutex_release(dev);
return err;
@ -1007,7 +987,7 @@ mt7615_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
struct mt76_phy *mphy = hw->priv;
mt7615_mutex_acquire(dev);
mt7615_mcu_cancel_hw_scan(mphy->priv, vif);
mt76_connac_mcu_cancel_hw_scan(mphy, vif);
mt7615_mutex_release(dev);
}
@ -1020,13 +1000,16 @@ mt7615_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct mt76_phy *mphy = hw->priv;
int err;
if (!mt7615_firmware_offload(dev))
return -EOPNOTSUPP;
mt7615_mutex_acquire(dev);
err = mt7615_mcu_sched_scan_req(mphy->priv, vif, req);
err = mt76_connac_mcu_sched_scan_req(mphy, vif, req);
if (err < 0)
goto out;
err = mt7615_mcu_sched_scan_enable(mphy->priv, vif, true);
err = mt76_connac_mcu_sched_scan_enable(mphy, vif, true);
out:
mt7615_mutex_release(dev);
@ -1040,8 +1023,11 @@ mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
struct mt76_phy *mphy = hw->priv;
int err;
if (!mt7615_firmware_offload(dev))
return -EOPNOTSUPP;
mt7615_mutex_acquire(dev);
err = mt7615_mcu_sched_scan_enable(mphy->priv, vif, false);
err = mt76_connac_mcu_sched_scan_enable(mphy, vif, false);
mt7615_mutex_release(dev);
return err;
@ -1101,26 +1087,27 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw,
static int mt7615_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
struct mt7615_dev *dev = mt7615_hw_dev(hw);
int err = 0;
cancel_delayed_work_sync(&dev->pm.ps_work);
mt7615_free_pending_tx_skbs(dev, NULL);
mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
mt7615_mutex_acquire(dev);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
set_bit(MT76_STATE_SUSPEND, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_mcu_set_suspend_iter, phy);
mt76_connac_mcu_set_suspend_iter,
phy->mt76);
if (!mt7615_dev_running(dev))
err = mt7615_mcu_set_hif_suspend(dev, true);
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
mt7615_mutex_release(dev);
@ -1129,8 +1116,8 @@ static int mt7615_suspend(struct ieee80211_hw *hw,
static int mt7615_resume(struct ieee80211_hw *hw)
{
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_phy *phy = mt7615_hw_phy(hw);
struct mt7615_dev *dev = mt7615_hw_dev(hw);
bool running;
mt7615_mutex_acquire(dev);
@ -1141,7 +1128,7 @@ static int mt7615_resume(struct ieee80211_hw *hw)
if (!running) {
int err;
err = mt7615_mcu_set_hif_suspend(dev, false);
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
if (err < 0) {
mt7615_mutex_release(dev);
return err;
@ -1151,9 +1138,10 @@ static int mt7615_resume(struct ieee80211_hw *hw)
clear_bit(MT76_STATE_SUSPEND, &phy->mt76->state);
ieee80211_iterate_active_interfaces(hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_mcu_set_suspend_iter, phy);
mt76_connac_mcu_set_suspend_iter,
phy->mt76);
ieee80211_queue_delayed_work(hw, &phy->mac_work,
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
MT7615_WATCHDOG_TIME);
mt7615_mutex_release(dev);
@ -1176,7 +1164,7 @@ static void mt7615_set_rekey_data(struct ieee80211_hw *hw,
struct mt7615_dev *dev = mt7615_hw_dev(hw);
mt7615_mutex_acquire(dev);
mt7615_mcu_update_gtk_rekey(hw, vif, data);
mt76_connac_mcu_update_gtk_rekey(hw, vif, data);
mt7615_mutex_release(dev);
}
#endif /* CONFIG_PM */

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
#ifndef __MT7615_MCU_H
#define __MT7615_MCU_H
#include "../mt76_connac_mcu.h"
struct mt7615_mcu_txd {
__le32 txd[8];
@ -90,6 +92,7 @@ enum {
MCU_EVENT_SCHED_SCAN_DONE = 0x23,
MCU_EVENT_EXT = 0xed,
MCU_EVENT_RESTART_DL = 0xef,
MCU_EVENT_COREDUMP = 0xf0,
};
/* ext event table */
@ -236,64 +239,6 @@ enum {
MCU_S2D_H2CN
};
#define MCU_FW_PREFIX BIT(31)
#define MCU_UNI_PREFIX BIT(30)
#define MCU_CE_PREFIX BIT(29)
#define MCU_QUERY_PREFIX BIT(28)
#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX | \
MCU_CE_PREFIX | MCU_QUERY_PREFIX)
#define MCU_QUERY_MASK BIT(16)
enum {
MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01,
MCU_CMD_FW_START_REQ = MCU_FW_PREFIX | 0x02,
MCU_CMD_INIT_ACCESS_REG = 0x3,
MCU_CMD_PATCH_START_REQ = 0x05,
MCU_CMD_PATCH_FINISH_REQ = MCU_FW_PREFIX | 0x07,
MCU_CMD_PATCH_SEM_CONTROL = MCU_FW_PREFIX | 0x10,
MCU_CMD_EXT_CID = 0xED,
MCU_CMD_FW_SCATTER = MCU_FW_PREFIX | 0xEE,
MCU_CMD_RESTART_DL_REQ = MCU_FW_PREFIX | 0xEF,
};
enum {
MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
MCU_EXT_CMD_EDCA_UPDATE = 0x27,
MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
MCU_EXT_CMD_GET_TEMP = 0x2c,
MCU_EXT_CMD_WTBL_UPDATE = 0x32,
MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
MCU_EXT_CMD_ATE_CTRL = 0x3d,
MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
MCU_EXT_CMD_DBDC_CTRL = 0x45,
MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
MCU_EXT_CMD_SET_RX_PATH = 0x4e,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_RXDCOC_CAL = 0x59,
MCU_EXT_CMD_TXDPD_CAL = 0x60,
MCU_EXT_CMD_SET_RDD_TH = 0x7c,
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
};
enum {
MCU_UNI_CMD_DEV_INFO_UPDATE = MCU_UNI_PREFIX | 0x01,
MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02,
MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
MCU_UNI_CMD_SUSPEND = MCU_UNI_PREFIX | 0x05,
MCU_UNI_CMD_OFFLOAD = MCU_UNI_PREFIX | 0x06,
MCU_UNI_CMD_HIF_CTRL = MCU_UNI_PREFIX | 0x07,
};
enum {
MCU_ATE_SET_FREQ_OFFSET = 0xa,
MCU_ATE_SET_TX_POWER_CONTROL = 0x15,
@ -305,269 +250,11 @@ struct mt7615_mcu_uni_event {
__le32 status; /* 0: success, others: fail */
} __packed;
struct mt7615_beacon_loss_event {
u8 bss_idx;
u8 reason;
u8 pad[2];
} __packed;
struct mt7615_mcu_scan_ssid {
__le32 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct mt7615_mcu_scan_channel {
u8 band; /* 1: 2.4GHz
* 2: 5.0GHz
* Others: Reserved
*/
u8 channel_num;
} __packed;
struct mt7615_mcu_scan_match {
__le32 rssi_th;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
u8 rsv[3];
} __packed;
struct mt7615_hw_scan_req {
u8 seq_num;
u8 bss_idx;
u8 scan_type; /* 0: PASSIVE SCAN
* 1: ACTIVE SCAN
*/
u8 ssid_type; /* BIT(0) wildcard SSID
* BIT(1) P2P wildcard SSID
* BIT(2) specified SSID + wildcard SSID
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
*/
u8 ssids_num;
u8 probe_req_num; /* Number of probe request for each SSID */
u8 scan_func; /* BIT(0) Enable random MAC scan
* BIT(1) Disable DBDC scan type 1~3.
* BIT(2) Use DBDC scan type 3 (dedicated one RF to scan).
*/
u8 version; /* 0: Not support fields after ies.
* 1: Support fields after ies.
*/
struct mt7615_mcu_scan_ssid ssids[4];
__le16 probe_delay_time;
__le16 channel_dwell_time; /* channel Dwell interval */
__le16 timeout_value;
u8 channel_type; /* 0: Full channels
* 1: Only 2.4GHz channels
* 2: Only 5GHz channels
* 3: P2P social channel only (channel #1, #6 and #11)
* 4: Specified channels
* Others: Reserved
*/
u8 channels_num; /* valid when channel_type is 4 */
/* valid when channels_num is set */
struct mt7615_mcu_scan_channel channels[32];
__le16 ies_len;
u8 ies[MT7615_SCAN_IE_LEN];
/* following fields are valid if version > 0 */
u8 ext_channels_num;
u8 ext_ssids_num;
__le16 channel_min_dwell_time;
struct mt7615_mcu_scan_channel ext_channels[32];
struct mt7615_mcu_scan_ssid ext_ssids[6];
u8 bssid[ETH_ALEN];
u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */
u8 pad[63];
u8 ssid_type_ext;
} __packed;
#define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64
struct mt7615_hw_scan_done {
u8 seq_num;
u8 sparse_channel_num;
struct mt7615_mcu_scan_channel sparse_channel;
u8 complete_channel_num;
u8 current_state;
u8 version;
u8 pad;
__le32 beacon_scan_num;
u8 pno_enabled;
u8 pad2[3];
u8 sparse_channel_valid_num;
u8 pad3[3];
u8 channel_num[SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
/* idle format for channel_idle_time
* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms)
* 1: first bytes: idle time(8ms) 2nd byte: dwell time(8ms)
* 2: dwell time (16us)
*/
__le16 channel_idle_time[SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
/* beacon and probe response count */
u8 beacon_probe_num[SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
u8 mdrdy_count[SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
__le32 beacon_2g_num;
__le32 beacon_5g_num;
} __packed;
struct mt7615_sched_scan_req {
u8 version;
u8 seq_num;
u8 stop_on_match;
u8 ssids_num;
u8 match_num;
u8 pad;
__le16 ie_len;
struct mt7615_mcu_scan_ssid ssids[MT7615_MAX_SCHED_SCAN_SSID];
struct mt7615_mcu_scan_match match[MT7615_MAX_SCAN_MATCH];
u8 channel_type;
u8 channels_num;
u8 intervals_num;
u8 scan_func; /* BIT(0) eable random mac address */
struct mt7615_mcu_scan_channel channels[64];
__le16 intervals[MT7615_MAX_SCHED_SCAN_INTERVAL];
u8 random_mac[ETH_ALEN]; /* valid when BIT(0) in scan_func is set */
u8 pad2[58];
} __packed;
struct nt7615_sched_scan_done {
u8 seq_num;
u8 status; /* 0: ssid found */
__le16 pad;
} __packed;
struct mt7615_mcu_reg_event {
__le32 reg;
__le32 val;
} __packed;
struct mt7615_mcu_bss_event {
u8 bss_idx;
u8 is_absent;
u8 free_quota;
u8 pad;
} __packed;
struct mt7615_bss_basic_tlv {
__le16 tag;
__le16 len;
u8 active;
u8 omac_idx;
u8 hw_bss_idx;
u8 band_idx;
__le32 conn_type;
u8 conn_state;
u8 wmm_idx;
u8 bssid[ETH_ALEN];
__le16 bmc_tx_wlan_idx;
__le16 bcn_interval;
u8 dtim_period;
u8 phymode; /* bit(0): A
* bit(1): B
* bit(2): G
* bit(3): GN
* bit(4): AN
* bit(5): AC
*/
__le16 sta_idx;
u8 nonht_basic_phy;
u8 pad[3];
} __packed;
struct mt7615_bss_qos_tlv {
__le16 tag;
__le16 len;
u8 qos;
u8 pad[3];
} __packed;
enum {
WOW_USB = 1,
WOW_PCIE = 2,
WOW_GPIO = 3,
};
struct mt7615_wow_ctrl_tlv {
__le16 tag;
__le16 len;
u8 cmd; /* 0x1: PM_WOWLAN_REQ_START
* 0x2: PM_WOWLAN_REQ_STOP
* 0x3: PM_WOWLAN_PARAM_CLEAR
*/
u8 trigger; /* 0: NONE
* BIT(0): NL80211_WOWLAN_TRIG_MAGIC_PKT
* BIT(1): NL80211_WOWLAN_TRIG_ANY
* BIT(2): NL80211_WOWLAN_TRIG_DISCONNECT
* BIT(3): NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
* BIT(4): BEACON_LOST
* BIT(5): NL80211_WOWLAN_TRIG_NET_DETECT
*/
u8 wakeup_hif; /* 0x0: HIF_SDIO
* 0x1: HIF_USB
* 0x2: HIF_PCIE
* 0x3: HIF_GPIO
*/
u8 pad;
u8 rsv[4];
} __packed;
struct mt7615_wow_gpio_param_tlv {
__le16 tag;
__le16 len;
u8 gpio_pin;
u8 trigger_lvl;
u8 pad[2];
__le32 gpio_interval;
u8 rsv[4];
} __packed;
#define MT7615_WOW_MASK_MAX_LEN 16
#define MT7615_WOW_PATTEN_MAX_LEN 128
struct mt7615_wow_pattern_tlv {
__le16 tag;
__le16 len;
u8 index; /* pattern index */
u8 enable; /* 0: disable
* 1: enable
*/
u8 data_len; /* pattern length */
u8 pad;
u8 mask[MT7615_WOW_MASK_MAX_LEN];
u8 pattern[MT7615_WOW_PATTEN_MAX_LEN];
u8 rsv[4];
} __packed;
struct mt7615_suspend_tlv {
__le16 tag;
__le16 len;
u8 enable; /* 0: suspend mode disabled
* 1: suspend mode enabled
*/
u8 mdtim; /* LP parameter */
u8 wow_suspend; /* 0: update by origin policy
* 1: update by wow dtim
*/
u8 pad[5];
} __packed;
struct mt7615_gtk_rekey_tlv {
__le16 tag;
__le16 len;
u8 kek[NL80211_KEK_LEN];
u8 kck[NL80211_KCK_LEN];
u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
u8 rekey_mode; /* 0: rekey offload enable
* 1: rekey offload disable
* 2: rekey update
*/
u8 keyid;
u8 pad[2];
__le32 proto; /* WPA-RSN-WAPI-OPSN */
__le32 pairwise_cipher;
__le32 group_cipher;
__le32 key_mgmt; /* NONE-PSK-IEEE802.1X */
__le32 mgmt_group_cipher;
u8 option; /* 1: rekey data update without enabling offload */
u8 reserverd[3];
} __packed;
struct mt7615_roc_tlv {
u8 bss_idx;
u8 token;
@ -585,65 +272,6 @@ struct mt7615_roc_tlv {
u8 rsv1[8];
} __packed;
struct mt7615_arpns_tlv {
__le16 tag;
__le16 len;
u8 mode;
u8 ips_num;
u8 option;
u8 pad[1];
} __packed;
/* offload mcu commands */
enum {
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
MCU_CMD_SET_PS_PROFILE = MCU_CE_PREFIX | 0x05,
MCU_CMD_SET_CHAN_DOMAIN = MCU_CE_PREFIX | 0x0f,
MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16,
MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17,
MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b,
MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1c,
MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33,
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0,
MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0,
};
#define MCU_CMD_ACK BIT(0)
#define MCU_CMD_UNI BIT(1)
#define MCU_CMD_QUERY BIT(2)
#define MCU_CMD_UNI_EXT_ACK (MCU_CMD_ACK | MCU_CMD_UNI | MCU_CMD_QUERY)
enum {
UNI_BSS_INFO_BASIC = 0,
UNI_BSS_INFO_RLM = 2,
UNI_BSS_INFO_BCN_CONTENT = 7,
UNI_BSS_INFO_QBSS = 15,
UNI_BSS_INFO_UAPSD = 19,
};
enum {
UNI_SUSPEND_MODE_SETTING,
UNI_SUSPEND_WOW_CTRL,
UNI_SUSPEND_WOW_GPIO_PARAM,
UNI_SUSPEND_WOW_WAKEUP_PORT,
UNI_SUSPEND_WOW_PATTERN,
};
enum {
UNI_OFFLOAD_OFFLOAD_ARP,
UNI_OFFLOAD_OFFLOAD_ND,
UNI_OFFLOAD_OFFLOAD_GTK_REKEY,
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};
enum {
PATCH_SEM_RELEASE = 0x0,
PATCH_SEM_GET = 0x1
};
enum {
PATCH_NOT_DL_SEM_FAIL = 0x0,
PATCH_IS_DL = 0x1,
@ -664,34 +292,6 @@ enum {
FW_STATE_N9_RDY = 2,
};
#define STA_TYPE_STA BIT(0)
#define STA_TYPE_AP BIT(1)
#define STA_TYPE_ADHOC BIT(2)
#define STA_TYPE_WDS BIT(4)
#define STA_TYPE_BC BIT(5)
#define NETWORK_INFRA BIT(16)
#define NETWORK_P2P BIT(17)
#define NETWORK_IBSS BIT(18)
#define NETWORK_WDS BIT(21)
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P)
#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS)
#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS)
#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA)
#define CONN_STATE_DISCONNECT 0
#define CONN_STATE_CONNECT 1
#define CONN_STATE_PORT_SECURE 2
enum {
DEV_INFO_ACTIVE,
DEV_INFO_MAX_NUM
};
enum {
DBDC_TYPE_WMM,
DBDC_TYPE_MGMT,
@ -704,11 +304,6 @@ enum {
__DBDC_TYPE_MAX,
};
struct tlv {
__le16 tag;
__le16 len;
} __packed;
struct bss_info_omac {
__le16 tag;
__le16 len;
@ -767,157 +362,6 @@ enum {
BSS_INFO_MAX_NUM
};
enum {
WTBL_RESET_AND_SET = 1,
WTBL_SET,
WTBL_QUERY,
WTBL_RESET_ALL
};
struct wtbl_req_hdr {
u8 wlan_idx;
u8 operation;
__le16 tlv_num;
u8 rsv[4];
} __packed;
struct wtbl_generic {
__le16 tag;
__le16 len;
u8 peer_addr[ETH_ALEN];
u8 muar_idx;
u8 skip_tx;
u8 cf_ack;
u8 qos;
u8 mesh;
u8 adm;
__le16 partial_aid;
u8 baf_en;
u8 aad_om;
} __packed;
struct wtbl_rx {
__le16 tag;
__le16 len;
u8 rcid;
u8 rca1;
u8 rca2;
u8 rv;
u8 rsv[4];
} __packed;
struct wtbl_ht {
__le16 tag;
__le16 len;
u8 ht;
u8 ldpc;
u8 af;
u8 mm;
u8 rsv[4];
} __packed;
struct wtbl_vht {
__le16 tag;
__le16 len;
u8 ldpc;
u8 dyn_bw;
u8 vht;
u8 txop_ps;
u8 rsv[4];
} __packed;
struct wtbl_tx_ps {
__le16 tag;
__le16 len;
u8 txps;
u8 rsv[3];
} __packed;
struct wtbl_hdr_trans {
__le16 tag;
__le16 len;
u8 to_ds;
u8 from_ds;
u8 disable_rx_trans;
u8 rsv;
} __packed;
enum {
MT_BA_TYPE_INVALID,
MT_BA_TYPE_ORIGINATOR,
MT_BA_TYPE_RECIPIENT
};
enum {
RST_BA_MAC_TID_MATCH,
RST_BA_MAC_MATCH,
RST_BA_NO_MATCH
};
struct wtbl_ba {
__le16 tag;
__le16 len;
/* common */
u8 tid;
u8 ba_type;
u8 rsv0[2];
/* originator only */
__le16 sn;
u8 ba_en;
u8 ba_winsize_idx;
__le16 ba_winsize;
/* recipient only */
u8 peer_addr[ETH_ALEN];
u8 rst_ba_tid;
u8 rst_ba_sel;
u8 rst_ba_sb;
u8 band_idx;
u8 rsv1[4];
} __packed;
struct wtbl_bf {
__le16 tag;
__le16 len;
u8 ibf;
u8 ebf;
u8 ibf_vht;
u8 ebf_vht;
u8 gid;
u8 pfmu_idx;
u8 rsv[2];
} __packed;
struct wtbl_smps {
__le16 tag;
__le16 len;
u8 smps;
u8 rsv[3];
} __packed;
struct wtbl_pn {
__le16 tag;
__le16 len;
u8 pn[6];
u8 rsv[2];
} __packed;
struct wtbl_spe {
__le16 tag;
__le16 len;
u8 spe_idx;
u8 rsv[3];
} __packed;
struct wtbl_raw {
__le16 tag;
__le16 len;
u8 wtbl_idx;
u8 dw;
u8 rsv[2];
__le32 msk;
__le32 val;
} __packed;
#define MT7615_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_generic) + \
sizeof(struct wtbl_rx) + \
@ -942,127 +386,6 @@ struct wtbl_raw {
#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_ba))
enum {
WTBL_GENERIC,
WTBL_RX,
WTBL_HT,
WTBL_VHT,
WTBL_PEER_PS, /* not used */
WTBL_TX_PS,
WTBL_HDR_TRANS,
WTBL_SEC_KEY,
WTBL_BA,
WTBL_RDG, /* obsoleted */
WTBL_PROTECT, /* not used */
WTBL_CLEAR, /* not used */
WTBL_BF,
WTBL_SMPS,
WTBL_RAW_DATA, /* debug only */
WTBL_PN,
WTBL_SPE,
WTBL_MAX_NUM
};
struct sta_ntlv_hdr {
u8 rsv[2];
__le16 tlv_num;
} __packed;
struct sta_req_hdr {
u8 bss_idx;
u8 wlan_idx;
__le16 tlv_num;
u8 is_tlv_append;
u8 muar_idx;
u8 rsv[2];
} __packed;
struct sta_rec_state {
__le16 tag;
__le16 len;
u8 state;
__le32 flags;
u8 vhtop;
u8 pad[2];
} __packed;
struct sta_rec_basic {
__le16 tag;
__le16 len;
__le32 conn_type;
u8 conn_state;
u8 qos;
__le16 aid;
u8 peer_addr[ETH_ALEN];
#define EXTRA_INFO_VER BIT(0)
#define EXTRA_INFO_NEW BIT(1)
__le16 extra_info;
} __packed;
struct sta_rec_ht {
__le16 tag;
__le16 len;
__le16 ht_cap;
u16 rsv;
} __packed;
struct sta_rec_vht {
__le16 tag;
__le16 len;
__le32 vht_cap;
__le16 vht_rx_mcs_map;
__le16 vht_tx_mcs_map;
} __packed;
struct sta_rec_ba {
__le16 tag;
__le16 len;
u8 tid;
u8 ba_type;
u8 amsdu;
u8 ba_en;
__le16 ssn;
__le16 winsize;
} __packed;
struct sta_rec_uapsd {
__le16 tag;
__le16 len;
u8 dac_map;
u8 tac_map;
u8 max_sp;
u8 rsv0;
__le16 listen_interval;
u8 rsv1[2];
} __packed;
enum {
STA_REC_BASIC,
STA_REC_RA,
STA_REC_RA_CMM_INFO,
STA_REC_RA_UPDATE,
STA_REC_BF,
STA_REC_AMSDU, /* for CR4 */
STA_REC_BA,
STA_REC_STATE,
STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */
STA_REC_HT,
STA_REC_VHT,
STA_REC_APPS,
STA_REC_WTBL = 13,
STA_REC_MAX_NUM
};
enum {
CMD_CBW_20MHZ,
CMD_CBW_40MHZ,
CMD_CBW_80MHZ,
CMD_CBW_160MHZ,
CMD_CBW_10MHZ,
CMD_CBW_5MHZ,
CMD_CBW_8080MHZ
};
enum {
CH_SWITCH_NORMAL = 0,
CH_SWITCH_SCAN = 3,

View File

@ -8,7 +8,7 @@
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <linux/regmap.h>
#include "../mt76.h"
#include "../mt76_connac_mcu.h"
#include "regs.h"
#define MT7615_MAX_INTERFACES 16
@ -65,11 +65,6 @@
#define MT7615_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7615_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7615_SCAN_IE_LEN 600
#define MT7615_MAX_SCHED_SCAN_INTERVAL 10
#define MT7615_MAX_SCHED_SCAN_SSID 10
#define MT7615_MAX_SCAN_MATCH 16
struct mt7615_vif;
struct mt7615_sta;
struct mt7615_dfs_pulse;
@ -133,12 +128,7 @@ struct mt7615_sta {
};
struct mt7615_vif {
u8 idx;
u8 omac_idx;
u8 band_idx;
u8 wmm_idx;
u8 scan_seq_num;
struct mt76_vif mt76; /* must be first */
struct mt7615_sta sta;
};
@ -171,8 +161,6 @@ struct mt7615_phy {
s8 ofdm_sensitivity;
s8 cck_sensitivity;
u16 chainmask;
s16 coverage_class;
u8 slottime;
@ -185,9 +173,6 @@ struct mt7615_phy {
struct mib_stats mib;
struct delayed_work mac_work;
u8 mac_work_count;
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
@ -195,13 +180,24 @@ struct mt7615_phy {
struct timer_list roc_timer;
wait_queue_head_t roc_wait;
bool roc_grant;
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
s16 last_freq_offset;
u8 last_rcpi[4];
s8 last_ib_rssi[4];
s8 last_wb_rssi[4];
} test;
#endif
};
#define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__)
#define mt7615_mcu_add_rx_ba(dev, ...) (dev)->mcu_ops->add_rx_ba((dev), __VA_ARGS__)
#define mt7615_mcu_sta_add(dev, ...) (dev)->mcu_ops->sta_add((dev), __VA_ARGS__)
#define mt7615_mcu_add_dev_info(dev, ...) (dev)->mcu_ops->add_dev_info((dev), __VA_ARGS__)
#define mt7615_mcu_add_bss_info(phy, ...) (phy->dev)->mcu_ops->add_bss_info((phy), __VA_ARGS__)
#define mt7615_mcu_sta_add(phy, ...) ((phy)->dev)->mcu_ops->sta_add((phy), __VA_ARGS__)
#define mt7615_mcu_add_dev_info(phy, ...) ((phy)->dev)->mcu_ops->add_dev_info((phy), __VA_ARGS__)
#define mt7615_mcu_add_bss_info(phy, ...) ((phy)->dev)->mcu_ops->add_bss_info((phy), __VA_ARGS__)
#define mt7615_mcu_add_beacon(dev, ...) (dev)->mcu_ops->add_beacon_offload((dev), __VA_ARGS__)
#define mt7615_mcu_set_pm(dev, ...) (dev)->mcu_ops->set_pm_state((dev), __VA_ARGS__)
#define mt7615_mcu_set_drv_ctrl(dev) (dev)->mcu_ops->set_drv_ctrl((dev))
@ -213,11 +209,10 @@ struct mt7615_mcu_ops {
int (*add_rx_ba)(struct mt7615_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
int (*sta_add)(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
int (*sta_add)(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable);
int (*add_dev_info)(struct mt7615_dev *dev,
struct ieee80211_vif *vif, bool enable);
int (*add_dev_info)(struct mt7615_phy *phy, struct ieee80211_vif *vif,
bool enable);
int (*add_bss_info)(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable);
int (*add_beacon_offload)(struct mt7615_dev *dev,
@ -281,33 +276,8 @@ struct mt7615_dev {
u32 muar_mask;
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
s16 last_freq_offset;
u8 last_rcpi[4];
s8 last_ib_rssi[4];
s8 last_wb_rssi[4];
} test;
#endif
struct {
bool enable;
spinlock_t txq_lock;
struct {
struct mt7615_sta *msta;
struct sk_buff *skb;
} tx_q[IEEE80211_NUM_ACS];
struct work_struct wake_work;
struct completion wake_cmpl;
struct delayed_work ps_work;
unsigned long last_activity;
unsigned long idle_timeout;
} pm;
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
};
enum tx_pkt_queue_idx {
@ -325,20 +295,6 @@ enum tx_pkt_queue_idx {
MT_LMAC_PSMP1,
};
enum {
HW_BSSID_0 = 0x0,
HW_BSSID_1,
HW_BSSID_2,
HW_BSSID_3,
HW_BSSID_MAX = HW_BSSID_3,
EXT_BSSID_START = 0x10,
EXT_BSSID_1,
EXT_BSSID_15 = 0x1f,
EXT_BSSID_MAX = EXT_BSSID_15,
REPEATER_BSSID_START = 0x20,
REPEATER_BSSID_MAX = 0x3f,
};
enum {
MT_RX_SEL0,
MT_RX_SEL1,
@ -407,7 +363,6 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
int irq, const u32 *map);
u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
void mt7615_check_offload_capability(struct mt7615_dev *dev);
void mt7615_init_device(struct mt7615_dev *dev);
int mt7615_register_device(struct mt7615_dev *dev);
void mt7615_unregister_device(struct mt7615_dev *dev);
@ -428,8 +383,6 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
struct ieee80211_tx_rate *probe_rate,
struct ieee80211_tx_rate *rates);
void mt7615_pm_wake_work(struct work_struct *work);
int mt7615_pm_wake(struct mt7615_dev *dev);
void mt7615_pm_power_save_sched(struct mt7615_dev *dev);
void mt7615_pm_power_save_work(struct work_struct *work);
int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev);
int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd);
@ -485,19 +438,10 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev)
return MT7615_WTBL_SIZE;
}
static inline void mt7615_mutex_acquire(struct mt7615_dev *dev)
__acquires(&dev->mt76.mutex)
{
mutex_lock(&dev->mt76.mutex);
mt7615_pm_wake(dev);
}
static inline void mt7615_mutex_release(struct mt7615_dev *dev)
__releases(&dev->mt76.mutex)
{
mt7615_pm_power_save_sched(dev);
mutex_unlock(&dev->mt76.mutex);
}
#define mt7615_mutex_acquire(dev) \
mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm)
#define mt7615_mutex_release(dev) \
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac)
{
@ -525,9 +469,8 @@ void mt7615_roc_work(struct work_struct *work);
void mt7615_roc_timer(struct timer_list *timer);
void mt7615_init_txpower(struct mt7615_dev *dev,
struct ieee80211_supported_band *sband);
void mt7615_phy_init(struct mt7615_dev *dev);
void mt7615_mac_init(struct mt7615_dev *dev);
int mt7615_set_channel(struct mt7615_phy *phy);
void mt7615_init_work(struct mt7615_dev *dev);
int mt7615_mcu_restart(struct mt76_dev *dev);
void mt7615_update_channel(struct mt76_dev *mdev);
@ -558,24 +501,11 @@ u32 mt7615_rf_rr(struct mt7615_dev *dev, u32 wf, u32 reg);
int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val);
int mt7615_mcu_set_dbdc(struct mt7615_dev *dev);
int mt7615_mcu_set_eeprom(struct mt7615_dev *dev);
int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable);
int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val);
int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index);
int mt7615_mcu_set_tx_power(struct mt7615_phy *phy);
void mt7615_mcu_exit(struct mt7615_dev *dev);
void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,
int cmd, int *wait_seq);
int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy);
int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_scan_request *scan_req);
int mt7615_mcu_cancel_hw_scan(struct mt7615_phy *phy,
struct ieee80211_vif *vif);
int mt7615_mcu_sched_scan_req(struct mt7615_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq);
int mt7615_mcu_sched_scan_enable(struct mt7615_phy *phy,
struct ieee80211_vif *vif,
bool enable);
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
@ -583,7 +513,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt76_tx_info *tx_info);
void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7615_tx_token_put(struct mt7615_dev *dev);
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
void mt7615_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
@ -604,7 +534,6 @@ int mt7615_mcu_set_test_param(struct mt7615_dev *dev, u8 param, bool test_mode,
int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable);
int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy);
int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy);
int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif);
int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy);
int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw,
@ -620,18 +549,13 @@ int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,
bool enable);
int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend);
void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *key);
int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info);
int __mt7663_load_firmware(struct mt7615_dev *dev);
u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset);
void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
void mt7615_coredump_work(struct work_struct *work);
/* usb */
int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,

View File

@ -10,6 +10,7 @@
#include <linux/pci.h>
#include "mt7615.h"
#include "mcu.h"
static const struct pci_device_id mt7615_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7615) },
@ -75,14 +76,14 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
bool hif_suspend;
int i, err;
err = mt7615_pm_wake(dev);
err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
if (err < 0)
return err;
hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
mt7615_firmware_offload(dev);
if (hif_suspend) {
err = mt7615_mcu_set_hif_suspend(dev, true);
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
if (err)
return err;
}
@ -130,7 +131,7 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
}
napi_enable(&mdev->tx_napi);
if (hif_suspend)
mt7615_mcu_set_hif_suspend(dev, false);
mt76_connac_mcu_set_hif_suspend(mdev, false);
return err;
}
@ -172,7 +173,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev)
if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
mt7615_firmware_offload(dev))
err = mt7615_mcu_set_hif_suspend(dev, false);
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
return err;
}

View File

@ -12,7 +12,7 @@
#include "mac.h"
#include "eeprom.h"
static void mt7615_init_work(struct work_struct *work)
static void mt7615_pci_init_work(struct work_struct *work)
{
struct mt7615_dev *dev = container_of(work, struct mt7615_dev,
mcu_work);
@ -27,12 +27,7 @@ static void mt7615_init_work(struct work_struct *work)
if (ret)
return;
mt7615_mcu_set_eeprom(dev);
mt7615_mac_init(dev);
mt7615_phy_init(dev);
mt7615_mcu_del_wtbl_all(dev);
mt7615_check_offload_capability(dev);
mt7615_init_work(dev);
if (dev->dbdc_support)
mt7615_register_ext_phy(dev);
}
@ -44,7 +39,7 @@ static int mt7615_init_hardware(struct mt7615_dev *dev)
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
INIT_WORK(&dev->mcu_work, mt7615_init_work);
INIT_WORK(&dev->mcu_work, mt7615_pci_init_work);
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);
@ -160,9 +155,7 @@ int mt7615_register_device(struct mt7615_dev *dev)
void mt7615_unregister_device(struct mt7615_dev *dev)
{
struct mt76_txwi_cache *txwi;
bool mcu_running;
int id;
mcu_running = mt7615_wait_for_mcu_init(dev);
@ -172,15 +165,7 @@ void mt7615_unregister_device(struct mt7615_dev *dev)
mt7615_mcu_exit(dev);
mt7615_dma_cleanup(dev);
spin_lock_bh(&dev->token_lock);
idr_for_each_entry(&dev->token, txwi, id) {
mt7615_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb)
dev_kfree_skb_any(txwi->skb);
mt76_put_txwi(&dev->mt76, txwi);
}
spin_unlock_bh(&dev->token_lock);
idr_destroy(&dev->token);
mt7615_tx_token_put(dev);
tasklet_disable(&dev->irq_tasklet);

View File

@ -118,7 +118,7 @@ mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
if (vif) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
txp->bss_idx = mvif->idx;
}

View File

@ -17,6 +17,7 @@
#include "mt7615.h"
#include "sdio.h"
#include "mac.h"
#include "mcu.h"
static const struct sdio_device_id mt7663s_table[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7603) },
@ -227,11 +228,7 @@ static void mt7663s_init_work(struct work_struct *work)
if (mt7663s_mcu_init(dev))
return;
mt7615_mcu_set_eeprom(dev);
mt7615_mac_init(dev);
mt7615_phy_init(dev);
mt7615_mcu_del_wtbl_all(dev);
mt7615_check_offload_capability(dev);
mt7615_init_work(dev);
}
static int mt7663s_hw_init(struct mt7615_dev *dev, struct sdio_func *func)
@ -417,7 +414,7 @@ static int mt7663s_suspend(struct device *dev)
mt7615_firmware_offload(mdev)) {
int err;
err = mt7615_mcu_set_hif_suspend(mdev, true);
err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, true);
if (err < 0)
return err;
}
@ -456,7 +453,7 @@ static int mt7663s_resume(struct device *dev)
if (!test_bit(MT76_STATE_SUSPEND, &mdev->mphy.state) &&
mt7615_firmware_offload(mdev))
err = mt7615_mcu_set_hif_suspend(mdev, false);
err = mt76_connac_mcu_set_hif_suspend(&mdev->mt76, false);
return err;
}

View File

@ -67,8 +67,8 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy)
};
u8 *tx_power = NULL;
if (dev->mt76.test.state != MT76_TM_STATE_OFF)
tx_power = dev->mt76.test.tx_power;
if (mphy->test.state != MT76_TM_STATE_OFF)
tx_power = mphy->test.tx_power;
len = MT7615_EE_MAX - MT_EE_NIC_CONF_0;
skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, sizeof(req_hdr) + len);
@ -95,14 +95,15 @@ mt7615_tm_set_tx_power(struct mt7615_phy *phy)
}
static void
mt7615_tm_reg_backup_restore(struct mt7615_dev *dev)
mt7615_tm_reg_backup_restore(struct mt7615_phy *phy)
{
u32 *b = dev->test.reg_backup;
struct mt7615_dev *dev = phy->dev;
u32 *b = phy->test.reg_backup;
int n_regs = ARRAY_SIZE(reg_backup_list);
int n_rf_regs = ARRAY_SIZE(rf_backup_list);
int i;
if (dev->mt76.test.state == MT76_TM_STATE_OFF) {
if (phy->mt76->test.state == MT76_TM_STATE_OFF) {
for (i = 0; i < n_regs; i++)
mt76_wr(dev, reg_backup_list[i], b[i]);
@ -120,7 +121,7 @@ mt7615_tm_reg_backup_restore(struct mt7615_dev *dev)
if (!b)
return;
dev->test.reg_backup = b;
phy->test.reg_backup = b;
for (i = 0; i < n_regs; i++)
b[i] = mt76_rr(dev, reg_backup_list[i]);
for (i = 0; i < n_rf_regs; i++)
@ -128,30 +129,23 @@ mt7615_tm_reg_backup_restore(struct mt7615_dev *dev)
rf_backup_list[i].reg);
}
static void
mt7615_tm_init_phy(struct mt7615_dev *dev, struct mt7615_phy *phy)
mt7615_tm_init(struct mt7615_phy *phy)
{
struct mt7615_dev *dev = phy->dev;
unsigned int total_flags = ~0;
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
mt7615_mcu_set_sku_en(phy, phy->mt76->test.state == MT76_TM_STATE_OFF);
mutex_unlock(&dev->mt76.mutex);
mt7615_set_channel(phy);
mt7615_ops.configure_filter(phy->mt76->hw, 0, &total_flags, 0);
mutex_lock(&dev->mt76.mutex);
mt7615_tm_reg_backup_restore(dev);
}
static void
mt7615_tm_init(struct mt7615_dev *dev)
{
mt7615_tm_init_phy(dev, &dev->phy);
if (dev->mt76.phy2)
mt7615_tm_init_phy(dev, dev->mt76.phy2->priv);
mt7615_tm_reg_backup_restore(phy);
}
static void
@ -175,9 +169,10 @@ mt7615_tm_set_rx_enable(struct mt7615_dev *dev, bool en)
}
static void
mt7615_tm_set_tx_antenna(struct mt7615_dev *dev, bool en)
mt7615_tm_set_tx_antenna(struct mt7615_phy *phy, bool en)
{
struct mt76_testmode_data *td = &dev->mt76.test;
struct mt7615_dev *dev = phy->dev;
struct mt76_testmode_data *td = &phy->mt76->test;
u8 mask = td->tx_antenna_mask;
int i;
@ -185,7 +180,7 @@ mt7615_tm_set_tx_antenna(struct mt7615_dev *dev, bool en)
return;
if (!en)
mask = dev->phy.chainmask;
mask = phy->mt76->chainmask;
for (i = 0; i < 4; i++) {
mt76_rmw_field(dev, MT_WF_PHY_RFINTF3_0(i),
@ -228,26 +223,28 @@ mt7615_tm_set_tx_antenna(struct mt7615_dev *dev, bool en)
}
static void
mt7615_tm_set_tx_frames(struct mt7615_dev *dev, bool en)
mt7615_tm_set_tx_frames(struct mt7615_phy *phy, bool en)
{
struct mt7615_dev *dev = phy->dev;
struct ieee80211_tx_info *info;
struct sk_buff *skb = dev->mt76.test.tx_skb;
struct sk_buff *skb = phy->mt76->test.tx_skb;
mt7615_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH);
mt7615_tm_set_tx_antenna(dev, en);
mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
mt7615_tm_set_tx_antenna(phy, en);
mt7615_tm_set_rx_enable(dev, !en);
if (!en || !skb)
return;
info = IEEE80211_SKB_CB(skb);
info->control.vif = dev->phy.monitor_vif;
info->control.vif = phy->monitor_vif;
}
static void
mt7615_tm_update_params(struct mt7615_dev *dev, u32 changed)
mt7615_tm_update_params(struct mt7615_phy *phy, u32 changed)
{
struct mt76_testmode_data *td = &dev->mt76.test;
bool en = dev->mt76.test.state != MT76_TM_STATE_OFF;
struct mt7615_dev *dev = phy->dev;
struct mt76_testmode_data *td = &phy->mt76->test;
bool en = phy->mt76->test.state != MT76_TM_STATE_OFF;
if (changed & BIT(TM_CHANGED_TXPOWER_CTRL))
mt7615_mcu_set_test_param(dev, MCU_ATE_SET_TX_POWER_CONTROL,
@ -256,25 +253,25 @@ mt7615_tm_update_params(struct mt7615_dev *dev, u32 changed)
mt7615_mcu_set_test_param(dev, MCU_ATE_SET_FREQ_OFFSET,
en, en ? td->freq_offset : 0);
if (changed & BIT(TM_CHANGED_TXPOWER))
mt7615_tm_set_tx_power(&dev->phy);
mt7615_tm_set_tx_power(phy);
}
static int
mt7615_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state)
mt7615_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt76_testmode_data *td = &mdev->test;
struct mt7615_phy *phy = mphy->priv;
struct mt76_testmode_data *td = &mphy->test;
enum mt76_testmode_state prev_state = td->state;
mdev->test.state = state;
mphy->test.state = state;
if (prev_state == MT76_TM_STATE_TX_FRAMES)
mt7615_tm_set_tx_frames(dev, false);
mt7615_tm_set_tx_frames(phy, false);
else if (state == MT76_TM_STATE_TX_FRAMES)
mt7615_tm_set_tx_frames(dev, true);
mt7615_tm_set_tx_frames(phy, true);
if (state <= MT76_TM_STATE_IDLE)
mt7615_tm_init(dev);
mt7615_tm_init(phy);
if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
@ -290,18 +287,18 @@ mt7615_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state)
changed |= BIT(i);
}
mt7615_tm_update_params(dev, changed);
mt7615_tm_update_params(phy, changed);
}
return 0;
}
static int
mt7615_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
mt7615_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
enum mt76_testmode_state new_state)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt76_testmode_data *td = &dev->mt76.test;
struct mt76_testmode_data *td = &mphy->test;
struct mt7615_phy *phy = mphy->priv;
u32 changed = 0;
int i;
@ -311,7 +308,7 @@ mt7615_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
td->state == MT76_TM_STATE_OFF)
return 0;
if (td->tx_antenna_mask & ~dev->phy.chainmask)
if (td->tx_antenna_mask & ~mphy->chainmask)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
@ -319,15 +316,15 @@ mt7615_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
changed |= BIT(i);
}
mt7615_tm_update_params(dev, changed);
mt7615_tm_update_params(phy, changed);
return 0;
}
static int
mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
mt7615_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_phy *phy = mphy->priv;
void *rx, *rssi;
int i;
@ -335,15 +332,15 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rx)
return -ENOMEM;
if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset))
if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, phy->test.last_freq_offset))
return -ENOMEM;
rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI);
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_rcpi); i++)
if (nla_put_u8(msg, i, dev->test.last_rcpi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_rcpi); i++)
if (nla_put_u8(msg, i, phy->test.last_rcpi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);
@ -352,8 +349,8 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++)
if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_ib_rssi); i++)
if (nla_put_s8(msg, i, phy->test.last_ib_rssi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);
@ -362,8 +359,8 @@ mt7615_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++)
if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_wb_rssi); i++)
if (nla_put_s8(msg, i, phy->test.last_wb_rssi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);

View File

@ -29,7 +29,7 @@ static void mt7663u_stop(struct ieee80211_hw *hw)
del_timer_sync(&phy->roc_timer);
cancel_work_sync(&phy->roc_work);
cancel_delayed_work_sync(&phy->scan_work);
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
mt76u_stop_tx(&dev->mt76);
}
@ -47,11 +47,7 @@ static void mt7663u_init_work(struct work_struct *work)
if (mt7663u_mcu_init(dev))
return;
mt7615_mcu_set_eeprom(dev);
mt7615_mac_init(dev);
mt7615_phy_init(dev);
mt7615_mcu_del_wtbl_all(dev);
mt7615_check_offload_capability(dev);
mt7615_init_work(dev);
}
static int mt7663u_probe(struct usb_interface *usb_intf,
@ -173,7 +169,7 @@ static int mt7663u_suspend(struct usb_interface *intf, pm_message_t state)
mt7615_firmware_offload(dev)) {
int err;
err = mt7615_mcu_set_hif_suspend(dev, true);
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
if (err < 0)
return err;
}
@ -201,7 +197,7 @@ static int mt7663u_resume(struct usb_interface *intf)
if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state) &&
mt7615_firmware_offload(dev))
err = mt7615_mcu_set_hif_suspend(dev, false);
err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
return err;
}

View File

@ -0,0 +1,105 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT76_CONNAC_H
#define __MT76_CONNAC_H
#include "mt76.h"
#define MT76_CONNAC_SCAN_IE_LEN 600
#define MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL 10
#define MT76_CONNAC_MAX_SCHED_SCAN_SSID 10
#define MT76_CONNAC_MAX_SCAN_MATCH 16
#define MT76_CONNAC_COREDUMP_TIMEOUT (HZ / 20)
#define MT76_CONNAC_COREDUMP_SZ (128 * 1024)
enum {
CMD_CBW_20MHZ = IEEE80211_STA_RX_BW_20,
CMD_CBW_40MHZ = IEEE80211_STA_RX_BW_40,
CMD_CBW_80MHZ = IEEE80211_STA_RX_BW_80,
CMD_CBW_160MHZ = IEEE80211_STA_RX_BW_160,
CMD_CBW_10MHZ,
CMD_CBW_5MHZ,
CMD_CBW_8080MHZ,
CMD_HE_MCS_BW80 = 0,
CMD_HE_MCS_BW160,
CMD_HE_MCS_BW8080,
CMD_HE_MCS_BW_NUM
};
enum {
HW_BSSID_0 = 0x0,
HW_BSSID_1,
HW_BSSID_2,
HW_BSSID_3,
HW_BSSID_MAX = HW_BSSID_3,
EXT_BSSID_START = 0x10,
EXT_BSSID_1,
EXT_BSSID_15 = 0x1f,
EXT_BSSID_MAX = EXT_BSSID_15,
REPEATER_BSSID_START = 0x20,
REPEATER_BSSID_MAX = 0x3f,
};
struct mt76_connac_pm {
bool enable;
spinlock_t txq_lock;
struct {
struct mt76_wcid *wcid;
struct sk_buff *skb;
} tx_q[IEEE80211_NUM_ACS];
struct work_struct wake_work;
struct completion wake_cmpl;
struct delayed_work ps_work;
unsigned long last_activity;
unsigned long idle_timeout;
};
struct mt76_connac_coredump {
struct sk_buff_head msg_list;
struct delayed_work work;
unsigned long last_activity;
};
extern const struct wiphy_wowlan_support mt76_connac_wowlan_support;
static inline bool is_mt7921(struct mt76_dev *dev)
{
return mt76_chip(dev) == 0x7961;
}
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
struct mt76_connac_pm *pm);
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
struct mt76_wcid *wcid);
static inline void
mt76_connac_mutex_acquire(struct mt76_dev *dev, struct mt76_connac_pm *pm)
__acquires(&dev->mutex)
{
mutex_lock(&dev->mutex);
mt76_connac_pm_wake(&dev->phy, pm);
}
static inline void
mt76_connac_mutex_release(struct mt76_dev *dev, struct mt76_connac_pm *pm)
__releases(&dev->mutex)
{
mt76_connac_power_save_sched(&dev->phy, pm);
mutex_unlock(&dev->mutex);
}
void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
struct mt76_connac_pm *pm,
struct mt76_wcid *wcid,
struct sk_buff *skb);
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
struct mt76_connac_pm *pm);
#endif /* __MT76_CONNAC_H */

View File

@ -0,0 +1,119 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt76_connac.h"
int mt76_connac_pm_wake(struct mt76_phy *phy, struct mt76_connac_pm *pm)
{
struct mt76_dev *dev = phy->dev;
if (!pm->enable)
return 0;
if (!mt76_is_mmio(dev))
return 0;
if (!test_bit(MT76_STATE_PM, &phy->state))
return 0;
if (test_bit(MT76_HW_SCANNING, &phy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &phy->state))
return 0;
if (queue_work(dev->wq, &pm->wake_work))
reinit_completion(&pm->wake_cmpl);
if (!wait_for_completion_timeout(&pm->wake_cmpl, 3 * HZ)) {
ieee80211_wake_queues(phy->hw);
return -ETIMEDOUT;
}
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac_pm_wake);
void mt76_connac_power_save_sched(struct mt76_phy *phy,
struct mt76_connac_pm *pm)
{
struct mt76_dev *dev = phy->dev;
if (!mt76_is_mmio(dev))
return;
if (!pm->enable || !test_bit(MT76_STATE_RUNNING, &phy->state))
return;
pm->last_activity = jiffies;
if (test_bit(MT76_HW_SCANNING, &phy->state) ||
test_bit(MT76_HW_SCHED_SCANNING, &phy->state))
return;
if (!test_bit(MT76_STATE_PM, &phy->state))
queue_delayed_work(dev->wq, &pm->ps_work, pm->idle_timeout);
}
EXPORT_SYMBOL_GPL(mt76_connac_power_save_sched);
void mt76_connac_free_pending_tx_skbs(struct mt76_connac_pm *pm,
struct mt76_wcid *wcid)
{
int i;
spin_lock_bh(&pm->txq_lock);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
if (wcid && pm->tx_q[i].wcid != wcid)
continue;
dev_kfree_skb(pm->tx_q[i].skb);
pm->tx_q[i].skb = NULL;
}
spin_unlock_bh(&pm->txq_lock);
}
EXPORT_SYMBOL_GPL(mt76_connac_free_pending_tx_skbs);
void mt76_connac_pm_queue_skb(struct ieee80211_hw *hw,
struct mt76_connac_pm *pm,
struct mt76_wcid *wcid,
struct sk_buff *skb)
{
int qid = skb_get_queue_mapping(skb);
struct mt76_phy *phy = hw->priv;
spin_lock_bh(&pm->txq_lock);
if (!pm->tx_q[qid].skb) {
ieee80211_stop_queues(hw);
pm->tx_q[qid].wcid = wcid;
pm->tx_q[qid].skb = skb;
queue_work(phy->dev->wq, &pm->wake_work);
} else {
dev_kfree_skb(skb);
}
spin_unlock_bh(&pm->txq_lock);
}
EXPORT_SYMBOL_GPL(mt76_connac_pm_queue_skb);
void mt76_connac_pm_dequeue_skbs(struct mt76_phy *phy,
struct mt76_connac_pm *pm)
{
int i;
spin_lock_bh(&pm->txq_lock);
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
struct mt76_wcid *wcid = pm->tx_q[i].wcid;
struct ieee80211_sta *sta = NULL;
if (!pm->tx_q[i].skb)
continue;
if (wcid && wcid->sta)
sta = container_of((void *)wcid, struct ieee80211_sta,
drv_priv);
mt76_tx(phy, sta, wcid, pm->tx_q[i].skb);
pm->tx_q[i].skb = NULL;
}
spin_unlock_bh(&pm->txq_lock);
mt76_worker_schedule(&phy->dev->tx_worker);
}
EXPORT_SYMBOL_GPL(mt76_connac_pm_dequeue_skbs);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,979 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT76_CONNAC_MCU_H
#define __MT76_CONNAC_MCU_H
#include "mt76_connac.h"
struct tlv {
__le16 tag;
__le16 len;
} __packed;
/* sta_rec */
struct sta_ntlv_hdr {
u8 rsv[2];
__le16 tlv_num;
} __packed;
struct sta_req_hdr {
u8 bss_idx;
u8 wlan_idx_lo;
__le16 tlv_num;
u8 is_tlv_append;
u8 muar_idx;
u8 wlan_idx_hi;
u8 rsv;
} __packed;
struct sta_rec_basic {
__le16 tag;
__le16 len;
__le32 conn_type;
u8 conn_state;
u8 qos;
__le16 aid;
u8 peer_addr[ETH_ALEN];
#define EXTRA_INFO_VER BIT(0)
#define EXTRA_INFO_NEW BIT(1)
__le16 extra_info;
} __packed;
struct sta_rec_ht {
__le16 tag;
__le16 len;
__le16 ht_cap;
u16 rsv;
} __packed;
struct sta_rec_vht {
__le16 tag;
__le16 len;
__le32 vht_cap;
__le16 vht_rx_mcs_map;
__le16 vht_tx_mcs_map;
/* mt7921 */
u8 rts_bw_sig;
u8 rsv[3];
} __packed;
struct sta_rec_uapsd {
__le16 tag;
__le16 len;
u8 dac_map;
u8 tac_map;
u8 max_sp;
u8 rsv0;
__le16 listen_interval;
u8 rsv1[2];
} __packed;
struct sta_rec_ba {
__le16 tag;
__le16 len;
u8 tid;
u8 ba_type;
u8 amsdu;
u8 ba_en;
__le16 ssn;
__le16 winsize;
} __packed;
struct sta_rec_he {
__le16 tag;
__le16 len;
__le32 he_cap;
u8 t_frame_dur;
u8 max_ampdu_exp;
u8 bw_set;
u8 device_class;
u8 dcm_tx_mode;
u8 dcm_tx_max_nss;
u8 dcm_rx_mode;
u8 dcm_rx_max_nss;
u8 dcm_max_ru;
u8 punc_pream_rx;
u8 pkt_ext;
u8 rsv1;
__le16 max_nss_mcs[CMD_HE_MCS_BW_NUM];
u8 rsv2[2];
} __packed;
struct sta_rec_amsdu {
__le16 tag;
__le16 len;
u8 max_amsdu_num;
u8 max_mpdu_size;
u8 amsdu_en;
u8 rsv;
} __packed;
struct sta_rec_state {
__le16 tag;
__le16 len;
__le32 flags;
u8 state;
u8 vht_opmode;
u8 action;
u8 rsv[1];
} __packed;
#define HT_MCS_MASK_NUM 10
struct sta_rec_ra_info {
__le16 tag;
__le16 len;
__le16 legacy;
u8 rx_mcs_bitmask[HT_MCS_MASK_NUM];
} __packed;
struct sta_rec_phy {
__le16 tag;
__le16 len;
__le16 basic_rate;
u8 phy_type;
u8 ampdu;
u8 rts_policy;
u8 rcpi;
u8 rsv[2];
} __packed;
/* wtbl_rec */
struct wtbl_req_hdr {
u8 wlan_idx_lo;
u8 operation;
__le16 tlv_num;
u8 wlan_idx_hi;
u8 rsv[3];
} __packed;
struct wtbl_generic {
__le16 tag;
__le16 len;
u8 peer_addr[ETH_ALEN];
u8 muar_idx;
u8 skip_tx;
u8 cf_ack;
u8 qos;
u8 mesh;
u8 adm;
__le16 partial_aid;
u8 baf_en;
u8 aad_om;
} __packed;
struct wtbl_rx {
__le16 tag;
__le16 len;
u8 rcid;
u8 rca1;
u8 rca2;
u8 rv;
u8 rsv[4];
} __packed;
struct wtbl_ht {
__le16 tag;
__le16 len;
u8 ht;
u8 ldpc;
u8 af;
u8 mm;
u8 rsv[4];
} __packed;
struct wtbl_vht {
__le16 tag;
__le16 len;
u8 ldpc;
u8 dyn_bw;
u8 vht;
u8 txop_ps;
u8 rsv[4];
} __packed;
struct wtbl_tx_ps {
__le16 tag;
__le16 len;
u8 txps;
u8 rsv[3];
} __packed;
struct wtbl_hdr_trans {
__le16 tag;
__le16 len;
u8 to_ds;
u8 from_ds;
u8 disable_rx_trans;
u8 rsv;
} __packed;
struct wtbl_ba {
__le16 tag;
__le16 len;
/* common */
u8 tid;
u8 ba_type;
u8 rsv0[2];
/* originator only */
__le16 sn;
u8 ba_en;
u8 ba_winsize_idx;
__le16 ba_winsize;
/* recipient only */
u8 peer_addr[ETH_ALEN];
u8 rst_ba_tid;
u8 rst_ba_sel;
u8 rst_ba_sb;
u8 band_idx;
u8 rsv1[4];
} __packed;
struct wtbl_smps {
__le16 tag;
__le16 len;
u8 smps;
u8 rsv[3];
} __packed;
/* mt7615 only */
struct wtbl_bf {
__le16 tag;
__le16 len;
u8 ibf;
u8 ebf;
u8 ibf_vht;
u8 ebf_vht;
u8 gid;
u8 pfmu_idx;
u8 rsv[2];
} __packed;
struct wtbl_pn {
__le16 tag;
__le16 len;
u8 pn[6];
u8 rsv[2];
} __packed;
struct wtbl_spe {
__le16 tag;
__le16 len;
u8 spe_idx;
u8 rsv[3];
} __packed;
struct wtbl_raw {
__le16 tag;
__le16 len;
u8 wtbl_idx;
u8 dw;
u8 rsv[2];
__le32 msk;
__le32 val;
} __packed;
#define MT76_CONNAC_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_generic) + \
sizeof(struct wtbl_rx) + \
sizeof(struct wtbl_ht) + \
sizeof(struct wtbl_vht) + \
sizeof(struct wtbl_tx_ps) + \
sizeof(struct wtbl_hdr_trans) +\
sizeof(struct wtbl_ba) + \
sizeof(struct wtbl_bf) + \
sizeof(struct wtbl_smps) + \
sizeof(struct wtbl_pn) + \
sizeof(struct wtbl_spe))
#define MT76_CONNAC_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_he) + \
sizeof(struct sta_rec_ba) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct tlv) + \
MT76_CONNAC_WTBL_UPDATE_MAX_SIZE)
#define MT76_CONNAC_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_ba))
enum {
STA_REC_BASIC,
STA_REC_RA,
STA_REC_RA_CMM_INFO,
STA_REC_RA_UPDATE,
STA_REC_BF,
STA_REC_AMSDU,
STA_REC_BA,
STA_REC_STATE,
STA_REC_TX_PROC, /* for hdr trans and CSO in CR4 */
STA_REC_HT,
STA_REC_VHT,
STA_REC_APPS,
STA_REC_KEY,
STA_REC_WTBL,
STA_REC_HE,
STA_REC_HW_AMSDU,
STA_REC_WTBL_AADOM,
STA_REC_KEY_V2,
STA_REC_MURU,
STA_REC_MUEDCA,
STA_REC_BFEE,
STA_REC_PHY = 0x15,
STA_REC_MAX_NUM
};
enum {
WTBL_GENERIC,
WTBL_RX,
WTBL_HT,
WTBL_VHT,
WTBL_PEER_PS, /* not used */
WTBL_TX_PS,
WTBL_HDR_TRANS,
WTBL_SEC_KEY,
WTBL_BA,
WTBL_RDG, /* obsoleted */
WTBL_PROTECT, /* not used */
WTBL_CLEAR, /* not used */
WTBL_BF,
WTBL_SMPS,
WTBL_RAW_DATA, /* debug only */
WTBL_PN,
WTBL_SPE,
WTBL_MAX_NUM
};
#define STA_TYPE_STA BIT(0)
#define STA_TYPE_AP BIT(1)
#define STA_TYPE_ADHOC BIT(2)
#define STA_TYPE_WDS BIT(4)
#define STA_TYPE_BC BIT(5)
#define NETWORK_INFRA BIT(16)
#define NETWORK_P2P BIT(17)
#define NETWORK_IBSS BIT(18)
#define NETWORK_WDS BIT(21)
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P)
#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS)
#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS)
#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA)
#define CONN_STATE_DISCONNECT 0
#define CONN_STATE_CONNECT 1
#define CONN_STATE_PORT_SECURE 2
/* HE MAC */
#define STA_REC_HE_CAP_HTC BIT(0)
#define STA_REC_HE_CAP_BQR BIT(1)
#define STA_REC_HE_CAP_BSR BIT(2)
#define STA_REC_HE_CAP_OM BIT(3)
#define STA_REC_HE_CAP_AMSDU_IN_AMPDU BIT(4)
/* HE PHY */
#define STA_REC_HE_CAP_DUAL_BAND BIT(5)
#define STA_REC_HE_CAP_LDPC BIT(6)
#define STA_REC_HE_CAP_TRIG_CQI_FK BIT(7)
#define STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE BIT(8)
/* STBC */
#define STA_REC_HE_CAP_LE_EQ_80M_TX_STBC BIT(9)
#define STA_REC_HE_CAP_LE_EQ_80M_RX_STBC BIT(10)
#define STA_REC_HE_CAP_GT_80M_TX_STBC BIT(11)
#define STA_REC_HE_CAP_GT_80M_RX_STBC BIT(12)
/* GI */
#define STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI BIT(13)
#define STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI BIT(14)
#define STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI BIT(15)
#define STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI BIT(16)
#define STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI BIT(17)
/* 242 TONE */
#define STA_REC_HE_CAP_BW20_RU242_SUPPORT BIT(18)
#define STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242 BIT(19)
#define STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242 BIT(20)
#define PHY_MODE_A BIT(0)
#define PHY_MODE_B BIT(1)
#define PHY_MODE_G BIT(2)
#define PHY_MODE_GN BIT(3)
#define PHY_MODE_AN BIT(4)
#define PHY_MODE_AC BIT(5)
#define PHY_MODE_AX_24G BIT(6)
#define PHY_MODE_AX_5G BIT(7)
#define PHY_MODE_AX_6G BIT(8)
#define MODE_CCK BIT(0)
#define MODE_OFDM BIT(1)
#define MODE_HT BIT(2)
#define MODE_VHT BIT(3)
#define MODE_HE BIT(4)
enum {
PHY_TYPE_HR_DSSS_INDEX = 0,
PHY_TYPE_ERP_INDEX,
PHY_TYPE_ERP_P2P_INDEX,
PHY_TYPE_OFDM_INDEX,
PHY_TYPE_HT_INDEX,
PHY_TYPE_VHT_INDEX,
PHY_TYPE_HE_INDEX,
PHY_TYPE_INDEX_NUM
};
#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX)
#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX)
#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX)
#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX)
#define PHY_TYPE_BIT_VHT BIT(PHY_TYPE_VHT_INDEX)
#define PHY_TYPE_BIT_HE BIT(PHY_TYPE_HE_INDEX)
#define MT_WTBL_RATE_TX_MODE GENMASK(9, 6)
#define MT_WTBL_RATE_MCS GENMASK(5, 0)
#define MT_WTBL_RATE_NSS GENMASK(12, 10)
#define MT_WTBL_RATE_HE_GI GENMASK(7, 4)
#define MT_WTBL_RATE_GI GENMASK(3, 0)
#define MT_WTBL_W5_CHANGE_BW_RATE GENMASK(7, 5)
#define MT_WTBL_W5_SHORT_GI_20 BIT(8)
#define MT_WTBL_W5_SHORT_GI_40 BIT(9)
#define MT_WTBL_W5_SHORT_GI_80 BIT(10)
#define MT_WTBL_W5_SHORT_GI_160 BIT(11)
#define MT_WTBL_W5_BW_CAP GENMASK(13, 12)
#define MT_WTBL_W5_MPDU_FAIL_COUNT GENMASK(25, 23)
#define MT_WTBL_W5_MPDU_OK_COUNT GENMASK(28, 26)
#define MT_WTBL_W5_RATE_IDX GENMASK(31, 29)
enum {
WTBL_RESET_AND_SET = 1,
WTBL_SET,
WTBL_QUERY,
WTBL_RESET_ALL
};
enum {
MT_BA_TYPE_INVALID,
MT_BA_TYPE_ORIGINATOR,
MT_BA_TYPE_RECIPIENT
};
enum {
RST_BA_MAC_TID_MATCH,
RST_BA_MAC_MATCH,
RST_BA_NO_MATCH
};
enum {
DEV_INFO_ACTIVE,
DEV_INFO_MAX_NUM
};
#define MCU_CMD_ACK BIT(0)
#define MCU_CMD_UNI BIT(1)
#define MCU_CMD_QUERY BIT(2)
#define MCU_CMD_UNI_EXT_ACK (MCU_CMD_ACK | MCU_CMD_UNI | \
MCU_CMD_QUERY)
#define MCU_FW_PREFIX BIT(31)
#define MCU_UNI_PREFIX BIT(30)
#define MCU_CE_PREFIX BIT(29)
#define MCU_QUERY_PREFIX BIT(28)
#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX | \
MCU_CE_PREFIX | MCU_QUERY_PREFIX)
#define MCU_QUERY_MASK BIT(16)
enum {
MCU_EXT_CMD_EFUSE_ACCESS = 0x01,
MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
MCU_EXT_CMD_BSS_INFO_UPDATE = 0x26,
MCU_EXT_CMD_EDCA_UPDATE = 0x27,
MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
MCU_EXT_CMD_GET_TEMP = 0x2c,
MCU_EXT_CMD_WTBL_UPDATE = 0x32,
MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
MCU_EXT_CMD_ATE_CTRL = 0x3d,
MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
MCU_EXT_CMD_DBDC_CTRL = 0x45,
MCU_EXT_CMD_MAC_INIT_CTRL = 0x46,
MCU_EXT_CMD_RX_HDR_TRANS = 0x47,
MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
MCU_EXT_CMD_SET_RX_PATH = 0x4e,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_RXDCOC_CAL = 0x59,
MCU_EXT_CMD_TXDPD_CAL = 0x60,
MCU_EXT_CMD_SET_RDD_TH = 0x7c,
MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
};
enum {
MCU_UNI_CMD_DEV_INFO_UPDATE = MCU_UNI_PREFIX | 0x01,
MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02,
MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
MCU_UNI_CMD_SUSPEND = MCU_UNI_PREFIX | 0x05,
MCU_UNI_CMD_OFFLOAD = MCU_UNI_PREFIX | 0x06,
MCU_UNI_CMD_HIF_CTRL = MCU_UNI_PREFIX | 0x07,
};
enum {
MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01,
MCU_CMD_FW_START_REQ = MCU_FW_PREFIX | 0x02,
MCU_CMD_INIT_ACCESS_REG = 0x3,
MCU_CMD_NIC_POWER_CTRL = MCU_FW_PREFIX | 0x4,
MCU_CMD_PATCH_START_REQ = MCU_FW_PREFIX | 0x05,
MCU_CMD_PATCH_FINISH_REQ = MCU_FW_PREFIX | 0x07,
MCU_CMD_PATCH_SEM_CONTROL = MCU_FW_PREFIX | 0x10,
MCU_CMD_EXT_CID = 0xed,
MCU_CMD_FW_SCATTER = MCU_FW_PREFIX | 0xee,
MCU_CMD_RESTART_DL_REQ = MCU_FW_PREFIX | 0xef,
};
/* offload mcu commands */
enum {
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
MCU_CMD_SET_PS_PROFILE = MCU_CE_PREFIX | 0x05,
MCU_CMD_SET_CHAN_DOMAIN = MCU_CE_PREFIX | 0x0f,
MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16,
MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17,
MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b,
MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1d,
MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33,
MCU_CMD_SET_RATE_TX_POWER = MCU_CE_PREFIX | 0x5d,
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
MCU_CMD_REG_WRITE = MCU_CE_PREFIX | 0xc0,
MCU_CMD_REG_READ = MCU_CE_PREFIX | MCU_QUERY_MASK | 0xc0,
MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca,
MCU_CMD_FWLOG_2_HOST = MCU_CE_PREFIX | 0xc5,
MCU_CMD_GET_WTBL = MCU_CE_PREFIX | 0xcd,
};
enum {
PATCH_SEM_RELEASE,
PATCH_SEM_GET
};
enum {
UNI_BSS_INFO_BASIC = 0,
UNI_BSS_INFO_RLM = 2,
UNI_BSS_INFO_HE_BASIC = 5,
UNI_BSS_INFO_BCN_CONTENT = 7,
UNI_BSS_INFO_QBSS = 15,
UNI_BSS_INFO_UAPSD = 19,
UNI_BSS_INFO_PS = 21,
UNI_BSS_INFO_BCNFT = 22,
};
enum {
UNI_OFFLOAD_OFFLOAD_ARP,
UNI_OFFLOAD_OFFLOAD_ND,
UNI_OFFLOAD_OFFLOAD_GTK_REKEY,
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};
enum {
UNI_SUSPEND_MODE_SETTING,
UNI_SUSPEND_WOW_CTRL,
UNI_SUSPEND_WOW_GPIO_PARAM,
UNI_SUSPEND_WOW_WAKEUP_PORT,
UNI_SUSPEND_WOW_PATTERN,
};
enum {
WOW_USB = 1,
WOW_PCIE = 2,
WOW_GPIO = 3,
};
struct mt76_connac_bss_basic_tlv {
__le16 tag;
__le16 len;
u8 active;
u8 omac_idx;
u8 hw_bss_idx;
u8 band_idx;
__le32 conn_type;
u8 conn_state;
u8 wmm_idx;
u8 bssid[ETH_ALEN];
__le16 bmc_tx_wlan_idx;
__le16 bcn_interval;
u8 dtim_period;
u8 phymode; /* bit(0): A
* bit(1): B
* bit(2): G
* bit(3): GN
* bit(4): AN
* bit(5): AC
*/
__le16 sta_idx;
u8 nonht_basic_phy;
u8 pad[3];
} __packed;
struct mt76_connac_bss_qos_tlv {
__le16 tag;
__le16 len;
u8 qos;
u8 pad[3];
} __packed;
struct mt76_connac_beacon_loss_event {
u8 bss_idx;
u8 reason;
u8 pad[2];
} __packed;
struct mt76_connac_mcu_bss_event {
u8 bss_idx;
u8 is_absent;
u8 free_quota;
u8 pad;
} __packed;
struct mt76_connac_mcu_scan_ssid {
__le32 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
} __packed;
struct mt76_connac_mcu_scan_channel {
u8 band; /* 1: 2.4GHz
* 2: 5.0GHz
* Others: Reserved
*/
u8 channel_num;
} __packed;
struct mt76_connac_mcu_scan_match {
__le32 rssi_th;
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
u8 rsv[3];
} __packed;
struct mt76_connac_hw_scan_req {
u8 seq_num;
u8 bss_idx;
u8 scan_type; /* 0: PASSIVE SCAN
* 1: ACTIVE SCAN
*/
u8 ssid_type; /* BIT(0) wildcard SSID
* BIT(1) P2P wildcard SSID
* BIT(2) specified SSID + wildcard SSID
* BIT(2) + ssid_type_ext BIT(0) specified SSID only
*/
u8 ssids_num;
u8 probe_req_num; /* Number of probe request for each SSID */
u8 scan_func; /* BIT(0) Enable random MAC scan
* BIT(1) Disable DBDC scan type 1~3.
* BIT(2) Use DBDC scan type 3 (dedicated one RF to scan).
*/
u8 version; /* 0: Not support fields after ies.
* 1: Support fields after ies.
*/
struct mt76_connac_mcu_scan_ssid ssids[4];
__le16 probe_delay_time;
__le16 channel_dwell_time; /* channel Dwell interval */
__le16 timeout_value;
u8 channel_type; /* 0: Full channels
* 1: Only 2.4GHz channels
* 2: Only 5GHz channels
* 3: P2P social channel only (channel #1, #6 and #11)
* 4: Specified channels
* Others: Reserved
*/
u8 channels_num; /* valid when channel_type is 4 */
/* valid when channels_num is set */
struct mt76_connac_mcu_scan_channel channels[32];
__le16 ies_len;
u8 ies[MT76_CONNAC_SCAN_IE_LEN];
/* following fields are valid if version > 0 */
u8 ext_channels_num;
u8 ext_ssids_num;
__le16 channel_min_dwell_time;
struct mt76_connac_mcu_scan_channel ext_channels[32];
struct mt76_connac_mcu_scan_ssid ext_ssids[6];
u8 bssid[ETH_ALEN];
u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */
u8 pad[63];
u8 ssid_type_ext;
} __packed;
#define MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64
struct mt76_connac_hw_scan_done {
u8 seq_num;
u8 sparse_channel_num;
struct mt76_connac_mcu_scan_channel sparse_channel;
u8 complete_channel_num;
u8 current_state;
u8 version;
u8 pad;
__le32 beacon_scan_num;
u8 pno_enabled;
u8 pad2[3];
u8 sparse_channel_valid_num;
u8 pad3[3];
u8 channel_num[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
/* idle format for channel_idle_time
* 0: first bytes: idle time(ms) 2nd byte: dwell time(ms)
* 1: first bytes: idle time(8ms) 2nd byte: dwell time(8ms)
* 2: dwell time (16us)
*/
__le16 channel_idle_time[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
/* beacon and probe response count */
u8 beacon_probe_num[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
u8 mdrdy_count[MT76_CONNAC_SCAN_DONE_EVENT_MAX_CHANNEL_NUM];
__le32 beacon_2g_num;
__le32 beacon_5g_num;
} __packed;
struct mt76_connac_sched_scan_req {
u8 version;
u8 seq_num;
u8 stop_on_match;
u8 ssids_num;
u8 match_num;
u8 pad;
__le16 ie_len;
struct mt76_connac_mcu_scan_ssid ssids[MT76_CONNAC_MAX_SCHED_SCAN_SSID];
struct mt76_connac_mcu_scan_match match[MT76_CONNAC_MAX_SCAN_MATCH];
u8 channel_type;
u8 channels_num;
u8 intervals_num;
u8 scan_func; /* BIT(0) eable random mac address */
struct mt76_connac_mcu_scan_channel channels[64];
__le16 intervals[MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL];
u8 random_mac[ETH_ALEN]; /* valid when BIT(0) in scan_func is set */
u8 pad2[58];
} __packed;
struct mt76_connac_sched_scan_done {
u8 seq_num;
u8 status; /* 0: ssid found */
__le16 pad;
} __packed;
struct bss_info_uni_he {
__le16 tag;
__le16 len;
__le16 he_rts_thres;
u8 he_pe_duration;
u8 su_disable;
__le16 max_nss_mcs[CMD_HE_MCS_BW_NUM];
u8 rsv[2];
} __packed;
struct mt76_connac_gtk_rekey_tlv {
__le16 tag;
__le16 len;
u8 kek[NL80211_KEK_LEN];
u8 kck[NL80211_KCK_LEN];
u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
u8 rekey_mode; /* 0: rekey offload enable
* 1: rekey offload disable
* 2: rekey update
*/
u8 keyid;
u8 pad[2];
__le32 proto; /* WPA-RSN-WAPI-OPSN */
__le32 pairwise_cipher;
__le32 group_cipher;
__le32 key_mgmt; /* NONE-PSK-IEEE802.1X */
__le32 mgmt_group_cipher;
u8 option; /* 1: rekey data update without enabling offload */
u8 reserverd[3];
} __packed;
#define MT76_CONNAC_WOW_MASK_MAX_LEN 16
#define MT76_CONNAC_WOW_PATTEN_MAX_LEN 128
struct mt76_connac_wow_pattern_tlv {
__le16 tag;
__le16 len;
u8 index; /* pattern index */
u8 enable; /* 0: disable
* 1: enable
*/
u8 data_len; /* pattern length */
u8 pad;
u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
u8 rsv[4];
} __packed;
struct mt76_connac_wow_ctrl_tlv {
__le16 tag;
__le16 len;
u8 cmd; /* 0x1: PM_WOWLAN_REQ_START
* 0x2: PM_WOWLAN_REQ_STOP
* 0x3: PM_WOWLAN_PARAM_CLEAR
*/
u8 trigger; /* 0: NONE
* BIT(0): NL80211_WOWLAN_TRIG_MAGIC_PKT
* BIT(1): NL80211_WOWLAN_TRIG_ANY
* BIT(2): NL80211_WOWLAN_TRIG_DISCONNECT
* BIT(3): NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE
* BIT(4): BEACON_LOST
* BIT(5): NL80211_WOWLAN_TRIG_NET_DETECT
*/
u8 wakeup_hif; /* 0x0: HIF_SDIO
* 0x1: HIF_USB
* 0x2: HIF_PCIE
* 0x3: HIF_GPIO
*/
u8 pad;
u8 rsv[4];
} __packed;
struct mt76_connac_wow_gpio_param_tlv {
__le16 tag;
__le16 len;
u8 gpio_pin;
u8 trigger_lvl;
u8 pad[2];
__le32 gpio_interval;
u8 rsv[4];
} __packed;
struct mt76_connac_arpns_tlv {
__le16 tag;
__le16 len;
u8 mode;
u8 ips_num;
u8 option;
u8 pad[1];
} __packed;
struct mt76_connac_suspend_tlv {
__le16 tag;
__le16 len;
u8 enable; /* 0: suspend mode disabled
* 1: suspend mode enabled
*/
u8 mdtim; /* LP parameter */
u8 wow_suspend; /* 0: update by origin policy
* 1: update by wow dtim
*/
u8 pad[5];
} __packed;
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)
static inline void
mt76_connac_mcu_get_wlan_idx(struct mt76_dev *dev, struct mt76_wcid *wcid,
u8 *wlan_idx_lo, u8 *wlan_idx_hi)
{
*wlan_idx_hi = 0;
if (is_mt7921(dev)) {
*wlan_idx_lo = wcid ? to_wcid_lo(wcid->idx) : 0;
*wlan_idx_hi = wcid ? to_wcid_hi(wcid->idx) : 0;
} else {
*wlan_idx_lo = wcid ? wcid->idx : 0;
}
}
struct sk_buff *
mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
struct mt76_wcid *wcid);
struct wtbl_req_hdr *
mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid,
int cmd, void *sta_wtbl, struct sk_buff **skb);
struct tlv *mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag,
int len, void *sta_ntlv,
void *sta_wtbl);
static inline struct tlv *
mt76_connac_mcu_add_tlv(struct sk_buff *skb, int tag, int len)
{
return mt76_connac_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL);
}
int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy);
int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif);
void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enable);
void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, void *sta_wtbl,
void *wtbl_tlv);
void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,
struct ieee80211_sta *sta,
struct ieee80211_vif *vif);
void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_sta *sta, void *sta_wtbl,
void *wtbl_tlv);
void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_ampdu_params *params,
bool enable, bool tx, void *sta_wtbl,
void *wtbl_tlv);
void mt76_connac_mcu_sta_ba_tlv(struct sk_buff *skb,
struct ieee80211_ampdu_params *params,
bool enable, bool tx);
int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct mt76_wcid *wcid,
bool enable);
int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
struct ieee80211_ampdu_params *params,
bool enable, bool tx);
int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct mt76_wcid *wcid,
bool enable);
int mt76_connac_mcu_add_sta_cmd(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct mt76_wcid *wcid,
bool enable, int cmd);
void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band);
int mt76_connac_mcu_set_mac_enable(struct mt76_dev *dev, int band, bool enable,
bool hdr_trans);
int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
u32 mode);
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);
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,
struct ieee80211_vif *vif);
int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *sreq);
int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy,
struct ieee80211_vif *vif,
bool enable);
int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *key);
int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend);
void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
struct mt76_connac_coredump *coredump);
#endif /* __MT76_CONNAC_MCU_H */

View File

@ -16,7 +16,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
mt76x02_mac_start(dev);
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work,
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);
@ -28,7 +28,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw)
static void mt76x0e_stop_hw(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
clear_bit(MT76_RESTART, &dev->mphy.state);
if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY,

View File

@ -82,7 +82,7 @@ static void mt76x0u_stop(struct ieee80211_hw *hw)
clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
mt76u_stop_tx(&dev->mt76);
mt76x02u_exit_beacon_config(dev);
@ -108,7 +108,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
return ret;
mt76x0_phy_calibrate(dev, true);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mt76.mac_work,
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
MT_CALIBRATE_INTERVAL);

View File

@ -82,8 +82,6 @@ struct mt76x02_dev {
struct mutex phy_mutex;
u16 chainmask;
u8 txdone_seq;
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
spinlock_t txstatus_fifo_lock;

View File

@ -345,7 +345,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi,
u16 txwi_flags = 0;
u8 nss;
s8 txpwr_adj, max_txpwr_adj;
u8 ccmp_pn[8], nstreams = dev->chainmask & 0xf;
u8 ccmp_pn[8], nstreams = dev->mphy.chainmask & 0xf;
memset(txwi, 0, sizeof(*txwi));
@ -685,7 +685,7 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev,
status->rate_idx = idx;
break;
case MT_PHY_TYPE_VHT: {
u8 n_rxstream = dev->chainmask & 0xf;
u8 n_rxstream = dev->mphy.chainmask & 0xf;
status->encoding = RX_ENC_VHT;
status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
@ -777,7 +777,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb,
u16 rate = le16_to_cpu(rxwi->rate);
u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
int pad_len = 0, nstreams = dev->chainmask & 0xf;
int pad_len = 0, nstreams = dev->mphy.chainmask & 0xf;
s8 signal;
u8 pn_len;
u8 wcid;
@ -1162,7 +1162,7 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)
void mt76x02_mac_work(struct work_struct *work)
{
struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
mt76.mac_work.work);
mphy.mac_work.work);
int i, idx;
mutex_lock(&dev->mt76.mutex);
@ -1185,7 +1185,7 @@ void mt76x02_mac_work(struct work_struct *work)
mt76_tx_status_check(&dev->mt76, NULL, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
}

View File

@ -416,7 +416,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev)
memset(msta, 0, sizeof(*msta));
}
dev->mphy.vif_mask = 0;
dev->mt76.vif_mask = 0;
dev->mt76.beacon_mask = 0;
}

View File

@ -16,7 +16,7 @@ void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev)
val = mt76_rr(dev, MT_BBP(AGC, 0));
val &= ~BIT(4);
switch (dev->chainmask & 0xf) {
switch (dev->mphy.chainmask & 0xf) {
case 2:
val |= BIT(3);
break;
@ -35,7 +35,7 @@ void mt76x02_phy_set_txdac(struct mt76x02_dev *dev)
{
int txpath;
txpath = (dev->chainmask >> 8) & 0xf;
txpath = (dev->mphy.chainmask >> 8) & 0xf;
switch (txpath) {
case 2:
mt76_set(dev, MT_BBP(TXBE, 5), 0x3);

View File

@ -149,7 +149,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
struct ieee80211_hw *hw = mt76_hw(dev);
struct wiphy *wiphy = hw->wiphy;
INIT_DELAYED_WORK(&dev->mt76.mac_work, mt76x02_mac_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt76x02_mac_work);
hw->queues = 4;
hw->max_rates = 1;
@ -197,10 +197,10 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
IEEE80211_HT_CAP_LDPC_CODING;
dev->mphy.sband_5g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING;
dev->chainmask = 0x202;
dev->mphy.chainmask = 0x202;
dev->mphy.antenna_mask = 3;
} else {
dev->chainmask = 0x101;
dev->mphy.chainmask = 0x101;
dev->mphy.antenna_mask = 1;
}
}
@ -304,7 +304,7 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
unsigned int idx = 0;
/* Allow to change address in HW if we create first interface. */
if (!dev->mphy.vif_mask &&
if (!dev->mt76.vif_mask &&
(((vif->addr[0] ^ dev->mphy.macaddr[0]) & ~GENMASK(4, 1)) ||
memcmp(vif->addr + 1, dev->mphy.macaddr + 1, ETH_ALEN - 1)))
mt76x02_mac_setaddr(dev, vif->addr);
@ -329,11 +329,11 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
idx += 8;
/* vif is already set or idx is 8 for AP/Mesh/... */
if (dev->mphy.vif_mask & BIT(idx) ||
if (dev->mt76.vif_mask & BIT(idx) ||
(vif->type != NL80211_IFTYPE_STATION && idx > 7))
return -EBUSY;
dev->mphy.vif_mask |= BIT(idx);
dev->mt76.vif_mask |= BIT(idx);
mt76x02_vif_init(dev, vif, idx);
return 0;
@ -346,7 +346,7 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw,
struct mt76x02_dev *dev = hw->priv;
struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
dev->mphy.vif_mask &= ~BIT(mvif->idx);
dev->mt76.vif_mask &= ~BIT(mvif->idx);
}
EXPORT_SYMBOL_GPL(mt76x02_remove_interface);

View File

@ -29,7 +29,7 @@ int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
.idx = channel,
.scan = scan,
.bw = bw,
.chainmask = cpu_to_le16(dev->chainmask),
.chainmask = cpu_to_le16(dev->mphy.chainmask),
};
/* first set the channel without the extension channel info */

View File

@ -271,7 +271,7 @@ static int mt76x2_init_hardware(struct mt76x02_dev *dev)
void mt76x2_stop_hardware(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
cancel_delayed_work_sync(&dev->wdt_work);
clear_bit(MT76_RESTART, &dev->mphy.state);
mt76x02_mcu_set_radio_state(dev, false);

View File

@ -14,7 +14,7 @@ mt76x2_start(struct ieee80211_hw *hw)
mt76x02_mac_start(dev);
mt76x2_phy_start(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work,
MT_WATCHDOG_TIME);
@ -116,7 +116,7 @@ static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
mutex_lock(&dev->mt76.mutex);
dev->chainmask = (tx_ant == 3) ? 0x202 : 0x101;
dev->mphy.chainmask = (tx_ant == 3) ? 0x202 : 0x101;
dev->mphy.antenna_mask = tx_ant;
mt76_set_stream_caps(&dev->mphy, true);

View File

@ -236,7 +236,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
void mt76x2u_stop_hw(struct mt76x02_dev *dev)
{
cancel_delayed_work_sync(&dev->cal_work);
cancel_delayed_work_sync(&dev->mt76.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
mt76x2u_mac_stop(dev);
}

View File

@ -15,7 +15,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw)
if (ret)
return ret;
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT_MAC_WORK_INTERVAL);
set_bit(MT76_STATE_RUNNING, &dev->mphy.state);

View File

@ -6,6 +6,32 @@
/** global debugfs **/
static int
mt7915_implicit_txbf_set(void *data, u64 val)
{
struct mt7915_dev *dev = data;
if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
return -EBUSY;
dev->ibf = !!val;
return mt7915_mcu_set_txbf_type(dev);
}
static int
mt7915_implicit_txbf_get(void *data, u64 *val)
{
struct mt7915_dev *dev = data;
*val = dev->ibf;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7915_implicit_txbf_get,
mt7915_implicit_txbf_set, "%lld\n");
/* test knob of system layer 1/2 error recovery */
static int mt7915_ser_trigger_set(void *data, u64 val)
{
@ -355,6 +381,8 @@ int mt7915_init_debugfs(struct mt7915_dev *dev)
mt7915_queues_acq);
debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("implicit_txbf", 0600, dir, dev,
&fops_implicit_txbf);
debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern);
/* test knobs */
debugfs_create_file("radar_trigger", 0200, dir, dev,

View File

@ -73,34 +73,41 @@ static int mt7915_poll_tx(struct napi_struct *napi, int budget)
return 0;
}
void mt7915_dma_prefetch(struct mt7915_dev *dev)
static void __mt7915_dma_prefetch(struct mt7915_dev *dev, u32 ofs)
{
#define PREFETCH(base, depth) ((base) << 16 | (depth))
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x80, 0x0));
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL + ofs, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING1_EXT_CTRL + ofs, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL + ofs, PREFETCH(0x80, 0x0));
mt76_wr(dev, MT_WFDMA1_TX_RING0_EXT_CTRL, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING1_EXT_CTRL, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING2_EXT_CTRL, PREFETCH(0x100, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING3_EXT_CTRL, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING4_EXT_CTRL, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING5_EXT_CTRL, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING6_EXT_CTRL, PREFETCH(0x200, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING7_EXT_CTRL, PREFETCH(0x240, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING0_EXT_CTRL + ofs, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING1_EXT_CTRL + ofs, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING2_EXT_CTRL + ofs, PREFETCH(0x100, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING3_EXT_CTRL + ofs, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING4_EXT_CTRL + ofs, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING5_EXT_CTRL + ofs, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING6_EXT_CTRL + ofs, PREFETCH(0x200, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING7_EXT_CTRL + ofs, PREFETCH(0x240, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING16_EXT_CTRL, PREFETCH(0x280, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING17_EXT_CTRL, PREFETCH(0x2c0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING18_EXT_CTRL, PREFETCH(0x300, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING19_EXT_CTRL, PREFETCH(0x340, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING20_EXT_CTRL, PREFETCH(0x380, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING21_EXT_CTRL, PREFETCH(0x3c0, 0x0));
mt76_wr(dev, MT_WFDMA1_TX_RING16_EXT_CTRL + ofs, PREFETCH(0x280, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING17_EXT_CTRL + ofs, PREFETCH(0x2c0, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING18_EXT_CTRL + ofs, PREFETCH(0x300, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING19_EXT_CTRL + ofs, PREFETCH(0x340, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING20_EXT_CTRL + ofs, PREFETCH(0x380, 0x4));
mt76_wr(dev, MT_WFDMA1_TX_RING21_EXT_CTRL + ofs, PREFETCH(0x3c0, 0x0));
mt76_wr(dev, MT_WFDMA1_RX_RING0_EXT_CTRL, PREFETCH(0x3c0, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING1_EXT_CTRL, PREFETCH(0x400, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING2_EXT_CTRL, PREFETCH(0x440, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL, PREFETCH(0x480, 0x0));
mt76_wr(dev, MT_WFDMA1_RX_RING0_EXT_CTRL + ofs, PREFETCH(0x3c0, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING1_EXT_CTRL + ofs, PREFETCH(0x400, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING2_EXT_CTRL + ofs, PREFETCH(0x440, 0x4));
mt76_wr(dev, MT_WFDMA1_RX_RING3_EXT_CTRL + ofs, PREFETCH(0x480, 0x0));
}
void mt7915_dma_prefetch(struct mt7915_dev *dev)
{
__mt7915_dma_prefetch(dev, 0);
if (dev->hif2)
__mt7915_dma_prefetch(dev, MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE);
}
static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
@ -204,6 +211,7 @@ int mt7915_dma_init(struct mt7915_dev *dev)
/* Increase buffer size to receive large VHT/HE MPDUs */
struct mt76_bus_ops *bus_ops;
int rx_buf_size = MT_RX_BUF_SIZE * 2;
u32 hif1_ofs = 0;
int ret;
dev->bus_ops = dev->mt76.bus;
@ -219,14 +227,14 @@ int mt7915_dma_init(struct mt7915_dev *dev)
mt76_dma_attach(&dev->mt76);
if (dev->hif2)
hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE;
/* configure global setting */
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
/* configure perfetch settings */
mt7915_dma_prefetch(dev);
/* reset dma idx */
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR, ~0);
@ -235,6 +243,21 @@ int mt7915_dma_init(struct mt7915_dev *dev)
mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0, 0);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
MT_WFDMA1_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA1_GLO_CFG_OMIT_RX_INFO);
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR + hif1_ofs, ~0);
mt76_wr(dev, MT_WFDMA1_RST_DTX_PTR + hif1_ofs, ~0);
mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0 + hif1_ofs, 0);
mt76_wr(dev, MT_WFDMA1_PRI_DLY_INT_CFG0 + hif1_ofs, 0);
}
/* configure perfetch settings */
mt7915_dma_prefetch(dev);
/* init tx queue */
ret = mt7915_init_tx_queues(&dev->phy, MT7915_TXQ_BAND0,
MT7915_TX_RING_SIZE);
@ -283,7 +306,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
if (dev->dbdc_support) {
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT],
MT7915_RXQ_BAND1, MT7915_RX_RING_SIZE,
rx_buf_size, MT_RX_DATA_RING_BASE);
rx_buf_size,
MT_RX_DATA_RING_BASE + hif1_ofs);
if (ret)
return ret;
/* event from WA */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_EXT_WA],
MT7915_RXQ_MCU_WA_EXT,
MT7915_RX_MCU_RING_SIZE,
rx_buf_size,
MT_RX_EVENT_RING_BASE + hif1_ofs);
if (ret)
return ret;
}
@ -326,6 +359,17 @@ int mt7915_dma_init(struct mt7915_dev *dev)
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
mt76_set(dev, MT_WFDMA_HOST_CONFIG,
MT_WFDMA_HOST_CONFIG_PDMA_BAND);
}
/* enable interrupts for TX/RX rings */
mt7915_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_MCU |
MT_INT_MCU_CMD);

View File

@ -22,7 +22,10 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
if (ret < 0)
return ret;
memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE);
if (ret)
dev->flash_mode = true;
else
memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE);
return 0;
}
@ -50,12 +53,15 @@ void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
u32 val;
val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);
val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val);
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
switch (val) {
case MT_EE_5GHZ:
case MT_EE_BAND_SEL_5GHZ:
phy->mt76->cap.has_5ghz = true;
break;
case MT_EE_2GHZ:
case MT_EE_BAND_SEL_2GHZ:
phy->mt76->cap.has_2ghz = true;
break;
default:
@ -67,26 +73,30 @@ void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
{
u8 nss, tx_mask[2] = {}, *eeprom = dev->mt76.eeprom.data;
u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data;
mt7915_eeprom_parse_band_config(&dev->phy);
/* read tx mask from eeprom */
tx_mask[0] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK,
eeprom[MT_EE_WIFI_CONF]);
if (dev->dbdc_support)
tx_mask[1] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK,
eeprom[MT_EE_WIFI_CONF + 1]);
nss = tx_mask[0] + tx_mask[1];
if (!nss || nss > 4) {
tx_mask[0] = 4;
nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]);
if (!nss || nss > 4)
nss = 4;
nss_band = nss;
if (dev->dbdc_support) {
nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
eeprom[MT_EE_WIFI_CONF + 3]);
if (!nss_band || nss_band > 2)
nss_band = 2;
if (nss_band >= nss)
nss = 4;
}
dev->chainmask = BIT(nss) - 1;
dev->mphy.antenna_mask = BIT(tx_mask[0]) - 1;
dev->phy.chainmask = dev->mphy.antenna_mask;
dev->mphy.antenna_mask = BIT(nss_band) - 1;
dev->mphy.chainmask = dev->mphy.antenna_mask;
}
int mt7915_eeprom_init(struct mt7915_dev *dev)

View File

@ -25,17 +25,20 @@ enum mt7915_eeprom_field {
__MT_EE_MAX = 0xe00
};
#define MT_EE_WIFI_CONF_TX_MASK GENMASK(2, 0)
#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(7, 6)
#define MT_EE_WIFI_CONF_TSSI0_2G BIT(0)
#define MT_EE_WIFI_CONF_TSSI0_5G BIT(2)
#define MT_EE_WIFI_CONF_TSSI1_5G BIT(4)
#define MT_EE_WIFI_CONF0_TX_PATH GENMASK(2, 0)
#define MT_EE_WIFI_CONF0_BAND_SEL GENMASK(7, 6)
#define MT_EE_WIFI_CONF1_BAND_SEL GENMASK(7, 6)
#define MT_EE_WIFI_CONF3_TX_PATH_B0 GENMASK(1, 0)
#define MT_EE_WIFI_CONF3_TX_PATH_B1 GENMASK(5, 4)
#define MT_EE_WIFI_CONF7_TSSI0_2G BIT(0)
#define MT_EE_WIFI_CONF7_TSSI0_5G BIT(2)
#define MT_EE_WIFI_CONF7_TSSI1_5G BIT(4)
enum mt7915_eeprom_band {
MT_EE_DUAL_BAND,
MT_EE_5GHZ,
MT_EE_2GHZ,
MT_EE_DBDC,
MT_EE_BAND_SEL_DEFAULT,
MT_EE_BAND_SEL_5GHZ,
MT_EE_BAND_SEL_2GHZ,
MT_EE_BAND_SEL_DUAL,
};
#define SKU_DELTA_VAL GENMASK(5, 0)
@ -116,9 +119,9 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
/* TODO: DBDC */
if (band == NL80211_BAND_5GHZ)
return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF_TSSI0_5G;
return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_5G;
else
return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF_TSSI0_2G;
return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_2G;
}
extern const struct sku_group mt7915_sku_groups[];

View File

@ -169,18 +169,19 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
{
int ret;
/*
* TODO: DBDC & check whether iBF phase calibration data has
* been stored in eeprom offset 0x651~0x7b8, then write down
* 0x1111 into 0x651 and 0x651 to trigger iBF.
*/
if (dev->dbdc_support) {
ret = mt7915_mcu_set_txbf_module(dev);
if (ret)
return ret;
}
/* trigger sounding packets */
ret = mt7915_mcu_set_txbf_sounding(dev);
if (ret)
return ret;
/* enable iBF & eBF */
/* enable eBF */
return mt7915_mcu_set_txbf_type(dev);
}
@ -235,12 +236,12 @@ static int mt7915_register_ext_phy(struct mt7915_dev *dev)
phy = mphy->priv;
phy->dev = dev;
phy->mt76 = mphy;
phy->chainmask = dev->chainmask & ~dev->phy.chainmask;
mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1;
mphy->chainmask = dev->chainmask & ~dev->mphy.chainmask;
mphy->antenna_mask = BIT(hweight8(mphy->chainmask)) - 1;
mt7915_init_wiphy(mphy->hw);
INIT_LIST_HEAD(&phy->stats_list);
INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work);
INIT_DELAYED_WORK(&mphy->mac_work, mt7915_mac_work);
mt7915_eeprom_parse_band_config(phy);
mt7915_set_stream_vht_txbf_caps(phy);
@ -329,7 +330,7 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
void mt7915_set_stream_vht_txbf_caps(struct mt7915_phy *phy)
{
int nss = hweight8(phy->chainmask);
int nss = hweight8(phy->mt76->chainmask);
u32 *cap = &phy->mt76->sband_5g.sband.vht_cap.cap;
*cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
@ -440,8 +441,7 @@ static int
mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
struct ieee80211_sband_iftype_data *data)
{
int i, idx = 0;
int nss = hweight8(phy->chainmask);
int i, idx = 0, nss = hweight8(phy->mt76->chainmask);
u16 mcs_map = 0;
for (i = 0; i < 8; i++) {
@ -622,7 +622,7 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->mt76.phy.priv = &dev->phy;
INIT_LIST_HEAD(&dev->phy.stats_list);
INIT_WORK(&dev->rc_work, mt7915_mac_sta_rc_work);
INIT_DELAYED_WORK(&dev->phy.mac_work, mt7915_mac_work);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7915_mac_work);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
@ -648,8 +648,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
dev->mphy.hw->wiphy->available_antennas_rx = dev->phy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->phy.chainmask;
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
mt76_set_stream_caps(&dev->mphy, true);
mt7915_set_stream_vht_txbf_caps(&dev->phy);
@ -672,28 +672,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
void mt7915_unregister_device(struct mt7915_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
mt7915_unregister_ext_phy(dev);
mt76_unregister_device(&dev->mt76);
mt7915_mcu_exit(dev);
mt7915_dma_cleanup(dev);
spin_lock_bh(&dev->token_lock);
idr_for_each_entry(&dev->token, txwi, id) {
mt7915_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb) {
struct ieee80211_hw *hw;
hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
ieee80211_free_txskb(hw, txwi->skb);
}
mt76_put_txwi(&dev->mt76, txwi);
dev->token_count--;
}
spin_unlock_bh(&dev->token_lock);
idr_destroy(&dev->token);
mt7915_tx_token_put(dev);
mt76_free_device(&dev->mt76);
}

View File

@ -565,13 +565,20 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
#ifdef CONFIG_NL80211_TESTMODE
void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
{
struct mt7915_phy *phy = &dev->phy;
__le32 *rxd = (__le32 *)skb->data;
__le32 *rxv_hdr = rxd + 2;
__le32 *rxv = rxd + 4;
u32 rcpi, ib_rssi, wb_rssi, v20, v21;
bool ext_phy;
s32 foe;
u8 snr;
int i;
ext_phy = FIELD_GET(MT_RXV_HDR_BAND_IDX, le32_to_cpu(rxv_hdr[1]));
if (ext_phy)
phy = mt7915_ext_phy(dev);
rcpi = le32_to_cpu(rxv[6]);
ib_rssi = le32_to_cpu(rxv[7]);
wb_rssi = le32_to_cpu(rxv[8]) >> 5;
@ -580,9 +587,9 @@ void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
if (i == 3)
wb_rssi = le32_to_cpu(rxv[9]);
dev->test.last_rcpi[i] = rcpi & 0xff;
dev->test.last_ib_rssi[i] = ib_rssi & 0xff;
dev->test.last_wb_rssi[i] = wb_rssi & 0xff;
phy->test.last_rcpi[i] = rcpi & 0xff;
phy->test.last_ib_rssi[i] = ib_rssi & 0xff;
phy->test.last_wb_rssi[i] = wb_rssi & 0xff;
}
v20 = le32_to_cpu(rxv[20]);
@ -593,26 +600,26 @@ void mt7915_mac_fill_rx_vector(struct mt7915_dev *dev, struct sk_buff *skb)
snr = FIELD_GET(MT_CRXV_SNR, v20) - 16;
dev->test.last_freq_offset = foe;
dev->test.last_snr = snr;
phy->test.last_freq_offset = foe;
phy->test.last_snr = snr;
dev_kfree_skb(skb);
}
#endif
static void
mt7915_mac_write_txwi_tm(struct mt7915_dev *dev, struct mt76_phy *mphy,
__le32 *txwi, struct sk_buff *skb)
mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
struct sk_buff *skb)
{
#ifdef CONFIG_NL80211_TESTMODE
struct mt76_testmode_data *td = &dev->mt76.test;
struct mt76_testmode_data *td = &phy->mt76->test;
u8 rate_idx = td->tx_rate_idx;
u8 nss = td->tx_rate_nss;
u8 bw, mode;
u16 rateval = 0;
u32 val;
if (skb != dev->mt76.test.tx_skb)
if (skb != phy->mt76->test.tx_skb)
return;
switch (td->tx_rate_mode) {
@ -644,7 +651,7 @@ mt7915_mac_write_txwi_tm(struct mt7915_dev *dev, struct mt76_phy *mphy,
break;
}
switch (mphy->chandef.width) {
switch (phy->mt76->chandef.width) {
case NL80211_CHAN_WIDTH_40:
bw = 1;
break;
@ -693,12 +700,12 @@ mt7915_mac_write_txwi_tm(struct mt7915_dev *dev, struct mt76_phy *mphy,
if (mode >= MT_PHY_TYPE_HE_SU)
val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf);
if (td->tx_rate_ldpc)
if (td->tx_rate_ldpc || bw > 0)
val |= MT_TXD6_LDPC;
txwi[6] |= cpu_to_le32(val);
txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX,
dev->test.spe_idx));
phy->test.spe_idx));
#endif
}
@ -902,8 +909,8 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
}
if (mt76_testmode_enabled(&dev->mt76))
mt7915_mac_write_txwi_tm(dev, mphy, txwi, skb);
if (mt76_testmode_enabled(mphy))
mt7915_mac_write_txwi_tm(mphy->priv, txwi, skb);
}
static void
@ -942,6 +949,9 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
int id, i, nbuf = tx_info->nbuf - 1;
u8 *txwi = (u8 *)txwi_ptr;
if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL;
if (!wcid)
wcid = &dev->mt76.global_wcid;
@ -1048,20 +1058,19 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
status.rate = &msta->stats.tx_rate;
}
hw = mt76_tx_status_get_hw(mdev, skb);
#ifdef CONFIG_NL80211_TESTMODE
if (skb == mdev->test.tx_skb) {
if (mt76_is_testmode_skb(mdev, skb, &hw)) {
struct mt7915_phy *phy = mt7915_hw_phy(hw);
struct ieee80211_vif *vif = phy->monitor_vif;
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
mt76_tx_complete_skb(mdev, mvif->sta.wcid.idx, skb);
return;
}
#endif
hw = mt76_tx_status_get_hw(mdev, skb);
if (info->flags & IEEE80211_TX_CTL_AMPDU)
info->flags |= IEEE80211_TX_STAT_AMPDU;
@ -1353,7 +1362,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx)
u32 val, sum = 0, n = 0;
int nss, i;
for (nss = 0; nss < hweight8(phy->chainmask); nss++) {
for (nss = 0; nss < hweight8(phy->mt76->chainmask); nss++) {
u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support));
for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {
@ -1434,7 +1443,15 @@ mt7915_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct ieee80211_hw *hw = priv;
mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
switch (vif->type) {
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
mt7915_mcu_add_beacon(hw, vif, vif->bss_conf.enable_beacon);
break;
default:
break;
}
}
static void
@ -1457,12 +1474,21 @@ mt7915_dma_reset(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy_ext = dev->mt76.phy2;
u32 hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE;
int i;
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_clear(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
if (dev->hif2) {
mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
mt76_clear(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
}
usleep_range(1000, 2000);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true);
@ -1483,6 +1509,35 @@ mt7915_dma_reset(struct mt7915_phy *phy)
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_set(dev, MT_WFDMA1_GLO_CFG,
MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN);
if (dev->hif2) {
mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
(MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN));
mt76_set(dev, MT_WFDMA1_GLO_CFG + hif1_ofs,
(MT_WFDMA1_GLO_CFG_TX_DMA_EN |
MT_WFDMA1_GLO_CFG_RX_DMA_EN));
}
}
void mt7915_tx_token_put(struct mt7915_dev *dev)
{
struct mt76_txwi_cache *txwi;
int id;
spin_lock_bh(&dev->token_lock);
idr_for_each_entry(&dev->token, txwi, id) {
mt7915_txp_skb_unmap(&dev->mt76, txwi);
if (txwi->skb) {
struct ieee80211_hw *hw;
hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb);
ieee80211_free_txskb(hw, txwi->skb);
}
mt76_put_txwi(&dev->mt76, txwi);
dev->token_count--;
}
spin_unlock_bh(&dev->token_lock);
idr_destroy(&dev->token);
}
/* system error recovery */
@ -1506,9 +1561,9 @@ void mt7915_mac_reset_work(struct work_struct *work)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
wake_up(&dev->mt76.mcu.wait);
cancel_delayed_work_sync(&dev->phy.mac_work);
cancel_delayed_work_sync(&dev->mphy.mac_work);
if (phy2)
cancel_delayed_work_sync(&phy2->mac_work);
cancel_delayed_work_sync(&phy2->mt76->mac_work);
/* lock/unlock all queues to ensure that no tx is pending */
mt76_txq_schedule_all(&dev->mphy);
@ -1525,6 +1580,9 @@ void mt7915_mac_reset_work(struct work_struct *work)
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
mt7915_tx_token_put(dev);
idr_init(&dev->token);
if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
mt7915_dma_reset(&dev->phy);
@ -1559,10 +1617,11 @@ void mt7915_mac_reset_work(struct work_struct *work)
mt7915_update_beacons(dev);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->phy.mac_work,
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,
MT7915_WATCHDOG_TIME);
if (phy2)
ieee80211_queue_delayed_work(ext_phy->hw, &phy2->mac_work,
ieee80211_queue_delayed_work(ext_phy->hw,
&phy2->mt76->mac_work,
MT7915_WATCHDOG_TIME);
}
@ -1673,17 +1732,17 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
void mt7915_mac_work(struct work_struct *work)
{
struct mt7915_phy *phy;
struct mt76_dev *mdev;
struct mt76_phy *mphy;
phy = (struct mt7915_phy *)container_of(work, struct mt7915_phy,
mac_work.work);
mdev = &phy->dev->mt76;
mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
mac_work.work);
phy = mphy->priv;
mutex_lock(&mdev->mutex);
mutex_lock(&mphy->dev->mutex);
mt76_update_survey(mdev);
if (++phy->mac_work_count == 5) {
phy->mac_work_count = 0;
mt76_update_survey(mphy->dev);
if (++mphy->mac_work_count == 5) {
mphy->mac_work_count = 0;
mt7915_mac_update_mib_stats(phy);
}
@ -1691,11 +1750,11 @@ void mt7915_mac_work(struct work_struct *work)
if (++phy->sta_work_count == 10) {
phy->sta_work_count = 0;
mt7915_mac_sta_stats_work(phy);
};
}
mutex_unlock(&mdev->mutex);
mutex_unlock(&mphy->dev->mutex);
ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
MT7915_WATCHDOG_TIME);
}

View File

@ -95,6 +95,8 @@ enum rx_pkt_type {
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
#define MT_RXV_HDR_BAND_IDX BIT(24)
/* P-RXV */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)

View File

@ -26,6 +26,8 @@ static int mt7915_start(struct ieee80211_hw *hw)
struct mt7915_phy *phy = mt7915_hw_phy(hw);
bool running;
flush_work(&dev->init_work);
mutex_lock(&dev->mt76.mutex);
running = mt7915_dev_running(dev);
@ -44,13 +46,13 @@ static int mt7915_start(struct ieee80211_hw *hw)
mt7915_mac_enable_nf(dev, 1);
}
mt7915_mcu_set_sku_en(phy, !mt76_testmode_enabled(&dev->mt76));
mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
mt7915_mcu_set_sku_en(phy, true);
mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
if (!mt76_testmode_enabled(&dev->mt76))
ieee80211_queue_delayed_work(hw, &phy->mac_work,
if (!mt76_testmode_enabled(phy->mt76))
ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
MT7915_WATCHDOG_TIME);
if (!running)
@ -66,11 +68,11 @@ static void mt7915_stop(struct ieee80211_hw *hw)
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
mutex_lock(&dev->mt76.mutex);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
@ -153,13 +155,13 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mutex_lock(&dev->mt76.mutex);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
if (vif->type == NL80211_IFTYPE_MONITOR &&
is_zero_ether_addr(vif->addr))
phy->monitor_vif = vif;
mvif->idx = ffs(~phy->mt76->vif_mask) - 1;
mvif->idx = ffs(~dev->mt76.vif_mask) - 1;
if (mvif->idx >= MT7915_MAX_INTERFACES) {
ret = -ENOSPC;
goto out;
@ -184,7 +186,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out;
phy->mt76->vif_mask |= BIT(mvif->idx);
dev->mt76.vif_mask |= BIT(mvif->idx);
phy->omac_mask |= BIT_ULL(mvif->omac_idx);
idx = MT7915_WTBL_RESERVED - mvif->idx;
@ -228,7 +230,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
/* TODO: disable beacon for the bss */
mutex_lock(&dev->mt76.mutex);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
mutex_unlock(&dev->mt76.mutex);
if (vif == phy->monitor_vif)
@ -239,7 +241,7 @@ static void mt7915_remove_interface(struct ieee80211_hw *hw,
rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
mutex_lock(&dev->mt76.mutex);
phy->mt76->vif_mask &= ~BIT(mvif->idx);
dev->mt76.vif_mask &= ~BIT(mvif->idx);
phy->omac_mask &= ~BIT_ULL(mvif->omac_idx);
mutex_unlock(&dev->mt76.mutex);
@ -273,7 +275,7 @@ int mt7915_set_channel(struct mt7915_phy *phy)
struct mt7915_dev *dev = phy->dev;
int ret;
cancel_delayed_work_sync(&phy->mac_work);
cancel_delayed_work_sync(&phy->mt76->mac_work);
mutex_lock(&dev->mt76.mutex);
set_bit(MT76_RESET, &phy->mt76->state);
@ -281,7 +283,7 @@ int mt7915_set_channel(struct mt7915_phy *phy)
mt7915_init_dfs_state(phy);
mt76_set_channel(phy->mt76);
ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH);
ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(CHANNEL_SWITCH));
if (ret)
goto out;
@ -298,8 +300,9 @@ int mt7915_set_channel(struct mt7915_phy *phy)
mt76_txq_schedule_all(phy->mt76);
if (!mt76_testmode_enabled(&dev->mt76))
ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
if (!mt76_testmode_enabled(phy->mt76))
ieee80211_queue_delayed_work(phy->mt76->hw,
&phy->mt76->mac_work,
MT7915_WATCHDOG_TIME);
return ret;
@ -365,9 +368,9 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
#ifdef CONFIG_NL80211_TESTMODE
if (dev->mt76.test.state != MT76_TM_STATE_OFF) {
if (phy->mt76->test.state != MT76_TM_STATE_OFF) {
mutex_lock(&dev->mt76.mutex);
mt76_testmode_reset(&dev->mt76, false);
mt76_testmode_reset(phy->mt76, false);
mutex_unlock(&dev->mt76.mutex);
}
#endif
@ -396,7 +399,7 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN,
enabled);
mt76_testmode_reset(&dev->mt76, true);
mt76_testmode_reset(phy->mt76, true);
mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
}
@ -427,7 +430,6 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
struct mt7915_dev *dev = mt7915_hw_dev(hw);
struct mt7915_phy *phy = mt7915_hw_phy(hw);
bool band = phy != &dev->phy;
u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
MT_WF_RFCR1_DROP_BF_POLL |
MT_WF_RFCR1_DROP_BA |
@ -441,6 +443,8 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \
} while (0)
mutex_lock(&dev->mt76.mutex);
phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
MT_WF_RFCR_DROP_OTHER_BEACON |
MT_WF_RFCR_DROP_FRAME_REPORT |
@ -471,6 +475,8 @@ static void mt7915_configure_filter(struct ieee80211_hw *hw,
mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
else
mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);
mutex_unlock(&dev->mt76.mutex);
}
static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
@ -808,7 +814,7 @@ mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
else
tx_ant <<= 1;
}
phy->chainmask = tx_ant;
phy->mt76->chainmask = tx_ant;
mt76_set_stream_caps(phy->mt76, true);
mt7915_set_stream_vht_txbf_caps(phy);

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,8 @@ enum {
enum {
MCU_ATE_SET_TRX = 0x1,
MCU_ATE_SET_FREQ_OFFSET = 0xa,
MCU_ATE_SET_SLOT_TIME = 0x13,
MCU_ATE_CLEAN_TXQUEUE = 0x1c,
};
struct mt7915_mcu_rxd {
@ -118,6 +120,12 @@ struct mt7915_mcu_rdd_report {
} hw_pulse[32];
} __packed;
struct mt7915_mcu_eeprom {
u8 buffer_mode;
u8 format;
__le16 len;
} __packed;
struct mt7915_mcu_eeprom_info {
__le32 addr;
__le32 valid;
@ -176,6 +184,30 @@ struct mt7915_mcu_phy_rx_info {
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
struct edca {
u8 queue;
u8 set;
u8 aifs;
u8 cw_min;
__le16 cw_max;
__le16 txop;
};
struct mt7915_mcu_tx {
u8 total;
u8 action;
u8 valid;
u8 mode;
struct edca edca[IEEE80211_NUM_ACS];
} __packed;
#define WMM_AIFS_SET BIT(0)
#define WMM_CW_MIN_SET BIT(1)
#define WMM_CW_MAX_SET BIT(2)
#define WMM_TXOP_SET BIT(3)
#define WMM_PARAM_SET GENMASK(3, 0)
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
@ -193,6 +225,12 @@ enum {
MCU_S2D_H2CN
};
#define __MCU_CMD_FIELD_ID GENMASK(7, 0)
#define __MCU_CMD_FIELD_EXT_ID GENMASK(15, 8)
#define __MCU_CMD_FIELD_QUERY BIT(16)
#define __MCU_CMD_FIELD_WA BIT(17)
enum {
MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01,
MCU_CMD_FW_START_REQ = 0x02,
@ -201,6 +239,7 @@ enum {
MCU_CMD_PATCH_START_REQ = 0x05,
MCU_CMD_PATCH_FINISH_REQ = 0x07,
MCU_CMD_PATCH_SEM_CONTROL = 0x10,
MCU_CMD_WA_PARAM = 0xC4,
MCU_CMD_EXT_CID = 0xED,
MCU_CMD_FW_SCATTER = 0xEE,
MCU_CMD_RESTART_DL_REQ = 0xEF,
@ -208,6 +247,7 @@ enum {
enum {
MCU_EXT_CMD_EFUSE_ACCESS = 0x01,
MCU_EXT_CMD_RF_TEST = 0x04,
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
@ -238,6 +278,29 @@ enum {
MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
};
enum {
MCU_WA_PARAM_CMD_QUERY,
MCU_WA_PARAM_CMD_SET,
MCU_WA_PARAM_CMD_CAPABILITY,
MCU_WA_PARAM_CMD_DEBUG,
};
enum {
MCU_WA_PARAM_RED = 0x0e,
};
#define MCU_CMD(_t) FIELD_PREP(__MCU_CMD_FIELD_ID, MCU_CMD_##_t)
#define MCU_EXT_CMD(_t) (MCU_CMD(EXT_CID) | \
FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \
MCU_EXT_CMD_##_t))
#define MCU_EXT_QUERY(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_QUERY)
#define MCU_WA_CMD(_t) (MCU_CMD(_t) | __MCU_CMD_FIELD_WA)
#define MCU_WA_EXT_CMD(_t) (MCU_EXT_CMD(_t) | __MCU_CMD_FIELD_WA)
#define MCU_WA_PARAM_CMD(_t) (MCU_WA_CMD(WA_PARAM) | \
FIELD_PREP(__MCU_CMD_FIELD_EXT_ID, \
MCU_WA_PARAM_CMD_##_t))
enum {
PATCH_SEM_RELEASE,
PATCH_SEM_GET

View File

@ -61,6 +61,7 @@ enum mt7915_rxq_id {
MT7915_RXQ_BAND1,
MT7915_RXQ_MCU_WM = 0,
MT7915_RXQ_MCU_WA,
MT7915_RXQ_MCU_WA_EXT,
};
struct mt7915_sta_stats {
@ -72,6 +73,11 @@ struct mt7915_sta_stats {
unsigned long jiffies;
};
struct mt7915_sta_key_conf {
s8 keyidx;
u8 key[16];
};
struct mt7915_sta {
struct mt76_wcid wcid; /* must be first */
@ -85,6 +91,8 @@ struct mt7915_sta {
struct mt7915_sta_stats stats;
unsigned long ampdu_state;
struct mt7915_sta_key_conf bip;
};
struct mt7915_vif {
@ -107,6 +115,14 @@ struct mib_stats {
u16 ba_miss_cnt;
};
struct mt7915_hif {
struct list_head list;
struct device *dev;
void __iomem *regs;
int irq;
};
struct mt7915_phy {
struct mt76_phy *mt76;
struct mt7915_dev *dev;
@ -119,7 +135,6 @@ struct mt7915_phy {
u64 omac_mask;
u16 noise;
u16 chainmask;
s16 coverage_class;
u8 slottime;
@ -133,9 +148,21 @@ struct mt7915_phy {
struct mib_stats mib;
struct list_head stats_list;
struct delayed_work mac_work;
u8 mac_work_count;
u8 sta_work_count;
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
s32 last_freq_offset;
u8 last_rcpi[4];
s8 last_ib_rssi[4];
s8 last_wb_rssi[4];
u8 last_snr;
u8 spe_idx;
} test;
#endif
};
struct mt7915_dev {
@ -144,10 +171,13 @@ struct mt7915_dev {
struct mt76_phy mphy;
};
struct mt7915_hif *hif2;
const struct mt76_bus_ops *bus_ops;
struct mt7915_phy phy;
u16 chainmask;
u32 hif_idx;
struct work_struct init_work;
struct work_struct rc_work;
@ -168,21 +198,9 @@ struct mt7915_dev {
s8 **rate_power; /* TODO: use mt76_rate_power */
bool dbdc_support;
bool flash_mode;
bool fw_debug;
#ifdef CONFIG_NL80211_TESTMODE
struct {
u32 *reg_backup;
s32 last_freq_offset;
u8 last_rcpi[4];
s8 last_ib_rssi[4];
s8 last_wb_rssi[4];
u8 last_snr;
u8 spe_idx;
} test;
#endif
bool ibf;
};
enum {
@ -271,7 +289,6 @@ static inline u8 mt7915_lmac_mapping(struct mt7915_dev *dev, u8 ac)
}
extern const struct ieee80211_ops mt7915_ops;
extern struct pci_driver mt7915_pci_driver;
extern const struct mt76_testmode_ops mt7915_testmode_ops;
u32 mt7915_reg_map(struct mt7915_dev *dev, u32 addr);
@ -319,6 +336,7 @@ int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
int mt7915_set_channel(struct mt7915_phy *phy);
int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd);
int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif);
int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req);
int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev,
struct ieee80211_sta *sta, u32 rate);
int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
@ -334,6 +352,7 @@ int mt7915_mcu_set_pm(struct mt7915_dev *dev, int band, int enter);
int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable);
int mt7915_mcu_set_sku(struct mt7915_phy *phy);
int mt7915_mcu_set_txbf_type(struct mt7915_dev *dev);
int mt7915_mcu_set_txbf_module(struct mt7915_dev *dev);
int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev);
int mt7915_mcu_set_fcc5_lpn(struct mt7915_dev *dev, int val);
int mt7915_mcu_set_pulse_th(struct mt7915_dev *dev,
@ -356,14 +375,23 @@ static inline bool is_mt7915(struct mt76_dev *dev)
return mt76_chip(dev) == 0x7915;
}
void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg,
u32 clear, u32 set);
static inline void mt7915_irq_enable(struct mt7915_dev *dev, u32 mask)
{
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
if (dev->hif2)
mt7915_dual_hif_set_irq_mask(dev, true, 0, mask);
else
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
}
static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
{
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
if (dev->hif2)
mt7915_dual_hif_set_irq_mask(dev, true, mask, 0);
else
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
}
static inline u32
@ -463,6 +491,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
void mt7915_tx_token_put(struct mt7915_dev *dev);
int mt7915_init_tx_queues(struct mt7915_phy *phy, int idx, int n_desc);
void mt7915_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);

View File

@ -12,11 +12,72 @@
#include "mac.h"
#include "../trace.h"
static LIST_HEAD(hif_list);
static DEFINE_SPINLOCK(hif_lock);
static u32 hif_idx;
static const struct pci_device_id mt7915_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7915) },
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) },
{ },
};
static const struct pci_device_id mt7915_hif_device_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },
{ },
};
void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg,
u32 clear, u32 set)
{
struct mt76_dev *mdev = &dev->mt76;
unsigned long flags;
spin_lock_irqsave(&mdev->mmio.irq_lock, flags);
mdev->mmio.irqmask &= ~clear;
mdev->mmio.irqmask |= set;
if (write_reg) {
mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask);
mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask);
}
spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags);
}
static struct mt7915_hif *
mt7915_pci_get_hif2(struct mt7915_dev *dev)
{
struct mt7915_hif *hif;
u32 val;
spin_lock_bh(&hif_lock);
list_for_each_entry(hif, &hif_list, list) {
val = readl(hif->regs + MT_PCIE_RECOG_ID);
val &= MT_PCIE_RECOG_ID_MASK;
if (val != dev->hif_idx)
continue;
get_device(hif->dev);
goto out;
}
hif = NULL;
out:
spin_unlock_bh(&hif_lock);
return hif;
}
static void mt7915_put_hif2(struct mt7915_hif *hif)
{
if (!hif)
return;
put_device(hif->dev);
}
static void
mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
@ -26,6 +87,7 @@ mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
[MT_RXQ_EXT] = MT_INT_RX_DONE_DATA1,
[MT_RXQ_MCU] = MT_INT_RX_DONE_WM,
[MT_RXQ_MCU_WA] = MT_INT_RX_DONE_WA,
[MT_RXQ_EXT_WA] = MT_INT_RX_DONE_WA_EXT,
};
mt7915_irq_enable(dev, rx_irq_mask[q]);
@ -35,12 +97,20 @@ mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
{
struct mt7915_dev *dev = dev_instance;
u32 intr, mask;
u32 intr, intr1, mask;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
if (dev->hif2) {
intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR);
intr1 &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1);
intr |= intr1;
}
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
@ -67,6 +137,9 @@ static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
if (intr & MT_INT_RX_DONE_WA)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);
if (intr & MT_INT_RX_DONE_WA_EXT)
napi_schedule(&dev->mt76.napi[MT_RXQ_EXT_WA]);
if (intr & MT_INT_MCU_CMD) {
u32 val = mt76_rr(dev, MT_MCU_CMD);
@ -103,6 +176,53 @@ mt7915_alloc_device(struct pci_dev *pdev, struct mt7915_dev *dev)
return 0;
}
static void mt7915_pci_init_hif2(struct mt7915_dev *dev)
{
struct mt7915_hif *hif;
dev->hif_idx = ++hif_idx;
if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL))
return;
mt76_wr(dev, MT_PCIE_RECOG_ID, dev->hif_idx | MT_PCIE_RECOG_ID_SEM);
hif = mt7915_pci_get_hif2(dev);
if (!hif)
return;
dev->hif2 = hif;
mt76_wr(dev, MT_INT1_MASK_CSR, 0);
if (devm_request_irq(dev->mt76.dev, hif->irq, mt7915_irq_handler,
IRQF_SHARED, KBUILD_MODNAME "-hif", dev)) {
mt7915_put_hif2(hif);
hif = NULL;
}
/* master switch of PCIe tnterrupt enable */
mt7915_l1_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
}
static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
{
struct mt7915_hif *hif;
hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
if (!hif)
return -ENOMEM;
hif->dev = &pdev->dev;
hif->regs = pcim_iomap_table(pdev)[0];
hif->irq = pdev->irq;
spin_lock_bh(&hif_lock);
list_add(&hif->list, &hif_list);
spin_unlock_bh(&hif_lock);
pci_set_drvdata(pdev, hif);
return 0;
}
static int mt7915_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@ -141,6 +261,9 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
if (id->device == 0x7916)
return mt7915_pci_hif2_probe(pdev);
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops,
&drv_ops);
if (!mdev)
@ -166,6 +289,8 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
if (ret)
goto error;
mt7915_pci_init_hif2(dev);
ret = mt7915_register_device(dev);
if (ret)
goto error;
@ -177,24 +302,64 @@ static int mt7915_pci_probe(struct pci_dev *pdev,
return ret;
}
static void mt7915_hif_remove(struct pci_dev *pdev)
{
struct mt7915_hif *hif = pci_get_drvdata(pdev);
list_del(&hif->list);
}
static void mt7915_pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt76_dev *mdev;
struct mt7915_dev *dev;
mdev = pci_get_drvdata(pdev);
dev = container_of(mdev, struct mt7915_dev, mt76);
mt7915_put_hif2(dev->hif2);
mt7915_unregister_device(dev);
}
struct pci_driver mt7915_pci_driver = {
static struct pci_driver mt7915_hif_driver = {
.name = KBUILD_MODNAME "_hif",
.id_table = mt7915_hif_device_table,
.probe = mt7915_pci_probe,
.remove = mt7915_hif_remove,
};
static struct pci_driver mt7915_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7915_pci_device_table,
.probe = mt7915_pci_probe,
.remove = mt7915_pci_remove,
};
module_pci_driver(mt7915_pci_driver);
static int __init mt7915_init(void)
{
int ret;
ret = pci_register_driver(&mt7915_hif_driver);
if (ret)
return ret;
ret = pci_register_driver(&mt7915_pci_driver);
if (ret)
pci_unregister_driver(&mt7915_hif_driver);
return ret;
}
static void __exit mt7915_exit(void)
{
pci_unregister_driver(&mt7915_pci_driver);
pci_unregister_driver(&mt7915_hif_driver);
}
module_init(mt7915_init);
module_exit(mt7915_exit);
MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
MODULE_FIRMWARE(MT7915_ROM_PATCH);

View File

@ -59,6 +59,13 @@
#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
#define MT_TMAC_ATCR(_band) MT_WF_TMAC(_band, 0x098)
#define MT_TMAC_ATCR_TXV_TOUT GENMASK(7, 0)
#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c)
#define MT_TMAC_TRCR0_TR2T_CHK GENMASK(8, 0)
#define MT_TMAC_TRCR0_I2T_CHK GENMASK(24, 16)
#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4)
#define MT_IFS_EIFS GENMASK(8, 0)
#define MT_IFS_RIFS GENMASK(14, 10)
@ -70,7 +77,6 @@
#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17)
#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18)
#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c)
#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0)
#define MT_WF_DMA_BASE(_band) ((_band) ? 0xa1e00 : 0x21e00)
@ -342,21 +348,36 @@
#define MT_INT_RX_DONE_DATA1 BIT(17)
#define MT_INT_RX_DONE_WM BIT(0)
#define MT_INT_RX_DONE_WA BIT(1)
#define MT_INT_RX_DONE_ALL (BIT(0) | BIT(1) | GENMASK(17, 16))
#define MT_INT_RX_DONE_WA_EXT BIT(2)
#define MT_INT_RX_DONE_ALL (GENMASK(2, 0) | GENMASK(17, 16))
#define MT_INT_TX_DONE_MCU_WA BIT(15)
#define MT_INT_TX_DONE_FWDL BIT(26)
#define MT_INT_TX_DONE_MCU_WM BIT(27)
#define MT_INT_TX_DONE_BAND0 BIT(30)
#define MT_INT_TX_DONE_BAND1 BIT(31)
#define MT_INT_BAND1_MASK (MT_INT_RX_DONE_WA_EXT | \
MT_INT_TX_DONE_BAND1)
#define MT_INT_MCU_CMD BIT(29)
#define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WA | \
MT_INT_TX_DONE_MCU_WM | \
MT_INT_TX_DONE_FWDL)
#define MT_WFDMA_HOST_CONFIG MT_WFDMA_EXT_CSR(0x30)
#define MT_WFDMA_HOST_CONFIG_PDMA_BAND BIT(0)
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_INT1_SOURCE_CSR MT_WFDMA_EXT_CSR(0x88)
#define MT_INT1_MASK_CSR MT_WFDMA_EXT_CSR(0x8c)
#define MT_PCIE_RECOG_ID MT_WFDMA_EXT_CSR(0x90)
#define MT_PCIE_RECOG_ID_MASK GENMASK(30, 0)
#define MT_PCIE_RECOG_ID_SEM BIT(31)
/* WFDMA0 PCIE1 */
#define MT_WFDMA0_PCIE1_BASE 0xd8000
#define MT_WFDMA0_PCIE1(ofs) (MT_WFDMA0_PCIE1_BASE + (ofs))
@ -411,6 +432,10 @@
#define MT_HW_CHIPID 0x70010200
#define MT_HW_REV 0x70010204
#define MT_PCIE1_MAC_BASE 0x74020000
#define MT_PCIE1_MAC(ofs) (MT_PCIE1_MAC_BASE + (ofs))
#define MT_PCIE1_MAC_INT_ENABLE MT_PCIE1_MAC(0x188)
#define MT_PCIE_MAC_BASE 0x74030000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)

View File

@ -70,30 +70,32 @@ mt7915_tm_set_tx_power(struct mt7915_phy *phy)
};
u8 *tx_power = NULL;
if (dev->mt76.test.state != MT76_TM_STATE_OFF)
tx_power = dev->mt76.test.tx_power;
if (phy->mt76->test.state != MT76_TM_STATE_OFF)
tx_power = phy->mt76->test.tx_power;
/* Tx power of the other antennas are the same as antenna 0 */
if (tx_power && tx_power[0])
req.tx_power = tx_power[0];
ret = mt76_mcu_send_msg(&dev->mt76,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL,
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
&req, sizeof(req), false);
return ret;
}
static int
mt7915_tm_set_freq_offset(struct mt7915_dev *dev, bool en, u32 val)
mt7915_tm_set_freq_offset(struct mt7915_phy *phy, bool en, u32 val)
{
struct mt7915_dev *dev = phy->dev;
struct mt7915_tm_cmd req = {
.testmode_en = en,
.param_idx = MCU_ATE_SET_FREQ_OFFSET,
.param.freq.band = phy != &dev->phy,
.param.freq.freq_offset = cpu_to_le32(val),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req,
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
sizeof(req), false);
}
@ -110,14 +112,14 @@ mt7915_tm_mode_ctrl(struct mt7915_dev *dev, bool enable)
};
return mt76_mcu_send_msg(&dev->mt76,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL,
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
&req, sizeof(req), false);
}
static int
mt7915_tm_set_trx(struct mt7915_dev *dev, struct mt7915_phy *phy,
int type, bool en)
mt7915_tm_set_trx(struct mt7915_phy *phy, int type, bool en)
{
struct mt7915_dev *dev = phy->dev;
struct mt7915_tm_cmd req = {
.testmode_en = 1,
.param_idx = MCU_ATE_SET_TRX,
@ -126,19 +128,230 @@ mt7915_tm_set_trx(struct mt7915_dev *dev, struct mt7915_phy *phy,
.param.trx.band = phy != &dev->phy,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_ATE_CTRL, &req,
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
sizeof(req), false);
}
static int
mt7915_tm_clean_hwq(struct mt7915_phy *phy, u8 wcid)
{
struct mt7915_dev *dev = phy->dev;
struct mt7915_tm_cmd req = {
.testmode_en = 1,
.param_idx = MCU_ATE_CLEAN_TXQUEUE,
.param.clean.wcid = wcid,
.param.clean.band = phy != &dev->phy,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
sizeof(req), false);
}
static int
mt7915_tm_set_slot_time(struct mt7915_phy *phy, u8 slot_time, u8 sifs)
{
struct mt7915_dev *dev = phy->dev;
struct mt7915_tm_cmd req = {
.testmode_en = !(phy->mt76->test.state == MT76_TM_STATE_OFF),
.param_idx = MCU_ATE_SET_SLOT_TIME,
.param.slot.slot_time = slot_time,
.param.slot.sifs = sifs,
.param.slot.rifs = 2,
.param.slot.eifs = cpu_to_le16(60),
.param.slot.band = phy != &dev->phy,
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(ATE_CTRL), &req,
sizeof(req), false);
}
static int
mt7915_tm_set_wmm_qid(struct mt7915_dev *dev, u8 qid, u8 aifs, u8 cw_min,
u16 cw_max, u16 txop)
{
struct mt7915_mcu_tx req = { .total = 1 };
struct edca *e = &req.edca[0];
e->queue = qid;
e->set = WMM_PARAM_SET;
e->aifs = aifs;
e->cw_min = cw_min;
e->cw_max = cpu_to_le16(cw_max);
e->txop = cpu_to_le16(txop);
return mt7915_mcu_update_edca(dev, &req);
}
static int
mt7915_tm_set_ipg_params(struct mt7915_phy *phy, u32 ipg, u8 mode)
{
#define TM_DEFAULT_SIFS 10
#define TM_MAX_SIFS 127
#define TM_MAX_AIFSN 0xf
#define TM_MIN_AIFSN 0x1
#define BBP_PROC_TIME 1500
struct mt7915_dev *dev = phy->dev;
u8 sig_ext = (mode == MT76_TM_TX_MODE_CCK) ? 0 : 6;
u8 slot_time = 9, sifs = TM_DEFAULT_SIFS;
u8 aifsn = TM_MIN_AIFSN;
u32 i2t_time, tr2t_time, txv_time;
bool ext_phy = phy != &dev->phy;
u16 cw = 0;
if (ipg < sig_ext + slot_time + sifs)
ipg = 0;
if (!ipg)
goto done;
ipg -= sig_ext;
if (ipg <= (TM_MAX_SIFS + slot_time)) {
sifs = ipg - slot_time;
} else {
u32 val = (ipg + slot_time) / slot_time;
while (val >>= 1)
cw++;
if (cw > 16)
cw = 16;
ipg -= ((1 << cw) - 1) * slot_time;
aifsn = ipg / slot_time;
if (aifsn > TM_MAX_AIFSN)
aifsn = TM_MAX_AIFSN;
ipg -= aifsn * slot_time;
if (ipg > TM_DEFAULT_SIFS) {
if (ipg < TM_MAX_SIFS)
sifs = ipg;
else
sifs = TM_MAX_SIFS;
}
}
done:
txv_time = mt76_get_field(dev, MT_TMAC_ATCR(ext_phy),
MT_TMAC_ATCR_TXV_TOUT);
txv_time *= 50; /* normal clock time */
i2t_time = (slot_time * 1000 - txv_time - BBP_PROC_TIME) / 50;
tr2t_time = (sifs * 1000 - txv_time - BBP_PROC_TIME) / 50;
mt76_set(dev, MT_TMAC_TRCR0(ext_phy),
FIELD_PREP(MT_TMAC_TRCR0_TR2T_CHK, tr2t_time) |
FIELD_PREP(MT_TMAC_TRCR0_I2T_CHK, i2t_time));
mt7915_tm_set_slot_time(phy, slot_time, sifs);
return mt7915_tm_set_wmm_qid(dev,
mt7915_lmac_mapping(dev, IEEE80211_AC_BE),
aifsn, cw, cw, 0);
}
static int
mt7915_tm_set_tx_len(struct mt7915_phy *phy, u32 tx_time)
{
struct mt76_phy *mphy = phy->mt76;
struct mt76_testmode_data *td = &mphy->test;
struct sk_buff *old = td->tx_skb, *new;
struct ieee80211_supported_band *sband;
struct rate_info rate = {};
u16 flags = 0, tx_len;
u32 bitrate;
if (!tx_time || !old)
return 0;
rate.mcs = td->tx_rate_idx;
rate.nss = td->tx_rate_nss;
switch (td->tx_rate_mode) {
case MT76_TM_TX_MODE_CCK:
case MT76_TM_TX_MODE_OFDM:
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.sband;
else
sband = &mphy->sband_2g.sband;
rate.legacy = sband->bitrates[rate.mcs].bitrate;
break;
case MT76_TM_TX_MODE_HT:
rate.mcs += rate.nss * 8;
flags |= RATE_INFO_FLAGS_MCS;
if (td->tx_rate_sgi)
flags |= RATE_INFO_FLAGS_SHORT_GI;
break;
case MT76_TM_TX_MODE_VHT:
flags |= RATE_INFO_FLAGS_VHT_MCS;
if (td->tx_rate_sgi)
flags |= RATE_INFO_FLAGS_SHORT_GI;
break;
case MT76_TM_TX_MODE_HE_SU:
case MT76_TM_TX_MODE_HE_EXT_SU:
case MT76_TM_TX_MODE_HE_TB:
case MT76_TM_TX_MODE_HE_MU:
rate.he_gi = td->tx_rate_sgi;
flags |= RATE_INFO_FLAGS_HE_MCS;
break;
default:
break;
}
rate.flags = flags;
switch (mphy->chandef.width) {
case NL80211_CHAN_WIDTH_160:
case NL80211_CHAN_WIDTH_80P80:
rate.bw = RATE_INFO_BW_160;
break;
case NL80211_CHAN_WIDTH_80:
rate.bw = RATE_INFO_BW_80;
break;
case NL80211_CHAN_WIDTH_40:
rate.bw = RATE_INFO_BW_40;
break;
default:
rate.bw = RATE_INFO_BW_20;
break;
}
bitrate = cfg80211_calculate_bitrate(&rate);
tx_len = bitrate * tx_time / 10 / 8;
if (tx_len < sizeof(struct ieee80211_hdr))
tx_len = sizeof(struct ieee80211_hdr);
else if (tx_len > IEEE80211_MAX_FRAME_LEN)
tx_len = IEEE80211_MAX_FRAME_LEN;
new = alloc_skb(tx_len, GFP_KERNEL);
if (!new)
return -ENOMEM;
skb_copy_header(new, old);
__skb_put_zero(new, tx_len);
memcpy(new->data, old->data, sizeof(struct ieee80211_hdr));
dev_kfree_skb(old);
td->tx_skb = new;
return 0;
}
static void
mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy)
mt7915_tm_reg_backup_restore(struct mt7915_phy *phy)
{
int n_regs = ARRAY_SIZE(reg_backup_list);
struct mt7915_dev *dev = phy->dev;
bool ext_phy = phy != &dev->phy;
u32 *b = dev->test.reg_backup;
u32 *b = phy->test.reg_backup;
int i;
if (dev->mt76.test.state == MT76_TM_STATE_OFF) {
if (phy->mt76->test.state == MT76_TM_STATE_OFF) {
for (i = 0; i < n_regs; i++)
mt76_wr(dev, reg_backup_list[i].band[ext_phy], b[i]);
return;
@ -151,7 +364,7 @@ mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy)
if (!b)
return;
dev->test.reg_backup = b;
phy->test.reg_backup = b;
for (i = 0; i < n_regs; i++)
b[i] = mt76_rr(dev, reg_backup_list[i].band[ext_phy]);
@ -182,93 +395,260 @@ mt7915_tm_reg_backup_restore(struct mt7915_dev *dev, struct mt7915_phy *phy)
}
static void
mt7915_tm_init(struct mt7915_dev *dev)
mt7915_tm_init(struct mt7915_phy *phy, bool en)
{
bool en = !(dev->mt76.test.state == MT76_TM_STATE_OFF);
struct mt7915_dev *dev = phy->dev;
if (!test_bit(MT76_STATE_RUNNING, &dev->phy.mt76->state))
if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
return;
mt7915_mcu_set_sku_en(phy, !en);
mt7915_tm_mode_ctrl(dev, en);
mt7915_tm_reg_backup_restore(dev, &dev->phy);
mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TXRX, !en);
mt7915_tm_reg_backup_restore(phy);
mt7915_tm_set_trx(phy, TM_MAC_TXRX, !en);
mt7915_mcu_add_bss_info(phy, phy->monitor_vif, en);
}
static void
mt7915_tm_set_tx_frames(struct mt7915_dev *dev, bool en)
mt7915_tm_update_channel(struct mt7915_phy *phy)
{
mutex_unlock(&phy->dev->mt76.mutex);
mt7915_set_channel(phy);
mutex_lock(&phy->dev->mt76.mutex);
mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD(SET_RX_PATH));
}
static void
mt7915_tm_set_tx_frames(struct mt7915_phy *phy, bool en)
{
static const u8 spe_idx_map[] = {0, 0, 1, 0, 3, 2, 4, 0,
9, 8, 6, 10, 16, 12, 18, 0};
struct sk_buff *skb = dev->mt76.test.tx_skb;
struct mt76_testmode_data *td = &phy->mt76->test;
struct mt7915_dev *dev = phy->dev;
struct ieee80211_tx_info *info;
u8 duty_cycle = td->tx_duty_cycle;
u32 tx_time = td->tx_time;
u32 ipg = td->tx_ipg;
mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, false);
mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, false);
mt7915_tm_clean_hwq(phy, dev->mt76.global_wcid.idx);
if (en) {
u8 tx_ant = dev->mt76.test.tx_antenna_mask;
mt7915_tm_update_channel(phy);
mutex_unlock(&dev->mt76.mutex);
mt7915_set_channel(&dev->phy);
mutex_lock(&dev->mt76.mutex);
if (td->tx_spe_idx) {
phy->test.spe_idx = td->tx_spe_idx;
} else {
u8 tx_ant = td->tx_antenna_mask;
mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH);
dev->test.spe_idx = spe_idx_map[tx_ant];
if (phy != &dev->phy)
tx_ant >>= 2;
phy->test.spe_idx = spe_idx_map[tx_ant];
}
}
mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_TX, en);
/* if all three params are set, duty_cycle will be ignored */
if (duty_cycle && tx_time && !ipg) {
ipg = tx_time * 100 / duty_cycle - tx_time;
} else if (duty_cycle && !tx_time && ipg) {
if (duty_cycle < 100)
tx_time = duty_cycle * ipg / (100 - duty_cycle);
}
if (!en || !skb)
mt7915_tm_set_ipg_params(phy, ipg, td->tx_rate_mode);
mt7915_tm_set_tx_len(phy, tx_time);
if (ipg)
td->tx_queued_limit = MT76_TM_TIMEOUT * 1000000 / ipg / 2;
if (!en || !td->tx_skb)
return;
info = IEEE80211_SKB_CB(skb);
info->control.vif = dev->phy.monitor_vif;
info = IEEE80211_SKB_CB(td->tx_skb);
info->control.vif = phy->monitor_vif;
mt7915_tm_set_trx(phy, TM_MAC_TX, en);
}
static void
mt7915_tm_set_rx_frames(struct mt7915_dev *dev, bool en)
mt7915_tm_set_rx_frames(struct mt7915_phy *phy, bool en)
{
if (en) {
mutex_unlock(&dev->mt76.mutex);
mt7915_set_channel(&dev->phy);
mutex_lock(&dev->mt76.mutex);
if (en)
mt7915_tm_update_channel(phy);
mt7915_mcu_set_chan_info(&dev->phy, MCU_EXT_CMD_SET_RX_PATH);
}
mt7915_tm_set_trx(dev, &dev->phy, TM_MAC_RX_RXV, en);
}
static void
mt7915_tm_update_params(struct mt7915_dev *dev, u32 changed)
{
struct mt76_testmode_data *td = &dev->mt76.test;
bool en = dev->mt76.test.state != MT76_TM_STATE_OFF;
if (changed & BIT(TM_CHANGED_FREQ_OFFSET))
mt7915_tm_set_freq_offset(dev, en, en ? td->freq_offset : 0);
if (changed & BIT(TM_CHANGED_TXPOWER))
mt7915_tm_set_tx_power(&dev->phy);
mt7915_tm_set_trx(phy, TM_MAC_RX_RXV, en);
}
static int
mt7915_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state)
mt7915_tm_rf_switch_mode(struct mt7915_dev *dev, u32 oper)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt76_testmode_data *td = &mdev->test;
struct mt7915_tm_rf_test req = {
.op.op_mode = cpu_to_le32(oper),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
sizeof(req), true);
}
static int
mt7915_tm_set_tx_cont(struct mt7915_phy *phy, bool en)
{
#define TX_CONT_START 0x05
#define TX_CONT_STOP 0x06
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
int freq1 = ieee80211_frequency_to_channel(chandef->center_freq1);
struct mt76_testmode_data *td = &phy->mt76->test;
u32 func_idx = en ? TX_CONT_START : TX_CONT_STOP;
u8 rate_idx = td->tx_rate_idx, mode;
u16 rateval;
struct mt7915_tm_rf_test req = {
.action = 1,
.icap_len = 120,
.op.rf.func_idx = cpu_to_le32(func_idx),
};
struct tm_tx_cont *tx_cont = &req.op.rf.param.tx_cont;
tx_cont->control_ch = chandef->chan->hw_value;
tx_cont->center_ch = freq1;
tx_cont->tx_ant = td->tx_antenna_mask;
tx_cont->band = phy != &dev->phy;
switch (chandef->width) {
case NL80211_CHAN_WIDTH_40:
tx_cont->bw = CMD_CBW_40MHZ;
break;
case NL80211_CHAN_WIDTH_80:
tx_cont->bw = CMD_CBW_80MHZ;
break;
case NL80211_CHAN_WIDTH_80P80:
tx_cont->bw = CMD_CBW_8080MHZ;
break;
case NL80211_CHAN_WIDTH_160:
tx_cont->bw = CMD_CBW_160MHZ;
break;
case NL80211_CHAN_WIDTH_5:
tx_cont->bw = CMD_CBW_5MHZ;
break;
case NL80211_CHAN_WIDTH_10:
tx_cont->bw = CMD_CBW_10MHZ;
break;
case NL80211_CHAN_WIDTH_20:
tx_cont->bw = CMD_CBW_20MHZ;
break;
case NL80211_CHAN_WIDTH_20_NOHT:
tx_cont->bw = CMD_CBW_20MHZ;
break;
default:
break;
}
if (!en) {
req.op.rf.param.func_data = cpu_to_le32(phy != &dev->phy);
goto out;
}
if (td->tx_rate_mode <= MT76_TM_TX_MODE_OFDM) {
struct ieee80211_supported_band *sband;
u8 idx = rate_idx;
if (chandef->chan->band == NL80211_BAND_5GHZ)
sband = &phy->mt76->sband_5g.sband;
else
sband = &phy->mt76->sband_2g.sband;
if (td->tx_rate_mode == MT76_TM_TX_MODE_OFDM)
idx += 4;
rate_idx = sband->bitrates[idx].hw_value & 0xff;
}
switch (td->tx_rate_mode) {
case MT76_TM_TX_MODE_CCK:
mode = MT_PHY_TYPE_CCK;
break;
case MT76_TM_TX_MODE_OFDM:
mode = MT_PHY_TYPE_OFDM;
break;
case MT76_TM_TX_MODE_HT:
mode = MT_PHY_TYPE_HT;
break;
case MT76_TM_TX_MODE_VHT:
mode = MT_PHY_TYPE_VHT;
break;
case MT76_TM_TX_MODE_HE_SU:
mode = MT_PHY_TYPE_HE_SU;
break;
case MT76_TM_TX_MODE_HE_EXT_SU:
mode = MT_PHY_TYPE_HE_EXT_SU;
break;
case MT76_TM_TX_MODE_HE_TB:
mode = MT_PHY_TYPE_HE_TB;
break;
case MT76_TM_TX_MODE_HE_MU:
mode = MT_PHY_TYPE_HE_MU;
break;
default:
break;
}
rateval = mode << 6 | rate_idx;
tx_cont->rateval = cpu_to_le16(rateval);
out:
if (!en) {
int ret;
ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
sizeof(req), true);
if (ret)
return ret;
return mt7915_tm_rf_switch_mode(dev, RF_OPER_NORMAL);
}
mt7915_tm_rf_switch_mode(dev, RF_OPER_RF_TEST);
mt7915_tm_update_channel(phy);
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(RF_TEST), &req,
sizeof(req), true);
}
static void
mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
{
struct mt76_testmode_data *td = &phy->mt76->test;
bool en = phy->mt76->test.state != MT76_TM_STATE_OFF;
if (changed & BIT(TM_CHANGED_FREQ_OFFSET))
mt7915_tm_set_freq_offset(phy, en, en ? td->freq_offset : 0);
if (changed & BIT(TM_CHANGED_TXPOWER))
mt7915_tm_set_tx_power(phy);
}
static int
mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
{
struct mt76_testmode_data *td = &mphy->test;
struct mt7915_phy *phy = mphy->priv;
enum mt76_testmode_state prev_state = td->state;
mdev->test.state = state;
mphy->test.state = state;
if (prev_state == MT76_TM_STATE_TX_FRAMES)
mt7915_tm_set_tx_frames(dev, false);
else if (state == MT76_TM_STATE_TX_FRAMES)
mt7915_tm_set_tx_frames(dev, true);
else if (prev_state == MT76_TM_STATE_RX_FRAMES)
mt7915_tm_set_rx_frames(dev, false);
else if (state == MT76_TM_STATE_RX_FRAMES)
mt7915_tm_set_rx_frames(dev, true);
else if (prev_state == MT76_TM_STATE_OFF || state == MT76_TM_STATE_OFF)
mt7915_tm_init(dev);
if (prev_state == MT76_TM_STATE_TX_FRAMES ||
state == MT76_TM_STATE_TX_FRAMES)
mt7915_tm_set_tx_frames(phy, state == MT76_TM_STATE_TX_FRAMES);
else if (prev_state == MT76_TM_STATE_RX_FRAMES ||
state == MT76_TM_STATE_RX_FRAMES)
mt7915_tm_set_rx_frames(phy, state == MT76_TM_STATE_RX_FRAMES);
else if (prev_state == MT76_TM_STATE_TX_CONT ||
state == MT76_TM_STATE_TX_CONT)
mt7915_tm_set_tx_cont(phy, state == MT76_TM_STATE_TX_CONT);
else if (prev_state == MT76_TM_STATE_OFF ||
state == MT76_TM_STATE_OFF)
mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
@ -284,18 +664,18 @@ mt7915_tm_set_state(struct mt76_dev *mdev, enum mt76_testmode_state state)
changed |= BIT(i);
}
mt7915_tm_update_params(dev, changed);
mt7915_tm_update_params(phy, changed);
}
return 0;
}
static int
mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
mt7915_tm_set_params(struct mt76_phy *mphy, struct nlattr **tb,
enum mt76_testmode_state new_state)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt76_testmode_data *td = &dev->mt76.test;
struct mt76_testmode_data *td = &mphy->test;
struct mt7915_phy *phy = mphy->priv;
u32 changed = 0;
int i;
@ -305,7 +685,7 @@ mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
td->state == MT76_TM_STATE_OFF)
return 0;
if (td->tx_antenna_mask & ~dev->phy.chainmask)
if (td->tx_antenna_mask & ~mphy->chainmask)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(tm_change_map); i++) {
@ -313,15 +693,15 @@ mt7915_tm_set_params(struct mt76_dev *mdev, struct nlattr **tb,
changed |= BIT(i);
}
mt7915_tm_update_params(dev, changed);
mt7915_tm_update_params(phy, changed);
return 0;
}
static int
mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
{
struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
struct mt7915_phy *phy = mphy->priv;
void *rx, *rssi;
int i;
@ -329,15 +709,15 @@ mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rx)
return -ENOMEM;
if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, dev->test.last_freq_offset))
if (nla_put_s32(msg, MT76_TM_RX_ATTR_FREQ_OFFSET, phy->test.last_freq_offset))
return -ENOMEM;
rssi = nla_nest_start(msg, MT76_TM_RX_ATTR_RCPI);
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_rcpi); i++)
if (nla_put_u8(msg, i, dev->test.last_rcpi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_rcpi); i++)
if (nla_put_u8(msg, i, phy->test.last_rcpi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);
@ -346,8 +726,8 @@ mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_ib_rssi); i++)
if (nla_put_s8(msg, i, dev->test.last_ib_rssi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_ib_rssi); i++)
if (nla_put_s8(msg, i, phy->test.last_ib_rssi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);
@ -356,13 +736,13 @@ mt7915_tm_dump_stats(struct mt76_dev *mdev, struct sk_buff *msg)
if (!rssi)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(dev->test.last_wb_rssi); i++)
if (nla_put_s8(msg, i, dev->test.last_wb_rssi[i]))
for (i = 0; i < ARRAY_SIZE(phy->test.last_wb_rssi); i++)
if (nla_put_s8(msg, i, phy->test.last_wb_rssi[i]))
return -ENOMEM;
nla_nest_end(msg, rssi);
if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, dev->test.last_snr))
if (nla_put_u8(msg, MT76_TM_RX_ATTR_SNR, phy->test.last_snr))
return -ENOMEM;
nla_nest_end(msg, rx);

View File

@ -16,6 +16,23 @@ struct mt7915_tm_freq_offset {
__le32 freq_offset;
};
struct mt7915_tm_slot_time {
u8 slot_time;
u8 sifs;
u8 rifs;
u8 _rsv;
__le16 eifs;
u8 band;
u8 _rsv1[5];
};
struct mt7915_tm_clean_txq {
bool sta_pause;
u8 wcid; /* 256 sta */
u8 band;
u8 rsv;
};
struct mt7915_tm_cmd {
u8 testmode_en;
u8 param_idx;
@ -24,6 +41,8 @@ struct mt7915_tm_cmd {
__le32 data;
struct mt7915_tm_trx trx;
struct mt7915_tm_freq_offset freq;
struct mt7915_tm_slot_time slot;
struct mt7915_tm_clean_txq clean;
u8 test[72];
} param;
} __packed;
@ -37,4 +56,44 @@ enum {
TM_MAC_RX_RXV,
};
struct tm_tx_cont {
u8 control_ch;
u8 center_ch;
u8 bw;
u8 tx_ant;
__le16 rateval;
u8 band;
u8 txfd_mode;
};
struct mt7915_tm_rf_test {
u8 action;
u8 icap_len;
u8 _rsv[2];
union {
__le32 op_mode;
__le32 freq;
struct {
__le32 func_idx;
union {
__le32 func_data;
__le32 cal_dump;
struct tm_tx_cont tx_cont;
u8 _pad[80];
} param;
} rf;
} op;
} __packed;
enum {
RF_OPER_NORMAL,
RF_OPER_RF_TEST,
RF_OPER_ICAP,
RF_OPER_ICAP_OVERLAP,
RF_OPER_WIFI_SPECTRUM,
};
#endif

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: ISC
config MT7921E
tristate "MediaTek MT7921E (PCIe) support"
select MT76_CONNAC_LIB
select WANT_DEV_COREDUMP
depends on MAC80211
depends on PCI
help
This adds support for MT7921E 802.11ax 2x2:2SS wireless devices.
To compile this driver as a module, choose M here.

View File

@ -0,0 +1,5 @@
#SPDX-License-Identifier: ISC
obj-$(CONFIG_MT7921E) += mt7921e.o
mt7921e-y := pci.o mac.o mcu.o dma.o eeprom.o main.o init.o debugfs.o

View File

@ -0,0 +1,250 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt7921.h"
#include "eeprom.h"
static int
mt7921_fw_debug_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
dev->fw_debug = (u8)val;
mt7921_mcu_fw_log_2_host(dev, dev->fw_debug);
return 0;
}
static int
mt7921_fw_debug_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
*val = dev->fw_debug;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get,
mt7921_fw_debug_set, "%lld\n");
static void
mt7921_ampdu_stat_read_phy(struct mt7921_phy *phy,
struct seq_file *file)
{
struct mt7921_dev *dev = file->private;
int bound[15], range[4], i;
if (!phy)
return;
/* Tx ampdu stat */
for (i = 0; i < ARRAY_SIZE(range); i++)
range[i] = mt76_rr(dev, MT_MIB_ARNG(0, i));
for (i = 0; i < ARRAY_SIZE(bound); i++)
bound[i] = MT_MIB_ARNCR_RANGE(range[i / 4], i) + 1;
seq_printf(file, "\nPhy0\n");
seq_printf(file, "Length: %8d | ", bound[0]);
for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
seq_printf(file, "%3d -%3d | ",
bound[i] + 1, bound[i + 1]);
seq_puts(file, "\nCount: ");
for (i = 0; i < ARRAY_SIZE(bound); i++)
seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]);
seq_puts(file, "\n");
seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
}
static int
mt7921_tx_stats_read(struct seq_file *file, void *data)
{
struct mt7921_dev *dev = file->private;
int stat[8], i, n;
mt7921_ampdu_stat_read_phy(&dev->phy, file);
/* Tx amsdu info */
seq_puts(file, "Tx MSDU stat:\n");
for (i = 0, n = 0; i < ARRAY_SIZE(stat); i++) {
stat[i] = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
n += stat[i];
}
for (i = 0; i < ARRAY_SIZE(stat); i++) {
seq_printf(file, "AMSDU pack count of %d MSDU in TXD: 0x%x ",
i + 1, stat[i]);
if (n != 0)
seq_printf(file, "(%d%%)\n", stat[i] * 100 / n);
else
seq_puts(file, "\n");
}
return 0;
}
static int
mt7921_tx_stats_open(struct inode *inode, struct file *f)
{
return single_open(f, mt7921_tx_stats_read, inode->i_private);
}
static const struct file_operations fops_tx_stats = {
.open = mt7921_tx_stats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
};
static int
mt7921_queues_acq(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
int i;
for (i = 0; i < 16; i++) {
int j, acs = i / 4, index = i % 4;
u32 ctrl, val, qlen = 0;
val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index));
ctrl = BIT(31) | BIT(15) | (acs << 8);
for (j = 0; j < 32; j++) {
if (val & BIT(j))
continue;
mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
ctrl | (j + (index << 5)));
qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
GENMASK(11, 0));
}
seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen);
}
return 0;
}
static int
mt7921_queues_read(struct seq_file *s, void *data)
{
struct mt7921_dev *dev = dev_get_drvdata(s->private);
struct {
struct mt76_queue *q;
char *queue;
} queue_map[] = {
{ dev->mphy.q_tx[MT_TXQ_BE], "WFDMA0" },
{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUWM" },
{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
};
int i;
for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
struct mt76_queue *q = queue_map[i].q;
if (!q)
continue;
seq_printf(s,
"%s: queued=%d head=%d tail=%d\n",
queue_map[i].queue, q->queued, q->head,
q->tail);
}
return 0;
}
static int
mt7921_pm_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
struct mt76_phy *mphy = dev->phy.mt76;
int ret = 0;
mt7921_mutex_acquire(dev);
dev->pm.enable = val;
ieee80211_iterate_active_interfaces(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7921_pm_interface_iter, mphy->priv);
mt7921_mutex_release(dev);
return ret;
}
static int
mt7921_pm_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
*val = dev->pm.enable;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
static int
mt7921_pm_idle_timeout_set(void *data, u64 val)
{
struct mt7921_dev *dev = data;
dev->pm.idle_timeout = msecs_to_jiffies(val);
return 0;
}
static int
mt7921_pm_idle_timeout_get(void *data, u64 *val)
{
struct mt7921_dev *dev = data;
*val = jiffies_to_msecs(dev->pm.idle_timeout);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7921_pm_idle_timeout_get,
mt7921_pm_idle_timeout_set, "%lld\n");
static int mt7921_config(void *data, u64 val)
{
struct mt7921_dev *dev = data;
int ret;
mt7921_mutex_acquire(dev);
ret = mt76_connac_mcu_chip_config(&dev->mt76);
mt7921_mutex_release(dev);
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_config, NULL, mt7921_config, "%lld\n");
int mt7921_init_debugfs(struct mt7921_dev *dev)
{
struct dentry *dir;
dir = mt76_register_debugfs(&dev->mt76);
if (!dir)
return -ENOMEM;
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
mt7921_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7921_queues_acq);
debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
debugfs_create_file("idle-timeout", 0600, dir, dev,
&fops_pm_idle_timeout);
debugfs_create_file("chip_config", 0600, dir, dev, &fops_config);
return 0;
}

View File

@ -0,0 +1,356 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt7921.h"
#include "../dma.h"
#include "mac.h"
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc)
{
int i, err;
err = mt76_init_tx_queue(phy->mt76, 0, idx, n_desc, MT_TX_RING_BASE);
if (err < 0)
return err;
for (i = 0; i <= MT_TXQ_PSD; i++)
phy->mt76->q_tx[i] = phy->mt76->q_tx[0];
return 0;
}
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
__le32 *rxd = (__le32 *)skb->data;
enum rx_pkt_type type;
u16 flag;
type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0]));
flag = FIELD_GET(MT_RXD0_PKT_FLAG, le32_to_cpu(rxd[0]));
if (type == PKT_TYPE_RX_EVENT && flag == 0x1)
type = PKT_TYPE_NORMAL_MCU;
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
mt7921_mac_tx_free(dev, skb);
break;
case PKT_TYPE_RX_EVENT:
mt7921_mcu_rx_event(dev, skb);
break;
case PKT_TYPE_NORMAL_MCU:
case PKT_TYPE_NORMAL:
if (!mt7921_mac_fill_rx(dev, skb)) {
mt76_rx(&dev->mt76, q, skb);
return;
}
fallthrough;
default:
dev_kfree_skb(skb);
break;
}
}
static void
mt7921_tx_cleanup(struct mt7921_dev *dev)
{
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], false);
}
static int mt7921_poll_tx(struct napi_struct *napi, int budget)
{
struct mt7921_dev *dev;
dev = container_of(napi, struct mt7921_dev, mt76.tx_napi);
mt7921_tx_cleanup(dev);
if (napi_complete_done(napi, 0))
mt7921_irq_enable(dev, MT_INT_TX_DONE_ALL);
return 0;
}
void mt7921_dma_prefetch(struct mt7921_dev *dev)
{
#define PREFETCH(base, depth) ((base) << 16 | (depth))
mt76_wr(dev, MT_WFDMA0_RX_RING0_EXT_CTRL, PREFETCH(0x0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING2_EXT_CTRL, PREFETCH(0x40, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING3_EXT_CTRL, PREFETCH(0x80, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING4_EXT_CTRL, PREFETCH(0xc0, 0x4));
mt76_wr(dev, MT_WFDMA0_RX_RING5_EXT_CTRL, PREFETCH(0x100, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, PREFETCH(0x140, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING1_EXT_CTRL, PREFETCH(0x180, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING2_EXT_CTRL, PREFETCH(0x1c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING3_EXT_CTRL, PREFETCH(0x200, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING4_EXT_CTRL, PREFETCH(0x240, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING5_EXT_CTRL, PREFETCH(0x280, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING6_EXT_CTRL, PREFETCH(0x2c0, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING16_EXT_CTRL, PREFETCH(0x340, 0x4));
mt76_wr(dev, MT_WFDMA0_TX_RING17_EXT_CTRL, PREFETCH(0x380, 0x4));
}
static u32 __mt7921_reg_addr(struct mt7921_dev *dev, u32 addr)
{
static const struct {
u32 phys;
u32 mapped;
u32 size;
} fixed_map[] = {
{ 0x00400000, 0x80000, 0x10000}, /* WF_MCU_SYSRAM */
{ 0x00410000, 0x90000, 0x10000}, /* WF_MCU_SYSRAM (configure register) */
{ 0x40000000, 0x70000, 0x10000}, /* WF_UMAC_SYSRAM */
{ 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
{ 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
{ 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
{ 0x59000000, 0x07000, 0x1000 }, /* WFDMA PCIE1 MCU DMA1 */
{ 0x7c000000, 0xf0000, 0x10000 }, /* CONN_INFRA */
{ 0x7c020000, 0xd0000, 0x10000 }, /* CONN_INFRA, WFDMA */
{ 0x7c060000, 0xe0000, 0x10000}, /* CONN_INFRA, conn_host_csr_top */
{ 0x80020000, 0xb0000, 0x10000 }, /* WF_TOP_MISC_OFF */
{ 0x81020000, 0xc0000, 0x10000 }, /* WF_TOP_MISC_ON */
{ 0x820c0000, 0x08000, 0x4000 }, /* WF_UMAC_TOP (PLE) */
{ 0x820c8000, 0x0c000, 0x2000 }, /* WF_UMAC_TOP (PSE) */
{ 0x820cc000, 0x0e000, 0x2000 }, /* WF_UMAC_TOP (PP) */
{ 0x820ce000, 0x21c00, 0x0200 }, /* WF_LMAC_TOP (WF_SEC) */
{ 0x820cf000, 0x22000, 0x1000 }, /* WF_LMAC_TOP (WF_PF) */
{ 0x820d0000, 0x30000, 0x10000 }, /* WF_LMAC_TOP (WF_WTBLON) */
{ 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) */
{ 0x820e7000, 0x21e00, 0x0200 }, /* WF_LMAC_TOP BN0 (WF_DMA) */
{ 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) */
{ 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) */
};
int i;
if (addr < 0x100000)
return addr;
for (i = 0; i < ARRAY_SIZE(fixed_map); i++) {
u32 ofs;
if (addr < fixed_map[i].phys)
continue;
ofs = addr - fixed_map[i].phys;
if (ofs > fixed_map[i].size)
continue;
return fixed_map[i].mapped + ofs;
}
if ((addr >= 0x18000000 && addr < 0x18c00000) ||
(addr >= 0x70000000 && addr < 0x78000000) ||
(addr >= 0x7c000000 && addr < 0x7c400000))
return mt7921_reg_map_l1(dev, addr);
dev_err(dev->mt76.dev, "Access currently unsupported address %08x\n",
addr);
return 0;
}
static u32 mt7921_rr(struct mt76_dev *mdev, u32 offset)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
return dev->bus_ops->rr(mdev, addr);
}
static void mt7921_wr(struct mt76_dev *mdev, u32 offset, u32 val)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
dev->bus_ops->wr(mdev, addr, val);
}
static u32 mt7921_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
u32 addr = __mt7921_reg_addr(dev, offset);
return dev->bus_ops->rmw(mdev, addr, mask, val);
}
static int mt7921_dmashdl_disabled(struct mt7921_dev *dev)
{
mt76_clear(dev, MT_WFDMA0_GLO_CFG_EXT0, MT_WFDMA0_CSR_TX_DMASHDL_ENABLE);
mt76_set(dev, MT_DMASHDL_SW_CONTROL, MT_DMASHDL_DMASHDL_BYPASS);
return 0;
}
int mt7921_dma_init(struct mt7921_dev *dev)
{
/* Increase buffer size to receive large VHT/HE MPDUs */
struct mt76_bus_ops *bus_ops;
int rx_buf_size = MT_RX_BUF_SIZE * 2;
int ret;
dev->bus_ops = dev->mt76.bus;
bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops),
GFP_KERNEL);
if (!bus_ops)
return -ENOMEM;
bus_ops->rr = mt7921_rr;
bus_ops->wr = mt7921_wr;
bus_ops->rmw = mt7921_rmw;
dev->mt76.bus = bus_ops;
mt76_dma_attach(&dev->mt76);
/* reset */
mt76_clear(dev, MT_WFDMA0_RST,
MT_WFDMA0_RST_DMASHDL_ALL_RST |
MT_WFDMA0_RST_LOGIC_RST);
mt76_set(dev, MT_WFDMA0_RST,
MT_WFDMA0_RST_DMASHDL_ALL_RST |
MT_WFDMA0_RST_LOGIC_RST);
ret = mt7921_dmashdl_disabled(dev);
if (ret)
return ret;
/* disable WFDMA0 */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
/* init tx queue */
ret = mt7921_init_tx_queues(&dev->phy, MT7921_TXQ_BAND0,
MT7921_TX_RING_SIZE);
if (ret)
return ret;
mt76_wr(dev, MT_WFDMA0_TX_RING0_EXT_CTRL, 0x4);
/* command to WM */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_WM, MT7921_TXQ_MCU_WM,
MT7921_TX_MCU_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* firmware download */
ret = mt76_init_mcu_queue(&dev->mt76, MT_MCUQ_FWDL, MT7921_TXQ_FWDL,
MT7921_TX_FWDL_RING_SIZE, MT_TX_RING_BASE);
if (ret)
return ret;
/* event from WM before firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
rx_buf_size, MT_RX_EVENT_RING_BASE);
if (ret)
return ret;
/* Change mcu queue after firmware download */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU_WA],
MT7921_RXQ_MCU_WM,
MT7921_RX_MCU_RING_SIZE,
rx_buf_size, MT_WFDMA0(0x540));
if (ret)
return ret;
/* rx data */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
MT7921_RXQ_BAND0, MT7921_RX_RING_SIZE,
rx_buf_size, MT_RX_DATA_RING_BASE);
if (ret)
return ret;
ret = mt76_init_queues(dev);
if (ret < 0)
return ret;
netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi,
mt7921_poll_tx, NAPI_POLL_WEIGHT);
napi_enable(&dev->mt76.tx_napi);
/* configure perfetch settings */
mt7921_dma_prefetch(dev);
/* reset dma idx */
mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
/* configure delay interrupt */
mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_WB_DDONE |
MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_set(dev, 0x54000120, BIT(1));
/* enable interrupts for TX/RX rings */
mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
MT_INT_MCU_CMD);
return 0;
}
void mt7921_dma_cleanup(struct mt7921_dev *dev)
{
/* disable */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN |
MT_WFDMA0_GLO_CFG_RX_DMA_EN |
MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO |
MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
/* reset */
mt76_clear(dev, MT_WFDMA0_RST,
MT_WFDMA0_RST_DMASHDL_ALL_RST |
MT_WFDMA0_RST_LOGIC_RST);
mt76_set(dev, MT_WFDMA0_RST,
MT_WFDMA0_RST_DMASHDL_ALL_RST |
MT_WFDMA0_RST_LOGIC_RST);
mt76_dma_cleanup(&dev->mt76);
}

View File

@ -0,0 +1,100 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include "mt7921.h"
#include "eeprom.h"
static u32 mt7921_eeprom_read(struct mt7921_dev *dev, u32 offset)
{
u8 *data = dev->mt76.eeprom.data;
if (data[offset] == 0xff)
mt7921_mcu_get_eeprom(dev, offset);
return data[offset];
}
static int mt7921_eeprom_load(struct mt7921_dev *dev)
{
int ret;
ret = mt76_eeprom_init(&dev->mt76, MT7921_EEPROM_SIZE);
if (ret < 0)
return ret;
memset(dev->mt76.eeprom.data, -1, MT7921_EEPROM_SIZE);
return 0;
}
static int mt7921_check_eeprom(struct mt7921_dev *dev)
{
u8 *eeprom = dev->mt76.eeprom.data;
u16 val;
mt7921_eeprom_read(dev, MT_EE_CHIP_ID);
val = get_unaligned_le16(eeprom);
switch (val) {
case 0x7961:
return 0;
default:
return -EINVAL;
}
}
void mt7921_eeprom_parse_band_config(struct mt7921_phy *phy)
{
struct mt7921_dev *dev = phy->dev;
u32 val;
val = mt7921_eeprom_read(dev, MT_EE_WIFI_CONF);
val = FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL, val);
switch (val) {
case MT_EE_5GHZ:
phy->mt76->cap.has_5ghz = true;
break;
case MT_EE_2GHZ:
phy->mt76->cap.has_2ghz = true;
break;
default:
phy->mt76->cap.has_2ghz = true;
phy->mt76->cap.has_5ghz = true;
break;
}
}
static void mt7921_eeprom_parse_hw_cap(struct mt7921_dev *dev)
{
u8 tx_mask;
mt7921_eeprom_parse_band_config(&dev->phy);
/* TODO: read NSS with MCU_CMD_NIC_CAPV2 */
tx_mask = 2;
dev->chainmask = BIT(tx_mask) - 1;
dev->mphy.antenna_mask = dev->chainmask;
dev->mphy.chainmask = dev->mphy.antenna_mask;
}
int mt7921_eeprom_init(struct mt7921_dev *dev)
{
int ret;
ret = mt7921_eeprom_load(dev);
if (ret < 0)
return ret;
ret = mt7921_check_eeprom(dev);
if (ret)
return ret;
mt7921_eeprom_parse_hw_cap(dev);
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
ETH_ALEN);
mt76_eeprom_override(&dev->mphy);
return 0;
}

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT7921_EEPROM_H
#define __MT7921_EEPROM_H
#include "mt7921.h"
enum mt7921_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
MT_EE_MAC_ADDR = 0x004,
MT_EE_WIFI_CONF = 0x07c,
__MT_EE_MAX = 0x3bf
};
#define MT_EE_WIFI_CONF_TX_MASK BIT(0)
#define MT_EE_WIFI_CONF_BAND_SEL GENMASK(3, 2)
enum mt7921_eeprom_band {
MT_EE_NA,
MT_EE_5GHZ,
MT_EE_2GHZ,
MT_EE_DUAL_BAND,
};
#endif

View File

@ -0,0 +1,282 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */
#include <linux/etherdevice.h>
#include "mt7921.h"
#include "mac.h"
#include "mcu.h"
#include "eeprom.h"
#define CCK_RATE(_idx, _rate) { \
.bitrate = _rate, \
.flags = IEEE80211_RATE_SHORT_PREAMBLE, \
.hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \
.hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + (_idx)), \
}
#define OFDM_RATE(_idx, _rate) { \
.bitrate = _rate, \
.hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
.hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \
}
static struct ieee80211_rate mt7921_rates[] = {
CCK_RATE(0, 10),
CCK_RATE(1, 20),
CCK_RATE(2, 55),
CCK_RATE(3, 110),
OFDM_RATE(11, 60),
OFDM_RATE(15, 90),
OFDM_RATE(10, 120),
OFDM_RATE(14, 180),
OFDM_RATE(9, 240),
OFDM_RATE(13, 360),
OFDM_RATE(8, 480),
OFDM_RATE(12, 540),
};
static const struct ieee80211_iface_limit if_limits[] = {
{
.max = MT7921_MAX_INTERFACES,
.types = BIT(NL80211_IFTYPE_STATION)
}
};
static const struct ieee80211_iface_combination if_comb[] = {
{
.limits = if_limits,
.n_limits = ARRAY_SIZE(if_limits),
.max_interfaces = MT7921_MAX_INTERFACES,
.num_different_channels = 1,
.beacon_int_infra_match = true,
}
};
static void
mt7921_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;
mt7921_mutex_acquire(dev);
mt76_connac_mcu_set_channel_domain(hw->priv);
mt7921_mutex_release(dev);
}
static void
mt7921_init_wiphy(struct ieee80211_hw *hw)
{
struct mt7921_phy *phy = mt7921_hw_phy(hw);
struct wiphy *wiphy = hw->wiphy;
hw->queues = 4;
hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
phy->slottime = 9;
hw->sta_data_size = sizeof(struct mt7921_sta);
hw->vif_data_size = sizeof(struct mt7921_vif);
wiphy->iface_combinations = if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
wiphy->max_scan_ssids = 4;
wiphy->max_sched_scan_plan_interval =
MT76_CONNAC_MAX_SCHED_SCAN_INTERVAL;
wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;
wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;
wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
wiphy->max_sched_scan_reqs = 1;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy->reg_notifier = mt7921_regd_notifier;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);
ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
ieee80211_hw_set(hw, HAS_RATE_CONTROL);
ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
ieee80211_hw_set(hw, SUPPORTS_PS);
ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
hw->max_tx_fragments = 4;
}
static void
mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
{
u32 mask, set;
mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
mt76_set(dev, MT_TMAC_CTCR0(band),
MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
MT_TMAC_CTCR0_INS_DDLMT_EN);
mask = MT_MDP_RCFR0_MCU_RX_MGMT |
MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR |
MT_MDP_RCFR0_MCU_RX_CTL_BAR;
set = FIELD_PREP(MT_MDP_RCFR0_MCU_RX_MGMT, MT_MDP_TO_HIF) |
FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR, MT_MDP_TO_HIF) |
FIELD_PREP(MT_MDP_RCFR0_MCU_RX_CTL_BAR, MT_MDP_TO_HIF);
mt76_rmw(dev, MT_MDP_BNRCFR0(band), mask, set);
mask = MT_MDP_RCFR1_MCU_RX_BYPASS |
MT_MDP_RCFR1_RX_DROPPED_UCAST |
MT_MDP_RCFR1_RX_DROPPED_MCAST;
set = FIELD_PREP(MT_MDP_RCFR1_MCU_RX_BYPASS, MT_MDP_TO_HIF) |
FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_UCAST, MT_MDP_TO_HIF) |
FIELD_PREP(MT_MDP_RCFR1_RX_DROPPED_MCAST, MT_MDP_TO_HIF);
mt76_rmw(dev, MT_MDP_BNRCFR1(band), mask, set);
mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
/* disable rx rate report by default due to hw issues */
mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
}
static void mt7921_mac_init(struct mt7921_dev *dev)
{
int i;
mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536);
/* disable hardware de-agg */
mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN);
mt76_clear(dev, MT_MDP_DCR0, MT_MDP_DCR0_RX_HDR_TRANS_EN);
for (i = 0; i < MT7921_WTBL_SIZE; i++)
mt7921_mac_wtbl_update(dev, i,
MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
for (i = 0; i < 2; i++)
mt7921_mac_init_band(dev, i);
mt76_connac_mcu_set_rts_thresh(&dev->mt76, 0x92b, 0);
}
static void mt7921_init_work(struct work_struct *work)
{
struct mt7921_dev *dev = container_of(work, struct mt7921_dev,
init_work);
mt7921_mcu_set_eeprom(dev);
mt7921_mac_init(dev);
}
static int mt7921_init_hardware(struct mt7921_dev *dev)
{
int ret, idx;
INIT_WORK(&dev->init_work, mt7921_init_work);
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);
ret = mt7921_dma_init(dev);
if (ret)
return ret;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
/* force firmware operation mode into normal state,
* which should be set before firmware download stage.
*/
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7921_mcu_init(dev);
if (ret)
return ret;
ret = mt7921_eeprom_init(dev);
if (ret < 0)
return ret;
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7921_WTBL_STA - 1);
if (idx)
return -ENOSPC;
dev->mt76.global_wcid.idx = idx;
dev->mt76.global_wcid.hw_key_idx = -1;
dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;
rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
return 0;
}
int mt7921_register_device(struct mt7921_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
int ret;
dev->phy.dev = dev;
dev->phy.mt76 = &dev->mt76.phy;
dev->mt76.phy.priv = &dev->phy;
INIT_DELAYED_WORK(&dev->pm.ps_work, mt7921_pm_power_save_work);
INIT_WORK(&dev->pm.wake_work, mt7921_pm_wake_work);
init_completion(&dev->pm.wake_cmpl);
spin_lock_init(&dev->pm.txq_lock);
set_bit(MT76_STATE_PM, &dev->mphy.state);
INIT_LIST_HEAD(&dev->phy.stats_list);
INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7921_mac_work);
INIT_DELAYED_WORK(&dev->phy.scan_work, mt7921_scan_work);
INIT_DELAYED_WORK(&dev->coredump.work, mt7921_coredump_work);
skb_queue_head_init(&dev->phy.scan_event_list);
skb_queue_head_init(&dev->coredump.msg_list);
INIT_LIST_HEAD(&dev->sta_poll_list);
spin_lock_init(&dev->sta_poll_lock);
init_waitqueue_head(&dev->reset_wait);
INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
ret = mt7921_init_hardware(dev);
if (ret)
return ret;
mt7921_init_wiphy(hw);
dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
dev->mphy.sband_2g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
dev->mphy.sband_5g.sband.ht_cap.cap |=
IEEE80211_HT_CAP_LDPC_CODING |
IEEE80211_HT_CAP_MAX_AMSDU;
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
dev->mphy.sband_5g.sband.vht_cap.cap |=
IEEE80211_VHT_CAP_SHORT_GI_160 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask;
dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask;
mt76_set_stream_caps(&dev->mphy, true);
mt7921_set_stream_he_caps(&dev->phy);
ret = mt76_register_device(&dev->mt76, true, mt7921_rates,
ARRAY_SIZE(mt7921_rates));
if (ret)
return ret;
ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
return mt7921_init_debugfs(dev);
}
void mt7921_unregister_device(struct mt7921_dev *dev)
{
mt76_unregister_device(&dev->mt76);
mt7921_mcu_exit(dev);
mt7921_dma_cleanup(dev);
mt7921_tx_token_put(dev);
tasklet_disable(&dev->irq_tasklet);
mt76_free_device(&dev->mt76);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,333 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT7921_MAC_H
#define __MT7921_MAC_H
#define MT_CT_PARSE_LEN 72
#define MT_CT_DMA_BUF_NUM 2
#define MT_RXD0_LENGTH GENMASK(15, 0)
#define MT_RXD0_PKT_FLAG GENMASK(19, 16)
#define MT_RXD0_PKT_TYPE GENMASK(31, 27)
#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16)
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
enum rx_pkt_type {
PKT_TYPE_TXS,
PKT_TYPE_TXRXV,
PKT_TYPE_NORMAL,
PKT_TYPE_RX_DUP_RFB,
PKT_TYPE_RX_TMR,
PKT_TYPE_RETRIEVE,
PKT_TYPE_TXRX_NOTIFY,
PKT_TYPE_RX_EVENT,
PKT_TYPE_NORMAL_MCU,
};
/* RXD DW1 */
#define MT_RXD1_NORMAL_WLAN_IDX GENMASK(9, 0)
#define MT_RXD1_NORMAL_GROUP_1 BIT(11)
#define MT_RXD1_NORMAL_GROUP_2 BIT(12)
#define MT_RXD1_NORMAL_GROUP_3 BIT(13)
#define MT_RXD1_NORMAL_GROUP_4 BIT(14)
#define MT_RXD1_NORMAL_GROUP_5 BIT(15)
#define MT_RXD1_NORMAL_SEC_MODE GENMASK(20, 16)
#define MT_RXD1_NORMAL_KEY_ID GENMASK(22, 21)
#define MT_RXD1_NORMAL_CM BIT(23)
#define MT_RXD1_NORMAL_CLM BIT(24)
#define MT_RXD1_NORMAL_ICV_ERR BIT(25)
#define MT_RXD1_NORMAL_TKIP_MIC_ERR BIT(26)
#define MT_RXD1_NORMAL_FCS_ERR BIT(27)
#define MT_RXD1_NORMAL_BAND_IDX BIT(28)
#define MT_RXD1_NORMAL_SPP_EN BIT(29)
#define MT_RXD1_NORMAL_ADD_OM BIT(30)
#define MT_RXD1_NORMAL_SEC_DONE BIT(31)
/* RXD DW2 */
#define MT_RXD2_NORMAL_BSSID GENMASK(5, 0)
#define MT_RXD2_NORMAL_CO_ANT BIT(6)
#define MT_RXD2_NORMAL_BF_CQI BIT(7)
#define MT_RXD2_NORMAL_MAC_HDR_LEN GENMASK(12, 8)
#define MT_RXD2_NORMAL_HDR_TRANS BIT(13)
#define MT_RXD2_NORMAL_HDR_OFFSET GENMASK(15, 14)
#define MT_RXD2_NORMAL_TID GENMASK(19, 16)
#define MT_RXD2_NORMAL_MU_BAR BIT(21)
#define MT_RXD2_NORMAL_SW_BIT BIT(22)
#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23)
#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24)
#define MT_RXD2_NORMAL_HDR_TRANS_ERROR BIT(25)
#define MT_RXD2_NORMAL_INT_FRAME BIT(26)
#define MT_RXD2_NORMAL_FRAG BIT(27)
#define MT_RXD2_NORMAL_NULL_FRAME BIT(28)
#define MT_RXD2_NORMAL_NDATA BIT(29)
#define MT_RXD2_NORMAL_NON_AMPDU BIT(30)
#define MT_RXD2_NORMAL_BF_REPORT BIT(31)
/* RXD DW3 */
#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0)
#define MT_RXD3_NORMAL_CH_FREQ GENMASK(15, 8)
#define MT_RXD3_NORMAL_ADDR_TYPE GENMASK(17, 16)
#define MT_RXD3_NORMAL_U2M BIT(0)
#define MT_RXD3_NORMAL_HTC_VLD BIT(0)
#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(19)
#define MT_RXD3_NORMAL_BEACON_MC BIT(20)
#define MT_RXD3_NORMAL_BEACON_UC BIT(21)
#define MT_RXD3_NORMAL_AMSDU BIT(22)
#define MT_RXD3_NORMAL_MESH BIT(23)
#define MT_RXD3_NORMAL_MHCP BIT(24)
#define MT_RXD3_NORMAL_NO_INFO_WB BIT(25)
#define MT_RXD3_NORMAL_DISABLE_RX_HDR_TRANS BIT(26)
#define MT_RXD3_NORMAL_POWER_SAVE_STAT BIT(27)
#define MT_RXD3_NORMAL_MORE BIT(28)
#define MT_RXD3_NORMAL_UNWANT BIT(29)
#define MT_RXD3_NORMAL_RX_DROP BIT(30)
#define MT_RXD3_NORMAL_VLAN2ETH BIT(31)
/* RXD DW4 */
#define MT_RXD4_NORMAL_PAYLOAD_FORMAT GENMASK(1, 0)
#define MT_RXD4_NORMAL_PATTERN_DROP BIT(9)
#define MT_RXD4_NORMAL_CLS BIT(10)
#define MT_RXD4_NORMAL_OFLD GENMASK(12, 11)
#define MT_RXD4_NORMAL_MAGIC_PKT BIT(13)
#define MT_RXD4_NORMAL_WOL GENMASK(18, 14)
#define MT_RXD4_NORMAL_CLS_BITMAP GENMASK(28, 19)
#define MT_RXD3_NORMAL_PF_MODE BIT(29)
#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30)
/* P-RXV */
#define MT_PRXV_TX_RATE GENMASK(6, 0)
#define MT_PRXV_TX_DCM BIT(4)
#define MT_PRXV_TX_ER_SU_106T BIT(5)
#define MT_PRXV_NSTS GENMASK(9, 7)
#define MT_PRXV_HT_AD_CODE BIT(11)
#define MT_PRXV_HE_RU_ALLOC_L GENMASK(31, 28)
#define MT_PRXV_HE_RU_ALLOC_H GENMASK(3, 0)
#define MT_PRXV_RCPI3 GENMASK(31, 24)
#define MT_PRXV_RCPI2 GENMASK(23, 16)
#define MT_PRXV_RCPI1 GENMASK(15, 8)
#define MT_PRXV_RCPI0 GENMASK(7, 0)
/* C-RXV */
#define MT_CRXV_HT_STBC GENMASK(1, 0)
#define MT_CRXV_TX_MODE GENMASK(7, 4)
#define MT_CRXV_FRAME_MODE GENMASK(10, 8)
#define MT_CRXV_HT_SHORT_GI GENMASK(14, 13)
#define MT_CRXV_HE_LTF_SIZE GENMASK(18, 17)
#define MT_CRXV_HE_LDPC_EXT_SYM BIT(20)
#define MT_CRXV_HE_PE_DISAMBIG BIT(23)
#define MT_CRXV_HE_UPLINK BIT(31)
#define MT_CRXV_HE_SR_MASK GENMASK(11, 8)
#define MT_CRXV_HE_SR1_MASK GENMASK(16, 12)
#define MT_CRXV_HE_SR2_MASK GENMASK(20, 17)
#define MT_CRXV_HE_SR3_MASK GENMASK(24, 21)
#define MT_CRXV_HE_BSS_COLOR GENMASK(5, 0)
#define MT_CRXV_HE_TXOP_DUR GENMASK(12, 6)
#define MT_CRXV_HE_BEAM_CHNG BIT(13)
#define MT_CRXV_HE_DOPPLER BIT(16)
#define MT_CRXV_SNR GENMASK(18, 13)
#define MT_CRXV_FOE_LO GENMASK(31, 19)
#define MT_CRXV_FOE_HI GENMASK(6, 0)
#define MT_CRXV_FOE_SHIFT 13
enum tx_header_format {
MT_HDR_FORMAT_802_3,
MT_HDR_FORMAT_CMD,
MT_HDR_FORMAT_802_11,
MT_HDR_FORMAT_802_11_EXT,
};
enum tx_pkt_type {
MT_TX_TYPE_CT,
MT_TX_TYPE_SF,
MT_TX_TYPE_CMD,
MT_TX_TYPE_FW,
};
enum tx_port_idx {
MT_TX_PORT_IDX_LMAC,
MT_TX_PORT_IDX_MCU
};
enum tx_mcu_port_q_idx {
MT_TX_MCU_PORT_RX_Q0 = 0x20,
MT_TX_MCU_PORT_RX_Q1,
MT_TX_MCU_PORT_RX_Q2,
MT_TX_MCU_PORT_RX_Q3,
MT_TX_MCU_PORT_RX_FWDL = 0x3e
};
#define MT_CT_INFO_APPLY_TXD BIT(0)
#define MT_CT_INFO_COPY_HOST_TXD_ALL BIT(1)
#define MT_CT_INFO_MGMT_FRAME BIT(2)
#define MT_CT_INFO_NONE_CIPHER_FRAME BIT(3)
#define MT_CT_INFO_HSR2_TX BIT(4)
#define MT_CT_INFO_FROM_HOST BIT(7)
#define MT_TXD_SIZE (8 * 4)
#define MT_TXD0_Q_IDX GENMASK(31, 25)
#define MT_TXD0_PKT_FMT GENMASK(24, 23)
#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
#define MT_TXD0_TX_BYTES GENMASK(15, 0)
#define MT_TXD1_LONG_FORMAT BIT(31)
#define MT_TXD1_TGID BIT(30)
#define MT_TXD1_OWN_MAC GENMASK(29, 24)
#define MT_TXD1_AMSDU BIT(23)
#define MT_TXD1_TID GENMASK(22, 20)
#define MT_TXD1_HDR_PAD GENMASK(19, 18)
#define MT_TXD1_HDR_FORMAT GENMASK(17, 16)
#define MT_TXD1_HDR_INFO GENMASK(15, 11)
#define MT_TXD1_ETH_802_3 BIT(15)
#define MT_TXD1_VTA BIT(10)
#define MT_TXD1_WLAN_IDX GENMASK(9, 0)
#define MT_TXD2_FIX_RATE BIT(31)
#define MT_TXD2_FIXED_RATE BIT(30)
#define MT_TXD2_POWER_OFFSET GENMASK(29, 24)
#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16)
#define MT_TXD2_FRAG GENMASK(15, 14)
#define MT_TXD2_HTC_VLD BIT(13)
#define MT_TXD2_DURATION BIT(12)
#define MT_TXD2_BIP BIT(11)
#define MT_TXD2_MULTICAST BIT(10)
#define MT_TXD2_RTS BIT(9)
#define MT_TXD2_SOUNDING BIT(8)
#define MT_TXD2_NDPA BIT(7)
#define MT_TXD2_NDP BIT(6)
#define MT_TXD2_FRAME_TYPE GENMASK(5, 4)
#define MT_TXD2_SUB_TYPE GENMASK(3, 0)
#define MT_TXD3_SN_VALID BIT(31)
#define MT_TXD3_PN_VALID BIT(30)
#define MT_TXD3_SW_POWER_MGMT BIT(29)
#define MT_TXD3_BA_DISABLE BIT(28)
#define MT_TXD3_SEQ GENMASK(27, 16)
#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11)
#define MT_TXD3_TX_COUNT GENMASK(10, 6)
#define MT_TXD3_TIMING_MEASURE BIT(5)
#define MT_TXD3_DAS BIT(4)
#define MT_TXD3_EEOSP BIT(3)
#define MT_TXD3_EMRD BIT(2)
#define MT_TXD3_PROTECT_FRAME BIT(1)
#define MT_TXD3_NO_ACK BIT(0)
#define MT_TXD4_PN_LOW GENMASK(31, 0)
#define MT_TXD5_PN_HIGH GENMASK(31, 16)
#define MT_TXD5_MD BIT(15)
#define MT_TXD5_ADD_BA BIT(14)
#define MT_TXD5_TX_STATUS_HOST BIT(10)
#define MT_TXD5_TX_STATUS_MCU BIT(9)
#define MT_TXD5_TX_STATUS_FMT BIT(8)
#define MT_TXD5_PID GENMASK(7, 0)
#define MT_TXD6_TX_IBF BIT(31)
#define MT_TXD6_TX_EBF BIT(30)
#define MT_TXD6_TX_RATE GENMASK(29, 16)
#define MT_TXD6_SGI GENMASK(15, 14)
#define MT_TXD6_HELTF GENMASK(13, 12)
#define MT_TXD6_LDPC BIT(11)
#define MT_TXD6_SPE_ID_IDX BIT(10)
#define MT_TXD6_ANT_ID GENMASK(7, 4)
#define MT_TXD6_DYN_BW BIT(3)
#define MT_TXD6_FIXED_BW BIT(2)
#define MT_TXD6_BW GENMASK(1, 0)
#define MT_TXD7_TXD_LEN GENMASK(31, 30)
#define MT_TXD7_UDP_TCP_SUM BIT(29)
#define MT_TXD7_IP_SUM BIT(28)
#define MT_TXD7_TYPE GENMASK(21, 20)
#define MT_TXD7_SUB_TYPE GENMASK(19, 16)
#define MT_TXD7_PSE_FID GENMASK(27, 16)
#define MT_TXD7_SPE_IDX GENMASK(15, 11)
#define MT_TXD7_HW_AMSDU BIT(10)
#define MT_TXD7_TX_TIME GENMASK(9, 0)
#define MT_TX_RATE_STBC BIT(13)
#define MT_TX_RATE_NSS GENMASK(12, 10)
#define MT_TX_RATE_MODE GENMASK(9, 6)
#define MT_TX_RATE_SU_EXT_TONE BIT(5)
#define MT_TX_RATE_DCM BIT(4)
#define MT_TX_RATE_IDX GENMASK(3, 0)
#define MT_TXP_MAX_BUF_NUM 6
struct mt7921_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
__le16 rept_wds_wcid;
u8 nbuf;
__le32 buf[MT_TXP_MAX_BUF_NUM];
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
struct mt7921_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
u8 txd_cnt;
u8 rsv[3];
__le32 info[];
} __packed __aligned(4);
#define MT_TX_FREE_MSDU_CNT GENMASK(9, 0)
#define MT_TX_FREE_WLAN_ID GENMASK(23, 14)
#define MT_TX_FREE_LATENCY GENMASK(12, 0)
/* 0: success, others: dropped */
#define MT_TX_FREE_STATUS GENMASK(14, 13)
#define MT_TX_FREE_MSDU_ID GENMASK(30, 16)
#define MT_TX_FREE_PAIR BIT(31)
/* will support this field in further revision */
#define MT_TX_FREE_RATE GENMASK(13, 0)
static inline struct mt7921_txp_common *
mt7921_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
if (!t)
return NULL;
txwi = mt76_get_txwi_ptr(dev, t);
return (struct mt7921_txp_common *)(txwi + MT_TXD_SIZE);
}
#define MT_HW_TXP_MAX_MSDU_NUM 4
#define MT_HW_TXP_MAX_BUF_NUM 4
#define MT_MSDU_ID_VALID BIT(15)
#define MT_TXD_LEN_MASK GENMASK(11, 0)
#define MT_TXD_LEN_MSDU_LAST BIT(14)
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
#define MT_TXD_LEN_LAST BIT(15)
struct mt7921_txp_ptr {
__le32 buf0;
__le16 len0;
__le16 len1;
__le32 buf1;
} __packed __aligned(4);
struct mt7921_hw_txp {
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
struct mt7921_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
} __packed __aligned(4);
struct mt7921_txp_common {
union {
struct mt7921_hw_txp hw;
};
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,434 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT7921_MCU_H
#define __MT7921_MCU_H
#include "../mt76_connac_mcu.h"
struct mt7921_mcu_txd {
__le32 txd[8];
__le16 len;
__le16 pq_id;
u8 cid;
u8 pkt_type;
u8 set_query; /* FW don't care */
u8 seq;
u8 uc_d2b0_rev;
u8 ext_cid;
u8 s2d_index;
u8 ext_cid_ack;
u32 reserved[5];
} __packed __aligned(4);
/**
* struct mt7921_uni_txd - mcu command descriptor for firmware v3
* @txd: hardware descriptor
* @len: total length not including txd
* @cid: command identifier
* @pkt_type: must be 0xa0 (cmd packet by long format)
* @frag_n: fragment number
* @seq: sequence number
* @checksum: 0 mean there is no checksum
* @s2d_index: index for command source and destination
* Definition | value | note
* CMD_S2D_IDX_H2N | 0x00 | command from HOST to WM
* CMD_S2D_IDX_C2N | 0x01 | command from WA to WM
* CMD_S2D_IDX_H2C | 0x02 | command from HOST to WA
* CMD_S2D_IDX_H2N_AND_H2C | 0x03 | command from HOST to WA and WM
*
* @option: command option
* BIT[0]: UNI_CMD_OPT_BIT_ACK
* set to 1 to request a fw reply
* if UNI_CMD_OPT_BIT_0_ACK is set and UNI_CMD_OPT_BIT_2_SET_QUERY
* is set, mcu firmware will send response event EID = 0x01
* (UNI_EVENT_ID_CMD_RESULT) to the host.
* BIT[1]: UNI_CMD_OPT_BIT_UNI_CMD
* 0: original command
* 1: unified command
* BIT[2]: UNI_CMD_OPT_BIT_SET_QUERY
* 0: QUERY command
* 1: SET command
*/
struct mt7921_uni_txd {
__le32 txd[8];
/* DW1 */
__le16 len;
__le16 cid;
/* DW2 */
u8 reserved;
u8 pkt_type;
u8 frag_n;
u8 seq;
/* DW3 */
__le16 checksum;
u8 s2d_index;
u8 option;
/* DW4 */
u8 reserved2[4];
} __packed __aligned(4);
/* event table */
enum {
MCU_EVENT_REG_ACCESS = 0x05,
MCU_EVENT_SCAN_DONE = 0x0d,
MCU_EVENT_BSS_ABSENCE = 0x11,
MCU_EVENT_BSS_BEACON_LOSS = 0x13,
MCU_EVENT_CH_PRIVILEGE = 0x18,
MCU_EVENT_SCHED_SCAN_DONE = 0x23,
MCU_EVENT_DBG_MSG = 0x27,
MCU_EVENT_COREDUMP = 0xf0,
};
/* ext event table */
enum {
MCU_EXT_EVENT_RATE_REPORT = 0x87,
};
struct mt7921_mcu_rxd {
__le32 rxd[6];
__le16 len;
__le16 pkt_type_id;
u8 eid;
u8 seq;
__le16 __rsv;
u8 ext_eid;
u8 __rsv1[2];
u8 s2d_index;
};
struct mt7921_mcu_eeprom_info {
__le32 addr;
__le32 valid;
u8 data[16];
} __packed;
#define MT_RA_RATE_NSS GENMASK(8, 6)
#define MT_RA_RATE_MCS GENMASK(3, 0)
#define MT_RA_RATE_TX_MODE GENMASK(12, 9)
#define MT_RA_RATE_DCM_EN BIT(4)
#define MT_RA_RATE_BW GENMASK(14, 13)
#define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10))
#define MCU_PKT_ID 0xa0
enum {
MCU_Q_QUERY,
MCU_Q_SET,
MCU_Q_RESERVED,
MCU_Q_NA
};
enum {
MCU_S2D_H2N,
MCU_S2D_C2N,
MCU_S2D_H2C,
MCU_S2D_H2CN
};
struct mt7921_mcu_uni_event {
u8 cid;
u8 pad[3];
__le32 status; /* 0: success, others: fail */
} __packed;
enum {
PATCH_NOT_DL_SEM_FAIL,
PATCH_IS_DL,
PATCH_NOT_DL_SEM_SUCCESS,
PATCH_REL_SEM_SUCCESS
};
enum {
FW_STATE_INITIAL,
FW_STATE_FW_DOWNLOAD,
FW_STATE_NORMAL_OPERATION,
FW_STATE_NORMAL_TRX,
FW_STATE_WACPU_RDY = 7
};
enum {
EE_MODE_EFUSE,
EE_MODE_BUFFER,
};
enum {
EE_FORMAT_BIN,
EE_FORMAT_WHOLE,
EE_FORMAT_MULTIPLE,
};
enum {
MCU_PHY_STATE_TX_RATE,
MCU_PHY_STATE_RX_RATE,
MCU_PHY_STATE_RSSI,
MCU_PHY_STATE_CONTENTION_RX_RATE,
MCU_PHY_STATE_OFDMLQ_CNINFO,
};
#define STA_TYPE_STA BIT(0)
#define STA_TYPE_AP BIT(1)
#define STA_TYPE_ADHOC BIT(2)
#define STA_TYPE_WDS BIT(4)
#define STA_TYPE_BC BIT(5)
#define NETWORK_INFRA BIT(16)
#define NETWORK_P2P BIT(17)
#define NETWORK_IBSS BIT(18)
#define NETWORK_WDS BIT(21)
#define CONNECTION_INFRA_STA (STA_TYPE_STA | NETWORK_INFRA)
#define CONNECTION_INFRA_AP (STA_TYPE_AP | NETWORK_INFRA)
#define CONNECTION_P2P_GC (STA_TYPE_STA | NETWORK_P2P)
#define CONNECTION_P2P_GO (STA_TYPE_AP | NETWORK_P2P)
#define CONNECTION_IBSS_ADHOC (STA_TYPE_ADHOC | NETWORK_IBSS)
#define CONNECTION_WDS (STA_TYPE_WDS | NETWORK_WDS)
#define CONNECTION_INFRA_BC (STA_TYPE_BC | NETWORK_INFRA)
struct sec_key {
u8 cipher_id;
u8 cipher_len;
u8 key_id;
u8 key_len;
u8 key[32];
} __packed;
struct sta_rec_sec {
__le16 tag;
__le16 len;
u8 add;
u8 n_cipher;
u8 rsv[2];
struct sec_key key[2];
} __packed;
enum mt7921_cipher_type {
MT_CIPHER_NONE,
MT_CIPHER_WEP40,
MT_CIPHER_WEP104,
MT_CIPHER_WEP128,
MT_CIPHER_TKIP,
MT_CIPHER_AES_CCMP,
MT_CIPHER_CCMP_256,
MT_CIPHER_GCMP,
MT_CIPHER_GCMP_256,
MT_CIPHER_WAPI,
MT_CIPHER_BIP_CMAC_128,
};
enum {
CH_SWITCH_NORMAL = 0,
CH_SWITCH_SCAN = 3,
CH_SWITCH_MCC = 4,
CH_SWITCH_DFS = 5,
CH_SWITCH_BACKGROUND_SCAN_START = 6,
CH_SWITCH_BACKGROUND_SCAN_RUNNING = 7,
CH_SWITCH_BACKGROUND_SCAN_STOP = 8,
CH_SWITCH_SCAN_BYPASS_DPD = 9
};
enum {
THERMAL_SENSOR_TEMP_QUERY,
THERMAL_SENSOR_MANUAL_CTRL,
THERMAL_SENSOR_INFO_QUERY,
THERMAL_SENSOR_TASK_CTRL,
};
enum {
MT_EBF = BIT(0), /* explicit beamforming */
MT_IBF = BIT(1) /* implicit beamforming */
};
#define MT7921_WTBL_UPDATE_MAX_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_generic) + \
sizeof(struct wtbl_rx) + \
sizeof(struct wtbl_ht) + \
sizeof(struct wtbl_vht) + \
sizeof(struct wtbl_hdr_trans) +\
sizeof(struct wtbl_ba) + \
sizeof(struct wtbl_smps))
#define MT7921_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
sizeof(struct sta_rec_basic) + \
sizeof(struct sta_rec_ht) + \
sizeof(struct sta_rec_he) + \
sizeof(struct sta_rec_ba) + \
sizeof(struct sta_rec_vht) + \
sizeof(struct sta_rec_uapsd) + \
sizeof(struct sta_rec_amsdu) + \
sizeof(struct tlv) + \
MT7921_WTBL_UPDATE_MAX_SIZE)
#define MT7921_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \
sizeof(struct wtbl_ba))
#define STA_CAP_WMM BIT(0)
#define STA_CAP_SGI_20 BIT(4)
#define STA_CAP_SGI_40 BIT(5)
#define STA_CAP_TX_STBC BIT(6)
#define STA_CAP_RX_STBC BIT(7)
#define STA_CAP_VHT_SGI_80 BIT(16)
#define STA_CAP_VHT_SGI_160 BIT(17)
#define STA_CAP_VHT_TX_STBC BIT(18)
#define STA_CAP_VHT_RX_STBC BIT(19)
#define STA_CAP_VHT_LDPC BIT(23)
#define STA_CAP_LDPC BIT(24)
#define STA_CAP_HT BIT(26)
#define STA_CAP_VHT BIT(27)
#define STA_CAP_HE BIT(28)
struct mt7921_mcu_reg_event {
__le32 reg;
__le32 val;
} __packed;
struct mt7921_mcu_tx_config {
u8 peer_addr[ETH_ALEN];
u8 sw;
u8 dis_rx_hdr_tran;
u8 aad_om;
u8 pfmu_idx;
__le16 partial_aid;
u8 ibf;
u8 ebf;
u8 is_ht;
u8 is_vht;
u8 mesh;
u8 baf_en;
u8 cf_ack;
u8 rdg_ba;
u8 rdg;
u8 pm;
u8 rts;
u8 smps;
u8 txop_ps;
u8 not_update_ipsm;
u8 skip_tx;
u8 ldpc;
u8 qos;
u8 from_ds;
u8 to_ds;
u8 dyn_bw;
u8 amdsu_cross_lg;
u8 check_per;
u8 gid_63;
u8 he;
u8 vht_ibf;
u8 vht_ebf;
u8 vht_ldpc;
u8 he_ldpc;
} __packed;
struct mt7921_mcu_sec_config {
u8 wpi_flag;
u8 rv;
u8 ikv;
u8 rkv;
u8 rcid;
u8 rca1;
u8 rca2;
u8 even_pn;
u8 key_id;
u8 muar_idx;
u8 cipher_suit;
u8 rsv[1];
} __packed;
struct mt7921_mcu_key_config {
u8 key[32];
} __packed;
struct mt7921_mcu_rate_info {
u8 mpdu_fail;
u8 mpdu_tx;
u8 rate_idx;
u8 rsv[1];
__le16 rate[8];
} __packed;
struct mt7921_mcu_ba_config {
u8 ba_en;
u8 rsv[3];
__le32 ba_winsize;
} __packed;
struct mt7921_mcu_ant_id_config {
u8 ant_id[4];
} __packed;
struct mt7921_mcu_peer_cap {
struct mt7921_mcu_ant_id_config ant_id_config;
u8 power_offset;
u8 bw_selector;
u8 change_bw_rate_n;
u8 bw;
u8 spe_idx;
u8 g2;
u8 g4;
u8 g8;
u8 g16;
u8 mmss;
u8 ampdu_factor;
u8 rsv[1];
} __packed;
struct mt7921_mcu_rx_cnt {
u8 rx_rcpi[4];
u8 rx_cc[4];
u8 rx_cc_sel;
u8 ce_rmsd;
u8 rsv[2];
} __packed;
struct mt7921_mcu_tx_cnt {
__le16 rate1_cnt;
__le16 rate1_fail_cnt;
__le16 rate2_cnt;
__le16 rate3_cnt;
__le16 cur_bw_tx_cnt;
__le16 cur_bw_tx_fail_cnt;
__le16 other_bw_tx_cnt;
__le16 other_bw_tx_fail_cnt;
} __packed;
struct mt7921_mcu_wlan_info_event {
struct mt7921_mcu_tx_config tx_config;
struct mt7921_mcu_sec_config sec_config;
struct mt7921_mcu_key_config key_config;
struct mt7921_mcu_rate_info rate_info;
struct mt7921_mcu_ba_config ba_config;
struct mt7921_mcu_peer_cap peer_cap;
struct mt7921_mcu_rx_cnt rx_cnt;
struct mt7921_mcu_tx_cnt tx_cnt;
} __packed;
struct mt7921_mcu_wlan_info {
__le32 wlan_idx;
struct mt7921_mcu_wlan_info_event event;
} __packed;
#endif

View File

@ -0,0 +1,342 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT7921_H
#define __MT7921_H
#include <linux/interrupt.h>
#include <linux/ktime.h>
#include "../mt76_connac_mcu.h"
#include "regs.h"
#define MT7921_MAX_INTERFACES 4
#define MT7921_MAX_WMM_SETS 4
#define MT7921_WTBL_SIZE 20
#define MT7921_WTBL_RESERVED (MT7921_WTBL_SIZE - 1)
#define MT7921_WTBL_STA (MT7921_WTBL_RESERVED - \
MT7921_MAX_INTERFACES)
#define MT7921_PM_TIMEOUT (HZ / 12)
#define MT7921_HW_SCAN_TIMEOUT (HZ / 10)
#define MT7921_WATCHDOG_TIME (HZ / 10)
#define MT7921_RESET_TIMEOUT (30 * HZ)
#define MT7921_TX_RING_SIZE 2048
#define MT7921_TX_MCU_RING_SIZE 256
#define MT7921_TX_FWDL_RING_SIZE 128
#define MT7921_RX_RING_SIZE 1536
#define MT7921_RX_MCU_RING_SIZE 512
#define MT7921_DRV_OWN_RETRY_COUNT 10
#define MT7921_FIRMWARE_WM "mediatek/WIFI_RAM_CODE_MT7961_1.bin"
#define MT7921_ROM_PATCH "mediatek/WIFI_MT7961_patch_mcu_1_2_hdr.bin"
#define MT7921_EEPROM_SIZE 3584
#define MT7921_TOKEN_SIZE 8192
#define MT7921_TOKEN_FREE_THR 64
#define MT7921_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */
#define MT7921_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
#define MT7921_5G_RATE_DEFAULT 0x4b /* OFDM 6M */
#define MT7921_2G_RATE_DEFAULT 0x0 /* CCK 1M */
#define MT7921_SKU_RATE_NUM 161
#define MT7921_SKU_MAX_DELTA_IDX MT7921_SKU_RATE_NUM
#define MT7921_SKU_TABLE_SIZE (MT7921_SKU_RATE_NUM + 1)
struct mt7921_vif;
struct mt7921_sta;
enum mt7921_txq_id {
MT7921_TXQ_BAND0,
MT7921_TXQ_BAND1,
MT7921_TXQ_FWDL = 16,
MT7921_TXQ_MCU_WM,
};
enum mt7921_rxq_id {
MT7921_RXQ_BAND0 = 0,
MT7921_RXQ_BAND1,
MT7921_RXQ_MCU_WM = 0,
};
struct mt7921_sta_stats {
struct rate_info prob_rate;
struct rate_info tx_rate;
unsigned long per;
unsigned long changed;
unsigned long jiffies;
};
struct mt7921_sta_key_conf {
s8 keyidx;
u8 key[16];
};
struct mt7921_sta {
struct mt76_wcid wcid; /* must be first */
struct mt7921_vif *vif;
struct list_head stats_list;
struct list_head poll_list;
u32 airtime_ac[8];
struct mt7921_sta_stats stats;
unsigned long ampdu_state;
struct mt7921_sta_key_conf bip;
};
struct mt7921_vif {
struct mt76_vif mt76; /* must be first */
struct mt7921_sta sta;
struct mt7921_phy *phy;
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
};
struct mib_stats {
u16 ack_fail_cnt;
u16 fcs_err_cnt;
u16 rts_cnt;
u16 rts_retries_cnt;
u16 ba_miss_cnt;
};
struct mt7921_phy {
struct mt76_phy *mt76;
struct mt7921_dev *dev;
struct ieee80211_sband_iftype_data iftype[2][NUM_NL80211_IFTYPES];
struct ieee80211_vif *monitor_vif;
u32 rxfilter;
u64 omac_mask;
u16 noise;
s16 coverage_class;
u8 slottime;
__le32 rx_ampdu_ts;
u32 ampdu_ref;
struct mib_stats mib;
struct list_head stats_list;
u8 sta_work_count;
struct sk_buff_head scan_event_list;
struct delayed_work scan_work;
};
struct mt7921_dev {
union { /* must be first */
struct mt76_dev mt76;
struct mt76_phy mphy;
};
const struct mt76_bus_ops *bus_ops;
struct mt7921_phy phy;
struct tasklet_struct irq_tasklet;
u16 chainmask;
struct work_struct init_work;
struct work_struct reset_work;
wait_queue_head_t reset_wait;
u32 reset_state;
struct list_head sta_poll_list;
spinlock_t sta_poll_lock;
spinlock_t token_lock;
int token_count;
struct idr token;
u8 fw_debug;
struct mt76_connac_pm pm;
struct mt76_connac_coredump coredump;
};
enum {
MT_LMAC_AC00,
MT_LMAC_AC01,
MT_LMAC_AC02,
MT_LMAC_AC03,
MT_LMAC_ALTX0 = 0x10,
MT_LMAC_BMC0,
MT_LMAC_BCN0,
};
static inline struct mt7921_phy *
mt7921_hw_phy(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return phy->priv;
}
static inline struct mt7921_dev *
mt7921_hw_dev(struct ieee80211_hw *hw)
{
struct mt76_phy *phy = hw->priv;
return container_of(phy->dev, struct mt7921_dev, mt76);
}
#define mt7921_mutex_acquire(dev) \
mt76_connac_mutex_acquire(&(dev)->mt76, &(dev)->pm)
#define mt7921_mutex_release(dev) \
mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
static inline u8 mt7921_lmac_mapping(struct mt7921_dev *dev, u8 ac)
{
/* LMAC uses the reverse order of mac80211 AC indexes */
return 3 - ac;
}
extern const struct ieee80211_ops mt7921_ops;
extern struct pci_driver mt7921_pci_driver;
u32 mt7921_reg_map(struct mt7921_dev *dev, u32 addr);
int mt7921_register_device(struct mt7921_dev *dev);
void mt7921_unregister_device(struct mt7921_dev *dev);
int mt7921_eeprom_init(struct mt7921_dev *dev);
void mt7921_eeprom_parse_band_config(struct mt7921_phy *phy);
int mt7921_eeprom_get_target_power(struct mt7921_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx);
void mt7921_eeprom_init_sku(struct mt7921_dev *dev);
int mt7921_dma_init(struct mt7921_dev *dev);
void mt7921_dma_prefetch(struct mt7921_dev *dev);
void mt7921_dma_cleanup(struct mt7921_dev *dev);
int mt7921_mcu_init(struct mt7921_dev *dev);
int mt7921_mcu_add_bss_info(struct mt7921_phy *phy,
struct ieee80211_vif *vif, int enable);
int mt7921_mcu_add_key(struct mt7921_dev *dev, struct ieee80211_vif *vif,
struct mt7921_sta *msta, struct ieee80211_key_conf *key,
enum set_key_cmd cmd);
int mt7921_set_channel(struct mt7921_phy *phy);
int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd);
int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif);
int mt7921_mcu_set_eeprom(struct mt7921_dev *dev);
int mt7921_mcu_get_eeprom(struct mt7921_dev *dev, u32 offset);
int mt7921_mcu_get_rx_rate(struct mt7921_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct rate_info *rate);
int mt7921_mcu_fw_log_2_host(struct mt7921_dev *dev, u8 ctrl);
void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb);
void mt7921_mcu_exit(struct mt7921_dev *dev);
static inline void mt7921_irq_enable(struct mt7921_dev *dev, u32 mask)
{
mt76_set_irq_mask(&dev->mt76, 0, 0, mask);
tasklet_schedule(&dev->irq_tasklet);
}
static inline u32
mt7921_reg_map_l1(struct mt7921_dev *dev, u32 addr)
{
u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
mt76_rmw_field(dev, MT_HIF_REMAP_L1, MT_HIF_REMAP_L1_MASK, base);
/* use read to push write */
mt76_rr(dev, MT_HIF_REMAP_L1);
return MT_HIF_REMAP_BASE_L1 + offset;
}
static inline u32
mt7921_l1_rr(struct mt7921_dev *dev, u32 addr)
{
return mt76_rr(dev, mt7921_reg_map_l1(dev, addr));
}
static inline void
mt7921_l1_wr(struct mt7921_dev *dev, u32 addr, u32 val)
{
mt76_wr(dev, mt7921_reg_map_l1(dev, addr), val);
}
static inline u32
mt7921_l1_rmw(struct mt7921_dev *dev, u32 addr, u32 mask, u32 val)
{
val |= mt7921_l1_rr(dev, addr) & ~mask;
mt7921_l1_wr(dev, addr, val);
return val;
}
#define mt7921_l1_set(dev, addr, val) mt7921_l1_rmw(dev, addr, 0, val)
#define mt7921_l1_clear(dev, addr, val) mt7921_l1_rmw(dev, addr, val, 0)
bool mt7921_mac_wtbl_update(struct mt7921_dev *dev, int idx, u32 mask);
void mt7921_mac_reset_counters(struct mt7921_phy *phy);
void mt7921_mac_write_txwi(struct mt7921_dev *dev, __le32 *txwi,
struct sk_buff *skb, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key, bool beacon);
void mt7921_mac_set_timing(struct mt7921_phy *phy);
int mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb);
void mt7921_mac_fill_rx_vector(struct mt7921_dev *dev, struct sk_buff *skb);
void mt7921_mac_tx_free(struct mt7921_dev *dev, struct sk_buff *skb);
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
void mt7921_mac_work(struct work_struct *work);
void mt7921_mac_reset_work(struct work_struct *work);
int mt7921_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info);
void mt7921_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
int mt7921_init_tx_queues(struct mt7921_phy *phy, int idx, int n_desc);
void mt7921_tx_token_put(struct mt7921_dev *dev);
void mt7921_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb);
void mt7921_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps);
void mt7921_stats_work(struct work_struct *work);
void mt7921_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *txwi);
void mt7921_set_stream_he_caps(struct mt7921_phy *phy);
void mt7921_update_channel(struct mt76_dev *mdev);
int mt7921_init_debugfs(struct mt7921_dev *dev);
int mt7921_mcu_uni_tx_ba(struct mt7921_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
struct ieee80211_ampdu_params *params,
bool enable);
void mt7921_scan_work(struct work_struct *work);
u32 mt7921_get_wtbl_info(struct mt7921_dev *dev, u32 wlan_idx);
int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
int mt7921_mcu_uni_bss_bcnft(struct mt7921_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
bool enable);
int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info);
int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
void mt7921_pm_wake_work(struct work_struct *work);
void mt7921_pm_power_save_work(struct work_struct *work);
bool mt7921_wait_for_mcu_init(struct mt7921_dev *dev);
int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy,
struct ieee80211_vif *vif,
bool enable);
void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
void mt7921_coredump_work(struct work_struct *work);
#endif

View File

@ -0,0 +1,292 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "mt7921.h"
#include "mac.h"
#include "mcu.h"
#include "../trace.h"
static const struct pci_device_id mt7921_pci_device_table[] = {
{ PCI_DEVICE(0x14c3, 0x7961) },
{ },
};
static void
mt7921_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
{
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
if (q == MT_RXQ_MAIN)
mt7921_irq_enable(dev, MT_INT_RX_DONE_DATA);
else if (q == MT_RXQ_MCU_WA)
mt7921_irq_enable(dev, MT_INT_RX_DONE_WM2);
else
mt7921_irq_enable(dev, MT_INT_RX_DONE_WM);
}
static irqreturn_t mt7921_irq_handler(int irq, void *dev_instance)
{
struct mt7921_dev *dev = dev_instance;
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
tasklet_schedule(&dev->irq_tasklet);
return IRQ_HANDLED;
}
static void mt7921_irq_tasklet(unsigned long data)
{
struct mt7921_dev *dev = (struct mt7921_dev *)data;
u32 intr, mask = 0;
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
intr = mt76_rr(dev, MT_WFDMA0_HOST_INT_STA);
intr &= dev->mt76.mmio.irqmask;
mt76_wr(dev, MT_WFDMA0_HOST_INT_STA, intr);
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
mask |= intr & MT_INT_RX_DONE_ALL;
if (intr & MT_INT_TX_DONE_MCU)
mask |= MT_INT_TX_DONE_MCU;
mt76_set_irq_mask(&dev->mt76, MT_WFDMA0_HOST_INT_ENA, mask, 0);
if (intr & MT_INT_TX_DONE_ALL)
napi_schedule(&dev->mt76.tx_napi);
if (intr & MT_INT_RX_DONE_WM)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU]);
if (intr & MT_INT_RX_DONE_WM2)
napi_schedule(&dev->mt76.napi[MT_RXQ_MCU_WA]);
if (intr & MT_INT_RX_DONE_DATA)
napi_schedule(&dev->mt76.napi[MT_RXQ_MAIN]);
}
static int mt7921_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7921_txp_common),
.drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ |
MT_DRV_AMSDU_OFFLOAD,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
.tx_prepare_skb = mt7921_tx_prepare_skb,
.tx_complete_skb = mt7921_tx_complete_skb,
.rx_skb = mt7921_queue_rx_skb,
.rx_poll_complete = mt7921_rx_poll_complete,
.sta_ps = mt7921_sta_ps,
.sta_add = mt7921_mac_sta_add,
.sta_remove = mt7921_mac_sta_remove,
.update_survey = mt7921_update_channel,
};
struct mt7921_dev *dev;
struct mt76_dev *mdev;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
if (ret)
return ret;
pci_set_master(pdev);
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0)
return ret;
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret)
goto err_free_pci_vec;
mt76_pci_disable_aspm(pdev);
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7921_ops,
&drv_ops);
if (!mdev) {
ret = -ENOMEM;
goto err_free_pci_vec;
}
dev = container_of(mdev, struct mt7921_dev, mt76);
mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
mdev->rev = (mt7921_l1_rr(dev, MT_HW_CHIPID) << 16) |
(mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
dev_err(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
ret = devm_request_irq(mdev->dev, pdev->irq, mt7921_irq_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (ret)
goto err_free_dev;
ret = mt7921_register_device(dev);
if (ret)
goto err_free_dev;
return 0;
err_free_dev:
mt76_free_device(&dev->mt76);
err_free_pci_vec:
pci_free_irq_vectors(pdev);
return ret;
}
static void mt7921_pci_remove(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
mt7921_unregister_device(dev);
devm_free_irq(&pdev->dev, pdev->irq, dev);
pci_free_irq_vectors(pdev);
}
#ifdef CONFIG_PM
static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
bool hif_suspend;
int i, err;
err = mt76_connac_pm_wake(&dev->mphy, &dev->pm);
if (err < 0)
return err;
hif_suspend = !test_bit(MT76_STATE_SUSPEND, &dev->mphy.state);
if (hif_suspend) {
err = mt76_connac_mcu_set_hif_suspend(mdev, true);
if (err)
return err;
}
napi_disable(&mdev->tx_napi);
mt76_worker_disable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_disable(&mdev->napi[i]);
}
tasklet_kill(&dev->irq_tasklet);
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
/* wait until dma is idle */
mt76_poll(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_BUSY |
MT_WFDMA0_GLO_CFG_RX_DMA_BUSY, 0, 1000);
/* put dma disabled */
mt76_clear(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
/* disable interrupt */
mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
pci_save_state(pdev);
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err)
goto restore;
err = mt7921_mcu_drv_pmctrl(dev);
if (err)
goto restore;
return 0;
restore:
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
if (hif_suspend)
mt76_connac_mcu_set_hif_suspend(mdev, false);
return err;
}
static int mt7921_pci_resume(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
int i, err;
err = mt7921_mcu_fw_pmctrl(dev);
if (err < 0)
return err;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
/* enable interrupt */
mt7921_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
mt7921_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
MT_INT_MCU_CMD);
/* put dma enabled */
mt76_set(dev, MT_WFDMA0_GLO_CFG,
MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
mt76_worker_enable(&mdev->tx_worker);
mt76_for_each_q_rx(mdev, i) {
napi_enable(&mdev->napi[i]);
napi_schedule(&mdev->napi[i]);
}
napi_enable(&mdev->tx_napi);
napi_schedule(&mdev->tx_napi);
if (!test_bit(MT76_STATE_SUSPEND, &dev->mphy.state))
err = mt76_connac_mcu_set_hif_suspend(mdev, false);
return err;
}
#endif /* CONFIG_PM */
struct pci_driver mt7921_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7921_pci_device_table,
.probe = mt7921_pci_probe,
.remove = mt7921_pci_remove,
#ifdef CONFIG_PM
.suspend = mt7921_pci_suspend,
.resume = mt7921_pci_resume,
#endif /* CONFIG_PM */
};
module_pci_driver(mt7921_pci_driver);
MODULE_DEVICE_TABLE(pci, mt7921_pci_device_table);
MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
MODULE_FIRMWARE(MT7921_ROM_PATCH);
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
MODULE_LICENSE("Dual BSD/GPL");

View File

@ -0,0 +1,419 @@
/* SPDX-License-Identifier: ISC */
/* Copyright (C) 2020 MediaTek Inc. */
#ifndef __MT7921_REGS_H
#define __MT7921_REGS_H
/* MCU WFDMA1 */
#define MT_MCU_WFDMA1_BASE 0x3000
#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs))
#define MT_MCU_INT_EVENT MT_MCU_WFDMA1(0x108)
#define MT_MCU_INT_EVENT_DMA_STOPPED BIT(0)
#define MT_MCU_INT_EVENT_DMA_INIT BIT(1)
#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2)
#define MT_MCU_INT_EVENT_RESET_DONE BIT(3)
#define MT_PLE_BASE 0x8000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)
#define MT_PLE_FL_Q2_CTRL MT_PLE(0x1b8)
#define MT_PLE_FL_Q3_CTRL MT_PLE(0x1bc)
#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \
((n) << 2))
#define MT_PLE_AMSDU_PACK_MSDU_CNT(n) MT_PLE(0x10e0 + ((n) << 2))
#define MT_MDP_BASE 0xf000
#define MT_MDP(ofs) (MT_MDP_BASE + (ofs))
#define MT_MDP_DCR0 MT_MDP(0x000)
#define MT_MDP_DCR0_DAMSDU_EN BIT(15)
#define MT_MDP_DCR0_RX_HDR_TRANS_EN BIT(19)
#define MT_MDP_DCR1 MT_MDP(0x004)
#define MT_MDP_DCR1_MAX_RX_LEN GENMASK(15, 3)
#define MT_MDP_BNRCFR0(_band) MT_MDP(0x070 + ((_band) << 8))
#define MT_MDP_RCFR0_MCU_RX_MGMT GENMASK(5, 4)
#define MT_MDP_RCFR0_MCU_RX_CTL_NON_BAR GENMASK(7, 6)
#define MT_MDP_RCFR0_MCU_RX_CTL_BAR GENMASK(9, 8)
#define MT_MDP_BNRCFR1(_band) MT_MDP(0x074 + ((_band) << 8))
#define MT_MDP_RCFR1_MCU_RX_BYPASS GENMASK(23, 22)
#define MT_MDP_RCFR1_RX_DROPPED_UCAST GENMASK(28, 27)
#define MT_MDP_RCFR1_RX_DROPPED_MCAST GENMASK(30, 29)
#define MT_MDP_TO_HIF 0
#define MT_MDP_TO_WM 1
/* TMAC: band 0(0x21000), band 1(0xa1000) */
#define MT_WF_TMAC_BASE(_band) ((_band) ? 0xa1000 : 0x21000)
#define MT_WF_TMAC(_band, ofs) (MT_WF_TMAC_BASE(_band) + (ofs))
#define MT_TMAC_TCR0(_band) MT_WF_TMAC(_band, 0)
#define MT_TMAC_TCR0_TBTT_STOP_CTRL BIT(25)
#define MT_TMAC_CDTR(_band) MT_WF_TMAC(_band, 0x090)
#define MT_TMAC_ODTR(_band) MT_WF_TMAC(_band, 0x094)
#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0)
#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16)
#define MT_TMAC_ICR0(_band) MT_WF_TMAC(_band, 0x0a4)
#define MT_IFS_EIFS GENMASK(8, 0)
#define MT_IFS_RIFS GENMASK(14, 10)
#define MT_IFS_SIFS GENMASK(22, 16)
#define MT_IFS_SLOT GENMASK(30, 24)
#define MT_TMAC_CTCR0(_band) MT_WF_TMAC(_band, 0x0f4)
#define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0)
#define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17)
#define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18)
#define MT_TMAC_TRCR0(_band) MT_WF_TMAC(_band, 0x09c)
#define MT_TMAC_TFCR0(_band) MT_WF_TMAC(_band, 0x1e0)
#define MT_WF_DMA_BASE(_band) ((_band) ? 0xa1e00 : 0x21e00)
#define MT_WF_DMA(_band, ofs) (MT_WF_DMA_BASE(_band) + (ofs))
#define MT_DMA_DCR0(_band) MT_WF_DMA(_band, 0x000)
#define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 3)
#define MT_DMA_DCR0_RXD_G5_EN BIT(23)
/* LPON: band 0(0x24200), band 1(0xa4200) */
#define MT_WF_LPON_BASE(_band) ((_band) ? 0xa4200 : 0x24200)
#define MT_WF_LPON(_band, ofs) (MT_WF_LPON_BASE(_band) + (ofs))
#define MT_LPON_UTTR0(_band) MT_WF_LPON(_band, 0x080)
#define MT_LPON_UTTR1(_band) MT_WF_LPON(_band, 0x084)
#define MT_LPON_TCR(_band, n) MT_WF_LPON(_band, 0x0a8 + (n) * 4)
#define MT_LPON_TCR_SW_MODE GENMASK(1, 0)
#define MT_LPON_TCR_SW_WRITE BIT(0)
/* MIB: band 0(0x24800), band 1(0xa4800) */
#define MT_WF_MIB_BASE(_band) ((_band) ? 0xa4800 : 0x24800)
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE(_band) + (ofs))
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014)
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0)
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR16(_band) MT_WF_MIB(_band, 0x048)
#define MT_MIB_SDR16_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR34(_band) MT_WF_MIB(_band, 0x090)
#define MT_MIB_MU_BF_TX_CNT GENMASK(15, 0)
#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098)
#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c)
#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0)
#define MT_MIB_DR8(_band) MT_WF_MIB(_band, 0x0c0)
#define MT_MIB_DR9(_band) MT_WF_MIB(_band, 0x0c4)
#define MT_MIB_DR11(_band) MT_WF_MIB(_band, 0x0cc)
#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(_band, 0x100 + ((n) << 4))
#define MT_MIB_RTS_RETRIES_COUNT_MASK GENMASK(31, 16)
#define MT_MIB_RTS_COUNT_MASK GENMASK(15, 0)
#define MT_MIB_MB_SDR1(_band, n) MT_WF_MIB(_band, 0x104 + ((n) << 4))
#define MT_MIB_BA_MISS_COUNT_MASK GENMASK(15, 0)
#define MT_MIB_ACK_FAIL_COUNT_MASK GENMASK(31, 16)
#define MT_MIB_MB_SDR2(_band, n) MT_WF_MIB(_band, 0x108 + ((n) << 4))
#define MT_MIB_FRAME_RETRIES_COUNT_MASK GENMASK(15, 0)
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0x0a8 + ((n) << 2))
#define MT_TX_AGG_CNT2(_band, n) MT_WF_MIB(_band, 0x164 + ((n) << 2))
#define MT_MIB_ARNG(_band, n) MT_WF_MIB(_band, 0x4b8 + ((n) << 2))
#define MT_MIB_ARNCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(7, 0))
#define MT_WTBLON_TOP_BASE 0x34000
#define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs))
#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x0)
#define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0)
#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x030)
#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0)
#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12)
#define MT_WTBL_UPDATE_BUSY BIT(31)
#define MT_WTBL_BASE 0x38000
#define MT_WTBL_LMAC_ID GENMASK(14, 8)
#define MT_WTBL_LMAC_DW GENMASK(7, 2)
#define MT_WTBL_LMAC_OFFS(_id, _dw) (MT_WTBL_BASE | \
FIELD_PREP(MT_WTBL_LMAC_ID, _id) | \
FIELD_PREP(MT_WTBL_LMAC_DW, _dw))
/* AGG: band 0(0x20800), band 1(0xa0800) */
#define MT_WF_AGG_BASE(_band) ((_band) ? 0xa0800 : 0x20800)
#define MT_WF_AGG(_band, ofs) (MT_WF_AGG_BASE(_band) + (ofs))
#define MT_AGG_AWSCR0(_band, _n) MT_WF_AGG(_band, 0x05c + (_n) * 4)
#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, 0x06c + (_n) * 4)
#define MT_AGG_PCR0_MM_PROT BIT(0)
#define MT_AGG_PCR0_GF_PROT BIT(1)
#define MT_AGG_PCR0_BW20_PROT BIT(2)
#define MT_AGG_PCR0_BW40_PROT BIT(4)
#define MT_AGG_PCR0_BW80_PROT BIT(6)
#define MT_AGG_PCR0_ERP_PROT GENMASK(12, 8)
#define MT_AGG_PCR0_VHT_PROT BIT(13)
#define MT_AGG_PCR0_PTA_WIN_DIS BIT(15)
#define MT_AGG_PCR1_RTS0_NUM_THRES GENMASK(31, 23)
#define MT_AGG_PCR1_RTS0_LEN_THRES GENMASK(19, 0)
#define MT_AGG_ACR0(_band) MT_WF_AGG(_band, 0x084)
#define MT_AGG_ACR_CFEND_RATE GENMASK(13, 0)
#define MT_AGG_ACR_BAR_RATE GENMASK(29, 16)
#define MT_AGG_MRCR(_band) MT_WF_AGG(_band, 0x098)
#define MT_AGG_MRCR_BAR_CNT_LIMIT GENMASK(15, 12)
#define MT_AGG_MRCR_LAST_RTS_CTS_RN BIT(6)
#define MT_AGG_MRCR_RTS_FAIL_LIMIT GENMASK(11, 7)
#define MT_AGG_MRCR_TXCMD_RTS_FAIL_LIMIT GENMASK(28, 24)
#define MT_AGG_ATCR1(_band) MT_WF_AGG(_band, 0x0f0)
#define MT_AGG_ATCR3(_band) MT_WF_AGG(_band, 0x0f4)
/* ARB: band 0(0x20c00), band 1(0xa0c00) */
#define MT_WF_ARB_BASE(_band) ((_band) ? 0xa0c00 : 0x20c00)
#define MT_WF_ARB(_band, ofs) (MT_WF_ARB_BASE(_band) + (ofs))
#define MT_ARB_SCR(_band) MT_WF_ARB(_band, 0x080)
#define MT_ARB_SCR_TX_DISABLE BIT(8)
#define MT_ARB_SCR_RX_DISABLE BIT(9)
#define MT_ARB_DRNGR0(_band, _n) MT_WF_ARB(_band, 0x194 + (_n) * 4)
/* RMAC: band 0(0x21400), band 1(0xa1400) */
#define MT_WF_RMAC_BASE(_band) ((_band) ? 0xa1400 : 0x21400)
#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs))
#define MT_WF_RFCR(_band) MT_WF_RMAC(_band, 0x000)
#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0)
#define MT_WF_RFCR_DROP_FCSFAIL BIT(1)
#define MT_WF_RFCR_DROP_VERSION BIT(3)
#define MT_WF_RFCR_DROP_PROBEREQ BIT(4)
#define MT_WF_RFCR_DROP_MCAST BIT(5)
#define MT_WF_RFCR_DROP_BCAST BIT(6)
#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7)
#define MT_WF_RFCR_DROP_A3_MAC BIT(8)
#define MT_WF_RFCR_DROP_A3_BSSID BIT(9)
#define MT_WF_RFCR_DROP_A2_BSSID BIT(10)
#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11)
#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12)
#define MT_WF_RFCR_DROP_CTL_RSV BIT(13)
#define MT_WF_RFCR_DROP_CTS BIT(14)
#define MT_WF_RFCR_DROP_RTS BIT(15)
#define MT_WF_RFCR_DROP_DUPLICATE BIT(16)
#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17)
#define MT_WF_RFCR_DROP_OTHER_UC BIT(18)
#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19)
#define MT_WF_RFCR_DROP_NDPA BIT(20)
#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21)
#define MT_WF_RFCR1(_band) MT_WF_RMAC(_band, 0x004)
#define MT_WF_RFCR1_DROP_ACK BIT(4)
#define MT_WF_RFCR1_DROP_BF_POLL BIT(5)
#define MT_WF_RFCR1_DROP_BA BIT(6)
#define MT_WF_RFCR1_DROP_CFEND BIT(7)
#define MT_WF_RFCR1_DROP_CFACK BIT(8)
#define MT_WF_RMAC_MIB_TIME0(_band) MT_WF_RMAC(_band, 0x03c4)
#define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31)
#define MT_WF_RMAC_MIB_RXTIME_EN BIT(30)
#define MT_WF_RMAC_MIB_AIRTIME14(_band) MT_WF_RMAC(_band, 0x03b8)
#define MT_MIB_OBSSTIME_MASK GENMASK(23, 0)
#define MT_WF_RMAC_MIB_AIRTIME0(_band) MT_WF_RMAC(_band, 0x0380)
/* WFDMA0 */
#define MT_WFDMA0_BASE 0xd4000
#define MT_WFDMA0(ofs) (MT_WFDMA0_BASE + (ofs))
#define MT_WFDMA0_RST MT_WFDMA0(0x100)
#define MT_WFDMA0_RST_LOGIC_RST BIT(4)
#define MT_WFDMA0_RST_DMASHDL_ALL_RST BIT(5)
#define MT_WFDMA0_BUSY_ENA MT_WFDMA0(0x13c)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO0 BIT(0)
#define MT_WFDMA0_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA0_BUSY_ENA_RX_FIFO BIT(2)
#define MT_MCU_CMD MT_WFDMA0(0x1f0)
#define MT_MCU_CMD_STOP_DMA_FW_RELOAD BIT(1)
#define MT_MCU_CMD_STOP_DMA BIT(2)
#define MT_MCU_CMD_RESET_DONE BIT(3)
#define MT_MCU_CMD_RECOVERY_DONE BIT(4)
#define MT_MCU_CMD_NORMAL_STATE BIT(5)
#define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
#define MT_WFDMA0_HOST_INT_STA MT_WFDMA0(0x200)
#define HOST_RX_DONE_INT_STS0 BIT(0) /* Rx mcu */
#define HOST_RX_DONE_INT_STS2 BIT(2) /* Rx data */
#define HOST_RX_DONE_INT_STS4 BIT(22) /* Rx mcu after fw downloaded */
#define HOST_TX_DONE_INT_STS16 BIT(26)
#define HOST_TX_DONE_INT_STS17 BIT(27) /* MCU tx done*/
#define MT_WFDMA0_HOST_INT_ENA MT_WFDMA0(0x204)
#define HOST_RX_DONE_INT_ENA0 BIT(0)
#define HOST_RX_DONE_INT_ENA1 BIT(1)
#define HOST_RX_DONE_INT_ENA2 BIT(2)
#define HOST_RX_DONE_INT_ENA3 BIT(3)
#define HOST_TX_DONE_INT_ENA0 BIT(4)
#define HOST_TX_DONE_INT_ENA1 BIT(5)
#define HOST_TX_DONE_INT_ENA2 BIT(6)
#define HOST_TX_DONE_INT_ENA3 BIT(7)
#define HOST_TX_DONE_INT_ENA4 BIT(8)
#define HOST_TX_DONE_INT_ENA5 BIT(9)
#define HOST_TX_DONE_INT_ENA6 BIT(10)
#define HOST_TX_DONE_INT_ENA7 BIT(11)
#define HOST_TX_DONE_INT_ENA8 BIT(12)
#define HOST_TX_DONE_INT_ENA9 BIT(13)
#define HOST_TX_DONE_INT_ENA10 BIT(14)
#define HOST_TX_DONE_INT_ENA11 BIT(15)
#define HOST_TX_DONE_INT_ENA12 BIT(16)
#define HOST_TX_DONE_INT_ENA13 BIT(17)
#define HOST_TX_DONE_INT_ENA14 BIT(18)
#define HOST_RX_COHERENT_EN BIT(20)
#define HOST_TX_COHERENT_EN BIT(21)
#define HOST_RX_DONE_INT_ENA4 BIT(22)
#define HOST_RX_DONE_INT_ENA5 BIT(23)
#define HOST_TX_DONE_INT_ENA16 BIT(26)
#define HOST_TX_DONE_INT_ENA17 BIT(27)
#define MCU2HOST_SW_INT_ENA BIT(29)
#define HOST_TX_DONE_INT_ENA18 BIT(30)
/* WFDMA interrupt */
#define MT_INT_RX_DONE_DATA HOST_RX_DONE_INT_ENA2
#define MT_INT_RX_DONE_WM HOST_RX_DONE_INT_ENA0
#define MT_INT_RX_DONE_WM2 HOST_RX_DONE_INT_ENA4
#define MT_INT_RX_DONE_ALL (MT_INT_RX_DONE_DATA | \
MT_INT_RX_DONE_WM | \
MT_INT_RX_DONE_WM2)
#define MT_INT_TX_DONE_MCU_WM HOST_TX_DONE_INT_ENA17
#define MT_INT_TX_DONE_FWDL HOST_TX_DONE_INT_ENA16
#define MT_INT_TX_DONE_BAND0 HOST_TX_DONE_INT_ENA0
#define MT_INT_MCU_CMD MCU2HOST_SW_INT_ENA
#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 | \
MT_INT_TX_DONE_BAND0 | \
GENMASK(18, 4))
#define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
#define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
#define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1)
#define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
#define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
#define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
#define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
#define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
#define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
#define MT_WFDMA0_GLO_CFG_OMIT_TX_INFO BIT(28)
#define MT_WFDMA0_GLO_CFG_CLK_GAT_DIS BIT(30)
#define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
#define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
#define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6)
#define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
#define MT_RX_DATA_RING_BASE MT_WFDMA0(0x520)
#define MT_WFDMA0_TX_RING0_EXT_CTRL MT_WFDMA0(0x600)
#define MT_WFDMA0_TX_RING1_EXT_CTRL MT_WFDMA0(0x604)
#define MT_WFDMA0_TX_RING2_EXT_CTRL MT_WFDMA0(0x608)
#define MT_WFDMA0_TX_RING3_EXT_CTRL MT_WFDMA0(0x60c)
#define MT_WFDMA0_TX_RING4_EXT_CTRL MT_WFDMA0(0x610)
#define MT_WFDMA0_TX_RING5_EXT_CTRL MT_WFDMA0(0x614)
#define MT_WFDMA0_TX_RING6_EXT_CTRL MT_WFDMA0(0x618)
#define MT_WFDMA0_TX_RING16_EXT_CTRL MT_WFDMA0(0x640)
#define MT_WFDMA0_TX_RING17_EXT_CTRL MT_WFDMA0(0x644)
#define MT_WFDMA0_RX_RING0_EXT_CTRL MT_WFDMA0(0x680)
#define MT_WFDMA0_RX_RING1_EXT_CTRL MT_WFDMA0(0x684)
#define MT_WFDMA0_RX_RING2_EXT_CTRL MT_WFDMA0(0x688)
#define MT_WFDMA0_RX_RING3_EXT_CTRL MT_WFDMA0(0x68c)
#define MT_WFDMA0_RX_RING4_EXT_CTRL MT_WFDMA0(0x690)
#define MT_WFDMA0_RX_RING5_EXT_CTRL MT_WFDMA0(0x694)
#define MT_TX_RING_BASE MT_WFDMA0(0x300)
#define MT_RX_EVENT_RING_BASE MT_WFDMA0(0x500)
/* WFDMA CSR */
#define MT_WFDMA_EXT_CSR_BASE 0xd7000
#define MT_WFDMA_EXT_CSR(ofs) (MT_WFDMA_EXT_CSR_BASE + (ofs))
#define MT_WFDMA_EXT_CSR_HIF_MISC MT_WFDMA_EXT_CSR(0x44)
#define MT_WFDMA_EXT_CSR_HIF_MISC_BUSY BIT(0)
#define MT_INFRA_CFG_BASE 0xfe000
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
#define MT_HIF_REMAP_L1 MT_INFRA(0x260)
#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 0xe0000
#define MT_SWDEF_BASE 0x41f200
#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
#define MT_SWDEF_MODE MT_SWDEF(0x3c)
#define MT_SWDEF_NORMAL_MODE 0
#define MT_SWDEF_ICAP_MODE 1
#define MT_SWDEF_SPECTRUM_MODE 2
#define MT_TOP_BASE 0x18060000
#define MT_TOP(ofs) (MT_TOP_BASE + (ofs))
#define MT_TOP_LPCR_HOST_BAND0 MT_TOP(0x10)
#define MT_TOP_LPCR_HOST_FW_OWN BIT(0)
#define MT_TOP_LPCR_HOST_DRV_OWN BIT(1)
#define MT_TOP_MISC MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
#define MT_HW_BOUND 0x70010020
#define MT_HW_CHIPID 0x70010200
#define MT_HW_REV 0x70010204
#define MT_PCIE_MAC_BASE 0x74030000
#define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
#define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
#define MT_DMA_SHDL(ofs) (0xd6000 + (ofs))
#define MT_DMASHDL_SW_CONTROL MT_DMA_SHDL(0x004)
#define MT_DMASHDL_DMASHDL_BYPASS BIT(28)
#define MT_DMASHDL_OPTIONAL MT_DMA_SHDL(0x008)
#define MT_DMASHDL_PAGE MT_DMA_SHDL(0x00c)
#define MT_DMASHDL_REFILL MT_DMA_SHDL(0x010)
#define MT_DMASHDL_PKT_MAX_SIZE MT_DMA_SHDL(0x01c)
#define MT_DMASHDL_PKT_MAX_SIZE_PLE GENMASK(11, 0)
#define MT_DMASHDL_PKT_MAX_SIZE_PSE GENMASK(27, 16)
#define MT_DMASHDL_GROUP_QUOTA(_n) MT_DMA_SHDL(0x020 + ((_n) << 2))
#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0)
#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16)
#define MT_DMASHDL_Q_MAP(_n) MT_DMA_SHDL(0x060 + ((_n) << 2))
#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0)
#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8))
#define MT_DMASHDL_SCHED_SET(_n) MT_DMA_SHDL(0x070 + ((_n) << 2))
#define MT_CONN_ON_LPCTL 0x7c060010
#define PCIE_LPCR_HOST_OWN_SYNC BIT(2)
#define PCIE_LPCR_HOST_CLR_OWN BIT(1)
#define PCIE_LPCR_HOST_SET_OWN BIT(0)
#define MT_CONN_ON_MISC 0x7c0600f0
#define MT_TOP_MISC2_FW_N9_RDY GENMASK(1, 0)
#endif

View File

@ -14,18 +14,23 @@ static const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
[MT76_TM_ATTR_TX_RATE_STBC] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_LTF] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_ANTENNA] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_SPE_IDX] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_POWER_CONTROL] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_POWER] = { .type = NLA_NESTED },
[MT76_TM_ATTR_TX_DUTY_CYCLE] = { .type = NLA_U8 },
[MT76_TM_ATTR_TX_IPG] = { .type = NLA_U32 },
[MT76_TM_ATTR_TX_TIME] = { .type = NLA_U32 },
[MT76_TM_ATTR_FREQ_OFFSET] = { .type = NLA_U32 },
};
void mt76_testmode_tx_pending(struct mt76_dev *dev)
void mt76_testmode_tx_pending(struct mt76_phy *phy)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
struct mt76_wcid *wcid = &dev->global_wcid;
struct mt76_phy *phy = &dev->phy;
struct sk_buff *skb = td->tx_skb;
struct mt76_queue *q;
u16 tx_queued_limit;
int qid;
if (!skb || !td->tx_pending)
@ -34,9 +39,12 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)
qid = skb_get_queue_mapping(skb);
q = phy->q_tx[qid];
tx_queued_limit = td->tx_queued_limit ? td->tx_queued_limit : 1000;
spin_lock_bh(&q->lock);
while (td->tx_pending > 0 && td->tx_queued - td->tx_done < 1000 &&
while (td->tx_pending > 0 &&
td->tx_queued - td->tx_done < tx_queued_limit &&
q->queued < q->ndesc / 2) {
int ret;
@ -56,10 +64,9 @@ void mt76_testmode_tx_pending(struct mt76_dev *dev)
static int
mt76_testmode_tx_init(struct mt76_dev *dev)
mt76_testmode_tx_init(struct mt76_phy *phy)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_phy *phy = &dev->phy;
struct mt76_testmode_data *td = &phy->test;
struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
@ -67,6 +74,7 @@ mt76_testmode_tx_init(struct mt76_dev *dev)
IEEE80211_FCTL_FROMDS;
struct ieee80211_tx_rate *rate;
u8 max_nss = hweight8(phy->antenna_mask);
bool ext_phy = phy != &phy->dev->phy;
if (td->tx_antenna_mask)
max_nss = min_t(u8, max_nss, hweight8(td->tx_antenna_mask));
@ -88,6 +96,9 @@ mt76_testmode_tx_init(struct mt76_dev *dev)
IEEE80211_TX_CTL_NO_ACK |
IEEE80211_TX_CTL_NO_PS_BUFFER;
if (ext_phy)
info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY;
if (td->tx_rate_mode > MT76_TM_TX_MODE_VHT)
goto out;
@ -166,9 +177,10 @@ mt76_testmode_tx_init(struct mt76_dev *dev)
}
static void
mt76_testmode_tx_start(struct mt76_dev *dev)
mt76_testmode_tx_start(struct mt76_phy *phy)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
td->tx_queued = 0;
td->tx_done = 0;
@ -177,9 +189,10 @@ mt76_testmode_tx_start(struct mt76_dev *dev)
}
static void
mt76_testmode_tx_stop(struct mt76_dev *dev)
mt76_testmode_tx_stop(struct mt76_phy *phy)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
mt76_worker_disable(&dev->tx_worker);
@ -187,7 +200,8 @@ mt76_testmode_tx_stop(struct mt76_dev *dev)
mt76_worker_enable(&dev->tx_worker);
wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued, 10 * HZ);
wait_event_timeout(dev->tx_wait, td->tx_done == td->tx_queued,
MT76_TM_TIMEOUT * HZ);
dev_kfree_skb(td->tx_skb);
td->tx_skb = NULL;
@ -206,9 +220,9 @@ mt76_testmode_param_present(struct mt76_testmode_data *td, u16 idx)
}
static void
mt76_testmode_init_defaults(struct mt76_dev *dev)
mt76_testmode_init_defaults(struct mt76_phy *phy)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
if (td->tx_msdu_len > 0)
return;
@ -220,49 +234,50 @@ mt76_testmode_init_defaults(struct mt76_dev *dev)
}
static int
__mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state)
__mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
{
enum mt76_testmode_state prev_state = dev->test.state;
enum mt76_testmode_state prev_state = phy->test.state;
struct mt76_dev *dev = phy->dev;
int err;
if (prev_state == MT76_TM_STATE_TX_FRAMES)
mt76_testmode_tx_stop(dev);
mt76_testmode_tx_stop(phy);
if (state == MT76_TM_STATE_TX_FRAMES) {
err = mt76_testmode_tx_init(dev);
err = mt76_testmode_tx_init(phy);
if (err)
return err;
}
err = dev->test_ops->set_state(dev, state);
err = dev->test_ops->set_state(phy, state);
if (err) {
if (state == MT76_TM_STATE_TX_FRAMES)
mt76_testmode_tx_stop(dev);
mt76_testmode_tx_stop(phy);
return err;
}
if (state == MT76_TM_STATE_TX_FRAMES)
mt76_testmode_tx_start(dev);
mt76_testmode_tx_start(phy);
else if (state == MT76_TM_STATE_RX_FRAMES) {
memset(&dev->test.rx_stats, 0, sizeof(dev->test.rx_stats));
memset(&phy->test.rx_stats, 0, sizeof(phy->test.rx_stats));
}
dev->test.state = state;
phy->test.state = state;
return 0;
}
int mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state)
int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state)
{
struct mt76_testmode_data *td = &dev->test;
struct ieee80211_hw *hw = dev->phy.hw;
struct mt76_testmode_data *td = &phy->test;
struct ieee80211_hw *hw = phy->hw;
if (state == td->state && state == MT76_TM_STATE_OFF)
return 0;
if (state > MT76_TM_STATE_OFF &&
(!test_bit(MT76_STATE_RUNNING, &dev->phy.state) ||
(!test_bit(MT76_STATE_RUNNING, &phy->state) ||
!(hw->conf.flags & IEEE80211_CONF_MONITOR)))
return -ENOTCONN;
@ -270,12 +285,12 @@ int mt76_testmode_set_state(struct mt76_dev *dev, enum mt76_testmode_state state
td->state != MT76_TM_STATE_IDLE) {
int ret;
ret = __mt76_testmode_set_state(dev, MT76_TM_STATE_IDLE);
ret = __mt76_testmode_set_state(phy, MT76_TM_STATE_IDLE);
if (ret)
return ret;
}
return __mt76_testmode_set_state(dev, state);
return __mt76_testmode_set_state(phy, state);
}
EXPORT_SYMBOL(mt76_testmode_set_state);
@ -301,8 +316,9 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
{
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct nlattr *tb[NUM_MT76_TM_ATTRS];
bool ext_phy = phy != &dev->phy;
u32 state;
int err;
int i;
@ -320,11 +336,11 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mutex_lock(&dev->mutex);
if (tb[MT76_TM_ATTR_RESET]) {
mt76_testmode_set_state(dev, MT76_TM_STATE_OFF);
mt76_testmode_set_state(phy, MT76_TM_STATE_OFF);
memset(td, 0, sizeof(*td));
}
mt76_testmode_init_defaults(dev);
mt76_testmode_init_defaults(phy);
if (tb[MT76_TM_ATTR_TX_COUNT])
td->tx_count = nla_get_u32(tb[MT76_TM_ATTR_TX_COUNT]);
@ -350,12 +366,21 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_LDPC], &td->tx_rate_ldpc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_RATE_STBC], &td->tx_rate_stbc, 0, 1) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_LTF], &td->tx_ltf, 0, 2) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask, 1,
phy->antenna_mask) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_ANTENNA], &td->tx_antenna_mask,
1 << (ext_phy * 2), phy->antenna_mask << (ext_phy * 2)) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_SPE_IDX], &td->tx_spe_idx, 0, 27) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_DUTY_CYCLE],
&td->tx_duty_cycle, 0, 99) ||
mt76_tm_get_u8(tb[MT76_TM_ATTR_TX_POWER_CONTROL],
&td->tx_power_control, 0, 1))
goto out;
if (tb[MT76_TM_ATTR_TX_IPG])
td->tx_ipg = nla_get_u32(tb[MT76_TM_ATTR_TX_IPG]);
if (tb[MT76_TM_ATTR_TX_TIME])
td->tx_time = nla_get_u32(tb[MT76_TM_ATTR_TX_TIME]);
if (tb[MT76_TM_ATTR_FREQ_OFFSET])
td->freq_offset = nla_get_u32(tb[MT76_TM_ATTR_FREQ_OFFSET]);
@ -382,7 +407,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
if (dev->test_ops->set_params) {
err = dev->test_ops->set_params(dev, tb, state);
err = dev->test_ops->set_params(phy, tb, state);
if (err)
goto out;
}
@ -393,7 +418,7 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
err = 0;
if (tb[MT76_TM_ATTR_STATE])
err = mt76_testmode_set_state(dev, state);
err = mt76_testmode_set_state(phy, state);
out:
mutex_unlock(&dev->mutex);
@ -403,9 +428,10 @@ int mt76_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
EXPORT_SYMBOL(mt76_testmode_cmd);
static int
mt76_testmode_dump_stats(struct mt76_dev *dev, struct sk_buff *msg)
mt76_testmode_dump_stats(struct mt76_phy *phy, struct sk_buff *msg)
{
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct mt76_dev *dev = phy->dev;
u64 rx_packets = 0;
u64 rx_fcs_error = 0;
int i;
@ -425,7 +451,7 @@ mt76_testmode_dump_stats(struct mt76_dev *dev, struct sk_buff *msg)
return -EMSGSIZE;
if (dev->test_ops->dump_stats)
return dev->test_ops->dump_stats(dev, msg);
return dev->test_ops->dump_stats(phy, msg);
return 0;
}
@ -435,7 +461,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
{
struct mt76_phy *phy = hw->priv;
struct mt76_dev *dev = phy->dev;
struct mt76_testmode_data *td = &dev->test;
struct mt76_testmode_data *td = &phy->test;
struct nlattr *tb[NUM_MT76_TM_ATTRS] = {};
int err = 0;
void *a;
@ -461,22 +487,22 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
a = nla_nest_start(msg, MT76_TM_ATTR_STATS);
if (a) {
err = mt76_testmode_dump_stats(dev, msg);
err = mt76_testmode_dump_stats(phy, msg);
nla_nest_end(msg, a);
}
goto out;
}
mt76_testmode_init_defaults(dev);
mt76_testmode_init_defaults(phy);
err = -EMSGSIZE;
if (nla_put_u32(msg, MT76_TM_ATTR_STATE, td->state))
goto out;
if (td->mtd_name &&
(nla_put_string(msg, MT76_TM_ATTR_MTD_PART, td->mtd_name) ||
nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, td->mtd_offset)))
if (dev->test_mtd.name &&
(nla_put_string(msg, MT76_TM_ATTR_MTD_PART, dev->test_mtd.name) ||
nla_put_u32(msg, MT76_TM_ATTR_MTD_OFFSET, dev->test_mtd.offset)))
goto out;
if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
@ -491,6 +517,14 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_ANTENNA, td->tx_antenna_mask)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_SPE_IDX) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_SPE_IDX, td->tx_spe_idx)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_DUTY_CYCLE) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_DUTY_CYCLE, td->tx_duty_cycle)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_IPG) &&
nla_put_u32(msg, MT76_TM_ATTR_TX_IPG, td->tx_ipg)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_TIME) &&
nla_put_u32(msg, MT76_TM_ATTR_TX_TIME, td->tx_time)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_POWER_CONTROL) &&
nla_put_u8(msg, MT76_TM_ATTR_TX_POWER_CONTROL, td->tx_power_control)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_FREQ_OFFSET) &&

View File

@ -5,6 +5,8 @@
#ifndef __MT76_TESTMODE_H
#define __MT76_TESTMODE_H
#define MT76_TM_TIMEOUT 10
/**
* enum mt76_testmode_attr - testmode attributes inside NL80211_ATTR_TESTDATA
*
@ -35,6 +37,13 @@
* @MT76_TM_ATTR_FREQ_OFFSET: RF frequency offset (u32)
*
* @MT76_TM_ATTR_STATS: statistics (nested, see &enum mt76_testmode_stats_attr)
*
* @MT76_TM_ATTR_TX_SPE_IDX: tx spatial extension index (u8)
*
* @MT76_TM_ATTR_TX_DUTY_CYCLE: packet tx duty cycle (u8)
* @MT76_TM_ATTR_TX_IPG: tx inter-packet gap, in unit of us (u32)
* @MT76_TM_ATTR_TX_TIME: packet transmission time, in unit of us (u32)
*
*/
enum mt76_testmode_attr {
MT76_TM_ATTR_UNSPEC,
@ -63,6 +72,12 @@ enum mt76_testmode_attr {
MT76_TM_ATTR_STATS,
MT76_TM_ATTR_TX_SPE_IDX,
MT76_TM_ATTR_TX_DUTY_CYCLE,
MT76_TM_ATTR_TX_IPG,
MT76_TM_ATTR_TX_TIME,
/* keep last */
NUM_MT76_TM_ATTRS,
MT76_TM_ATTR_MAX = NUM_MT76_TM_ATTRS - 1,
@ -128,12 +143,14 @@ enum mt76_testmode_rx_attr {
* @MT76_TM_STATE_IDLE: test mode enabled, but idle
* @MT76_TM_STATE_TX_FRAMES: send a fixed number of test frames
* @MT76_TM_STATE_RX_FRAMES: receive packets and keep statistics
* @MT76_TM_STATE_TX_CONT: waveform tx without time gap
*/
enum mt76_testmode_state {
MT76_TM_STATE_OFF,
MT76_TM_STATE_IDLE,
MT76_TM_STATE_TX_FRAMES,
MT76_TM_STATE_RX_FRAMES,
MT76_TM_STATE_TX_CONT,
/* keep last */
NUM_MT76_TM_STATES,

View File

@ -202,16 +202,22 @@ void mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *sk
struct ieee80211_hw *hw;
struct sk_buff_head list;
mt76_tx_check_non_aql(dev, wcid_idx, skb);
#ifdef CONFIG_NL80211_TESTMODE
if (skb == dev->test.tx_skb) {
dev->test.tx_done++;
if (dev->test.tx_queued == dev->test.tx_done)
if (mt76_is_testmode_skb(dev, skb, &hw)) {
struct mt76_phy *phy = hw->priv;
if (skb == phy->test.tx_skb)
phy->test.tx_done++;
if (phy->test.tx_queued == phy->test.tx_done)
wake_up(&dev->tx_wait);
ieee80211_free_txskb(hw, skb);
return;
}
#endif
mt76_tx_check_non_aql(dev, wcid_idx, skb);
if (!skb->prev) {
hw = mt76_tx_status_get_hw(dev, skb);
ieee80211_free_txskb(hw, skb);
@ -261,7 +267,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
int qid = skb_get_queue_mapping(skb);
bool ext_phy = phy != &dev->phy;
if (mt76_testmode_enabled(dev)) {
if (mt76_testmode_enabled(phy)) {
ieee80211_free_txskb(phy->hw, skb);
return;
}
@ -454,7 +460,6 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
struct mt76_wcid *wcid;
int ret = 0;
spin_lock_bh(&q->lock);
while (1) {
if (test_bit(MT76_STATE_PM, &phy->state) ||
test_bit(MT76_RESET, &phy->state)) {
@ -464,14 +469,9 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
if (dev->queue_ops->tx_cleanup &&
q->queued + 2 * MT_TXQ_FREE_THR >= q->ndesc) {
spin_unlock_bh(&q->lock);
dev->queue_ops->tx_cleanup(dev, q, false);
spin_lock_bh(&q->lock);
}
if (mt76_txq_stopped(q))
break;
txq = ieee80211_next_txq(phy->hw, qid);
if (!txq)
break;
@ -481,6 +481,8 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
if (wcid && test_bit(MT_WCID_FLAG_PS, &wcid->flags))
continue;
spin_lock_bh(&q->lock);
if (mtxq->send_bar && mtxq->aggr) {
struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
struct ieee80211_sta *sta = txq->sta;
@ -494,10 +496,13 @@ mt76_txq_schedule_list(struct mt76_phy *phy, enum mt76_txq_id qid)
spin_lock_bh(&q->lock);
}
ret += mt76_txq_send_burst(phy, q, mtxq);
if (!mt76_txq_stopped(q))
ret += mt76_txq_send_burst(phy, q, mtxq);
spin_unlock_bh(&q->lock);
ieee80211_return_txq(phy->hw, txq, false);
}
spin_unlock_bh(&q->lock);
return ret;
}
@ -539,8 +544,10 @@ void mt76_tx_worker(struct mt76_worker *w)
mt76_txq_schedule_all(dev->phy2);
#ifdef CONFIG_NL80211_TESTMODE
if (dev->test.tx_pending)
mt76_testmode_tx_pending(dev);
if (dev->phy.test.tx_pending)
mt76_testmode_tx_pending(&dev->phy);
if (dev->phy2 && dev->phy2->test.tx_pending)
mt76_testmode_tx_pending(dev->phy2);
#endif
}

View File

@ -612,6 +612,7 @@ static void mt76u_complete_rx(struct urb *urb)
case -ECONNRESET:
case -ESHUTDOWN:
case -ENOENT:
case -EPROTO:
return;
default:
dev_err_ratelimited(dev->dev, "rx urb failed: %d\n",