diff --git a/mt7603.h b/mt7603.h index ba7fcf13..be79e6db 100644 --- a/mt7603.h +++ b/mt7603.h @@ -29,6 +29,8 @@ #define MT7603_EEPROM_SIZE 1024 +#define MT_AGG_SIZE_LIMIT(n) ((4 + 2 * (n & 1)) << (n / 2)) + enum { MT7603_REV_E1 = 0x00, MT7603_REV_E2 = 0x10 @@ -166,6 +168,8 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data); struct sk_buff *mt7603_mac_status_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pktid); void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid); +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, + int ba_size); int mt7603_mcu_set_channel(struct mt7603_dev *dev); int mt7603_mcu_reg_read(struct mt7603_dev *dev, u32 reg, u32 *val, bool rf); diff --git a/mt7603_init.c b/mt7603_init.c index 29ac914c..b850d259 100644 --- a/mt7603_init.c +++ b/mt7603_init.c @@ -179,6 +179,18 @@ mt7603_mac_init(struct mt7603_dev *dev) u32 addr; int i; + mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_0, + (MT_AGG_SIZE_LIMIT(0) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(1) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(2) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(3) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); + + mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_1, + (MT_AGG_SIZE_LIMIT(4) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(5) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(6) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(7) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); + mt76_rmw(dev, MT_DMA_DCR0, ~0xfffc, MT_RX_BUF_SIZE); mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13)); diff --git a/mt7603_mac.c b/mt7603_mac.c index 7ff2480f..0fdc2e27 100644 --- a/mt7603_mac.c +++ b/mt7603_mac.c @@ -169,6 +169,69 @@ void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid) MT_BA_CONTROL_1_RESET)); } +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, + int ba_size) +{ + u32 addr = mt7603_wtbl2_addr(wcid); + u32 tid_mask = MT76_SET(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | + (MT_WTBL2_W15_BA_WIN_SIZE << + (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT)); + u32 tid_val; + int i; + + if (ba_size < 0) { + /* disable */ + mt76_clear(dev, addr + (15 * 4), tid_mask); + return; + } + + mt7603_mac_stop(dev); + switch (tid) { + case 0: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn); + break; + case 1: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn); + break; + case 2: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO, + ssn); + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI, + ssn >> 8); + break; + case 3: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn); + break; + case 4: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn); + break; + case 5: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO, + ssn); + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI, + ssn >> 4); + break; + case 6: + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn); + break; + case 7: + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn); + break; + } + mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2); + mt7603_mac_start(dev); + + for (i = 7; i > 0; i--) { + if (ba_size >= MT_AGG_SIZE_LIMIT(i)) + break; + } + + tid_val = MT76_SET(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | + i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT); + + mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); +} + static int mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, int idx, bool cck) diff --git a/mt7603_main.c b/mt7603_main.c index 9ae691bf..de1b725e 100644 --- a/mt7603_main.c +++ b/mt7603_main.c @@ -369,9 +369,11 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct mt7603_dev *dev = hw->priv; struct ieee80211_sta *sta = params->sta; struct ieee80211_txq *txq = sta->txq[params->tid]; + struct mt7603_sta *msta = (struct mt7603_sta *) sta->drv_priv; struct mt76_txq *mtxq = (struct mt76_txq *) txq->drv_priv; u16 tid = params->tid; u16 *ssn = ¶ms->ssn; + u8 ba_size = params->buf_size; if (!txq) return -EINVAL; @@ -385,18 +387,21 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, case IEEE80211_AMPDU_TX_OPERATIONAL: mtxq->aggr = true; mtxq->send_bar = false; - ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size); break; case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: mtxq->aggr = false; ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); break; case IEEE80211_AMPDU_TX_START: mtxq->agg_ssn = *ssn << 4; ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; } diff --git a/mt7603_regs.h b/mt7603_regs.h index cf57da6c..36d9972b 100644 --- a/mt7603_regs.h +++ b/mt7603_regs.h @@ -141,6 +141,10 @@ #define MT_AGG_ARxCR_LIMIT(_n) GENMASK(3 + MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ MT_AGG_ARxCR_LIMIT_SHIFT(_n)) +#define MT_AGG_BA_SIZE_LIMIT_0 MT_WF_AGG(0x048) +#define MT_AGG_BA_SIZE_LIMIT_1 MT_WF_AGG(0x04c) +#define MT_AGG_BA_SIZE_LIMIT_SHIFT 8 + #define MT_AGG_TMP MT_WF_AGG(0x0d8) #define MT_AGG_BWCR MT_WF_AGG(0x0ec) @@ -458,7 +462,8 @@ #define MT_WTBL2_W14_CC_NOISE_SEL BIT(15) #define MT_WTBL2_W14_ANT_SEL GENMASK(31, 26) -#define MT_WTBL2_W15_BA_WIN_SIZE GENMASK(23, 0) +#define MT_WTBL2_W15_BA_WIN_SIZE GENMASK(2, 0) +#define MT_WTBL2_W15_BA_WIN_SIZE_SHIFT 3 #define MT_WTBL2_W15_BA_EN_TIDS GENMASK(31, 24) #define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300)