developer | 0f312e8 | 2022-11-01 12:31:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: ISC |
| 2 | /* Copyright (C) 2021 MediaTek Inc. */ |
| 3 | |
| 4 | #include "mt7921.h" |
| 5 | #include "../dma.h" |
| 6 | #include "mac.h" |
| 7 | |
| 8 | int mt7921e_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, |
| 9 | enum mt76_txq_id qid, struct mt76_wcid *wcid, |
| 10 | struct ieee80211_sta *sta, |
| 11 | struct mt76_tx_info *tx_info) |
| 12 | { |
| 13 | struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); |
| 14 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); |
| 15 | struct ieee80211_key_conf *key = info->control.hw_key; |
| 16 | struct mt76_connac_hw_txp *txp; |
| 17 | struct mt76_txwi_cache *t; |
| 18 | int id, pid; |
| 19 | u8 *txwi = (u8 *)txwi_ptr; |
| 20 | |
| 21 | if (unlikely(tx_info->skb->len <= ETH_HLEN)) |
| 22 | return -EINVAL; |
| 23 | |
| 24 | if (!wcid) |
| 25 | wcid = &dev->mt76.global_wcid; |
| 26 | |
| 27 | t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); |
| 28 | t->skb = tx_info->skb; |
| 29 | |
| 30 | id = mt76_token_consume(mdev, &t); |
| 31 | if (id < 0) |
| 32 | return id; |
| 33 | |
| 34 | if (sta) { |
| 35 | struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; |
| 36 | |
| 37 | if (time_after(jiffies, msta->last_txs + HZ / 4)) { |
| 38 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; |
| 39 | msta->last_txs = jiffies; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); |
| 44 | mt76_connac2_mac_write_txwi(mdev, txwi_ptr, tx_info->skb, wcid, key, |
| 45 | pid, qid, 0); |
| 46 | |
| 47 | txp = (struct mt76_connac_hw_txp *)(txwi + MT_TXD_SIZE); |
| 48 | memset(txp, 0, sizeof(struct mt76_connac_hw_txp)); |
| 49 | mt76_connac_write_hw_txp(mdev, tx_info, txp, id); |
| 50 | |
| 51 | tx_info->skb = DMA_DUMMY_DATA; |
| 52 | |
| 53 | return 0; |
| 54 | } |
| 55 | |
| 56 | void mt7921_tx_token_put(struct mt7921_dev *dev) |
| 57 | { |
| 58 | struct mt76_txwi_cache *txwi; |
| 59 | int id; |
| 60 | |
| 61 | spin_lock_bh(&dev->mt76.token_lock); |
| 62 | idr_for_each_entry(&dev->mt76.token, txwi, id) { |
| 63 | mt7921_txwi_free(dev, txwi, NULL, false, NULL); |
| 64 | dev->mt76.token_count--; |
| 65 | } |
| 66 | spin_unlock_bh(&dev->mt76.token_lock); |
| 67 | idr_destroy(&dev->mt76.token); |
| 68 | } |
| 69 | |
| 70 | int mt7921e_mac_reset(struct mt7921_dev *dev) |
| 71 | { |
| 72 | int i, err; |
| 73 | |
| 74 | mt7921e_mcu_drv_pmctrl(dev); |
| 75 | |
| 76 | mt76_connac_free_pending_tx_skbs(&dev->pm, NULL); |
| 77 | |
| 78 | mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0); |
| 79 | mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0); |
| 80 | |
| 81 | set_bit(MT76_RESET, &dev->mphy.state); |
| 82 | set_bit(MT76_MCU_RESET, &dev->mphy.state); |
| 83 | wake_up(&dev->mt76.mcu.wait); |
| 84 | skb_queue_purge(&dev->mt76.mcu.res_q); |
| 85 | |
| 86 | mt76_txq_schedule_all(&dev->mphy); |
| 87 | |
| 88 | mt76_worker_disable(&dev->mt76.tx_worker); |
| 89 | napi_disable(&dev->mt76.napi[MT_RXQ_MAIN]); |
| 90 | napi_disable(&dev->mt76.napi[MT_RXQ_MCU]); |
| 91 | napi_disable(&dev->mt76.napi[MT_RXQ_MCU_WA]); |
| 92 | napi_disable(&dev->mt76.tx_napi); |
| 93 | |
| 94 | mt7921_tx_token_put(dev); |
| 95 | idr_init(&dev->mt76.token); |
| 96 | |
| 97 | mt7921_wpdma_reset(dev, true); |
| 98 | |
| 99 | local_bh_disable(); |
| 100 | mt76_for_each_q_rx(&dev->mt76, i) { |
| 101 | napi_enable(&dev->mt76.napi[i]); |
| 102 | napi_schedule(&dev->mt76.napi[i]); |
| 103 | } |
| 104 | local_bh_enable(); |
| 105 | |
| 106 | dev->fw_assert = false; |
| 107 | clear_bit(MT76_MCU_RESET, &dev->mphy.state); |
| 108 | |
| 109 | mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, |
| 110 | MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | |
| 111 | MT_INT_MCU_CMD); |
| 112 | mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); |
| 113 | |
| 114 | err = mt7921e_driver_own(dev); |
| 115 | if (err) |
| 116 | return err; |
| 117 | |
| 118 | err = mt7921_run_firmware(dev); |
| 119 | if (err) |
| 120 | goto out; |
| 121 | |
| 122 | err = mt7921_mcu_set_eeprom(dev); |
| 123 | if (err) |
| 124 | goto out; |
| 125 | |
| 126 | err = mt7921_mac_init(dev); |
| 127 | if (err) |
| 128 | goto out; |
| 129 | |
| 130 | err = __mt7921_start(&dev->phy); |
| 131 | out: |
| 132 | clear_bit(MT76_RESET, &dev->mphy.state); |
| 133 | |
| 134 | local_bh_disable(); |
| 135 | napi_enable(&dev->mt76.tx_napi); |
| 136 | napi_schedule(&dev->mt76.tx_napi); |
| 137 | local_bh_enable(); |
| 138 | |
| 139 | mt76_worker_enable(&dev->mt76.tx_worker); |
| 140 | |
| 141 | return err; |
| 142 | } |