1c8846e10SFelix Fietkau /* SPDX-License-Identifier: ISC */ 2c8846e10SFelix Fietkau 3c8846e10SFelix Fietkau #include "mt7603.h" 4c8846e10SFelix Fietkau #include "mac.h" 5c8846e10SFelix Fietkau #include "../dma.h" 6c8846e10SFelix Fietkau 7c8846e10SFelix Fietkau static int 8af005f26SLorenzo Bianconi mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_sw_queue *q, 9c8846e10SFelix Fietkau int idx, int n_desc) 10c8846e10SFelix Fietkau { 11af005f26SLorenzo Bianconi struct mt76_queue *hwq; 12b1bfbe70SLorenzo Bianconi int err; 13c8846e10SFelix Fietkau 14af005f26SLorenzo Bianconi hwq = devm_kzalloc(dev->mt76.dev, sizeof(*hwq), GFP_KERNEL); 15af005f26SLorenzo Bianconi if (!hwq) 16af005f26SLorenzo Bianconi return -ENOMEM; 17af005f26SLorenzo Bianconi 18af005f26SLorenzo Bianconi err = mt76_queue_alloc(dev, hwq, idx, n_desc, 0, MT_TX_RING_BASE); 19b1bfbe70SLorenzo Bianconi if (err < 0) 20b1bfbe70SLorenzo Bianconi return err; 21c8846e10SFelix Fietkau 22af005f26SLorenzo Bianconi INIT_LIST_HEAD(&q->swq); 23af005f26SLorenzo Bianconi q->q = hwq; 24af005f26SLorenzo Bianconi 25c8846e10SFelix Fietkau mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); 26c8846e10SFelix Fietkau 27c8846e10SFelix Fietkau return 0; 28c8846e10SFelix Fietkau } 29c8846e10SFelix Fietkau 30c8846e10SFelix Fietkau static void 31c8846e10SFelix Fietkau mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) 32c8846e10SFelix Fietkau { 33c8846e10SFelix Fietkau __le32 *txd = (__le32 *)skb->data; 34e004b700SFelix Fietkau struct ieee80211_hdr *hdr; 35e004b700SFelix Fietkau struct ieee80211_sta *sta; 36c8846e10SFelix Fietkau struct mt7603_sta *msta; 37c8846e10SFelix Fietkau struct mt76_wcid *wcid; 38e004b700SFelix Fietkau void *priv; 39c8846e10SFelix Fietkau int idx; 40c8846e10SFelix Fietkau u32 val; 41e004b700SFelix Fietkau u8 tid; 42c8846e10SFelix Fietkau 43e004b700SFelix Fietkau if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr)) 44c8846e10SFelix Fietkau goto free; 45c8846e10SFelix Fietkau 46c8846e10SFelix Fietkau val = le32_to_cpu(txd[1]); 47c8846e10SFelix Fietkau idx = FIELD_GET(MT_TXD1_WLAN_IDX, val); 48c8846e10SFelix Fietkau skb->priority = FIELD_GET(MT_TXD1_TID, val); 49c8846e10SFelix Fietkau 50c8846e10SFelix Fietkau if (idx >= MT7603_WTBL_STA - 1) 51c8846e10SFelix Fietkau goto free; 52c8846e10SFelix Fietkau 53c8846e10SFelix Fietkau wcid = rcu_dereference(dev->mt76.wcid[idx]); 54c8846e10SFelix Fietkau if (!wcid) 55c8846e10SFelix Fietkau goto free; 56c8846e10SFelix Fietkau 57e004b700SFelix Fietkau priv = msta = container_of(wcid, struct mt7603_sta, wcid); 58c8846e10SFelix Fietkau val = le32_to_cpu(txd[0]); 59c8846e10SFelix Fietkau skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); 60c8846e10SFelix Fietkau 61fca9615fSFelix Fietkau val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX); 62fca9615fSFelix Fietkau val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT); 63fca9615fSFelix Fietkau txd[0] = cpu_to_le32(val); 64fca9615fSFelix Fietkau 65e004b700SFelix Fietkau sta = container_of(priv, struct ieee80211_sta, drv_priv); 66e004b700SFelix Fietkau hdr = (struct ieee80211_hdr *) &skb->data[MT_TXD_SIZE]; 67e004b700SFelix Fietkau tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; 68e004b700SFelix Fietkau ieee80211_sta_set_buffered(sta, tid, true); 69e004b700SFelix Fietkau 70c8846e10SFelix Fietkau spin_lock_bh(&dev->ps_lock); 71c8846e10SFelix Fietkau __skb_queue_tail(&msta->psq, skb); 72c8846e10SFelix Fietkau if (skb_queue_len(&msta->psq) >= 64) { 73c8846e10SFelix Fietkau skb = __skb_dequeue(&msta->psq); 74c8846e10SFelix Fietkau dev_kfree_skb(skb); 75c8846e10SFelix Fietkau } 76c8846e10SFelix Fietkau spin_unlock_bh(&dev->ps_lock); 77c8846e10SFelix Fietkau return; 78c8846e10SFelix Fietkau 79c8846e10SFelix Fietkau free: 80c8846e10SFelix Fietkau dev_kfree_skb(skb); 81c8846e10SFelix Fietkau } 82c8846e10SFelix Fietkau 83c8846e10SFelix Fietkau void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, 84c8846e10SFelix Fietkau struct sk_buff *skb) 85c8846e10SFelix Fietkau { 86c8846e10SFelix Fietkau struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); 87c8846e10SFelix Fietkau __le32 *rxd = (__le32 *)skb->data; 88c8846e10SFelix Fietkau __le32 *end = (__le32 *)&skb->data[skb->len]; 89c8846e10SFelix Fietkau enum rx_pkt_type type; 90c8846e10SFelix Fietkau 91c8846e10SFelix Fietkau type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); 92c8846e10SFelix Fietkau 93c8846e10SFelix Fietkau if (q == MT_RXQ_MCU) { 94c8846e10SFelix Fietkau if (type == PKT_TYPE_RX_EVENT) 95c8846e10SFelix Fietkau mt76_mcu_rx_event(&dev->mt76, skb); 96c8846e10SFelix Fietkau else 97c8846e10SFelix Fietkau mt7603_rx_loopback_skb(dev, skb); 98c8846e10SFelix Fietkau return; 99c8846e10SFelix Fietkau } 100c8846e10SFelix Fietkau 101c8846e10SFelix Fietkau switch (type) { 102c8846e10SFelix Fietkau case PKT_TYPE_TXS: 103c8846e10SFelix Fietkau for (rxd++; rxd + 5 <= end; rxd += 5) 104c8846e10SFelix Fietkau mt7603_mac_add_txs(dev, rxd); 105c8846e10SFelix Fietkau dev_kfree_skb(skb); 106c8846e10SFelix Fietkau break; 107c8846e10SFelix Fietkau case PKT_TYPE_RX_EVENT: 108c8846e10SFelix Fietkau mt76_mcu_rx_event(&dev->mt76, skb); 109c8846e10SFelix Fietkau return; 110c8846e10SFelix Fietkau case PKT_TYPE_NORMAL: 111c8846e10SFelix Fietkau if (mt7603_mac_fill_rx(dev, skb) == 0) { 112c8846e10SFelix Fietkau mt76_rx(&dev->mt76, q, skb); 113c8846e10SFelix Fietkau return; 114c8846e10SFelix Fietkau } 115c8846e10SFelix Fietkau /* fall through */ 116c8846e10SFelix Fietkau default: 117c8846e10SFelix Fietkau dev_kfree_skb(skb); 118c8846e10SFelix Fietkau break; 119c8846e10SFelix Fietkau } 120c8846e10SFelix Fietkau } 121c8846e10SFelix Fietkau 122c8846e10SFelix Fietkau static int 123c8846e10SFelix Fietkau mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q, 124c8846e10SFelix Fietkau int idx, int n_desc, int bufsize) 125c8846e10SFelix Fietkau { 126b1bfbe70SLorenzo Bianconi int err; 127c8846e10SFelix Fietkau 128b1bfbe70SLorenzo Bianconi err = mt76_queue_alloc(dev, q, idx, n_desc, bufsize, 129b1bfbe70SLorenzo Bianconi MT_RX_RING_BASE); 130b1bfbe70SLorenzo Bianconi if (err < 0) 131b1bfbe70SLorenzo Bianconi return err; 132c8846e10SFelix Fietkau 133c8846e10SFelix Fietkau mt7603_irq_enable(dev, MT_INT_RX_DONE(idx)); 134c8846e10SFelix Fietkau 135c8846e10SFelix Fietkau return 0; 136c8846e10SFelix Fietkau } 137c8846e10SFelix Fietkau 138c8846e10SFelix Fietkau static void 139c8846e10SFelix Fietkau mt7603_tx_tasklet(unsigned long data) 140c8846e10SFelix Fietkau { 141c8846e10SFelix Fietkau struct mt7603_dev *dev = (struct mt7603_dev *)data; 142c8846e10SFelix Fietkau int i; 143c8846e10SFelix Fietkau 144c8846e10SFelix Fietkau dev->tx_dma_check = 0; 145c8846e10SFelix Fietkau for (i = MT_TXQ_MCU; i >= 0; i--) 146c8846e10SFelix Fietkau mt76_queue_tx_cleanup(dev, i, false); 147c8846e10SFelix Fietkau 148c8846e10SFelix Fietkau mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); 149c8846e10SFelix Fietkau } 150c8846e10SFelix Fietkau 151c8846e10SFelix Fietkau int mt7603_dma_init(struct mt7603_dev *dev) 152c8846e10SFelix Fietkau { 153c8846e10SFelix Fietkau static const u8 wmm_queue_map[] = { 154c8846e10SFelix Fietkau [IEEE80211_AC_BK] = 0, 155c8846e10SFelix Fietkau [IEEE80211_AC_BE] = 1, 156c8846e10SFelix Fietkau [IEEE80211_AC_VI] = 2, 157c8846e10SFelix Fietkau [IEEE80211_AC_VO] = 3, 158c8846e10SFelix Fietkau }; 159c8846e10SFelix Fietkau int ret; 160c8846e10SFelix Fietkau int i; 161c8846e10SFelix Fietkau 162c8846e10SFelix Fietkau mt76_dma_attach(&dev->mt76); 163c8846e10SFelix Fietkau 164c8846e10SFelix Fietkau init_waitqueue_head(&dev->mt76.mmio.mcu.wait); 165c8846e10SFelix Fietkau skb_queue_head_init(&dev->mt76.mmio.mcu.res_q); 166c8846e10SFelix Fietkau 167*a33b8ab8SFelix Fietkau tasklet_init(&dev->mt76.tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev); 168c8846e10SFelix Fietkau 169c8846e10SFelix Fietkau mt76_clear(dev, MT_WPDMA_GLO_CFG, 170c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_DMA_EN | 171c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_RX_DMA_EN | 172c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_DMA_BURST_SIZE | 173c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); 174c8846e10SFelix Fietkau 175c8846e10SFelix Fietkau mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); 176c8846e10SFelix Fietkau mt7603_pse_client_reset(dev); 177c8846e10SFelix Fietkau 178c8846e10SFelix Fietkau for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { 179c8846e10SFelix Fietkau ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i], 180c8846e10SFelix Fietkau wmm_queue_map[i], 181c8846e10SFelix Fietkau MT_TX_RING_SIZE); 182c8846e10SFelix Fietkau if (ret) 183c8846e10SFelix Fietkau return ret; 184c8846e10SFelix Fietkau } 185c8846e10SFelix Fietkau 186c8846e10SFelix Fietkau ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], 187c8846e10SFelix Fietkau MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE); 188c8846e10SFelix Fietkau if (ret) 189c8846e10SFelix Fietkau return ret; 190c8846e10SFelix Fietkau 191c8846e10SFelix Fietkau ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], 192c8846e10SFelix Fietkau MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); 193c8846e10SFelix Fietkau if (ret) 194c8846e10SFelix Fietkau return ret; 195c8846e10SFelix Fietkau 196c8846e10SFelix Fietkau ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON], 197c8846e10SFelix Fietkau MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE); 198c8846e10SFelix Fietkau if (ret) 199c8846e10SFelix Fietkau return ret; 200c8846e10SFelix Fietkau 201c8846e10SFelix Fietkau ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB], 202c8846e10SFelix Fietkau MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE); 203c8846e10SFelix Fietkau if (ret) 204c8846e10SFelix Fietkau return ret; 205c8846e10SFelix Fietkau 206c8846e10SFelix Fietkau ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, 207c8846e10SFelix Fietkau MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); 208c8846e10SFelix Fietkau if (ret) 209c8846e10SFelix Fietkau return ret; 210c8846e10SFelix Fietkau 211c8846e10SFelix Fietkau ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, 212c8846e10SFelix Fietkau MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE); 213c8846e10SFelix Fietkau if (ret) 214c8846e10SFelix Fietkau return ret; 215c8846e10SFelix Fietkau 216c8846e10SFelix Fietkau mt76_wr(dev, MT_DELAY_INT_CFG, 0); 217c8846e10SFelix Fietkau return mt76_init_queues(dev); 218c8846e10SFelix Fietkau } 219c8846e10SFelix Fietkau 220c8846e10SFelix Fietkau void mt7603_dma_cleanup(struct mt7603_dev *dev) 221c8846e10SFelix Fietkau { 222c8846e10SFelix Fietkau mt76_clear(dev, MT_WPDMA_GLO_CFG, 223c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_DMA_EN | 224c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_RX_DMA_EN | 225c8846e10SFelix Fietkau MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); 226c8846e10SFelix Fietkau 227*a33b8ab8SFelix Fietkau tasklet_kill(&dev->mt76.tx_tasklet); 228c8846e10SFelix Fietkau mt76_dma_cleanup(&dev->mt76); 229c8846e10SFelix Fietkau } 230