|
|
|
@@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|