diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7615')
19 files changed, 4466 insertions, 1617 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig index 4cabba9aa2ea..6afd4aea67ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Kconfig @@ -11,3 +11,14 @@ config MT7615E MU-MIMO up to 4 users/group and 160MHz channels. To compile this driver as a module, choose M here. + +config MT7622_WMAC + bool "MT7622 (SoC) WMAC support" + depends on MT7615E + depends on ARCH_MEDIATEK || COMPILE_TEST + select REGMAP + default y + help + 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. diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile index 5aaac69849d6..5c6a220ed7e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/Makefile +++ b/drivers/net/wireless/mediatek/mt76/mt7615/Makefile @@ -2,5 +2,8 @@ obj-$(CONFIG_MT7615E) += mt7615e.o -mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o \ - debugfs.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 +mt7615e-$(CONFIG_MT7622_WMAC) += soc.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index f6b75f832e6a..b4d0795154e3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -7,6 +7,9 @@ mt7615_radar_pattern_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + return mt7615_mcu_rdd_send_pattern(dev); } @@ -18,6 +21,9 @@ mt7615_scs_set(void *data, u64 val) { struct mt7615_dev *dev = data; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + mt7615_mac_set_scs(dev, val); return 0; @@ -37,6 +43,84 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get, mt7615_scs_set, "%lld\n"); static int +mt7615_dbdc_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + if (val) + mt7615_register_ext_phy(dev); + else + mt7615_unregister_ext_phy(dev); + + return 0; +} + +static int +mt7615_dbdc_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = !!mt7615_ext_phy(dev); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get, + mt7615_dbdc_set, "%lld\n"); + +static int +mt7615_fw_debug_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + dev->fw_debug = val; + mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0); + + return 0; +} + +static int +mt7615_fw_debug_get(void *data, u64 *val) +{ + struct mt7615_dev *dev = data; + + *val = dev->fw_debug; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get, + mt7615_fw_debug_set, "%lld\n"); + +static int +mt7615_reset_test_set(void *data, u64 val) +{ + struct mt7615_dev *dev = data; + struct sk_buff *skb; + + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + + skb = alloc_skb(1, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + skb_put(skb, 1); + mt76_tx_queue_skb_raw(dev, 0, skb, 0); + + return 0; +} + +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) { struct mt7615_dev *dev = file->private; @@ -74,15 +158,28 @@ static const struct file_operations fops_ampdu_stat = { .release = single_release, }; +static void +mt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s) +{ + struct mt7615_dev *dev = dev_get_drvdata(s->private); + bool ext_phy = phy != &dev->phy; + + if (!phy) + return; + + seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy, + phy->ofdm_sensitivity, phy->cck_sensitivity); + seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy, + phy->false_cca_ofdm, phy->false_cca_cck); +} + static int mt7615_radio_read(struct seq_file *s, void *data) { struct mt7615_dev *dev = dev_get_drvdata(s->private); - seq_printf(s, "Sensitivity: ofdm=%d cck=%d\n", - dev->ofdm_sensitivity, dev->cck_sensitivity); - seq_printf(s, "False CCA: ofdm=%d cck=%d\n", - dev->false_cca_ofdm, dev->false_cca_cck); + mt7615_radio_read_phy(&dev->phy, s); + mt7615_radio_read_phy(mt7615_ext_phy(dev), s); return 0; } @@ -92,6 +189,9 @@ static int mt7615_read_temperature(struct seq_file *s, void *data) struct mt7615_dev *dev = dev_get_drvdata(s->private); int temp; + if (!mt7615_wait_for_mcu_init(dev)) + return 0; + /* cpu */ temp = mt7615_mcu_get_temperature(dev, 0); seq_printf(s, "Temperature: %d\n", temp); @@ -164,12 +264,18 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) if (!dir) return -ENOMEM; - debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, - mt7615_queues_read); + if (is_mt7615(&dev->mt76)) + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt7615_queues_read); + else + debugfs_create_devm_seqfile(dev->mt76.dev, "queues", dir, + mt76_queues_read); debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, mt7615_queues_acq); debugfs_create_file("ampdu_stat", 0400, dir, dev, &fops_ampdu_stat); debugfs_create_file("scs", 0600, dir, dev, &fops_scs); + debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc); + debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); @@ -184,6 +290,8 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) &dev->radar_pattern.power); debugfs_create_file("radar_trigger", 0200, dir, dev, &fops_radar_pattern); + debugfs_create_file("reset_test", 0200, dir, dev, + &fops_reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "temperature", dir, mt7615_read_temperature); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 285d4f1d6178..b19f208e3d54 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -12,47 +12,85 @@ #include "mac.h" static int -mt7615_init_tx_queues(struct mt7615_dev *dev, int n_desc) +mt7615_init_tx_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, + int idx, int n_desc) { - struct mt76_sw_queue *q; struct mt76_queue *hwq; - int err, i; + int err; hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); if (!hwq) return -ENOMEM; - err = mt76_queue_alloc(dev, hwq, 0, n_desc, 0, MT_TX_RING_BASE); + err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); if (err < 0) return err; - for (i = 0; i < MT_TXQ_MCU; i++) { - q = &dev->mt76.q_tx[i]; - INIT_LIST_HEAD(&q->swq); - q->q = hwq; - } + INIT_LIST_HEAD(&q->swq); + q->q = hwq; return 0; } static int -mt7615_init_mcu_queue(struct mt7615_dev *dev, struct mt76_sw_queue *q, - int idx, int n_desc) +mt7622_init_tx_queues_multi(struct mt7615_dev *dev) { - struct mt76_queue *hwq; - int err; + static const u8 wmm_queue_map[] = { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_AC3, + }; + int ret; + int i; - hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); - if (!hwq) - return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[i], + wmm_queue_map[i], + MT7615_TX_RING_SIZE / 2); + if (ret) + return ret; + } - err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); - if (err < 0) - return err; + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], + MT7622_TXQ_MGMT, MT7615_TX_MGMT_RING_SIZE); + if (ret) + return ret; - INIT_LIST_HEAD(&q->swq); - q->q = hwq; + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7622_TXQ_MCU, MT7615_TX_MCU_RING_SIZE); + return ret; +} + +static int +mt7615_init_tx_queues(struct mt7615_dev *dev) +{ + struct mt76_sw_queue *q; + int ret, i; + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], + MT7615_TXQ_FWDL, + MT7615_TX_FWDL_RING_SIZE); + if (ret) + return ret; + + if (!is_mt7615(&dev->mt76)) + return mt7622_init_tx_queues_multi(dev); + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[0], 0, + MT7615_TX_RING_SIZE); + if (ret) + return ret; + for (i = 1; i < MT_TXQ_MCU; i++) { + q = &dev->mt76.q_tx[i]; + INIT_LIST_HEAD(&q->swq); + q->q = dev->mt76.q_tx[0].q; + } + + ret = mt7615_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT7615_TXQ_MCU, + MT7615_TX_MCU_RING_SIZE); return 0; } @@ -63,8 +101,12 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, __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: @@ -78,6 +120,7 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 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); @@ -90,25 +133,32 @@ void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, } } +static void +mt7615_tx_cleanup(struct mt7615_dev *dev) +{ + int i; + + mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); + if (is_mt7615(&dev->mt76)) { + mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); + } else { + for (i = 0; i < IEEE80211_NUM_ACS; i++) + mt76_queue_tx_cleanup(dev, i, false); + } +} + static int mt7615_poll_tx(struct napi_struct *napi, int budget) { - static const u8 queue_map[] = { - MT_TXQ_MCU, - MT_TXQ_BE - }; struct mt7615_dev *dev; - int i; dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); if (napi_complete_done(napi, 0)) mt7615_irq_enable(dev, MT_INT_TX_DONE_ALL); - for (i = 0; i < ARRAY_SIZE(queue_map); i++) - mt76_queue_tx_cleanup(dev, queue_map[i], false); + mt7615_tx_cleanup(dev); mt7615_mac_sta_poll(dev); @@ -117,8 +167,68 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) return 0; } +static void mt7622_dma_sched_init(struct mt7615_dev *dev) +{ + u32 reg = mt7615_reg_map(dev, MT_DMASHDL_BASE); + int i; + + mt76_rmw(dev, reg + 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)); + + for (i = 0; i <= 5; i++) + mt76_wr(dev, reg + MT_DMASHDL_GROUP_QUOTA(i), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x10) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800)); + + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(0), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(1), 0x42104210); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(2), 0x5); + mt76_wr(dev, reg + MT_DMASHDL_Q_MAP(3), 0); + + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET0, 0x6012345f); + mt76_wr(dev, reg + MT_DMASHDL_SCHED_SET1, 0xedcba987); +} + +static void mt7663_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)); + + /* enable refill control group 0, 1, 2, 4, 5 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_REFILL), 0xffc80000); + /* enable group 0, 1, 2, 4, 5, 15 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_OPTIONAL), 0x70068037); + + /* each group min quota must larger then PLE_PKT_MAX_SIZE_NUM */ + for (i = 0; i < 5; i++) + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(i)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x40) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x800)); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(5)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x40) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x40)); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_GROUP_QUOTA(15)), + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MIN, 0x20) | + FIELD_PREP(MT_DMASHDL_GROUP_QUOTA_MAX, 0x20)); + + 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)), 0x00050005); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_Q_MAP(3)), 0); + /* ALTX0 and ALTX1 QID mapping to group 5 */ + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET0), 0x6012345f); + mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987); +} + int mt7615_dma_init(struct mt7615_dev *dev) { + int rx_ring_size = MT7615_RX_RING_SIZE; int ret; mt76_dma_attach(&dev->mt76); @@ -126,7 +236,6 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_wr(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE | MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN | - MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY | MT_WPDMA_GLO_CFG_OMIT_TX_INFO); mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, @@ -141,28 +250,22 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_rmw_field(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_MULTI_DMA_EN, 0x3); - mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); - mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); - mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); - mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); - mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); - mt76_set(dev, 0x7158, BIT(16)); - mt76_clear(dev, 0x7000, BIT(23)); - mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); - - ret = mt7615_init_tx_queues(dev, MT7615_TX_RING_SIZE); - if (ret) - return ret; + if (is_mt7615(&dev->mt76)) { + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY); + + mt76_wr(dev, MT_WPDMA_GLO_CFG1, 0x1); + mt76_wr(dev, MT_WPDMA_TX_PRE_CFG, 0xf0000); + mt76_wr(dev, MT_WPDMA_RX_PRE_CFG, 0xf7f0000); + mt76_wr(dev, MT_WPDMA_ABT_CFG, 0x4000026); + mt76_wr(dev, MT_WPDMA_ABT_CFG1, 0x18811881); + mt76_set(dev, 0x7158, BIT(16)); + mt76_clear(dev, 0x7000, BIT(23)); + } - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], - MT7615_TXQ_MCU, - MT7615_TX_MCU_RING_SIZE); - if (ret) - return ret; + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); - ret = mt7615_init_mcu_queue(dev, &dev->mt76.q_tx[MT_TXQ_FWDL], - MT7615_TXQ_FWDL, - MT7615_TX_FWDL_RING_SIZE); + ret = mt7615_init_tx_queues(dev); if (ret) return ret; @@ -173,9 +276,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) if (ret) return ret; + if (!is_mt7615(&dev->mt76)) + rx_ring_size /= 2; + ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, - MT7615_RX_RING_SIZE, MT_RX_BUF_SIZE, - MT_RX_RING_BASE); + rx_ring_size, MT_RX_BUF_SIZE, MT_RX_RING_BASE); if (ret) return ret; @@ -199,7 +304,14 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_RX_DMA_EN); /* enable interrupts for TX/RX rings */ - mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); + mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | + MT_INT_MCU_CMD); + + if (is_mt7622(&dev->mt76)) + mt7622_dma_sched_init(dev); + + if (is_mt7663(&dev->mt76)) + mt7663_dma_sched_init(dev); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 17e277bf39e0..dfa9a08b896d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -84,17 +84,30 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: + case 0x7622: return 0; default: return -EINVAL; } } -static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +static void +mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) { - u8 *eeprom = dev->mt76.eeprom.data; - u8 tx_mask, rx_mask, max_nss; - u32 val; + u8 val, *eeprom = dev->mt76.eeprom.data; + + if (is_mt7663(&dev->mt76)) { + /* dual band */ + dev->mt76.cap.has_2ghz = true; + dev->mt76.cap.has_5ghz = true; + return; + } + + if (is_mt7622(&dev->mt76)) { + /* 2GHz only */ + dev->mt76.cap.has_2ghz = true; + return; + } val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, eeprom[MT_EE_WIFI_CONF]); @@ -110,23 +123,34 @@ static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) dev->mt76.cap.has_5ghz = true; break; } +} + +static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) +{ + u8 *eeprom = dev->mt76.eeprom.data; + u8 tx_mask; - /* read tx-rx mask from eeprom */ - val = mt76_rr(dev, MT_TOP_STRAP_STA); - max_nss = val & MT_TOP_3NSS ? 3 : 4; + mt7615_eeprom_parse_hw_band_cap(dev); - rx_mask = FIELD_GET(MT_EE_NIC_CONF_RX_MASK, - eeprom[MT_EE_NIC_CONF_0]); - if (!rx_mask || rx_mask > max_nss) - rx_mask = max_nss; + if (is_mt7663(&dev->mt76)) { + tx_mask = 2; + } else { + u8 max_nss; + u32 val; - 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; + /* read tx-rx mask from eeprom */ + val = mt76_rr(dev, MT_TOP_STRAP_STA); + max_nss = val & MT_TOP_3NSS ? 3 : 4; - dev->mt76.chainmask = tx_mask << 8 | rx_mask; - dev->mt76.antenna_mask = BIT(tx_mask) - 1; + 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; + } + + 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, @@ -209,6 +233,38 @@ static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; } +static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) +{ + static const u16 ical[] = { + 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b + }; + u8 *eeprom = dev->mt76.eeprom.data; + u8 *otp = dev->mt76.otp.data; + int i; + + if (!otp) + return; + + for (i = 0; i < ARRAY_SIZE(ical); i++) { + if (!otp[ical[i]]) + continue; + + eeprom[ical[i]] = otp[ical[i]]; + } +} + +static void mt7615_cal_free_data(struct mt7615_dev *dev) +{ + switch (mt76_chip(&dev->mt76)) { + case 0x7622: + mt7622_apply_cal_free_data(dev); + break; + case 0x7615: + mt7615_apply_cal_free_data(dev); + break; + } +} + int mt7615_eeprom_init(struct mt7615_dev *dev) { int ret; @@ -222,7 +278,7 @@ int mt7615_eeprom_init(struct mt7615_dev *dev) memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, MT7615_EEPROM_SIZE); else - mt7615_apply_cal_free_data(dev); + mt7615_cal_free_data(dev); mt7615_eeprom_parse_hw_cap(dev); memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index c3bc69ac210e..8a2a64b7fcd3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -18,10 +18,13 @@ enum mt7615_eeprom_field { MT_EE_TX1_5G_G0_TARGET_POWER = 0x098, 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, - __MT_EE_MAX = 0x3bf + MT7615_EE_MAX = 0x3bf, + MT7622_EE_MAX = 0x3db, + MT7663_EE_MAX = 0x400, }; #define MT_EE_NIC_CONF_TX_MASK GENMASK(7, 4) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 553bd4d988f7..03b1e56534d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -4,6 +4,7 @@ * 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> @@ -13,55 +14,35 @@ static void mt7615_phy_init(struct mt7615_dev *dev) { - /* disable band 0 rf low power beacon mode */ - mt76_rmw(dev, MT_WF_PHY_WF2_RFCTRL0, MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN, - MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN); + /* 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); } -static void mt7615_mac_init(struct mt7615_dev *dev) +static void +mt7615_init_mac_chain(struct mt7615_dev *dev, int chain) { u32 val, mask, set; - int i; - /* enable band 0/1 clk */ - mt76_set(dev, MT_CFG_CCR, - MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN | - MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN); - - val = mt76_rmw(dev, MT_TMAC_TRCR0, - MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, - FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | - FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); - mt76_wr(dev, MT_TMAC_TRCR1, val); - - val = MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | - FIELD_PREP(MT_AGG_ACR_CFEND_RATE, 0x49) | /* 24M */ - FIELD_PREP(MT_AGG_ACR_BAR_RATE, 0x4b); /* 6M */ - mt76_wr(dev, MT_AGG_ACR0, val); - mt76_wr(dev, MT_AGG_ACR1, val); - - mt76_rmw_field(dev, MT_TMAC_CTCR0, - MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); - mt76_rmw_field(dev, MT_TMAC_CTCR0, - MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3); - mt76_rmw(dev, MT_TMAC_CTCR0, - MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | - MT_TMAC_CTCR0_INS_DDLMT_EN, - MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | - MT_TMAC_CTCR0_INS_DDLMT_EN); - - mt7615_mcu_set_rts_thresh(dev, 0x92b); - mt7615_mac_set_scs(dev, true); + if (!chain) + val = MT_CFG_CCR_MAC_D0_1X_GC_EN | MT_CFG_CCR_MAC_D0_2X_GC_EN; + else + val = MT_CFG_CCR_MAC_D1_1X_GC_EN | MT_CFG_CCR_MAC_D1_2X_GC_EN; - mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, - MT_AGG_SCR_NLNAV_MID_PTEC_DIS); + /* enable band 0/1 clk */ + mt76_set(dev, MT_CFG_CCR, val); - mt7615_mcu_init_mac(dev); + mt76_rmw(dev, MT_TMAC_TRCR(chain), + MT_TMAC_TRCR_CCA_SEL | MT_TMAC_TRCR_SEC_CCA_SEL, + FIELD_PREP(MT_TMAC_TRCR_CCA_SEL, 2) | + FIELD_PREP(MT_TMAC_TRCR_SEC_CCA_SEL, 0)); - mt76_wr(dev, MT_DMA_DCR0, MT_DMA_DCR0_RX_VEC_DROP | - FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072)); + mt76_wr(dev, MT_AGG_ACR(chain), + MT_AGG_ACR_PKT_TIME_EN | MT_AGG_ACR_NO_BA_AR_RULE | + FIELD_PREP(MT_AGG_ACR_CFEND_RATE, MT7615_CFEND_RATE_DEFAULT) | + FIELD_PREP(MT_AGG_ACR_BAR_RATE, MT7615_BAR_RATE_DEFAULT)); - mt76_wr(dev, MT_AGG_ARUCR, + mt76_wr(dev, MT_AGG_ARUCR(chain), FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), 2) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), 2) | @@ -71,7 +52,7 @@ static void mt7615_mac_init(struct mt7615_dev *dev) FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), 1)); - mt76_wr(dev, MT_AGG_ARDCR, + mt76_wr(dev, MT_AGG_ARDCR(chain), FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), MT7615_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), MT7615_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7615_RATE_RETRY - 1) | @@ -81,12 +62,6 @@ static void mt7615_mac_init(struct mt7615_dev *dev) FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7615_RATE_RETRY - 1) | FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7615_RATE_RETRY - 1)); - mt76_wr(dev, MT_AGG_ARCR, - (FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | - MT_AGG_ARCR_RATE_DOWN_RATIO_EN | - FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | - FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); - mask = MT_DMA_RCFR0_MCU_RX_MGMT | MT_DMA_RCFR0_MCU_RX_CTL_NON_BAR | MT_DMA_RCFR0_MCU_RX_CTL_BAR | @@ -95,8 +70,36 @@ static void mt7615_mac_init(struct mt7615_dev *dev) MT_DMA_RCFR0_RX_DROPPED_MCAST; set = FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_UCAST, 2) | FIELD_PREP(MT_DMA_RCFR0_RX_DROPPED_MCAST, 2); - mt76_rmw(dev, MT_DMA_BN0RCFR0, mask, set); - mt76_rmw(dev, MT_DMA_BN1RCFR0, mask, set); + mt76_rmw(dev, MT_DMA_RCFR0(chain), mask, set); +} + +static void mt7615_mac_init(struct mt7615_dev *dev) +{ + int i; + + mt7615_init_mac_chain(dev, 0); + + mt76_rmw_field(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f); + mt76_rmw_field(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_DENSITY, 0x3); + mt76_rmw(dev, MT_TMAC_CTCR0, + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN, + MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN | + MT_TMAC_CTCR0_INS_DDLMT_EN); + + mt7615_mcu_set_rts_thresh(&dev->phy, 0x92b); + mt7615_mac_set_scs(dev, true); + + mt76_rmw(dev, MT_AGG_SCR, MT_AGG_SCR_NLNAV_MID_PTEC_DIS, + MT_AGG_SCR_NLNAV_MID_PTEC_DIS); + + mt76_wr(dev, MT_AGG_ARCR, + FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | + MT_AGG_ARCR_RATE_DOWN_RATIO_EN | + FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | + FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4)); for (i = 0; i < MT7615_WTBL_SIZE; i++) mt7615_mac_wtbl_update(dev, i, @@ -104,6 +107,39 @@ static void mt7615_mac_init(struct mt7615_dev *dev) mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_EN); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_EN); + + /* disable hdr translation and hw AMSDU */ + mt76_wr(dev, MT_DMA_DCR0, + FIELD_PREP(MT_DMA_DCR0_MAX_RX_LEN, 3072) | + MT_DMA_DCR0_RX_VEC_DROP); + if (is_mt7663(&dev->mt76)) { + mt76_wr(dev, MT_CSR(0x010), 0x8208); + mt76_wr(dev, 0x44064, 0x2000000); + mt76_wr(dev, MT_WF_AGG(0x160), 0x5c341c02); + mt76_wr(dev, MT_WF_AGG(0x164), 0x70708040); + } else { + mt7615_init_mac_chain(dev, 1); + } +} + +bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev) +{ + flush_work(&dev->mcu_work); + + return test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); +} + +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); } static int mt7615_init_hardware(struct mt7615_dev *dev) @@ -112,6 +148,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); spin_lock_init(&dev->token_lock); idr_init(&dev->token); @@ -123,17 +160,7 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) if (ret) return ret; - set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); - - ret = mt7615_mcu_init(dev); - if (ret) - return ret; - - mt7615_mcu_set_eeprom(dev); - mt7615_mac_init(dev); - mt7615_phy_init(dev); - mt7615_mcu_ctrl_pm_state(dev, 0); - mt7615_mcu_del_wtbl_all(dev); + 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); @@ -200,12 +227,65 @@ static const struct ieee80211_iface_combination if_comb[] = { }; 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); +} + +static void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband) { - int i, n_chains = hweight8(dev->mt76.antenna_mask), target_chains; + int i, n_chains = hweight8(dev->mphy.antenna_mask), target_chains; u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; + int delta = mt76_tx_power_nss_delta(n_chains); target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; for (i = 0; i < sband->n_channels; i++) { @@ -220,21 +300,7 @@ mt7615_init_txpower(struct mt7615_dev *dev, target_power = max(target_power, eep[index]); } - target_power = DIV_ROUND_UP(target_power, 2); - switch (n_chains) { - case 4: - target_power += 6; - break; - case 3: - target_power += 4; - break; - case 2: - target_power += 3; - break; - default: - break; - } - + target_power = DIV_ROUND_UP(target_power + delta, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; @@ -246,74 +312,190 @@ mt7615_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct mt7615_dev *dev = hw->priv; - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - - if (request->dfs_region == dev->mt76.region) - return; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; + struct mt7615_phy *phy = mphy->priv; + struct cfg80211_chan_def *chandef = &mphy->chandef; dev->mt76.region = request->dfs_region; if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) return; - mt7615_dfs_stop_radar_detector(dev); - if (request->dfs_region == NL80211_DFS_UNSET) - mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); - else - mt7615_dfs_start_radar_detector(dev); + mt7615_dfs_init_radar_detector(phy); } -int mt7615_register_device(struct mt7615_dev *dev) +static void +mt7615_init_wiphy(struct ieee80211_hw *hw) { - struct ieee80211_hw *hw = mt76_hw(dev); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct wiphy *wiphy = hw->wiphy; - int ret; - - INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); - INIT_LIST_HEAD(&dev->sta_poll_list); - spin_lock_init(&dev->sta_poll_lock); - - ret = mt7615_init_hardware(dev); - if (ret) - return ret; hw->queues = 4; hw->max_rates = 3; hw->max_report_rates = 7; hw->max_rate_tries = 11; + phy->slottime = 9; + hw->sta_data_size = sizeof(struct mt7615_sta); hw->vif_data_size = sizeof(struct mt7615_vif); wiphy->iface_combinations = if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); wiphy->reg_notifier = mt7615_regd_notifier; - wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); - dev->mt76.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - dev->mt76.sband_5g.sband.vht_cap.cap |= + if (is_mt7615(&phy->dev->mt76)) + hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + else + hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM; +} + +static void +mt7615_cap_dbdc_enable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap &= + ~(IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + if (dev->chainmask == 0xf) + 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; + mt76_set_stream_caps(&dev->mt76, true); +} + +static void +mt7615_cap_dbdc_disable(struct mt7615_dev *dev) +{ + dev->mphy.sband_5g.sband.vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; - dev->dfs_state = -1; + dev->mphy.antenna_mask = dev->chainmask; + dev->phy.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->mt76, true); +} + +int mt7615_register_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy; + int ret; + + if (!is_mt7615(&dev->mt76)) + return -EOPNOTSUPP; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return -EINVAL; + + if (phy) + return 0; + + mt7615_cap_dbdc_enable(dev); + mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); + if (!mphy) + return -ENOMEM; + + phy = mphy->priv; + phy->dev = dev; + phy->mt76 = mphy; + phy->chainmask = dev->chainmask & ~dev->phy.chainmask; + mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; + mt7615_init_wiphy(mphy->hw); + + /* + * Make the secondary PHY MAC address local without overlapping with + * the usual MAC address allocation scheme on multiple virtual interfaces + */ + mphy->hw->wiphy->perm_addr[0] |= 2; + mphy->hw->wiphy->perm_addr[0] ^= BIT(7); + + /* second phy can only handle 5 GHz */ + mphy->sband_2g.sband.n_channels = 0; + mphy->hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL; + + /* The second interface does not get any packets unless it has a vif */ + ieee80211_hw_set(mphy->hw, WANT_MONITOR_VIF); + + ret = mt76_register_phy(mphy); + if (ret) + ieee80211_free_hw(mphy->hw); + + return ret; +} + +void mt7615_unregister_ext_phy(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = dev->mt76.phy2; + + if (!phy) + return; + + mt7615_cap_dbdc_disable(dev); + mt76_unregister_phy(mphy); + ieee80211_free_hw(mphy->hw); +} + +void mt7615_init_device(struct mt7615_dev *dev) +{ + struct ieee80211_hw *hw = mt76_hw(dev); + + dev->phy.dev = dev; + dev->phy.mt76 = &dev->mt76.phy; + dev->mt76.phy.priv = &dev->phy; + INIT_DELAYED_WORK(&dev->mt76.mac_work, mt7615_mac_work); + 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, mt7615_mac_reset_work); + + mt7615_init_wiphy(hw); + 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_11454 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; + mt7615_cap_dbdc_disable(dev); + dev->phy.dfs_state = -1; +} + +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; - mt7615_init_txpower(dev, &dev->mt76.sband_2g.sband); - mt7615_init_txpower(dev, &dev->mt76.sband_5g.sband); - - hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM; + 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); } @@ -321,10 +503,15 @@ 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); + + mt7615_unregister_ext_phy(dev); mt76_unregister_device(&dev->mt76); - mt7615_mcu_exit(dev); + if (mcu_running) + mt7615_mcu_exit(dev); mt7615_dma_cleanup(dev); spin_lock_bh(&dev->token_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index c77adc5d2552..a27a6d164009 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -10,13 +10,50 @@ #include <linux/etherdevice.h> #include <linux/timekeeping.h> #include "mt7615.h" +#include "../trace.h" #include "../dma.h" +#include "mt7615_trace.h" #include "mac.h" -static inline s8 to_rssi(u32 field, u32 rxv) -{ - return (FIELD_GET(field, rxv) - 220) / 2; -} +#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2) + +static const struct mt7615_dfs_radar_spec etsi_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [5] = { 1, 0, 6, 32, 28, 0, 17, 990, 5010, 1, 1 }, + [6] = { 1, 0, 9, 32, 28, 0, 27, 615, 5010, 1, 1 }, + [7] = { 1, 0, 15, 32, 28, 0, 27, 240, 445, 1, 1 }, + [8] = { 1, 0, 12, 32, 28, 0, 42, 240, 510, 1, 1 }, + [9] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 12, 32, 28 }, + [10] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 15, 32, 24 }, + [11] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 18, 32, 28 }, + [12] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 27, 32, 24 }, + }, +}; + +static const struct mt7615_dfs_radar_spec fcc_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 9, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 255, 28, 0, 13, 323, 343, 1, 32 }, + }, +}; + +static const struct mt7615_dfs_radar_spec jp_radar_specs = { + .pulse_th = { 40, -10, -80, 800, 3360, 128, 5200 }, + .radar_pattern = { + [0] = { 1, 0, 8, 32, 28, 0, 13, 508, 3076, 1, 1 }, + [1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 }, + [2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 }, + [3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 }, + [4] = { 1, 0, 9, 32, 28, 0, 13, 323, 343, 1, 32 }, + [13] = { 1, 0, 8, 32, 28, 0, 14, 3836, 3856, 1, 1 }, + [14] = { 1, 0, 8, 32, 28, 0, 14, 3990, 4010, 1, 1 }, + }, +}; static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, u8 idx, bool unicast) @@ -49,34 +86,116 @@ void mt7615_mac_reset_counters(struct mt7615_dev *dev) mt76_rr(dev, MT_TX_AGG_CNT(i)); memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats)); - - /* TODO: add DBDC support */ + dev->mt76.phy.survey_time = ktime_get_boottime(); + if (dev->mt76.phy2) + dev->mt76.phy2->survey_time = ktime_get_boottime(); /* reset airtime counters */ mt76_rr(dev, MT_MIB_SDR9(0)); + mt76_rr(dev, MT_MIB_SDR9(1)); + mt76_rr(dev, MT_MIB_SDR36(0)); + mt76_rr(dev, MT_MIB_SDR36(1)); + mt76_rr(dev, MT_MIB_SDR37(0)); + mt76_rr(dev, MT_MIB_SDR37(1)); + mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +void mt7615_mac_set_timing(struct mt7615_phy *phy) +{ + s16 coverage_class = phy->coverage_class; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 val, reg_offset; + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); + int sifs, offset; + + if (phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ) + sifs = 16; + else + sifs = 10; + + if (ext_phy) { + coverage_class = max_t(s16, dev->phy.coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + } else { + struct mt7615_phy *phy_ext = mt7615_ext_phy(dev); + + if (phy_ext) + coverage_class = max_t(s16, phy_ext->coverage_class, + coverage_class); + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + } + udelay(1); + + offset = 3 * coverage_class; + reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + mt76_wr(dev, MT_TMAC_CDTR, cck + reg_offset); + mt76_wr(dev, MT_TMAC_ODTR, ofdm + reg_offset); + + mt76_wr(dev, MT_TMAC_ICR(ext_phy), + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, phy->slottime)); + + if (phy->slottime < 20) + val = MT7615_CFEND_RATE_DEFAULT; + else + val = MT7615_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_ACR(ext_phy), MT_AGG_ACR_CFEND_RATE, val); + if (ext_phy) + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE); + else + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE); + +} + int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_phy *phy = &dev->phy; + struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; __le32 *rxd = (__le32 *)skb->data; u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); + __le32 rxd12 = rxd[12]; bool unicast, remove_pad, insert_ccmp_hdr = false; + int phy_idx; int i, idx; - - if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) - return -EINVAL; + u8 chfreq; memset(status, 0, sizeof(*status)); + chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); + if (!phy2) + phy_idx = 0; + else if (phy2->chfreq == phy->chfreq) + phy_idx = -1; + else if (phy->chfreq == chfreq) + phy_idx = 0; + else if (phy2->chfreq == chfreq) + phy_idx = 1; + else + phy_idx = -1; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); @@ -91,14 +210,6 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } - /* TODO: properly support DBDC */ - status->freq = dev->mt76.chandef.chan->center_freq; - status->band = dev->mt76.chandef.chan->band; - if (status->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; - else - sband = &dev->mt76.sband_2g.sband; - if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -112,28 +223,11 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | - MT_RXD2_NORMAL_NON_AMPDU))) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (dev->rx_ampdu_ts != rxd[12]) { - if (!++dev->mt76.ampdu_ref) - dev->mt76.ampdu_ref++; - } - dev->rx_ampdu_ts = rxd[12]; - - status->ampdu_ref = dev->mt76.ampdu_ref; - } - remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) return -EINVAL; - if (!sband->channels) - return -EINVAL; - rxd += 4; if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { rxd += 4; @@ -166,6 +260,59 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) } if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + u32 rxdg5 = le32_to_cpu(rxd[5]); + + /* + * If both PHYs are on the same channel and we don't have a WCID, + * we need to figure out which PHY this packet was received on. + * On the primary PHY, the noise value for the chains belonging to the + * second PHY will be set to the noise value of the last packet from + * that PHY. + */ + if (phy_idx < 0) { + int first_chain = ffs(phy2->chainmask) - 1; + + phy_idx = ((rxdg5 >> (first_chain * 8)) & 0xff) == 0; + } + } + + if (phy_idx == 1 && phy2) { + mphy = dev->mt76.phy2; + phy = phy2; + status->ext_phy = true; + } + + if (chfreq != phy->chfreq) + return -EINVAL; + + status->freq = mphy->chandef.chan->center_freq; + status->band = mphy->chandef.chan->band; + if (status->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) + return -EINVAL; + + if (!sband->channels) + return -EINVAL; + + if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB | + MT_RXD2_NORMAL_NON_AMPDU))) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != rxd12) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = rxd12; + + status->ampdu_ref = phy->ampdu_ref; + } + + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { u32 rxdg0 = le32_to_cpu(rxd[0]); u32 rxdg1 = le32_to_cpu(rxd[1]); u32 rxdg3 = le32_to_cpu(rxd[3]); @@ -218,14 +365,14 @@ int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; - status->chains = dev->mt76.antenna_mask; + status->chains = mphy->antenna_mask; status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3); status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3); status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3); status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3); status->signal = status->chain_signal[0]; - for (i = 1; i < hweight8(dev->mt76.antenna_mask); i++) { + for (i = 1; i < hweight8(mphy->antenna_mask); i++) { if (!(status->chains & BIT(i))) continue; @@ -274,13 +421,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, if (e->skb == DMA_DUMMY_DATA) { struct mt76_txwi_cache *t; struct mt7615_dev *dev; - struct mt7615_txp *txp; + 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, le16_to_cpu(txp->token)); + t = idr_remove(&dev->token, token); spin_unlock_bh(&dev->token_lock); e->skb = t ? t->skb : NULL; } @@ -291,6 +445,7 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, static u16 mt7615_mac_tx_rate_val(struct mt7615_dev *dev, + struct mt76_phy *mphy, const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) { @@ -319,11 +474,11 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, *bw = 1; } else { const struct ieee80211_rate *r; - int band = dev->mt76.chandef.chan->band; + int band = mphy->chandef.chan->band; u16 val; nss = 1; - r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; + r = &mphy->hw->wiphy->bands[band]->bitrates[rate->idx]; if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) val = r->hw_value_short; else @@ -348,13 +503,15 @@ mt7615_mac_tx_rate_val(struct mt7615_dev *dev, int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key) + struct ieee80211_key_conf *key, bool beacon) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *rate = &info->control.rates[0]; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool multicast = is_multicast_ether_addr(hdr->addr1); struct ieee80211_vif *vif = info->control.vif; + struct mt76_phy *mphy = &dev->mphy; + bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY; int tx_count = 8; u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; __le16 fc = hdr->frame_control; @@ -374,6 +531,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, tx_count = msta->rate_count; } + if (ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; @@ -381,11 +541,17 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, q_idx = wmm_idx * MT7615_MAX_WMM_SETS + skb_get_queue_mapping(skb); p_fmt = MT_TX_TYPE_CT; - } else if (ieee80211_is_beacon(fc)) { - q_idx = MT_LMAC_BCN0; + } else if (beacon) { + if (ext_phy) + q_idx = MT_LMAC_BCN1; + else + q_idx = MT_LMAC_BCN0; p_fmt = MT_TX_TYPE_FW; } else { - q_idx = MT_LMAC_ALTX0; + if (ext_phy) + q_idx = MT_LMAC_ALTX1; + else + q_idx = MT_LMAC_ALTX0; p_fmt = MT_TX_TYPE_CT; } @@ -431,7 +597,8 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { bool stbc = info->flags & IEEE80211_TX_CTL_STBC; u8 bw; - u16 rateval = mt7615_mac_tx_rate_val(dev, rate, stbc, &bw); + u16 rateval = mt7615_mac_tx_rate_val(dev, mphy, rate, stbc, + &bw); txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); @@ -486,21 +653,59 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, return 0; } -void mt7615_txp_skb_unmap(struct mt76_dev *dev, - struct mt76_txwi_cache *t) +static void +mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) { - struct mt7615_txp *txp; int i; - txp = mt7615_txwi_to_txp(dev, t); for (i = 1; i < txp->nbuf; i++) dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); } -static u32 mt7615_mac_wtbl_addr(int wcid) +static void +mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp) { - return MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE; + int i; + + for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) { + struct mt7615_txp_ptr *ptr = &txp->ptr[i]; + bool last; + u16 len; + + len = le16_to_cpu(ptr->len0); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len, + DMA_TO_DEVICE); + if (last) + break; + + len = le16_to_cpu(ptr->len1); + last = len & MT_TXD_LEN_MSDU_LAST; + len &= ~MT_TXD_LEN_MSDU_LAST; + dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len, + DMA_TO_DEVICE); + if (last) + break; + } +} + +void mt7615_txp_skb_unmap(struct mt76_dev *dev, + struct mt76_txwi_cache *t) +{ + struct mt7615_txp_common *txp; + + txp = mt7615_txwi_to_txp(dev, t); + if (is_mt7615(dev)) + mt7615_txp_skb_unmap_fw(dev, &txp->fw); + else + mt7615_txp_skb_unmap_hw(dev, &txp->hw); +} + +static u32 mt7615_mac_wtbl_addr(struct mt7615_dev *dev, int wcid) +{ + return MT_WTBL_BASE(dev) + wcid * MT_WTBL_ENTRY_SIZE; } bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask) @@ -546,7 +751,7 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) list_del_init(&msta->poll_list); spin_unlock_bh(&dev->sta_poll_lock); - addr = mt7615_mac_wtbl_addr(msta->wcid.idx) + 19 * 4; + addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; for (i = 0; i < 4; i++, addr += 8) { u32 tx_last = msta->airtime_ac[i]; @@ -588,13 +793,15 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) rcu_read_unlock(); } -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates) { + struct mt7615_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; struct ieee80211_tx_rate *ref; int wcid = sta->wcid.idx; - u32 addr = mt7615_mac_wtbl_addr(wcid); + u32 addr = mt7615_mac_wtbl_addr(dev, wcid); bool stbc = false; int n_rates = sta->n_rates; u8 bw, bw_prev, bw_idx = 0; @@ -649,11 +856,12 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, } } - val[0] = mt7615_mac_tx_rate_val(dev, &rates[0], stbc, &bw); + val[0] = mt7615_mac_tx_rate_val(dev, mphy, &rates[0], stbc, &bw); bw_prev = bw; if (probe_rate) { - probe_val = mt7615_mac_tx_rate_val(dev, probe_rate, stbc, &bw); + probe_val = mt7615_mac_tx_rate_val(dev, mphy, probe_rate, + stbc, &bw); if (bw) bw_idx = 1; else @@ -662,19 +870,19 @@ void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, probe_val = val[0]; } - val[1] = mt7615_mac_tx_rate_val(dev, &rates[1], stbc, &bw); + val[1] = mt7615_mac_tx_rate_val(dev, mphy, &rates[1], stbc, &bw); if (bw_prev) { bw_idx = 3; bw_prev = bw; } - val[2] = mt7615_mac_tx_rate_val(dev, &rates[2], stbc, &bw); + val[2] = mt7615_mac_tx_rate_val(dev, mphy, &rates[2], stbc, &bw); if (bw_prev) { bw_idx = 5; bw_prev = bw; } - val[3] = mt7615_mac_tx_rate_val(dev, &rates[3], stbc, &bw); + val[3] = mt7615_mac_tx_rate_val(dev, mphy, &rates[3], stbc, &bw); if (bw_prev) bw_idx = 7; @@ -758,7 +966,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx) + 30 * 4; + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; u8 data[32] = {}; if (key->keylen > sizeof(data)) @@ -796,7 +1004,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, int keyidx, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx), w0, w1; + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) return -ETIMEDOUT; @@ -832,7 +1040,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, enum mt7615_cipher_type cipher, enum set_key_cmd cmd) { - u32 addr = mt7615_mac_wtbl_addr(wcid->idx); + u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); if (cmd == SET_KEY) { if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) @@ -884,39 +1092,51 @@ out: return err; } -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) +static void +mt7615_write_hw_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 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; - struct ieee80211_vif *vif = info->control.vif; - int i, pid, id, nbuf = tx_info->nbuf - 1; - u8 *txwi = (u8 *)txwi_ptr; - struct mt76_txwi_cache *t; - struct mt7615_txp *txp; + struct mt7615_hw_txp *txp = txp_ptr; + struct mt7615_txp_ptr *ptr = &txp->ptr[0]; + int nbuf = tx_info->nbuf - 1; + int i; - if (!wcid) - wcid = &dev->mt76.global_wcid; + tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp); + tx_info->nbuf = 1; - pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); + txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID); - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { - spin_lock_bh(&dev->mt76.lock); - mt7615_mac_set_rates(dev, msta, &info->control.rates[0], - msta->rates); - msta->rate_probe = true; - spin_unlock_bh(&dev->mt76.lock); + for (i = 0; i < nbuf; i++) { + u32 addr = tx_info->buf[i + 1].addr; + u16 len = tx_info->buf[i + 1].len; + + if (i == nbuf - 1) + len |= MT_TXD_LEN_MSDU_LAST | + MT_TXD_LEN_AMSDU_LAST; + + 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); + } } +} - mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, - pid, key); +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; - txp = (struct mt7615_txp *)(txwi + MT_TXD_SIZE); for (i = 0; i < nbuf; i++) { txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr); txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len); @@ -924,6 +1144,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 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; @@ -941,6 +1162,42 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 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; @@ -950,8 +1207,16 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (id < 0) return id; - txp->token = cpu_to_le16(id); - txp->rept_wds_wcid = 0xff; + 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; @@ -962,6 +1227,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, { struct ieee80211_supported_band *sband; struct mt7615_rate_set *rs; + struct mt76_phy *mphy; int first_idx = 0, last_idx; int i, idx, count; bool fixed_rate, ack_timeout; @@ -1019,7 +1285,12 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, spin_lock_bh(&dev->mt76.lock); if (sta->rate_probe) { - mt7615_mac_set_rates(dev, sta, NULL, sta->rates); + struct mt7615_phy *phy = &dev->phy; + + if (sta->wcid.ext_phy && dev->mt76.phy2) + phy = dev->mt76.phy2->priv; + + mt7615_mac_set_rates(phy, sta, NULL, sta->rates); sta->rate_probe = false; } spin_unlock_bh(&dev->mt76.lock); @@ -1059,10 +1330,14 @@ out: cck = true; /* fall through */ case MT_PHY_TYPE_OFDM: - if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) - sband = &dev->mt76.sband_5g.sband; + mphy = &dev->mphy; + if (sta->wcid.ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; else - sband = &dev->mt76.sband_2g.sband; + sband = &mphy->sband_2g.sband; final_rate &= MT_TX_RATE_IDX; final_rate = mt76_get_rate(&dev->mt76, sband, final_rate, cck); @@ -1105,6 +1380,8 @@ static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev, if (pid < MT_PACKET_ID_FIRST) return false; + trace_mac_txdone(mdev, sta->wcid.idx, pid); + mt76_tx_status_lock(mdev, &list); skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); if (skb) { @@ -1128,6 +1405,7 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) struct ieee80211_sta *sta = NULL; struct mt7615_sta *msta = NULL; struct mt76_wcid *wcid; + struct mt76_phy *mphy = &dev->mt76.phy; __le32 *txs_data = data; u32 txs; u8 wcidx; @@ -1164,111 +1442,160 @@ void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (wcidx >= MT7615_WTBL_STA || !sta) goto out; + if (wcid->ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + if (mt7615_fill_txs(dev, msta, &info, txs_data)) - ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + ieee80211_tx_status_noskb(mphy->hw, sta, &info); out: rcu_read_unlock(); } -void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) +static void +mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) { - struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; struct mt76_dev *mdev = &dev->mt76; struct mt76_txwi_cache *txwi; + + trace_mac_tx_free(dev, token); + + spin_lock_bh(&dev->token_lock); + txwi = idr_remove(&dev->token, token); + spin_unlock_bh(&dev->token_lock); + + if (!txwi) + return; + + mt7615_txp_skb_unmap(mdev, txwi); + if (txwi->skb) { + mt76_tx_complete_skb(mdev, txwi->skb); + txwi->skb = NULL; + } + + mt76_put_txwi(mdev, txwi); +} + +void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data; u8 i, count; count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl)); - for (i = 0; i < count; i++) { - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, le16_to_cpu(free->token[i])); - spin_unlock_bh(&dev->token_lock); - - if (!txwi) - continue; + if (is_mt7615(&dev->mt76)) { + __le16 *token = &free->token[0]; - mt7615_txp_skb_unmap(mdev, txwi); - if (txwi->skb) { - mt76_tx_complete_skb(mdev, txwi->skb); - txwi->skb = NULL; - } + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i])); + } else { + __le32 *token = (__le32 *)&free->token[0]; - mt76_put_txwi(mdev, txwi); + for (i = 0; i < count; i++) + mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i])); } + dev_kfree_skb(skb); } static void -mt7615_mac_set_default_sensitivity(struct mt7615_dev *dev) +mt7615_mac_set_default_sensitivity(struct mt7615_phy *phy) { - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(0x13c)); - mt76_rmw(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_OFDM_MASK, - MT_WF_PHY_B1_PD_OFDM(0x13c)); - - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(0x92)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(0x92)); - - dev->ofdm_sensitivity = -98; - dev->cck_sensitivity = -110; - dev->last_cca_adj = jiffies; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, 0x13c)); + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, 0x92)); + + phy->ofdm_sensitivity = -98; + phy->cck_sensitivity = -110; + phy->last_cca_adj = jiffies; } void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable) { + struct mt7615_phy *ext_phy; + mutex_lock(&dev->mt76.mutex); if (dev->scs_en == enable) goto out; + if (is_mt7663(&dev->mt76)) + goto out; + if (enable) { - /* DBDC not supported */ - mt76_set(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_set(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); if (is_mt7622(&dev->mt76)) { mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7 << 8); mt76_set(dev, MT_MIB_M0_MISC_CR, 0x7); } } else { - mt76_clear(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_BLK); - mt76_clear(dev, MT_WF_PHY_B1_MIN_PRI_PWR, - MT_WF_PHY_B1_PD_BLK); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(0), + MT_WF_PHY_PD_BLK(0)); + mt76_clear(dev, MT_WF_PHY_MIN_PRI_PWR(1), + MT_WF_PHY_PD_BLK(1)); } - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(&dev->phy); + ext_phy = mt7615_ext_phy(dev); + if (ext_phy) + mt7615_mac_set_default_sensitivity(ext_phy); + dev->scs_en = enable; out: mutex_unlock(&dev->mt76.mutex); } -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev) +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy) { - mt76_clear(dev, MT_WF_PHY_R0_B0_PHYMUX_5, GENMASK(22, 20)); - mt76_set(dev, MT_WF_PHY_R0_B0_PHYMUX_5, BIT(22) | BIT(20)); + u32 rxtd; + + if (is_mt7663(&dev->mt76)) + return; + + if (ext_phy) + rxtd = MT_WF_PHY_RXTD2(10); + else + rxtd = MT_WF_PHY_RXTD(12); + + mt76_set(dev, rxtd, BIT(18) | BIT(29)); + mt76_set(dev, MT_WF_PHY_R0_PHYMUX_5(ext_phy), 0x5 << 12); +} + +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; + u32 reg = MT_WF_PHY_R0_PHYMUX_5(ext_phy); + + mt76_clear(dev, reg, GENMASK(22, 20)); + mt76_set(dev, reg, BIT(22) | BIT(20)); } static void -mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, +mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy, u32 rts_err_rate, bool ofdm) { - int false_cca = ofdm ? dev->false_cca_ofdm : dev->false_cca_cck; + struct mt7615_dev *dev = phy->dev; + int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck; + bool ext_phy = phy != &dev->phy; u16 def_th = ofdm ? -98 : -110; bool update = false; s8 *sensitivity; int signal; - sensitivity = ofdm ? &dev->ofdm_sensitivity : &dev->cck_sensitivity; - signal = mt76_get_min_avg_rssi(&dev->mt76); + sensitivity = ofdm ? &phy->ofdm_sensitivity : &phy->cck_sensitivity; + signal = mt76_get_min_avg_rssi(&dev->mt76, ext_phy); if (!signal) { - mt7615_mac_set_default_sensitivity(dev); + mt7615_mac_set_default_sensitivity(phy); return; } @@ -1303,99 +1630,155 @@ mt7615_mac_adjust_sensitivity(struct mt7615_dev *dev, u16 val; if (ofdm) { - /* DBDC not supported */ val = *sensitivity * 2 + 512; - mt76_rmw(dev, MT_WF_PHY_B0_MIN_PRI_PWR, - MT_WF_PHY_B0_PD_OFDM_MASK, - MT_WF_PHY_B0_PD_OFDM(val)); + mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy), + MT_WF_PHY_PD_OFDM_MASK(ext_phy), + MT_WF_PHY_PD_OFDM(ext_phy, val)); } else { val = *sensitivity + 256; - mt76_rmw(dev, MT_WF_PHY_B0_RXTD_CCK_PD, - MT_WF_PHY_B0_PD_CCK_MASK, - MT_WF_PHY_B0_PD_CCK(val)); - mt76_rmw(dev, MT_WF_PHY_B1_RXTD_CCK_PD, - MT_WF_PHY_B1_PD_CCK_MASK, - MT_WF_PHY_B1_PD_CCK(val)); + mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy), + MT_WF_PHY_PD_CCK_MASK(ext_phy), + MT_WF_PHY_PD_CCK(ext_phy, val)); } - dev->last_cca_adj = jiffies; + phy->last_cca_adj = jiffies; } } static void -mt7615_mac_scs_check(struct mt7615_dev *dev) +mt7615_mac_scs_check(struct mt7615_phy *phy) { - u32 val, rts_cnt = 0, rts_retries_cnt = 0, rts_err_rate = 0; + struct mt7615_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + u32 val, rts_err_rate = 0; u32 mdrdy_cck, mdrdy_ofdm, pd_cck, pd_ofdm; - int i; + bool ext_phy = phy != &dev->phy; if (!dev->scs_en) return; - for (i = 0; i < 4; i++) { - u32 data; - - val = mt76_rr(dev, MT_MIB_MB_SDR0(i)); - data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (data > rts_retries_cnt) { - rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - rts_retries_cnt = data; - } - } - - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS0); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS0(ext_phy)); pd_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_CCK, val); pd_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_OFDM, val); - val = mt76_rr(dev, MT_WF_PHY_R0_B0_PHYCTRL_STS5); + val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS5(ext_phy)); mdrdy_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_CCK, val); mdrdy_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_OFDM, val); - dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; - dev->false_cca_cck = pd_cck - mdrdy_cck; - mt7615_mac_cca_stats_reset(dev); + phy->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; + phy->false_cca_cck = pd_cck - mdrdy_cck; + mt7615_mac_cca_stats_reset(phy); - if (rts_cnt + rts_retries_cnt) - rts_err_rate = MT_FRAC(rts_retries_cnt, - rts_cnt + rts_retries_cnt); + if (mib->rts_cnt + mib->rts_retries_cnt) + rts_err_rate = MT_FRAC(mib->rts_retries_cnt, + mib->rts_cnt + mib->rts_retries_cnt); /* cck */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, false); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, false); /* ofdm */ - mt7615_mac_adjust_sensitivity(dev, rts_err_rate, true); + mt7615_mac_adjust_sensitivity(phy, rts_err_rate, true); - if (time_after(jiffies, dev->last_cca_adj + 10 * HZ)) - mt7615_mac_set_default_sensitivity(dev); + if (time_after(jiffies, phy->last_cca_adj + 10 * HZ)) + mt7615_mac_set_default_sensitivity(phy); } -void mt7615_update_channel(struct mt76_dev *mdev) +static u8 +mt7615_phy_get_nf(struct mt7615_dev *dev, int idx) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 }; + u32 reg = idx ? MT_WF_PHY_RXTD2(17) : MT_WF_PHY_RXTD(20); + u32 val, sum = 0, n = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { + val = mt76_rr(dev, reg); + sum += val * nf_power[i]; + n += val; + } + + if (!n) + return 0; + + return sum / n; +} + +static void +mt7615_phy_update_channel(struct mt76_phy *mphy, int idx) +{ + struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76); + struct mt7615_phy *phy = mphy->priv; struct mt76_channel_state *state; u64 busy_time, tx_time, rx_time, obss_time; + u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5; + int nf; - /* TODO: add DBDC support */ - busy_time = mt76_get_field(dev, MT_MIB_SDR9(0), + busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx), MT_MIB_SDR9_BUSY_MASK); - tx_time = mt76_get_field(dev, MT_MIB_SDR36(0), + tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx), MT_MIB_SDR36_TXTIME_MASK); - rx_time = mt76_get_field(dev, MT_MIB_SDR37(0), + rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx), MT_MIB_SDR37_RXTIME_MASK); - obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_TIME5, - MT_MIB_OBSSTIME_MASK); + obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK); + + nf = mt7615_phy_get_nf(dev, idx); + if (!phy->noise) + phy->noise = nf << 4; + else if (nf) + phy->noise += nf - (phy->noise >> 4); - state = mdev->chan_state; + state = mphy->chan_state; state->cc_busy += busy_time; state->cc_tx += tx_time; state->cc_rx += rx_time + obss_time; state->cc_bss_rx += rx_time; + state->noise = -(phy->noise >> 4); +} + +void mt7615_update_channel(struct mt76_dev *mdev) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_phy_update_channel(&mdev->phy, 0); + if (mdev->phy2) + mt7615_phy_update_channel(mdev->phy2, 1); /* reset obss airtime */ mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR); } +static void +mt7615_mac_update_mib_stats(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + struct mib_stats *mib = &phy->mib; + bool ext_phy = phy != &dev->phy; + int i; + + memset(mib, 0, sizeof(*mib)); + + mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); + + for (i = 0; i < 4; i++) { + u32 data, val, val2; + + val = mt76_get_field(dev, MT_MIB_MB_SDR1(ext_phy, i), + MT_MIB_ACK_FAIL_COUNT_MASK); + if (val > mib->ack_fail_cnt) + mib->ack_fail_cnt = val; + + val2 = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); + data = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val2); + if (data > mib->rts_retries_cnt) { + mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val2); + mib->rts_retries_cnt = data; + } + } +} + void mt7615_mac_work(struct work_struct *work) { struct mt7615_dev *dev; + struct mt7615_phy *ext_phy; int i, idx; dev = (struct mt7615_dev *)container_of(work, struct mt76_dev, @@ -1404,7 +1787,15 @@ void mt7615_mac_work(struct work_struct *work) mutex_lock(&dev->mt76.mutex); mt76_update_survey(&dev->mt76); if (++dev->mac_work_count == 5) { - mt7615_mac_scs_check(dev); + ext_phy = mt7615_ext_phy(dev); + + mt7615_mac_update_mib_stats(&dev->phy); + mt7615_mac_scs_check(&dev->phy); + if (ext_phy) { + mt7615_mac_update_mib_stats(ext_phy); + mt7615_mac_scs_check(ext_phy); + } + dev->mac_work_count = 0; } @@ -1421,21 +1812,140 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev) +static bool +mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - int err; + bool ret; - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD0, - MT_RX_SEL0, 0); - if (err < 0) - return err; + ret = wait_event_timeout(dev->reset_wait, + (READ_ONCE(dev->reset_state) & state), + MT7615_RESET_TIMEOUT); + WARN(!ret, "Timeout waiting for MCU reset state %x\n", state); + return ret; +} - if (chandef->width == NL80211_CHAN_WIDTH_160 || - chandef->width == NL80211_CHAN_WIDTH_80P80) - err = mt7615_mcu_rdd_cmd(dev, RDD_STOP, MT_HW_RDD1, - MT_RX_SEL0, 0); - return err; +static void +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); +} + +static void +mt7615_update_beacons(struct mt7615_dev *dev) +{ + ieee80211_iterate_active_interfaces(dev->mt76.hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.hw); + + if (!dev->mt76.phy2) + return; + + ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_update_vif_beacon, dev->mt76.phy2->hw); +} + +static void +mt7615_dma_reset(struct mt7615_dev *dev) +{ + int i; + + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + usleep_range(1000, 2000); + + for (i = 0; i < __MT_TXQ_MAX; i++) + mt76_queue_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_queue_rx_reset(dev, i); + + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); +} + +void mt7615_mac_reset_work(struct work_struct *work) +{ + struct mt7615_dev *dev; + + dev = container_of(work, struct mt7615_dev, reset_work); + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_stop_queues(dev->mt76.phy2->hw); + + 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->mt76.mac_work); + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (dev->mt76.phy2) + mt76_txq_schedule_all(dev->mt76.phy2); + + tasklet_disable(&dev->mt76.tx_tasklet); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); + + mutex_lock(&dev->mt76.mutex); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED); + + if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7615_dma_reset(dev); + + mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_INIT); + mt7615_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); + } + + clear_bit(MT76_MCU_RESET, &dev->mphy.state); + clear_bit(MT76_RESET, &dev->mphy.state); + + tasklet_enable(&dev->mt76.tx_tasklet); + napi_enable(&dev->mt76.tx_napi); + napi_schedule(&dev->mt76.tx_napi); + + napi_enable(&dev->mt76.napi[0]); + napi_schedule(&dev->mt76.napi[0]); + + napi_enable(&dev->mt76.napi[1]); + napi_schedule(&dev->mt76.napi[1]); + + ieee80211_wake_queues(mt76_hw(dev)); + if (dev->mt76.phy2) + ieee80211_wake_queues(dev->mt76.phy2->hw); + + mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mutex_unlock(&dev->mt76.mutex); + + mt7615_update_beacons(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, + MT7615_WATCHDOG_TIME); +} + +static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) +{ + struct mt7615_dev *dev = phy->dev; + + if (phy->rdd_state & BIT(0)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 0, MT_RX_SEL0, 0); + if (phy->rdd_state & BIT(1)) + mt7615_mcu_rdd_cmd(dev, RDD_STOP, 1, MT_RX_SEL0, 0); } static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) @@ -1450,61 +1960,112 @@ static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain) MT_RX_SEL0, 1); } -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev) +static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; /* start CAC */ - err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, MT_HW_RDD0, - MT_RX_SEL0, 0); + err = mt7615_mcu_rdd_cmd(dev, RDD_CAC_START, ext_phy, MT_RX_SEL0, 0); if (err < 0) return err; - /* TODO: DBDC support */ - - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD0); + err = mt7615_dfs_start_rdd(dev, ext_phy); if (err < 0) return err; + phy->rdd_state |= BIT(ext_phy); + if (chandef->width == NL80211_CHAN_WIDTH_160 || chandef->width == NL80211_CHAN_WIDTH_80P80) { - err = mt7615_dfs_start_rdd(dev, MT_HW_RDD1); + err = mt7615_dfs_start_rdd(dev, 1); if (err < 0) return err; + + phy->rdd_state |= BIT(1); } return 0; } -int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev) +static int +mt7615_dfs_init_radar_specs(struct mt7615_phy *phy) +{ + const struct mt7615_dfs_radar_spec *radar_specs; + struct mt7615_dev *dev = phy->dev; + int err, i; + + switch (dev->mt76.region) { + case NL80211_DFS_FCC: + radar_specs = &fcc_radar_specs; + err = mt7615_mcu_set_fcc5_lpn(dev, 8); + if (err < 0) + return err; + break; + case NL80211_DFS_ETSI: + radar_specs = &etsi_radar_specs; + break; + case NL80211_DFS_JP: + radar_specs = &jp_radar_specs; + break; + default: + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) { + err = mt7615_mcu_set_radar_th(dev, i, + &radar_specs->radar_pattern[i]); + if (err < 0) + return err; + } + + return mt7615_mcu_set_pulse_th(dev, &radar_specs->pulse_th); +} + +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int err; - if (dev->mt76.region == NL80211_DFS_UNSET) + if (dev->mt76.region == NL80211_DFS_UNSET) { + phy->dfs_state = -1; + if (phy->rdd_state) + goto stop; + return 0; + } - if (test_bit(MT76_SCANNING, &dev->mt76.state)) + if (test_bit(MT76_SCANNING, &phy->mt76->state)) return 0; - if (dev->dfs_state == chandef->chan->dfs_state) + if (phy->dfs_state == chandef->chan->dfs_state) return 0; - dev->dfs_state = chandef->chan->dfs_state; + err = mt7615_dfs_init_radar_specs(phy); + if (err < 0) { + phy->dfs_state = -1; + goto stop; + } + + phy->dfs_state = chandef->chan->dfs_state; if (chandef->chan->flags & IEEE80211_CHAN_RADAR) { if (chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) - return mt7615_dfs_start_radar_detector(dev); - else - return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, MT_HW_RDD0, - MT_RX_SEL0, 0); - } else { - err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, - MT_HW_RDD0, MT_RX_SEL0, 0); - if (err < 0) - return err; + return mt7615_dfs_start_radar_detector(phy); - return mt7615_dfs_stop_radar_detector(dev); + return mt7615_mcu_rdd_cmd(dev, RDD_CAC_END, ext_phy, + MT_RX_SEL0, 0); } + +stop: + err = mt7615_mcu_rdd_cmd(dev, RDD_NORMAL_START, ext_phy, MT_RX_SEL0, 0); + if (err < 0) + return err; + + mt7615_dfs_stop_radar_detector(phy); + return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 38695d4f92e2..e0b89257db90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -8,6 +8,7 @@ #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, 29) #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) @@ -26,7 +27,8 @@ enum rx_pkt_type { PKT_TYPE_RX_TMR, PKT_TYPE_RETRIEVE, PKT_TYPE_TXRX_NOTIFY, - PKT_TYPE_RX_EVENT + PKT_TYPE_RX_EVENT, + PKT_TYPE_NORMAL_MCU, }; #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) @@ -103,6 +105,11 @@ enum rx_pkt_type { #define MT_RXV4_RCPI1 GENMASK(15, 8) #define MT_RXV4_RCPI0 GENMASK(7, 0) +#define MT_RXV6_NF3 GENMASK(31, 24) +#define MT_RXV6_NF2 GENMASK(23, 16) +#define MT_RXV6_NF1 GENMASK(15, 8) +#define MT_RXV6_NF0 GENMASK(7, 0) + enum tx_header_format { MT_HDR_FORMAT_802_3, MT_HDR_FORMAT_CMD, @@ -126,6 +133,10 @@ enum tx_pkt_queue_idx { MT_LMAC_BMC0, MT_LMAC_BCN0, MT_LMAC_PSMP0, + MT_LMAC_ALTX1, + MT_LMAC_BMC1, + MT_LMAC_BCN1, + MT_LMAC_PSMP1, }; enum tx_port_idx { @@ -220,8 +231,15 @@ enum tx_phy_bandwidth { #define MT_TXD6_FIXED_BW BIT(2) #define MT_TXD6_BW GENMASK(1, 0) +/* MT7663 DW7 HW-AMSDU */ +#define MT_TXD7_HW_AMSDU_CAP BIT(30) #define MT_TXD7_TYPE GENMASK(21, 20) #define MT_TXD7_SUB_TYPE GENMASK(19, 16) +#define MT_TXD7_SPE_IDX GENMASK(15, 11) +#define MT_TXD7_SPE_IDX_SLE BIT(10) + +#define MT_TXD8_L_TYPE GENMASK(5, 4) +#define MT_TXD8_L_SUB_TYPE GENMASK(3, 0) #define MT_TX_RATE_STBC BIT(11) #define MT_TX_RATE_NSS GENMASK(10, 9) @@ -229,8 +247,27 @@ enum tx_phy_bandwidth { #define MT_TX_RATE_IDX GENMASK(5, 0) #define MT_TXP_MAX_BUF_NUM 6 +#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_MSDU_LAST BIT(14) +#define MT_TXD_LEN_AMSDU_LAST BIT(15) -struct mt7615_txp { +struct mt7615_txp_ptr { + __le32 buf0; + __le16 len0; + __le16 len1; + __le32 buf1; +} __packed __aligned(4); + +struct mt7615_hw_txp { + __le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM]; + struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2]; +} __packed __aligned(4); + +struct mt7615_fw_txp { __le16 flags; __le16 token; u8 bss_idx; @@ -239,7 +276,14 @@ struct mt7615_txp { u8 nbuf; __le32 buf[MT_TXP_MAX_BUF_NUM]; __le16 len[MT_TXP_MAX_BUF_NUM]; -} __packed; +} __packed __aligned(4); + +struct mt7615_txp_common { + union { + struct mt7615_fw_txp fw; + struct mt7615_hw_txp hw; + }; +}; struct mt7615_tx_free { __le16 rx_byte_cnt; @@ -247,7 +291,7 @@ struct mt7615_tx_free { u8 txd_cnt; u8 rsv[3]; __le16 token[]; -} __packed; +} __packed __aligned(4); #define MT_TX_FREE_MSDU_ID_CNT GENMASK(6, 0) @@ -302,6 +346,38 @@ struct mt7615_tx_free { #define MT_TXS6_F1_RCPI_1 GENMASK(15, 8) #define MT_TXS6_F1_RCPI_0 GENMASK(7, 0) +struct mt7615_dfs_pulse { + u32 max_width; /* us */ + int max_pwr; /* dbm */ + int min_pwr; /* dbm */ + u32 min_stgr_pri; /* us */ + u32 max_stgr_pri; /* us */ + u32 min_cr_pri; /* us */ + u32 max_cr_pri; /* us */ +}; + +struct mt7615_dfs_pattern { + u8 enb; + u8 stgr; + u8 min_crpn; + u8 max_crpn; + u8 min_crpr; + u8 min_pw; + u8 max_pw; + u32 min_pri; + u32 max_pri; + u8 min_crbn; + u8 max_crbn; + u8 min_stgpn; + u8 max_stgpn; + u8 min_stgpr; +}; + +struct mt7615_dfs_radar_spec { + struct mt7615_dfs_pulse pulse_th; + struct mt7615_dfs_pattern radar_pattern[16]; +}; + enum mt7615_cipher_type { MT_CIPHER_NONE, MT_CIPHER_WEP40, @@ -317,7 +393,7 @@ enum mt7615_cipher_type { MT_CIPHER_GCMP_256, }; -static inline struct mt7615_txp * +static inline struct mt7615_txp_common * mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) { u8 *txwi; @@ -327,7 +403,7 @@ mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t) txwi = mt76_get_txwi_ptr(dev, t); - return (struct mt7615_txp *)(txwi + MT_TXD_SIZE); + return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE); } #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 070b03403894..6586176c29af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -11,27 +11,85 @@ #include <linux/pci.h> #include <linux/module.h> #include "mt7615.h" +#include "mcu.h" + +static bool mt7615_dev_running(struct mt7615_dev *dev) +{ + struct mt7615_phy *phy; + + if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) + return true; + + phy = mt7615_ext_phy(dev); + + return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state); +} static int mt7615_start(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool running; + + if (!mt7615_wait_for_mcu_init(dev)) + return -EIO; + + mutex_lock(&dev->mt76.mutex); + + running = mt7615_dev_running(dev); + + if (!running) { + mt7615_mcu_set_pm(dev, 0, 0); + mt7615_mcu_set_mac_enable(dev, 0, true); + 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); + mt7615_mac_enable_nf(dev, 1); + } + + mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + + set_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (running) + goto out; mt7615_mac_reset_counters(dev); - dev->mt76.survey_time = ktime_get_boottime(); - set_bit(MT76_STATE_RUNNING, &dev->mt76.state); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); +out: + mutex_unlock(&dev->mt76.mutex); + return 0; } static void mt7615_stop(struct ieee80211_hw *hw) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); - clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); - cancel_delayed_work_sync(&dev->mt76.mac_work); + mutex_lock(&dev->mt76.mutex); + + clear_bit(MT76_STATE_RUNNING, &phy->mt76->state); + + if (phy != &dev->phy) { + mt7615_mcu_set_pm(dev, 1, 1); + mt7615_mcu_set_mac_enable(dev, 1, false); + } + + if (!mt7615_dev_running(dev)) { + cancel_delayed_work_sync(&dev->mt76.mac_work); + + mt7615_mcu_set_pm(dev, 0, 1); + mt7615_mcu_set_mac_enable(dev, 0, false); + } + + mutex_unlock(&dev->mt76.mutex); } static int get_omac_idx(enum nl80211_iftype type, u32 mask) @@ -39,6 +97,7 @@ static int get_omac_idx(enum nl80211_iftype type, u32 mask) int i; switch (type) { + case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_ADHOC: @@ -70,8 +129,10 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt76_txq *mtxq; + bool ext_phy = phy != &dev->phy; int idx, ret = 0; mutex_lock(&dev->mt76.mutex); @@ -89,28 +150,38 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, } mvif->omac_idx = idx; - /* TODO: DBDC support. Use band 0 for now */ - mvif->band_idx = 0; - mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; + mvif->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); + else + mvif->wmm_idx = mvif->idx % MT7615_MAX_WMM_SETS; - ret = mt7615_mcu_set_dev_info(dev, vif, 1); + ret = mt7615_mcu_add_dev_info(dev, vif, true); if (ret) goto out; dev->vif_mask |= BIT(mvif->idx); dev->omac_mask |= BIT(mvif->omac_idx); + phy->omac_mask |= BIT(mvif->omac_idx); + + mt7615_mcu_set_dbdc(dev); + idx = MT7615_WTBL_RESERVED - mvif->idx; INIT_LIST_HEAD(&mvif->sta.poll_list); mvif->sta.wcid.idx = idx; + mvif->sta.wcid.ext_phy = mvif->band_idx; mvif->sta.wcid.hw_key_idx = -1; mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); - mtxq = (struct mt76_txq *)vif->txq->drv_priv; - mtxq->wcid = &mvif->sta.wcid; - mt76_txq_init(&dev->mt76, vif->txq); + if (vif->txq) { + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + } out: mutex_unlock(&dev->mt76.mutex); @@ -123,19 +194,22 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = &mvif->sta; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); int idx = msta->wcid.idx; /* TODO: disable beacon for the bss */ - mt7615_mcu_set_dev_info(dev, vif, 0); + mt7615_mcu_add_dev_info(dev, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); - mt76_txq_remove(&dev->mt76, vif->txq); + if (vif->txq) + mt76_txq_remove(&dev->mt76, vif->txq); mutex_lock(&dev->mt76.mutex); dev->vif_mask &= ~BIT(mvif->idx); dev->omac_mask &= ~BIT(mvif->omac_idx); + phy->omac_mask &= ~BIT(mvif->omac_idx); mutex_unlock(&dev->mt76.mutex); spin_lock_bh(&dev->sta_poll_lock); @@ -144,34 +218,38 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, spin_unlock_bh(&dev->sta_poll_lock); } -static int mt7615_set_channel(struct mt7615_dev *dev) +static int mt7615_set_channel(struct mt7615_phy *phy) { + struct mt7615_dev *dev = phy->dev; + bool ext_phy = phy != &dev->phy; int ret; cancel_delayed_work_sync(&dev->mt76.mac_work); mutex_lock(&dev->mt76.mutex); - set_bit(MT76_RESET, &dev->mt76.state); + set_bit(MT76_RESET, &phy->mt76->state); - mt7615_dfs_check_channel(dev); + phy->dfs_state = -1; + mt76_set_channel(phy->mt76); - mt76_set_channel(&dev->mt76); - - ret = mt7615_mcu_set_channel(dev); + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); if (ret) goto out; - ret = mt7615_dfs_init_radar_detector(dev); - mt7615_mac_cca_stats_reset(dev); - dev->mt76.survey_time = ktime_get_boottime(); + mt7615_mac_set_timing(phy); + ret = mt7615_dfs_init_radar_detector(phy); + mt7615_mac_cca_stats_reset(phy); + mt7615_mcu_set_sku_en(phy, true); mt7615_mac_reset_counters(dev); + phy->noise = 0; + phy->chfreq = mt76_rr(dev, MT_CHFREQ(ext_phy)); out: - clear_bit(MT76_RESET, &dev->mt76.state); + clear_bit(MT76_RESET, &phy->mt76->state); mutex_unlock(&dev->mt76.mutex); - mt76_txq_schedule_all(&dev->mt76); + mt76_txq_schedule_all(phy->mt76); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work, MT7615_WATCHDOG_TIME); return ret; @@ -181,7 +259,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; @@ -230,27 +308,27 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + bool band = phy != &dev->phy; int ret = 0; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | + IEEE80211_CONF_CHANGE_POWER)) { ieee80211_stop_queues(hw); - ret = mt7615_set_channel(dev); + ret = mt7615_set_channel(phy); ieee80211_wake_queues(hw); } mutex_lock(&dev->mt76.mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) - ret = mt7615_mcu_set_tx_power(dev); - if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) - dev->mt76.rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; else - dev->mt76.rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } mutex_unlock(&dev->mt76.mutex); @@ -263,7 +341,7 @@ 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 mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS; @@ -275,7 +353,10 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, unsigned int *total_flags, u64 multicast) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_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 | @@ -285,21 +366,21 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, #define MT76_FILTER(_flag, _hw) do { \ flags |= *total_flags & FIF_##_flag; \ - dev->mt76.rxfilter &= ~(_hw); \ - dev->mt76.rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + phy->rxfilter &= ~(_hw); \ + phy->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ } while (0) - dev->mt76.rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | - MT_WF_RFCR_DROP_OTHER_BEACON | - MT_WF_RFCR_DROP_FRAME_REPORT | - MT_WF_RFCR_DROP_PROBEREQ | - MT_WF_RFCR_DROP_MCAST_FILTERED | - MT_WF_RFCR_DROP_MCAST | - MT_WF_RFCR_DROP_BCAST | - MT_WF_RFCR_DROP_DUPLICATE | - MT_WF_RFCR_DROP_A2_BSSID | - MT_WF_RFCR_DROP_UNWANTED_CTL | - MT_WF_RFCR_DROP_STBC_MULTI); + phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | MT_WF_RFCR_DROP_A3_MAC | @@ -313,12 +394,12 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw, MT_WF_RFCR_DROP_NDPA); *total_flags = flags; - mt76_wr(dev, MT_WF_RFCR, dev->mt76.rxfilter); + mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); if (*total_flags & FIF_CONTROL) - mt76_clear(dev, MT_WF_RFCR1, ctl_flags); + mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags); else - mt76_set(dev, MT_WF_RFCR1, ctl_flags); + mt76_set(dev, MT_WF_RFCR1(band), ctl_flags); } static void mt7615_bss_info_changed(struct ieee80211_hw *hw, @@ -326,24 +407,32 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *info, u32 changed) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); if (changed & BSS_CHANGED_ASSOC) - mt7615_mcu_set_bss_info(dev, vif, info->assoc); + mt7615_mcu_add_bss_info(dev, vif, info->assoc); - /* TODO: update beacon content - * BSS_CHANGED_BEACON - */ + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + if (slottime != phy->slottime) { + phy->slottime = slottime; + mt7615_mac_set_timing(phy); + } + } if (changed & BSS_CHANGED_BEACON_ENABLED) { - mt7615_mcu_set_bss_info(dev, vif, info->enable_beacon); - mt7615_mcu_wtbl_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_sta_rec_bmc(dev, vif, info->enable_beacon); - mt7615_mcu_set_bcn(dev, vif, info->enable_beacon); + mt7615_mcu_add_bss_info(dev, vif, info->enable_beacon); + mt7615_mcu_sta_add(dev, vif, NULL, info->enable_beacon); } + if (changed & (BSS_CHANGED_BEACON | + BSS_CHANGED_BEACON_ENABLED)) + mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); + mutex_unlock(&dev->mt76.mutex); } @@ -352,15 +441,15 @@ mt7615_channel_switch_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct cfg80211_chan_def *chandef) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_bcn(dev, vif, true); + mt7615_mcu_add_beacon(dev, hw, vif, true); mutex_unlock(&dev->mt76.mutex); } -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -375,33 +464,23 @@ int mt7615_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; + mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_add_wtbl(dev, vif, sta); - mt7615_mcu_set_sta_rec(dev, vif, sta, 1); + mt7615_mcu_sta_add(dev, vif, sta, true); return 0; } -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - if (sta->ht_cap.ht_supported) - mt7615_mcu_set_ht_cap(dev, vif, sta); -} - -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - mt7615_mcu_set_sta_rec(dev, vif, sta, 0); - mt7615_mcu_del_wtbl(dev, sta); - + mt7615_mcu_sta_add(dev, vif, sta, false); mt7615_mac_wtbl_update(dev, msta->wcid.idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); @@ -415,7 +494,8 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); int i; @@ -430,7 +510,7 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, break; } msta->n_rates = i; - mt7615_mac_set_rates(dev, msta, NULL, msta->rates); + mt7615_mac_set_rates(phy, msta, NULL, msta->rates); msta->rate_probe = false; spin_unlock_bh(&dev->mt76.lock); } @@ -439,7 +519,8 @@ static void mt7615_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt76_phy *mphy = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; struct mt76_wcid *wcid = &dev->mt76.global_wcid; @@ -458,15 +539,16 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &mvif->sta.wcid; } - mt76_tx(&dev->mt76, control->sta, wcid, skb); + mt76_tx(mphy, control->sta, wcid, skb); } static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); mutex_lock(&dev->mt76.mutex); - mt7615_mcu_set_rts_thresh(dev, val); + mt7615_mcu_set_rts_thresh(phy, val); mutex_unlock(&dev->mt76.mutex); return 0; @@ -477,7 +559,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) { enum ieee80211_ampdu_mlme_action action = params->action; - struct mt7615_dev *dev = hw->priv; + struct mt7615_dev *dev = mt7615_hw_dev(hw); struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; @@ -496,21 +578,21 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_RX_START: mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn, params->buf_size); - mt7615_mcu_set_rx_ba(dev, params, 1); + mt7615_mcu_add_rx_ba(dev, params, true); break; case IEEE80211_AMPDU_RX_STOP: mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); - mt7615_mcu_set_rx_ba(dev, params, 0); + mt7615_mcu_add_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7615_mcu_set_tx_ba(dev, params, 1); + mt7615_mcu_add_tx_ba(dev, params, true); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - mt7615_mcu_set_tx_ba(dev, params, 0); + mt7615_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn); @@ -518,7 +600,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - mt7615_mcu_set_tx_ba(dev, params, 0); + mt7615_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } @@ -527,6 +609,98 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return ret; } +static int +mt7615_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST, + IEEE80211_STA_NONE); +} + +static int +mt7615_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE, + IEEE80211_STA_NOTEXIST); +} + +static int +mt7615_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + struct mib_stats *mib = &phy->mib; + + stats->dot11RTSSuccessCount = mib->rts_cnt; + stats->dot11RTSFailureCount = mib->rts_retries_cnt; + stats->dot11FCSErrorCount = mib->fcs_err_cnt; + stats->dot11ACKFailureCount = mib->ack_fail_cnt; + + return 0; +} + +static u64 +mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + union { + u64 t64; + u32 t32[2]; + } tsf; + + mutex_lock(&dev->mt76.mutex); + + mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0); + tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1); + + mutex_unlock(&dev->mt76.mutex); + + return tsf.t64; +} + +static void +mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + phy->coverage_class = max_t(s16, coverage_class, 0); + mt7615_mac_set_timing(phy); +} + +static int +mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int max_nss = hweight8(hw->wiphy->available_antennas_tx); + bool ext_phy = phy != &dev->phy; + + if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss) + return -EINVAL; + + if ((BIT(hweight8(tx_ant)) - 1) != tx_ant) + tx_ant = BIT(ffs(tx_ant) - 1) - 1; + + mutex_lock(&dev->mt76.mutex); + + phy->mt76->antenna_mask = tx_ant; + if (ext_phy) { + if (dev->chainmask == 0xf) + tx_ant <<= 2; + else + tx_ant <<= 1; + } + phy->chainmask = tx_ant; + + mt76_set_stream_caps(&dev->mt76, true); + + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + const struct ieee80211_ops mt7615_ops = { .tx = mt7615_tx, .start = mt7615_start, @@ -537,7 +711,9 @@ const struct ieee80211_ops mt7615_ops = { .conf_tx = mt7615_conf_tx, .configure_filter = mt7615_configure_filter, .bss_info_changed = mt7615_bss_info_changed, - .sta_state = mt76_sta_state, + .sta_add = mt7615_sta_add, + .sta_remove = mt7615_sta_remove, + .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7615_set_key, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, @@ -548,6 +724,38 @@ const struct ieee80211_ops mt7615_ops = { .release_buffered_frames = mt76_release_buffered_frames, .get_txpower = mt76_get_txpower, .channel_switch_beacon = mt7615_channel_switch_beacon, + .get_stats = mt7615_get_stats, + .get_tsf = mt7615_get_tsf, .get_survey = mt76_get_survey, .get_antenna = mt76_get_antenna, + .set_antenna = mt7615_set_antenna, + .set_coverage_class = mt7615_set_coverage_class, }; + +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"); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index f229c9ce9f65..610cfa918c7b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -29,7 +29,37 @@ struct mt7615_fw_trailer { __le32 len; } __packed; -#define MCU_PATCH_ADDRESS 0x80000 +#define FW_V3_COMMON_TAILER_SIZE 36 +#define FW_V3_REGION_TAILER_SIZE 40 +#define FW_START_OVERRIDE BIT(0) +#define FW_START_DLYCAL BIT(1) +#define FW_START_WORKING_PDA_CR4 BIT(2) + +struct mt7663_fw_trailer { + u8 chip_id; + u8 eco_code; + u8 n_region; + u8 format_ver; + u8 format_flag; + u8 reserv[2]; + char fw_ver[10]; + char build_date[15]; + __le32 crc; +} __packed; + +struct mt7663_fw_buf { + __le32 crc; + __le32 d_img_size; + __le32 block_size; + u8 rsv[4]; + __le32 img_dest_addr; + __le32 img_size; + u8 feature_set; +}; + +#define MT7615_PATCH_ADDRESS 0x80000 +#define MT7622_PATCH_ADDRESS 0x9c000 +#define MT7663_PATCH_ADDRESS 0xdc000 #define N9_REGION_NUM 2 #define CR4_REGION_NUM 1 @@ -43,29 +73,32 @@ struct mt7615_fw_trailer { #define DL_MODE_KEY_IDX GENMASK(2, 1) #define DL_MODE_RESET_SEC_IV BIT(3) #define DL_MODE_WORKING_PDA_CR4 BIT(4) +#define DL_MODE_VALID_RAM_ENTRY BIT(5) #define DL_MODE_NEED_RSP BIT(31) #define FW_START_OVERRIDE BIT(0) #define FW_START_WORKING_PDA_CR4 BIT(2) -static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, - int cmd, int *wait_seq) +void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) { + int txd_len, mcu_cmd = cmd & MCU_CMD_MASK; + struct mt7615_uni_txd *uni_txd; struct mt7615_mcu_txd *mcu_txd; u8 seq, q_idx, pkt_fmt; - enum mt76_txq_id qid; - u32 val; __le32 *txd; + u32 val; - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; if (!seq) - seq = ++dev->mt76.mmio.mcu.msg_seq & 0xf; + seq = ++dev->mt76.mcu.msg_seq & 0xf; + if (wait_seq) + *wait_seq = seq; - mcu_txd = (struct mt7615_mcu_txd *)skb_push(skb, - sizeof(struct mt7615_mcu_txd)); - memset(mcu_txd, 0, sizeof(struct mt7615_mcu_txd)); + txd_len = cmd & MCU_UNI_PREFIX ? sizeof(*uni_txd) : sizeof(*mcu_txd); + txd = (__le32 *)skb_push(skb, txd_len); - if (cmd != -MCU_CMD_FW_SCATTER) { + if (cmd != MCU_CMD_FW_SCATTER) { q_idx = MT_TX_MCU_PORT_RX_Q0; pkt_fmt = MT_TX_TYPE_CMD; } else { @@ -73,8 +106,6 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, pkt_fmt = MT_TX_TYPE_FW; } - txd = mcu_txd->txd; - val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) | FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_MCU) | FIELD_PREP(MT_TXD0_Q_IDX, q_idx); @@ -85,26 +116,43 @@ static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, FIELD_PREP(MT_TXD1_PKT_FMT, pkt_fmt); txd[1] = cpu_to_le32(val); + if (cmd & MCU_UNI_PREFIX) { + uni_txd = (struct mt7615_uni_txd *)txd; + uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd)); + uni_txd->option = MCU_CMD_UNI_EXT_ACK; + uni_txd->cid = cpu_to_le16(mcu_cmd); + uni_txd->s2d_index = MCU_S2D_H2N; + uni_txd->pkt_type = MCU_PKT_ID; + uni_txd->seq = seq; + + return; + } + + mcu_txd = (struct mt7615_mcu_txd *)txd; mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd)); mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU, q_idx)); + mcu_txd->s2d_index = MCU_S2D_H2N; mcu_txd->pkt_type = MCU_PKT_ID; mcu_txd->seq = seq; - if (cmd < 0) { + if (cmd & MCU_FW_PREFIX) { mcu_txd->set_query = MCU_Q_NA; - mcu_txd->cid = -cmd; + mcu_txd->cid = mcu_cmd; } else { mcu_txd->cid = MCU_CMD_EXT_CID; mcu_txd->set_query = MCU_Q_SET; mcu_txd->ext_cid = cmd; mcu_txd->ext_cid_ack = 1; } - mcu_txd->s2d_index = MCU_S2D_H2N; +} - if (wait_seq) - *wait_seq = seq; +static int __mt7615_mcu_msg_send(struct mt7615_dev *dev, struct sk_buff *skb, + int cmd, int *wait_seq) +{ + enum mt76_txq_id qid; - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) + mt7615_mcu_fill_msg(dev, skb, cmd, wait_seq); + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) qid = MT_TXQ_MCU; else qid = MT_TXQ_FWDL; @@ -123,7 +171,7 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, return -EAGAIN; switch (cmd) { - case -MCU_CMD_PATCH_SEM_CONTROL: + case MCU_CMD_PATCH_SEM_CONTROL: skb_pull(skb, sizeof(*rxd) - 4); ret = *skb->data; break; @@ -139,32 +187,18 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd, return ret; } -static int -mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, - int len, bool wait_resp) +int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq) { - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - unsigned long expires = jiffies + 10 * HZ; + unsigned long expires = jiffies + 20 * HZ; struct sk_buff *skb; - int ret, seq; - - skb = mt7615_mcu_msg_alloc(data, len); - if (!skb) - return -ENOMEM; - - mutex_lock(&mdev->mmio.mcu.mutex); - - ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); - if (ret) - goto out; + int ret = 0; - while (wait_resp) { - skb = mt76_mcu_get_response(mdev, expires); + while (true) { + skb = mt76_mcu_get_response(&dev->mt76, expires); if (!skb) { - dev_err(mdev->dev, "Message %d (seq %d) timeout\n", - cmd, seq); - ret = -ETIMEDOUT; - break; + dev_err(dev->mt76.dev, "Message %ld (seq %d) timeout\n", + cmd & MCU_CMD_MASK, seq); + return -ETIMEDOUT; } ret = mt7615_mcu_parse_response(dev, cmd, skb, seq); @@ -172,12 +206,44 @@ mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, break; } + return ret; +} + +static int +mt7615_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; + + mutex_lock(&mdev->mcu.mutex); + + ret = __mt7615_mcu_msg_send(dev, skb, cmd, &seq); + if (ret) + goto out; + + if (wait_resp) + ret = mt7615_mcu_wait_response(dev, cmd, seq); + out: - mutex_unlock(&mdev->mmio.mcu.mutex); + mutex_unlock(&mdev->mcu.mutex); return ret; } +static int +mt7615_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, + int len, bool wait_resp) +{ + struct sk_buff *skb; + + skb = mt7615_mcu_msg_alloc(data, len); + if (!skb) + return -ENOMEM; + + return __mt76_mcu_skb_send_msg(mdev, skb, cmd, wait_resp); +} + static void mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) { @@ -186,20 +252,59 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) } static void +mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_mcu_rdd_report *r; + + r = (struct mt7615_mcu_rdd_report *)skb->data; + + if (r->idx && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ieee80211_radar_detected(mphy->hw); + dev->hw_pattern++; +} + +static void +mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; + const char *data = (char *)&rxd[1]; + const char *type; + + switch (rxd->s2d_index) { + case 0: + type = "N9"; + break; + case 2: + type = "CR4"; + break; + default: + type = "unknown"; + break; + } + + wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); +} + +static void mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data; switch (rxd->ext_eid) { case MCU_EXT_EVENT_RDD_REPORT: - ieee80211_radar_detected(dev->mt76.hw); - dev->hw_pattern++; + mt7615_mcu_rx_radar_detected(dev, skb); break; case MCU_EXT_EVENT_CSA_NOTIFY: ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw, IEEE80211_IFACE_ITER_RESUME_ALL, mt7615_mcu_csa_finish, dev); break; + case MCU_EXT_EVENT_FW_LOG_2_HOST: + mt7615_mcu_rx_log_message(dev, skb); + break; default: break; } @@ -247,10 +352,1095 @@ static int mt7615_mcu_init_download(struct mt7615_dev *dev, u32 addr, .mode = cpu_to_le32(mode), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_TARGET_ADDRESS_LEN_REQ, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_add_dev(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 tlv_num; + u8 is_tlv_append; + u8 rsv[3]; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 band_idx; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .tlv_num = cpu_to_le16(1), + .is_tlv_append = 1, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + .band_idx = mvif->band_idx, + }, + }; + + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); +} + +static int +mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct ieee80211_mutable_offsets offs; + struct ieee80211_tx_info *info; + struct req { + u8 omac_idx; + u8 enable; + u8 wlan_idx; + u8 band_idx; + u8 pkt_type; + u8 need_pre_tbtt_int; + __le16 csa_ie_pos; + __le16 pkt_len; + __le16 tim_ie_pos; + u8 pkt[512]; + u8 csa_cnt; + /* bss color change */ + u8 bcc_cnt; + __le16 bcc_ie_pos; + } __packed req = { + .omac_idx = mvif->omac_idx, + .enable = enable, + .wlan_idx = wcid->idx, + .band_idx = mvif->band_idx, + }; + struct sk_buff *skb; + + skb = ieee80211_beacon_get_template(hw, vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + if (mvif->band_idx) { + info = IEEE80211_SKB_CB(skb); + info->hw_queue |= MT_TX_HW_QUEUE_EXT_PHY; + } + + mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, + 0, NULL, true); + memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + if (offs.csa_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; + req.csa_ie_pos = cpu_to_le16(csa_offs); + req.csa_cnt = skb->data[offs.csa_counter_offs[0]]; + } + dev_kfree_skb(skb); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) +{ +#define ENTER_PM_STATE 1 +#define EXIT_PM_STATE 2 + struct { + u8 pm_number; + u8 pm_state; + u8 bssid[ETH_ALEN]; + u8 dtim_period; + u8 wlan_idx; + __le16 bcn_interval; + __le32 aid; + __le32 rx_filter; + u8 band_idx; + u8 rsv[3]; + __le32 feature; + u8 omac_idx; + u8 wmm_idx; + u8 bcn_loss_cnt; + u8 bcn_sp_duration; + } __packed req = { + .pm_number = 5, + .pm_state = state ? ENTER_PM_STATE : EXIT_PM_STATE, + .band_idx = band, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, + &req, sizeof(req), true); +} + +static struct sk_buff * +mt7615_mcu_alloc_sta_req(struct mt7615_vif *mvif, struct mt7615_sta *msta) +{ + struct sta_req_hdr hdr = { + .bss_idx = mvif->idx, + .wlan_idx = msta ? msta->wcid.idx : 0, + .muar_idx = msta ? mvif->omac_idx : 0, + .is_tlv_append = 1, + }; + struct sk_buff *skb; + + skb = mt7615_mcu_msg_alloc(NULL, MT7615_STA_UPDATE_MAX_SIZE); + if (!skb) + return ERR_PTR(-ENOMEM); + + skb_put_data(skb, &hdr, sizeof(hdr)); + + return skb; +} + +static struct wtbl_req_hdr * +mt7615_mcu_alloc_wtbl_req(struct mt7615_sta *msta, int cmd, + void *sta_wtbl, struct sk_buff **skb) +{ + struct tlv *sta_hdr = sta_wtbl; + struct wtbl_req_hdr hdr = { + .wlan_idx = msta->wcid.idx, + .operation = cmd, + }; + struct sk_buff *nskb = *skb; + + if (!nskb) { + nskb = mt7615_mcu_msg_alloc(NULL, MT7615_WTBL_UPDATE_BA_SIZE); + if (!nskb) + return ERR_PTR(-ENOMEM); + + *skb = nskb; + } + + if (sta_hdr) + sta_hdr->len = cpu_to_le16(sizeof(hdr)); + + return skb_put_data(nskb, &hdr, sizeof(hdr)); +} + +static struct tlv * +mt7615_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, + void *sta_ntlv, void *sta_wtbl) +{ + struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv; + struct tlv *sta_hdr = sta_wtbl; + struct tlv *ptlv, tlv = { + .tag = cpu_to_le16(tag), + .len = cpu_to_le16(len), + }; + u16 ntlv; + + ptlv = skb_put(skb, len); + memcpy(ptlv, &tlv, sizeof(tlv)); + + ntlv = le16_to_cpu(ntlv_hdr->tlv_num); + ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); + + if (sta_hdr) { + u16 size = le16_to_cpu(sta_hdr->len); + + sta_hdr->len = cpu_to_le16(size + len); + } + + return ptlv; +} + +static struct tlv * +mt7615_mcu_add_tlv(struct sk_buff *skb, int tag, int len) +{ + return mt7615_mcu_add_nested_tlv(skb, tag, len, skb->data, NULL); +} + +static int +mt7615_mcu_bss_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_basic *bss; + u8 wlan_idx = mvif->sta.wcid.idx; + u32 type = NETWORK_INFRA; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + break; + case NL80211_IFTYPE_STATION: + /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ + if (enable) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + break; + case NL80211_IFTYPE_ADHOC: + type = NETWORK_IBSS; + break; + default: + WARN_ON(1); + break; + } + + bss = (struct bss_info_basic *)tlv; + memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN); + bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); + bss->network_type = cpu_to_le32(type); + bss->dtim_period = vif->bss_conf.dtim_period; + bss->bmc_tx_wlan_idx = wlan_idx; + bss->wmm_idx = mvif->wmm_idx; + bss->active = enable; + + return 0; +} + +static void +mt7615_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct bss_info_omac *omac; + struct tlv *tlv; + u32 type = 0; + u8 idx; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac)); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + type = CONNECTION_INFRA_AP; + break; + case NL80211_IFTYPE_STATION: + type = CONNECTION_INFRA_STA; + break; + case NL80211_IFTYPE_ADHOC: + type = CONNECTION_IBSS_ADHOC; + break; + default: + WARN_ON(1); + break; + } + + omac = (struct bss_info_omac *)tlv; + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + omac->conn_type = cpu_to_le32(type); + omac->omac_idx = mvif->omac_idx; + omac->band_idx = mvif->band_idx; + omac->hw_bss_idx = idx; +} + +/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ +#define BCN_TX_ESTIMATE_TIME (4096 + 20) +static void +mt7615_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7615_vif *mvif) +{ + struct bss_info_ext_bss *ext; + int ext_bss_idx, tsf_offset; + struct tlv *tlv; + + ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; + if (ext_bss_idx < 0) + return; + + tlv = mt7615_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext)); + + ext = (struct bss_info_ext_bss *)tlv; + tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; + ext->mbss_tsf_offset = cpu_to_le32(tsf_offset); +} + +static void +mt7615_mcu_sta_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct sta_rec_ba *ba; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba)); + + ba = (struct sta_rec_ba *)tlv; + ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT, + ba->winsize = cpu_to_le16(params->buf_size); + ba->ssn = cpu_to_le16(params->ssn); + ba->ba_en = enable << params->tid; + ba->amsdu = params->amsdu; + ba->tid = params->tid; +} + +static void +mt7615_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + struct sta_rec_basic *basic; + struct tlv *tlv; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic)); + + basic = (struct sta_rec_basic *)tlv; + basic->extra_info = cpu_to_le16(EXTRA_INFO_VER); + + if (enable) { + basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW); + basic->conn_state = CONN_STATE_PORT_SECURE; + } else { + basic->conn_state = CONN_STATE_DISCONNECT; + } + + if (!sta) { + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC); + eth_broadcast_addr(basic->peer_addr); + return; + } + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + case NL80211_IFTYPE_STATION: + basic->conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + break; + case NL80211_IFTYPE_ADHOC: + basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); + break; + default: + WARN_ON(1); + break; + } + + memcpy(basic->peer_addr, sta->addr, ETH_ALEN); + basic->aid = cpu_to_le16(sta->aid); + basic->qos = sta->wme; +} + +static void +mt7615_mcu_sta_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta) +{ + struct tlv *tlv; + + if (sta->ht_cap.ht_supported) { + struct sta_rec_ht *ht; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); + ht = (struct sta_rec_ht *)tlv; + ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + } + if (sta->vht_cap.vht_supported) { + struct sta_rec_vht *vht; + + tlv = mt7615_mcu_add_tlv(skb, STA_REC_VHT, sizeof(*vht)); + vht = (struct sta_rec_vht *)tlv; + vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; + vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); + } +} + +static void +mt7615_mcu_wtbl_ba_tlv(struct sk_buff *skb, + struct ieee80211_ampdu_params *params, + bool enable, bool tx, void *sta_wtbl, + void *wtbl_tlv) +{ + struct wtbl_ba *ba; + struct tlv *tlv; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba), + wtbl_tlv, sta_wtbl); + + ba = (struct wtbl_ba *)tlv; + ba->tid = params->tid; + + if (tx) { + ba->ba_type = MT_BA_TYPE_ORIGINATOR; + ba->sn = enable ? cpu_to_le16(params->ssn) : 0; + ba->ba_winsize = cpu_to_le16(params->buf_size); + ba->ba_en = enable; + } else { + memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN); + ba->ba_type = MT_BA_TYPE_RECIPIENT; + ba->rst_ba_tid = params->tid; + ba->rst_ba_sel = RST_BA_MAC_TID_MATCH; + ba->rst_ba_sb = 1; + } + + if (enable && tx) { + u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; + int i; + + for (i = 7; i > 0; i--) { + if (params->buf_size >= ba_range[i]) + break; + } + ba->ba_winsize_idx = i; + } +} + +static void +mt7615_mcu_wtbl_generic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, void *sta_wtbl, + void *wtbl_tlv) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_generic *generic; + struct wtbl_rx *rx; + struct tlv *tlv; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_GENERIC, sizeof(*generic), + wtbl_tlv, sta_wtbl); + + generic = (struct wtbl_generic *)tlv; + + if (sta) { + memcpy(generic->peer_addr, sta->addr, ETH_ALEN); + generic->partial_aid = cpu_to_le16(sta->aid); + generic->muar_idx = mvif->omac_idx; + generic->qos = sta->wme; + } else { + eth_broadcast_addr(generic->peer_addr); + generic->muar_idx = 0xe; + } + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx), + wtbl_tlv, sta_wtbl); + + rx = (struct wtbl_rx *)tlv; + rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1; + rx->rca2 = 1; + rx->rv = 1; +} + +static void +mt7615_mcu_wtbl_ht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta, + void *sta_wtbl, void *wtbl_tlv) +{ + struct tlv *tlv; + u32 flags = 0; + + if (sta->ht_cap.ht_supported) { + struct wtbl_ht *ht; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht), + wtbl_tlv, sta_wtbl); + ht = (struct wtbl_ht *)tlv; + ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; + ht->af = sta->ht_cap.ampdu_factor; + ht->mm = sta->ht_cap.ampdu_density; + ht->ht = 1; + + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + flags |= MT_WTBL_W5_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + flags |= MT_WTBL_W5_SHORT_GI_40; + } + + if (sta->vht_cap.vht_supported) { + struct wtbl_vht *vht; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_VHT, sizeof(*vht), + wtbl_tlv, sta_wtbl); + vht = (struct wtbl_vht *)tlv; + vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC, + vht->vht = 1; + + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) + flags |= MT_WTBL_W5_SHORT_GI_80; + if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) + flags |= MT_WTBL_W5_SHORT_GI_160; + } + + /* wtbl smps */ + if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { + struct wtbl_smps *smps; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps), + wtbl_tlv, sta_wtbl); + smps = (struct wtbl_smps *)tlv; + smps->smps = 1; + } + + if (sta->ht_cap.ht_supported) { + /* sgi */ + u32 msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | + MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; + struct wtbl_raw *raw; + + tlv = mt7615_mcu_add_nested_tlv(skb, WTBL_RAW_DATA, + sizeof(*raw), wtbl_tlv, + sta_wtbl); + raw = (struct wtbl_raw *)tlv; + raw->val = cpu_to_le32(flags); + raw->msk = cpu_to_le32(~msk); + raw->wtbl_idx = 1; + raw->dw = 5; + } +} + +static int +mt7615_mcu_add_bss(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct sk_buff *skb; + + skb = mt7615_mcu_alloc_sta_req(mvif, NULL); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + if (enable) + mt7615_mcu_bss_omac_tlv(skb, vif); + + mt7615_mcu_bss_basic_tlv(skb, vif, enable); + + if (enable && mvif->omac_idx > EXT_BSSID_START) + mt7615_mcu_bss_ext_tlv(skb, mvif); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_BSS_INFO_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb = NULL; + int err; + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, NULL, wtbl_hdr); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_WTBL_UPDATE, true); + if (err < 0) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, true); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, false); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); + if (err < 0 || !enable) + return err; + + skb = NULL; + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, NULL, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_WTBL_UPDATE, true); +} + +static int +mt7615_mcu_wtbl_sta_add(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct sk_buff *skb, *sskb, *wskb = NULL; + struct wtbl_req_hdr *wtbl_hdr; + struct mt7615_sta *msta; + int cmd, err; + + msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; + + sskb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(sskb)) + return PTR_ERR(sskb); + + mt7615_mcu_sta_basic_tlv(sskb, vif, sta, enable); + if (enable && sta) + mt7615_mcu_sta_ht_tlv(sskb, sta); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_RESET_AND_SET, NULL, + &wskb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + if (enable) { + mt7615_mcu_wtbl_generic_tlv(wskb, vif, sta, NULL, wtbl_hdr); + if (sta) + mt7615_mcu_wtbl_ht_tlv(wskb, sta, NULL, wtbl_hdr); + } + + cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; + skb = enable ? wskb : sskb; + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); + if (err < 0) + return err; + + cmd = enable ? MCU_EXT_CMD_STA_REC_UPDATE : MCU_EXT_CMD_WTBL_UPDATE; + skb = enable ? sskb : wskb; + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +} + +static const struct mt7615_mcu_ops wtbl_update_ops = { + .add_beacon_offload = mt7615_mcu_add_beacon_offload, + .set_pm_state = mt7615_mcu_ctrl_pm_state, + .add_dev_info = mt7615_mcu_add_dev, + .add_bss_info = mt7615_mcu_add_bss, + .add_tx_ba = mt7615_mcu_wtbl_tx_ba, + .add_rx_ba = mt7615_mcu_wtbl_rx_ba, + .sta_add = mt7615_mcu_wtbl_sta_add, +}; + +static int +mt7615_mcu_sta_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable, bool tx) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, tx); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, tx, sta_wtbl, wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_sta_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7615_mcu_sta_ba(dev, params, enable, true); +} + +static int +mt7615_mcu_sta_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + return mt7615_mcu_sta_ba(dev, params, enable, false); +} + +static int +mt7615_mcu_add_sta_cmd(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable, int cmd) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct mt7615_sta *msta; + struct tlv *sta_wtbl; + struct sk_buff *skb; + + msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_basic_tlv(skb, vif, sta, enable); + if (enable && sta) + mt7615_mcu_sta_ht_tlv(skb, sta); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_RESET_AND_SET, + sta_wtbl, &skb); + if (enable) { + mt7615_mcu_wtbl_generic_tlv(skb, vif, sta, sta_wtbl, wtbl_hdr); + if (sta) + mt7615_mcu_wtbl_ht_tlv(skb, sta, sta_wtbl, wtbl_hdr); + } + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, cmd, true); +} + +static int +mt7615_mcu_add_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + return mt7615_mcu_add_sta_cmd(dev, vif, sta, enable, + MCU_EXT_CMD_STA_REC_UPDATE); +} + +static const struct mt7615_mcu_ops sta_update_ops = { + .add_beacon_offload = mt7615_mcu_add_beacon_offload, + .set_pm_state = mt7615_mcu_ctrl_pm_state, + .add_dev_info = mt7615_mcu_add_dev, + .add_bss_info = mt7615_mcu_add_bss, + .add_tx_ba = mt7615_mcu_sta_tx_ba, + .add_rx_ba = mt7615_mcu_sta_rx_ba, + .sta_add = mt7615_mcu_add_sta, +}; + +static int +mt7615_mcu_uni_add_dev(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 omac_idx; + u8 band_idx; + __le16 pad; + } __packed hdr; + struct req_tlv { + __le16 tag; + __le16 len; + u8 active; + u8 pad; + u8 omac_addr[ETH_ALEN]; + } __packed tlv; + } data = { + .hdr = { + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + }, + .tlv = { + .tag = cpu_to_le16(DEV_INFO_ACTIVE), + .len = cpu_to_le16(sizeof(struct req_tlv)), + .active = enable, + }, + }; + + memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_DEV_INFO_UPDATE, + &data, sizeof(data), true); +} + +static int +mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) +{ + return 0; +} + +static int +mt7615_mcu_uni_add_bss(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct 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; + __le16 sta_idx; + u8 nonht_basic_phy; + u8 pad[3]; + } __packed basic; + } req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .basic = { + .tag = cpu_to_le16(UNI_BSS_INFO_BASIC), + .len = cpu_to_le16(sizeof(struct basic_tlv)), + .bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int), + .dtim_period = vif->bss_conf.dtim_period, + .omac_idx = mvif->omac_idx, + .band_idx = mvif->band_idx, + .wmm_idx = mvif->wmm_idx, + .active = enable, + }, + }; + u8 idx, tx_wlan_idx = 0; + + idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; + req.basic.hw_bss_idx = idx; + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_AP: + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); + tx_wlan_idx = mvif->sta.wcid.idx; + break; + case NL80211_IFTYPE_STATION: + if (enable) { + struct ieee80211_sta *sta; + struct mt7615_sta *msta; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (!sta) { + rcu_read_unlock(); + return -EINVAL; + } + + msta = (struct mt7615_sta *)sta->drv_priv; + tx_wlan_idx = msta->wcid.idx; + rcu_read_unlock(); + } + req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); + break; + default: + WARN_ON(1); + break; + } + + memcpy(req.basic.bssid, vif->bss_conf.bssid, ETH_ALEN); + req.basic.bmc_tx_wlan_idx = cpu_to_le16(tx_wlan_idx); + req.basic.sta_idx = cpu_to_le16(tx_wlan_idx); + req.basic.conn_state = !enable; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, + &req, sizeof(req), true); +} + +static int +mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + bool enable) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt76_wcid *wcid = &dev->mt76.global_wcid; + struct ieee80211_mutable_offsets offs; + struct { + struct req_hdr { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct bcn_content_tlv { + __le16 tag; + __le16 len; + __le16 tim_ie_pos; + __le16 csa_ie_pos; + __le16 bcc_ie_pos; + /* 0: enable beacon offload + * 1: disable beacon offload + * 2: update probe respond offload + */ + u8 enable; + /* 0: legacy format (TXD + payload) + * 1: only cap field IE + */ + u8 type; + __le16 pkt_len; + u8 pkt[512]; + } __packed beacon_tlv; + } req = { + .hdr = { + .bss_idx = mvif->idx, + }, + .beacon_tlv = { + .tag = cpu_to_le16(UNI_BSS_INFO_BCN_CONTENT), + .len = cpu_to_le16(sizeof(struct bcn_content_tlv)), + .enable = enable, + }, + }; + struct sk_buff *skb; + + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); + if (!skb) + return -EINVAL; + + if (skb->len > 512 - MT_TXD_SIZE) { + dev_err(dev->mt76.dev, "beacon size limit exceed\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + + mt7615_mac_write_txwi(dev, (__le32 *)(req.beacon_tlv.pkt), skb, + wcid, NULL, 0, NULL, true); + memcpy(req.beacon_tlv.pkt + MT_TXD_SIZE, skb->data, skb->len); + req.beacon_tlv.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); + req.beacon_tlv.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); + + if (offs.csa_counter_offs[0]) { + u16 csa_offs; + + csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; + req.beacon_tlv.csa_ie_pos = cpu_to_le16(csa_offs); + } + dev_kfree_skb(skb); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, &req, sizeof(req), true); } +static int +mt7615_mcu_uni_tx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, true, sta_wtbl, + wtbl_hdr); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); + if (err < 0) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, true); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_uni_rx_ba(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; + struct mt7615_vif *mvif = msta->vif; + struct wtbl_req_hdr *wtbl_hdr; + struct tlv *sta_wtbl; + struct sk_buff *skb; + int err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + mt7615_mcu_sta_ba_tlv(skb, params, enable, false); + + err = __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); + if (err < 0 || !enable) + return err; + + skb = mt7615_mcu_alloc_sta_req(mvif, msta); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + sta_wtbl = mt7615_mcu_add_tlv(skb, STA_REC_WTBL, sizeof(struct tlv)); + + wtbl_hdr = mt7615_mcu_alloc_wtbl_req(msta, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt7615_mcu_wtbl_ba_tlv(skb, params, enable, false, sta_wtbl, + wtbl_hdr); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_UNI_CMD_STA_REC_UPDATE, true); +} + +static int +mt7615_mcu_uni_add_sta(struct mt7615_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, bool enable) +{ + return mt7615_mcu_add_sta_cmd(dev, vif, sta, enable, + MCU_UNI_CMD_STA_REC_UPDATE); +} + +static const struct mt7615_mcu_ops uni_update_ops = { + .add_beacon_offload = mt7615_mcu_uni_add_beacon_offload, + .set_pm_state = mt7615_mcu_uni_ctrl_pm_state, + .add_dev_info = mt7615_mcu_uni_add_dev, + .add_bss_info = mt7615_mcu_uni_add_bss, + .add_tx_ba = mt7615_mcu_uni_tx_ba, + .add_rx_ba = mt7615_mcu_uni_rx_ba, + .sta_add = mt7615_mcu_uni_add_sta, +}; + static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, int len) { @@ -260,14 +1450,16 @@ static int mt7615_mcu_send_firmware(struct mt7615_dev *dev, const void *data, cur_len = min_t(int, 4096 - sizeof(struct mt7615_mcu_txd), len); - ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER, + ret = __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_SCATTER, data, cur_len, false); if (ret) break; data += cur_len; len -= cur_len; - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + + if (mt76_is_mmio(&dev->mt76)) + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); } return ret; @@ -284,13 +1476,13 @@ static int mt7615_mcu_start_firmware(struct mt7615_dev *dev, u32 addr, .addr = cpu_to_le32(addr), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_FW_START_REQ, &req, sizeof(req), true); } static int mt7615_mcu_restart(struct mt76_dev *dev) { - return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, + return __mt76_mcu_send_msg(dev, MCU_CMD_RESTART_DL_REQ, NULL, 0, true); } @@ -302,7 +1494,7 @@ static int mt7615_mcu_patch_sem_ctrl(struct mt7615_dev *dev, bool get) .op = cpu_to_le32(get ? PATCH_SEM_GET : PATCH_SEM_RELEASE), }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_SEM_CONTROL, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_SEM_CONTROL, &req, sizeof(req), true); } @@ -315,23 +1507,59 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev) .check_crc = 0, }; - return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_PATCH_FINISH_REQ, + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_PATCH_FINISH_REQ, &req, sizeof(req), true); } +static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +{ + if (!is_mt7622(&dev->mt76)) + return; + + regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC, + MT_INFRACFG_MISC_AP2CONN_WAKE, + !en * MT_INFRACFG_MISC_AP2CONN_WAKE); +} + static int mt7615_driver_own(struct mt7615_dev *dev) { - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN); - if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST, - MT_CFG_LPCR_HOST_FW_OWN, 0, 500)) { + u32 addr; + + addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); + + mt7622_trigger_hif_int(dev, true); + if (!mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) { dev_err(dev->mt76.dev, "Timeout for driver own\n"); return -EIO; } + mt7622_trigger_hif_int(dev, false); return 0; } -static int mt7615_load_patch(struct mt7615_dev *dev) +static int mt7615_firmware_own(struct mt7615_dev *dev) +{ + u32 addr; + + addr = is_mt7663(&dev->mt76) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; + mt7622_trigger_hif_int(dev, true); + + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_FW_OWN); + + if (is_mt7622(&dev->mt76) && + !mt76_poll_msec(dev, MT_CFG_LPCR_HOST, + MT_CFG_LPCR_HOST_FW_OWN, + MT_CFG_LPCR_HOST_FW_OWN, 3000)) { + dev_err(dev->mt76.dev, "Timeout for firmware own\n"); + return -EIO; + } + mt7622_trigger_hif_int(dev, false); + + return 0; +} + +static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) { const struct mt7615_patch_hdr *hdr; const struct firmware *fw = NULL; @@ -348,7 +1576,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev) return -EAGAIN; } - ret = request_firmware(&fw, MT7615_ROM_PATCH, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) goto out; @@ -365,8 +1593,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev) len = fw->size - sizeof(*hdr); - ret = mt7615_mcu_init_download(dev, MCU_PATCH_ADDRESS, len, - DL_MODE_NEED_RSP); + ret = mt7615_mcu_init_download(dev, addr, len, DL_MODE_NEED_RSP); if (ret) { dev_err(dev->mt76.dev, "Download request failed\n"); goto out; @@ -444,13 +1671,13 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev, return 0; } -static int mt7615_load_ram(struct mt7615_dev *dev) +static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) { const struct mt7615_fw_trailer *hdr; const struct firmware *fw; int ret; - ret = request_firmware(&fw, MT7615_FIRMWARE_N9, dev->mt76.dev); + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -477,9 +1704,30 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; } + snprintf(dev->mt76.hw->wiphy->fw_version, + sizeof(dev->mt76.hw->wiphy->fw_version), + "%.10s-%.15s", hdr->fw_ver, hdr->build_date); + + if (!strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) { + dev->fw_ver = MT7615_FIRMWARE_V2; + dev->mcu_ops = &sta_update_ops; + } else { + dev->fw_ver = MT7615_FIRMWARE_V1; + dev->mcu_ops = &wtbl_update_ops; + } + +out: release_firmware(fw); + return ret; +} - ret = request_firmware(&fw, MT7615_FIRMWARE_CR4, dev->mt76.dev); +static int mt7615_load_cr4(struct mt7615_dev *dev, const char *name) +{ + const struct mt7615_fw_trailer *hdr; + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, name, dev->mt76.dev); if (ret) return ret; @@ -500,8 +1748,10 @@ static int mt7615_load_ram(struct mt7615_dev *dev) goto out; ret = mt7615_mcu_start_firmware(dev, 0, FW_START_WORKING_PDA_CR4); - if (ret) + if (ret) { dev_err(dev->mt76.dev, "Failed to start CR4 firmware\n"); + goto out; + } out: release_firmware(fw); @@ -509,6 +1759,17 @@ out: return ret; } +static int mt7615_load_ram(struct mt7615_dev *dev) +{ + int ret; + + ret = mt7615_load_n9(dev, MT7615_FIRMWARE_N9); + if (ret) + return ret; + + return mt7615_load_cr4(dev, MT7615_FIRMWARE_CR4); +} + static int mt7615_load_firmware(struct mt7615_dev *dev) { int ret; @@ -521,7 +1782,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - ret = mt7615_load_patch(dev); + ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH); if (ret) return ret; @@ -536,7 +1797,164 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) return -EIO; } - mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + return 0; +} + +static int mt7622_load_firmware(struct mt7615_dev *dev) +{ + int ret; + u32 val; + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE); + if (val != FW_STATE_FW_DOWNLOAD) { + dev_err(dev->mt76.dev, "Firmware is not ready for download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH); + if (ret) + return ret; + + ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE, + FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE, + FW_STATE_NORMAL_TRX), 1500)) { + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + return 0; +} + +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl) +{ + struct { + u8 ctrl_val; + u8 pad[3]; + } data = { + .ctrl_val = ctrl + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_FW_LOG_2_HOST, + &data, sizeof(data), true); +} + +static int mt7663_load_n9(struct mt7615_dev *dev, const char *name) +{ + u32 offset = 0, override_addr = 0, flag = 0; + const struct mt7663_fw_trailer *hdr; + const struct mt7663_fw_buf *buf; + const struct firmware *fw; + const u8 *base_addr; + int i, ret; + + ret = request_firmware(&fw, name, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < FW_V3_COMMON_TAILER_SIZE) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7663_fw_trailer *)(fw->data + fw->size - + FW_V3_COMMON_TAILER_SIZE); + + dev_info(dev->mt76.dev, "N9 Firmware Version: %.10s, Build Time: %.15s\n", + hdr->fw_ver, hdr->build_date); + dev_info(dev->mt76.dev, "Region number: 0x%x\n", hdr->n_region); + + base_addr = fw->data + fw->size - FW_V3_COMMON_TAILER_SIZE; + for (i = 0; i < hdr->n_region; i++) { + u32 shift = (hdr->n_region - i) * FW_V3_REGION_TAILER_SIZE; + u32 len, addr, mode; + + dev_info(dev->mt76.dev, "Parsing tailer Region: %d\n", i); + + buf = (const struct mt7663_fw_buf *)(base_addr - shift); + mode = mt7615_mcu_gen_dl_mode(buf->feature_set, false); + addr = le32_to_cpu(buf->img_dest_addr); + len = le32_to_cpu(buf->img_size); + + ret = mt7615_mcu_init_download(dev, addr, len, mode); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7615_mcu_send_firmware(dev, fw->data + offset, len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware\n"); + goto out; + } + + offset += le32_to_cpu(buf->img_size); + if (buf->feature_set & DL_MODE_VALID_RAM_ENTRY) { + override_addr = le32_to_cpu(buf->img_dest_addr); + dev_info(dev->mt76.dev, "Region %d, override_addr = 0x%08x\n", + i, override_addr); + } + } + + if (is_mt7663(&dev->mt76)) { + flag |= FW_START_DLYCAL; + if (override_addr) + flag |= FW_START_OVERRIDE; + + dev_info(dev->mt76.dev, "override_addr = 0x%08x, option = %d\n", + override_addr, flag); + } + + ret = mt7615_mcu_start_firmware(dev, override_addr, flag); + if (ret) + dev_err(dev->mt76.dev, "Failed to start N9 firmware\n"); + +out: + release_firmware(fw); + + return ret; +} + +static int mt7663_load_firmware(struct mt7615_dev *dev) +{ + int ret; + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); + + ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY); + if (ret) { + dev_dbg(dev->mt76.dev, "Firmware is already download\n"); + return -EIO; + } + + ret = mt7615_load_patch(dev, MT7663_PATCH_ADDRESS, MT7663_ROM_PATCH); + if (ret) + return ret; + + dev->fw_ver = MT7615_FIRMWARE_V3; + dev->mcu_ops = &uni_update_ops; + + ret = mt7663_load_n9(dev, MT7663_FIRMWARE_N9); + if (ret) + return ret; + + if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY, + MT_TOP_MISC2_FW_N9_RDY, 1500)) { + ret = mt76_get_field(dev, MT_CONN_ON_MISC, + MT7663_TOP_MISC2_FW_STATE); + dev_err(dev->mt76.dev, "Timeout for initializing firmware\n"); + return -EIO; + } + + mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH); dev_dbg(dev->mt76.dev, "Firmware init done\n"); @@ -546,6 +1964,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev) int mt7615_mcu_init(struct mt7615_dev *dev) { static const struct mt76_mcu_ops mt7615_mcu_ops = { + .mcu_skb_send_msg = mt7615_mcu_send_message, .mcu_send_msg = mt7615_mcu_msg_send, .mcu_restart = mt7615_mcu_restart, }; @@ -557,11 +1976,24 @@ int mt7615_mcu_init(struct mt7615_dev *dev) if (ret) return ret; - ret = mt7615_load_firmware(dev); + switch (mt76_chip(&dev->mt76)) { + case 0x7622: + ret = mt7622_load_firmware(dev); + break; + case 0x7663: + ret = mt7663_load_firmware(dev); + break; + default: + ret = mt7615_load_firmware(dev); + break; + } if (ret) return ret; - set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); + mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false); + dev_dbg(dev->mt76.dev, "Firmware init done\n"); + set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); + mt7615_mcu_fw_log_2_host(dev, 0); return 0; } @@ -569,55 +2001,70 @@ int mt7615_mcu_init(struct mt7615_dev *dev) void mt7615_mcu_exit(struct mt7615_dev *dev) { __mt76_mcu_restart(&dev->mt76); - mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN); - skb_queue_purge(&dev->mt76.mmio.mcu.res_q); + mt7615_firmware_own(dev); + skb_queue_purge(&dev->mt76.mcu.res_q); } int mt7615_mcu_set_eeprom(struct mt7615_dev *dev) { struct { u8 buffer_mode; - u8 pad; - u16 len; + u8 content_format; + __le16 len; } __packed req_hdr = { .buffer_mode = 1, - .len = __MT_EE_MAX - MT_EE_NIC_CONF_0, }; - int ret, len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; - u8 *req, *eep = (u8 *)dev->mt76.eeprom.data; + u8 *eep = (u8 *)dev->mt76.eeprom.data; + struct sk_buff *skb; + int eep_len, offset; - req = kzalloc(len, GFP_KERNEL); - if (!req) - return -ENOMEM; + switch (mt76_chip(&dev->mt76)) { + case 0x7622: + eep_len = MT7622_EE_MAX - MT_EE_NIC_CONF_0; + offset = MT_EE_NIC_CONF_0; + break; + case 0x7663: + eep_len = MT7663_EE_MAX - MT_EE_CHIP_ID; + req_hdr.content_format = 1; + offset = MT_EE_CHIP_ID; + break; + default: + eep_len = MT7615_EE_MAX - MT_EE_NIC_CONF_0; + offset = MT_EE_NIC_CONF_0; + break; + } - memcpy(req, &req_hdr, sizeof(req_hdr)); - memcpy(req + sizeof(req_hdr), eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); + req_hdr.len = cpu_to_le16(eep_len); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE, - req, len, true); - kfree(req); + skb = mt7615_mcu_msg_alloc(NULL, sizeof(req_hdr) + eep_len); + if (!skb) + return -ENOMEM; - return ret; + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + skb_put_data(skb, eep + offset, eep_len); + + return __mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD_EFUSE_BUFFER_MODE, true); } -int mt7615_mcu_init_mac(struct mt7615_dev *dev) +int mt7615_mcu_set_mac_enable(struct mt7615_dev *dev, int band, bool enable) { struct { u8 enable; u8 band; u8 rsv[2]; } __packed req = { - .enable = 1, - .band = 0, + .enable = enable, + .band = band, }; return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_MAC_INIT_CTRL, &req, sizeof(req), true); } -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) +int mt7615_mcu_set_rts_thresh(struct mt7615_phy *phy, u32 val) { + struct mt7615_dev *dev = phy->dev; struct { u8 prot_idx; u8 band; @@ -626,7 +2073,7 @@ int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val) __le32 pkt_thresh; } __packed req = { .prot_idx = 1, - .band = 0, + .band = phy != &dev->phy, .len_thresh = cpu_to_le32(val), .pkt_thresh = cpu_to_le32(0x2), }; @@ -672,329 +2119,62 @@ int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, &req, sizeof(req), true); } -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter) +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev) { -#define ENTER_PM_STATE 1 -#define EXIT_PM_STATE 2 - struct { - u8 pm_number; - u8 pm_state; - u8 bssid[ETH_ALEN]; - u8 dtim_period; - u8 wlan_idx; - __le16 bcn_interval; - __le32 aid; - __le32 rx_filter; - u8 band_idx; - u8 rsv[3]; - __le32 feature; - u8 omac_idx; - u8 wmm_idx; - u8 bcn_loss_cnt; - u8 bcn_sp_duration; - } __packed req = { - .pm_number = 5, - .pm_state = (enter) ? ENTER_PM_STATE : EXIT_PM_STATE, - .band_idx = 0, + struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); + struct dbdc_entry { + u8 type; + u8 index; + u8 band; + u8 _rsv; }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_PM_STATE_CTRL, - &req, sizeof(req), true); -} - -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct { - struct req_hdr { - u8 omac_idx; - u8 band_idx; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv[3]; - } __packed hdr; - struct req_tlv { - __le16 tag; - __le16 len; - u8 active; - u8 band_idx; - u8 omac_addr[ETH_ALEN]; - } __packed tlv; - } data = { - .hdr = { - .omac_idx = mvif->omac_idx, - .band_idx = mvif->band_idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - }, - .tlv = { - .tag = cpu_to_le16(DEV_INFO_ACTIVE), - .len = cpu_to_le16(sizeof(struct req_tlv)), - .active = enable, - .band_idx = mvif->band_idx, - }, + u8 enable; + u8 num; + u8 _rsv[2]; + struct dbdc_entry entry[64]; + } req = { + .enable = !!ext_phy, }; + int i; - memcpy(data.tlv.omac_addr, vif->addr, ETH_ALEN); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DEV_INFO_UPDATE, - &data, sizeof(data), true); -} - -static void -mt7615_mcu_bss_info_omac_header(struct mt7615_vif *mvif, u8 *data, - u32 conn_type) -{ - struct bss_info_omac *hdr = (struct bss_info_omac *)data; - u8 idx; - - idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx; - hdr->tag = cpu_to_le16(BSS_INFO_OMAC); - hdr->len = cpu_to_le16(sizeof(struct bss_info_omac)); - hdr->hw_bss_idx = idx; - hdr->omac_idx = mvif->omac_idx; - hdr->band_idx = mvif->band_idx; - hdr->conn_type = cpu_to_le32(conn_type); -} - -static void -mt7615_mcu_bss_info_basic_header(struct ieee80211_vif *vif, u8 *data, - u32 net_type, u8 tx_wlan_idx, - bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct bss_info_basic *hdr = (struct bss_info_basic *)data; - - hdr->tag = cpu_to_le16(BSS_INFO_BASIC); - hdr->len = cpu_to_le16(sizeof(struct bss_info_basic)); - hdr->network_type = cpu_to_le32(net_type); - hdr->active = enable; - hdr->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int); - memcpy(hdr->bssid, vif->bss_conf.bssid, ETH_ALEN); - hdr->wmm_idx = mvif->wmm_idx; - hdr->dtim_period = vif->bss_conf.dtim_period; - hdr->bmc_tx_wlan_idx = tx_wlan_idx; -} - -static void -mt7615_mcu_bss_info_ext_header(struct mt7615_vif *mvif, u8 *data) -{ -/* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ -#define BCN_TX_ESTIMATE_TIME (4096 + 20) - struct bss_info_ext_bss *hdr = (struct bss_info_ext_bss *)data; - int ext_bss_idx, tsf_offset; - - ext_bss_idx = mvif->omac_idx - EXT_BSSID_START; - if (ext_bss_idx < 0) - return; - - hdr->tag = cpu_to_le16(BSS_INFO_EXT_BSS); - hdr->len = cpu_to_le16(sizeof(struct bss_info_ext_bss)); - tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME; - hdr->mbss_tsf_offset = cpu_to_le32(tsf_offset); -} - -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, int en) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct req_hdr { - u8 bss_idx; - u8 rsv0; - __le16 tlv_num; - u8 is_tlv_append; - u8 rsv1[3]; - } __packed; - int len = sizeof(struct req_hdr) + sizeof(struct bss_info_basic); - int ret, i, features = BIT(BSS_INFO_BASIC), ntlv = 1; - u32 conn_type = 0, net_type = NETWORK_INFRA; - u8 *buf, *data, tx_wlan_idx = 0; - struct req_hdr *hdr; - - if (en) { - len += sizeof(struct bss_info_omac); - features |= BIT(BSS_INFO_OMAC); - if (mvif->omac_idx > EXT_BSSID_START) { - len += sizeof(struct bss_info_ext_bss); - features |= BIT(BSS_INFO_EXT_BSS); - ntlv++; - } - ntlv++; - } - - switch (vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - tx_wlan_idx = mvif->sta.wcid.idx; - conn_type = CONNECTION_INFRA_AP; - break; - case NL80211_IFTYPE_STATION: { - /* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */ - if (en) { - struct ieee80211_sta *sta; - struct mt7615_sta *msta; - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (!sta) { - rcu_read_unlock(); - return -EINVAL; - } - - msta = (struct mt7615_sta *)sta->drv_priv; - tx_wlan_idx = msta->wcid.idx; - rcu_read_unlock(); - } - conn_type = CONNECTION_INFRA_STA; - break; - } - case NL80211_IFTYPE_ADHOC: - conn_type = CONNECTION_IBSS_ADHOC; - tx_wlan_idx = mvif->sta.wcid.idx; - net_type = NETWORK_IBSS; - break; - default: - WARN_ON(1); - break; - } - - buf = kzalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; + if (!ext_phy) + goto out; - hdr = (struct req_hdr *)buf; - hdr->bss_idx = mvif->idx; - hdr->tlv_num = cpu_to_le16(ntlv); - hdr->is_tlv_append = 1; +#define ADD_DBDC_ENTRY(_type, _idx, _band) \ + do { \ + req.entry[req.num].type = _type; \ + req.entry[req.num].index = _idx; \ + req.entry[req.num++].band = _band; \ + } while (0) - data = buf + sizeof(*hdr); - for (i = 0; i < BSS_INFO_MAX_NUM; i++) { - int tag = ffs(features & BIT(i)) - 1; + for (i = 0; i < 4; i++) { + bool band = !!(ext_phy->omac_mask & BIT(i)); - switch (tag) { - case BSS_INFO_OMAC: - mt7615_mcu_bss_info_omac_header(mvif, data, - conn_type); - data += sizeof(struct bss_info_omac); - break; - case BSS_INFO_BASIC: - mt7615_mcu_bss_info_basic_header(vif, data, net_type, - tx_wlan_idx, en); - data += sizeof(struct bss_info_basic); - break; - case BSS_INFO_EXT_BSS: - mt7615_mcu_bss_info_ext_header(mvif, data); - data += sizeof(struct bss_info_ext_bss); - break; - default: - break; - } + ADD_DBDC_ENTRY(DBDC_TYPE_BSS, i, band); } - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BSS_INFO_UPDATE, - buf, len, true); - kfree(buf); - - return ret; -} - -static int -mt7615_mcu_add_wtbl_bmc(struct mt7615_dev *dev, - struct mt7615_vif *mvif) -{ - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = 0xe, - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = 1, - .rca2 = 1, - .rv = 1, - }, - }; - eth_broadcast_addr(req.g_wtbl.peer_addr); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} - -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + for (i = 0; i < 14; i++) { + bool band = !!(ext_phy->omac_mask & BIT(0x11 + i)); - if (!enable) { - struct wtbl_req_hdr req = { - .wlan_idx = mvif->sta.wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); + ADD_DBDC_ENTRY(DBDC_TYPE_MBSS, i, band); } - return mt7615_mcu_add_wtbl_bmc(dev, mvif); -} + ADD_DBDC_ENTRY(DBDC_TYPE_MU, 0, 1); -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_generic g_wtbl; - struct wtbl_rx rx_wtbl; - } req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - .tlv_num = cpu_to_le16(2), - }, - .g_wtbl = { - .tag = cpu_to_le16(WTBL_GENERIC), - .len = cpu_to_le16(sizeof(struct wtbl_generic)), - .muar_idx = mvif->omac_idx, - .qos = sta->wme, - .partial_aid = cpu_to_le16(sta->aid), - }, - .rx_wtbl = { - .tag = cpu_to_le16(WTBL_RX), - .len = cpu_to_le16(sizeof(struct wtbl_rx)), - .rca1 = vif->type != NL80211_IFTYPE_AP, - .rca2 = 1, - .rv = 1, - }, - }; - memcpy(req.g_wtbl.peer_addr, sta->addr, ETH_ALEN); + for (i = 0; i < 3; i++) + ADD_DBDC_ENTRY(DBDC_TYPE_BF, i, 1); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &req, sizeof(req), true); -} + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 1, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 2, 1); + ADD_DBDC_ENTRY(DBDC_TYPE_WMM, 3, 1); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct wtbl_req_hdr req = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_RESET_AND_SET, - }; + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 0, 0); + ADD_DBDC_ENTRY(DBDC_TYPE_MGMT, 1, 1); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, +out: + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_DBDC_CTRL, &req, sizeof(req), true); } @@ -1008,238 +2188,72 @@ int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev) &req, sizeof(req), true); } -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en) +int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, + enum mt7615_rdd_cmd cmd, u8 index, + u8 rx_sel, u8 val) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct { - struct sta_req_hdr hdr; - struct sta_rec_basic basic; + u8 ctrl; + u8 rdd_idx; + u8 rdd_rx_sel; + u8 val; + u8 rsv[4]; } req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = mvif->sta.wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .basic = { - .tag = cpu_to_le16(STA_REC_BASIC), - .len = cpu_to_le16(sizeof(struct sta_rec_basic)), - .conn_type = cpu_to_le32(CONNECTION_INFRA_BC), - }, + .ctrl = cmd, + .rdd_idx = index, + .rdd_rx_sel = rx_sel, + .val = val, }; - eth_broadcast_addr(req.basic.peer_addr); - - if (en) { - req.basic.conn_state = CONN_STATE_PORT_SECURE; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | - EXTRA_INFO_NEW); - } else { - req.basic.conn_state = CONN_STATE_DISCONNECT; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - } - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, &req, sizeof(req), true); } -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en) +int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct { - struct sta_req_hdr hdr; - struct sta_rec_basic basic; + u16 tag; + u16 min_lpn; } req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .basic = { - .tag = cpu_to_le16(STA_REC_BASIC), - .len = cpu_to_le16(sizeof(struct sta_rec_basic)), - .qos = sta->wme, - .aid = cpu_to_le16(sta->aid), - }, + .tag = 0x1, + .min_lpn = val, }; - memcpy(req.basic.peer_addr, sta->addr, ETH_ALEN); - switch (vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA); - break; - case NL80211_IFTYPE_STATION: - req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP); - break; - case NL80211_IFTYPE_ADHOC: - req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC); - break; - default: - WARN_ON(1); - break; - } - - if (en) { - req.basic.conn_state = CONN_STATE_PORT_SECURE; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER | - EXTRA_INFO_NEW); - } else { - req.basic.conn_state = CONN_STATE_DISCONNECT; - req.basic.extra_info = cpu_to_le16(EXTRA_INFO_VER); - } - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, sizeof(req), true); } -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en) +int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, + const struct mt7615_dfs_pulse *pulse) { - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid = &dev->mt76.global_wcid; - struct ieee80211_mutable_offsets offs; - struct req { - u8 omac_idx; - u8 enable; - u8 wlan_idx; - u8 band_idx; - u8 pkt_type; - u8 need_pre_tbtt_int; - __le16 csa_ie_pos; - __le16 pkt_len; - __le16 tim_ie_pos; - u8 pkt[512]; - u8 csa_cnt; - /* bss color change */ - u8 bcc_cnt; - __le16 bcc_ie_pos; - } __packed req = { - .omac_idx = mvif->omac_idx, - .enable = en, - .wlan_idx = wcid->idx, - .band_idx = mvif->band_idx, - }; - struct sk_buff *skb; - - skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); - if (!skb) - return -EINVAL; - - if (skb->len > 512 - MT_TXD_SIZE) { - dev_err(dev->mt76.dev, "Bcn size limit exceed\n"); - dev_kfree_skb(skb); - return -EINVAL; - } - - mt7615_mac_write_txwi(dev, (__le32 *)(req.pkt), skb, wcid, NULL, - 0, NULL); - memcpy(req.pkt + MT_TXD_SIZE, skb->data, skb->len); - req.pkt_len = cpu_to_le16(MT_TXD_SIZE + skb->len); - req.tim_ie_pos = cpu_to_le16(MT_TXD_SIZE + offs.tim_offset); - if (offs.csa_counter_offs[0]) { - u16 csa_offs; - - csa_offs = MT_TXD_SIZE + offs.csa_counter_offs[0] - 4; - req.csa_ie_pos = cpu_to_le16(csa_offs); - req.csa_cnt = skb->data[offs.csa_counter_offs[0]]; - } - dev_kfree_skb(skb); - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, - &req, sizeof(req), true); -} - -int mt7615_mcu_set_tx_power(struct mt7615_dev *dev) -{ - int i, ret, n_chains = hweight8(dev->mt76.antenna_mask); - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; - int freq = chandef->center_freq1, len, target_chains; - u8 *req, *data, *eep = (u8 *)dev->mt76.eeprom.data; - enum nl80211_band band = chandef->chan->band; - struct ieee80211_hw *hw = mt76_hw(dev); struct { - u8 center_chan; - u8 dbdc_idx; - u8 band; - u8 rsv; - } __packed req_hdr = { - .center_chan = ieee80211_frequency_to_channel(freq), - .band = band, + u16 tag; + struct mt7615_dfs_pulse pulse; + } req = { + .tag = 0x3, }; - s8 tx_power; - - len = sizeof(req_hdr) + __MT_EE_MAX - MT_EE_NIC_CONF_0; - req = kzalloc(len, GFP_KERNEL); - if (!req) - return -ENOMEM; - memcpy(req, &req_hdr, sizeof(req_hdr)); - data = req + sizeof(req_hdr); - memcpy(data, eep + MT_EE_NIC_CONF_0, - __MT_EE_MAX - MT_EE_NIC_CONF_0); + memcpy(&req.pulse, pulse, sizeof(*pulse)); - tx_power = hw->conf.power_level * 2; - switch (n_chains) { - case 4: - tx_power -= 12; - break; - case 3: - tx_power -= 8; - break; - case 2: - tx_power -= 6; - break; - default: - break; - } - tx_power = max_t(s8, tx_power, 0); - dev->mt76.txpower_cur = tx_power; - - target_chains = mt7615_ext_pa_enabled(dev, band) ? 1 : n_chains; - for (i = 0; i < target_chains; i++) { - int index = -MT_EE_NIC_CONF_0; - - ret = mt7615_eeprom_get_power_index(dev, chandef->chan, i); - if (ret < 0) - goto out; - - index += ret; - data[index] = min_t(u8, data[index], tx_power); - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL, - req, len, true); -out: - kfree(req); - - return ret; + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, + &req, sizeof(req), true); } -int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, - enum mt7615_rdd_cmd cmd, u8 index, - u8 rx_sel, u8 val) +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern) { struct { - u8 ctrl; - u8 rdd_idx; - u8 rdd_rx_sel; - u8 val; - u8 rsv[4]; + u16 tag; + u16 radar_type; + struct mt7615_dfs_pattern pattern; } req = { - .ctrl = cmd, - .rdd_idx = index, - .rdd_rx_sel = rx_sel, - .val = val, + .tag = 0x2, + .radar_type = index, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_CTRL, + memcpy(&req.pattern, pattern, sizeof(*pattern)); + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RDD_TH, &req, sizeof(req), true); } @@ -1274,9 +2288,35 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev) &req, sizeof(req), false); } -int mt7615_mcu_set_channel(struct mt7615_dev *dev) +static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) { - struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct mt76_phy *mphy = phy->mt76; + struct ieee80211_hw *hw = mphy->hw; + int n_chains = hweight8(mphy->antenna_mask); + int tx_power; + int i; + + tx_power = hw->conf.power_level * 2 - + mt76_tx_power_nss_delta(n_chains); + mphy->txpower_cur = tx_power; + + for (i = 0; i < MT_SKU_1SS_DELTA; i++) + sku[i] = tx_power; + + for (i = 0; i < 4; i++) { + int delta = 0; + + if (i < n_chains - 1) + delta = mt76_tx_power_nss_delta(n_chains) - + mt76_tx_power_nss_delta(i + 1); + sku[MT_SKU_1SS_DELTA + i] = delta; + } +} + +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) +{ + struct mt7615_dev *dev = phy->dev; + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2; struct { u8 control_chan; @@ -1299,11 +2339,10 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) } req = { .control_chan = chandef->chan->hw_value, .center_chan = ieee80211_frequency_to_channel(freq1), - .tx_streams = (dev->mt76.chainmask >> 8) & 0xf, - .rx_streams_mask = dev->mt76.antenna_mask, + .tx_streams = hweight8(phy->mt76->antenna_mask), + .rx_streams_mask = phy->chainmask, .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - int ret; if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; @@ -1313,7 +2352,9 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) else req.switch_reason = CH_SWITCH_NORMAL; - switch (dev->mt76.chandef.width) { + req.band_idx = phy != &dev->phy; + + switch (chandef->width) { case NL80211_CHAN_WIDTH_40: req.bw = CMD_CBW_40MHZ; break; @@ -1338,278 +2379,39 @@ int mt7615_mcu_set_channel(struct mt7615_dev *dev) req.bw = CMD_CBW_20MHZ; break; } - memset(req.txpower_sku, 0x3f, 49); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH, - &req, sizeof(req), true); - if (ret) - return ret; + mt7615_mcu_set_txpower_sku(phy, req.txpower_sku); - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_RX_PATH, - &req, sizeof(req), true); + return __mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true); } -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct wtbl_req_hdr *wtbl_hdr; - struct sta_req_hdr *sta_hdr; - struct wtbl_raw *wtbl_raw; - struct sta_rec_ht *sta_ht; - struct wtbl_ht *wtbl_ht; - int buf_len, ret, ntlv = 2; - u32 msk, val = 0; - u8 *buf; - - buf = kzalloc(MT7615_WTBL_UPDATE_MAX_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wtbl_hdr = (struct wtbl_req_hdr *)buf; - wtbl_hdr->wlan_idx = msta->wcid.idx; - wtbl_hdr->operation = WTBL_SET; - buf_len = sizeof(*wtbl_hdr); - - /* ht basic */ - wtbl_ht = (struct wtbl_ht *)(buf + buf_len); - wtbl_ht->tag = cpu_to_le16(WTBL_HT); - wtbl_ht->len = cpu_to_le16(sizeof(*wtbl_ht)); - wtbl_ht->ht = 1; - wtbl_ht->ldpc = sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING; - wtbl_ht->af = sta->ht_cap.ampdu_factor; - wtbl_ht->mm = sta->ht_cap.ampdu_density; - buf_len += sizeof(*wtbl_ht); - - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - val |= MT_WTBL_W5_SHORT_GI_20; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - val |= MT_WTBL_W5_SHORT_GI_40; - - /* vht basic */ - if (sta->vht_cap.vht_supported) { - struct wtbl_vht *wtbl_vht; - - wtbl_vht = (struct wtbl_vht *)(buf + buf_len); - buf_len += sizeof(*wtbl_vht); - wtbl_vht->tag = cpu_to_le16(WTBL_VHT); - wtbl_vht->len = cpu_to_le16(sizeof(*wtbl_vht)); - wtbl_vht->ldpc = sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC; - wtbl_vht->vht = 1; - ntlv++; - - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80) - val |= MT_WTBL_W5_SHORT_GI_80; - if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160) - val |= MT_WTBL_W5_SHORT_GI_160; - } - - /* smps */ - if (sta->smps_mode == IEEE80211_SMPS_DYNAMIC) { - struct wtbl_smps *wtbl_smps; - - wtbl_smps = (struct wtbl_smps *)(buf + buf_len); - buf_len += sizeof(*wtbl_smps); - wtbl_smps->tag = cpu_to_le16(WTBL_SMPS); - wtbl_smps->len = cpu_to_le16(sizeof(*wtbl_smps)); - wtbl_smps->smps = 1; - ntlv++; - } - - /* sgi */ - msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 | - MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160; - - wtbl_raw = (struct wtbl_raw *)(buf + buf_len); - buf_len += sizeof(*wtbl_raw); - wtbl_raw->tag = cpu_to_le16(WTBL_RAW_DATA); - wtbl_raw->len = cpu_to_le16(sizeof(*wtbl_raw)); - wtbl_raw->wtbl_idx = 1; - wtbl_raw->dw = 5; - wtbl_raw->msk = cpu_to_le32(~msk); - wtbl_raw->val = cpu_to_le32(val); - - wtbl_hdr->tlv_num = cpu_to_le16(ntlv); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - buf, buf_len, true); - if (ret) - goto out; - - memset(buf, 0, MT7615_WTBL_UPDATE_MAX_SIZE); - - sta_hdr = (struct sta_req_hdr *)buf; - sta_hdr->bss_idx = mvif->idx; - sta_hdr->wlan_idx = msta->wcid.idx; - sta_hdr->is_tlv_append = 1; - ntlv = sta->vht_cap.vht_supported ? 2 : 1; - sta_hdr->tlv_num = cpu_to_le16(ntlv); - sta_hdr->muar_idx = mvif->omac_idx; - buf_len = sizeof(*sta_hdr); - - sta_ht = (struct sta_rec_ht *)(buf + buf_len); - sta_ht->tag = cpu_to_le16(STA_REC_HT); - sta_ht->len = cpu_to_le16(sizeof(*sta_ht)); - sta_ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); - buf_len += sizeof(*sta_ht); - - if (sta->vht_cap.vht_supported) { - struct sta_rec_vht *sta_vht; - - sta_vht = (struct sta_rec_vht *)(buf + buf_len); - buf_len += sizeof(*sta_vht); - sta_vht->tag = cpu_to_le16(STA_REC_VHT); - sta_vht->len = cpu_to_le16(sizeof(*sta_vht)); - sta_vht->vht_cap = cpu_to_le32(sta->vht_cap.cap); - sta_vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; - sta_vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map; - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - buf, buf_len, true); -out: - kfree(buf); - - return ret; -} - -int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add) -{ - struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; - struct mt7615_vif *mvif = msta->vif; - struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_ORIGINATOR, - .sn = add ? cpu_to_le16(params->ssn) : 0, - .ba_en = add, - }, - }; - struct { - struct sta_req_hdr hdr; - struct sta_rec_ba ba; - } sta_req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .ba = { - .tag = cpu_to_le16(STA_REC_BA), - .len = cpu_to_le16(sizeof(struct sta_rec_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_ORIGINATOR, - .amsdu = params->amsdu, - .ba_en = add << params->tid, - .ssn = cpu_to_le16(params->ssn), - .winsize = cpu_to_le16(params->buf_size), - }, - }; - int ret; - - if (add) { - u8 idx, ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 }; - - for (idx = 7; idx > 0; idx--) { - if (params->buf_size >= ba_range[idx]) - break; - } - - wtbl_req.ba.ba_winsize_idx = idx; - } - - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); - if (ret) - return ret; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); -} - -int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add) +int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) { - struct mt7615_sta *msta = (struct mt7615_sta *)params->sta->drv_priv; - struct mt7615_vif *mvif = msta->vif; struct { - struct wtbl_req_hdr hdr; - struct wtbl_ba ba; - } wtbl_req = { - .hdr = { - .wlan_idx = msta->wcid.idx, - .operation = WTBL_SET, - .tlv_num = cpu_to_le16(1), - }, - .ba = { - .tag = cpu_to_le16(WTBL_BA), - .len = cpu_to_le16(sizeof(struct wtbl_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_RECIPIENT, - .rst_ba_tid = params->tid, - .rst_ba_sel = RST_BA_MAC_TID_MATCH, - .rst_ba_sb = 1, - }, - }; - struct { - struct sta_req_hdr hdr; - struct sta_rec_ba ba; - } sta_req = { - .hdr = { - .bss_idx = mvif->idx, - .wlan_idx = msta->wcid.idx, - .tlv_num = cpu_to_le16(1), - .is_tlv_append = 1, - .muar_idx = mvif->omac_idx, - }, - .ba = { - .tag = cpu_to_le16(STA_REC_BA), - .len = cpu_to_le16(sizeof(struct sta_rec_ba)), - .tid = params->tid, - .ba_type = MT_BA_TYPE_RECIPIENT, - .amsdu = params->amsdu, - .ba_en = add << params->tid, - .ssn = cpu_to_le16(params->ssn), - .winsize = cpu_to_le16(params->buf_size), - }, + u8 action; + u8 rsv[3]; + } req = { + .action = index, }; - int ret; - - memcpy(wtbl_req.ba.peer_addr, params->sta->addr, ETH_ALEN); - ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_STA_REC_UPDATE, - &sta_req, sizeof(sta_req), true); - if (ret || !add) - return ret; - - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_WTBL_UPDATE, - &wtbl_req, sizeof(wtbl_req), true); + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, + sizeof(req), true); } -int mt7615_mcu_get_temperature(struct mt7615_dev *dev, int index) +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) { + struct mt7615_dev *dev = phy->dev; struct { - u8 action; - u8 rsv[3]; + u8 format_id; + u8 sku_enable; + u8 band_idx; + u8 rsv; } req = { - .action = index, + .format_id = 0, + .band_idx = phy != &dev->phy, + .sku_enable = enable, }; - return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_GET_TEMP, &req, + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TX_POWER_FEATURE_CTRL, &req, sizeof(req), true); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 1fd7dffa6eef..d1f7391472fc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -23,6 +23,57 @@ struct mt7615_mcu_txd { u32 reserved[5]; } __packed __aligned(4); +/** + * struct mt7615_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 mt7615_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_TARGET_ADDRESS_LEN = 0x01, @@ -45,6 +96,62 @@ enum { MCU_EXT_EVENT_CSA_NOTIFY = 0x4f, }; +enum { + MT_SKU_CCK_1_2 = 0, + MT_SKU_CCK_55_11, + MT_SKU_OFDM_6_9, + MT_SKU_OFDM_12_18, + MT_SKU_OFDM_24_36, + MT_SKU_OFDM_48, + MT_SKU_OFDM_54, + MT_SKU_HT20_0_8, + MT_SKU_HT20_32, + MT_SKU_HT20_1_2_9_10, + MT_SKU_HT20_3_4_11_12, + MT_SKU_HT20_5_13, + MT_SKU_HT20_6_14, + MT_SKU_HT20_7_15, + MT_SKU_HT40_0_8, + MT_SKU_HT40_32, + MT_SKU_HT40_1_2_9_10, + MT_SKU_HT40_3_4_11_12, + MT_SKU_HT40_5_13, + MT_SKU_HT40_6_14, + MT_SKU_HT40_7_15, + MT_SKU_VHT20_0, + MT_SKU_VHT20_1_2, + MT_SKU_VHT20_3_4, + MT_SKU_VHT20_5_6, + MT_SKU_VHT20_7, + MT_SKU_VHT20_8, + MT_SKU_VHT20_9, + MT_SKU_VHT40_0, + MT_SKU_VHT40_1_2, + MT_SKU_VHT40_3_4, + MT_SKU_VHT40_5_6, + MT_SKU_VHT40_7, + MT_SKU_VHT40_8, + MT_SKU_VHT40_9, + MT_SKU_VHT80_0, + MT_SKU_VHT80_1_2, + MT_SKU_VHT80_3_4, + MT_SKU_VHT80_5_6, + MT_SKU_VHT80_7, + MT_SKU_VHT80_8, + MT_SKU_VHT80_9, + MT_SKU_VHT160_0, + MT_SKU_VHT160_1_2, + MT_SKU_VHT160_3_4, + MT_SKU_VHT160_5_6, + MT_SKU_VHT160_7, + MT_SKU_VHT160_8, + MT_SKU_VHT160_9, + MT_SKU_1SS_DELTA, + MT_SKU_2SS_DELTA, + MT_SKU_3SS_DELTA, + MT_SKU_4SS_DELTA, +}; + struct mt7615_mcu_rxd { __le32 rxd[4]; @@ -60,6 +167,52 @@ struct mt7615_mcu_rxd { u8 s2d_index; }; +struct mt7615_mcu_rdd_report { + struct mt7615_mcu_rxd rxd; + + u8 idx; + u8 long_detected; + u8 constant_prf_detected; + u8 staggered_prf_detected; + u8 radar_type_idx; + u8 periodic_pulse_num; + u8 long_pulse_num; + u8 hw_pulse_num; + + u8 out_lpn; + u8 out_spn; + u8 out_crpn; + u8 out_crpw; + u8 out_crbn; + u8 out_stgpn; + u8 out_stgpw; + + u8 _rsv[2]; + + __le32 out_pri_const; + __le32 out_pri_stg[3]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } long_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + } periodic_pulse[32]; + + struct { + __le32 start; + __le16 pulse_width; + __le16 pulse_power; + u8 sc_pass; + u8 sw_reset; + } hw_pulse[32]; +}; + #define MCU_PQ_ID(p, q) (((p) << 15) | ((q) << 10)) #define MCU_PKT_ID 0xa0 @@ -77,22 +230,27 @@ enum { MCU_S2D_H2CN }; +#define MCU_FW_PREFIX BIT(31) +#define MCU_UNI_PREFIX BIT(30) +#define MCU_CMD_MASK ~(MCU_FW_PREFIX | MCU_UNI_PREFIX) + enum { - MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, - MCU_CMD_FW_START_REQ = 0x02, + 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 = 0x07, - MCU_CMD_PATCH_SEM_CONTROL = 0x10, + 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 = 0xEE, - MCU_CMD_RESTART_DL_REQ = 0xEF, + MCU_CMD_FW_SCATTER = MCU_FW_PREFIX | 0xEE, + MCU_CMD_RESTART_DL_REQ = MCU_FW_PREFIX | 0xEF, }; enum { 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, @@ -102,13 +260,33 @@ enum { MCU_EXT_CMD_WTBL_UPDATE = 0x32, MCU_EXT_CMD_SET_RDD_CTRL = 0x3a, MCU_EXT_CMD_PROTECT_CTRL = 0x3e, + MCU_EXT_CMD_DBDC_CTRL = 0x45, MCU_EXT_CMD_MAC_INIT_CTRL = 0x46, MCU_EXT_CMD_BCN_OFFLOAD = 0x49, MCU_EXT_CMD_SET_RX_PATH = 0x4e, + MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58, + 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, +}; + +#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_BCN_CONTENT = 7, +}; + +enum { PATCH_SEM_RELEASE = 0x0, PATCH_SEM_GET = 0x1 }; @@ -156,6 +334,23 @@ enum { DEV_INFO_MAX_NUM }; +enum { + DBDC_TYPE_WMM, + DBDC_TYPE_MGMT, + DBDC_TYPE_BSS, + DBDC_TYPE_MBSS, + DBDC_TYPE_REPEATER, + DBDC_TYPE_MU, + DBDC_TYPE_BF, + DBDC_TYPE_PTA, + __DBDC_TYPE_MAX, +}; + +struct tlv { + __le16 tag; + __le16 len; +} __packed; + struct bss_info_omac { __le16 tag; __le16 len; @@ -365,18 +560,28 @@ struct wtbl_raw { __le32 val; } __packed; -#define MT7615_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 MT7615_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 MT7615_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \ + sizeof(struct sta_rec_basic) + \ + sizeof(struct sta_rec_ht) + \ + sizeof(struct sta_rec_vht) + \ + sizeof(struct tlv) + \ + MT7615_WTBL_UPDATE_MAX_SIZE) + +#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ + sizeof(struct wtbl_ba)) enum { WTBL_GENERIC, @@ -399,6 +604,11 @@ enum { WTBL_MAX_NUM }; +struct sta_ntlv_hdr { + u8 rsv[2]; + __le16 tlv_num; +} __packed; + struct sta_req_hdr { u8 bss_idx; u8 wlan_idx; @@ -408,6 +618,15 @@ struct sta_req_hdr { 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; @@ -447,10 +666,6 @@ struct sta_rec_ba { __le16 winsize; } __packed; -#define MT7615_STA_REC_UPDATE_MAX_SIZE (sizeof(struct sta_rec_basic) + \ - sizeof(struct sta_rec_ht) + \ - sizeof(struct sta_rec_vht)) - enum { STA_REC_BASIC, STA_REC_RA, @@ -459,11 +674,12 @@ enum { STA_REC_BF, STA_REC_AMSDU, /* for CR4 */ STA_REC_BA, - STA_REC_RED, /* not used */ + 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 }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c new file mode 100644 index 000000000000..d2eff5442824 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -0,0 +1,174 @@ +#include <linux/kernel.h> +#include <linux/module.h> + +#include "mt7615.h" +#include "regs.h" +#include "mac.h" +#include "../trace.h" + +const u32 mt7615e_reg_map[] = { + [MT_TOP_CFG_BASE] = 0x01000, + [MT_HW_BASE] = 0x01000, + [MT_PCIE_REMAP_2] = 0x02504, + [MT_ARB_BASE] = 0x20c00, + [MT_HIF_BASE] = 0x04000, + [MT_CSR_BASE] = 0x07000, + [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_WTBL_BASE_ON] = 0x23000, + [MT_WTBL_BASE_OFF] = 0x23400, + [MT_LPON_BASE] = 0x24200, + [MT_MIB_BASE] = 0x24800, + [MT_WTBL_BASE_ADDR] = 0x30000, + [MT_PCIE_REMAP_BASE2] = 0x80000, + [MT_TOP_MISC_BASE] = 0xc0000, + [MT_EFUSE_ADDR_BASE] = 0x81070000, +}; + +const u32 mt7663e_reg_map[] = { + [MT_TOP_CFG_BASE] = 0x01000, + [MT_HW_BASE] = 0x02000, + [MT_DMA_SHDL_BASE] = 0x06000, + [MT_PCIE_REMAP_2] = 0x0700c, + [MT_ARB_BASE] = 0x20c00, + [MT_HIF_BASE] = 0x04000, + [MT_CSR_BASE] = 0x07000, + [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_WTBL_BASE_ON] = 0x29000, + [MT_WTBL_BASE_OFF] = 0x29800, + [MT_LPON_BASE] = 0x2b000, + [MT_MIB_BASE] = 0x2d000, + [MT_WTBL_BASE_ADDR] = 0x30000, + [MT_PCIE_REMAP_BASE2] = 0x90000, + [MT_TOP_MISC_BASE] = 0xc0000, + [MT_EFUSE_ADDR_BASE] = 0x78011000, +}; + +u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) +{ + u32 base, offset; + + if (is_mt7663(&dev->mt76)) { + base = addr & MT7663_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT7663_MCU_PCIE_REMAP_2_OFFSET; + } else { + base = addr & MT_MCU_PCIE_REMAP_2_BASE; + offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; + } + mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} + +static void +mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); + + mt7615_irq_enable(dev, MT_INT_RX_DONE(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); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) + return IRQ_NONE; + + 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); + napi_schedule(&dev->mt76.tx_napi); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt7615_irq_disable(dev, 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)); + napi_schedule(&dev->mt76.napi[1]); + } + + if (intr & MT_INT_MCU_CMD) { + u32 val = mt76_rr(dev, MT_MCU_CMD); + + if (val & MT_MCU_CMD_ERROR_MASK) { + dev->reset_state = val; + ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + wake_up(&dev->reset_wait); + } + } + + return IRQ_HANDLED; +} + +int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, + int irq, const u32 *map) +{ + static const struct mt76_driver_ops drv_ops = { + /* txwi_size = txd size + txp size */ + .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), + .drv_flags = MT_DRV_TXWI_NO_FREE, + .survey_flags = SURVEY_INFO_TIME_TX | + SURVEY_INFO_TIME_RX | + SURVEY_INFO_TIME_BSS_RX, + .tx_prepare_skb = mt7615_tx_prepare_skb, + .tx_complete_skb = mt7615_tx_complete_skb, + .rx_skb = mt7615_queue_rx_skb, + .rx_poll_complete = mt7615_rx_poll_complete, + .sta_ps = mt7615_sta_ps, + .sta_add = mt7615_mac_sta_add, + .sta_remove = mt7615_mac_sta_remove, + .update_survey = mt7615_update_channel, + }; + struct mt7615_dev *dev; + struct mt76_dev *mdev; + int ret; + + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt7615_ops, &drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7615_dev, mt76); + mt76_mmio_init(&dev->mt76, mem_base); + + dev->reg_map = map; + 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); + + ret = devm_request_irq(mdev->dev, irq, mt7615_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + if (is_mt7663(mdev)) + mt76_wr(dev, MT_PCIE_IRQ_ENABLE, 1); + + ret = mt7615_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 21486831172c..676ca622c35a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -6,6 +6,7 @@ #include <linux/interrupt.h> #include <linux/ktime.h> +#include <linux/regmap.h> #include "../mt76.h" #include "regs.h" @@ -17,9 +18,11 @@ MT7615_MAX_INTERFACES) #define MT7615_WATCHDOG_TIME (HZ / 10) +#define MT7615_RESET_TIMEOUT (30 * HZ) #define MT7615_RATE_RETRY 2 #define MT7615_TX_RING_SIZE 1024 +#define MT7615_TX_MGMT_RING_SIZE 128 #define MT7615_TX_MCU_RING_SIZE 128 #define MT7615_TX_FWDL_RING_SIZE 128 @@ -30,14 +33,34 @@ #define MT7615_FIRMWARE_N9 "mediatek/mt7615_n9.bin" #define MT7615_ROM_PATCH "mediatek/mt7615_rom_patch.bin" +#define MT7622_FIRMWARE_N9 "mediatek/mt7622_n9.bin" +#define MT7622_ROM_PATCH "mediatek/mt7622_rom_patch.bin" + +#define MT7615_FIRMWARE_V1 1 +#define MT7615_FIRMWARE_V2 2 +#define MT7615_FIRMWARE_V3 3 + +#define MT7663_ROM_PATCH "mediatek/mt7663pr2h_v3.bin" +#define MT7663_FIRMWARE_N9 "mediatek/mt7663_n9_v3.bin" + #define MT7615_EEPROM_SIZE 1024 #define MT7615_TOKEN_SIZE 4096 #define MT_FRAC_SCALE 12 #define MT_FRAC(val, div) (((val) << MT_FRAC_SCALE) / (div)) +#define MT_CHFREQ_VALID BIT(7) +#define MT_CHFREQ_DBDC_IDX BIT(6) +#define MT_CHFREQ_SEQ GENMASK(5, 0) + +#define MT7615_BAR_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7615_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ +#define MT7615_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + struct mt7615_vif; struct mt7615_sta; +struct mt7615_dfs_pulse; +struct mt7615_dfs_pattern; enum mt7615_hw_txq_id { MT7615_TXQ_MAIN, @@ -46,6 +69,16 @@ enum mt7615_hw_txq_id { MT7615_TXQ_FWDL, }; +enum mt7622_hw_txq_id { + MT7622_TXQ_AC0, + MT7622_TXQ_AC1, + MT7622_TXQ_AC2, + MT7622_TXQ_FWDL = MT7615_TXQ_FWDL, + MT7622_TXQ_AC3, + MT7622_TXQ_MGMT, + MT7622_TXQ_MCU = 15, +}; + struct mt7615_rate_set { struct ieee80211_tx_rate probe_rate; struct ieee80211_tx_rate rates[4]; @@ -79,12 +112,90 @@ struct mt7615_vif { struct mt7615_sta sta; }; +struct mib_stats { + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; +}; + +struct mt7615_phy { + struct mt76_phy *mt76; + struct mt7615_dev *dev; + + u32 rxfilter; + u32 omac_mask; + + u16 noise; + + unsigned long last_cca_adj; + int false_cca_ofdm, false_cca_cck; + s8 ofdm_sensitivity; + s8 cck_sensitivity; + + u16 chainmask; + + s16 coverage_class; + u8 slottime; + + u8 chfreq; + u8 rdd_state; + int dfs_state; + + __le32 rx_ampdu_ts; + u32 ampdu_ref; + + struct mib_stats mib; +}; + +#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(dev, ...) (dev)->mcu_ops->add_bss_info((dev), __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__) +struct mt7615_mcu_ops { + int (*add_tx_ba)(struct mt7615_dev *dev, + struct ieee80211_ampdu_params *params, + bool enable); + 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, + struct ieee80211_sta *sta, bool enable); + int (*add_dev_info)(struct mt7615_dev *dev, + struct ieee80211_vif *vif, bool enable); + int (*add_bss_info)(struct mt7615_dev *dev, struct ieee80211_vif *vif, + bool enable); + int (*add_beacon_offload)(struct mt7615_dev *dev, + struct ieee80211_hw *hw, + struct ieee80211_vif *vif, bool enable); + int (*set_pm_state)(struct mt7615_dev *dev, int band, int state); +}; + struct mt7615_dev { - struct mt76_dev mt76; /* must be first */ + union { /* must be first */ + struct mt76_dev mt76; + struct mt76_phy mphy; + }; + + struct mt7615_phy phy; u32 vif_mask; u32 omac_mask; - __le32 rx_ampdu_ts; + u16 chainmask; + + const struct mt7615_mcu_ops *mcu_ops; + struct regmap *infracfg; + const u32 *reg_map; + + struct work_struct mcu_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; @@ -96,17 +207,15 @@ struct mt7615_dev { s16 power; } radar_pattern; u32 hw_pattern; - int dfs_state; - int false_cca_ofdm, false_cca_cck; - unsigned long last_cca_adj; u8 mac_work_count; - s8 ofdm_sensitivity; - s8 cck_sensitivity; bool scs_en; + bool fw_debug; spinlock_t token_lock; struct idr token; + + u8 fw_ver; }; enum { @@ -135,11 +244,6 @@ enum { }; enum { - MT_HW_RDD0, - MT_HW_RDD1, -}; - -enum { MT_RX_SEL0, MT_RX_SEL1, }; @@ -158,13 +262,57 @@ enum mt7615_rdd_cmd { RDD_RESUME_BF, }; +static inline struct mt7615_phy * +mt7615_hw_phy(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return phy->priv; +} + +static inline struct mt7615_dev * +mt7615_hw_dev(struct ieee80211_hw *hw) +{ + struct mt76_phy *phy = hw->priv; + + return container_of(phy->dev, struct mt7615_dev, mt76); +} + +static inline struct mt7615_phy * +mt7615_ext_phy(struct mt7615_dev *dev) +{ + struct mt76_phy *phy = dev->mt76.phy2; + + if (!phy) + return NULL; + + return phy->priv; +} + extern const struct ieee80211_ops mt7615_ops; +extern const u32 mt7615e_reg_map[__MT_BASE_MAX]; +extern const u32 mt7663e_reg_map[__MT_BASE_MAX]; extern struct pci_driver mt7615_pci_driver; +extern struct platform_driver mt7622_wmac_driver; +#ifdef CONFIG_MT7622_WMAC +int mt7622_wmac_init(struct mt7615_dev *dev); +#else +static inline int mt7622_wmac_init(struct mt7615_dev *dev) +{ + return 0; +} +#endif + +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_init_device(struct mt7615_dev *dev); int mt7615_register_device(struct mt7615_dev *dev); void mt7615_unregister_device(struct mt7615_dev *dev); +int mt7615_register_ext_phy(struct mt7615_dev *dev); +void mt7615_unregister_ext_phy(struct mt7615_dev *dev); int mt7615_eeprom_init(struct mt7615_dev *dev); int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, struct ieee80211_channel *chan, @@ -172,58 +320,37 @@ int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, int mt7615_dma_init(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); -int mt7615_mcu_set_dev_info(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool enable); -int mt7615_mcu_set_bss_info(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en); -void mt7615_mac_set_rates(struct mt7615_dev *dev, struct mt7615_sta *sta, +bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); +void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct ieee80211_tx_rate *probe_rate, struct ieee80211_tx_rate *rates); -int mt7615_mcu_wtbl_bmc(struct mt7615_dev *dev, struct ieee80211_vif *vif, - bool enable); -int mt7615_mcu_add_wtbl(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -int mt7615_mcu_del_wtbl(struct mt7615_dev *dev, struct ieee80211_sta *sta); int mt7615_mcu_del_wtbl_all(struct mt7615_dev *dev); -int mt7615_mcu_set_sta_rec_bmc(struct mt7615_dev *dev, - struct ieee80211_vif *vif, bool en); -int mt7615_mcu_set_sta_rec(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, bool en); -int mt7615_mcu_set_bcn(struct mt7615_dev *dev, struct ieee80211_vif *vif, - int en); -int mt7615_mcu_set_channel(struct mt7615_dev *dev); +int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd); int mt7615_mcu_set_wmm(struct mt7615_dev *dev, u8 queue, const struct ieee80211_tx_queue_params *params); -int mt7615_mcu_set_tx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add); -int mt7615_mcu_set_rx_ba(struct mt7615_dev *dev, - struct ieee80211_ampdu_params *params, - bool add); -int mt7615_mcu_set_ht_cap(struct mt7615_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mcu_rdd_cmd(struct mt7615_dev *dev, enum mt7615_rdd_cmd cmd, u8 index, u8 rx_sel, u8 val); -int mt7615_dfs_start_radar_detector(struct mt7615_dev *dev); -int mt7615_dfs_stop_radar_detector(struct mt7615_dev *dev); int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev); +int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl); static inline bool is_mt7622(struct mt76_dev *dev) { + if (!IS_ENABLED(CONFIG_MT7622_WMAC)) + return false; + return mt76_chip(dev) == 0x7622; } -static inline void mt7615_dfs_check_channel(struct mt7615_dev *dev) +static inline bool is_mt7615(struct mt76_dev *dev) { - enum nl80211_chan_width width = dev->mt76.chandef.width; - u32 freq = dev->mt76.chandef.chan->center_freq; - struct ieee80211_hw *hw = mt76_hw(dev); + return mt76_chip(dev) == 0x7615; +} - if (hw->conf.chandef.chan->center_freq != freq || - hw->conf.chandef.width != width) - dev->dfs_state = -1; +static inline bool is_mt7663(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7663; } static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) @@ -239,27 +366,32 @@ static inline void mt7615_irq_disable(struct mt7615_dev *dev, u32 mask) void mt7615_update_channel(struct mt76_dev *mdev); bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask); void mt7615_mac_reset_counters(struct mt7615_dev *dev); -void mt7615_mac_cca_stats_reset(struct mt7615_dev *dev); +void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy); void mt7615_mac_set_scs(struct mt7615_dev *dev, bool enable); +void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy); void mt7615_mac_sta_poll(struct mt7615_dev *dev); int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int pid, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key, bool beacon); +void mt7615_mac_set_timing(struct mt7615_phy *phy); int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb); void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data); void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb); int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, enum set_key_cmd cmd); +void mt7615_mac_reset_work(struct work_struct *work); +int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq); +int mt7615_mcu_set_dbdc(struct mt7615_dev *dev); int mt7615_mcu_set_eeprom(struct mt7615_dev *dev); -int mt7615_mcu_init_mac(struct mt7615_dev *dev); -int mt7615_mcu_set_rts_thresh(struct mt7615_dev *dev, u32 val); -int mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int enter); +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_dev *dev); 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_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, @@ -272,17 +404,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, 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); -int mt7615_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); -void mt7615_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, +int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); +void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); -int mt76_dfs_start_rdd(struct mt7615_dev *dev, bool force); -int mt7615_dfs_init_radar_detector(struct mt7615_dev *dev); +int mt7615_mcu_set_fcc5_lpn(struct mt7615_dev *dev, int val); +int mt7615_mcu_set_pulse_th(struct mt7615_dev *dev, + const struct mt7615_dfs_pulse *pulse); +int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, + const struct mt7615_dfs_pattern *pattern); +int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); +int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_init_debugfs(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h new file mode 100644 index 000000000000..d3eb49d83b98 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615_trace.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#if !defined(__MT7615_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define __MT7615_TRACE_H + +#include <linux/tracepoint.h> +#include "mt7615.h" + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mt7615 + +#define MAXNAME 32 +#define DEV_ENTRY __array(char, wiphy_name, 32) +#define DEV_ASSIGN strlcpy(__entry->wiphy_name, \ + wiphy_name(mt76_hw(dev)->wiphy), MAXNAME) +#define DEV_PR_FMT "%s" +#define DEV_PR_ARG __entry->wiphy_name + +#define TOKEN_ENTRY __field(u16, token) +#define TOKEN_ASSIGN __entry->token = token +#define TOKEN_PR_FMT " %d" +#define TOKEN_PR_ARG __entry->token + +DECLARE_EVENT_CLASS(dev_token, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token), + TP_STRUCT__entry( + DEV_ENTRY + TOKEN_ENTRY + ), + TP_fast_assign( + DEV_ASSIGN; + TOKEN_ASSIGN; + ), + TP_printk( + DEV_PR_FMT TOKEN_PR_FMT, + DEV_PR_ARG, TOKEN_PR_ARG + ) +); + +DEFINE_EVENT(dev_token, mac_tx_free, + TP_PROTO(struct mt7615_dev *dev, u16 token), + TP_ARGS(dev, token) +); + +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE mt7615_trace + +#include <trace/define_trace.h> diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 1eb1eb659c3f..c8d0f893a47f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -10,84 +10,17 @@ #include <linux/pci.h> #include "mt7615.h" -#include "mac.h" static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, + { PCI_DEVICE(0x14c3, 0x7663) }, { }, }; -u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr) -{ - u32 base = addr & MT_MCU_PCIE_REMAP_2_BASE; - u32 offset = addr & MT_MCU_PCIE_REMAP_2_OFFSET; - - mt76_wr(dev, MT_MCU_PCIE_REMAP_2, base); - - return MT_PCIE_REMAP_BASE_2 + offset; -} - -static void -mt7615_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) -{ - struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - - mt7615_irq_enable(dev, MT_INT_RX_DONE(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); - - if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) - return IRQ_NONE; - - intr &= dev->mt76.mmio.irqmask; - - if (intr & MT_INT_TX_DONE_ALL) { - mt7615_irq_disable(dev, 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)); - napi_schedule(&dev->mt76.napi[0]); - } - - if (intr & MT_INT_RX_DONE(1)) { - mt7615_irq_disable(dev, MT_INT_RX_DONE(1)); - napi_schedule(&dev->mt76.napi[1]); - } - - return IRQ_HANDLED; -} - static int mt7615_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 mt7615_txp), - .drv_flags = MT_DRV_TXWI_NO_FREE, - .survey_flags = SURVEY_INFO_TIME_TX | - SURVEY_INFO_TIME_RX | - SURVEY_INFO_TIME_BSS_RX, - .tx_prepare_skb = mt7615_tx_prepare_skb, - .tx_complete_skb = mt7615_tx_complete_skb, - .rx_skb = mt7615_queue_rx_skb, - .rx_poll_complete = mt7615_rx_poll_complete, - .sta_ps = mt7615_sta_ps, - .sta_add = mt7615_sta_add, - .sta_assoc = mt7615_sta_assoc, - .sta_remove = mt7615_sta_remove, - .update_survey = mt7615_update_channel, - }; - struct mt7615_dev *dev; - struct mt76_dev *mdev; + const u32 *map; int ret; ret = pcim_enable_device(pdev); @@ -104,31 +37,9 @@ static int mt7615_pci_probe(struct pci_dev *pdev, if (ret) return ret; - mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7615_ops, - &drv_ops); - if (!mdev) - return -ENOMEM; - - dev = container_of(mdev, struct mt7615_dev, mt76); - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); - - 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); - - ret = devm_request_irq(mdev->dev, pdev->irq, mt7615_irq_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (ret) - goto error; - - ret = mt7615_register_device(dev); - if (ret) - goto error; - - return 0; -error: - ieee80211_free_hw(mt76_hw(dev)); - return ret; + map = id->device == 0x7663 ? mt7663e_reg_map : mt7615e_reg_map; + return mt7615_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0], + pdev->irq, map); } static void mt7615_pci_remove(struct pci_dev *pdev) @@ -146,10 +57,9 @@ struct pci_driver mt7615_pci_driver = { .remove = mt7615_pci_remove, }; -module_pci_driver(mt7615_pci_driver); - MODULE_DEVICE_TABLE(pci, mt7615_pci_device_table); MODULE_FIRMWARE(MT7615_FIRMWARE_CR4); MODULE_FIRMWARE(MT7615_FIRMWARE_N9); MODULE_FIRMWARE(MT7615_ROM_PATCH); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(MT7663_FIRMWARE_N9); +MODULE_FIRMWARE(MT7663_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 61a4aa9ac6e6..1e0d95b917e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -4,13 +4,46 @@ #ifndef __MT7615_REGS_H #define __MT7615_REGS_H -#define MT_HW_REV 0x1000 -#define MT_HW_CHIPID 0x1008 -#define MT_TOP_STRAP_STA 0x1010 +enum mt7615_reg_base { + MT_TOP_CFG_BASE, + MT_HW_BASE, + MT_DMA_SHDL_BASE, + MT_PCIE_REMAP_2, + MT_ARB_BASE, + MT_HIF_BASE, + MT_CSR_BASE, + MT_PHY_BASE, + MT_CFG_BASE, + MT_AGG_BASE, + MT_TMAC_BASE, + MT_RMAC_BASE, + MT_DMA_BASE, + MT_WTBL_BASE_ON, + MT_WTBL_BASE_OFF, + MT_LPON_BASE, + MT_MIB_BASE, + MT_WTBL_BASE_ADDR, + MT_PCIE_REMAP_BASE2, + MT_TOP_MISC_BASE, + MT_EFUSE_ADDR_BASE, + __MT_BASE_MAX, +}; + +#define MT_HW_INFO_BASE ((dev)->reg_map[MT_HW_BASE]) +#define MT_HW_INFO(ofs) (MT_HW_INFO_BASE + (ofs)) +#define MT_HW_REV MT_HW_INFO(0x000) +#define MT_HW_CHIPID MT_HW_INFO(0x008) +#define MT_TOP_STRAP_STA MT_HW_INFO(0x010) #define MT_TOP_3NSS BIT(24) -#define MT_TOP_MISC2 0x1134 + +#define MT_TOP_OFF_RSV 0x1128 +#define MT_TOP_OFF_RSV_FW_STATE GENMASK(18, 16) + +#define MT_TOP_MISC2 ((dev)->reg_map[MT_TOP_CFG_BASE] + 0x134) #define MT_TOP_MISC2_FW_STATE GENMASK(2, 0) +#define MT7663_TOP_MISC2_FW_STATE GENMASK(3, 1) + #define MT_MCU_BASE 0x2000 #define MT_MCU(ofs) (MT_MCU_BASE + (ofs)) @@ -19,26 +52,39 @@ #define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18) #define MT_PCIE_REMAP_BASE_1 0x40000 -#define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504) +#define MT_MCU_PCIE_REMAP_2 ((dev)->reg_map[MT_PCIE_REMAP_2]) #define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0) #define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) -#define MT_PCIE_REMAP_BASE_2 0x80000 +#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 MT7663_MCU_PCIE_REMAP_2_OFFSET GENMASK(15, 0) +#define MT7663_MCU_PCIE_REMAP_2_BASE GENMASK(31, 16) -#define MT_HIF_BASE 0x4000 -#define MT_HIF(ofs) (MT_HIF_BASE + (ofs)) +#define MT_HIF2_BASE 0xf0000 +#define MT_HIF2(ofs) (MT_HIF2_BASE + (ofs)) +#define MT_PCIE_IRQ_ENABLE MT_HIF2(0x188) #define MT_CFG_LPCR_HOST MT_HIF(0x1f0) #define MT_CFG_LPCR_HOST_FW_OWN BIT(0) #define MT_CFG_LPCR_HOST_DRV_OWN BIT(1) +#define MT_MCU_INT_EVENT MT_HIF(0x1f8) +#define MT_MCU_INT_EVENT_PDMA_STOPPED BIT(0) +#define MT_MCU_INT_EVENT_PDMA_INIT BIT(1) +#define MT_MCU_INT_EVENT_SER_TRIGGER BIT(2) +#define MT_MCU_INT_EVENT_RESET_DONE BIT(3) + #define MT_INT_SOURCE_CSR MT_HIF(0x200) #define MT_INT_MASK_CSR MT_HIF(0x204) #define MT_DELAY_INT_CFG MT_HIF(0x210) #define MT_INT_RX_DONE(_n) BIT(_n) #define MT_INT_RX_DONE_ALL GENMASK(1, 0) -#define MT_INT_TX_DONE_ALL GENMASK(7, 4) +#define MT_INT_TX_DONE_ALL GENMASK(19, 4) #define MT_INT_TX_DONE(_n) BIT((_n) + 4) +#define MT_INT_MCU_CMD BIT(30) #define MT_WPDMA_GLO_CFG MT_HIF(0x208) #define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) @@ -49,6 +95,7 @@ #define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) #define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0 BIT(9) +#define MT_WPDMA_GLO_CFG_BYPASS_TX_SCH BIT(9) /* MT7622 */ #define MT_WPDMA_GLO_CFG_MULTI_DMA_EN GENMASK(11, 10) #define MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12) #define MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21 GENMASK(23, 22) @@ -58,6 +105,22 @@ #define MT_WPDMA_RST_IDX MT_HIF(0x20c) +#define MT_WPDMA_MEM_RNG_ERR MT_HIF(0x224) + +#define MT_MCU_CMD MT_HIF(0x234) +#define MT_MCU_CMD_CLEAR_FW_OWN BIT(0) +#define MT_MCU_CMD_STOP_PDMA_FW_RELOAD BIT(1) +#define MT_MCU_CMD_STOP_PDMA 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_LMAC_ERROR BIT(24) +#define MT_MCU_CMD_PSE_ERROR BIT(25) +#define MT_MCU_CMD_PLE_ERROR BIT(26) +#define MT_MCU_CMD_PDMA_ERROR BIT(27) +#define MT_MCU_CMD_PCIE_ERROR BIT(28) +#define MT_MCU_CMD_ERROR_MASK (GENMASK(5, 1) | GENMASK(28, 24)) + #define MT_TX_RING_BASE MT_HIF(0x300) #define MT_RX_RING_BASE MT_HIF(0x400) @@ -67,6 +130,9 @@ #define MT_WPDMA_ABT_CFG MT_HIF(0x530) #define MT_WPDMA_ABT_CFG1 MT_HIF(0x534) +#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)) @@ -78,41 +144,40 @@ #define MT_PLE_AC_QEMPTY(ac, n) MT_PLE(0x300 + 0x10 * (ac) + \ ((n) << 2)) -#define MT_WF_PHY_BASE 0x10000 +#define MT_WF_PHY_BASE ((dev)->reg_map[MT_PHY_BASE]) #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) -#define MT_WF_PHY_WF2_RFCTRL0 MT_WF_PHY(0x1900) +#define MT_WF_PHY_WF2_RFCTRL0(n) MT_WF_PHY(0x1900 + (n) * 0x400) #define MT_WF_PHY_WF2_RFCTRL0_LPBCN_EN BIT(9) -#define MT_WF_PHY_R0_B0_PHYMUX_5 MT_WF_PHY(0x0614) +#define MT_WF_PHY_R0_PHYMUX_5(_phy) MT_WF_PHY(0x0614 + ((_phy) << 9)) -#define MT_WF_PHY_R0_B0_PHYCTRL_STS0 MT_WF_PHY(0x020c) +#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 MT_WF_PHY_R0_B0_PHYCTRL_STS5 MT_WF_PHY(0x0220) +#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 MT_WF_PHY_B0_MIN_PRI_PWR MT_WF_PHY(0x229c) -#define MT_WF_PHY_B0_PD_OFDM_MASK GENMASK(28, 20) -#define MT_WF_PHY_B0_PD_OFDM(v) ((v) << 20) -#define MT_WF_PHY_B0_PD_BLK BIT(19) +#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 MT_WF_PHY_B1_MIN_PRI_PWR MT_WF_PHY(0x084) -#define MT_WF_PHY_B1_PD_OFDM_MASK GENMASK(24, 16) -#define MT_WF_PHY_B1_PD_OFDM(v) ((v) << 16) -#define MT_WF_PHY_B1_PD_BLK BIT(25) +#define MT_WF_PHY_RXTD_BASE MT_WF_PHY(0x2200) +#define MT_WF_PHY_RXTD(_n) (MT_WF_PHY_RXTD_BASE + ((_n) << 2)) -#define MT_WF_PHY_B0_RXTD_CCK_PD MT_WF_PHY(0x2310) -#define MT_WF_PHY_B0_PD_CCK_MASK GENMASK(8, 1) -#define MT_WF_PHY_B0_PD_CCK(v) ((v) << 1) +#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 MT_WF_PHY_B1_RXTD_CCK_PD MT_WF_PHY(0x2314) -#define MT_WF_PHY_B1_PD_CCK_MASK GENMASK(31, 24) -#define MT_WF_PHY_B1_PD_CCK(v) ((v) << 24) +#define MT_WF_PHY_RXTD2_BASE MT_WF_PHY(0x2a00) +#define MT_WF_PHY_RXTD2(_n) (MT_WF_PHY_RXTD2_BASE + ((_n) << 2)) -#define MT_WF_CFG_BASE 0x20200 +#define MT_WF_CFG_BASE ((dev)->reg_map[MT_CFG_BASE]) #define MT_WF_CFG(ofs) (MT_WF_CFG_BASE + (ofs)) #define MT_CFG_CCR MT_WF_CFG(0x000) @@ -121,7 +186,7 @@ #define MT_CFG_CCR_MAC_D1_2X_GC_EN BIT(30) #define MT_CFG_CCR_MAC_D0_2X_GC_EN BIT(31) -#define MT_WF_AGG_BASE 0x20a00 +#define MT_WF_AGG_BASE ((dev)->reg_map[MT_AGG_BASE]) #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) #define MT_AGG_ARCR MT_WF_AGG(0x010) @@ -131,8 +196,8 @@ #define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) #define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) -#define MT_AGG_ARUCR MT_WF_AGG(0x018) -#define MT_AGG_ARDCR MT_WF_AGG(0x01c) +#define MT_AGG_ARUCR(_band) MT_WF_AGG(0x018 + (_band) * 0x100) +#define MT_AGG_ARDCR(_band) MT_WF_AGG(0x01c + (_band) * 0x100) #define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) #define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ @@ -142,8 +207,7 @@ #define MT_AGG_ASRCR1 MT_WF_AGG(0x064) #define MT_AGG_ASRCR_RANGE(val, n) (((val) >> ((n) << 3)) & GENMASK(5, 0)) -#define MT_AGG_ACR0 MT_WF_AGG(0x070) -#define MT_AGG_ACR1 MT_WF_AGG(0x170) +#define MT_AGG_ACR(_band) MT_WF_AGG(0x070 + (_band) * 0x100) #define MT_AGG_ACR_NO_BA_RULE BIT(0) #define MT_AGG_ACR_NO_BA_AR_RULE BIT(1) #define MT_AGG_ACR_PKT_TIME_EN BIT(2) @@ -153,24 +217,43 @@ #define MT_AGG_SCR MT_WF_AGG(0x0fc) #define MT_AGG_SCR_NLNAV_MID_PTEC_DIS BIT(3) -#define MT_WF_TMAC_BASE 0x21000 +#define MT_WF_ARB_BASE ((dev)->reg_map[MT_ARB_BASE]) +#define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) + +#define MT_ARB_SCR MT_WF_ARB(0x080) +#define MT_ARB_SCR_TX0_DISABLE BIT(8) +#define MT_ARB_SCR_RX0_DISABLE BIT(9) +#define MT_ARB_SCR_TX1_DISABLE BIT(10) +#define MT_ARB_SCR_RX1_DISABLE BIT(11) + +#define MT_WF_TMAC_BASE ((dev)->reg_map[MT_TMAC_BASE]) #define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) -#define MT_TMAC_TRCR0 MT_WF_TMAC(0x09c) -#define MT_TMAC_TRCR1 MT_WF_TMAC(0x070) +#define MT_TMAC_CDTR MT_WF_TMAC(0x090) +#define MT_TMAC_ODTR MT_WF_TMAC(0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TMAC_TRCR(_band) MT_WF_TMAC((_band) ? 0x070 : 0x09c) #define MT_TMAC_TRCR_CCA_SEL GENMASK(31, 30) #define MT_TMAC_TRCR_SEC_CCA_SEL GENMASK(29, 28) +#define MT_TMAC_ICR(_band) MT_WF_TMAC((_band) ? 0x074 : 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 MT_WF_TMAC(0x0f4) #define MT_TMAC_CTCR0_INS_DDLMT_REFTIME GENMASK(5, 0) #define MT_TMAC_CTCR0_INS_DDLMT_DENSITY GENMASK(15, 12) #define MT_TMAC_CTCR0_INS_DDLMT_EN BIT(17) #define MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN BIT(18) -#define MT_WF_RMAC_BASE 0x21200 +#define MT_WF_RMAC_BASE ((dev)->reg_map[MT_RMAC_BASE]) #define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) -#define MT_WF_RFCR MT_WF_RMAC(0x000) +#define MT_WF_RFCR(_band) MT_WF_RMAC((_band) ? 0x100 : 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) @@ -193,13 +276,15 @@ #define MT_WF_RFCR_DROP_NDPA BIT(20) #define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) -#define MT_WF_RFCR1 MT_WF_RMAC(0x004) +#define MT_WF_RFCR1(_band) MT_WF_RMAC((_band) ? 0x104 : 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_CHFREQ(_band) MT_WF_RMAC((_band) ? 0x130 : 0x030) + #define MT_WF_RMAC_MIB_TIME0 MT_WF_RMAC(0x03c4) #define MT_WF_RMAC_MIB_RXTIME_CLR BIT(31) #define MT_WF_RMAC_MIB_RXTIME_EN BIT(30) @@ -207,17 +292,17 @@ #define MT_WF_RMAC_MIB_AIRTIME0 MT_WF_RMAC(0x0380) #define MT_WF_RMAC_MIB_TIME5 MT_WF_RMAC(0x03d8) +#define MT_WF_RMAC_MIB_TIME6 MT_WF_RMAC(0x03dc) #define MT_MIB_OBSSTIME_MASK GENMASK(23, 0) -#define MT_WF_DMA_BASE 0x21800 +#define MT_WF_DMA_BASE ((dev)->reg_map[MT_DMA_BASE]) #define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) #define MT_DMA_DCR0 MT_WF_DMA(0x000) #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) -#define MT_DMA_BN0RCFR0 MT_WF_DMA(0x070) -#define MT_DMA_BN1RCFR0 MT_WF_DMA(0x0b0) +#define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) #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) @@ -225,10 +310,10 @@ #define MT_DMA_RCFR0_RX_DROPPED_UCAST GENMASK(25, 24) #define MT_DMA_RCFR0_RX_DROPPED_MCAST GENMASK(27, 26) -#define MT_WTBL_BASE 0x30000 +#define MT_WTBL_BASE(dev) ((dev)->reg_map[MT_WTBL_BASE_ADDR]) #define MT_WTBL_ENTRY_SIZE 256 -#define MT_WTBL_OFF_BASE 0x23400 +#define MT_WTBL_OFF_BASE ((dev)->reg_map[MT_WTBL_BASE_OFF]) #define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n)) #define MT_WTBL_W0_KEY_IDX GENMASK(24, 23) @@ -245,7 +330,11 @@ #define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14) #define MT_WTBL_UPDATE_BUSY BIT(31) -#define MT_WTBL_ON_BASE 0x23000 +#define MT_TOP_MISC(ofs) ((dev)->reg_map[MT_TOP_MISC_BASE] + (ofs)) +#define MT_CONN_ON_MISC MT_TOP_MISC(0x1140) +#define MT_TOP_MISC2_FW_N9_RDY BIT(2) + +#define MT_WTBL_ON_BASE ((dev)->reg_map[MT_WTBL_BASE_ON]) #define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n)) #define MT_WTBL_RICR0 MT_WTBL_ON(0x010) @@ -281,8 +370,7 @@ #define MT_WTBL_W27_CC_BW_SEL GENMASK(6, 5) -#define MT_LPON_BASE 0x24200 -#define MT_LPON(_n) (MT_LPON_BASE + (_n)) +#define MT_LPON(_n) ((dev)->reg_map[MT_LPON_BASE] + (_n)) #define MT_LPON_T0CR MT_LPON(0x010) #define MT_LPON_T0CR_MODE GENMASK(1, 0) @@ -290,13 +378,13 @@ #define MT_LPON_UTTR0 MT_LPON(0x018) #define MT_LPON_UTTR1 MT_LPON(0x01c) -#define MT_WF_MIB_BASE 0x24800 +#define MT_WF_MIB_BASE (dev->reg_map[MT_MIB_BASE]) #define MT_WF_MIB(ofs) (MT_WF_MIB_BASE + (ofs)) #define MT_MIB_M0_MISC_CR MT_WF_MIB(0x00c) -#define MT_MIB_MB_SDR0(n) MT_WF_MIB(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_SDR3(n) MT_WF_MIB(0x014 + ((n) << 9)) +#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_BUSY_MASK GENMASK(23, 0) @@ -309,9 +397,59 @@ #define MT_MIB_SDR37(n) MT_WF_MIB(0x09c + ((n) << 9)) #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_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_ACK_FAIL_COUNT_MASK GENMASK(31, 16) + #define MT_TX_AGG_CNT(n) MT_WF_MIB(0xa8 + ((n) << 2)) -#define MT_EFUSE_BASE 0x81070000 +#define MT_DMA_SHDL(ofs) (dev->reg_map[MT_DMA_SHDL_BASE] + (ofs)) + +#define MT_DMASHDL_BASE 0x5000a000 +#define MT_DMASHDL_OPTIONAL 0x008 +#define MT_DMASHDL_PAGE 0x00c + +#define MT_DMASHDL_REFILL 0x010 + +#define MT_DMASHDL_PKT_MAX_SIZE 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) (0x020 + ((_n) << 2)) +#define MT_DMASHDL_GROUP_QUOTA_MIN GENMASK(11, 0) +#define MT_DMASHDL_GROUP_QUOTA_MAX GENMASK(27, 16) + +#define MT_DMASHDL_SCHED_SET0 0x0b0 +#define MT_DMASHDL_SCHED_SET1 0x0b4 + +#define MT_DMASHDL_Q_MAP(_n) (0x0d0 + ((_n) << 2)) +#define MT_DMASHDL_Q_MAP_MASK GENMASK(3, 0) +#define MT_DMASHDL_Q_MAP_SHIFT(_n) (4 * ((_n) % 8)) + +#define MT_LED_BASE_PHYS 0x80024000 +#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) + +#define MT_LED_CTRL MT_LED_PHYS(0x00) + +#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) +#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) +#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) +#define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) +#define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) +#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) + +#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) +#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) +#define MT_LED_STATUS_OFF GENMASK(31, 24) +#define MT_LED_STATUS_ON GENMASK(23, 16) +#define MT_LED_STATUS_DURATION GENMASK(15, 0) + +#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) @@ -328,4 +466,8 @@ #define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) #define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) +/* INFRACFG host register range on MT7622 */ +#define MT_INFRACFG_MISC 0x700 +#define MT_INFRACFG_MISC_AP2CONN_WAKE BIT(1) + #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c new file mode 100644 index 000000000000..43aa49706c66 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2019 MediaTek Inc. + * + * Author: Ryder Lee <ryder.lee@mediatek.com> + * Felix Fietkau <nbd@nbd.name> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include "mt7615.h" + +int mt7622_wmac_init(struct mt7615_dev *dev) +{ + struct device_node *np = dev->mt76.dev->of_node; + + if (!is_mt7622(&dev->mt76)) + return 0; + + dev->infracfg = syscon_regmap_lookup_by_phandle(np, "mediatek,infracfg"); + if (IS_ERR(dev->infracfg)) { + dev_err(dev->mt76.dev, "Cannot find infracfg controller\n"); + return PTR_ERR(dev->infracfg); + } + + return 0; +} + +static int mt7622_wmac_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + void __iomem *mem_base; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get device IRQ\n"); + return irq; + } + + mem_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mem_base)) { + dev_err(&pdev->dev, "Failed to get memory resource\n"); + return PTR_ERR(mem_base); + } + + return mt7615_mmio_probe(&pdev->dev, mem_base, irq, mt7615e_reg_map); +} + +static int mt7622_wmac_remove(struct platform_device *pdev) +{ + struct mt7615_dev *dev = platform_get_drvdata(pdev); + + mt7615_unregister_device(dev); + + return 0; +} + +static const struct of_device_id mt7622_wmac_of_match[] = { + { .compatible = "mediatek,mt7622-wmac" }, + {}, +}; + +struct platform_driver mt7622_wmac_driver = { + .driver = { + .name = "mt7622-wmac", + .of_match_table = mt7622_wmac_of_match, + }, + .probe = mt7622_wmac_probe, + .remove = mt7622_wmac_remove, +}; + +MODULE_FIRMWARE(MT7622_FIRMWARE_N9); +MODULE_FIRMWARE(MT7622_ROM_PATCH); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/trace.c b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c new file mode 100644 index 000000000000..6c02d5aff68f --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7615/trace.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> + */ + +#include <linux/module.h> + +#ifndef __CHECKER__ +#define CREATE_TRACE_POINTS +#include "mt7615_trace.h" + +#endif |