Commit eda31200 authored by Kalle Valo's avatar Kalle Valo

Merge tag 'mt76-for-kvalo-2020-05-14' of https://github.com/nbd168/wireless

mt76 patches for 5.8

* new devices for mt76x0/mt76x2
* mt7615 fixes
* mt7663 fixes
* support for non-offload firmware on mt7663
* hw/sched scan support for mt7663
* mt7615/mt7663 MSI support
* TDLS support
* mt7603/mt7615 rate control fixes
* new driver for mt7915
* wowlan support for mt7663
* suspend/resume support for mt7663

# gpg: Signature made Thu 14 May 2020 01:10:07 PM EEST using DSA key ID 02A76EF5
# gpg: Good signature from "Felix Fietkau <nbd@nbd.name>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 75D1 1A7D 91A7 710F 4900  42EF D77D 141D 02A7 6EF5
parents c73fb4d3 12a87174
......@@ -25,6 +25,9 @@ Optional properties:
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
- big-endian: if the radio eeprom partition is written in big-endian, specify
this property
- mediatek,eeprom-merge-otp: Merge EEPROM data with OTP data. Can be used on
boards where the flash calibration data is generic and specific calibration
data should be pulled from the OTP ROM
The MAC address can as well be set with corresponding optional properties
defined in net/ethernet.txt.
......
......@@ -24,3 +24,4 @@ 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"
......@@ -26,4 +26,5 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
obj-$(CONFIG_MT76x2_COMMON) += mt76x2/
obj-$(CONFIG_MT7603E) += mt7603/
obj-$(CONFIG_MT7615E) += mt7615/
obj-$(CONFIG_MT7615_COMMON) += mt7615/
obj-$(CONFIG_MT7915E) += mt7915/
......@@ -119,7 +119,7 @@ static void
mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
struct ieee80211_bar *bar = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct mt76_rx_tid *tid;
u16 seqno;
......@@ -147,13 +147,13 @@ mt76_rx_aggr_check_ctl(struct sk_buff *skb, struct sk_buff_head *frames)
void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_wcid *wcid = status->wcid;
struct ieee80211_sta *sta;
struct mt76_rx_tid *tid;
bool sn_less;
u16 seqno, head, size;
u8 ackp, idx;
u16 seqno, head, size, idx;
u8 ackp;
__skb_queue_tail(frames, skb);
......@@ -239,7 +239,7 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
}
int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno,
u16 ssn, u8 size)
u16 ssn, u16 size)
{
struct mt76_rx_tid *tid;
......@@ -264,7 +264,7 @@ EXPORT_SYMBOL_GPL(mt76_rx_aggr_start);
static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid)
{
u8 size = tid->size;
u16 size = tid->size;
int i;
spin_lock_bh(&tid->lock);
......
......@@ -46,6 +46,25 @@ int mt76_queues_read(struct seq_file *s, void *data)
}
EXPORT_SYMBOL_GPL(mt76_queues_read);
static int mt76_rx_queues_read(struct seq_file *s, void *data)
{
struct mt76_dev *dev = dev_get_drvdata(s->private);
int i, queued;
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) {
struct mt76_queue *q = &dev->q_rx[i];
if (!q->ndesc)
continue;
queued = mt76_is_usb(dev) ? q->ndesc - q->queued : q->queued;
seq_printf(s, "%d: queued=%d head=%d tail=%d\n",
i, queued, q->head, q->tail);
}
return 0;
}
void mt76_seq_puts_array(struct seq_file *file, const char *str,
s8 *val, int len)
{
......@@ -92,6 +111,8 @@ struct dentry *mt76_register_debugfs(struct mt76_dev *dev)
debugfs_create_blob("otp", 0400, dir, &dev->otp);
debugfs_create_devm_seqfile(dev->dev, "rate_txpower", dir,
mt76_read_rate_txpower);
debugfs_create_devm_seqfile(dev->dev, "rx-queues", dir,
mt76_rx_queues_read);
return dir;
}
......
......@@ -116,12 +116,12 @@ static void mt76_led_cleanup(struct mt76_dev *dev)
led_classdev_unregister(&dev->led_cdev);
}
static void mt76_init_stream_cap(struct mt76_dev *dev,
static void mt76_init_stream_cap(struct mt76_phy *phy,
struct ieee80211_supported_band *sband,
bool vht)
{
struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
int i, nstream = hweight8(dev->phy.antenna_mask);
int i, nstream = hweight8(phy->antenna_mask);
struct ieee80211_sta_vht_cap *vht_cap;
u16 mcs_map = 0;
......@@ -153,12 +153,12 @@ static void mt76_init_stream_cap(struct mt76_dev *dev,
vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
}
void mt76_set_stream_caps(struct mt76_dev *dev, bool vht)
void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
{
if (dev->cap.has_2ghz)
mt76_init_stream_cap(dev, &dev->phy.sband_2g.sband, false);
if (dev->cap.has_5ghz)
mt76_init_stream_cap(dev, &dev->phy.sband_5g.sband, vht);
if (phy->dev->cap.has_2ghz)
mt76_init_stream_cap(phy, &phy->sband_2g.sband, false);
if (phy->dev->cap.has_5ghz)
mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht);
}
EXPORT_SYMBOL_GPL(mt76_set_stream_caps);
......@@ -198,9 +198,8 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
mt76_init_stream_cap(dev, sband, vht);
mt76_init_stream_cap(&dev->phy, sband, vht);
if (!vht)
return 0;
......@@ -279,7 +278,8 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)
SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
WIPHY_FLAG_SUPPORTS_TDLS;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
......@@ -294,7 +294,6 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)
hw->max_tx_fragments = 16;
ieee80211_hw_set(hw, SIGNAL_DBM);
ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
......@@ -314,6 +313,8 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_ADHOC);
}
......@@ -677,7 +678,6 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
struct ieee80211_hw **hw,
struct ieee80211_sta **sta)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct mt76_rx_status mstat;
......@@ -689,6 +689,9 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
status->enc_flags = mstat.enc_flags;
status->encoding = mstat.encoding;
status->bw = mstat.bw;
status->he_ru = mstat.he_ru;
status->he_gi = mstat.he_gi;
status->he_dcm = mstat.he_dcm;
status->rate_idx = mstat.rate_idx;
status->nss = mstat.nss;
status->band = mstat.band;
......@@ -725,7 +728,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)
* Validate the first fragment both here and in mac80211
* All further fragments will be validated by mac80211 only.
*/
hdr = (struct ieee80211_hdr *)skb->data;
hdr = mt76_skb_get_hdr(skb);
if (ieee80211_is_frag(hdr) &&
!ieee80211_is_first_frag(hdr->frame_control))
return 0;
......@@ -798,7 +801,7 @@ mt76_airtime_flush_ampdu(struct mt76_dev *dev)
static void
mt76_airtime_check(struct mt76_dev *dev, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_wcid *wcid = status->wcid;
......@@ -835,7 +838,7 @@ static void
mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb)
{
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
struct ieee80211_sta *sta;
struct ieee80211_hw *hw;
struct mt76_wcid *wcid = status->wcid;
......
......@@ -6,10 +6,11 @@
#include "mt76.h"
struct sk_buff *
mt76_mcu_msg_alloc(const void *data, int head_len,
int data_len, int tail_len)
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
int data_len)
{
int length = head_len + data_len + tail_len;
const struct mt76_mcu_ops *ops = dev->mcu_ops;
int length = ops->headroom + data_len + ops->tailroom;
struct sk_buff *skb;
skb = alloc_skb(length, GFP_KERNEL);
......@@ -17,7 +18,7 @@ mt76_mcu_msg_alloc(const void *data, int head_len,
return NULL;
memset(skb->head, 0, length);
skb_reserve(skb, head_len);
skb_reserve(skb, ops->headroom);
if (data && data_len)
skb_put_data(skb, data, data_len);
......
......@@ -73,7 +73,8 @@ void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr,
spin_lock_irqsave(&dev->mmio.irq_lock, flags);
dev->mmio.irqmask &= ~clear;
dev->mmio.irqmask |= set;
mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
if (addr)
mt76_mmio_wr(dev, addr, dev->mmio.irqmask);
spin_unlock_irqrestore(&dev->mmio.irq_lock, flags);
}
EXPORT_SYMBOL_GPL(mt76_set_irq_mask);
......
......@@ -60,6 +60,7 @@ enum mt76_txq_id {
MT_TXQ_BK = IEEE80211_AC_BK,
MT_TXQ_PSD,
MT_TXQ_MCU,
MT_TXQ_MCU_WA,
MT_TXQ_BEACON,
MT_TXQ_CAB,
MT_TXQ_FWDL,
......@@ -69,6 +70,7 @@ enum mt76_txq_id {
enum mt76_rxq_id {
MT_RXQ_MAIN,
MT_RXQ_MCU,
MT_RXQ_MCU_WA,
__MT_RXQ_MAX
};
......@@ -137,6 +139,9 @@ struct mt76_sw_queue {
};
struct mt76_mcu_ops {
u32 headroom;
u32 tailroom;
int (*mcu_send_msg)(struct mt76_dev *dev, int cmd, const void *data,
int len, bool wait_resp);
int (*mcu_skb_send_msg)(struct mt76_dev *dev, struct sk_buff *skb,
......@@ -178,7 +183,7 @@ enum mt76_wcid_flags {
MT_WCID_FLAG_PS,
};
#define MT76_N_WCIDS 128
#define MT76_N_WCIDS 288
/* stored in ieee80211_tx_info::hw_queue */
#define MT_TX_HW_QUEUE_EXT_PHY BIT(3)
......@@ -198,7 +203,7 @@ struct mt76_wcid {
struct ewma_signal rssi;
int inactive_count;
u8 idx;
u16 idx;
u8 hw_key_idx;
u8 sta:1;
......@@ -241,8 +246,8 @@ struct mt76_rx_tid {
struct delayed_work reorder_work;
u16 head;
u8 size;
u8 nframes;
u16 size;
u16 nframes;
u8 num;
......@@ -265,7 +270,7 @@ struct mt76_rx_tid {
struct mt76_tx_cb {
unsigned long jiffies;
u8 wcid;
u16 wcid;
u8 pktid;
u8 flags;
};
......@@ -275,10 +280,16 @@ enum {
MT76_STATE_RUNNING,
MT76_STATE_MCU_RUNNING,
MT76_SCANNING,
MT76_HW_SCANNING,
MT76_HW_SCHED_SCANNING,
MT76_RESTART,
MT76_RESET,
MT76_MCU_RESET,
MT76_REMOVED,
MT76_READING_STATS,
MT76_STATE_POWER_OFF,
MT76_STATE_PS,
MT76_STATE_SUSPEND,
};
struct mt76_hw_cap {
......@@ -372,6 +383,7 @@ enum mt_vendor_req {
MT_VEND_READ_CFG = 0x47,
MT_VEND_READ_EXT = 0x63,
MT_VEND_WRITE_EXT = 0x66,
MT_VEND_FEATURE_SET = 0x91,
};
enum mt76u_in_ep {
......@@ -435,7 +447,7 @@ struct mt76_mmio {
struct mt76_rx_status {
union {
struct mt76_wcid *wcid;
u8 wcid_idx;
u16 wcid_idx;
};
unsigned long reorder_time;
......@@ -452,7 +464,8 @@ struct mt76_rx_status {
u16 freq;
u32 flag;
u8 enc_flags;
u8 encoding:2, bw:3;
u8 encoding:2, bw:3, he_ru:3;
u8 he_gi:2, he_dcm:1;
u8 rate_idx;
u8 nss;
u8 band;
......@@ -570,6 +583,10 @@ enum mt76_phy_type {
MT_PHY_TYPE_HT,
MT_PHY_TYPE_HT_GF,
MT_PHY_TYPE_VHT,
MT_PHY_TYPE_HE_SU = 8,
MT_PHY_TYPE_HE_EXT_SU,
MT_PHY_TYPE_HE_TB,
MT_PHY_TYPE_HE_MU,
};
#define __mt76_rr(dev, ...) (dev)->bus->rr((dev), __VA_ARGS__)
......@@ -611,7 +628,7 @@ enum mt76_phy_type {
#define mt76_hw(dev) (dev)->mphy.hw
static inline struct ieee80211_hw *
mt76_wcid_hw(struct mt76_dev *dev, u8 wcid)
mt76_wcid_hw(struct mt76_dev *dev, u16 wcid)
{
if (wcid <= MT76_N_WCIDS &&
mt76_wcid_mask_test(dev->wcid_phy_mask, wcid))
......@@ -735,6 +752,25 @@ static inline struct mt76_tx_cb *mt76_tx_skb_cb(struct sk_buff *skb)
return ((void *)IEEE80211_SKB_CB(skb)->status.status_driver_data);
}
static inline void *mt76_skb_get_hdr(struct sk_buff *skb)
{
struct mt76_rx_status mstat;
u8 *data = skb->data;
/* Alignment concerns */
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4);
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4);
mstat = *((struct mt76_rx_status *)skb->cb);
if (mstat.flag & RX_FLAG_RADIOTAP_HE)
data += sizeof(struct ieee80211_radiotap_he);
if (mstat.flag & RX_FLAG_RADIOTAP_HE_MU)
data += sizeof(struct ieee80211_radiotap_he_mu);
return data;
}
static inline void mt76_insert_hdr_pad(struct sk_buff *skb)
{
int len = ieee80211_get_hdrlen_from_skb(skb);
......@@ -785,10 +821,10 @@ void mt76_set_channel(struct mt76_phy *phy);
void mt76_update_survey(struct mt76_dev *dev);
int mt76_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void mt76_set_stream_caps(struct mt76_dev *dev, bool vht);
void mt76_set_stream_caps(struct mt76_phy *phy, bool vht);
int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid,
u16 ssn, u8 size);
u16 ssn, u16 size);
void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid);
void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
......@@ -911,8 +947,8 @@ int mt76u_resume_rx(struct mt76_dev *dev);
void mt76u_queues_deinit(struct mt76_dev *dev);
struct sk_buff *
mt76_mcu_msg_alloc(const void *data, int head_len,
int data_len, int tail_len);
mt76_mcu_msg_alloc(struct mt76_dev *dev, const void *data,
int data_len);
void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb);
struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev,
unsigned long expires);
......
......@@ -113,7 +113,7 @@ void mt7603_init_debugfs(struct mt7603_dev *dev)
return;
debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat);
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
mt76_queues_read);
debugfs_create_file("edcca", 0600, dir, dev, &fops_edcca);
debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test);
......
// SPDX-License-Identifier: ISC
#include <linux/of.h>
#include "mt7603.h"
#include "eeprom.h"
......@@ -100,10 +101,14 @@ mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
MT_EE_TX_POWER_1_START_2G,
MT_EE_TX_POWER_1_START_2G + 1,
};
struct device_node *np = dev->mt76.dev->of_node;
u8 *eeprom = dev->mt76.eeprom.data;
int n = ARRAY_SIZE(cal_free_bytes);
int i;
if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
return;
if (!mt7603_has_cal_free_data(dev, efuse))
return;
......
......@@ -342,6 +342,8 @@ static const struct ieee80211_iface_limit if_limits[] = {
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
#endif
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_AP)
},
};
......
......@@ -51,10 +51,11 @@ void mt7603_mac_set_timing(struct mt7603_dev *dev)
int offset = 3 * dev->coverage_class;
u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
bool is_5ghz = dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ;
int sifs;
u32 val;
if (dev->mphy.chandef.chan->band == NL80211_BAND_5GHZ)
if (is_5ghz)
sifs = 16;
else
sifs = 10;
......@@ -71,7 +72,7 @@ void mt7603_mac_set_timing(struct mt7603_dev *dev)
FIELD_PREP(MT_IFS_SIFS, sifs) |
FIELD_PREP(MT_IFS_SLOT, dev->slottime));
if (dev->slottime < 20)
if (dev->slottime < 20 || is_5ghz)
val = MT7603_CFEND_RATE_DEFAULT;
else
val = MT7603_CFEND_RATE_11B;
......@@ -318,11 +319,16 @@ void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta)
{
struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
int idx = msta->wcid.idx;
u8 ampdu_density;
u32 addr;
u32 val;
addr = mt7603_wtbl1_addr(idx);
ampdu_density = sta->ht_cap.ampdu_density;
if (ampdu_density < IEEE80211_HT_MPDU_DENSITY_4)
ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
val = mt76_rr(dev, addr + 2 * 4);
val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL;
val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) |
......@@ -1097,7 +1103,7 @@ mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta,
if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU))
info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU;
first_idx = max_t(int, 0, last_idx - (count + 1) / MT7603_RATE_RETRY);
first_idx = max_t(int, 0, last_idx - (count - 1) / MT7603_RATE_RETRY);
if (fixed_rate && !probe) {
info->status.rates[0].count = count;
......
......@@ -62,7 +62,7 @@ mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
struct sk_buff *skb;
int ret, seq;
skb = mt7603_mcu_msg_alloc(data, len);
skb = mt76_mcu_msg_alloc(mdev, data, len);
if (!skb)
return -ENOMEM;
......@@ -265,6 +265,7 @@ static int mt7603_load_firmware(struct mt7603_dev *dev)
int mt7603_mcu_init(struct mt7603_dev *dev)
{
static const struct mt76_mcu_ops mt7603_mcu_ops = {
.headroom = sizeof(struct mt7603_mcu_txd),
.mcu_send_msg = mt7603_mcu_msg_send,
.mcu_restart = mt7603_mcu_restart,
};
......
......@@ -100,11 +100,4 @@ enum {
MCU_EXT_EVENT_BCN_UPDATE = 0x31,
};
static inline struct sk_buff *
mt7603_mcu_msg_alloc(const void *data, int len)
{
return mt76_mcu_msg_alloc(data, sizeof(struct mt7603_mcu_txd),
len, 0);
}
#endif
......@@ -20,10 +20,8 @@ mt76_wmac_probe(struct platform_device *pdev)
return irq;
mem_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mem_base)) {
dev_err(&pdev->dev, "Failed to get memory resource\n");
if (IS_ERR(mem_base))
return PTR_ERR(mem_base);
}
mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops,
&mt7603_drv_ops);
......
# SPDX-License-Identifier: GPL-2.0-only
config MT7615E
tristate "MediaTek MT7615E (PCIe) support"
config MT7615_COMMON
tristate
select MT76_CORE
config MT7615E
tristate "MediaTek MT7615E and MT7663E (PCIe) support"
select MT7615_COMMON
depends on MAC80211
depends on PCI
help
......@@ -22,3 +27,14 @@ config MT7622_WMAC
This adds support for the built-in WMAC on MT7622 SoC devices
which has the same feature set as a MT7615, but limited to
2.4 GHz only.
config MT7663U
tristate "MediaTek MT7663U (USB) support"
select MT76_USB
select MT7615_COMMON
depends on MAC80211
depends on USB
help
This adds support for MT7663U 802.11ax 2x2:2 wireless devices.
To compile this driver as a module, choose M here.
#SPDX-License-Identifier: ISC
obj-$(CONFIG_MT7615_COMMON) += mt7615-common.o
obj-$(CONFIG_MT7615E) += mt7615e.o
obj-$(CONFIG_MT7663U) += mt7663u.o
CFLAGS_trace.o := -I$(src)
mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o mmio.o \
debugfs.o trace.o
mt7615-common-y := main.o init.o mcu.o eeprom.o mac.o \
debugfs.o trace.o
mt7615e-y := pci.o pci_init.o dma.o pci_mac.o mmio.o
mt7615e-$(CONFIG_MT7622_WMAC) += soc.o
mt7663u-y := usb.o usb_mcu.o usb_init.o
......@@ -20,11 +20,15 @@ static int
mt7615_scs_set(void *data, u64 val)
{
struct mt7615_dev *dev = data;
struct mt7615_phy *ext_phy;
if (!mt7615_wait_for_mcu_init(dev))
return 0;
mt7615_mac_set_scs(dev, val);
mt7615_mac_set_scs(&dev->phy, val);
ext_phy = mt7615_ext_phy(dev);
if (ext_phy)
mt7615_mac_set_scs(ext_phy, val);
return 0;
}
......@@ -34,7 +38,7 @@ mt7615_scs_get(void *data, u64 *val)
{
struct mt7615_dev *dev = data;
*val = dev->scs_en;
*val = dev->phy.scs_en;
return 0;
}
......@@ -120,28 +124,52 @@ mt7615_reset_test_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL,
mt7615_reset_test_set, "%lld\n");
static int
mt7615_ampdu_stat_read(struct seq_file *file, void *data)
static void
mt7615_ampdu_stat_read_phy(struct mt7615_phy *phy,
struct seq_file *file)
{
struct mt7615_dev *dev = file->private;
u32 reg = is_mt7663(&dev->mt76) ? MT_MIB_ARNG(0) : MT_AGG_ASRCR0;
bool ext_phy = phy != &dev->phy;
int bound[7], i, range;
range = mt76_rr(dev, MT_AGG_ASRCR0);
if (!phy)
return;
range = mt76_rr(dev, reg);
for (i = 0; i < 4; i++)
bound[i] = MT_AGG_ASRCR_RANGE(range, i) + 1;
range = mt76_rr(dev, MT_AGG_ASRCR1);
range = mt76_rr(dev, reg + 4);
for (i = 0; i < 3; i++)
bound[i + 4] = MT_AGG_ASRCR_RANGE(range, i) + 1;
seq_printf(file, "\nPhy %d\n", ext_phy);
seq_printf(file, "Length: %8d | ", bound[0]);
for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
seq_printf(file, "%3d -%3d | ",
bound[i], bound[i + 1]);
seq_puts(file, "\nCount: ");
range = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0;
for (i = 0; i < ARRAY_SIZE(bound); i++)
seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i]);
seq_printf(file, "%8d | ", dev->mt76.aggr_stats[i + range]);
seq_puts(file, "\n");
seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
seq_printf(file, "PER: %ld.%1ld%%\n",
phy->mib.aggr_per / 10, phy->mib.aggr_per % 10);
}
static int
mt7615_ampdu_stat_read(struct seq_file *file, void *data)
{
struct mt7615_dev *dev = file->private;
mt7615_ampdu_stat_read_phy(&dev->phy, file);
mt7615_ampdu_stat_read_phy(mt7615_ext_phy(dev), file);
return 0;
}
......@@ -265,10 +293,10 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
return -ENOMEM;
if (is_mt7615(&dev->mt76))
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
mt7615_queues_read);
else
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
mt76_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7615_queues_acq);
......@@ -297,3 +325,4 @@ int mt7615_init_debugfs(struct mt7615_dev *dev)
return 0;
}
EXPORT_SYMBOL_GPL(mt7615_init_debugfs);
......@@ -94,45 +94,6 @@ mt7615_init_tx_queues(struct mt7615_dev *dev)
return 0;
}
void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
struct sk_buff *skb)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
__le32 *rxd = (__le32 *)skb->data;
__le32 *end = (__le32 *)&skb->data[skb->len];
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_TXS:
for (rxd++; rxd + 7 <= end; rxd += 7)
mt7615_mac_add_txs(dev, rxd);
dev_kfree_skb(skb);
break;
case PKT_TYPE_TXRX_NOTIFY:
mt7615_mac_tx_free(dev, skb);
break;
case PKT_TYPE_RX_EVENT:
mt7615_mcu_rx_event(dev, skb);
break;
case PKT_TYPE_NORMAL_MCU:
case PKT_TYPE_NORMAL:
if (!mt7615_mac_fill_rx(dev, skb)) {
mt76_rx(&dev->mt76, q, skb);
return;
}
/* fall through */
default:
dev_kfree_skb(skb);
break;
}
}
static void
mt7615_tx_cleanup(struct mt7615_dev *dev)
{
......@@ -160,13 +121,52 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget)
mt7615_tx_cleanup(dev);
rcu_read_lock();
mt7615_mac_sta_poll(dev);
rcu_read_unlock();
tasklet_schedule(&dev->mt76.tx_tasklet);
return 0;
}
int mt7615_wait_pdma_busy(struct mt7615_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
if (!is_mt7663(mdev)) {
u32 mask = MT_PDMA_TX_BUSY | MT_PDMA_RX_BUSY;
u32 reg = mt7615_reg_map(dev, MT_PDMA_BUSY);
if (!mt76_poll_msec(dev, reg, mask, 0, 1000)) {
dev_err(mdev->dev, "PDMA engine busy\n");
return -EIO;
}
return 0;
}
if (!mt76_poll_msec(dev, MT_PDMA_BUSY_STATUS,
MT_PDMA_TX_IDX_BUSY, 0, 1000)) {
dev_err(mdev->dev, "PDMA engine tx busy\n");
return -EIO;
}
if (!mt76_poll_msec(dev, MT_PSE_PG_INFO,
MT_PSE_SRC_CNT, 0, 1000)) {
dev_err(mdev->dev, "PSE engine busy\n");
return -EIO;
}
if (!mt76_poll_msec(dev, MT_PDMA_BUSY_STATUS,
MT_PDMA_BUSY_IDX, 0, 1000)) {
dev_err(mdev->dev, "PDMA engine busy\n");
return -EIO;
}
return 0;
}
static void mt7622_dma_sched_init(struct mt7615_dev *dev)
{
u32 reg = mt7615_reg_map(dev, MT_DMASHDL_BASE);
......@@ -229,8 +229,13 @@ static void mt7663_dma_sched_init(struct mt7615_dev *dev)
int mt7615_dma_init(struct mt7615_dev *dev)
{
int rx_ring_size = MT7615_RX_RING_SIZE;
int rx_buf_size = MT_RX_BUF_SIZE;
int ret;
/* Increase buffer size to receive large VHT MPDUs */
if (dev->mt76.cap.has_5ghz)
rx_buf_size *= 2;
mt76_dma_attach(&dev->mt76);
mt76_wr(dev, MT_WPDMA_GLO_CFG,
......@@ -271,7 +276,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
/* init rx queues */
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1,
MT7615_RX_MCU_RING_SIZE, MT_RX_BUF_SIZE,
MT7615_RX_MCU_RING_SIZE, rx_buf_size,
MT_RX_RING_BASE);
if (ret)
return ret;
......@@ -280,7 +285,7 @@ int mt7615_dma_init(struct mt7615_dev *dev)
rx_ring_size /= 2;
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0,
rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE);
rx_ring_size, rx_buf_size, MT_RX_RING_BASE);
if (ret)
return ret;
......
......@@ -5,6 +5,7 @@
* Felix Fietkau <nbd@nbd.name>
*/
#include <linux/of.h>
#include "mt7615.h"
#include "eeprom.h"
......@@ -40,11 +41,11 @@ static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
return 0;
}
static int mt7615_efuse_init(struct mt7615_dev *dev)
static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
{
u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE);
int i, len = MT7615_EEPROM_SIZE;
void *buf;
u32 val;
val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
if (val & MT_EFUSE_BASE_CTRL_EMPTY)
......@@ -67,15 +68,16 @@ static int mt7615_efuse_init(struct mt7615_dev *dev)
return 0;
}
static int mt7615_eeprom_load(struct mt7615_dev *dev)
static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
{
int ret;
ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE);
ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE +
MT7615_EEPROM_EXTRA_DATA);
if (ret < 0)
return ret;
return mt7615_efuse_init(dev);
return mt7615_efuse_init(dev, addr);
}
static int mt7615_check_eeprom(struct mt76_dev *dev)
......@@ -128,14 +130,15 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
{
u8 *eeprom = dev->mt76.eeprom.data;
u8 tx_mask;
u8 tx_mask, max_nss;
mt7615_eeprom_parse_hw_band_cap(dev);
if (is_mt7663(&dev->mt76)) {
tx_mask = 2;
max_nss = 2;
tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK,
eeprom[MT7663_EE_HW_CONF1]);
} else {
u8 max_nss;
u32 val;
/* read tx-rx mask from eeprom */
......@@ -144,21 +147,46 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
eeprom[MT_EE_NIC_CONF_0]);
if (!tx_mask || tx_mask > max_nss)
tx_mask = max_nss;
}
if (!tx_mask || tx_mask > max_nss)
tx_mask = max_nss;
dev->chainmask = BIT(tx_mask) - 1;
dev->mphy.antenna_mask = dev->chainmask;
dev->phy.chainmask = dev->chainmask;
}
int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx)
static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx)
{
int index, group;
if (chain_idx > 1)
return -EINVAL;
if (chan->band == NL80211_BAND_2GHZ)
return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4);
group = mt7615_get_channel_group(chan->hw_value);
if (chain_idx == 1)
index = MT7663_EE_TX1_5G_G0_TARGET_POWER;
else
index = MT7663_EE_TX0_5G_G0_TARGET_POWER;
return index + group * 3;
}
int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev,
struct ieee80211_channel *chan,
u8 chain_idx)
{
int index;
if (is_mt7663(&dev->mt76))
return mt7663_eeprom_get_target_power_index(dev, chan,
chain_idx);
if (chain_idx > 3)
return -EINVAL;
......@@ -197,6 +225,23 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
return index;
}
int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
enum nl80211_band band)
{
/* assume the first rate has the highest power offset */
if (is_mt7663(&dev->mt76)) {
if (band == NL80211_BAND_2GHZ)
return MT_EE_TX0_5G_G0_TARGET_POWER;
else
return MT7663_EE_5G_RATE_POWER;
}
if (band == NL80211_BAND_2GHZ)
return MT_EE_2G_RATE_POWER;
else
return MT_EE_5G_RATE_POWER;
}
static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
{
static const u16 ical[] = {
......@@ -255,6 +300,11 @@ static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)
static void mt7615_cal_free_data(struct mt7615_dev *dev)
{
struct device_node *np = dev->mt76.dev->of_node;
if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
return;
switch (mt76_chip(&dev->mt76)) {
case 0x7622:
mt7622_apply_cal_free_data(dev);
......@@ -265,20 +315,22 @@ static void mt7615_cal_free_data(struct mt7615_dev *dev)
}
}
int mt7615_eeprom_init(struct mt7615_dev *dev)
int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
{
int ret;
ret = mt7615_eeprom_load(dev);
ret = mt7615_eeprom_load(dev, addr);
if (ret < 0)
return ret;
ret = mt7615_check_eeprom(&dev->mt76);
if (ret && dev->mt76.otp.data)
if (ret && dev->mt76.otp.data) {
memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
MT7615_EEPROM_SIZE);
else
} else {
dev->flash_eeprom = true;
mt7615_cal_free_data(dev);
}
mt7615_eeprom_parse_hw_cap(dev);
memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
......@@ -288,3 +340,4 @@ int mt7615_eeprom_init(struct mt7615_dev *dev)
return 0;
}
EXPORT_SYMBOL_GPL(mt7615_eeprom_init);
......@@ -6,6 +6,21 @@
#include "mt7615.h"
#define MT7615_EEPROM_DCOC_OFFSET MT7615_EEPROM_SIZE
#define MT7615_EEPROM_DCOC_SIZE 256
#define MT7615_EEPROM_DCOC_COUNT 34
#define MT7615_EEPROM_TXDPD_OFFSET (MT7615_EEPROM_SIZE + \
MT7615_EEPROM_DCOC_COUNT * \
MT7615_EEPROM_DCOC_SIZE)
#define MT7615_EEPROM_TXDPD_SIZE 216
#define MT7615_EEPROM_TXDPD_COUNT (44 + 3)
#define MT7615_EEPROM_EXTRA_DATA (MT7615_EEPROM_TXDPD_OFFSET + \
MT7615_EEPROM_TXDPD_COUNT * \
MT7615_EEPROM_TXDPD_SIZE)
enum mt7615_eeprom_field {
MT_EE_CHIP_ID = 0x000,
MT_EE_VERSION = 0x002,
......@@ -13,23 +28,39 @@ enum mt7615_eeprom_field {
MT_EE_NIC_CONF_0 = 0x034,
MT_EE_NIC_CONF_1 = 0x036,
MT_EE_WIFI_CONF = 0x03e,
MT_EE_CALDATA_FLASH = 0x052,
MT_EE_TX0_2G_TARGET_POWER = 0x058,
MT_EE_TX0_5G_G0_TARGET_POWER = 0x070,
MT7663_EE_5G_RATE_POWER = 0x089,
MT_EE_TX1_5G_G0_TARGET_POWER = 0x098,
MT_EE_2G_RATE_POWER = 0x0be,
MT_EE_5G_RATE_POWER = 0x0d5,
MT7663_EE_TX0_2G_TARGET_POWER = 0x0e3,
MT_EE_EXT_PA_2G_TARGET_POWER = 0x0f2,
MT_EE_EXT_PA_5G_TARGET_POWER = 0x0f3,
MT7663_EE_TX0_2G_TARGET_POWER = 0x123,
MT_EE_TX2_5G_G0_TARGET_POWER = 0x142,
MT_EE_TX3_5G_G0_TARGET_POWER = 0x16a,
MT7663_EE_HW_CONF1 = 0x1b0,
MT7663_EE_TX0_5G_G0_TARGET_POWER = 0x245,
MT7663_EE_TX1_5G_G0_TARGET_POWER = 0x2b5,
MT7615_EE_MAX = 0x3bf,
MT7622_EE_MAX = 0x3db,
MT7663_EE_MAX = 0x400,
};
#define MT_EE_RATE_POWER_MASK GENMASK(5, 0)
#define MT_EE_RATE_POWER_SIGN BIT(6)
#define MT_EE_RATE_POWER_EN BIT(7)
#define MT_EE_CALDATA_FLASH_TX_DPD BIT(0)
#define MT_EE_CALDATA_FLASH_RX_CAL BIT(1)
#define MT_EE_NIC_CONF_TX_MASK GENMASK(7, 4)
#define MT_EE_NIC_CONF_RX_MASK GENMASK(3, 0)
#define MT_EE_HW_CONF1_TX_MASK GENMASK(2, 0)
#define MT_EE_NIC_CONF_TSSI_2G BIT(5)
#define MT_EE_NIC_CONF_TSSI_5G BIT(6)
......
......@@ -167,6 +167,10 @@ enum tx_phy_bandwidth {
#define MT_TXD_SIZE (8 * 4)
#define MT_USB_TXD_SIZE (MT_TXD_SIZE + 8 * 4)
#define MT_USB_HDR_SIZE 4
#define MT_USB_TAIL_SIZE 4
#define MT_TXD0_P_IDX BIT(31)
#define MT_TXD0_Q_IDX GENMASK(30, 26)
#define MT_TXD0_UDP_TCP_SUM BIT(24)
......@@ -252,8 +256,11 @@ enum tx_phy_bandwidth {
#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)
/* mt7663 */
#define MT_TXD_LEN_LAST BIT(15)
struct mt7615_txp_ptr {
__le32 buf0;
......@@ -393,6 +400,33 @@ enum mt7615_cipher_type {
MT_CIPHER_GCMP_256,
};
static inline enum mt7615_cipher_type
mt7615_mac_get_cipher(int cipher)
{
switch (cipher) {
case WLAN_CIPHER_SUITE_WEP40:
return MT_CIPHER_WEP40;
case WLAN_CIPHER_SUITE_WEP104:
return MT_CIPHER_WEP104;
case WLAN_CIPHER_SUITE_TKIP:
return MT_CIPHER_TKIP;
case WLAN_CIPHER_SUITE_AES_CMAC:
return MT_CIPHER_BIP_CMAC_128;
case WLAN_CIPHER_SUITE_CCMP:
return MT_CIPHER_AES_CCMP;
case WLAN_CIPHER_SUITE_CCMP_256:
return MT_CIPHER_CCMP_256;
case WLAN_CIPHER_SUITE_GCMP:
return MT_CIPHER_GCMP;
case WLAN_CIPHER_SUITE_GCMP_256:
return MT_CIPHER_GCMP_256;
case WLAN_CIPHER_SUITE_SMS4:
return MT_CIPHER_WAPI;
default:
return MT_CIPHER_NONE;
}
}
static inline struct mt7615_txp_common *
mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
......@@ -406,4 +440,9 @@ mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE);
}
static inline u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid)
{
return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE;
}
#endif
......@@ -81,7 +81,11 @@ enum {
MCU_EVENT_GENERIC = 0x01,
MCU_EVENT_ACCESS_REG = 0x02,
MCU_EVENT_MT_PATCH_SEM = 0x04,
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_EXT = 0xed,
MCU_EVENT_RESTART_DL = 0xef,
};
......@@ -232,7 +236,9 @@ enum {
#define MCU_FW_PREFIX BIT(31)
#define MCU_UNI_PREFIX BIT(30)
#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX)
#define MCU_CE_PREFIX BIT(29)
#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX | \
MCU_CE_PREFIX)
enum {
MCU_CMD_TARGET_ADDRESS_LEN_REQ = MCU_FW_PREFIX | 0x01,
......@@ -265,6 +271,8 @@ enum {
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,
};
......@@ -273,6 +281,261 @@ 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,
};
struct mt7615_mcu_uni_event {
u8 cid;
u8 pad[3];
__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
*/
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[64];
} __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_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_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;
#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;
/* 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_P2P_OPPPS = MCU_CE_PREFIX | 0x33,
MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61,
MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62,
};
#define MCU_CMD_ACK BIT(0)
......@@ -283,9 +546,25 @@ enum {
enum {
UNI_BSS_INFO_BASIC = 0,
UNI_BSS_INFO_RLM = 2,
UNI_BSS_INFO_BCN_CONTENT = 7,
};
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_ARPNS_IPV4,
UNI_OFFLOAD_OFFLOAD_ARPNS_IPV6,
UNI_OFFLOAD_OFFLOAD_GTK_REKEY,
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};
enum {
PATCH_SEM_RELEASE = 0x0,
PATCH_SEM_GET = 0x1
......@@ -306,6 +585,11 @@ enum {
FW_STATE_CR4_RDY = 7
};
enum {
FW_STATE_PWR_ON = 1,
FW_STATE_N9_RDY = 2,
};
#define STA_TYPE_STA BIT(0)
#define STA_TYPE_AP BIT(1)
#define STA_TYPE_ADHOC BIT(2)
......@@ -704,11 +988,4 @@ enum {
CH_SWITCH_SCAN_BYPASS_DPD = 9
};
static inline struct sk_buff *
mt7615_mcu_msg_alloc(const void *data, int len)
{
return mt76_mcu_msg_alloc(data, sizeof(struct mt7615_mcu_txd),
len, 0);
}
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include "mt7615.h"
#include "regs.h"
......@@ -13,12 +15,15 @@ const u32 mt7615e_reg_map[] = {
[MT_ARB_BASE] = 0x20c00,
[MT_HIF_BASE] = 0x04000,
[MT_CSR_BASE] = 0x07000,
[MT_PLE_BASE] = 0x08000,
[MT_PSE_BASE] = 0x0c000,
[MT_PHY_BASE] = 0x10000,
[MT_CFG_BASE] = 0x20200,
[MT_AGG_BASE] = 0x20a00,
[MT_TMAC_BASE] = 0x21000,
[MT_RMAC_BASE] = 0x21200,
[MT_DMA_BASE] = 0x21800,
[MT_PF_BASE] = 0x22000,
[MT_WTBL_BASE_ON] = 0x23000,
[MT_WTBL_BASE_OFF] = 0x23400,
[MT_LPON_BASE] = 0x24200,
......@@ -37,12 +42,15 @@ const u32 mt7663e_reg_map[] = {
[MT_ARB_BASE] = 0x20c00,
[MT_HIF_BASE] = 0x04000,
[MT_CSR_BASE] = 0x07000,
[MT_PLE_BASE] = 0x08000,
[MT_PSE_BASE] = 0x0c000,
[MT_PHY_BASE] = 0x10000,
[MT_CFG_BASE] = 0x20000,
[MT_AGG_BASE] = 0x22000,
[MT_TMAC_BASE] = 0x24000,
[MT_RMAC_BASE] = 0x25000,
[MT_DMA_BASE] = 0x27000,
[MT_PF_BASE] = 0x28000,
[MT_WTBL_BASE_ON] = 0x29000,
[MT_WTBL_BASE_OFF] = 0x29800,
[MT_LPON_BASE] = 0x2b000,
......@@ -80,30 +88,42 @@ mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q)
static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
{
struct mt7615_dev *dev = dev_instance;
u32 intr;
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
mt76_wr(dev, MT_INT_MASK_CSR, 0);
if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
return IRQ_NONE;
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
tasklet_schedule(&dev->irq_tasklet);
return IRQ_HANDLED;
}
static void mt7615_irq_tasklet(unsigned long data)
{
struct mt7615_dev *dev = (struct mt7615_dev *)data;
u32 intr, mask = 0;
mt76_wr(dev, MT_INT_MASK_CSR, 0);
intr = mt76_rr(dev, MT_INT_SOURCE_CSR);
mt76_wr(dev, MT_INT_SOURCE_CSR, intr);
trace_dev_irq(&dev->mt76, intr, dev->mt76.mmio.irqmask);
intr &= dev->mt76.mmio.irqmask;
if (intr & MT_INT_TX_DONE_ALL) {
mt7615_irq_disable(dev, MT_INT_TX_DONE_ALL);
mask |= MT_INT_TX_DONE_ALL;
napi_schedule(&dev->mt76.tx_napi);
}
if (intr & MT_INT_RX_DONE(0)) {
mt7615_irq_disable(dev, MT_INT_RX_DONE(0));
mask |= MT_INT_RX_DONE(0);
napi_schedule(&dev->mt76.napi[0]);
}
if (intr & MT_INT_RX_DONE(1)) {
mt7615_irq_disable(dev, MT_INT_RX_DONE(1));
mask |= MT_INT_RX_DONE(1);
napi_schedule(&dev->mt76.napi[1]);
}
......@@ -117,7 +137,7 @@ static irqreturn_t mt7615_irq_handler(int irq, void *dev_instance)
}
}
return IRQ_HANDLED;
mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
}
int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
......@@ -139,18 +159,25 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
.sta_remove = mt7615_mac_sta_remove,
.update_survey = mt7615_update_channel,
};
struct ieee80211_ops *ops;
struct mt7615_dev *dev;
struct mt76_dev *mdev;
int ret;
mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7615_ops, &drv_ops);
ops = devm_kmemdup(pdev, &mt7615_ops, sizeof(mt7615_ops), GFP_KERNEL);
if (!ops)
return -ENOMEM;
mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, &drv_ops);
if (!mdev)
return -ENOMEM;
dev = container_of(mdev, struct mt7615_dev, mt76);
mt76_mmio_init(&dev->mt76, mem_base);
tasklet_init(&dev->irq_tasklet, mt7615_irq_tasklet, (unsigned long)dev);
dev->reg_map = map;
dev->ops = ops;
mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
(mt76_rr(dev, MT_HW_REV) & 0xff);
dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
......@@ -172,3 +199,31 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,
ieee80211_free_hw(mt76_hw(dev));
return ret;
}
static int __init mt7615_init(void)
{
int ret;
ret = pci_register_driver(&mt7615_pci_driver);
if (ret)
return ret;
if (IS_ENABLED(CONFIG_MT7622_WMAC)) {
ret = platform_driver_register(&mt7622_wmac_driver);
if (ret)
pci_unregister_driver(&mt7615_pci_driver);
}
return ret;
}
static void __exit mt7615_exit(void)
{
if (IS_ENABLED(CONFIG_MT7622_WMAC))
platform_driver_unregister(&mt7622_wmac_driver);
pci_unregister_driver(&mt7615_pci_driver);
}
module_init(mt7615_init);
module_exit(mt7615_exit);
MODULE_LICENSE("Dual BSD/GPL");
......@@ -33,13 +33,27 @@ static int mt7615_pci_probe(struct pci_dev *pdev,
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)
return ret;
goto error;
mt76_pci_disable_aspm(pdev);
map = id->device == 0x7663 ? mt7663e_reg_map : mt7615e_reg_map;
return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
pdev->irq, map);
ret = mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
pdev->irq, map);
if (ret)
goto error;
return 0;
error:
pci_free_irq_vectors(pdev);
return ret;
}
static void mt7615_pci_remove(struct pci_dev *pdev)
......@@ -48,18 +62,130 @@ static void mt7615_pci_remove(struct pci_dev *pdev)
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
mt7615_unregister_device(dev);
devm_free_irq(&pdev->dev, pdev->irq, dev);
pci_free_irq_vectors(pdev);
}
#ifdef CONFIG_PM
static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
bool hif_suspend;
int i, 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);
if (err)
return err;
}
napi_disable(&mdev->tx_napi);
tasklet_kill(&mdev->tx_tasklet);
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++)
napi_disable(&mdev->napi[i]);
tasklet_kill(&dev->irq_tasklet);
mt7615_dma_reset(dev);
err = mt7615_wait_pdma_busy(dev);
if (err)
goto restore;
if (is_mt7663(mdev)) {
mt76_set(dev, MT_PDMA_SLP_PROT, MT_PDMA_AXI_SLPPROT_ENABLE);
if (!mt76_poll_msec(dev, MT_PDMA_SLP_PROT,
MT_PDMA_AXI_SLPPROT_RDY,
MT_PDMA_AXI_SLPPROT_RDY, 1000)) {
dev_err(mdev->dev, "PDMA sleep protection failed\n");
err = -EIO;
goto restore;
}
}
pci_enable_wake(pdev, pci_choose_state(pdev, state), true);
pci_save_state(pdev);
err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
if (err)
goto restore;
err = mt7615_firmware_own(dev);
if (err)
goto restore;
return 0;
restore:
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++)
napi_enable(&mdev->napi[i]);
napi_enable(&mdev->tx_napi);
if (hif_suspend)
mt7615_mcu_set_hif_suspend(dev, false);
return err;
}
static int mt7615_pci_resume(struct pci_dev *pdev)
{
struct mt76_dev *mdev = pci_get_drvdata(pdev);
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
bool pdma_reset;
int i, err;
err = mt7615_driver_own(dev);
if (err < 0)
return err;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
return err;
pci_restore_state(pdev);
if (is_mt7663(&dev->mt76)) {
mt76_clear(dev, MT_PDMA_SLP_PROT, MT_PDMA_AXI_SLPPROT_ENABLE);
mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1);
}
pdma_reset = !mt76_rr(dev, MT_WPDMA_TX_RING0_CTRL0) &&
!mt76_rr(dev, MT_WPDMA_TX_RING0_CTRL1);
if (pdma_reset)
dev_err(mdev->dev, "PDMA engine must be reinitialized\n");
for (i = 0; i < ARRAY_SIZE(mdev->q_rx); 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) &&
mt7615_firmware_offload(dev))
err = mt7615_mcu_set_hif_suspend(dev, false);
return err;
}
#endif /* CONFIG_PM */
struct pci_driver mt7615_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = mt7615_pci_device_table,
.probe = mt7615_pci_probe,
.remove = mt7615_pci_remove,
#ifdef CONFIG_PM
.suspend = mt7615_pci_suspend,
.resume = mt7615_pci_resume,
#endif /* CONFIG_PM */
};
MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table);
MODULE_FIRMWARE(MT7615_FIRMWARE_CR4);
MODULE_FIRMWARE(MT7615_FIRMWARE_N9);
MODULE_FIRMWARE(MT7615_ROM_PATCH);
MODULE_FIRMWARE(MT7663_OFFLOAD_FIRMWARE_N9);
MODULE_FIRMWARE(MT7663_OFFLOAD_ROM_PATCH);
MODULE_FIRMWARE(MT7663_FIRMWARE_N9);
MODULE_FIRMWARE(MT7663_ROM_PATCH);
// SPDX-License-Identifier: ISC
/* Copyright (C) 2019 MediaTek Inc.
*
* Author: Roy Luo <royluo@google.com>
* Ryder Lee <ryder.lee@mediatek.com>
* Felix Fietkau <nbd@nbd.name>
* Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/etherdevice.h>
#include "mt7615.h"
#include "mac.h"
#include "eeprom.h"
static void mt7615_init_work(struct work_struct *work)
{
struct mt7615_dev *dev = container_of(work, struct mt7615_dev,
mcu_work);
if (mt7615_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);
}
static int mt7615_init_hardware(struct mt7615_dev *dev)
{
u32 addr = mt7615_reg_map(dev, MT_EFUSE_BASE);
int ret, idx;
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
INIT_WORK(&dev->mcu_work, mt7615_init_work);
spin_lock_init(&dev->token_lock);
idr_init(&dev->token);
ret = mt7615_eeprom_init(dev, addr);
if (ret < 0)
return ret;
ret = mt7615_dma_init(dev);
if (ret)
return ret;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
if (idx)
return -ENOSPC;
dev->mt76.global_wcid.idx = idx;
dev->mt76.global_wcid.hw_key_idx = -1;
rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
return 0;
}
static void
mt7615_led_set_config(struct led_classdev *led_cdev,
u8 delay_on, u8 delay_off)
{
struct mt7615_dev *dev;
struct mt76_dev *mt76;
u32 val, addr;
mt76 = container_of(led_cdev, struct mt76_dev, led_cdev);
dev = container_of(mt76, struct mt7615_dev, mt76);
val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) |
FIELD_PREP(MT_LED_STATUS_OFF, delay_off) |
FIELD_PREP(MT_LED_STATUS_ON, delay_on);
addr = mt7615_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin));
mt76_wr(dev, addr, val);
addr = mt7615_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin));
mt76_wr(dev, addr, val);
val = MT_LED_CTRL_REPLAY(mt76->led_pin) |
MT_LED_CTRL_KICK(mt76->led_pin);
if (mt76->led_al)
val |= MT_LED_CTRL_POLARITY(mt76->led_pin);
addr = mt7615_reg_map(dev, MT_LED_CTRL);
mt76_wr(dev, addr, val);
}
static int
mt7615_led_set_blink(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
u8 delta_on, delta_off;
delta_off = max_t(u8, *delay_off / 10, 1);
delta_on = max_t(u8, *delay_on / 10, 1);
mt7615_led_set_config(led_cdev, delta_on, delta_off);
return 0;
}
static void
mt7615_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
if (!brightness)
mt7615_led_set_config(led_cdev, 0, 0xff);
else
mt7615_led_set_config(led_cdev, 0xff, 0);
}
int mt7615_register_device(struct mt7615_dev *dev)
{
int ret;
mt7615_init_device(dev);
/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
dev->mt76.led_cdev.brightness_set = mt7615_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt7615_led_set_blink;
}
ret = mt7622_wmac_init(dev);
if (ret)
return ret;
ret = mt7615_init_hardware(dev);
if (ret)
return ret;
ret = mt76_register_device(&dev->mt76, true, mt7615_rates,
ARRAY_SIZE(mt7615_rates));
if (ret)
return ret;
ieee80211_queue_work(mt76_hw(dev), &dev->mcu_work);
mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband);
return mt7615_init_debugfs(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);
mt7615_unregister_ext_phy(dev);
mt76_unregister_device(&dev->mt76);
if (mcu_running)
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);
tasklet_disable(&dev->irq_tasklet);
mt76_free_device(&dev->mt76);
}
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc.
*
* Author: Ryder Lee <ryder.lee@mediatek.com>
* Roy Luo <royluo@google.com>
* Felix Fietkau <nbd@nbd.name>
* Lorenzo Bianconi <lorenzo@kernel.org>
*/
#include <linux/etherdevice.h>
#include <linux/timekeeping.h>
#include "mt7615.h"
#include "../dma.h"
#include "mac.h"
void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
struct mt76_queue_entry *e)
{
if (!e->txwi) {
dev_kfree_skb_any(e->skb);
return;
}
/* error path */
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_txwi_cache *t;
struct mt7615_dev *dev;
struct mt7615_txp_common *txp;
u16 token;
dev = container_of(mdev, struct mt7615_dev, mt76);
txp = mt7615_txwi_to_txp(mdev, e->txwi);
if (is_mt7615(&dev->mt76))
token = le16_to_cpu(txp->fw.token);
else
token = le16_to_cpu(txp->hw.msdu_id[0]) &
~MT_MSDU_ID_VALID;
spin_lock_bh(&dev->token_lock);
t = idr_remove(&dev->token, token);
spin_unlock_bh(&dev->token_lock);
e->skb = t ? t->skb : NULL;
}
if (e->skb)
mt76_tx_complete_skb(mdev, e->skb);
}
static void
mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct mt7615_hw_txp *txp = txp_ptr;
struct mt7615_txp_ptr *ptr = &txp->ptr[0];
int i, nbuf = tx_info->nbuf - 1;
u32 last_mask;
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
tx_info->nbuf = 1;
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
if (is_mt7663(&dev->mt76))
last_mask = MT_TXD_LEN_LAST;
else
last_mask = MT_TXD_LEN_AMSDU_LAST |
MT_TXD_LEN_MSDU_LAST;
for (i = 0; i < nbuf; i++) {
u16 len = tx_info->buf[i + 1].len & MT_TXD_LEN_MASK;
u32 addr = tx_info->buf[i + 1].addr;
if (i == nbuf - 1)
len |= last_mask;
if (i & 1) {
ptr->buf1 = cpu_to_le32(addr);
ptr->len1 = cpu_to_le16(len);
ptr++;
} else {
ptr->buf0 = cpu_to_le32(addr);
ptr->len0 = cpu_to_le16(len);
}
}
}
static void
mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
struct mt7615_fw_txp *txp = txp_ptr;
int nbuf = tx_info->nbuf - 1;
int i;
for (i = 0; i < nbuf; i++) {
txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
}
txp->nbuf = nbuf;
/* pass partial skb header to fw */
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
tx_info->buf[1].len = MT_CT_PARSE_LEN;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);
if (!key)
txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
if (ieee80211_is_mgmt(hdr->frame_control))
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
if (vif) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
txp->bss_idx = mvif->idx;
}
txp->token = cpu_to_le16(id);
txp->rept_wds_wcid = 0xff;
}
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
int pid, id;
u8 *txwi = (u8 *)txwi_ptr;
struct mt76_txwi_cache *t;
void *txp;
if (!wcid)
wcid = &dev->mt76.global_wcid;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
struct mt7615_phy *phy = &dev->phy;
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
phy = mdev->phy2->priv;
spin_lock_bh(&dev->mt76.lock);
mt7615_mac_set_rates(phy, msta, &info->control.rates[0],
msta->rates);
msta->rate_probe = true;
spin_unlock_bh(&dev->mt76.lock);
}
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
spin_lock_bh(&dev->token_lock);
id = idr_alloc(&dev->token, t, 0, MT7615_TOKEN_SIZE, GFP_ATOMIC);
spin_unlock_bh(&dev->token_lock);
if (id < 0)
return id;
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
pid, key, false);
txp = txwi + MT_TXD_SIZE;
memset(txp, 0, sizeof(struct mt7615_txp_common));
if (is_mt7615(&dev->mt76))
mt7615_write_fw_txp(dev, tx_info, txp, id);
else
mt7615_write_hw_txp(dev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
return 0;
}
......@@ -12,12 +12,15 @@ enum mt7615_reg_base {
MT_ARB_BASE,
MT_HIF_BASE,
MT_CSR_BASE,
MT_PLE_BASE,
MT_PSE_BASE,
MT_PHY_BASE,
MT_CFG_BASE,
MT_AGG_BASE,
MT_TMAC_BASE,
MT_RMAC_BASE,
MT_DMA_BASE,
MT_PF_BASE,
MT_WTBL_BASE_ON,
MT_WTBL_BASE_OFF,
MT_LPON_BASE,
......@@ -43,6 +46,7 @@ enum mt7615_reg_base {
#define MT_TOP_MISC2_FW_STATE GENMASK(2, 0)
#define MT7663_TOP_MISC2_FW_STATE GENMASK(3, 1)
#define MT_TOP_MISC2_FW_PWR_ON BIT(1)
#define MT_MCU_BASE 0x2000
#define MT_MCU(ofs) (MT_MCU_BASE + (ofs))
......@@ -58,6 +62,19 @@ enum mt7615_reg_base {
#define MT_PCIE_REMAP_BASE_2 ((dev)->reg_map[MT_PCIE_REMAP_BASE2])
#define MT_HIF(ofs) ((dev)->reg_map[MT_HIF_BASE] + (ofs))
#define MT_HIF_RST MT_HIF(0x100)
#define MT_HIF_LOGIC_RST_N BIT(4)
#define MT_PDMA_SLP_PROT MT_HIF(0x154)
#define MT_PDMA_AXI_SLPPROT_ENABLE BIT(0)
#define MT_PDMA_AXI_SLPPROT_RDY BIT(16)
#define MT_PDMA_BUSY_STATUS MT_HIF(0x168)
#define MT_PDMA_TX_IDX_BUSY BIT(2)
#define MT_PDMA_BUSY_IDX BIT(31)
#define MT_WPDMA_TX_RING0_CTRL0 MT_HIF(0x300)
#define MT_WPDMA_TX_RING0_CTRL1 MT_HIF(0x304)
#define MT7663_MCU_PCIE_REMAP_2_OFFSET GENMASK(15, 0)
#define MT7663_MCU_PCIE_REMAP_2_BASE GENMASK(31, 16)
......@@ -65,6 +82,7 @@ enum mt7615_reg_base {
#define MT_HIF2_BASE 0xf0000
#define MT_HIF2(ofs) (MT_HIF2_BASE + (ofs))
#define MT_PCIE_IRQ_ENABLE MT_HIF2(0x188)
#define MT_PCIE_DOORBELL_PUSH MT_HIF2(0x1484)
#define MT_CFG_LPCR_HOST MT_HIF(0x1f0)
#define MT_CFG_LPCR_HOST_FW_OWN BIT(0)
......@@ -133,8 +151,7 @@ enum mt7615_reg_base {
#define MT_CSR(ofs) ((dev)->reg_map[MT_CSR_BASE] + (ofs))
#define MT_CONN_HIF_ON_LPCTL MT_CSR(0x000)
#define MT_PLE_BASE 0x8000
#define MT_PLE(ofs) (MT_PLE_BASE + (ofs))
#define MT_PLE(ofs) ((dev)->reg_map[MT_PLE_BASE] + (ofs))
#define MT_PLE_FL_Q0_CTRL MT_PLE(0x1b0)
#define MT_PLE_FL_Q1_CTRL MT_PLE(0x1b4)
......@@ -144,6 +161,14 @@ enum mt7615_reg_base {
#define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \
((n) << 2))
#define MT_PSE(ofs) ((dev)->reg_map[MT_PSE_BASE] + (ofs))
#define MT_PSE_QUEUE_EMPTY MT_PSE(0x0b4)
#define MT_HIF_0_EMPTY_MASK BIT(16)
#define MT_HIF_1_EMPTY_MASK BIT(17)
#define MT_HIF_ALL_EMPTY_MASK GENMASK(17, 16)
#define MT_PSE_PG_INFO MT_PSE(0x194)
#define MT_PSE_SRC_CNT GENMASK(27, 16)
#define MT_WF_PHY_BASE ((dev)->reg_map[MT_PHY_BASE])
#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs))
......@@ -151,29 +176,40 @@ enum mt7615_reg_base {
#define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9)
#define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9))
#define MT7663_WF_PHY_R0_PHYMUX_5 MT_WF_PHY(0x0414)
#define MT_WF_PHY_R0_PHYCTRL_STS0(_phy) MT_WF_PHY(0x020c + ((_phy) << 9))
#define MT_WF_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16)
#define MT_WF_PHYCTRL_STAT_PD_CCK GENMASK(15, 0)
#define MT7663_WF_PHY_R0_PHYCTRL_STS0(_phy) MT_WF_PHY(0x0210 + ((_phy) << 12))
#define MT_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0220 + ((_phy) << 9))
#define MT_WF_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16)
#define MT_WF_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0)
#define MT7663_WF_PHY_R0_PHYCTRL_STS5(_phy) MT_WF_PHY(0x0224 + ((_phy) << 12))
#define MT_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x084 : 0x229c)
#define MT_WF_PHY_PD_OFDM_MASK(_phy) ((_phy) ? GENMASK(24, 16) : \
GENMASK(28, 20))
#define MT_WF_PHY_PD_OFDM(_phy, v) ((v) << ((_phy) ? 16 : 20))
#define MT_WF_PHY_PD_BLK(_phy) ((_phy) ? BIT(25) : BIT(19))
#define MT7663_WF_PHY_MIN_PRI_PWR(_phy) MT_WF_PHY((_phy) ? 0x2aec : 0x22f0)
#define MT_WF_PHY_RXTD_BASE MT_WF_PHY(0x2200)
#define MT_WF_PHY_RXTD(_n) (MT_WF_PHY_RXTD_BASE + ((_n) << 2))
#define MT7663_WF_PHY_RXTD(_n) (MT_WF_PHY(0x25b0) + ((_n) << 2))
#define MT_WF_PHY_RXTD_CCK_PD(_phy) MT_WF_PHY((_phy) ? 0x2314 : 0x2310)
#define MT_WF_PHY_PD_CCK_MASK(_phy) (_phy) ? GENMASK(31, 24) : \
GENMASK(8, 1)
#define MT_WF_PHY_PD_CCK(_phy, v) ((v) << ((_phy) ? 24 : 1))
#define MT7663_WF_PHY_RXTD_CCK_PD(_phy) MT_WF_PHY((_phy) ? 0x2350 : 0x234c)
#define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00)
#define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2))
......@@ -306,10 +342,17 @@ enum mt7615_reg_base {
#define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2)
#define MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR BIT(3)
#define MT_DMA_RCFR0_MCU_RX_CTL_BAR BIT(4)
#define MT_DMA_RCFR0_MCU_RX_TDLS BIT(19)
#define MT_DMA_RCFR0_MCU_RX_BYPASS BIT(21)
#define MT_DMA_RCFR0_RX_DROPPED_UCAST GENMASK(25, 24)
#define MT_DMA_RCFR0_RX_DROPPED_MCAST GENMASK(27, 26)
#define MT_WF_PF_BASE ((dev)->reg_map[MT_PF_BASE])
#define MT_WF_PF(ofs) (MT_WF_PF_BASE + (ofs))
#define MT_WF_PFCR MT_WF_PF(0x000)
#define MT_WF_PFCR_TDLS_EN BIT(9)
#define MT_WTBL_BASE(dev) ((dev)->reg_map[MT_WTBL_BASE_ADDR])
#define MT_WTBL_ENTRY_SIZE 256
......@@ -379,34 +422,44 @@ enum mt7615_reg_base {
#define MT_LPON_UTTR1 MT_LPON(0x01c)
#define MT_WF_MIB_BASE (dev->reg_map[MT_MIB_BASE])
#define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs))
#define MT_WF_MIB(_band, ofs) (MT_WF_MIB_BASE + (ofs) + (_band) * 0x200)
#define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c)
#define MT_WF_MIB_SCR0 MT_WF_MIB(0, 0)
#define MT_MIB_SCR0_AGG_CNT_RANGE_EN BIT(21)
#define MT_MIB_SDR3(n) MT_WF_MIB(0x014 + ((n) << 9))
#define MT_MIB_M0_MISC_CR(_band) MT_WF_MIB(_band, 0x00c)
#define MT_MIB_SDR3(_band) MT_WF_MIB(_band, 0x014)
#define MT_MIB_SDR3_FCS_ERR_MASK GENMASK(15, 0)
#define MT_MIB_SDR9(n) MT_WF_MIB(0x02c + ((n) << 9))
#define MT_MIB_SDR9(_band) MT_WF_MIB(_band, 0x02c)
#define MT_MIB_SDR9_BUSY_MASK GENMASK(23, 0)
#define MT_MIB_SDR16(n) MT_WF_MIB(0x048 + ((n) << 9))
#define MT_MIB_SDR14(_band) MT_WF_MIB(_band, 0x040)
#define MT_MIB_AMPDU_MPDU_COUNT GENMASK(23, 0)
#define MT_MIB_SDR15(_band) MT_WF_MIB(_band, 0x044)
#define MT_MIB_AMPDU_ACK_COUNT 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_SDR36(n) MT_WF_MIB(0x098 + ((n) << 9))
#define MT_MIB_SDR36(_band) MT_WF_MIB(_band, 0x098)
#define MT_MIB_SDR36_TXTIME_MASK GENMASK(23, 0)
#define MT_MIB_SDR37(n) MT_WF_MIB(0x09c + ((n) << 9))
#define MT_MIB_SDR37(_band) MT_WF_MIB(_band, 0x09c)
#define MT_MIB_SDR37_RXTIME_MASK GENMASK(23, 0)
#define MT_MIB_MB_SDR0(_band, n) MT_WF_MIB(0x100 + ((_band) << 9) + \
((n) << 4))
#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(0x104 + ((_band) << 9) + \
((n) << 4))
#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_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2))
#define MT_MIB_ARNG(n) MT_WF_MIB(0, 0x4b8 + ((n) << 2))
#define MT_TX_AGG_CNT(_band, n) MT_WF_MIB(_band, 0xa8 + ((n) << 2))
#define MT_DMA_SHDL(ofs) (dev->reg_map[MT_DMA_SHDL_BASE] + (ofs))
......@@ -449,6 +502,10 @@ enum mt7615_reg_base {
#define MT_LED_STATUS_ON GENMASK(23, 16)
#define MT_LED_STATUS_DURATION GENMASK(15, 0)
#define MT_PDMA_BUSY 0x82000504
#define MT_PDMA_TX_BUSY BIT(0)
#define MT_PDMA_RX_BUSY BIT(1)
#define MT_EFUSE_BASE ((dev)->reg_map[MT_EFUSE_ADDR_BASE])
#define MT_EFUSE_BASE_CTRL 0x000
#define MT_EFUSE_BASE_CTRL_EMPTY BIT(30)
......@@ -470,4 +527,27 @@ enum mt7615_reg_base {
#define MT_INFRACFG_MISC 0x700
#define MT_INFRACFG_MISC_AP2CONN_WAKE BIT(1)
#define MT_UMAC_BASE 0x7c000000
#define MT_UMAC(ofs) (MT_UMAC_BASE + (ofs))
#define MT_UDMA_TX_QSEL MT_UMAC(0x008)
#define MT_FW_DL_EN BIT(3)
#define MT_UDMA_WLCFG_1 MT_UMAC(0x00c)
#define MT_WL_RX_AGG_PKT_LMT GENMASK(7, 0)
#define MT_WL_TX_TMOUT_LMT GENMASK(27, 8)
#define MT_UDMA_WLCFG_0 MT_UMAC(0x18)
#define MT_WL_RX_AGG_TO GENMASK(7, 0)
#define MT_WL_RX_AGG_LMT GENMASK(15, 8)
#define MT_WL_TX_TMOUT_FUNC_EN BIT(16)
#define MT_WL_TX_DPH_CHK_EN BIT(17)
#define MT_WL_RX_MPSZ_PAD0 BIT(18)
#define MT_WL_RX_FLUSH BIT(19)
#define MT_TICK_1US_EN BIT(20)
#define MT_WL_RX_AGG_EN BIT(21)
#define MT_WL_RX_EN BIT(22)
#define MT_WL_TX_EN BIT(23)
#define MT_WL_RX_BUSY BIT(30)
#define MT_WL_TX_BUSY BIT(31)
#endif
......@@ -36,10 +36,8 @@ static int mt7622_wmac_probe(struct platform_device *pdev)
int irq;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Failed to get device IRQ\n");
if (irq < 0)
return irq;
}
mem_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(mem_base)) {
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 MediaTek Inc.
*
* Author: Felix Fietkau <nbd@nbd.name>
* Lorenzo Bianconi <lorenzo@kernel.org>
* Sean Wang <sean.wang@mediatek.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "mt7615.h"
#include "mac.h"
#include "regs.h"
static int mt7663u_dma_sched_init(struct mt7615_dev *dev)
{
int i;
mt76_rmw(dev, MT_DMA_SHDL(MT_DMASHDL_PKT_MAX_SIZE),
MT_DMASHDL_PKT_MAX_SIZE_PLE | MT_DMASHDL_PKT_MAX_SIZE_PSE,
FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PLE, 1) |
FIELD_PREP(MT_DMASHDL_PKT_MAX_SIZE_PSE, 8));
/* disable refill group 5 - group 15 and raise group 2
* and 3 as high priority.
*/
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_REFILL), 0xffe00006);
mt76_clear(dev, MT_DMA_SHDL(MT_DMASHDL_PAGE), BIT(16));
for (i = 0; i < 5; i++)
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(i)),
FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x3) |
FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x1ff));
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(0)), 0x42104210);
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(1)), 0x42104210);
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(2)), 0x4444);
/* group pririority from high to low:
* 15 (cmd groups) > 4 > 3 > 2 > 1 > 0.
*/
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET0), 0x6501234f);
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987);
mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_OPTIONAL), 0x7004801c);
mt76_wr(dev, MT_UDMA_WLCFG_1,
FIELD_PREP(MT_WL_TX_TMOUT_LMT, 80000) |
FIELD_PREP(MT_WL_RX_AGG_PKT_LMT, 1));
/* setup UDMA Rx Flush */
mt76_clear(dev, MT_UDMA_WLCFG_0, MT_WL_RX_FLUSH);
/* hif reset */
mt76_set(dev, MT_HIF_RST, MT_HIF_LOGIC_RST_N);
mt76_set(dev, MT_UDMA_WLCFG_0,
MT_WL_RX_AGG_EN | MT_WL_RX_EN | MT_WL_TX_EN |
MT_WL_RX_MPSZ_PAD0 | MT_TICK_1US_EN |
MT_WL_TX_TMOUT_FUNC_EN);
mt76_rmw(dev, MT_UDMA_WLCFG_0, MT_WL_RX_AGG_LMT | MT_WL_RX_AGG_TO,
FIELD_PREP(MT_WL_RX_AGG_LMT, 32) |
FIELD_PREP(MT_WL_RX_AGG_TO, 100));
return 0;
}
static int mt7663u_init_hardware(struct mt7615_dev *dev)
{
int ret, idx;
ret = mt7615_eeprom_init(dev, MT_EFUSE_BASE);
if (ret < 0)
return ret;
ret = mt7663u_dma_sched_init(dev);
if (ret)
return ret;
set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);
/* Beacon and mgmt frames should occupy wcid 0 */
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7615_WTBL_STA - 1);
if (idx)
return -ENOSPC;
dev->mt76.global_wcid.idx = idx;
dev->mt76.global_wcid.hw_key_idx = -1;
rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);
return 0;
}
static void mt7663u_init_work(struct work_struct *work)
{
struct mt7615_dev *dev;
dev = container_of(work, struct mt7615_dev, mcu_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);
}
int mt7663u_register_device(struct mt7615_dev *dev)
{
struct ieee80211_hw *hw = mt76_hw(dev);
int err;
INIT_WORK(&dev->wtbl_work, mt7663u_wtbl_work);
INIT_WORK(&dev->mcu_work, mt7663u_init_work);
INIT_LIST_HEAD(&dev->wd_head);
mt7615_init_device(dev);
err = mt7663u_init_hardware(dev);
if (err)
return err;
hw->extra_tx_headroom += MT_USB_HDR_SIZE + MT_USB_TXD_SIZE;
/* check hw sg support in order to enable AMSDU */
hw->max_tx_fragments = dev->mt76.usb.sg_en ? MT_HW_TXP_MAX_BUF_NUM : 1;
err = mt76_register_device(&dev->mt76, true, mt7615_rates,
ARRAY_SIZE(mt7615_rates));
if (err < 0)
return err;
if (!dev->mt76.usb.sg_en) {
struct ieee80211_sta_vht_cap *vht_cap;
/* decrease max A-MSDU size if SG is not supported */
vht_cap = &dev->mphy.sband_5g.sband.vht_cap;
vht_cap->cap &= ~IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
}
ieee80211_queue_work(hw, &dev->mcu_work);
mt7615_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7615_init_txpower(dev, &dev->mphy.sband_5g.sband);
return mt7615_init_debugfs(dev);
}
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 MediaTek Inc.
*
* Author: Felix Fietkau <nbd@nbd.name>
* Lorenzo Bianconi <lorenzo@kernel.org>
* Sean Wang <sean.wang@mediatek.com>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "mt7615.h"
#include "mac.h"
#include "mcu.h"
#include "regs.h"
static int
mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, bool wait_resp)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
int ret, seq, ep;
mutex_lock(&mdev->mcu.mutex);
mt7615_mcu_fill_msg(dev, skb, cmd, &seq);
if (cmd != MCU_CMD_FW_SCATTER)
ep = MT_EP_OUT_INBAND_CMD;
else
ep = MT_EP_OUT_AC_BE;
ret = mt76u_skb_dma_info(skb, skb->len);
if (ret < 0)
goto out;
ret = mt76u_bulk_msg(&dev->mt76, skb->data, skb->len, NULL,
1000, ep);
dev_kfree_skb(skb);
if (ret < 0)
goto out;
if (wait_resp)
ret = mt7615_mcu_wait_response(dev, cmd, seq);
out:
mutex_unlock(&mdev->mcu.mutex);
return ret;
}
int mt7663u_mcu_init(struct mt7615_dev *dev)
{
static const struct mt76_mcu_ops mt7663u_mcu_ops = {
.headroom = MT_USB_HDR_SIZE + sizeof(struct mt7615_mcu_txd),
.tailroom = MT_USB_TAIL_SIZE,
.mcu_skb_send_msg = mt7663u_mcu_send_message,
.mcu_send_msg = mt7615_mcu_msg_send,
.mcu_restart = mt7615_mcu_restart,
};
int ret;
dev->mt76.mcu_ops = &mt7663u_mcu_ops,
mt76_set(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
if (test_and_clear_bit(MT76_STATE_POWER_OFF, &dev->mphy.state)) {
mt7615_mcu_restart(&dev->mt76);
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
MT_TOP_MISC2_FW_PWR_ON, 0, 500))
return -EIO;
ret = mt76u_vendor_request(&dev->mt76, MT_VEND_POWER_ON,
USB_DIR_OUT | USB_TYPE_VENDOR,
0x0, 0x1, NULL, 0);
if (ret)
return ret;
if (!mt76_poll_msec(dev, MT_CONN_ON_MISC,
MT_TOP_MISC2_FW_PWR_ON,
FW_STATE_PWR_ON << 1, 500)) {
dev_err(dev->mt76.dev, "Timeout for power on\n");
return -EIO;
}
}
ret = __mt7663_load_firmware(dev);
if (ret)
return ret;
mt76_clear(dev, MT_UDMA_TX_QSEL, MT_FW_DL_EN);
set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
return 0;
}
......@@ -12,24 +12,6 @@
#include "initvals.h"
#include "../mt76x02_phy.h"
static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
{
struct ieee80211_sta_vht_cap *vht_cap = &sband->vht_cap;
u16 mcs_map = 0;
int i;
vht_cap->cap &= ~IEEE80211_VHT_CAP_RXLDPC;
for (i = 0; i < 8; i++) {
if (!i)
mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_7 << (i * 2));
else
mcs_map |=
(IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
}
vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
}
static void
mt76x0_set_wlan_state(struct mt76x02_dev *dev, u32 val, bool enable)
{
......@@ -263,9 +245,11 @@ int mt76x0_register_device(struct mt76x02_dev *dev)
return ret;
if (dev->mt76.cap.has_5ghz) {
/* overwrite unsupported features */
mt76x0_vht_cap_mask(&dev->mphy.sband_5g.sband);
mt76x0_init_txpower(dev, &dev->mphy.sband_5g.sband);
struct ieee80211_supported_band *sband;
sband = &dev->mphy.sband_5g.sband;
sband->vht_cap.cap &= ~IEEE80211_VHT_CAP_RXLDPC;
mt76x0_init_txpower(dev, sband);
}
if (dev->mt76.cap.has_2ghz)
......
......@@ -144,7 +144,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev)
if (!dir)
return;
debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir,
debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
mt76_queues_read);
debugfs_create_u8("temperature", 0400, dir, &dev->cal.temp);
debugfs_create_bool("tpc", 0600, dir, &dev->enable_tpc);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment