mt76: mt7615: implement DMA support for MT7622

MT7622 does not have the CR4 microcontroller sitting in the data path.
Because of that, it uses the chip's native tx descriptor format instead of
something parsed and converted by the firmware.

Co-developed-by: Shayne Chen <shayne.chen@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
This commit is contained in:
Felix Fietkau
2019-12-18 17:46:27 +01:00
parent 35da599fcd
commit 6aa4ed7927
4 changed files with 204 additions and 64 deletions

View File

@@ -346,7 +346,10 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN);
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
if (is_mt7615(&phy->dev->mt76))
hw->max_tx_fragments = MT_TXP_MAX_BUF_NUM;
else
hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
}
static void

View File

@@ -396,13 +396,20 @@ void mt7615_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
if (e->skb == DMA_DUMMY_DATA) {
struct mt76_txwi_cache *t;
struct mt7615_dev *dev;
struct mt7615_txp *txp;
struct mt7615_txp_common *txp;
u16 token;
dev = container_of(mdev, struct mt7615_dev, mt76);
txp = mt7615_txwi_to_txp(mdev, e->txwi);
if (is_mt7615(&dev->mt76))
token = le16_to_cpu(txp->fw.token);
else
token = le16_to_cpu(txp->hw.msdu_id[0]) &
~MT_MSDU_ID_VALID;
spin_lock_bh(&dev->token_lock);
t = idr_remove(&dev->token, le16_to_cpu(txp->token));
t = idr_remove(&dev->token, token);
spin_unlock_bh(&dev->token_lock);
e->skb = t ? t->skb : NULL;
}
@@ -621,18 +628,56 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
return 0;
}
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *t)
static void
mt7615_txp_skb_unmap_fw(struct mt76_dev *dev, struct mt7615_fw_txp *txp)
{
struct mt7615_txp *txp;
int i;
txp = mt7615_txwi_to_txp(dev, t);
for (i = 1; i < txp->nbuf; i++)
dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
}
static void
mt7615_txp_skb_unmap_hw(struct mt76_dev *dev, struct mt7615_hw_txp *txp)
{
int i;
for (i = 0; i < ARRAY_SIZE(txp->ptr); i++) {
struct mt7615_txp_ptr *ptr = &txp->ptr[i];
bool last;
u16 len;
len = le16_to_cpu(ptr->len0);
last = len & MT_TXD_LEN_MSDU_LAST;
len &= ~MT_TXD_LEN_MSDU_LAST;
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf0), len,
DMA_TO_DEVICE);
if (last)
break;
len = le16_to_cpu(ptr->len1);
last = len & MT_TXD_LEN_MSDU_LAST;
len &= ~MT_TXD_LEN_MSDU_LAST;
dma_unmap_single(dev->dev, le32_to_cpu(ptr->buf1), len,
DMA_TO_DEVICE);
if (last)
break;
}
}
void mt7615_txp_skb_unmap(struct mt76_dev *dev,
struct mt76_txwi_cache *t)
{
struct mt7615_txp_common *txp;
txp = mt7615_txwi_to_txp(dev, t);
if (is_mt7615(dev))
mt7615_txp_skb_unmap_fw(dev, &txp->fw);
else
mt7615_txp_skb_unmap_hw(dev, &txp->hw);
}
static u32 mt7615_mac_wtbl_addr(int wcid)
{
return MT_WTBL_BASE + wcid * MT_WTBL_ENTRY_SIZE;
@@ -1022,21 +1067,93 @@ out:
return err;
}
static void
mt7615_write_hw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct mt7615_hw_txp *txp = txp_ptr;
struct mt7615_txp_ptr *ptr = &txp->ptr[0];
int nbuf = tx_info->nbuf - 1;
int i;
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
tx_info->nbuf = 1;
txp->msdu_id[0] = cpu_to_le16(id | MT_MSDU_ID_VALID);
for (i = 0; i < nbuf; i++) {
u32 addr = tx_info->buf[i + 1].addr;
u16 len = tx_info->buf[i + 1].len;
if (i == nbuf - 1)
len |= MT_TXD_LEN_MSDU_LAST |
MT_TXD_LEN_AMSDU_LAST;
if (i & 1) {
ptr->buf1 = cpu_to_le32(addr);
ptr->len1 = cpu_to_le16(len);
ptr++;
} else {
ptr->buf0 = cpu_to_le32(addr);
ptr->len0 = cpu_to_le16(len);
}
}
}
static void
mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,
void *txp_ptr, u32 id)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
struct mt7615_fw_txp *txp = txp_ptr;
int nbuf = tx_info->nbuf - 1;
int i;
for (i = 0; i < nbuf; i++) {
txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
}
txp->nbuf = nbuf;
/* pass partial skb header to fw */
tx_info->buf[0].len = MT_TXD_SIZE + sizeof(*txp);
tx_info->buf[1].len = MT_CT_PARSE_LEN;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);
if (!key)
txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
if (ieee80211_is_mgmt(hdr->frame_control))
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
if (vif) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
txp->bss_idx = mvif->idx;
}
txp->token = cpu_to_le16(id);
txp->rept_wds_wcid = 0xff;
}
int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
enum mt76_txq_id qid, struct mt76_wcid *wcid,
struct ieee80211_sta *sta,
struct mt76_tx_info *tx_info)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx_info->skb->data;
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct ieee80211_vif *vif = info->control.vif;
int i, pid, id, nbuf = tx_info->nbuf - 1;
int pid, id;
u8 *txwi = (u8 *)txwi_ptr;
struct mt76_txwi_cache *t;
struct mt7615_txp *txp;
void *txp;
if (!wcid)
wcid = &dev->mt76.global_wcid;
@@ -1056,34 +1173,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
spin_unlock_bh(&dev->mt76.lock);
}
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
pid, key);
txp = (struct mt7615_txp *)(txwi + MT_TXD_SIZE);
for (i = 0; i < nbuf; i++) {
txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
}
txp->nbuf = nbuf;
/* pass partial skb header to fw */
tx_info->buf[1].len = MT_CT_PARSE_LEN;
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
txp->flags = cpu_to_le16(MT_CT_INFO_APPLY_TXD);
if (!key)
txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
if (ieee80211_is_mgmt(hdr->frame_control))
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
if (vif) {
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
txp->bss_idx = mvif->idx;
}
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
@@ -1093,8 +1182,16 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (id < 0)
return id;
txp->token = cpu_to_le16(id);
txp->rept_wds_wcid = 0xff;
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
pid, key);
txp = txwi + MT_TXD_SIZE;
memset(txp, 0, sizeof(struct mt7615_txp_common));
if (is_mt7615(&dev->mt76))
mt7615_write_fw_txp(dev, tx_info, txp, id);
else
mt7615_write_hw_txp(dev, tx_info, txp, id);
tx_info->skb = DMA_DUMMY_DATA;
return 0;
@@ -1330,34 +1427,48 @@ out:
rcu_read_unlock();
}
static void
mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)
{
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
trace_mac_tx_free(dev, token);
spin_lock_bh(&dev->token_lock);
txwi = idr_remove(&dev->token, token);
spin_unlock_bh(&dev->token_lock);
if (!txwi)
return;
mt7615_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
mt76_tx_complete_skb(mdev, txwi->skb);
txwi->skb = NULL;
}
mt76_put_txwi(mdev, txwi);
}
void mt7615_mac_tx_free(struct mt7615_dev *dev, struct sk_buff *skb)
{
struct mt7615_tx_free *free = (struct mt7615_tx_free *)skb->data;
struct mt76_dev *mdev = &dev->mt76;
struct mt76_txwi_cache *txwi;
u8 i, count;
count = FIELD_GET(MT_TX_FREE_MSDU_ID_CNT, le16_to_cpu(free->ctrl));
for (i = 0; i < count; i++) {
u16 token = le16_to_cpu(free->token[i]);
if (is_mt7615(&dev->mt76)) {
__le16 *token = &free->token[0];
spin_lock_bh(&dev->token_lock);
txwi = idr_remove(&dev->token, token);
spin_unlock_bh(&dev->token_lock);
for (i = 0; i < count; i++)
mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i]));
} else {
__le32 *token = (__le32 *)&free->token[0];
if (!txwi)
continue;
trace_mac_tx_free(dev, token);
mt7615_txp_skb_unmap(mdev, txwi);
if (txwi->skb) {
mt76_tx_complete_skb(mdev, txwi->skb);
txwi->skb = NULL;
}
mt76_put_txwi(mdev, txwi);
for (i = 0; i < count; i++)
mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i]));
}
dev_kfree_skb(skb);
}

View File

@@ -233,8 +233,27 @@ enum tx_phy_bandwidth {
#define MT_TX_RATE_IDX GENMASK(5, 0)
#define MT_TXP_MAX_BUF_NUM 6
#define MT_HW_TXP_MAX_MSDU_NUM 4
#define MT_HW_TXP_MAX_BUF_NUM 4
struct mt7615_txp {
#define MT_MSDU_ID_VALID BIT(15)
#define MT_TXD_LEN_MSDU_LAST BIT(14)
#define MT_TXD_LEN_AMSDU_LAST BIT(15)
struct mt7615_txp_ptr {
__le32 buf0;
__le16 len0;
__le16 len1;
__le32 buf1;
} __packed __aligned(4);
struct mt7615_hw_txp {
__le16 msdu_id[MT_HW_TXP_MAX_MSDU_NUM];
struct mt7615_txp_ptr ptr[MT_HW_TXP_MAX_BUF_NUM / 2];
} __packed __aligned(4);
struct mt7615_fw_txp {
__le16 flags;
__le16 token;
u8 bss_idx;
@@ -245,6 +264,13 @@ struct mt7615_txp {
__le16 len[MT_TXP_MAX_BUF_NUM];
} __packed __aligned(4);
struct mt7615_txp_common {
union {
struct mt7615_fw_txp fw;
struct mt7615_hw_txp hw;
};
};
struct mt7615_tx_free {
__le16 rx_byte_cnt;
__le16 ctrl;
@@ -353,7 +379,7 @@ enum mt7615_cipher_type {
MT_CIPHER_GCMP_256,
};
static inline struct mt7615_txp *
static inline struct mt7615_txp_common *
mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
{
u8 *txwi;
@@ -363,7 +389,7 @@ mt7615_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
txwi = mt76_get_txwi_ptr(dev, t);
return (struct mt7615_txp *)(txwi + MT_TXD_SIZE);
return (struct mt7615_txp_common *)(txwi + MT_TXD_SIZE);
}
#endif

View File

@@ -60,7 +60,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq)
{
static const struct mt76_driver_ops drv_ops = {
/* txwi_size = txd size + txp size */
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp),
.txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common),
.drv_flags = MT_DRV_TXWI_NO_FREE,
.survey_flags = SURVEY_INFO_TIME_TX |
SURVEY_INFO_TIME_RX |