Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7603/beacon.c
48525 views
// SPDX-License-Identifier: ISC12#include "mt7603.h"34struct beacon_bc_data {5struct mt7603_dev *dev;6struct sk_buff_head q;7struct sk_buff *tail[MT7603_MAX_INTERFACES];8int count[MT7603_MAX_INTERFACES];9};1011static void12mt7603_mac_stuck_beacon_recovery(struct mt7603_dev *dev)13{14if (dev->beacon_check % 5 != 4)15return;1617mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);18mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET);19mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET);20mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN);2122mt76_set(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);23mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);24mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TX_DISABLE);25mt76_clear(dev, MT_WF_CFG_OFF_WOCCR, MT_WF_CFG_OFF_WOCCR_TMAC_GC_DIS);26}2728static void29mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)30{31struct mt7603_dev *dev = (struct mt7603_dev *)priv;32struct mt76_dev *mdev = &dev->mt76;33struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;34struct sk_buff *skb = NULL;35u32 om_idx = mvif->idx;36u32 val;3738if (!(mdev->beacon_mask & BIT(mvif->idx)))39return;4041skb = ieee80211_beacon_get(mt76_hw(dev), vif, 0);42if (!skb)43return;4445if (om_idx)46om_idx |= 0x10;47val = MT_DMA_FQCR0_BUSY | MT_DMA_FQCR0_MODE |48FIELD_PREP(MT_DMA_FQCR0_TARGET_BSS, om_idx) |49FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) |50FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8);5152spin_lock_bh(&dev->ps_lock);5354mt76_wr(dev, MT_DMA_FQCR0, val |55FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BCN));56if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {57dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;58goto out;59}6061mt76_wr(dev, MT_DMA_FQCR0, val |62FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, MT_TX_HW_QUEUE_BMC));63if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) {64dev->beacon_check = MT7603_WATCHDOG_TIMEOUT;65goto out;66}6768mt76_tx_queue_skb(dev, dev->mphy.q_tx[MT_TXQ_BEACON],69MT_TXQ_BEACON, skb, &mvif->sta.wcid, NULL);7071out:72spin_unlock_bh(&dev->ps_lock);73}7475static void76mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)77{78struct beacon_bc_data *data = priv;79struct mt7603_dev *dev = data->dev;80struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;81struct ieee80211_tx_info *info;82struct sk_buff *skb;8384if (!(dev->mt76.beacon_mask & BIT(mvif->idx)))85return;8687skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);88if (!skb)89return;9091info = IEEE80211_SKB_CB(skb);92info->control.vif = vif;93info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;94mt76_skb_set_moredata(skb, true);95__skb_queue_tail(&data->q, skb);96data->tail[mvif->idx] = skb;97data->count[mvif->idx]++;98}99100void mt7603_pre_tbtt_tasklet(struct tasklet_struct *t)101{102struct mt7603_dev *dev = from_tasklet(dev, t, mt76.pre_tbtt_tasklet);103struct mt76_dev *mdev = &dev->mt76;104struct mt76_queue *q;105struct beacon_bc_data data = {};106struct sk_buff *skb;107int i, nframes;108109if (dev->mphy.offchannel)110return;111112data.dev = dev;113__skb_queue_head_init(&data.q);114115/* Flush all previous CAB queue packets and beacons */116mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0));117118mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_CAB], false);119mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BEACON], false);120121if (dev->mphy.q_tx[MT_TXQ_BEACON]->queued > 0)122dev->beacon_check++;123else124dev->beacon_check = 0;125mt7603_mac_stuck_beacon_recovery(dev);126127q = dev->mphy.q_tx[MT_TXQ_BEACON];128spin_lock(&q->lock);129ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),130IEEE80211_IFACE_ITER_RESUME_ALL,131mt7603_update_beacon_iter, dev);132mt76_queue_kick(dev, q);133spin_unlock(&q->lock);134135mt76_csa_check(mdev);136if (mdev->csa_complete)137return;138139q = dev->mphy.q_tx[MT_TXQ_CAB];140do {141nframes = skb_queue_len(&data.q);142ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),143IEEE80211_IFACE_ITER_RESUME_ALL,144mt7603_add_buffered_bc, &data);145} while (nframes != skb_queue_len(&data.q) &&146skb_queue_len(&data.q) < 8);147148if (skb_queue_empty(&data.q))149return;150151for (i = 0; i < ARRAY_SIZE(data.tail); i++) {152if (!data.tail[i])153continue;154155mt76_skb_set_moredata(data.tail[i], false);156}157158spin_lock(&q->lock);159while ((skb = __skb_dequeue(&data.q)) != NULL) {160struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);161struct ieee80211_vif *vif = info->control.vif;162struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;163164mt76_tx_queue_skb(dev, q, MT_TXQ_CAB, skb, &mvif->sta.wcid, NULL);165}166mt76_queue_kick(dev, q);167spin_unlock(&q->lock);168169for (i = 0; i < ARRAY_SIZE(data.count); i++)170mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i),171data.count[i] << MT_WF_ARB_CAB_COUNT_B0_SHIFT(i));172173mt76_wr(dev, MT_WF_ARB_CAB_START,174MT_WF_ARB_CAB_START_BSSn(0) |175(MT_WF_ARB_CAB_START_BSS0n(1) *176((1 << (MT7603_MAX_INTERFACES - 1)) - 1)));177}178179void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval)180{181u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64;182183if (idx >= 0) {184if (intval)185dev->mt76.beacon_mask |= BIT(idx);186else187dev->mt76.beacon_mask &= ~BIT(idx);188}189190if (!dev->mt76.beacon_mask || (!intval && idx < 0)) {191mt7603_irq_disable(dev, MT_INT_MAC_IRQ3);192mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK);193mt76_wr(dev, MT_HW_INT_MASK(3), 0);194return;195}196197if (intval)198dev->mt76.beacon_int = intval;199mt76_wr(dev, MT_TBTT,200FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE);201202mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */203204mt76_rmw_field(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK,205MT_BCNQ_OPMODE_AP);206mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCN_PRIO);207mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCAST_PRIO);208209mt76_wr(dev, MT_PRE_TBTT, pre_tbtt);210211mt76_set(dev, MT_HW_INT_MASK(3),212MT_HW_INT3_PRE_TBTT0 | MT_HW_INT3_TBTT0);213214mt76_set(dev, MT_WF_ARB_BCN_START,215MT_WF_ARB_BCN_START_BSSn(0) |216((dev->mt76.beacon_mask >> 1) *217MT_WF_ARB_BCN_START_BSS0n(1)));218mt7603_irq_enable(dev, MT_INT_MAC_IRQ3);219220if (dev->mt76.beacon_mask & ~BIT(0))221mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);222else223mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN);224}225226227