diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7615')
18 files changed, 929 insertions, 526 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index 7ae48b4fa564..676bb22726d6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -69,6 +69,7 @@ static int mt7615_pm_set(void *data, u64 val) { struct mt7615_dev *dev = data; + struct mt76_connac_pm *pm = &dev->pm; int ret = 0; if (!mt7615_wait_for_mcu_init(dev)) @@ -77,6 +78,9 @@ mt7615_pm_set(void *data, u64 val) if (!mt7615_firmware_offload(dev) || !mt76_is_mmio(&dev->mt76)) return -EOPNOTSUPP; + if (val == pm->enable) + return 0; + mt7615_mutex_acquire(dev); if (dev->phy.n_beacon_vif) { @@ -84,7 +88,11 @@ mt7615_pm_set(void *data, u64 val) goto out; } - dev->pm.enable = val; + if (!pm->enable) { + pm->stats.last_wake_event = jiffies; + pm->stats.last_doze_event = jiffies; + } + pm->enable = val; out: mt7615_mutex_release(dev); @@ -104,6 +112,26 @@ mt7615_pm_get(void *data, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7615_pm_get, mt7615_pm_set, "%lld\n"); static int +mt7615_pm_stats(struct seq_file *s, void *data) +{ + struct mt7615_dev *dev = dev_get_drvdata(s->private); + struct mt76_connac_pm *pm = &dev->pm; + unsigned long awake_time = pm->stats.awake_time; + unsigned long doze_time = pm->stats.doze_time; + + if (!test_bit(MT76_STATE_PM, &dev->mphy.state)) + awake_time += jiffies - pm->stats.last_wake_event; + else + doze_time += jiffies - pm->stats.last_doze_event; + + seq_printf(s, "awake time: %14u\ndoze time: %15u\n", + jiffies_to_msecs(awake_time), + jiffies_to_msecs(doze_time)); + + return 0; +} + +static int mt7615_pm_idle_timeout_set(void *data, u64 val) { struct mt7615_dev *dev = data; @@ -515,20 +543,27 @@ int mt7615_init_debugfs(struct mt7615_dev *dev) debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); debugfs_create_file("idle-timeout", 0600, dir, dev, &fops_pm_idle_timeout); + debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, + mt7615_pm_stats); debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, mt7615_radio_read); - debugfs_create_u32("dfs_hw_pattern", 0400, dir, &dev->hw_pattern); - /* test pattern knobs */ - debugfs_create_u8("pattern_len", 0600, dir, - &dev->radar_pattern.n_pulses); - debugfs_create_u32("pulse_period", 0600, dir, - &dev->radar_pattern.period); - debugfs_create_u16("pulse_width", 0600, dir, - &dev->radar_pattern.width); - debugfs_create_u16("pulse_power", 0600, dir, - &dev->radar_pattern.power); - debugfs_create_file("radar_trigger", 0200, dir, dev, - &fops_radar_pattern); + + if (is_mt7615(&dev->mt76)) { + debugfs_create_u32("dfs_hw_pattern", 0400, dir, + &dev->hw_pattern); + /* test pattern knobs */ + debugfs_create_u8("pattern_len", 0600, dir, + &dev->radar_pattern.n_pulses); + debugfs_create_u32("pulse_period", 0600, dir, + &dev->radar_pattern.period); + debugfs_create_u16("pulse_width", 0600, dir, + &dev->radar_pattern.width); + debugfs_create_u16("pulse_power", 0600, dir, + &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, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 25e3069cf2b1..8004ae5c16a9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -71,15 +71,39 @@ static int mt7615_poll_tx(struct napi_struct *napi, int budget) struct mt7615_dev *dev; dev = container_of(napi, struct mt7615_dev, mt76.tx_napi); + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); - - if (napi_complete_done(napi, 0)) + if (napi_complete(napi)) mt7615_irq_enable(dev, mt7615_tx_mcu_int_mask(dev)); + mt76_connac_pm_unref(&dev->pm); + return 0; } +static int mt7615_poll_rx(struct napi_struct *napi, int budget) +{ + struct mt7615_dev *dev; + int done; + + dev = container_of(napi->dev, struct mt7615_dev, mt76.napi_dev); + + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { + napi_complete(napi); + queue_work(dev->mt76.wq, &dev->pm.wake_work); + return 0; + } + done = mt76_dma_rx_poll(napi, budget); + mt76_connac_pm_unref(&dev->pm); + + return done; +} + int mt7615_wait_pdma_busy(struct mt7615_dev *dev) { struct mt76_dev *mdev = &dev->mt76; @@ -176,10 +200,30 @@ static void mt7663_dma_sched_init(struct mt7615_dev *dev) mt76_wr(dev, MT_DMA_SHDL(MT_DMASHDL_SCHED_SET1), 0xedcba987); } +void mt7615_dma_start(struct mt7615_dev *dev) +{ + /* start dma engine */ + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + + if (is_mt7622(&dev->mt76)) + mt7622_dma_sched_init(dev); + + if (is_mt7663(&dev->mt76)) { + mt7663_dma_sched_init(dev); + + mt76_wr(dev, MT_MCU2HOST_INT_ENABLE, MT7663_MCU_CMD_ERROR_MASK); + } + +} + int mt7615_dma_init(struct mt7615_dev *dev) { int rx_ring_size = MT7615_RX_RING_SIZE; int rx_buf_size = MT_RX_BUF_SIZE; + u32 mask; int ret; /* Increase buffer size to receive large VHT MPDUs */ @@ -241,11 +285,11 @@ int mt7615_dma_init(struct mt7615_dev *dev) mt76_wr(dev, MT_DELAY_INT_CFG, 0); - ret = mt76_init_queues(dev); + ret = mt76_init_queues(dev, mt7615_poll_rx); if (ret < 0) return ret; - netif_tx_napi_add(&dev->mt76.napi_dev, &dev->mt76.tx_napi, + netif_tx_napi_add(&dev->mt76.tx_napi_dev, &dev->mt76.tx_napi, mt7615_poll_tx, NAPI_POLL_WEIGHT); napi_enable(&dev->mt76.tx_napi); @@ -253,20 +297,17 @@ int mt7615_dma_init(struct mt7615_dev *dev) MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); - /* start dma engine */ - mt76_set(dev, MT_WPDMA_GLO_CFG, - MT_WPDMA_GLO_CFG_TX_DMA_EN | - MT_WPDMA_GLO_CFG_RX_DMA_EN); - /* enable interrupts for TX/RX rings */ - mt7615_irq_enable(dev, MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev) | - MT_INT_MCU_CMD); - - if (is_mt7622(&dev->mt76)) - mt7622_dma_sched_init(dev); + mask = MT_INT_RX_DONE_ALL | mt7615_tx_mcu_int_mask(dev); if (is_mt7663(&dev->mt76)) - mt7663_dma_sched_init(dev); + mask |= MT7663_INT_MCU_CMD; + else + mask |= MT_INT_MCU_CMD; + + mt7615_irq_enable(dev, mask); + + mt7615_dma_start(dev); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 2eab23898c77..6dbaaf95ee38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev) switch (val) { case 0x7615: case 0x7622: + case 0x7663: return 0; default: return -EINVAL; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 571390fa4de7..86341d1f82f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -116,10 +116,10 @@ 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); + MT_DMA_DCR0_RX_VEC_DROP | MT_DMA_DCR0_DAMSDU_EN | + MT_DMA_DCR0_RX_HDR_TRANS_EN); /* disable TDLS filtering */ mt76_clear(dev, MT_WF_PFCR, MT_WF_PFCR_TDLS_EN); mt76_set(dev, MT_WF_MIB_SCR0, MT_MIB_SCR0_AGG_CNT_RANGE_EN); @@ -129,6 +129,7 @@ mt7615_mac_init(struct mt7615_dev *dev) } else { mt7615_init_mac_chain(dev, 1); } + mt7615_mcu_set_rx_hdr_trans_blacklist(dev); } static void @@ -251,6 +252,7 @@ void mt7615_init_txpower(struct mt7615_dev *dev, int delta_idx, delta = mt76_tx_power_nss_delta(n_chains); u8 *eep = (u8 *)dev->mt76.eeprom.data; enum nl80211_band band = sband->band; + struct mt76_power_limits limits; u8 rate_val; delta_idx = mt7615_eeprom_get_power_delta_index(dev, band); @@ -279,7 +281,11 @@ void mt7615_init_txpower(struct mt7615_dev *dev, target_power = max(target_power, eep[index]); } - target_power = DIV_ROUND_UP(target_power + delta, 2); + target_power = mt76_get_rate_power_limits(&dev->mphy, chan, + &limits, + target_power); + target_power += delta; + target_power = DIV_ROUND_UP(target_power, 2); chan->max_power = min_t(int, chan->max_reg_power, target_power); chan->orig_mpwr = target_power; @@ -310,12 +316,18 @@ mt7615_regd_notifier(struct wiphy *wiphy, memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2)); dev->mt76.region = request->dfs_region; + mt7615_init_txpower(dev, &mphy->sband_2g.sband); + mt7615_init_txpower(dev, &mphy->sband_5g.sband); + mt7615_mutex_acquire(dev); if (chandef->chan->flags & IEEE80211_CHAN_RADAR) mt7615_dfs_init_radar_detector(phy); - if (mt7615_firmware_offload(phy->dev)) + + if (mt7615_firmware_offload(phy->dev)) { mt76_connac_mcu_set_channel_domain(mphy); + mt76_connac_mcu_set_rate_txpower(mphy); + } mt7615_mutex_release(dev); } @@ -330,6 +342,10 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) hw->max_rates = 3; hw->max_report_rates = 7; hw->max_rate_tries = 11; + hw->netdev_features = NETIF_F_RXCSUM; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US; phy->slottime = 9; @@ -360,11 +376,17 @@ mt7615_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); ieee80211_hw_set(hw, WANT_MONITOR_VIF); + ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD); 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; + + phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + phy->mt76->sband_5g.sband.vht_cap.cap |= + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK; } static void @@ -480,10 +502,13 @@ void mt7615_init_device(struct mt7615_dev *dev) dev->phy.dev = dev; dev->phy.mt76 = &dev->mt76.phy; dev->mt76.phy.priv = &dev->phy; + dev->mt76.tx_worker.fn = mt7615_tx_worker; INIT_DELAYED_WORK(&dev->pm.ps_work, mt7615_pm_power_save_work); INIT_WORK(&dev->pm.wake_work, mt7615_pm_wake_work); - init_completion(&dev->pm.wake_cmpl); + spin_lock_init(&dev->pm.wake.lock); + mutex_init(&dev->pm.mutex); + init_waitqueue_head(&dev->pm.wait); spin_lock_init(&dev->pm.txq_lock); set_bit(MT76_STATE_PM, &dev->mphy.state); INIT_DELAYED_WORK(&dev->mphy.mac_work, mt7615_mac_work); @@ -496,16 +521,13 @@ void mt7615_init_device(struct mt7615_dev *dev) init_waitqueue_head(&dev->reset_wait); init_waitqueue_head(&dev->phy.roc_wait); - INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); mt7615_init_wiphy(hw); dev->pm.idle_timeout = MT7615_PM_TIMEOUT; - 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_A_MPDU_LENGTH_EXPONENT_MASK; + dev->pm.stats.last_wake_event = jiffies; + dev->pm.stats.last_doze_event = jiffies; mt7615_cap_dbdc_disable(dev); dev->phy.dfs_state = -1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 59fdd0fc2ad4..f81a17d56008 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -234,11 +234,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) 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; + u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; + bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false; int phy_idx; int i, idx; - u8 chfreq; + u8 chfreq, amsdu_info, qos_ctl = 0; + u16 seq_ctrl = 0; + __le16 fc = 0; memset(status, 0, sizeof(*status)); @@ -254,8 +256,12 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) else phy_idx = -1; + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M; idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); + hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS; status->wcid = mt7615_rx_get_wcid(dev, idx, unicast); if (status->wcid) { @@ -268,6 +274,9 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) spin_unlock_bh(&dev->sta_poll_lock); } + if ((rxd0 & csum_mask) == csum_mask) + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -288,6 +297,13 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) rxd += 4; if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { + u32 v0 = le32_to_cpu(rxd[0]); + u32 v2 = le32_to_cpu(rxd[2]); + + fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0)); + qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2); + seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2); + rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -312,6 +328,23 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) } if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + 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 != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -355,20 +388,6 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) 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]); @@ -446,20 +465,42 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb) skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); - if (insert_ccmp_hdr) { + amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1); + status->amsdu = !!amsdu_info; + if (status->amsdu) { + status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME; + status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME; + if (!hdr_trans) { + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } + } + + if (insert_ccmp_hdr && !hdr_trans) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); mt76_insert_ccmp_hdr(skb, key_id); } - hdr = (struct ieee80211_hdr *)skb->data; - if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + if (!hdr_trans) { + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } + } else { + status->flag |= RX_FLAG_8023; + } + + if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; status->aggr = unicast && - !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; - status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + !ieee80211_is_qos_nullfunc(fc); + status->qos_ctl = qos_ctl; + status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); return 0; } @@ -690,7 +731,7 @@ mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp) { int i; - for (i = 1; i < txp->nbuf; i++) + for (i = 0; i < txp->nbuf; i++) dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); } @@ -966,6 +1007,7 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, struct mt7615_dev *dev = phy->dev; struct mt7615_rate_desc rd; u32 w5, w27, addr; + u16 idx = sta->vif->mt76.omac_idx; if (!mt76_is_mmio(&dev->mt76)) { mt7615_mac_queue_rate_update(phy, sta, probe_rate, rates); @@ -1017,7 +1059,10 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta, mt76_wr(dev, addr + 27 * 4, w27); - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); + + mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */ sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0); sta->rate_set_tsf |= rd.rateset; @@ -1033,7 +1078,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; @@ -1050,22 +1095,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, memcpy(data + 16, key->key + 24, 8); memcpy(data + 24, key->key + 16, 8); } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) - memmove(data + 16, data, 16); - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) + if (cipher_mask == BIT(cipher)) memcpy(data, key->key, key->keylen); - else if (cipher == MT_CIPHER_BIP_CMAC_128) + else if (cipher != MT_CIPHER_BIP_CMAC_128) + memcpy(data, key->key, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memcpy(data + 16, key->key, 16); } } else { - if (wcid->cipher & ~BIT(cipher)) { - if (cipher != MT_CIPHER_BIP_CMAC_128) - memmove(data, data + 16, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memset(data + 16, 0, 16); - } else { + else if (cipher_mask) + memset(data, 0, 16); + if (!cipher_mask) memset(data, 0, sizeof(data)); - } } + mt76_wr_copy(dev, addr, data, sizeof(data)); return 0; @@ -1073,7 +1118,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, static int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1083,20 +1128,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, w0 = mt76_rr(dev, addr); w1 = mt76_rr(dev, addr + 4); - if (cmd == SET_KEY) { - w0 |= MT_WTBL_W0_RX_KEY_VALID | - FIELD_PREP(MT_WTBL_W0_RX_IK_VALID, - cipher == MT_CIPHER_BIP_CMAC_128); - if (cipher != MT_CIPHER_BIP_CMAC_128 || - !wcid->cipher) - w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); - } else { - if (!(wcid->cipher & ~BIT(cipher))) - w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | - MT_WTBL_W0_KEY_IDX); - if (cipher == MT_CIPHER_BIP_CMAC_128) - w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cipher_mask) + w0 |= MT_WTBL_W0_RX_KEY_VALID; + else + w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX); + if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128)) + w0 |= MT_WTBL_W0_RX_IK_VALID; + else + w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cmd == SET_KEY && + (cipher != MT_CIPHER_BIP_CMAC_128 || + cipher_mask == BIT(cipher))) { + w0 &= ~MT_WTBL_W0_KEY_IDX; + w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); } + mt76_wr(dev, MT_WTBL_RICR0, w0); mt76_wr(dev, MT_WTBL_RICR1, w1); @@ -1109,24 +1157,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, static void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); - if (cmd == SET_KEY) { - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); - } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && - wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128)) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, - MT_CIPHER_BIP_CMAC_128)); - else if (!(wcid->cipher & ~BIT(cipher))) - mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + if (!cipher_mask) { + mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + return; } + + if (cmd != SET_KEY) + return; + + if (cipher == MT_CIPHER_BIP_CMAC_128 && + cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) + return; + + mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, + FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); } int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, @@ -1135,25 +1184,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, enum set_key_cmd cmd) { enum mt7615_cipher_type cipher; + u16 cipher_mask = wcid->cipher; int err; cipher = mt7615_mac_get_cipher(key->cipher); if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; - mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); + if (cmd == SET_KEY) + cipher_mask |= BIT(cipher); + else + cipher_mask &= ~BIT(cipher); + + mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); + err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, + cmd); if (err < 0) return err; - err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, + key->keyidx, cmd); if (err < 0) return err; - if (cmd == SET_KEY) - wcid->cipher |= BIT(cipher); - else - wcid->cipher &= ~BIT(cipher); + wcid->cipher = cipher_mask; return 0; } @@ -1411,11 +1465,7 @@ mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token) u8 wcid; trace_mac_tx_free(dev, token); - - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, token); - spin_unlock_bh(&dev->token_lock); - + txwi = mt76_token_put(mdev, token); if (!txwi) return; @@ -1460,14 +1510,10 @@ static void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb) dev_kfree_skb(skb); - if (test_bit(MT76_STATE_PM, &dev->phy.mt76->state)) - return; - rcu_read_lock(); mt7615_mac_sta_poll(dev); rcu_read_unlock(); - mt76_connac_power_save_sched(&dev->mphy, &dev->pm); mt76_worker_schedule(&dev->mt76.tx_worker); } @@ -1821,10 +1867,8 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy) int i, aggr; u32 val, val2; - memset(mib, 0, sizeof(*mib)); - - mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); val = mt76_get_field(dev, MT_MIB_SDR14(ext_phy), MT_MIB_AMPDU_MPDU_COUNT); @@ -1837,24 +1881,16 @@ mt7615_mac_update_mib_stats(struct mt7615_phy *phy) aggr = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0; i < 4; i++) { val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); - - val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); - if (val2 > mib->ack_fail_cnt) - mib->ack_fail_cnt = val2; - - val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - if (val2 > mib->ba_miss_cnt) - mib->ba_miss_cnt = val2; + mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + mib->ack_fail_cnt += FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, + val); val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); - val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (val2 > mib->rts_retries_cnt) { - mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt = val2; - } + mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt += FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, + val); val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - dev->mt76.aggr_stats[aggr++] += val & 0xffff; dev->mt76.aggr_stats[aggr++] += val >> 16; } @@ -1869,13 +1905,19 @@ void mt7615_pm_wake_work(struct work_struct *work) pm.wake_work); mphy = dev->phy.mt76; - if (!mt7615_mcu_set_drv_ctrl(dev)) + if (!mt7615_mcu_set_drv_ctrl(dev)) { + int i; + + mt76_for_each_q_rx(&dev->mt76, i) + napi_schedule(&dev->mt76.napi[i]); mt76_connac_pm_dequeue_skbs(mphy, &dev->pm); - else - dev_err(mphy->dev->dev, "failed to wake device\n"); + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], false); + ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, + MT7615_WATCHDOG_TIME); + } ieee80211_wake_queues(mphy->hw); - complete_all(&dev->pm.wake_cmpl); + wake_up(&dev->pm.wait); } void mt7615_pm_power_save_work(struct work_struct *work) @@ -1887,6 +1929,10 @@ void mt7615_pm_power_save_work(struct work_struct *work) pm.ps_work.work); delta = dev->pm.idle_timeout; + if (test_bit(MT76_HW_SCANNING, &dev->mphy.state) || + test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state)) + goto out; + if (time_is_after_jiffies(dev->pm.last_activity + delta)) { delta = dev->pm.last_activity + delta - jiffies; goto out; @@ -1924,179 +1970,27 @@ void mt7615_mac_work(struct work_struct *work) MT7615_WATCHDOG_TIME); } -static bool -mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) -{ - bool ret; - - 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; -} - -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); - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - mt7615_mcu_add_beacon(dev, hw, vif, - vif->bss_conf.enable_beacon); - break; - default: - break; - } -} - -static void -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); -} - -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); - - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WM], true); - for (i = 0; i < __MT_TXQ_MAX; i++) - mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); - - mt76_for_each_q_rx(&dev->mt76, 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); -} -EXPORT_SYMBOL_GPL(mt7615_dma_reset); - void mt7615_tx_token_put(struct mt7615_dev *dev) { struct mt76_txwi_cache *txwi; int id; - spin_lock_bh(&dev->token_lock); - idr_for_each_entry(&dev->token, txwi, id) { + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { mt7615_txp_skb_unmap(&dev->mt76, txwi); - if (txwi->skb) - dev_kfree_skb_any(txwi->skb); + if (txwi->skb) { + struct ieee80211_hw *hw; + + hw = mt76_tx_status_get_hw(&dev->mt76, txwi->skb); + ieee80211_free_txskb(hw, txwi->skb); + } mt76_put_txwi(&dev->mt76, txwi); } - spin_unlock_bh(&dev->token_lock); - idr_destroy(&dev->token); + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); } EXPORT_SYMBOL_GPL(mt7615_tx_token_put); -void mt7615_mac_reset_work(struct work_struct *work) -{ - struct mt7615_phy *phy2; - struct mt76_phy *ext_phy; - struct mt7615_dev *dev; - - dev = container_of(work, struct mt7615_dev, reset_work); - ext_phy = dev->mt76.phy2; - phy2 = ext_phy ? ext_phy->priv : NULL; - - if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) - return; - - ieee80211_stop_queues(mt76_hw(dev)); - if (ext_phy) - ieee80211_stop_queues(ext_phy->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->mphy.mac_work); - del_timer_sync(&dev->phy.roc_timer); - cancel_work_sync(&dev->phy.roc_work); - if (phy2) { - cancel_delayed_work_sync(&phy2->mt76->mac_work); - del_timer_sync(&phy2->roc_timer); - cancel_work_sync(&phy2->roc_work); - } - - /* lock/unlock all queues to ensure that no tx is pending */ - mt76_txq_schedule_all(&dev->mphy); - if (ext_phy) - mt76_txq_schedule_all(ext_phy); - - mt76_worker_disable(&dev->mt76.tx_worker); - napi_disable(&dev->mt76.napi[0]); - napi_disable(&dev->mt76.napi[1]); - napi_disable(&dev->mt76.tx_napi); - - mt7615_mutex_acquire(dev); - - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_PDMA_STOPPED); - - mt7615_tx_token_put(dev); - idr_init(&dev->token); - - if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7615_dma_reset(dev); - - 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); - - mt76_worker_enable(&dev->mt76.tx_worker); - 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 (ext_phy) - ieee80211_wake_queues(ext_phy->hw); - - mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_RESET_DONE); - mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); - - mt7615_update_beacons(dev); - - mt7615_mutex_release(dev); - - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, - MT7615_WATCHDOG_TIME); - if (phy2) - ieee80211_queue_delayed_work(ext_phy->hw, - &phy2->mt76->mac_work, - MT7615_WATCHDOG_TIME); - -} - static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy) { struct mt7615_dev *dev = phy->dev; @@ -2304,8 +2198,10 @@ void mt7615_coredump_work(struct work_struct *work) break; skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); - if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) - break; + if (data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) { + dev_kfree_skb(skb); + continue; + } memcpy(data, skb->data, skb->len); data += skb->len; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index 169f4e17b5b4..6bf9da040196 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -33,6 +33,9 @@ enum rx_pkt_type { #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) #define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) +#define MT_RXD1_FIRST_AMSDU_FRAME GENMASK(1, 0) +#define MT_RXD1_MID_AMSDU_FRAME BIT(1) +#define MT_RXD1_LAST_AMSDU_FRAME BIT(0) #define MT_RXD1_NORMAL_HDR_TRANS BIT(23) #define MT_RXD1_NORMAL_HDR_OFFSET BIT(22) #define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16) @@ -78,6 +81,11 @@ enum rx_pkt_type { #define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8) #define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) +#define MT_RXD4_FRAME_CONTROL GENMASK(15, 0) + +#define MT_RXD6_SEQ_CTRL GENMASK(15, 0) +#define MT_RXD6_QOS_CTL GENMASK(31, 16) + #define MT_RXV1_ACID_DET_H BIT(31) #define MT_RXV1_ACID_DET_L BIT(30) #define MT_RXV1_VHTA2_B8_B3 GENMASK(29, 24) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 25faf486d279..39733b351ac4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -29,6 +29,7 @@ static int mt7615_start(struct ieee80211_hw *hw) struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); bool running; + int ret; if (!mt7615_wait_for_mcu_init(dev)) return -EIO; @@ -38,21 +39,42 @@ static int mt7615_start(struct ieee80211_hw *hw) running = mt7615_dev_running(dev); if (!running) { - mt7615_mcu_set_pm(dev, 0, 0); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + ret = mt7615_mcu_set_pm(dev, 0, 0); + if (ret) + goto out; + + ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, true, false); + if (ret) + goto out; + mt7615_mac_enable_nf(dev, 0); } if (phy != &dev->phy) { - mt7615_mcu_set_pm(dev, 1, 0); - mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false); + ret = mt7615_mcu_set_pm(dev, 1, 0); + if (ret) + goto out; + + ret = mt76_connac_mcu_set_mac_enable(&dev->mt76, 1, true, false); + if (ret) + goto out; + mt7615_mac_enable_nf(dev, 1); } - if (mt7615_firmware_offload(dev)) - mt76_connac_mcu_set_channel_domain(phy->mt76); + if (mt7615_firmware_offload(dev)) { + ret = mt76_connac_mcu_set_channel_domain(phy->mt76); + if (ret) + goto out; - mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + ret = mt76_connac_mcu_set_rate_txpower(phy->mt76); + if (ret) + goto out; + } + + ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH); + if (ret) + goto out; set_bit(MT76_STATE_RUNNING, &phy->mt76->state); @@ -62,9 +84,10 @@ static int mt7615_start(struct ieee80211_hw *hw) if (!running) mt7615_mac_reset_counters(dev); +out: mt7615_mutex_release(dev); - return 0; + return ret; } static void mt7615_stop(struct ieee80211_hw *hw) @@ -197,7 +220,9 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, dev->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx); - mt7615_mcu_set_dbdc(dev); + ret = mt7615_mcu_set_dbdc(dev); + if (ret) + goto out; idx = MT7615_WTBL_RESERVED - mvif->mt76.idx; @@ -217,8 +242,6 @@ static int mt7615_add_interface(struct ieee80211_hw *hw, ret = mt7615_mcu_add_dev_info(phy, vif, true); if (ret) goto out; - - mt7615_mac_set_beacon_filter(phy, vif, true); out: mt7615_mutex_release(dev); @@ -234,17 +257,17 @@ static void mt7615_remove_interface(struct ieee80211_hw *hw, struct mt7615_phy *phy = mt7615_hw_phy(hw); int idx = msta->wcid.idx; - /* TODO: disable beacon for the bss */ - mt7615_mutex_acquire(dev); + mt7615_mcu_add_bss_info(phy, vif, NULL, false); + mt7615_mcu_sta_add(phy, vif, NULL, false); + mt76_testmode_reset(phy->mt76, true); if (vif == phy->monitor_vif) phy->monitor_vif = NULL; mt76_connac_free_pending_tx_skbs(&dev->pm, &msta->wcid); - mt7615_mac_set_beacon_filter(phy, vif, false); mt7615_mcu_add_dev_info(phy, vif, false); rcu_assign_pointer(dev->mt76.wcid[idx], NULL); @@ -296,8 +319,13 @@ int mt7615_set_channel(struct mt7615_phy *phy) mt76_set_channel(phy->mt76); if (is_mt7615(&dev->mt76) && dev->flash_eeprom) { - mt7615_mcu_apply_rx_dcoc(phy); - mt7615_mcu_apply_tx_dpd(phy); + ret = mt7615_mcu_apply_rx_dcoc(phy); + if (ret) + goto out; + + ret = mt7615_mcu_apply_tx_dpd(phy); + if (ret) + goto out; } ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH); @@ -306,8 +334,13 @@ int mt7615_set_channel(struct mt7615_phy *phy) mt7615_mac_set_timing(phy); ret = mt7615_dfs_init_radar_detector(phy); + if (ret) + goto out; + mt7615_mac_cca_stats_reset(phy); - mt7615_mcu_set_sku_en(phy, true); + ret = mt7615_mcu_set_sku_en(phy, true); + if (ret) + goto out; mt7615_mac_reset_counters(dev); phy->noise = 0; @@ -318,8 +351,7 @@ out: mt7615_mutex_release(dev); - mt76_txq_schedule_all(phy->mt76); - + mt76_worker_schedule(&dev->mt76.tx_worker); if (!mt76_testmode_enabled(phy->mt76)) ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mt76->mac_work, @@ -337,7 +369,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx, err; + int idx = key->keyidx, err = 0; + u8 *wcid_keyidx = &wcid->hw_key_idx; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -352,6 +385,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -369,12 +403,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt7615_mutex_acquire(dev); - if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); @@ -383,6 +418,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); +out: mt7615_mutex_release(dev); return err; @@ -526,11 +562,11 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BEACON_ENABLED) { - mt7615_mcu_add_bss_info(phy, vif, NULL, info->enable_beacon); - mt7615_mcu_sta_add(phy, vif, NULL, info->enable_beacon); + if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) { + mt7615_mcu_add_bss_info(phy, vif, NULL, true); + mt7615_mcu_sta_add(phy, vif, NULL, true); - if (vif->p2p && info->enable_beacon) + if (vif->p2p) mt7615_mcu_set_p2p_oppps(hw, vif); } @@ -541,8 +577,16 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_PS) mt76_connac_mcu_set_vif_ps(&dev->mt76, vif); - if (changed & BSS_CHANGED_ARP_FILTER) - mt7615_mcu_update_arp_filter(hw, vif, info); + if ((changed & BSS_CHANGED_ARP_FILTER) && + mt7615_firmware_offload(dev)) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + + mt76_connac_mcu_update_arp_filter(&dev->mt76, &mvif->mt76, + info); + } + + if (changed & BSS_CHANGED_ASSOC) + mt7615_mac_set_beacon_filter(phy, vif, info->assoc); mt7615_mutex_release(dev); } @@ -583,15 +627,21 @@ int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (err) return err; - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) - mt7615_mcu_add_bss_info(phy, vif, sta, true); + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + err = mt7615_mcu_add_bss_info(phy, vif, sta, true); + if (err) + return err; + } + mt7615_mac_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); - mt7615_mcu_sta_add(&dev->phy, vif, sta, true); + err = mt7615_mcu_sta_add(&dev->phy, vif, sta, true); + if (err) + return err; mt76_connac_power_save_sched(phy->mt76, &dev->pm); - return 0; + return err; } EXPORT_SYMBOL_GPL(mt7615_mac_sta_add); @@ -643,28 +693,25 @@ static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw, break; } msta->n_rates = i; - if (!test_bit(MT76_STATE_PM, &phy->mt76->state)) + if (mt76_connac_pm_ref(phy->mt76, &dev->pm)) { mt7615_mac_set_rates(phy, msta, NULL, msta->rates); + mt76_connac_pm_unref(&dev->pm); + } spin_unlock_bh(&dev->mt76.lock); } -static void -mt7615_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +void mt7615_tx_worker(struct mt76_worker *w) { - struct mt7615_dev *dev = mt7615_hw_dev(hw); - struct mt7615_phy *phy = mt7615_hw_phy(hw); - struct mt76_phy *mphy = phy->mt76; - - if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) - return; + struct mt7615_dev *dev = container_of(w, struct mt7615_dev, + mt76.tx_worker); - if (test_bit(MT76_STATE_PM, &mphy->state)) { + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) { queue_work(dev->mt76.wq, &dev->pm.wake_work); return; } - dev->pm.last_activity = jiffies; - mt76_worker_schedule(&dev->mt76.tx_worker); + mt76_tx_worker_run(&dev->mt76); + mt76_connac_pm_unref(&dev->pm); } static void mt7615_tx(struct ieee80211_hw *hw, @@ -692,9 +739,9 @@ static void mt7615_tx(struct ieee80211_hw *hw, wcid = &msta->wcid; } - if (!test_bit(MT76_STATE_PM, &mphy->state)) { - dev->pm.last_activity = jiffies; + if (mt76_connac_pm_ref(mphy, &dev->pm)) { mt76_tx(mphy, control->sta, wcid, skb); + mt76_connac_pm_unref(&dev->pm); return; } @@ -711,13 +758,13 @@ static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, u32 val) { struct mt7615_dev *dev = mt7615_hw_dev(hw); struct mt7615_phy *phy = mt7615_hw_phy(hw); - int band = phy != &dev->phy; + int err, band = phy != &dev->phy; mt7615_mutex_acquire(dev); - mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band); + err = mt76_connac_mcu_set_rts_thresh(&dev->mt76, val, band); mt7615_mutex_release(dev); - return 0; + return err; } static int @@ -745,16 +792,16 @@ 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_add_rx_ba(dev, params, true); + ret = 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_add_rx_ba(dev, params, false); + ret = mt7615_mcu_add_rx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - mt7615_mcu_add_tx_ba(dev, params, true); + ret = mt7615_mcu_add_tx_ba(dev, params, true); ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid); ieee80211_send_bar(vif, sta->addr, tid, IEEE80211_SN_TO_SEQ(ssn)); @@ -762,7 +809,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; - mt7615_mcu_add_tx_ba(dev, params, false); + ret = mt7615_mcu_add_tx_ba(dev, params, false); break; case IEEE80211_AMPDU_TX_START: ssn = mt7615_mac_get_sta_tid_sn(dev, msta->wcid.idx, tid); @@ -771,7 +818,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, break; case IEEE80211_AMPDU_TX_STOP_CONT: mtxq->aggr = false; - mt7615_mcu_add_tx_ba(dev, params, false); + ret = mt7615_mcu_add_tx_ba(dev, params, false); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } @@ -803,26 +850,38 @@ mt7615_get_stats(struct ieee80211_hw *hw, struct mt7615_phy *phy = mt7615_hw_phy(hw); struct mib_stats *mib = &phy->mib; + mt7615_mutex_acquire(phy->dev); + stats->dot11RTSSuccessCount = mib->rts_cnt; stats->dot11RTSFailureCount = mib->rts_retries_cnt; stats->dot11FCSErrorCount = mib->fcs_err_cnt; stats->dot11ACKFailureCount = mib->ack_fail_cnt; + memset(mib, 0, sizeof(*mib)); + + mt7615_mutex_release(phy->dev); + return 0; } static u64 mt7615_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); union { u64 t64; u32 t32[2]; } tsf; + u16 idx = mvif->mt76.omac_idx; + u32 reg; + + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); mt7615_mutex_acquire(dev); - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + mt76_set(dev, reg, MT_LPON_TCR_MODE); /* TSF read */ tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0); tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1); @@ -835,18 +894,24 @@ static void mt7615_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 timestamp) { + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); union { u64 t64; u32 t32[2]; } tsf = { .t64 = timestamp, }; + u16 idx = mvif->mt76.omac_idx; + u32 reg; + + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + reg = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); mt7615_mutex_acquire(dev); mt76_wr(dev, MT_LPON_UTTR0, tsf.t32[0]); mt76_wr(dev, MT_LPON_UTTR1, tsf.t32[1]); /* TSF software overwrite */ - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_WRITE); + mt76_set(dev, reg, MT_LPON_TCR_WRITE); mt7615_mutex_release(dev); } @@ -1069,6 +1134,7 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt7615_phy *phy = mt7615_hw_phy(hw); + int err; if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) return 0; @@ -1077,10 +1143,26 @@ static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, cancel_work_sync(&phy->roc_work); mt7615_mutex_acquire(phy->dev); - mt7615_mcu_set_roc(phy, vif, NULL, 0); + err = mt7615_mcu_set_roc(phy, vif, NULL, 0); mt7615_mutex_release(phy->dev); - return 0; + return err; +} + +static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + bool enabled) +{ + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + + mt7615_mcu_sta_update_hdr_trans(dev, vif, sta); } #ifdef CONFIG_PM @@ -1183,9 +1265,10 @@ const struct ieee80211_ops mt7615_ops = { .sta_remove = mt7615_sta_remove, .sta_pre_rcu_remove = mt76_sta_pre_rcu_remove, .set_key = mt7615_set_key, + .sta_set_decap_offload = mt7615_sta_set_decap_offload, .ampdu_action = mt7615_ampdu_action, .set_rts_threshold = mt7615_set_rts_threshold, - .wake_tx_queue = mt7615_wake_tx_queue, + .wake_tx_queue = mt76_wake_tx_queue, .sta_rate_tbl_update = mt7615_sta_rate_tbl_update, .sw_scan_start = mt76_sw_scan, .sw_scan_complete = mt76_sw_scan_complete, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index 631596fc2f36..aa42af9ebfd6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -175,8 +175,8 @@ int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd, int ret = 0; if (!skb) { - dev_err(mdev->dev, "Message %ld (seq %d) timeout\n", - cmd & MCU_CMD_MASK, seq); + dev_err(mdev->dev, "Message %08x (seq %d) timeout\n", + cmd, seq); return -ETIMEDOUT; } @@ -274,7 +274,7 @@ int mt7615_rf_wr(struct mt7615_dev *dev, u32 wf, u32 reg, u32 val) sizeof(req), false); } -static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) +void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) { if (!is_mt7622(&dev->mt76)) return; @@ -283,20 +283,30 @@ static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en) MT_INFRACFG_MISC_AP2CONN_WAKE, !en * MT_INFRACFG_MISC_AP2CONN_WAKE); } +EXPORT_SYMBOL_GPL(mt7622_trigger_hif_int); static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; struct mt76_dev *mdev = &dev->mt76; u32 addr; int err; - addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST; + if (is_mt7663(mdev)) { + /* Clear firmware own via N9 eint */ + mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN); + mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); + + addr = MT_CONN_HIF_ON_LPCTL; + } else { + addr = MT_CFG_LPCR_HOST; + } + mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN); mt7622_trigger_hif_int(dev, true); - addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST; err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000); mt7622_trigger_hif_int(dev, false); @@ -308,15 +318,22 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev) clear_bit(MT76_STATE_PM, &mphy->state); + pm->stats.last_wake_event = jiffies; + pm->stats.doze_time += pm->stats.last_wake_event - + pm->stats.last_doze_event; + return 0; } static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; - int i; + struct mt76_connac_pm *pm = &dev->pm; + int i, err = 0; + + mutex_lock(&pm->mutex); - if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state)) + if (!test_bit(MT76_STATE_PM, &mphy->state)) goto out; for (i = 0; i < MT7615_DRV_OWN_RETRY_COUNT; i++) { @@ -328,24 +345,31 @@ static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev) if (i == MT7615_DRV_OWN_RETRY_COUNT) { dev_err(dev->mt76.dev, "driver own failed\n"); - set_bit(MT76_STATE_PM, &mphy->state); - return -EIO; + err = -EIO; + goto out; } + clear_bit(MT76_STATE_PM, &mphy->state); + pm->stats.last_wake_event = jiffies; + pm->stats.doze_time += pm->stats.last_wake_event - + pm->stats.last_doze_event; out: - dev->pm.last_activity = jiffies; + mutex_unlock(&pm->mutex); - return 0; + return err; } static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) { struct mt76_phy *mphy = &dev->mt76.phy; + struct mt76_connac_pm *pm = &dev->pm; int err = 0; u32 addr; - if (test_and_set_bit(MT76_STATE_PM, &mphy->state)) - return 0; + mutex_lock(&pm->mutex); + + if (mt76_connac_skip_fw_pmctrl(mphy, pm)) + goto out; mt7622_trigger_hif_int(dev, true); @@ -362,6 +386,12 @@ static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev) mt7622_trigger_hif_int(dev, false); + pm->stats.last_doze_event = jiffies; + pm->stats.awake_time += pm->stats.last_doze_event - + pm->stats.last_wake_event; +out: + mutex_unlock(&pm->mutex); + return err; } @@ -373,6 +403,23 @@ mt7615_mcu_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) } static void +mt7615_mcu_rx_csa_notify(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_phy *ext_phy = mt7615_ext_phy(dev); + struct mt76_phy *mphy = &dev->mt76.phy; + struct mt7615_mcu_csa_notify *c; + + c = (struct mt7615_mcu_csa_notify *)skb->data; + + if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx)) + mphy = dev->mt76.phy2; + + ieee80211_iterate_active_interfaces_atomic(mphy->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_mcu_csa_finish, mphy->hw); +} + +static void mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) { struct mt76_phy *mphy = &dev->mt76.phy; @@ -380,7 +427,7 @@ mt7615_mcu_rx_radar_detected(struct mt7615_dev *dev, struct sk_buff *skb) r = (struct mt7615_mcu_rdd_report *)skb->data; - if (r->idx && dev->mt76.phy2) + if (r->band_idx && dev->mt76.phy2) mphy = dev->mt76.phy2; ieee80211_radar_detected(mphy->hw); @@ -406,7 +453,8 @@ mt7615_mcu_rx_log_message(struct mt7615_dev *dev, struct sk_buff *skb) break; } - wiphy_info(mt76_hw(dev)->wiphy, "%s: %s", type, data); + wiphy_info(mt76_hw(dev)->wiphy, "%s: %.*s", type, + (int)(skb->len - sizeof(*rxd)), data); } static void @@ -419,9 +467,7 @@ mt7615_mcu_rx_ext_event(struct mt7615_dev *dev, struct sk_buff *skb) 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); + mt7615_mcu_rx_csa_notify(dev, skb); break; case MCU_EXT_EVENT_FW_LOG_2_HOST: mt7615_mcu_rx_log_message(dev, skb); @@ -685,6 +731,9 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, }; struct sk_buff *skb; + if (!enable) + goto out; + skb = ieee80211_beacon_get_template(hw, vif, &offs); if (!skb) return -EINVAL; @@ -714,6 +763,7 @@ mt7615_mcu_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); +out: return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_BCN_OFFLOAD, &req, sizeof(req), true); } @@ -973,7 +1023,7 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, mt76_connac_mcu_sta_basic_tlv(sskb, vif, sta, enable); if (enable && sta) - mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif); + mt76_connac_mcu_sta_tlv(phy->mt76, sskb, sta, vif, 0); wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, WTBL_RESET_AND_SET, NULL, @@ -987,6 +1037,8 @@ mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif, if (sta) mt76_connac_mcu_wtbl_ht_tlv(&dev->mt76, wskb, sta, NULL, wtbl_hdr); + mt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, &msta->wcid, NULL, + wtbl_hdr); } cmd = enable ? MCU_EXT_CMD_WTBL_UPDATE : MCU_EXT_CMD_STA_REC_UPDATE; @@ -1040,6 +1092,9 @@ mt7615_mcu_sta_ba(struct mt7615_dev *dev, wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, WTBL_SET, sta_wtbl, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + mt76_connac_mcu_wtbl_ba_tlv(&dev->mt76, skb, params, enable, tx, sta_wtbl, wtbl_hdr); @@ -1068,10 +1123,15 @@ __mt7615_mcu_add_sta(struct mt76_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta, bool enable, int cmd) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt76_wcid *wcid; + struct mt76_sta_cmd_info info = { + .sta = sta, + .vif = vif, + .enable = enable, + .cmd = cmd, + }; - wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid; - return mt76_connac_mcu_add_sta_cmd(phy, vif, sta, wcid, enable, cmd); + info.wcid = sta ? (struct mt76_wcid *)sta->drv_priv : &mvif->sta.wcid; + return mt76_connac_mcu_add_sta_cmd(phy, &info); } static int @@ -1094,6 +1154,25 @@ static const struct mt7615_mcu_ops sta_update_ops = { .set_fw_ctrl = mt7615_mcu_fw_pmctrl, }; +int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + struct wtbl_req_hdr *wtbl_hdr; + struct sk_buff *skb = NULL; + + wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(&dev->mt76, &msta->wcid, + WTBL_SET, NULL, &skb); + if (IS_ERR(wtbl_hdr)) + return PTR_ERR(wtbl_hdr); + + mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, &msta->wcid, NULL, wtbl_hdr); + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_EXT_CMD_WTBL_UPDATE, + true); +} + static int mt7615_mcu_uni_ctrl_pm_state(struct mt7615_dev *dev, int band, int state) { @@ -1120,8 +1199,8 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, __le16 tim_ie_pos; __le16 csa_ie_pos; __le16 bcc_ie_pos; - /* 0: enable beacon offload - * 1: disable beacon offload + /* 0: disable beacon offload + * 1: enable beacon offload * 2: update probe respond offload */ u8 enable; @@ -1144,6 +1223,9 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, }; struct sk_buff *skb; + if (!enable) + goto out; + skb = ieee80211_beacon_get_template(mt76_hw(dev), vif, &offs); if (!skb) return -EINVAL; @@ -1168,6 +1250,7 @@ mt7615_mcu_uni_add_beacon_offload(struct mt7615_dev *dev, } dev_kfree_skb(skb); +out: return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_BSS_INFO_UPDATE, &req, sizeof(req), true); } @@ -1279,25 +1362,26 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) const struct firmware *fw = NULL; int len, ret, sem; + ret = firmware_request_nowarn(&fw, name, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto release_fw; + } + sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true); switch (sem) { case PATCH_IS_DL: - return 0; + goto release_fw; case PATCH_NOT_DL_SEM_SUCCESS: break; default: dev_err(dev->mt76.dev, "Failed to get patch semaphore\n"); - return -EAGAIN; - } - - ret = firmware_request_nowarn(&fw, name, dev->mt76.dev); - if (ret) - goto out; - - if (!fw || !fw->data || fw->size < sizeof(*hdr)) { - dev_err(dev->mt76.dev, "Invalid firmware\n"); - ret = -EINVAL; - goto out; + ret = -EAGAIN; + goto release_fw; } hdr = (const struct mt7615_patch_hdr *)(fw->data); @@ -1326,8 +1410,6 @@ static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name) dev_err(dev->mt76.dev, "Failed to start patch\n"); out: - release_firmware(fw); - sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false); switch (sem) { case PATCH_REL_SEM_SUCCESS: @@ -1338,6 +1420,9 @@ out: break; } +release_fw: + release_firmware(fw); + return ret; } @@ -1427,8 +1512,7 @@ static int mt7615_load_n9(struct mt7615_dev *dev, const char *name) sizeof(dev->mt76.hw->wiphy->fw_version), "%.10s-%.15s", hdr->fw_ver, hdr->build_date); - if (!is_mt7615(&dev->mt76) && - !strncmp(hdr->fw_ver, "2.0", sizeof(hdr->fw_ver))) { + if (!is_mt7615(&dev->mt76)) { dev->fw_ver = MT7615_FIRMWARE_V2; dev->mcu_ops = &sta_update_ops; } else { @@ -2084,16 +2168,80 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku) { struct mt76_phy *mphy = phy->mt76; struct ieee80211_hw *hw = mphy->hw; + struct mt76_power_limits limits; + s8 *limits_array = (s8 *)&limits; int n_chains = hweight8(mphy->antenna_mask); int tx_power; int i; + static const u8 sku_mapping[] = { +#define SKU_FIELD(_type, _field) \ + [MT_SKU_##_type] = offsetof(struct mt76_power_limits, _field) + SKU_FIELD(CCK_1_2, cck[0]), + SKU_FIELD(CCK_55_11, cck[2]), + SKU_FIELD(OFDM_6_9, ofdm[0]), + SKU_FIELD(OFDM_12_18, ofdm[2]), + SKU_FIELD(OFDM_24_36, ofdm[4]), + SKU_FIELD(OFDM_48, ofdm[6]), + SKU_FIELD(OFDM_54, ofdm[7]), + SKU_FIELD(HT20_0_8, mcs[0][0]), + SKU_FIELD(HT20_32, ofdm[0]), + SKU_FIELD(HT20_1_2_9_10, mcs[0][1]), + SKU_FIELD(HT20_3_4_11_12, mcs[0][3]), + SKU_FIELD(HT20_5_13, mcs[0][5]), + SKU_FIELD(HT20_6_14, mcs[0][6]), + SKU_FIELD(HT20_7_15, mcs[0][7]), + SKU_FIELD(HT40_0_8, mcs[1][0]), + SKU_FIELD(HT40_32, ofdm[0]), + SKU_FIELD(HT40_1_2_9_10, mcs[1][1]), + SKU_FIELD(HT40_3_4_11_12, mcs[1][3]), + SKU_FIELD(HT40_5_13, mcs[1][5]), + SKU_FIELD(HT40_6_14, mcs[1][6]), + SKU_FIELD(HT40_7_15, mcs[1][7]), + SKU_FIELD(VHT20_0, mcs[0][0]), + SKU_FIELD(VHT20_1_2, mcs[0][1]), + SKU_FIELD(VHT20_3_4, mcs[0][3]), + SKU_FIELD(VHT20_5_6, mcs[0][5]), + SKU_FIELD(VHT20_7, mcs[0][7]), + SKU_FIELD(VHT20_8, mcs[0][8]), + SKU_FIELD(VHT20_9, mcs[0][9]), + SKU_FIELD(VHT40_0, mcs[1][0]), + SKU_FIELD(VHT40_1_2, mcs[1][1]), + SKU_FIELD(VHT40_3_4, mcs[1][3]), + SKU_FIELD(VHT40_5_6, mcs[1][5]), + SKU_FIELD(VHT40_7, mcs[1][7]), + SKU_FIELD(VHT40_8, mcs[1][8]), + SKU_FIELD(VHT40_9, mcs[1][9]), + SKU_FIELD(VHT80_0, mcs[2][0]), + SKU_FIELD(VHT80_1_2, mcs[2][1]), + SKU_FIELD(VHT80_3_4, mcs[2][3]), + SKU_FIELD(VHT80_5_6, mcs[2][5]), + SKU_FIELD(VHT80_7, mcs[2][7]), + SKU_FIELD(VHT80_8, mcs[2][8]), + SKU_FIELD(VHT80_9, mcs[2][9]), + SKU_FIELD(VHT160_0, mcs[3][0]), + SKU_FIELD(VHT160_1_2, mcs[3][1]), + SKU_FIELD(VHT160_3_4, mcs[3][3]), + SKU_FIELD(VHT160_5_6, mcs[3][5]), + SKU_FIELD(VHT160_7, mcs[3][7]), + SKU_FIELD(VHT160_8, mcs[3][8]), + SKU_FIELD(VHT160_9, mcs[3][9]), +#undef SKU_FIELD + }; tx_power = hw->conf.power_level * 2 - mt76_tx_power_nss_delta(n_chains); + + tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan, + &limits, tx_power); mphy->txpower_cur = tx_power; + if (is_mt7663(mphy->dev)) { + memset(sku, tx_power, MT_SKU_4SS_DELTA + 1); + return; + } + for (i = 0; i < MT_SKU_1SS_DELTA; i++) - sku[i] = tx_power; + sku[i] = limits_array[sku_mapping[i]]; for (i = 0; i < 4; i++) { int delta = 0; @@ -2155,7 +2303,7 @@ int mt7615_mcu_set_chan_info(struct mt7615_phy *phy, int cmd) .center_chan2 = ieee80211_frequency_to_channel(freq2), }; - if (dev->mt76.hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + if (phy->mt76->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) req.switch_reason = CH_SWITCH_SCAN_BYPASS_DPD; else if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) && chandef->chan->dfs_state != NL80211_DFS_AVAILABLE) @@ -2497,6 +2645,26 @@ out: return ret; } +int mt7615_mcu_set_rx_hdr_trans_blacklist(struct mt7615_dev *dev) +{ + struct { + u8 operation; + u8 count; + u8 _rsv[2]; + u8 index; + u8 enable; + __le16 etype; + } req = { + .operation = 1, + .count = 1, + .enable = 1, + .etype = cpu_to_le16(ETH_P_PAE), + }; + + return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_RX_HDR_TRANS, + &req, sizeof(req), false); +} + int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable) { @@ -2557,53 +2725,6 @@ int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, sizeof(req), false); } -int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info) -{ - struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_dev *dev = mt7615_hw_dev(hw); - struct sk_buff *skb; - int i, len = min_t(int, info->arp_addr_cnt, - IEEE80211_BSS_ARP_ADDR_LIST_LEN); - struct { - struct { - u8 bss_idx; - u8 pad[3]; - } __packed hdr; - struct mt76_connac_arpns_tlv arp; - } req_hdr = { - .hdr = { - .bss_idx = mvif->mt76.idx, - }, - .arp = { - .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP), - .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)), - .ips_num = len, - .mode = 2, /* update */ - .option = 1, - }, - }; - - if (!mt7615_firmware_offload(dev)) - return 0; - - skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, - sizeof(req_hdr) + len * sizeof(__be32)); - if (!skb) - return -ENOMEM; - - skb_put_data(skb, &req_hdr, sizeof(req_hdr)); - for (i = 0; i < len; i++) { - u8 *addr = (u8 *)skb_put(skb, sizeof(__be32)); - - memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); - } - - return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, - true); -} - int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 3874f45da9eb..98c383e400a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -176,10 +176,18 @@ struct mt7615_mcu_rxd { u8 s2d_index; }; +struct mt7615_mcu_csa_notify { + struct mt7615_mcu_rxd rxd; + + u8 omac_idx; + u8 csa_count; + u8 rsv[2]; +} __packed; + struct mt7615_mcu_rdd_report { struct mt7615_mcu_rxd rxd; - u8 idx; + u8 band_idx; u8 long_detected; u8 constant_prf_detected; u8 staggered_prf_detected; @@ -362,30 +370,6 @@ enum { BSS_INFO_MAX_NUM }; -#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 sta_rec_uapsd) + \ - sizeof(struct tlv) + \ - MT7615_WTBL_UPDATE_MAX_SIZE) - -#define MT7615_WTBL_UPDATE_BA_SIZE (sizeof(struct wtbl_req_hdr) + \ - sizeof(struct wtbl_ba)) - enum { CH_SWITCH_NORMAL = 0, CH_SWITCH_SCAN = 3, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index a7f92fa0488f..202ea235415e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: ISC +/* Copyright (C) 2020 MediaTek Inc. */ + #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -102,6 +105,7 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t) { struct mt7615_dev *dev = from_tasklet(dev, t, irq_tasklet); u32 intr, mask = 0, tx_mcu_mask = mt7615_tx_mcu_int_mask(dev); + u32 mcu_int; mt76_wr(dev, MT_INT_MASK_CSR, 0); @@ -125,15 +129,23 @@ static void mt7615_irq_tasklet(struct tasklet_struct *t) if (intr & 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 (!(intr & (MT_INT_MCU_CMD | MT7663_INT_MCU_CMD))) + return; - 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); - } + if (is_mt7663(&dev->mt76)) { + mcu_int = mt76_rr(dev, MT_MCU2HOST_INT_STATUS); + mcu_int &= MT7663_MCU_CMD_ERROR_MASK; + } else { + mcu_int = mt76_rr(dev, MT_MCU_CMD); + mcu_int &= MT_MCU_CMD_ERROR_MASK; } + + if (!mcu_int) + return; + + dev->reset_state = mcu_int; + ieee80211_queue_work(mt76_hw(dev), &dev->reset_work); + wake_up(&dev->reset_wait); } static u32 __mt7615_reg_addr(struct mt7615_dev *dev, u32 addr) @@ -178,6 +190,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, + .token_size = MT7615_TOKEN_SIZE, .tx_prepare_skb = mt7615_tx_prepare_skb, .tx_complete_skb = mt7615_tx_complete_skb, .rx_skb = mt7615_queue_rx_skb, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index 491841bc6291..989f05ed4377 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -133,11 +133,11 @@ struct mt7615_vif { }; struct mib_stats { - u16 ack_fail_cnt; - u16 fcs_err_cnt; - u16 rts_cnt; - u16 rts_retries_cnt; - u16 ba_miss_cnt; + u32 ack_fail_cnt; + u32 fcs_err_cnt; + u32 rts_cnt; + u32 rts_retries_cnt; + u32 ba_miss_cnt; unsigned long aggr_per; }; @@ -168,7 +168,7 @@ struct mt7615_phy { u8 rdd_state; int dfs_state; - __le32 rx_ampdu_ts; + u32 rx_ampdu_ts; u32 ampdu_ref; struct mib_stats mib; @@ -263,9 +263,6 @@ struct mt7615_dev { bool flash_eeprom; bool dbdc_support; - spinlock_t token_lock; - struct idr token; - u8 fw_ver; struct work_struct rate_work; @@ -376,6 +373,7 @@ int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev, enum nl80211_band band); int mt7615_wait_pdma_busy(struct mt7615_dev *dev); int mt7615_dma_init(struct mt7615_dev *dev); +void mt7615_dma_start(struct mt7615_dev *dev); void mt7615_dma_cleanup(struct mt7615_dev *dev); int mt7615_mcu_init(struct mt7615_dev *dev); bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev); @@ -408,11 +406,6 @@ static inline bool is_mt7615(struct mt76_dev *dev) return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; } -static inline bool is_mt7663(struct mt76_dev *dev) -{ - return mt76_chip(dev) == 0x7663; -} - static inline bool is_mt7611(struct mt76_dev *dev) { return mt76_chip(dev) == 0x7611; @@ -512,6 +505,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info); +void mt7615_tx_worker(struct mt76_worker *w); void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e); void mt7615_tx_token_put(struct mt7615_dev *dev); void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, @@ -524,6 +518,10 @@ void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, void mt7615_mac_work(struct work_struct *work); void mt7615_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *txwi); +int mt7615_mcu_sta_update_hdr_trans(struct mt7615_dev *dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +int mt7615_mcu_set_rx_hdr_trans_blacklist(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); @@ -549,14 +547,13 @@ int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy, bool enable); int mt7615_mcu_set_bss_pm(struct mt7615_dev *dev, struct ieee80211_vif *vif, bool enable); -int mt7615_mcu_update_arp_filter(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info); int __mt7663_load_firmware(struct mt7615_dev *dev); u32 mt7615_mcu_reg_rr(struct mt76_dev *dev, u32 offset); void mt7615_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val); void mt7615_coredump_work(struct work_struct *work); +void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en); + /* usb */ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 71487f532f36..11f169cdd603 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -13,9 +13,9 @@ #include "mcu.h" static const struct pci_device_id mt7615_pci_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7615) }, - { PCI_DEVICE(0x14c3, 0x7663) }, - { PCI_DEVICE(0x14c3, 0x7611) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7615) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7663) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7611) }, { }, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c index 72395925ddee..ec8ec1a2033f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_init.c @@ -40,13 +40,16 @@ static int mt7615_init_hardware(struct mt7615_dev *dev) mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); INIT_WORK(&dev->mcu_work, mt7615_pci_init_work); - spin_lock_init(&dev->token_lock); - idr_init(&dev->token); - ret = mt7615_eeprom_init(dev, addr); if (ret < 0) return ret; + if (is_mt7663(&dev->mt76)) { + /* Reset RGU */ + mt76_clear(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1)); + mt76_set(dev, MT_MCU_CIRQ_IRQ_SEL(4), BIT(1)); + } + ret = mt7615_dma_init(dev); if (ret) return ret; @@ -76,7 +79,7 @@ mt7615_led_set_config(struct led_classdev *led_cdev, mt76 = container_of(led_cdev, struct mt76_dev, led_cdev); dev = container_of(mt76, struct mt7615_dev, mt76); - if (test_bit(MT76_STATE_PM, &mt76->phy.state)) + if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) return; val = FIELD_PREP(MT_LED_STATUS_DURATION, 0xffff) | @@ -94,6 +97,8 @@ mt7615_led_set_config(struct led_classdev *led_cdev, val |= MT_LED_CTRL_POLARITY(mt76->led_pin); addr = mt7615_reg_map(dev, MT_LED_CTRL); mt76_wr(dev, addr, val); + + mt76_connac_pm_unref(&dev->pm); } static int @@ -126,6 +131,7 @@ int mt7615_register_device(struct mt7615_dev *dev) int ret; mt7615_init_device(dev); + INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { @@ -163,10 +169,9 @@ void mt7615_unregister_device(struct mt7615_dev *dev) mt76_unregister_device(&dev->mt76); if (mcu_running) mt7615_mcu_exit(dev); - mt7615_dma_cleanup(dev); mt7615_tx_token_put(dev); - + mt7615_dma_cleanup(dev); tasklet_disable(&dev->irq_tasklet); mt76_free_device(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index 1b4cb145f38e..d7cbef752f9f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -37,9 +37,7 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) token = le16_to_cpu(txp->hw.msdu_id[0]) & ~MT_MSDU_ID_VALID; - spin_lock_bh(&dev->token_lock); - t = idr_remove(&dev->token, token); - spin_unlock_bh(&dev->token_lock); + t = mt76_token_put(mdev, token); e->skb = t ? t->skb : NULL; } @@ -161,9 +159,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; - spin_lock_bh(&dev->token_lock); - id = idr_alloc(&dev->token, t, 0, MT7615_TOKEN_SIZE, GFP_ATOMIC); - spin_unlock_bh(&dev->token_lock); + id = mt76_token_get(mdev, &t); if (id < 0) return id; @@ -181,3 +177,178 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, return 0; } + +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, dev->mphy.q_tx[i], true); + + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) + mt76_queue_rx_reset(dev, i); + + mt76_tx_status_check(&dev->mt76, NULL, true); + + mt7615_dma_start(dev); +} +EXPORT_SYMBOL_GPL(mt7615_dma_reset); + +static void +mt7615_hif_int_event_trigger(struct mt7615_dev *dev, u8 event) +{ + u32 reg = MT_MCU_INT_EVENT; + + if (is_mt7663(&dev->mt76)) + reg = MT7663_MCU_INT_EVENT; + + mt76_wr(dev, reg, event); + + mt7622_trigger_hif_int(dev, true); + mt7622_trigger_hif_int(dev, false); +} + +static bool +mt7615_wait_reset_state(struct mt7615_dev *dev, u32 state) +{ + bool ret; + + 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; +} + +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); + + switch (vif->type) { + case NL80211_IFTYPE_MESH_POINT: + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_AP: + mt7615_mcu_add_beacon(dev, hw, vif, + vif->bss_conf.enable_beacon); + break; + default: + break; + } +} + +static void +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); +} + +void mt7615_mac_reset_work(struct work_struct *work) +{ + struct mt7615_phy *phy2; + struct mt76_phy *ext_phy; + struct mt7615_dev *dev; + + dev = container_of(work, struct mt7615_dev, reset_work); + ext_phy = dev->mt76.phy2; + phy2 = ext_phy ? ext_phy->priv : NULL; + + if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA)) + return; + + ieee80211_stop_queues(mt76_hw(dev)); + if (ext_phy) + ieee80211_stop_queues(ext_phy->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->mphy.mac_work); + del_timer_sync(&dev->phy.roc_timer); + cancel_work_sync(&dev->phy.roc_work); + if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); + cancel_delayed_work_sync(&phy2->mt76->mac_work); + del_timer_sync(&phy2->roc_timer); + cancel_work_sync(&phy2->roc_work); + } + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mphy); + if (ext_phy) + mt76_txq_schedule_all(ext_phy); + + mt76_worker_disable(&dev->mt76.tx_worker); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + napi_disable(&dev->mt76.tx_napi); + + mt7615_mutex_acquire(dev); + + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_PDMA_STOPPED); + + if (mt7615_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { + mt7615_dma_reset(dev); + + mt7615_tx_token_put(dev); + idr_init(&dev->mt76.token); + + mt76_wr(dev, MT_WPDMA_MEM_RNG_ERR, 0); + + mt7615_hif_int_event_trigger(dev, 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); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); + + mt76_worker_enable(&dev->mt76.tx_worker); + 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 (ext_phy) + ieee80211_wake_queues(ext_phy->hw); + + mt7615_hif_int_event_trigger(dev, MT_MCU_INT_EVENT_RESET_DONE); + mt7615_wait_reset_state(dev, MT_MCU_CMD_NORMAL_STATE); + + mt7615_update_beacons(dev); + + mt7615_mutex_release(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work, + MT7615_WATCHDOG_TIME); + if (phy2) + ieee80211_queue_delayed_work(ext_phy->hw, + &phy2->mt76->mac_work, + MT7615_WATCHDOG_TIME); + +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h index 6e5db015b32c..63c081bb04d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/regs.h @@ -61,6 +61,11 @@ enum mt7615_reg_base { #define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) #define MT_PCIE_REMAP_BASE_2 ((dev)->reg_map[MT_PCIE_REMAP_BASE2]) +#define MT_MCU_CIRQ_BASE 0xc0000 +#define MT_MCU_CIRQ(ofs) (MT_MCU_CIRQ_BASE + (ofs)) + +#define MT_MCU_CIRQ_IRQ_SEL(n) MT_MCU_CIRQ((n) << 2) + #define MT_HIF(ofs) ((dev)->reg_map[MT_HIF_BASE] + (ofs)) #define MT_HIF_RST MT_HIF(0x100) #define MT_HIF_LOGIC_RST_N BIT(4) @@ -88,6 +93,10 @@ enum mt7615_reg_base { #define MT_CFG_LPCR_HOST_FW_OWN BIT(0) #define MT_CFG_LPCR_HOST_DRV_OWN BIT(1) +#define MT_MCU2HOST_INT_STATUS MT_HIF(0x1f0) +#define MT_MCU2HOST_INT_ENABLE MT_HIF(0x1f4) + +#define MT7663_MCU_INT_EVENT MT_HIF(0x108) #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) @@ -102,6 +111,7 @@ enum mt7615_reg_base { #define MT_INT_RX_DONE_ALL GENMASK(1, 0) #define MT_INT_TX_DONE_ALL GENMASK(19, 4) #define MT_INT_TX_DONE(_n) BIT((_n) + 4) +#define MT7663_INT_MCU_CMD BIT(29) #define MT_INT_MCU_CMD BIT(30) #define MT_WPDMA_GLO_CFG MT_HIF(0x208) @@ -138,6 +148,7 @@ enum mt7615_reg_base { #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 MT7663_MCU_CMD_ERROR_MASK GENMASK(5, 2) #define MT_TX_RING_BASE MT_HIF(0x300) #define MT_RX_RING_BASE MT_HIF(0x400) @@ -368,7 +379,9 @@ enum mt7615_reg_base { #define MT_DMA_DCR0 MT_WF_DMA(0x000) #define MT_DMA_DCR0_MAX_RX_LEN GENMASK(15, 2) +#define MT_DMA_DCR0_DAMSDU_EN BIT(16) #define MT_DMA_DCR0_RX_VEC_DROP BIT(17) +#define MT_DMA_DCR0_RX_HDR_TRANS_EN BIT(19) #define MT_DMA_RCFR0(_band) MT_WF_DMA(0x070 + (_band) * 0x40) #define MT_DMA_RCFR0_MCU_RX_MGMT BIT(2) @@ -447,9 +460,10 @@ enum mt7615_reg_base { #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) -#define MT_LPON_T0CR_WRITE BIT(0) +#define MT_LPON_TCR0(_n) MT_LPON(0x010 + ((_n) * 4)) +#define MT_LPON_TCR2(_n) MT_LPON(0x0f8 + ((_n) - 2) * 4) +#define MT_LPON_TCR_MODE GENMASK(1, 0) +#define MT_LPON_TCR_WRITE BIT(0) #define MT_LPON_UTTR0 MT_LPON(0x018) #define MT_LPON_UTTR1 MT_LPON(0x01c) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c index 9fb506f2ace6..4393dd21ebbb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c @@ -218,12 +218,15 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) int qid, err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0; bool mcu = q == dev->q_mcu[MT_MCUQ_WM]; struct mt76_sdio *sdio = &dev->sdio; + u8 pad; qid = mcu ? ARRAY_SIZE(sdio->xmit_buf) - 1 : q->qid; while (q->first != q->head) { struct mt76_queue_entry *e = &q->entry[q->first]; struct sk_buff *iter; + smp_rmb(); + if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) { __skb_put_zero(e->skb, 4); err = __mt7663s_xmit_queue(dev, e->skb->data, @@ -234,7 +237,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) goto next; } - if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ) + pad = roundup(e->skb->len, 4) - e->skb->len; + if (len + e->skb->len + pad + 4 > MT76S_XMIT_BUF_SZ) break; if (mt7663s_tx_pick_quota(sdio, mcu, e->buf_sz, &pse_sz, @@ -252,6 +256,11 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q) len += iter->len; nframes++; } + + if (unlikely(pad)) { + memset(sdio->xmit_buf[qid] + len, 0, pad); + len += pad; + } next: q->first = (q->first + 1) % q->ndesc; e->done = true; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c index 9aa5183c7a56..be9a69fe1b38 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/soc.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/soc.c @@ -40,10 +40,8 @@ static int mt7622_wmac_probe(struct platform_device *pdev) 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"); + if (IS_ERR(mem_base)) return PTR_ERR(mem_base); - } return mt7615_mmio_probe(&pdev->dev, mem_base, irq, mt7615e_reg_map); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 203256862dfd..f8d3673c2cae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -67,6 +67,7 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, struct mt7615_rate_desc *rate = &wrd->rate; struct mt7615_sta *sta = wrd->sta; u32 w5, w27, addr, val; + u16 idx; lockdep_assert_held(&dev->mt76.mutex); @@ -118,7 +119,11 @@ static int mt7663_usb_sdio_set_rates(struct mt7615_dev *dev, sta->rate_probe = sta->rateset[rate->rateset].probe_rate.idx != -1; - mt76_set(dev, MT_LPON_T0CR, MT_LPON_T0CR_MODE); /* TSF read */ + idx = sta->vif->mt76.omac_idx; + idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx; + addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx); + + mt76_set(dev, addr, MT_LPON_TCR_MODE); /* TSF read */ val = mt76_rr(dev, MT_LPON_UTTR0); sta->rate_set_tsf = (val & ~BIT(0)) | rate->rateset; |