1c8846e10SFelix Fietkau /* SPDX-License-Identifier: ISC */ 2c8846e10SFelix Fietkau 3c8846e10SFelix Fietkau #include <linux/etherdevice.h> 4c8846e10SFelix Fietkau #include <linux/timekeeping.h> 5c8846e10SFelix Fietkau #include "mt7603.h" 6c8846e10SFelix Fietkau #include "mac.h" 7c8846e10SFelix Fietkau 8c8846e10SFelix Fietkau #define MT_PSE_PAGE_SIZE 128 9c8846e10SFelix Fietkau 10c8846e10SFelix Fietkau static u32 11c8846e10SFelix Fietkau mt7603_ac_queue_mask0(u32 mask) 12c8846e10SFelix Fietkau { 13c8846e10SFelix Fietkau u32 ret = 0; 14c8846e10SFelix Fietkau 15c8846e10SFelix Fietkau ret |= GENMASK(3, 0) * !!(mask & BIT(0)); 16c8846e10SFelix Fietkau ret |= GENMASK(8, 5) * !!(mask & BIT(1)); 17c8846e10SFelix Fietkau ret |= GENMASK(13, 10) * !!(mask & BIT(2)); 18c8846e10SFelix Fietkau ret |= GENMASK(19, 16) * !!(mask & BIT(3)); 19c8846e10SFelix Fietkau return ret; 20c8846e10SFelix Fietkau } 21c8846e10SFelix Fietkau 22c8846e10SFelix Fietkau static void 23c8846e10SFelix Fietkau mt76_stop_tx_ac(struct mt7603_dev *dev, u32 mask) 24c8846e10SFelix Fietkau { 25c8846e10SFelix Fietkau mt76_set(dev, MT_WF_ARB_TX_STOP_0, mt7603_ac_queue_mask0(mask)); 26c8846e10SFelix Fietkau } 27c8846e10SFelix Fietkau 28c8846e10SFelix Fietkau static void 29c8846e10SFelix Fietkau mt76_start_tx_ac(struct mt7603_dev *dev, u32 mask) 30c8846e10SFelix Fietkau { 31c8846e10SFelix Fietkau mt76_set(dev, MT_WF_ARB_TX_START_0, mt7603_ac_queue_mask0(mask)); 32c8846e10SFelix Fietkau } 33c8846e10SFelix Fietkau 34c8846e10SFelix Fietkau void mt7603_mac_set_timing(struct mt7603_dev *dev) 35c8846e10SFelix Fietkau { 36c8846e10SFelix Fietkau u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | 37c8846e10SFelix Fietkau FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); 38c8846e10SFelix Fietkau u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | 39c8846e10SFelix Fietkau FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); 40c8846e10SFelix Fietkau int offset = 3 * dev->coverage_class; 41c8846e10SFelix Fietkau u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | 42c8846e10SFelix Fietkau FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); 43c8846e10SFelix Fietkau int sifs; 44c8846e10SFelix Fietkau u32 val; 45c8846e10SFelix Fietkau 46c8846e10SFelix Fietkau if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) 47c8846e10SFelix Fietkau sifs = 16; 48c8846e10SFelix Fietkau else 49c8846e10SFelix Fietkau sifs = 10; 50c8846e10SFelix Fietkau 51c8846e10SFelix Fietkau mt76_set(dev, MT_ARB_SCR, 52c8846e10SFelix Fietkau MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 53c8846e10SFelix Fietkau udelay(1); 54c8846e10SFelix Fietkau 55c8846e10SFelix Fietkau mt76_wr(dev, MT_TIMEOUT_CCK, cck + reg_offset); 56c8846e10SFelix Fietkau mt76_wr(dev, MT_TIMEOUT_OFDM, ofdm + reg_offset); 57c8846e10SFelix Fietkau mt76_wr(dev, MT_IFS, 58c8846e10SFelix Fietkau FIELD_PREP(MT_IFS_EIFS, 360) | 59c8846e10SFelix Fietkau FIELD_PREP(MT_IFS_RIFS, 2) | 60c8846e10SFelix Fietkau FIELD_PREP(MT_IFS_SIFS, sifs) | 61c8846e10SFelix Fietkau FIELD_PREP(MT_IFS_SLOT, dev->slottime)); 62c8846e10SFelix Fietkau 63c8846e10SFelix Fietkau if (dev->slottime < 20) 64c8846e10SFelix Fietkau val = MT7603_CFEND_RATE_DEFAULT; 65c8846e10SFelix Fietkau else 66c8846e10SFelix Fietkau val = MT7603_CFEND_RATE_11B; 67c8846e10SFelix Fietkau 68c8846e10SFelix Fietkau mt76_rmw_field(dev, MT_AGG_CONTROL, MT_AGG_CONTROL_CFEND_RATE, val); 69c8846e10SFelix Fietkau 70c8846e10SFelix Fietkau mt76_clear(dev, MT_ARB_SCR, 71c8846e10SFelix Fietkau MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 72c8846e10SFelix Fietkau } 73c8846e10SFelix Fietkau 74c8846e10SFelix Fietkau static void 75c8846e10SFelix Fietkau mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask) 76c8846e10SFelix Fietkau { 77c8846e10SFelix Fietkau mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, 78c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); 79c8846e10SFelix Fietkau 80c8846e10SFelix Fietkau mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); 81c8846e10SFelix Fietkau } 82c8846e10SFelix Fietkau 83c8846e10SFelix Fietkau static u32 84c8846e10SFelix Fietkau mt7603_wtbl1_addr(int idx) 85c8846e10SFelix Fietkau { 86c8846e10SFelix Fietkau return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; 87c8846e10SFelix Fietkau } 88c8846e10SFelix Fietkau 89c8846e10SFelix Fietkau static u32 90c8846e10SFelix Fietkau mt7603_wtbl2_addr(int idx) 91c8846e10SFelix Fietkau { 92c8846e10SFelix Fietkau /* Mapped to WTBL2 */ 93c8846e10SFelix Fietkau return MT_PCIE_REMAP_BASE_1 + idx * MT_WTBL2_SIZE; 94c8846e10SFelix Fietkau } 95c8846e10SFelix Fietkau 96c8846e10SFelix Fietkau static u32 97c8846e10SFelix Fietkau mt7603_wtbl3_addr(int idx) 98c8846e10SFelix Fietkau { 99c8846e10SFelix Fietkau u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE); 100c8846e10SFelix Fietkau 101c8846e10SFelix Fietkau return base + idx * MT_WTBL3_SIZE; 102c8846e10SFelix Fietkau } 103c8846e10SFelix Fietkau 104c8846e10SFelix Fietkau static u32 105c8846e10SFelix Fietkau mt7603_wtbl4_addr(int idx) 106c8846e10SFelix Fietkau { 107c8846e10SFelix Fietkau u32 base = mt7603_wtbl3_addr(MT7603_WTBL_SIZE); 108c8846e10SFelix Fietkau 109c8846e10SFelix Fietkau return base + idx * MT_WTBL4_SIZE; 110c8846e10SFelix Fietkau } 111c8846e10SFelix Fietkau 112c8846e10SFelix Fietkau void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif, 113c8846e10SFelix Fietkau const u8 *mac_addr) 114c8846e10SFelix Fietkau { 115c8846e10SFelix Fietkau const void *_mac = mac_addr; 116c8846e10SFelix Fietkau u32 addr = mt7603_wtbl1_addr(idx); 117c8846e10SFelix Fietkau u32 w0 = 0, w1 = 0; 118c8846e10SFelix Fietkau int i; 119c8846e10SFelix Fietkau 120c8846e10SFelix Fietkau if (_mac) { 121c8846e10SFelix Fietkau w0 = FIELD_PREP(MT_WTBL1_W0_ADDR_HI, 122c8846e10SFelix Fietkau get_unaligned_le16(_mac + 4)); 123c8846e10SFelix Fietkau w1 = FIELD_PREP(MT_WTBL1_W1_ADDR_LO, 124c8846e10SFelix Fietkau get_unaligned_le32(_mac)); 125c8846e10SFelix Fietkau } 126c8846e10SFelix Fietkau 127c8846e10SFelix Fietkau if (vif < 0) 128c8846e10SFelix Fietkau vif = 0; 129c8846e10SFelix Fietkau else 130c8846e10SFelix Fietkau w0 |= MT_WTBL1_W0_RX_CHECK_A1; 131c8846e10SFelix Fietkau w0 |= FIELD_PREP(MT_WTBL1_W0_MUAR_IDX, vif); 132c8846e10SFelix Fietkau 133c8846e10SFelix Fietkau mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); 134c8846e10SFelix Fietkau 135c8846e10SFelix Fietkau mt76_set(dev, addr + 0 * 4, w0); 136c8846e10SFelix Fietkau mt76_set(dev, addr + 1 * 4, w1); 137c8846e10SFelix Fietkau mt76_set(dev, addr + 2 * 4, MT_WTBL1_W2_ADMISSION_CONTROL); 138c8846e10SFelix Fietkau 139c8846e10SFelix Fietkau mt76_stop_tx_ac(dev, GENMASK(3, 0)); 140c8846e10SFelix Fietkau addr = mt7603_wtbl2_addr(idx); 141c8846e10SFelix Fietkau for (i = 0; i < MT_WTBL2_SIZE; i += 4) 142c8846e10SFelix Fietkau mt76_wr(dev, addr + i, 0); 143c8846e10SFelix Fietkau mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); 144c8846e10SFelix Fietkau mt76_start_tx_ac(dev, GENMASK(3, 0)); 145c8846e10SFelix Fietkau 146c8846e10SFelix Fietkau addr = mt7603_wtbl3_addr(idx); 147c8846e10SFelix Fietkau for (i = 0; i < MT_WTBL3_SIZE; i += 4) 148c8846e10SFelix Fietkau mt76_wr(dev, addr + i, 0); 149c8846e10SFelix Fietkau 150c8846e10SFelix Fietkau addr = mt7603_wtbl4_addr(idx); 151c8846e10SFelix Fietkau for (i = 0; i < MT_WTBL4_SIZE; i += 4) 152c8846e10SFelix Fietkau mt76_wr(dev, addr + i, 0); 153c8846e10SFelix Fietkau } 154c8846e10SFelix Fietkau 155c8846e10SFelix Fietkau static void 156c8846e10SFelix Fietkau mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled) 157c8846e10SFelix Fietkau { 158c8846e10SFelix Fietkau u32 addr = mt7603_wtbl1_addr(idx); 159c8846e10SFelix Fietkau u32 val = mt76_rr(dev, addr + 3 * 4); 160c8846e10SFelix Fietkau 161c8846e10SFelix Fietkau val &= ~MT_WTBL1_W3_SKIP_TX; 162c8846e10SFelix Fietkau val |= enabled * MT_WTBL1_W3_SKIP_TX; 163c8846e10SFelix Fietkau 164c8846e10SFelix Fietkau mt76_wr(dev, addr + 3 * 4, val); 165c8846e10SFelix Fietkau } 166c8846e10SFelix Fietkau 167c8846e10SFelix Fietkau void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) 168c8846e10SFelix Fietkau { 169c8846e10SFelix Fietkau int i, port, queue; 170c8846e10SFelix Fietkau 171c8846e10SFelix Fietkau if (abort) { 172c8846e10SFelix Fietkau port = 3; /* PSE */ 173c8846e10SFelix Fietkau queue = 8; /* free queue */ 174c8846e10SFelix Fietkau } else { 175c8846e10SFelix Fietkau port = 0; /* HIF */ 176c8846e10SFelix Fietkau queue = 1; /* MCU queue */ 177c8846e10SFelix Fietkau } 178c8846e10SFelix Fietkau 179c8846e10SFelix Fietkau mt7603_wtbl_set_skip_tx(dev, idx, true); 180c8846e10SFelix Fietkau 181c8846e10SFelix Fietkau mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN | 182c8846e10SFelix Fietkau FIELD_PREP(MT_TX_ABORT_WCID, idx)); 183c8846e10SFelix Fietkau 184c8846e10SFelix Fietkau for (i = 0; i < 4; i++) { 185c8846e10SFelix Fietkau mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | 186c8846e10SFelix Fietkau FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) | 187c8846e10SFelix Fietkau FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, i) | 188c8846e10SFelix Fietkau FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | 189c8846e10SFelix Fietkau FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); 190c8846e10SFelix Fietkau 191c8846e10SFelix Fietkau WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 192c8846e10SFelix Fietkau 0, 5000)); 193c8846e10SFelix Fietkau } 194c8846e10SFelix Fietkau 195c8846e10SFelix Fietkau mt76_wr(dev, MT_TX_ABORT, 0); 196c8846e10SFelix Fietkau 197c8846e10SFelix Fietkau mt7603_wtbl_set_skip_tx(dev, idx, false); 198c8846e10SFelix Fietkau } 199c8846e10SFelix Fietkau 200c8846e10SFelix Fietkau void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, 201c8846e10SFelix Fietkau bool enabled) 202c8846e10SFelix Fietkau { 203c8846e10SFelix Fietkau u32 addr = mt7603_wtbl1_addr(sta->wcid.idx); 204c8846e10SFelix Fietkau 205c8846e10SFelix Fietkau if (sta->smps == enabled) 206c8846e10SFelix Fietkau return; 207c8846e10SFelix Fietkau 208c8846e10SFelix Fietkau mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_SMPS, enabled); 209c8846e10SFelix Fietkau sta->smps = enabled; 210c8846e10SFelix Fietkau } 211c8846e10SFelix Fietkau 212c8846e10SFelix Fietkau void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, 213c8846e10SFelix Fietkau bool enabled) 214c8846e10SFelix Fietkau { 215c8846e10SFelix Fietkau int idx = sta->wcid.idx; 216c8846e10SFelix Fietkau u32 addr; 217c8846e10SFelix Fietkau 218c8846e10SFelix Fietkau spin_lock_bh(&dev->ps_lock); 219c8846e10SFelix Fietkau 220c8846e10SFelix Fietkau if (sta->ps == enabled) 221c8846e10SFelix Fietkau goto out; 222c8846e10SFelix Fietkau 223c8846e10SFelix Fietkau mt76_wr(dev, MT_PSE_RTA, 224c8846e10SFelix Fietkau FIELD_PREP(MT_PSE_RTA_TAG_ID, idx) | 225c8846e10SFelix Fietkau FIELD_PREP(MT_PSE_RTA_PORT_ID, 0) | 226c8846e10SFelix Fietkau FIELD_PREP(MT_PSE_RTA_QUEUE_ID, 1) | 227c8846e10SFelix Fietkau FIELD_PREP(MT_PSE_RTA_REDIRECT_EN, enabled) | 228c8846e10SFelix Fietkau MT_PSE_RTA_WRITE | MT_PSE_RTA_BUSY); 229c8846e10SFelix Fietkau 230c8846e10SFelix Fietkau mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); 231c8846e10SFelix Fietkau 232c8846e10SFelix Fietkau if (enabled) 233c8846e10SFelix Fietkau mt7603_filter_tx(dev, idx, false); 234c8846e10SFelix Fietkau 235c8846e10SFelix Fietkau addr = mt7603_wtbl1_addr(idx); 236c8846e10SFelix Fietkau mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); 237c8846e10SFelix Fietkau mt76_rmw(dev, addr + 3 * 4, MT_WTBL1_W3_POWER_SAVE, 238c8846e10SFelix Fietkau enabled * MT_WTBL1_W3_POWER_SAVE); 239c8846e10SFelix Fietkau mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); 240c8846e10SFelix Fietkau sta->ps = enabled; 241c8846e10SFelix Fietkau 242c8846e10SFelix Fietkau out: 243c8846e10SFelix Fietkau spin_unlock_bh(&dev->ps_lock); 244c8846e10SFelix Fietkau } 245c8846e10SFelix Fietkau 246c8846e10SFelix Fietkau void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx) 247c8846e10SFelix Fietkau { 248c8846e10SFelix Fietkau int wtbl2_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL2_SIZE; 249c8846e10SFelix Fietkau int wtbl2_frame = idx / wtbl2_frame_size; 250c8846e10SFelix Fietkau int wtbl2_entry = idx % wtbl2_frame_size; 251c8846e10SFelix Fietkau 252c8846e10SFelix Fietkau int wtbl3_base_frame = MT_WTBL3_OFFSET / MT_PSE_PAGE_SIZE; 253c8846e10SFelix Fietkau int wtbl3_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL3_SIZE; 254c8846e10SFelix Fietkau int wtbl3_frame = wtbl3_base_frame + idx / wtbl3_frame_size; 255c8846e10SFelix Fietkau int wtbl3_entry = (idx % wtbl3_frame_size) * 2; 256c8846e10SFelix Fietkau 257c8846e10SFelix Fietkau int wtbl4_base_frame = MT_WTBL4_OFFSET / MT_PSE_PAGE_SIZE; 258c8846e10SFelix Fietkau int wtbl4_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL4_SIZE; 259c8846e10SFelix Fietkau int wtbl4_frame = wtbl4_base_frame + idx / wtbl4_frame_size; 260c8846e10SFelix Fietkau int wtbl4_entry = idx % wtbl4_frame_size; 261c8846e10SFelix Fietkau 262c8846e10SFelix Fietkau u32 addr = MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; 263c8846e10SFelix Fietkau int i; 264c8846e10SFelix Fietkau 265c8846e10SFelix Fietkau mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); 266c8846e10SFelix Fietkau 267c8846e10SFelix Fietkau mt76_wr(dev, addr + 0 * 4, 268c8846e10SFelix Fietkau MT_WTBL1_W0_RX_CHECK_A1 | 269c8846e10SFelix Fietkau MT_WTBL1_W0_RX_CHECK_A2 | 270c8846e10SFelix Fietkau MT_WTBL1_W0_RX_VALID); 271c8846e10SFelix Fietkau mt76_wr(dev, addr + 1 * 4, 0); 272c8846e10SFelix Fietkau mt76_wr(dev, addr + 2 * 4, 0); 273c8846e10SFelix Fietkau 274c8846e10SFelix Fietkau mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); 275c8846e10SFelix Fietkau 276c8846e10SFelix Fietkau mt76_wr(dev, addr + 3 * 4, 277c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W3_WTBL2_FRAME_ID, wtbl2_frame) | 278c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W3_WTBL2_ENTRY_ID, wtbl2_entry) | 279c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W3_WTBL4_FRAME_ID, wtbl4_frame) | 280c8846e10SFelix Fietkau MT_WTBL1_W3_I_PSM | MT_WTBL1_W3_KEEP_I_PSM); 281c8846e10SFelix Fietkau mt76_wr(dev, addr + 4 * 4, 282c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W4_WTBL3_FRAME_ID, wtbl3_frame) | 283c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W4_WTBL3_ENTRY_ID, wtbl3_entry) | 284c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W4_WTBL4_ENTRY_ID, wtbl4_entry)); 285c8846e10SFelix Fietkau 286c8846e10SFelix Fietkau mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); 287c8846e10SFelix Fietkau 288c8846e10SFelix Fietkau addr = mt7603_wtbl2_addr(idx); 289c8846e10SFelix Fietkau 290c8846e10SFelix Fietkau /* Clear BA information */ 291c8846e10SFelix Fietkau mt76_wr(dev, addr + (15 * 4), 0); 292c8846e10SFelix Fietkau 293c8846e10SFelix Fietkau mt76_stop_tx_ac(dev, GENMASK(3, 0)); 294c8846e10SFelix Fietkau for (i = 2; i <= 4; i++) 295c8846e10SFelix Fietkau mt76_wr(dev, addr + (i * 4), 0); 296c8846e10SFelix Fietkau mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); 297c8846e10SFelix Fietkau mt76_start_tx_ac(dev, GENMASK(3, 0)); 298c8846e10SFelix Fietkau 299c8846e10SFelix Fietkau mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_RX_COUNT_CLEAR); 300c8846e10SFelix Fietkau mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_TX_COUNT_CLEAR); 301c8846e10SFelix Fietkau mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); 302c8846e10SFelix Fietkau } 303c8846e10SFelix Fietkau 304c8846e10SFelix Fietkau void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta) 305c8846e10SFelix Fietkau { 306c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 307c8846e10SFelix Fietkau int idx = msta->wcid.idx; 308c8846e10SFelix Fietkau u32 addr; 309c8846e10SFelix Fietkau u32 val; 310c8846e10SFelix Fietkau 311c8846e10SFelix Fietkau addr = mt7603_wtbl1_addr(idx); 312c8846e10SFelix Fietkau 313c8846e10SFelix Fietkau val = mt76_rr(dev, addr + 2 * 4); 314c8846e10SFelix Fietkau val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL; 315c8846e10SFelix Fietkau val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) | 316c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) | 317c8846e10SFelix Fietkau MT_WTBL1_W2_TXS_BAF_REPORT; 318c8846e10SFelix Fietkau 319c8846e10SFelix Fietkau if (sta->ht_cap.cap) 320c8846e10SFelix Fietkau val |= MT_WTBL1_W2_HT; 321c8846e10SFelix Fietkau if (sta->vht_cap.cap) 322c8846e10SFelix Fietkau val |= MT_WTBL1_W2_VHT; 323c8846e10SFelix Fietkau 324c8846e10SFelix Fietkau mt76_wr(dev, addr + 2 * 4, val); 325c8846e10SFelix Fietkau 326c8846e10SFelix Fietkau addr = mt7603_wtbl2_addr(idx); 327c8846e10SFelix Fietkau val = mt76_rr(dev, addr + 9 * 4); 328c8846e10SFelix Fietkau val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | 329c8846e10SFelix Fietkau MT_WTBL2_W9_SHORT_GI_80); 330c8846e10SFelix Fietkau if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) 331c8846e10SFelix Fietkau val |= MT_WTBL2_W9_SHORT_GI_20; 332c8846e10SFelix Fietkau if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) 333c8846e10SFelix Fietkau val |= MT_WTBL2_W9_SHORT_GI_40; 334c8846e10SFelix Fietkau mt76_wr(dev, addr + 9 * 4, val); 335c8846e10SFelix Fietkau } 336c8846e10SFelix Fietkau 337c8846e10SFelix Fietkau void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid) 338c8846e10SFelix Fietkau { 339c8846e10SFelix Fietkau mt76_wr(dev, MT_BA_CONTROL_0, get_unaligned_le32(addr)); 340c8846e10SFelix Fietkau mt76_wr(dev, MT_BA_CONTROL_1, 341c8846e10SFelix Fietkau (get_unaligned_le16(addr + 4) | 342c8846e10SFelix Fietkau FIELD_PREP(MT_BA_CONTROL_1_TID, tid) | 343c8846e10SFelix Fietkau MT_BA_CONTROL_1_RESET)); 344c8846e10SFelix Fietkau } 345c8846e10SFelix Fietkau 346aa3cb24bSFelix Fietkau void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, 347c8846e10SFelix Fietkau int ba_size) 348c8846e10SFelix Fietkau { 349c8846e10SFelix Fietkau u32 addr = mt7603_wtbl2_addr(wcid); 350c8846e10SFelix Fietkau u32 tid_mask = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | 351c8846e10SFelix Fietkau (MT_WTBL2_W15_BA_WIN_SIZE << 352c8846e10SFelix Fietkau (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT)); 353c8846e10SFelix Fietkau u32 tid_val; 354c8846e10SFelix Fietkau int i; 355c8846e10SFelix Fietkau 356c8846e10SFelix Fietkau if (ba_size < 0) { 357c8846e10SFelix Fietkau /* disable */ 358c8846e10SFelix Fietkau mt76_clear(dev, addr + (15 * 4), tid_mask); 359c8846e10SFelix Fietkau return; 360c8846e10SFelix Fietkau } 361c8846e10SFelix Fietkau 362c8846e10SFelix Fietkau for (i = 7; i > 0; i--) { 363c8846e10SFelix Fietkau if (ba_size >= MT_AGG_SIZE_LIMIT(i)) 364c8846e10SFelix Fietkau break; 365c8846e10SFelix Fietkau } 366c8846e10SFelix Fietkau 367c8846e10SFelix Fietkau tid_val = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | 368c8846e10SFelix Fietkau i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT); 369c8846e10SFelix Fietkau 370c8846e10SFelix Fietkau mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); 371c8846e10SFelix Fietkau } 372c8846e10SFelix Fietkau 373c8846e10SFelix Fietkau static int 374c8846e10SFelix Fietkau mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, 375c8846e10SFelix Fietkau int idx, bool cck) 376c8846e10SFelix Fietkau { 377c8846e10SFelix Fietkau int offset = 0; 378c8846e10SFelix Fietkau int len = sband->n_bitrates; 379c8846e10SFelix Fietkau int i; 380c8846e10SFelix Fietkau 381c8846e10SFelix Fietkau if (cck) { 382c8846e10SFelix Fietkau if (sband == &dev->mt76.sband_5g.sband) 383c8846e10SFelix Fietkau return 0; 384c8846e10SFelix Fietkau 385c8846e10SFelix Fietkau idx &= ~BIT(2); /* short preamble */ 386c8846e10SFelix Fietkau } else if (sband == &dev->mt76.sband_2g.sband) { 387c8846e10SFelix Fietkau offset = 4; 388c8846e10SFelix Fietkau } 389c8846e10SFelix Fietkau 390c8846e10SFelix Fietkau for (i = offset; i < len; i++) { 391c8846e10SFelix Fietkau if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) 392c8846e10SFelix Fietkau return i; 393c8846e10SFelix Fietkau } 394c8846e10SFelix Fietkau 395c8846e10SFelix Fietkau return 0; 396c8846e10SFelix Fietkau } 397c8846e10SFelix Fietkau 398c8846e10SFelix Fietkau static struct mt76_wcid * 399c8846e10SFelix Fietkau mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) 400c8846e10SFelix Fietkau { 401c8846e10SFelix Fietkau struct mt7603_sta *sta; 402c8846e10SFelix Fietkau struct mt76_wcid *wcid; 403c8846e10SFelix Fietkau 404c8846e10SFelix Fietkau if (idx >= ARRAY_SIZE(dev->mt76.wcid)) 405c8846e10SFelix Fietkau return NULL; 406c8846e10SFelix Fietkau 407c8846e10SFelix Fietkau wcid = rcu_dereference(dev->mt76.wcid[idx]); 408c8846e10SFelix Fietkau if (unicast || !wcid) 409c8846e10SFelix Fietkau return wcid; 410c8846e10SFelix Fietkau 411c8846e10SFelix Fietkau if (!wcid->sta) 412c8846e10SFelix Fietkau return NULL; 413c8846e10SFelix Fietkau 414c8846e10SFelix Fietkau sta = container_of(wcid, struct mt7603_sta, wcid); 415c8846e10SFelix Fietkau if (!sta->vif) 416c8846e10SFelix Fietkau return NULL; 417c8846e10SFelix Fietkau 418c8846e10SFelix Fietkau return &sta->vif->sta.wcid; 419c8846e10SFelix Fietkau } 420c8846e10SFelix Fietkau 421c8846e10SFelix Fietkau static void 422c8846e10SFelix Fietkau mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) 423c8846e10SFelix Fietkau { 424c8846e10SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 425c8846e10SFelix Fietkau int hdr_len = ieee80211_get_hdrlen_from_skb(skb); 426c8846e10SFelix Fietkau u8 *pn = status->iv; 427c8846e10SFelix Fietkau u8 *hdr; 428c8846e10SFelix Fietkau 429c8846e10SFelix Fietkau __skb_push(skb, 8); 430c8846e10SFelix Fietkau memmove(skb->data, skb->data + 8, hdr_len); 431c8846e10SFelix Fietkau hdr = skb->data + hdr_len; 432c8846e10SFelix Fietkau 433c8846e10SFelix Fietkau hdr[0] = pn[5]; 434c8846e10SFelix Fietkau hdr[1] = pn[4]; 435c8846e10SFelix Fietkau hdr[2] = 0; 436c8846e10SFelix Fietkau hdr[3] = 0x20 | (key_id << 6); 437c8846e10SFelix Fietkau hdr[4] = pn[3]; 438c8846e10SFelix Fietkau hdr[5] = pn[2]; 439c8846e10SFelix Fietkau hdr[6] = pn[1]; 440c8846e10SFelix Fietkau hdr[7] = pn[0]; 441c8846e10SFelix Fietkau 442c8846e10SFelix Fietkau status->flag &= ~RX_FLAG_IV_STRIPPED; 443c8846e10SFelix Fietkau } 444c8846e10SFelix Fietkau 445c8846e10SFelix Fietkau int 446c8846e10SFelix Fietkau mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) 447c8846e10SFelix Fietkau { 448c8846e10SFelix Fietkau struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 449c8846e10SFelix Fietkau struct ieee80211_supported_band *sband; 450c8846e10SFelix Fietkau struct ieee80211_hdr *hdr; 451c8846e10SFelix Fietkau __le32 *rxd = (__le32 *)skb->data; 452c8846e10SFelix Fietkau u32 rxd0 = le32_to_cpu(rxd[0]); 453c8846e10SFelix Fietkau u32 rxd1 = le32_to_cpu(rxd[1]); 454c8846e10SFelix Fietkau u32 rxd2 = le32_to_cpu(rxd[2]); 455c8846e10SFelix Fietkau bool unicast = rxd1 & MT_RXD1_NORMAL_U2M; 456c8846e10SFelix Fietkau bool insert_ccmp_hdr = false; 457c8846e10SFelix Fietkau bool remove_pad; 458c8846e10SFelix Fietkau int idx; 459c8846e10SFelix Fietkau int i; 460c8846e10SFelix Fietkau 461c8846e10SFelix Fietkau memset(status, 0, sizeof(*status)); 462c8846e10SFelix Fietkau 463c8846e10SFelix Fietkau i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); 464c8846e10SFelix Fietkau sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; 465c8846e10SFelix Fietkau i >>= 1; 466c8846e10SFelix Fietkau 467c8846e10SFelix Fietkau idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); 468c8846e10SFelix Fietkau status->wcid = mt7603_rx_get_wcid(dev, idx, unicast); 469c8846e10SFelix Fietkau 470c8846e10SFelix Fietkau status->band = sband->band; 471c8846e10SFelix Fietkau if (i < sband->n_channels) 472c8846e10SFelix Fietkau status->freq = sband->channels[i].center_freq; 473c8846e10SFelix Fietkau 474c8846e10SFelix Fietkau if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) 475c8846e10SFelix Fietkau status->flag |= RX_FLAG_FAILED_FCS_CRC; 476c8846e10SFelix Fietkau 477c8846e10SFelix Fietkau if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) 478c8846e10SFelix Fietkau status->flag |= RX_FLAG_MMIC_ERROR; 479c8846e10SFelix Fietkau 480c8846e10SFelix Fietkau if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && 481c8846e10SFelix Fietkau !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { 482c8846e10SFelix Fietkau status->flag |= RX_FLAG_DECRYPTED; 483c8846e10SFelix Fietkau status->flag |= RX_FLAG_IV_STRIPPED; 484c8846e10SFelix Fietkau status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; 485c8846e10SFelix Fietkau } 486c8846e10SFelix Fietkau 487c8846e10SFelix Fietkau remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; 488c8846e10SFelix Fietkau 489c8846e10SFelix Fietkau if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) 490c8846e10SFelix Fietkau return -EINVAL; 491c8846e10SFelix Fietkau 492c8846e10SFelix Fietkau if (!sband->channels) 493c8846e10SFelix Fietkau return -EINVAL; 494c8846e10SFelix Fietkau 495c8846e10SFelix Fietkau rxd += 4; 496c8846e10SFelix Fietkau if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { 497c8846e10SFelix Fietkau rxd += 4; 498c8846e10SFelix Fietkau if ((u8 *)rxd - skb->data >= skb->len) 499c8846e10SFelix Fietkau return -EINVAL; 500c8846e10SFelix Fietkau } 501c8846e10SFelix Fietkau if (rxd0 & MT_RXD0_NORMAL_GROUP_1) { 502c8846e10SFelix Fietkau u8 *data = (u8 *)rxd; 503c8846e10SFelix Fietkau 504c8846e10SFelix Fietkau if (status->flag & RX_FLAG_DECRYPTED) { 505c8846e10SFelix Fietkau status->iv[0] = data[5]; 506c8846e10SFelix Fietkau status->iv[1] = data[4]; 507c8846e10SFelix Fietkau status->iv[2] = data[3]; 508c8846e10SFelix Fietkau status->iv[3] = data[2]; 509c8846e10SFelix Fietkau status->iv[4] = data[1]; 510c8846e10SFelix Fietkau status->iv[5] = data[0]; 511c8846e10SFelix Fietkau 512c8846e10SFelix Fietkau insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); 513c8846e10SFelix Fietkau } 514c8846e10SFelix Fietkau 515c8846e10SFelix Fietkau rxd += 4; 516c8846e10SFelix Fietkau if ((u8 *)rxd - skb->data >= skb->len) 517c8846e10SFelix Fietkau return -EINVAL; 518c8846e10SFelix Fietkau } 519c8846e10SFelix Fietkau if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { 520c8846e10SFelix Fietkau rxd += 2; 521c8846e10SFelix Fietkau if ((u8 *)rxd - skb->data >= skb->len) 522c8846e10SFelix Fietkau return -EINVAL; 523c8846e10SFelix Fietkau } 524c8846e10SFelix Fietkau if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { 525c8846e10SFelix Fietkau u32 rxdg0 = le32_to_cpu(rxd[0]); 526c8846e10SFelix Fietkau u32 rxdg3 = le32_to_cpu(rxd[3]); 527c8846e10SFelix Fietkau bool cck = false; 528c8846e10SFelix Fietkau 529c8846e10SFelix Fietkau i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0); 530c8846e10SFelix Fietkau switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) { 531c8846e10SFelix Fietkau case MT_PHY_TYPE_CCK: 532c8846e10SFelix Fietkau cck = true; 533c8846e10SFelix Fietkau /* fall through */ 534c8846e10SFelix Fietkau case MT_PHY_TYPE_OFDM: 535c8846e10SFelix Fietkau i = mt7603_get_rate(dev, sband, i, cck); 536c8846e10SFelix Fietkau break; 537c8846e10SFelix Fietkau case MT_PHY_TYPE_HT_GF: 538c8846e10SFelix Fietkau case MT_PHY_TYPE_HT: 539c8846e10SFelix Fietkau status->encoding = RX_ENC_HT; 540c8846e10SFelix Fietkau if (i > 15) 541c8846e10SFelix Fietkau return -EINVAL; 542c8846e10SFelix Fietkau break; 543c8846e10SFelix Fietkau default: 544c8846e10SFelix Fietkau return -EINVAL; 545c8846e10SFelix Fietkau } 546c8846e10SFelix Fietkau 547c8846e10SFelix Fietkau if (rxdg0 & MT_RXV1_HT_SHORT_GI) 548c8846e10SFelix Fietkau status->enc_flags |= RX_ENC_FLAG_SHORT_GI; 549c8846e10SFelix Fietkau if (rxdg0 & MT_RXV1_HT_AD_CODE) 550c8846e10SFelix Fietkau status->enc_flags |= RX_ENC_FLAG_LDPC; 551c8846e10SFelix Fietkau 552c8846e10SFelix Fietkau status->enc_flags |= RX_ENC_FLAG_STBC_MASK * 553c8846e10SFelix Fietkau FIELD_GET(MT_RXV1_HT_STBC, rxdg0); 554c8846e10SFelix Fietkau 555c8846e10SFelix Fietkau status->rate_idx = i; 556c8846e10SFelix Fietkau 557c8846e10SFelix Fietkau status->chains = dev->mt76.antenna_mask; 558c8846e10SFelix Fietkau status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) + 559c8846e10SFelix Fietkau dev->rssi_offset[0]; 560c8846e10SFelix Fietkau status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + 561c8846e10SFelix Fietkau dev->rssi_offset[1]; 562c8846e10SFelix Fietkau 563c8846e10SFelix Fietkau status->signal = status->chain_signal[0]; 564c8846e10SFelix Fietkau if (status->chains & BIT(1)) 565c8846e10SFelix Fietkau status->signal = max(status->signal, 566c8846e10SFelix Fietkau status->chain_signal[1]); 567c8846e10SFelix Fietkau 568c8846e10SFelix Fietkau if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1) 569c8846e10SFelix Fietkau status->bw = RATE_INFO_BW_40; 570c8846e10SFelix Fietkau 571c8846e10SFelix Fietkau rxd += 6; 572c8846e10SFelix Fietkau if ((u8 *)rxd - skb->data >= skb->len) 573c8846e10SFelix Fietkau return -EINVAL; 574c8846e10SFelix Fietkau } else { 575c8846e10SFelix Fietkau return -EINVAL; 576c8846e10SFelix Fietkau } 577c8846e10SFelix Fietkau 578c8846e10SFelix Fietkau skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); 579c8846e10SFelix Fietkau 580c8846e10SFelix Fietkau if (insert_ccmp_hdr) { 581c8846e10SFelix Fietkau u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); 582c8846e10SFelix Fietkau 583c8846e10SFelix Fietkau mt7603_insert_ccmp_hdr(skb, key_id); 584c8846e10SFelix Fietkau } 585c8846e10SFelix Fietkau 586c8846e10SFelix Fietkau hdr = (struct ieee80211_hdr *)skb->data; 587c8846e10SFelix Fietkau if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) 588c8846e10SFelix Fietkau return 0; 589c8846e10SFelix Fietkau 590c8846e10SFelix Fietkau status->aggr = unicast && 591c8846e10SFelix Fietkau !ieee80211_is_qos_nullfunc(hdr->frame_control); 592c8846e10SFelix Fietkau status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; 593c8846e10SFelix Fietkau status->seqno = hdr->seq_ctrl >> 4; 594c8846e10SFelix Fietkau 595c8846e10SFelix Fietkau return 0; 596c8846e10SFelix Fietkau } 597c8846e10SFelix Fietkau 598c8846e10SFelix Fietkau static u16 599c8846e10SFelix Fietkau mt7603_mac_tx_rate_val(struct mt7603_dev *dev, 600c8846e10SFelix Fietkau const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) 601c8846e10SFelix Fietkau { 602c8846e10SFelix Fietkau u8 phy, nss, rate_idx; 603c8846e10SFelix Fietkau u16 rateval; 604c8846e10SFelix Fietkau 605c8846e10SFelix Fietkau *bw = 0; 606c8846e10SFelix Fietkau if (rate->flags & IEEE80211_TX_RC_MCS) { 607c8846e10SFelix Fietkau rate_idx = rate->idx; 608c8846e10SFelix Fietkau nss = 1 + (rate->idx >> 3); 609c8846e10SFelix Fietkau phy = MT_PHY_TYPE_HT; 610c8846e10SFelix Fietkau if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) 611c8846e10SFelix Fietkau phy = MT_PHY_TYPE_HT_GF; 612c8846e10SFelix Fietkau if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 613c8846e10SFelix Fietkau *bw = 1; 614c8846e10SFelix Fietkau } else { 615c8846e10SFelix Fietkau const struct ieee80211_rate *r; 616c8846e10SFelix Fietkau int band = dev->mt76.chandef.chan->band; 617c8846e10SFelix Fietkau u16 val; 618c8846e10SFelix Fietkau 619c8846e10SFelix Fietkau nss = 1; 620c8846e10SFelix Fietkau r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; 621c8846e10SFelix Fietkau if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) 622c8846e10SFelix Fietkau val = r->hw_value_short; 623c8846e10SFelix Fietkau else 624c8846e10SFelix Fietkau val = r->hw_value; 625c8846e10SFelix Fietkau 626c8846e10SFelix Fietkau phy = val >> 8; 627c8846e10SFelix Fietkau rate_idx = val & 0xff; 628c8846e10SFelix Fietkau } 629c8846e10SFelix Fietkau 630c8846e10SFelix Fietkau rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | 631c8846e10SFelix Fietkau FIELD_PREP(MT_TX_RATE_MODE, phy)); 632c8846e10SFelix Fietkau 633c8846e10SFelix Fietkau if (stbc && nss == 1) 634c8846e10SFelix Fietkau rateval |= MT_TX_RATE_STBC; 635c8846e10SFelix Fietkau 636c8846e10SFelix Fietkau return rateval; 637c8846e10SFelix Fietkau } 638c8846e10SFelix Fietkau 639c8846e10SFelix Fietkau void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, 640c8846e10SFelix Fietkau struct ieee80211_tx_rate *probe_rate, 641c8846e10SFelix Fietkau struct ieee80211_tx_rate *rates) 642c8846e10SFelix Fietkau { 643c8846e10SFelix Fietkau int wcid = sta->wcid.idx; 644c8846e10SFelix Fietkau u32 addr = mt7603_wtbl2_addr(wcid); 645c8846e10SFelix Fietkau bool stbc = false; 646c8846e10SFelix Fietkau int n_rates = sta->n_rates; 647c8846e10SFelix Fietkau u8 bw, bw_prev, bw_idx = 0; 648c8846e10SFelix Fietkau u16 val[4]; 649c8846e10SFelix Fietkau u16 probe_val; 650c8846e10SFelix Fietkau u32 w9 = mt76_rr(dev, addr + 9 * 4); 651c8846e10SFelix Fietkau int i; 652c8846e10SFelix Fietkau 653c8846e10SFelix Fietkau if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) 654c8846e10SFelix Fietkau return; 655c8846e10SFelix Fietkau 656c8846e10SFelix Fietkau for (i = n_rates; i < 4; i++) 657c8846e10SFelix Fietkau rates[i] = rates[n_rates - 1]; 658c8846e10SFelix Fietkau 659c8846e10SFelix Fietkau w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | 660c8846e10SFelix Fietkau MT_WTBL2_W9_SHORT_GI_80; 661c8846e10SFelix Fietkau 662c8846e10SFelix Fietkau val[0] = mt7603_mac_tx_rate_val(dev, &rates[0], stbc, &bw); 663c8846e10SFelix Fietkau bw_prev = bw; 664c8846e10SFelix Fietkau 665c8846e10SFelix Fietkau if (probe_rate) { 666c8846e10SFelix Fietkau probe_val = mt7603_mac_tx_rate_val(dev, probe_rate, stbc, &bw); 667c8846e10SFelix Fietkau if (bw) 668c8846e10SFelix Fietkau bw_idx = 1; 669c8846e10SFelix Fietkau else 670c8846e10SFelix Fietkau bw_prev = 0; 671c8846e10SFelix Fietkau } else { 672c8846e10SFelix Fietkau probe_val = val[0]; 673c8846e10SFelix Fietkau } 674c8846e10SFelix Fietkau 675c8846e10SFelix Fietkau w9 |= FIELD_PREP(MT_WTBL2_W9_CC_BW_SEL, bw); 676c8846e10SFelix Fietkau w9 |= FIELD_PREP(MT_WTBL2_W9_BW_CAP, bw); 677c8846e10SFelix Fietkau 678c8846e10SFelix Fietkau val[1] = mt7603_mac_tx_rate_val(dev, &rates[1], stbc, &bw); 679c8846e10SFelix Fietkau if (bw_prev) { 680c8846e10SFelix Fietkau bw_idx = 3; 681c8846e10SFelix Fietkau bw_prev = bw; 682c8846e10SFelix Fietkau } 683c8846e10SFelix Fietkau 684c8846e10SFelix Fietkau val[2] = mt7603_mac_tx_rate_val(dev, &rates[2], stbc, &bw); 685c8846e10SFelix Fietkau if (bw_prev) { 686c8846e10SFelix Fietkau bw_idx = 5; 687c8846e10SFelix Fietkau bw_prev = bw; 688c8846e10SFelix Fietkau } 689c8846e10SFelix Fietkau 690c8846e10SFelix Fietkau val[3] = mt7603_mac_tx_rate_val(dev, &rates[3], stbc, &bw); 691c8846e10SFelix Fietkau if (bw_prev) 692c8846e10SFelix Fietkau bw_idx = 7; 693c8846e10SFelix Fietkau 694c8846e10SFelix Fietkau w9 |= FIELD_PREP(MT_WTBL2_W9_CHANGE_BW_RATE, 695c8846e10SFelix Fietkau bw_idx ? bw_idx - 1 : 7); 696c8846e10SFelix Fietkau 697c8846e10SFelix Fietkau mt76_wr(dev, MT_WTBL_RIUCR0, w9); 698c8846e10SFelix Fietkau 699c8846e10SFelix Fietkau mt76_wr(dev, MT_WTBL_RIUCR1, 700c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | 701c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | 702c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); 703c8846e10SFelix Fietkau 704c8846e10SFelix Fietkau mt76_wr(dev, MT_WTBL_RIUCR2, 705c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | 706c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | 707c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | 708c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); 709c8846e10SFelix Fietkau 710c8846e10SFelix Fietkau mt76_wr(dev, MT_WTBL_RIUCR3, 711c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | 712c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | 713c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); 714c8846e10SFelix Fietkau 715c8846e10SFelix Fietkau mt76_wr(dev, MT_WTBL_UPDATE, 716c8846e10SFelix Fietkau FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | 717c8846e10SFelix Fietkau MT_WTBL_UPDATE_RATE_UPDATE | 718c8846e10SFelix Fietkau MT_WTBL_UPDATE_TX_COUNT_CLEAR); 719c8846e10SFelix Fietkau 720c8846e10SFelix Fietkau if (!sta->wcid.tx_rate_set) 721c8846e10SFelix Fietkau mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); 722c8846e10SFelix Fietkau 723c8846e10SFelix Fietkau sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates; 724c8846e10SFelix Fietkau sta->wcid.tx_rate_set = true; 725c8846e10SFelix Fietkau } 726c8846e10SFelix Fietkau 727c8846e10SFelix Fietkau static enum mt7603_cipher_type 728c8846e10SFelix Fietkau mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) 729c8846e10SFelix Fietkau { 730c8846e10SFelix Fietkau memset(key_data, 0, 32); 731c8846e10SFelix Fietkau if (!key) 732c8846e10SFelix Fietkau return MT_CIPHER_NONE; 733c8846e10SFelix Fietkau 734c8846e10SFelix Fietkau if (key->keylen > 32) 735c8846e10SFelix Fietkau return MT_CIPHER_NONE; 736c8846e10SFelix Fietkau 737c8846e10SFelix Fietkau memcpy(key_data, key->key, key->keylen); 738c8846e10SFelix Fietkau 739c8846e10SFelix Fietkau switch (key->cipher) { 740c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_WEP40: 741c8846e10SFelix Fietkau return MT_CIPHER_WEP40; 742c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_WEP104: 743c8846e10SFelix Fietkau return MT_CIPHER_WEP104; 744c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_TKIP: 745c8846e10SFelix Fietkau /* Rx/Tx MIC keys are swapped */ 746c8846e10SFelix Fietkau memcpy(key_data + 16, key->key + 24, 8); 747c8846e10SFelix Fietkau memcpy(key_data + 24, key->key + 16, 8); 748c8846e10SFelix Fietkau return MT_CIPHER_TKIP; 749c8846e10SFelix Fietkau case WLAN_CIPHER_SUITE_CCMP: 750c8846e10SFelix Fietkau return MT_CIPHER_AES_CCMP; 751c8846e10SFelix Fietkau default: 752c8846e10SFelix Fietkau return MT_CIPHER_NONE; 753c8846e10SFelix Fietkau } 754c8846e10SFelix Fietkau } 755c8846e10SFelix Fietkau 756c8846e10SFelix Fietkau int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, 757c8846e10SFelix Fietkau struct ieee80211_key_conf *key) 758c8846e10SFelix Fietkau { 759c8846e10SFelix Fietkau enum mt7603_cipher_type cipher; 760c8846e10SFelix Fietkau u32 addr = mt7603_wtbl3_addr(wcid); 761c8846e10SFelix Fietkau u8 key_data[32]; 762c8846e10SFelix Fietkau int key_len = sizeof(key_data); 763c8846e10SFelix Fietkau 764c8846e10SFelix Fietkau cipher = mt7603_mac_get_key_info(key, key_data); 765c8846e10SFelix Fietkau if (cipher == MT_CIPHER_NONE && key) 766c8846e10SFelix Fietkau return -EOPNOTSUPP; 767c8846e10SFelix Fietkau 768c8846e10SFelix Fietkau if (key && (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104)) { 769c8846e10SFelix Fietkau addr += key->keyidx * 16; 770c8846e10SFelix Fietkau key_len = 16; 771c8846e10SFelix Fietkau } 772c8846e10SFelix Fietkau 773c8846e10SFelix Fietkau mt76_wr_copy(dev, addr, key_data, key_len); 774c8846e10SFelix Fietkau 775c8846e10SFelix Fietkau addr = mt7603_wtbl1_addr(wcid); 776c8846e10SFelix Fietkau mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher); 777c8846e10SFelix Fietkau if (key) 778c8846e10SFelix Fietkau mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx); 779c8846e10SFelix Fietkau mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key); 780c8846e10SFelix Fietkau 781c8846e10SFelix Fietkau return 0; 782c8846e10SFelix Fietkau } 783c8846e10SFelix Fietkau 784c8846e10SFelix Fietkau static int 785c8846e10SFelix Fietkau mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, 786300832adSLorenzo Bianconi struct sk_buff *skb, enum mt76_txq_id qid, 787c8846e10SFelix Fietkau struct mt76_wcid *wcid, struct ieee80211_sta *sta, 788c8846e10SFelix Fietkau int pid, struct ieee80211_key_conf *key) 789c8846e10SFelix Fietkau { 790c8846e10SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 791c8846e10SFelix Fietkau struct ieee80211_tx_rate *rate = &info->control.rates[0]; 792c8846e10SFelix Fietkau struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 793aa3cb24bSFelix Fietkau struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; 794c8846e10SFelix Fietkau struct ieee80211_vif *vif = info->control.vif; 795af005f26SLorenzo Bianconi struct mt76_queue *q = dev->mt76.q_tx[qid].q; 796c8846e10SFelix Fietkau struct mt7603_vif *mvif; 797c8846e10SFelix Fietkau int wlan_idx; 798c8846e10SFelix Fietkau int hdr_len = ieee80211_get_hdrlen_from_skb(skb); 799c8846e10SFelix Fietkau int tx_count = 8; 800c8846e10SFelix Fietkau u8 frame_type, frame_subtype; 801c8846e10SFelix Fietkau u16 fc = le16_to_cpu(hdr->frame_control); 802aa3cb24bSFelix Fietkau u16 seqno = 0; 803c8846e10SFelix Fietkau u8 vif_idx = 0; 804c8846e10SFelix Fietkau u32 val; 805c8846e10SFelix Fietkau u8 bw; 806c8846e10SFelix Fietkau 807c8846e10SFelix Fietkau if (vif) { 808c8846e10SFelix Fietkau mvif = (struct mt7603_vif *)vif->drv_priv; 809c8846e10SFelix Fietkau vif_idx = mvif->idx; 810300832adSLorenzo Bianconi if (vif_idx && qid >= MT_TXQ_BEACON) 811c8846e10SFelix Fietkau vif_idx += 0x10; 812c8846e10SFelix Fietkau } 813c8846e10SFelix Fietkau 814c8846e10SFelix Fietkau if (sta) { 815c8846e10SFelix Fietkau struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; 816c8846e10SFelix Fietkau 817c8846e10SFelix Fietkau tx_count = msta->rate_count; 818c8846e10SFelix Fietkau } 819c8846e10SFelix Fietkau 820c8846e10SFelix Fietkau if (wcid) 821c8846e10SFelix Fietkau wlan_idx = wcid->idx; 822c8846e10SFelix Fietkau else 823c8846e10SFelix Fietkau wlan_idx = MT7603_WTBL_RESERVED; 824c8846e10SFelix Fietkau 825c8846e10SFelix Fietkau frame_type = (fc & IEEE80211_FCTL_FTYPE) >> 2; 826c8846e10SFelix Fietkau frame_subtype = (fc & IEEE80211_FCTL_STYPE) >> 4; 827c8846e10SFelix Fietkau 828c8846e10SFelix Fietkau val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | 829c8846e10SFelix Fietkau FIELD_PREP(MT_TXD0_Q_IDX, q->hw_idx); 830c8846e10SFelix Fietkau txwi[0] = cpu_to_le32(val); 831c8846e10SFelix Fietkau 832c8846e10SFelix Fietkau val = MT_TXD1_LONG_FORMAT | 833c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_OWN_MAC, vif_idx) | 834c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_TID, 835c8846e10SFelix Fietkau skb->priority & IEEE80211_QOS_CTL_TID_MASK) | 836c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | 837c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) | 838c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) | 839c8846e10SFelix Fietkau FIELD_PREP(MT_TXD1_PROTECTED, !!key); 840c8846e10SFelix Fietkau txwi[1] = cpu_to_le32(val); 841c8846e10SFelix Fietkau 842c8846e10SFelix Fietkau if (info->flags & IEEE80211_TX_CTL_NO_ACK) 843c8846e10SFelix Fietkau txwi[1] |= cpu_to_le32(MT_TXD1_NO_ACK); 844c8846e10SFelix Fietkau 845c8846e10SFelix Fietkau val = FIELD_PREP(MT_TXD2_FRAME_TYPE, frame_type) | 846c8846e10SFelix Fietkau FIELD_PREP(MT_TXD2_SUB_TYPE, frame_subtype) | 847c8846e10SFelix Fietkau FIELD_PREP(MT_TXD2_MULTICAST, 848c8846e10SFelix Fietkau is_multicast_ether_addr(hdr->addr1)); 849c8846e10SFelix Fietkau txwi[2] = cpu_to_le32(val); 850c8846e10SFelix Fietkau 851c8846e10SFelix Fietkau if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) 852c8846e10SFelix Fietkau txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); 853c8846e10SFelix Fietkau 854c8846e10SFelix Fietkau txwi[4] = 0; 855c8846e10SFelix Fietkau 856c8846e10SFelix Fietkau val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT | 857c8846e10SFelix Fietkau FIELD_PREP(MT_TXD5_PID, pid); 858c8846e10SFelix Fietkau txwi[5] = cpu_to_le32(val); 859c8846e10SFelix Fietkau 860c8846e10SFelix Fietkau txwi[6] = 0; 861c8846e10SFelix Fietkau 862c8846e10SFelix Fietkau if (rate->idx >= 0 && rate->count && 863c8846e10SFelix Fietkau !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { 864c8846e10SFelix Fietkau bool stbc = info->flags & IEEE80211_TX_CTL_STBC; 865c8846e10SFelix Fietkau u16 rateval = mt7603_mac_tx_rate_val(dev, rate, stbc, &bw); 866c8846e10SFelix Fietkau 867c8846e10SFelix Fietkau txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); 868c8846e10SFelix Fietkau 869c8846e10SFelix Fietkau val = MT_TXD6_FIXED_BW | 870c8846e10SFelix Fietkau FIELD_PREP(MT_TXD6_BW, bw) | 871c8846e10SFelix Fietkau FIELD_PREP(MT_TXD6_TX_RATE, rateval); 872c8846e10SFelix Fietkau txwi[6] |= cpu_to_le32(val); 873c8846e10SFelix Fietkau 874c8846e10SFelix Fietkau if (rate->flags & IEEE80211_TX_RC_SHORT_GI) 875c8846e10SFelix Fietkau txwi[6] |= cpu_to_le32(MT_TXD6_SGI); 876c8846e10SFelix Fietkau 877c8846e10SFelix Fietkau if (!(rate->flags & IEEE80211_TX_RC_MCS)) 878c8846e10SFelix Fietkau txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); 879c8846e10SFelix Fietkau 880c8846e10SFelix Fietkau tx_count = rate->count; 881c8846e10SFelix Fietkau } 882c8846e10SFelix Fietkau 883c8846e10SFelix Fietkau /* use maximum tx count for beacons and buffered multicast */ 884300832adSLorenzo Bianconi if (qid >= MT_TXQ_BEACON) 885c8846e10SFelix Fietkau tx_count = 0x1f; 886c8846e10SFelix Fietkau 887c8846e10SFelix Fietkau val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) | 888aa3cb24bSFelix Fietkau MT_TXD3_SN_VALID; 889aa3cb24bSFelix Fietkau 890aa3cb24bSFelix Fietkau if (ieee80211_is_data_qos(hdr->frame_control)) 891aa3cb24bSFelix Fietkau seqno = le16_to_cpu(hdr->seq_ctrl); 892aa3cb24bSFelix Fietkau else if (ieee80211_is_back_req(hdr->frame_control)) 893aa3cb24bSFelix Fietkau seqno = le16_to_cpu(bar->start_seq_num); 894aa3cb24bSFelix Fietkau else 895aa3cb24bSFelix Fietkau val &= ~MT_TXD3_SN_VALID; 896aa3cb24bSFelix Fietkau 897aa3cb24bSFelix Fietkau val |= FIELD_PREP(MT_TXD3_SEQ, seqno >> 4); 898aa3cb24bSFelix Fietkau 899c8846e10SFelix Fietkau txwi[3] = cpu_to_le32(val); 900c8846e10SFelix Fietkau 901c8846e10SFelix Fietkau if (key) { 902c8846e10SFelix Fietkau u64 pn = atomic64_inc_return(&key->tx_pn); 903c8846e10SFelix Fietkau 904c8846e10SFelix Fietkau txwi[3] |= cpu_to_le32(MT_TXD3_PN_VALID); 905c8846e10SFelix Fietkau txwi[4] = cpu_to_le32(pn & GENMASK(31, 0)); 906c8846e10SFelix Fietkau txwi[5] |= cpu_to_le32(FIELD_PREP(MT_TXD5_PN_HIGH, pn >> 32)); 907c8846e10SFelix Fietkau } 908c8846e10SFelix Fietkau 909c8846e10SFelix Fietkau txwi[7] = 0; 910c8846e10SFelix Fietkau 911c8846e10SFelix Fietkau return 0; 912c8846e10SFelix Fietkau } 913c8846e10SFelix Fietkau 914c8846e10SFelix Fietkau int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, 915300832adSLorenzo Bianconi struct sk_buff *skb, enum mt76_txq_id qid, 916c8846e10SFelix Fietkau struct mt76_wcid *wcid, struct ieee80211_sta *sta, 917*b5903c47SLorenzo Bianconi struct mt76_tx_info *tx_info) 918c8846e10SFelix Fietkau { 919c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 920c8846e10SFelix Fietkau struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid); 921c8846e10SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 922c8846e10SFelix Fietkau struct ieee80211_key_conf *key = info->control.hw_key; 923c8846e10SFelix Fietkau int pid; 924c8846e10SFelix Fietkau 925c8846e10SFelix Fietkau if (!wcid) 926c8846e10SFelix Fietkau wcid = &dev->global_sta.wcid; 927c8846e10SFelix Fietkau 928c8846e10SFelix Fietkau if (sta) { 929c8846e10SFelix Fietkau msta = (struct mt7603_sta *)sta->drv_priv; 930c8846e10SFelix Fietkau 931c8846e10SFelix Fietkau if ((info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER | 932c8846e10SFelix Fietkau IEEE80211_TX_CTL_CLEAR_PS_FILT)) || 933c8846e10SFelix Fietkau (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) 934c8846e10SFelix Fietkau mt7603_wtbl_set_ps(dev, msta, false); 935c8846e10SFelix Fietkau } 936c8846e10SFelix Fietkau 937c8846e10SFelix Fietkau pid = mt76_tx_status_skb_add(mdev, wcid, skb); 938c8846e10SFelix Fietkau 939c8846e10SFelix Fietkau if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { 940c8846e10SFelix Fietkau spin_lock_bh(&dev->mt76.lock); 941c8846e10SFelix Fietkau msta->rate_probe = true; 942c8846e10SFelix Fietkau mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0], 943c8846e10SFelix Fietkau msta->rates); 944c8846e10SFelix Fietkau spin_unlock_bh(&dev->mt76.lock); 945c8846e10SFelix Fietkau } 946c8846e10SFelix Fietkau 947300832adSLorenzo Bianconi mt7603_mac_write_txwi(dev, txwi_ptr, skb, qid, wcid, sta, pid, key); 948c8846e10SFelix Fietkau 949c8846e10SFelix Fietkau return 0; 950c8846e10SFelix Fietkau } 951c8846e10SFelix Fietkau 952c8846e10SFelix Fietkau static bool 953c8846e10SFelix Fietkau mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, 954c8846e10SFelix Fietkau struct ieee80211_tx_info *info, __le32 *txs_data) 955c8846e10SFelix Fietkau { 956c8846e10SFelix Fietkau struct ieee80211_supported_band *sband; 957c8846e10SFelix Fietkau int final_idx = 0; 958c8846e10SFelix Fietkau u32 final_rate; 959c8846e10SFelix Fietkau u32 final_rate_flags; 960c8846e10SFelix Fietkau bool final_mpdu; 961c8846e10SFelix Fietkau bool ack_timeout; 962c8846e10SFelix Fietkau bool fixed_rate; 963c8846e10SFelix Fietkau bool probe; 964c8846e10SFelix Fietkau bool ampdu; 965c8846e10SFelix Fietkau bool cck = false; 966c8846e10SFelix Fietkau int count; 967c8846e10SFelix Fietkau u32 txs; 968c8846e10SFelix Fietkau u8 pid; 969c8846e10SFelix Fietkau int idx; 970c8846e10SFelix Fietkau int i; 971c8846e10SFelix Fietkau 972c8846e10SFelix Fietkau fixed_rate = info->status.rates[0].count; 973c8846e10SFelix Fietkau probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); 974c8846e10SFelix Fietkau 975c8846e10SFelix Fietkau txs = le32_to_cpu(txs_data[4]); 976c8846e10SFelix Fietkau final_mpdu = txs & MT_TXS4_ACKED_MPDU; 977c8846e10SFelix Fietkau ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); 978c8846e10SFelix Fietkau pid = FIELD_GET(MT_TXS4_PID, txs); 979c8846e10SFelix Fietkau count = FIELD_GET(MT_TXS4_TX_COUNT, txs); 980c8846e10SFelix Fietkau 981c8846e10SFelix Fietkau txs = le32_to_cpu(txs_data[0]); 982c8846e10SFelix Fietkau final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); 983c8846e10SFelix Fietkau ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; 984c8846e10SFelix Fietkau 985c8846e10SFelix Fietkau if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT)) 986c8846e10SFelix Fietkau return false; 987c8846e10SFelix Fietkau 988c8846e10SFelix Fietkau if (txs & MT_TXS0_QUEUE_TIMEOUT) 989c8846e10SFelix Fietkau return false; 990c8846e10SFelix Fietkau 991c8846e10SFelix Fietkau if (!ack_timeout) 992c8846e10SFelix Fietkau info->flags |= IEEE80211_TX_STAT_ACK; 993c8846e10SFelix Fietkau 994c8846e10SFelix Fietkau info->status.ampdu_len = 1; 995c8846e10SFelix Fietkau info->status.ampdu_ack_len = !!(info->flags & 996c8846e10SFelix Fietkau IEEE80211_TX_STAT_ACK); 997c8846e10SFelix Fietkau 998c8846e10SFelix Fietkau if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) 999c8846e10SFelix Fietkau info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; 1000c8846e10SFelix Fietkau 1001c8846e10SFelix Fietkau if (fixed_rate && !probe) { 1002c8846e10SFelix Fietkau info->status.rates[0].count = count; 1003c8846e10SFelix Fietkau goto out; 1004c8846e10SFelix Fietkau } 1005c8846e10SFelix Fietkau 1006c8846e10SFelix Fietkau for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { 1007c8846e10SFelix Fietkau int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY); 1008c8846e10SFelix Fietkau 1009c8846e10SFelix Fietkau if (!i && probe) { 1010c8846e10SFelix Fietkau cur_count = 1; 1011c8846e10SFelix Fietkau } else { 1012c8846e10SFelix Fietkau info->status.rates[i] = sta->rates[idx]; 1013c8846e10SFelix Fietkau idx++; 1014c8846e10SFelix Fietkau } 1015c8846e10SFelix Fietkau 1016c8846e10SFelix Fietkau if (i && info->status.rates[i].idx < 0) { 1017c8846e10SFelix Fietkau info->status.rates[i - 1].count += count; 1018c8846e10SFelix Fietkau break; 1019c8846e10SFelix Fietkau } 1020c8846e10SFelix Fietkau 1021c8846e10SFelix Fietkau if (!count) { 1022c8846e10SFelix Fietkau info->status.rates[i].idx = -1; 1023c8846e10SFelix Fietkau break; 1024c8846e10SFelix Fietkau } 1025c8846e10SFelix Fietkau 1026c8846e10SFelix Fietkau info->status.rates[i].count = cur_count; 1027c8846e10SFelix Fietkau final_idx = i; 1028c8846e10SFelix Fietkau count -= cur_count; 1029c8846e10SFelix Fietkau } 1030c8846e10SFelix Fietkau 1031c8846e10SFelix Fietkau out: 1032c8846e10SFelix Fietkau final_rate_flags = info->status.rates[final_idx].flags; 1033c8846e10SFelix Fietkau 1034c8846e10SFelix Fietkau switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { 1035c8846e10SFelix Fietkau case MT_PHY_TYPE_CCK: 1036c8846e10SFelix Fietkau cck = true; 1037c8846e10SFelix Fietkau /* fall through */ 1038c8846e10SFelix Fietkau case MT_PHY_TYPE_OFDM: 1039c8846e10SFelix Fietkau if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) 1040c8846e10SFelix Fietkau sband = &dev->mt76.sband_5g.sband; 1041c8846e10SFelix Fietkau else 1042c8846e10SFelix Fietkau sband = &dev->mt76.sband_2g.sband; 1043c8846e10SFelix Fietkau final_rate &= GENMASK(5, 0); 1044c8846e10SFelix Fietkau final_rate = mt7603_get_rate(dev, sband, final_rate, cck); 1045c8846e10SFelix Fietkau final_rate_flags = 0; 1046c8846e10SFelix Fietkau break; 1047c8846e10SFelix Fietkau case MT_PHY_TYPE_HT_GF: 1048c8846e10SFelix Fietkau case MT_PHY_TYPE_HT: 1049c8846e10SFelix Fietkau final_rate_flags |= IEEE80211_TX_RC_MCS; 1050c8846e10SFelix Fietkau final_rate &= GENMASK(5, 0); 105176352769SFelix Fietkau if (final_rate > 15) 1052c8846e10SFelix Fietkau return false; 1053c8846e10SFelix Fietkau break; 1054c8846e10SFelix Fietkau default: 1055c8846e10SFelix Fietkau return false; 1056c8846e10SFelix Fietkau } 1057c8846e10SFelix Fietkau 1058c8846e10SFelix Fietkau info->status.rates[final_idx].idx = final_rate; 1059c8846e10SFelix Fietkau info->status.rates[final_idx].flags = final_rate_flags; 1060c8846e10SFelix Fietkau 1061c8846e10SFelix Fietkau return true; 1062c8846e10SFelix Fietkau } 1063c8846e10SFelix Fietkau 1064c8846e10SFelix Fietkau static bool 1065c8846e10SFelix Fietkau mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, 1066c8846e10SFelix Fietkau __le32 *txs_data) 1067c8846e10SFelix Fietkau { 1068c8846e10SFelix Fietkau struct mt76_dev *mdev = &dev->mt76; 1069c8846e10SFelix Fietkau struct sk_buff_head list; 1070c8846e10SFelix Fietkau struct sk_buff *skb; 1071c8846e10SFelix Fietkau 1072c8846e10SFelix Fietkau if (pid < MT_PACKET_ID_FIRST) 1073c8846e10SFelix Fietkau return false; 1074c8846e10SFelix Fietkau 1075c8846e10SFelix Fietkau mt76_tx_status_lock(mdev, &list); 1076c8846e10SFelix Fietkau skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); 1077c8846e10SFelix Fietkau if (skb) { 1078c8846e10SFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1079c8846e10SFelix Fietkau 1080c8846e10SFelix Fietkau if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { 1081c8846e10SFelix Fietkau spin_lock_bh(&dev->mt76.lock); 1082c8846e10SFelix Fietkau if (sta->rate_probe) { 1083c8846e10SFelix Fietkau mt7603_wtbl_set_rates(dev, sta, NULL, 1084c8846e10SFelix Fietkau sta->rates); 1085c8846e10SFelix Fietkau sta->rate_probe = false; 1086c8846e10SFelix Fietkau } 1087c8846e10SFelix Fietkau spin_unlock_bh(&dev->mt76.lock); 1088c8846e10SFelix Fietkau } 1089c8846e10SFelix Fietkau 1090c8846e10SFelix Fietkau if (!mt7603_fill_txs(dev, sta, info, txs_data)) { 1091c8846e10SFelix Fietkau ieee80211_tx_info_clear_status(info); 1092c8846e10SFelix Fietkau info->status.rates[0].idx = -1; 1093c8846e10SFelix Fietkau } 1094c8846e10SFelix Fietkau 1095c8846e10SFelix Fietkau mt76_tx_status_skb_done(mdev, skb, &list); 1096c8846e10SFelix Fietkau } 1097c8846e10SFelix Fietkau mt76_tx_status_unlock(mdev, &list); 1098c8846e10SFelix Fietkau 1099c8846e10SFelix Fietkau return !!skb; 1100c8846e10SFelix Fietkau } 1101c8846e10SFelix Fietkau 1102c8846e10SFelix Fietkau void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) 1103c8846e10SFelix Fietkau { 1104c8846e10SFelix Fietkau struct ieee80211_tx_info info = {}; 1105c8846e10SFelix Fietkau struct ieee80211_sta *sta = NULL; 1106c8846e10SFelix Fietkau struct mt7603_sta *msta = NULL; 1107c8846e10SFelix Fietkau struct mt76_wcid *wcid; 1108c8846e10SFelix Fietkau __le32 *txs_data = data; 1109c8846e10SFelix Fietkau u32 txs; 1110c8846e10SFelix Fietkau u8 wcidx; 1111c8846e10SFelix Fietkau u8 pid; 1112c8846e10SFelix Fietkau 1113c8846e10SFelix Fietkau txs = le32_to_cpu(txs_data[4]); 1114c8846e10SFelix Fietkau pid = FIELD_GET(MT_TXS4_PID, txs); 1115c8846e10SFelix Fietkau txs = le32_to_cpu(txs_data[3]); 1116c8846e10SFelix Fietkau wcidx = FIELD_GET(MT_TXS3_WCID, txs); 1117c8846e10SFelix Fietkau 1118c8846e10SFelix Fietkau if (pid == MT_PACKET_ID_NO_ACK) 1119c8846e10SFelix Fietkau return; 1120c8846e10SFelix Fietkau 1121c8846e10SFelix Fietkau if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) 1122c8846e10SFelix Fietkau return; 1123c8846e10SFelix Fietkau 1124c8846e10SFelix Fietkau rcu_read_lock(); 1125c8846e10SFelix Fietkau 1126c8846e10SFelix Fietkau wcid = rcu_dereference(dev->mt76.wcid[wcidx]); 1127c8846e10SFelix Fietkau if (!wcid) 1128c8846e10SFelix Fietkau goto out; 1129c8846e10SFelix Fietkau 1130c8846e10SFelix Fietkau msta = container_of(wcid, struct mt7603_sta, wcid); 1131c8846e10SFelix Fietkau sta = wcid_to_sta(wcid); 1132c8846e10SFelix Fietkau 1133c8846e10SFelix Fietkau if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) 1134c8846e10SFelix Fietkau goto out; 1135c8846e10SFelix Fietkau 1136c8846e10SFelix Fietkau if (wcidx >= MT7603_WTBL_STA || !sta) 1137c8846e10SFelix Fietkau goto out; 1138c8846e10SFelix Fietkau 1139c8846e10SFelix Fietkau if (mt7603_fill_txs(dev, msta, &info, txs_data)) 1140c8846e10SFelix Fietkau ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); 1141c8846e10SFelix Fietkau 1142c8846e10SFelix Fietkau out: 1143c8846e10SFelix Fietkau rcu_read_unlock(); 1144c8846e10SFelix Fietkau } 1145c8846e10SFelix Fietkau 1146e226ba2eSLorenzo Bianconi void mt7603_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid, 1147e226ba2eSLorenzo Bianconi struct mt76_queue_entry *e) 1148c8846e10SFelix Fietkau { 1149c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 1150c8846e10SFelix Fietkau struct sk_buff *skb = e->skb; 1151c8846e10SFelix Fietkau 1152c8846e10SFelix Fietkau if (!e->txwi) { 1153c8846e10SFelix Fietkau dev_kfree_skb_any(skb); 1154c8846e10SFelix Fietkau return; 1155c8846e10SFelix Fietkau } 1156c8846e10SFelix Fietkau 1157e226ba2eSLorenzo Bianconi if (qid < 4) 1158c8846e10SFelix Fietkau dev->tx_hang_check = 0; 1159c8846e10SFelix Fietkau 1160c8846e10SFelix Fietkau mt76_tx_complete_skb(mdev, skb); 1161c8846e10SFelix Fietkau } 1162c8846e10SFelix Fietkau 1163c8846e10SFelix Fietkau static bool 1164c8846e10SFelix Fietkau wait_for_wpdma(struct mt7603_dev *dev) 1165c8846e10SFelix Fietkau { 1166c8846e10SFelix Fietkau return mt76_poll(dev, MT_WPDMA_GLO_CFG, 1167c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_DMA_BUSY | 1168c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 1169c8846e10SFelix Fietkau 0, 1000); 1170c8846e10SFelix Fietkau } 1171c8846e10SFelix Fietkau 1172c8846e10SFelix Fietkau static void mt7603_pse_reset(struct mt7603_dev *dev) 1173c8846e10SFelix Fietkau { 1174c8846e10SFelix Fietkau /* Clear previous reset result */ 1175c8846e10SFelix Fietkau if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) 1176c8846e10SFelix Fietkau mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE_S); 1177c8846e10SFelix Fietkau 1178c8846e10SFelix Fietkau /* Reset PSE */ 1179c8846e10SFelix Fietkau mt76_set(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); 1180c8846e10SFelix Fietkau 1181c8846e10SFelix Fietkau if (!mt76_poll_msec(dev, MT_MCU_DEBUG_RESET, 1182c8846e10SFelix Fietkau MT_MCU_DEBUG_RESET_PSE_S, 1183c8846e10SFelix Fietkau MT_MCU_DEBUG_RESET_PSE_S, 500)) { 1184c8846e10SFelix Fietkau dev->reset_cause[RESET_CAUSE_RESET_FAILED]++; 1185c8846e10SFelix Fietkau mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); 1186c8846e10SFelix Fietkau } else { 1187c8846e10SFelix Fietkau dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; 1188c8846e10SFelix Fietkau mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_QUEUES); 1189c8846e10SFelix Fietkau } 1190c8846e10SFelix Fietkau 1191c8846e10SFelix Fietkau if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] >= 3) 1192c8846e10SFelix Fietkau dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; 1193c8846e10SFelix Fietkau } 1194c8846e10SFelix Fietkau 1195c8846e10SFelix Fietkau void mt7603_mac_dma_start(struct mt7603_dev *dev) 1196c8846e10SFelix Fietkau { 1197c8846e10SFelix Fietkau mt7603_mac_start(dev); 1198c8846e10SFelix Fietkau 1199c8846e10SFelix Fietkau wait_for_wpdma(dev); 1200c8846e10SFelix Fietkau usleep_range(50, 100); 1201c8846e10SFelix Fietkau 1202c8846e10SFelix Fietkau mt76_set(dev, MT_WPDMA_GLO_CFG, 1203c8846e10SFelix Fietkau (MT_WPDMA_GLO_CFG_TX_DMA_EN | 1204c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_RX_DMA_EN | 1205c8846e10SFelix Fietkau FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) | 1206c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE)); 1207c8846e10SFelix Fietkau 1208c8846e10SFelix Fietkau mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); 1209c8846e10SFelix Fietkau } 1210c8846e10SFelix Fietkau 1211c8846e10SFelix Fietkau void mt7603_mac_start(struct mt7603_dev *dev) 1212c8846e10SFelix Fietkau { 1213c8846e10SFelix Fietkau mt76_clear(dev, MT_ARB_SCR, 1214c8846e10SFelix Fietkau MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 1215c8846e10SFelix Fietkau mt76_wr(dev, MT_WF_ARB_TX_START_0, ~0); 1216c8846e10SFelix Fietkau mt76_set(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); 1217c8846e10SFelix Fietkau } 1218c8846e10SFelix Fietkau 1219c8846e10SFelix Fietkau void mt7603_mac_stop(struct mt7603_dev *dev) 1220c8846e10SFelix Fietkau { 1221c8846e10SFelix Fietkau mt76_set(dev, MT_ARB_SCR, 1222c8846e10SFelix Fietkau MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); 1223c8846e10SFelix Fietkau mt76_wr(dev, MT_WF_ARB_TX_START_0, 0); 1224c8846e10SFelix Fietkau mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); 1225c8846e10SFelix Fietkau } 1226c8846e10SFelix Fietkau 1227c8846e10SFelix Fietkau void mt7603_pse_client_reset(struct mt7603_dev *dev) 1228c8846e10SFelix Fietkau { 1229c8846e10SFelix Fietkau u32 addr; 1230c8846e10SFelix Fietkau 1231c8846e10SFelix Fietkau addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + 1232c8846e10SFelix Fietkau MT_CLIENT_RESET_TX); 1233c8846e10SFelix Fietkau 1234c8846e10SFelix Fietkau /* Clear previous reset state */ 1235c8846e10SFelix Fietkau mt76_clear(dev, addr, 1236c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_1 | 1237c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_2 | 1238c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_1_S | 1239c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_2_S); 1240c8846e10SFelix Fietkau 1241c8846e10SFelix Fietkau /* Start PSE client TX abort */ 1242c8846e10SFelix Fietkau mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); 1243c8846e10SFelix Fietkau mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, 1244c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_1_S, 500); 1245c8846e10SFelix Fietkau 1246c8846e10SFelix Fietkau mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2); 1247c8846e10SFelix Fietkau mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); 1248c8846e10SFelix Fietkau 1249c8846e10SFelix Fietkau /* Wait for PSE client to clear TX FIFO */ 1250c8846e10SFelix Fietkau mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S, 1251c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_2_S, 500); 1252c8846e10SFelix Fietkau 1253c8846e10SFelix Fietkau /* Clear PSE client TX abort state */ 1254c8846e10SFelix Fietkau mt76_clear(dev, addr, 1255c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_1 | 1256c8846e10SFelix Fietkau MT_CLIENT_RESET_TX_R_E_2); 1257c8846e10SFelix Fietkau } 1258c8846e10SFelix Fietkau 1259c8846e10SFelix Fietkau static void mt7603_dma_sched_reset(struct mt7603_dev *dev) 1260c8846e10SFelix Fietkau { 1261c8846e10SFelix Fietkau if (!is_mt7628(dev)) 1262c8846e10SFelix Fietkau return; 1263c8846e10SFelix Fietkau 1264c8846e10SFelix Fietkau mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET); 1265c8846e10SFelix Fietkau mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET); 1266c8846e10SFelix Fietkau } 1267c8846e10SFelix Fietkau 1268c8846e10SFelix Fietkau static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) 1269c8846e10SFelix Fietkau { 1270c8846e10SFelix Fietkau int beacon_int = dev->beacon_int; 1271c8846e10SFelix Fietkau u32 mask = dev->mt76.mmio.irqmask; 1272c8846e10SFelix Fietkau int i; 1273c8846e10SFelix Fietkau 1274c8846e10SFelix Fietkau ieee80211_stop_queues(dev->mt76.hw); 1275c8846e10SFelix Fietkau set_bit(MT76_RESET, &dev->mt76.state); 1276c8846e10SFelix Fietkau 1277c8846e10SFelix Fietkau /* lock/unlock all queues to ensure that no tx is pending */ 1278c8846e10SFelix Fietkau mt76_txq_schedule_all(&dev->mt76); 1279c8846e10SFelix Fietkau 1280c8846e10SFelix Fietkau tasklet_disable(&dev->tx_tasklet); 1281c8846e10SFelix Fietkau tasklet_disable(&dev->pre_tbtt_tasklet); 1282c8846e10SFelix Fietkau napi_disable(&dev->mt76.napi[0]); 1283c8846e10SFelix Fietkau napi_disable(&dev->mt76.napi[1]); 1284c8846e10SFelix Fietkau 1285c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 1286c8846e10SFelix Fietkau 1287c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, -1, 0); 1288c8846e10SFelix Fietkau 1289c8846e10SFelix Fietkau if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] || 1290c8846e10SFelix Fietkau dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY || 1291c8846e10SFelix Fietkau dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK || 1292c8846e10SFelix Fietkau dev->cur_reset_cause == RESET_CAUSE_TX_HANG) 1293c8846e10SFelix Fietkau mt7603_pse_reset(dev); 1294c8846e10SFelix Fietkau 1295c8846e10SFelix Fietkau if (dev->reset_cause[RESET_CAUSE_RESET_FAILED]) 1296c8846e10SFelix Fietkau goto skip_dma_reset; 1297c8846e10SFelix Fietkau 1298c8846e10SFelix Fietkau mt7603_mac_stop(dev); 1299c8846e10SFelix Fietkau 1300c8846e10SFelix Fietkau mt76_clear(dev, MT_WPDMA_GLO_CFG, 1301c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | 1302c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); 1303c8846e10SFelix Fietkau usleep_range(1000, 2000); 1304c8846e10SFelix Fietkau 1305c8846e10SFelix Fietkau mt7603_irq_disable(dev, mask); 1306c8846e10SFelix Fietkau 1307c8846e10SFelix Fietkau mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); 1308c8846e10SFelix Fietkau 1309c8846e10SFelix Fietkau mt7603_pse_client_reset(dev); 1310c8846e10SFelix Fietkau 1311c8846e10SFelix Fietkau for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) 1312c8846e10SFelix Fietkau mt76_queue_tx_cleanup(dev, i, true); 1313c8846e10SFelix Fietkau 1314c8846e10SFelix Fietkau for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) 1315c8846e10SFelix Fietkau mt76_queue_rx_reset(dev, i); 1316c8846e10SFelix Fietkau 1317c8846e10SFelix Fietkau mt7603_dma_sched_reset(dev); 1318c8846e10SFelix Fietkau 1319c8846e10SFelix Fietkau mt7603_mac_dma_start(dev); 1320c8846e10SFelix Fietkau 1321c8846e10SFelix Fietkau mt7603_irq_enable(dev, mask); 1322c8846e10SFelix Fietkau 1323c8846e10SFelix Fietkau skip_dma_reset: 1324c8846e10SFelix Fietkau clear_bit(MT76_RESET, &dev->mt76.state); 1325c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 1326c8846e10SFelix Fietkau 1327c8846e10SFelix Fietkau tasklet_enable(&dev->tx_tasklet); 1328c8846e10SFelix Fietkau tasklet_schedule(&dev->tx_tasklet); 1329c8846e10SFelix Fietkau 1330c8846e10SFelix Fietkau tasklet_enable(&dev->pre_tbtt_tasklet); 1331c8846e10SFelix Fietkau mt7603_beacon_set_timer(dev, -1, beacon_int); 1332c8846e10SFelix Fietkau 1333c8846e10SFelix Fietkau napi_enable(&dev->mt76.napi[0]); 1334c8846e10SFelix Fietkau napi_schedule(&dev->mt76.napi[0]); 1335c8846e10SFelix Fietkau 1336c8846e10SFelix Fietkau napi_enable(&dev->mt76.napi[1]); 1337c8846e10SFelix Fietkau napi_schedule(&dev->mt76.napi[1]); 1338c8846e10SFelix Fietkau 1339c8846e10SFelix Fietkau ieee80211_wake_queues(dev->mt76.hw); 1340c8846e10SFelix Fietkau mt76_txq_schedule_all(&dev->mt76); 1341c8846e10SFelix Fietkau } 1342c8846e10SFelix Fietkau 1343c8846e10SFelix Fietkau static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index) 1344c8846e10SFelix Fietkau { 1345c8846e10SFelix Fietkau u32 val; 1346c8846e10SFelix Fietkau 1347c8846e10SFelix Fietkau mt76_wr(dev, MT_WPDMA_DEBUG, 1348c8846e10SFelix Fietkau FIELD_PREP(MT_WPDMA_DEBUG_IDX, index) | 1349c8846e10SFelix Fietkau MT_WPDMA_DEBUG_SEL); 1350c8846e10SFelix Fietkau 1351c8846e10SFelix Fietkau val = mt76_rr(dev, MT_WPDMA_DEBUG); 1352c8846e10SFelix Fietkau return FIELD_GET(MT_WPDMA_DEBUG_VALUE, val); 1353c8846e10SFelix Fietkau } 1354c8846e10SFelix Fietkau 1355c8846e10SFelix Fietkau static bool mt7603_rx_fifo_busy(struct mt7603_dev *dev) 1356c8846e10SFelix Fietkau { 1357c8846e10SFelix Fietkau if (is_mt7628(dev)) 1358c8846e10SFelix Fietkau return mt7603_dma_debug(dev, 9) & BIT(9); 1359c8846e10SFelix Fietkau 1360c8846e10SFelix Fietkau return mt7603_dma_debug(dev, 2) & BIT(8); 1361c8846e10SFelix Fietkau } 1362c8846e10SFelix Fietkau 1363c8846e10SFelix Fietkau static bool mt7603_rx_dma_busy(struct mt7603_dev *dev) 1364c8846e10SFelix Fietkau { 1365c8846e10SFelix Fietkau if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_RX_DMA_BUSY)) 1366c8846e10SFelix Fietkau return false; 1367c8846e10SFelix Fietkau 1368c8846e10SFelix Fietkau return mt7603_rx_fifo_busy(dev); 1369c8846e10SFelix Fietkau } 1370c8846e10SFelix Fietkau 1371c8846e10SFelix Fietkau static bool mt7603_tx_dma_busy(struct mt7603_dev *dev) 1372c8846e10SFelix Fietkau { 1373c8846e10SFelix Fietkau u32 val; 1374c8846e10SFelix Fietkau 1375c8846e10SFelix Fietkau if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_TX_DMA_BUSY)) 1376c8846e10SFelix Fietkau return false; 1377c8846e10SFelix Fietkau 1378c8846e10SFelix Fietkau val = mt7603_dma_debug(dev, 9); 1379c8846e10SFelix Fietkau return (val & BIT(8)) && (val & 0xf) != 0xf; 1380c8846e10SFelix Fietkau } 1381c8846e10SFelix Fietkau 1382c8846e10SFelix Fietkau static bool mt7603_tx_hang(struct mt7603_dev *dev) 1383c8846e10SFelix Fietkau { 1384c8846e10SFelix Fietkau struct mt76_queue *q; 1385c8846e10SFelix Fietkau u32 dma_idx, prev_dma_idx; 1386c8846e10SFelix Fietkau int i; 1387c8846e10SFelix Fietkau 1388c8846e10SFelix Fietkau for (i = 0; i < 4; i++) { 1389af005f26SLorenzo Bianconi q = dev->mt76.q_tx[i].q; 1390c8846e10SFelix Fietkau 1391c8846e10SFelix Fietkau if (!q->queued) 1392c8846e10SFelix Fietkau continue; 1393c8846e10SFelix Fietkau 1394c8846e10SFelix Fietkau prev_dma_idx = dev->tx_dma_idx[i]; 1395c8846e10SFelix Fietkau dma_idx = ioread32(&q->regs->dma_idx); 1396c8846e10SFelix Fietkau dev->tx_dma_idx[i] = dma_idx; 1397c8846e10SFelix Fietkau 1398c8846e10SFelix Fietkau if (dma_idx == prev_dma_idx && 1399c8846e10SFelix Fietkau dma_idx != ioread32(&q->regs->cpu_idx)) 1400c8846e10SFelix Fietkau break; 1401c8846e10SFelix Fietkau } 1402c8846e10SFelix Fietkau 1403c8846e10SFelix Fietkau return i < 4; 1404c8846e10SFelix Fietkau } 1405c8846e10SFelix Fietkau 1406c8846e10SFelix Fietkau static bool mt7603_rx_pse_busy(struct mt7603_dev *dev) 1407c8846e10SFelix Fietkau { 1408c8846e10SFelix Fietkau u32 addr, val; 1409c8846e10SFelix Fietkau 1410c8846e10SFelix Fietkau if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES) 1411c8846e10SFelix Fietkau return true; 1412c8846e10SFelix Fietkau 1413c8846e10SFelix Fietkau if (mt7603_rx_fifo_busy(dev)) 1414c8846e10SFelix Fietkau return false; 1415c8846e10SFelix Fietkau 1416c8846e10SFelix Fietkau addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS); 1417c8846e10SFelix Fietkau mt76_wr(dev, addr, 3); 1418c8846e10SFelix Fietkau val = mt76_rr(dev, addr) >> 16; 1419c8846e10SFelix Fietkau 1420c8846e10SFelix Fietkau if (is_mt7628(dev) && (val & 0x4001) == 0x4001) 1421c8846e10SFelix Fietkau return true; 1422c8846e10SFelix Fietkau 1423c8846e10SFelix Fietkau return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001; 1424c8846e10SFelix Fietkau } 1425c8846e10SFelix Fietkau 1426c8846e10SFelix Fietkau static bool 1427c8846e10SFelix Fietkau mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter, 1428c8846e10SFelix Fietkau enum mt7603_reset_cause cause, 1429c8846e10SFelix Fietkau bool (*check)(struct mt7603_dev *dev)) 1430c8846e10SFelix Fietkau { 1431c8846e10SFelix Fietkau if (dev->reset_test == cause + 1) { 1432c8846e10SFelix Fietkau dev->reset_test = 0; 1433c8846e10SFelix Fietkau goto trigger; 1434c8846e10SFelix Fietkau } 1435c8846e10SFelix Fietkau 1436c8846e10SFelix Fietkau if (check) { 1437c8846e10SFelix Fietkau if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) { 1438c8846e10SFelix Fietkau *counter = 0; 1439c8846e10SFelix Fietkau return false; 1440c8846e10SFelix Fietkau } 1441c8846e10SFelix Fietkau 1442c8846e10SFelix Fietkau (*counter)++; 1443c8846e10SFelix Fietkau } 1444c8846e10SFelix Fietkau 1445c8846e10SFelix Fietkau if (*counter < MT7603_WATCHDOG_TIMEOUT) 1446c8846e10SFelix Fietkau return false; 1447c8846e10SFelix Fietkau trigger: 1448c8846e10SFelix Fietkau dev->cur_reset_cause = cause; 1449c8846e10SFelix Fietkau dev->reset_cause[cause]++; 1450c8846e10SFelix Fietkau return true; 1451c8846e10SFelix Fietkau } 1452c8846e10SFelix Fietkau 1453c8846e10SFelix Fietkau void mt7603_update_channel(struct mt76_dev *mdev) 1454c8846e10SFelix Fietkau { 1455c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 1456c8846e10SFelix Fietkau struct mt76_channel_state *state; 1457c8846e10SFelix Fietkau ktime_t cur_time; 1458c8846e10SFelix Fietkau u32 busy; 1459c8846e10SFelix Fietkau 1460c8846e10SFelix Fietkau if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) 1461c8846e10SFelix Fietkau return; 1462c8846e10SFelix Fietkau 1463c8846e10SFelix Fietkau state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan); 1464c8846e10SFelix Fietkau busy = mt76_rr(dev, MT_MIB_STAT_PSCCA); 1465c8846e10SFelix Fietkau 1466c8846e10SFelix Fietkau spin_lock_bh(&dev->mt76.cc_lock); 1467c8846e10SFelix Fietkau cur_time = ktime_get_boottime(); 1468c8846e10SFelix Fietkau state->cc_busy += busy; 1469c8846e10SFelix Fietkau state->cc_active += ktime_to_us(ktime_sub(cur_time, dev->survey_time)); 1470c8846e10SFelix Fietkau dev->survey_time = cur_time; 1471c8846e10SFelix Fietkau spin_unlock_bh(&dev->mt76.cc_lock); 1472c8846e10SFelix Fietkau } 1473c8846e10SFelix Fietkau 1474c8846e10SFelix Fietkau void 1475c8846e10SFelix Fietkau mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val) 1476c8846e10SFelix Fietkau { 1477c8846e10SFelix Fietkau u32 rxtd_6 = 0xd7c80000; 1478c8846e10SFelix Fietkau 1479c8846e10SFelix Fietkau if (val == dev->ed_strict_mode) 1480c8846e10SFelix Fietkau return; 1481c8846e10SFelix Fietkau 1482c8846e10SFelix Fietkau dev->ed_strict_mode = val; 1483c8846e10SFelix Fietkau 1484c8846e10SFelix Fietkau /* Ensure that ED/CCA does not trigger if disabled */ 1485c8846e10SFelix Fietkau if (!dev->ed_monitor) 1486c8846e10SFelix Fietkau rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34); 1487c8846e10SFelix Fietkau else 1488c8846e10SFelix Fietkau rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d); 1489c8846e10SFelix Fietkau 1490c8846e10SFelix Fietkau if (dev->ed_monitor && !dev->ed_strict_mode) 1491c8846e10SFelix Fietkau rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f); 1492c8846e10SFelix Fietkau else 1493c8846e10SFelix Fietkau rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10); 1494c8846e10SFelix Fietkau 1495c8846e10SFelix Fietkau mt76_wr(dev, MT_RXTD(6), rxtd_6); 1496c8846e10SFelix Fietkau 1497c8846e10SFelix Fietkau mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN, 1498c8846e10SFelix Fietkau dev->ed_monitor && !dev->ed_strict_mode); 1499c8846e10SFelix Fietkau } 1500c8846e10SFelix Fietkau 1501c8846e10SFelix Fietkau static void 1502c8846e10SFelix Fietkau mt7603_edcca_check(struct mt7603_dev *dev) 1503c8846e10SFelix Fietkau { 1504c8846e10SFelix Fietkau u32 val = mt76_rr(dev, MT_AGC(41)); 1505c8846e10SFelix Fietkau ktime_t cur_time; 1506c8846e10SFelix Fietkau int rssi0, rssi1; 1507c8846e10SFelix Fietkau u32 active; 1508c8846e10SFelix Fietkau u32 ed_busy; 1509c8846e10SFelix Fietkau 1510c8846e10SFelix Fietkau if (!dev->ed_monitor) 1511c8846e10SFelix Fietkau return; 1512c8846e10SFelix Fietkau 1513c8846e10SFelix Fietkau rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val); 1514c8846e10SFelix Fietkau if (rssi0 > 128) 1515c8846e10SFelix Fietkau rssi0 -= 256; 1516c8846e10SFelix Fietkau 1517c8846e10SFelix Fietkau rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val); 1518c8846e10SFelix Fietkau if (rssi1 > 128) 1519c8846e10SFelix Fietkau rssi1 -= 256; 1520c8846e10SFelix Fietkau 1521c8846e10SFelix Fietkau if (max(rssi0, rssi1) >= -40 && 1522c8846e10SFelix Fietkau dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH) 1523c8846e10SFelix Fietkau dev->ed_strong_signal++; 1524c8846e10SFelix Fietkau else if (dev->ed_strong_signal > 0) 1525c8846e10SFelix Fietkau dev->ed_strong_signal--; 1526c8846e10SFelix Fietkau 1527c8846e10SFelix Fietkau cur_time = ktime_get_boottime(); 1528c8846e10SFelix Fietkau ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK; 1529c8846e10SFelix Fietkau 1530c8846e10SFelix Fietkau active = ktime_to_us(ktime_sub(cur_time, dev->ed_time)); 1531c8846e10SFelix Fietkau dev->ed_time = cur_time; 1532c8846e10SFelix Fietkau 1533c8846e10SFelix Fietkau if (!active) 1534c8846e10SFelix Fietkau return; 1535c8846e10SFelix Fietkau 1536c8846e10SFelix Fietkau if (100 * ed_busy / active > 90) { 1537c8846e10SFelix Fietkau if (dev->ed_trigger < 0) 1538c8846e10SFelix Fietkau dev->ed_trigger = 0; 1539c8846e10SFelix Fietkau dev->ed_trigger++; 1540c8846e10SFelix Fietkau } else { 1541c8846e10SFelix Fietkau if (dev->ed_trigger > 0) 1542c8846e10SFelix Fietkau dev->ed_trigger = 0; 1543c8846e10SFelix Fietkau dev->ed_trigger--; 1544c8846e10SFelix Fietkau } 1545c8846e10SFelix Fietkau 1546c8846e10SFelix Fietkau if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH || 1547c8846e10SFelix Fietkau dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) { 1548c8846e10SFelix Fietkau mt7603_edcca_set_strict(dev, true); 1549c8846e10SFelix Fietkau } else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) { 1550c8846e10SFelix Fietkau mt7603_edcca_set_strict(dev, false); 1551c8846e10SFelix Fietkau } 1552c8846e10SFelix Fietkau 1553c8846e10SFelix Fietkau if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH) 1554c8846e10SFelix Fietkau dev->ed_trigger = MT7603_EDCCA_BLOCK_TH; 1555c8846e10SFelix Fietkau else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) 1556c8846e10SFelix Fietkau dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH; 1557c8846e10SFelix Fietkau } 1558c8846e10SFelix Fietkau 1559c8846e10SFelix Fietkau void mt7603_cca_stats_reset(struct mt7603_dev *dev) 1560c8846e10SFelix Fietkau { 1561c8846e10SFelix Fietkau mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); 1562c8846e10SFelix Fietkau mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); 1563c8846e10SFelix Fietkau mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN); 1564c8846e10SFelix Fietkau } 1565c8846e10SFelix Fietkau 1566c8846e10SFelix Fietkau static void 1567c8846e10SFelix Fietkau mt7603_adjust_sensitivity(struct mt7603_dev *dev) 1568c8846e10SFelix Fietkau { 1569c8846e10SFelix Fietkau u32 agc0 = dev->agc0, agc3 = dev->agc3; 1570c8846e10SFelix Fietkau u32 adj; 1571c8846e10SFelix Fietkau 1572c8846e10SFelix Fietkau if (!dev->sensitivity || dev->sensitivity < -100) { 1573c8846e10SFelix Fietkau dev->sensitivity = 0; 1574c8846e10SFelix Fietkau } else if (dev->sensitivity <= -84) { 1575c8846e10SFelix Fietkau adj = 7 + (dev->sensitivity + 92) / 2; 1576c8846e10SFelix Fietkau 1577c8846e10SFelix Fietkau agc0 = 0x56f0076f; 1578c8846e10SFelix Fietkau agc0 |= adj << 12; 1579c8846e10SFelix Fietkau agc0 |= adj << 16; 1580c8846e10SFelix Fietkau agc3 = 0x81d0d5e3; 1581c8846e10SFelix Fietkau } else if (dev->sensitivity <= -72) { 1582c8846e10SFelix Fietkau adj = 7 + (dev->sensitivity + 80) / 2; 1583c8846e10SFelix Fietkau 1584c8846e10SFelix Fietkau agc0 = 0x6af0006f; 1585c8846e10SFelix Fietkau agc0 |= adj << 8; 1586c8846e10SFelix Fietkau agc0 |= adj << 12; 1587c8846e10SFelix Fietkau agc0 |= adj << 16; 1588c8846e10SFelix Fietkau 1589c8846e10SFelix Fietkau agc3 = 0x8181d5e3; 1590c8846e10SFelix Fietkau } else { 1591c8846e10SFelix Fietkau if (dev->sensitivity > -54) 1592c8846e10SFelix Fietkau dev->sensitivity = -54; 1593c8846e10SFelix Fietkau 1594c8846e10SFelix Fietkau adj = 7 + (dev->sensitivity + 80) / 2; 1595c8846e10SFelix Fietkau 1596c8846e10SFelix Fietkau agc0 = 0x7ff0000f; 1597c8846e10SFelix Fietkau agc0 |= adj << 4; 1598c8846e10SFelix Fietkau agc0 |= adj << 8; 1599c8846e10SFelix Fietkau agc0 |= adj << 12; 1600c8846e10SFelix Fietkau agc0 |= adj << 16; 1601c8846e10SFelix Fietkau 1602c8846e10SFelix Fietkau agc3 = 0x818181e3; 1603c8846e10SFelix Fietkau } 1604c8846e10SFelix Fietkau 1605c8846e10SFelix Fietkau mt76_wr(dev, MT_AGC(0), agc0); 1606c8846e10SFelix Fietkau mt76_wr(dev, MT_AGC1(0), agc0); 1607c8846e10SFelix Fietkau 1608c8846e10SFelix Fietkau mt76_wr(dev, MT_AGC(3), agc3); 1609c8846e10SFelix Fietkau mt76_wr(dev, MT_AGC1(3), agc3); 1610c8846e10SFelix Fietkau } 1611c8846e10SFelix Fietkau 1612c8846e10SFelix Fietkau static void 1613c8846e10SFelix Fietkau mt7603_false_cca_check(struct mt7603_dev *dev) 1614c8846e10SFelix Fietkau { 1615c8846e10SFelix Fietkau int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm; 1616c8846e10SFelix Fietkau int false_cca; 1617c8846e10SFelix Fietkau int min_signal; 1618c8846e10SFelix Fietkau u32 val; 1619c8846e10SFelix Fietkau 1620c8846e10SFelix Fietkau val = mt76_rr(dev, MT_PHYCTRL_STAT_PD); 1621c8846e10SFelix Fietkau pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val); 1622c8846e10SFelix Fietkau pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val); 1623c8846e10SFelix Fietkau 1624c8846e10SFelix Fietkau val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY); 1625c8846e10SFelix Fietkau mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val); 1626c8846e10SFelix Fietkau mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val); 1627c8846e10SFelix Fietkau 1628c8846e10SFelix Fietkau dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; 1629c8846e10SFelix Fietkau dev->false_cca_cck = pd_cck - mdrdy_cck; 1630c8846e10SFelix Fietkau 1631c8846e10SFelix Fietkau mt7603_cca_stats_reset(dev); 1632c8846e10SFelix Fietkau 1633c8846e10SFelix Fietkau min_signal = mt76_get_min_avg_rssi(&dev->mt76); 1634c8846e10SFelix Fietkau if (!min_signal) { 1635c8846e10SFelix Fietkau dev->sensitivity = 0; 1636c8846e10SFelix Fietkau dev->last_cca_adj = jiffies; 1637c8846e10SFelix Fietkau goto out; 1638c8846e10SFelix Fietkau } 1639c8846e10SFelix Fietkau 1640c8846e10SFelix Fietkau min_signal -= 15; 1641c8846e10SFelix Fietkau 1642c8846e10SFelix Fietkau false_cca = dev->false_cca_ofdm + dev->false_cca_cck; 1643c8846e10SFelix Fietkau if (false_cca > 600) { 1644c8846e10SFelix Fietkau if (!dev->sensitivity) 1645c8846e10SFelix Fietkau dev->sensitivity = -92; 1646c8846e10SFelix Fietkau else 1647c8846e10SFelix Fietkau dev->sensitivity += 2; 1648c8846e10SFelix Fietkau dev->last_cca_adj = jiffies; 1649c8846e10SFelix Fietkau } else if (false_cca < 100 || 1650c8846e10SFelix Fietkau time_after(jiffies, dev->last_cca_adj + 10 * HZ)) { 1651c8846e10SFelix Fietkau dev->last_cca_adj = jiffies; 1652c8846e10SFelix Fietkau if (!dev->sensitivity) 1653c8846e10SFelix Fietkau goto out; 1654c8846e10SFelix Fietkau 1655c8846e10SFelix Fietkau dev->sensitivity -= 2; 1656c8846e10SFelix Fietkau } 1657c8846e10SFelix Fietkau 1658c8846e10SFelix Fietkau if (dev->sensitivity && dev->sensitivity > min_signal) { 1659c8846e10SFelix Fietkau dev->sensitivity = min_signal; 1660c8846e10SFelix Fietkau dev->last_cca_adj = jiffies; 1661c8846e10SFelix Fietkau } 1662c8846e10SFelix Fietkau 1663c8846e10SFelix Fietkau out: 1664c8846e10SFelix Fietkau mt7603_adjust_sensitivity(dev); 1665c8846e10SFelix Fietkau } 1666c8846e10SFelix Fietkau 1667c8846e10SFelix Fietkau void mt7603_mac_work(struct work_struct *work) 1668c8846e10SFelix Fietkau { 1669c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(work, struct mt7603_dev, 1670c8846e10SFelix Fietkau mac_work.work); 1671c8846e10SFelix Fietkau bool reset = false; 1672c8846e10SFelix Fietkau 1673c8846e10SFelix Fietkau mt76_tx_status_check(&dev->mt76, NULL, false); 1674c8846e10SFelix Fietkau 1675c8846e10SFelix Fietkau mutex_lock(&dev->mt76.mutex); 1676c8846e10SFelix Fietkau 1677c8846e10SFelix Fietkau dev->mac_work_count++; 1678c8846e10SFelix Fietkau mt7603_update_channel(&dev->mt76); 1679c8846e10SFelix Fietkau mt7603_edcca_check(dev); 1680c8846e10SFelix Fietkau 1681c8846e10SFelix Fietkau if (dev->mac_work_count == 10) 1682c8846e10SFelix Fietkau mt7603_false_cca_check(dev); 1683c8846e10SFelix Fietkau 1684c8846e10SFelix Fietkau if (mt7603_watchdog_check(dev, &dev->rx_pse_check, 1685c8846e10SFelix Fietkau RESET_CAUSE_RX_PSE_BUSY, 1686c8846e10SFelix Fietkau mt7603_rx_pse_busy) || 1687c8846e10SFelix Fietkau mt7603_watchdog_check(dev, &dev->beacon_check, 1688c8846e10SFelix Fietkau RESET_CAUSE_BEACON_STUCK, 1689c8846e10SFelix Fietkau NULL) || 1690c8846e10SFelix Fietkau mt7603_watchdog_check(dev, &dev->tx_hang_check, 1691c8846e10SFelix Fietkau RESET_CAUSE_TX_HANG, 1692c8846e10SFelix Fietkau mt7603_tx_hang) || 1693c8846e10SFelix Fietkau mt7603_watchdog_check(dev, &dev->tx_dma_check, 1694c8846e10SFelix Fietkau RESET_CAUSE_TX_BUSY, 1695c8846e10SFelix Fietkau mt7603_tx_dma_busy) || 1696c8846e10SFelix Fietkau mt7603_watchdog_check(dev, &dev->rx_dma_check, 1697c8846e10SFelix Fietkau RESET_CAUSE_RX_BUSY, 1698c8846e10SFelix Fietkau mt7603_rx_dma_busy) || 1699c8846e10SFelix Fietkau mt7603_watchdog_check(dev, &dev->mcu_hang, 1700c8846e10SFelix Fietkau RESET_CAUSE_MCU_HANG, 1701c8846e10SFelix Fietkau NULL) || 1702c8846e10SFelix Fietkau dev->reset_cause[RESET_CAUSE_RESET_FAILED]) { 1703c8846e10SFelix Fietkau dev->beacon_check = 0; 1704c8846e10SFelix Fietkau dev->tx_dma_check = 0; 1705c8846e10SFelix Fietkau dev->tx_hang_check = 0; 1706c8846e10SFelix Fietkau dev->rx_dma_check = 0; 1707c8846e10SFelix Fietkau dev->rx_pse_check = 0; 1708c8846e10SFelix Fietkau dev->mcu_hang = 0; 1709c8846e10SFelix Fietkau dev->rx_dma_idx = ~0; 1710c8846e10SFelix Fietkau memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx)); 1711c8846e10SFelix Fietkau reset = true; 1712c8846e10SFelix Fietkau dev->mac_work_count = 0; 1713c8846e10SFelix Fietkau } 1714c8846e10SFelix Fietkau 1715c8846e10SFelix Fietkau if (dev->mac_work_count >= 10) 1716c8846e10SFelix Fietkau dev->mac_work_count = 0; 1717c8846e10SFelix Fietkau 1718c8846e10SFelix Fietkau mutex_unlock(&dev->mt76.mutex); 1719c8846e10SFelix Fietkau 1720c8846e10SFelix Fietkau if (reset) 1721c8846e10SFelix Fietkau mt7603_mac_watchdog_reset(dev); 1722c8846e10SFelix Fietkau 1723c8846e10SFelix Fietkau ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, 1724c8846e10SFelix Fietkau msecs_to_jiffies(MT7603_WATCHDOG_TIME)); 1725c8846e10SFelix Fietkau } 1726