mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
move txwi cache to core
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -111,6 +111,8 @@ mt76_dma_cleanup(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
|
||||
q->swq_queued--;
|
||||
|
||||
done(dev, q, &entry);
|
||||
if (entry.txwi)
|
||||
mt76_put_txwi(dev, entry.txwi);
|
||||
|
||||
q->tail = (q->tail + 1) % q->ndesc;
|
||||
q->queued--;
|
||||
|
||||
+12
@@ -166,6 +166,9 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
struct wiphy *wiphy = hw->wiphy;
|
||||
int ret;
|
||||
|
||||
spin_lock_init(&dev->lock);
|
||||
INIT_LIST_HEAD(&dev->txwi_cache);
|
||||
|
||||
SET_IEEE80211_DEV(hw, dev->dev);
|
||||
|
||||
wiphy->interface_modes =
|
||||
@@ -203,3 +206,12 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
return ieee80211_register_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_register_device);
|
||||
|
||||
void mt76_unregister_device(struct mt76_dev *dev)
|
||||
{
|
||||
struct ieee80211_hw *hw = dev->hw;
|
||||
|
||||
mt76_tx_free(dev);
|
||||
ieee80211_unregister_hw(hw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_unregister_device);
|
||||
|
||||
@@ -51,7 +51,7 @@ struct mt76_queue_entry {
|
||||
struct sk_buff *skb;
|
||||
union {
|
||||
void *buf;
|
||||
struct mt76x2_txwi_cache *txwi;
|
||||
struct mt76_txwi_cache *txwi;
|
||||
};
|
||||
bool schedule;
|
||||
};
|
||||
@@ -122,6 +122,12 @@ struct mt76_txq {
|
||||
bool aggr;
|
||||
};
|
||||
|
||||
struct mt76_txwi_cache {
|
||||
u32 txwi[6];
|
||||
dma_addr_t dma_addr;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
enum {
|
||||
MT76_STATE_INITIALIZED,
|
||||
MT76_STATE_RUNNING,
|
||||
@@ -134,19 +140,25 @@ struct mt76_hw_cap {
|
||||
};
|
||||
|
||||
struct mt76_driver_ops {
|
||||
int (*fill_txwi)(struct mt76_dev *dev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
int (*tx_queue_skb)(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
struct sk_buff *skb, struct mt76_txwi_cache *txwi,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
|
||||
};
|
||||
|
||||
struct mt76_dev {
|
||||
struct ieee80211_hw *hw;
|
||||
|
||||
spinlock_t lock;
|
||||
const struct mt76_bus_ops *bus;
|
||||
const struct mt76_driver_ops *drv;
|
||||
void __iomem *regs;
|
||||
struct device *dev;
|
||||
|
||||
struct list_head txwi_cache;
|
||||
struct mt76_queue q_tx[__MT_TXQ_MAX];
|
||||
const struct mt76_queue_ops *queue_ops;
|
||||
|
||||
@@ -211,10 +223,9 @@ static inline u16 mt76_rev(struct mt76_dev *dev)
|
||||
#define mt76_queue_rx_fill(dev, ...) (dev)->mt76.queue_ops->rx_fill(&((dev)->mt76), __VA_ARGS__)
|
||||
#define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__)
|
||||
|
||||
#define mt76_tx_queue_skb(dev, ...) (dev)->drv->tx_queue_skb(dev, __VA_ARGS__)
|
||||
|
||||
int mt76_register_device(struct mt76_dev *dev, bool vht,
|
||||
struct ieee80211_rate *rates, int n_rates);
|
||||
void mt76_unregister_device(struct mt76_dev *dev);
|
||||
|
||||
struct dentry *mt76_register_debugfs(struct mt76_dev *dev);
|
||||
|
||||
@@ -236,6 +247,10 @@ mtxq_to_txq(struct mt76_txq *mtxq)
|
||||
return container_of(ptr, struct ieee80211_txq, drv_priv);
|
||||
}
|
||||
|
||||
int mt76_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
void mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb);
|
||||
void mt76_txq_init(struct mt76_dev *dev, struct ieee80211_txq *txq);
|
||||
@@ -249,4 +264,8 @@ void mt76_release_buffered_frames(struct ieee80211_hw *hw,
|
||||
enum ieee80211_frame_release_type reason,
|
||||
bool more_data);
|
||||
|
||||
/* internal */
|
||||
void mt76_tx_free(struct mt76_dev *dev);
|
||||
void mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ mt76pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct mt7603_dev *dev = pci_get_drvdata(pdev);
|
||||
|
||||
ieee80211_unregister_hw(mt76_hw(dev));
|
||||
mt76_unregister_device(&dev->mt76);
|
||||
mt7603_mcu_exit(dev);
|
||||
mt7603_dma_cleanup(dev);
|
||||
ieee80211_free_hw(mt76_hw(dev));
|
||||
|
||||
@@ -104,7 +104,6 @@ struct mt76x2_dev {
|
||||
u8 txdone_seq;
|
||||
DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x2_tx_status);
|
||||
|
||||
struct list_head txwi_cache;
|
||||
struct mt76x2_mcu mcu;
|
||||
struct mt76_queue q_rx;
|
||||
|
||||
@@ -121,7 +120,6 @@ struct mt76x2_dev {
|
||||
|
||||
struct mt76_wcid __rcu *wcid[254 - 8];
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t irq_lock;
|
||||
u32 irqmask;
|
||||
|
||||
@@ -219,9 +217,9 @@ void mt76x2_dma_cleanup(struct mt76x2_dev *dev);
|
||||
void mt76x2_cleanup(struct mt76x2_dev *dev);
|
||||
void mt76x2_rx(struct mt76x2_dev *dev, struct sk_buff *skb);
|
||||
|
||||
int mt76x2_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
int mt76x2_tx_queue_skb(struct mt76_dev *cdev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_txwi_cache *t,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta);
|
||||
int mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum mt76_txq_id qid,
|
||||
struct sk_buff *skb, int cmd, int seq);
|
||||
void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
|
||||
|
||||
+5
-90
@@ -14,68 +14,6 @@
|
||||
#include "mt76x2.h"
|
||||
#include "mt76x2_dma.h"
|
||||
|
||||
struct mt76x2_txwi_cache {
|
||||
u32 txwi[6];
|
||||
dma_addr_t dma_addr;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static struct mt76x2_txwi_cache *
|
||||
mt76x2_alloc_txwi(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct mt76x2_txwi_cache *t;
|
||||
dma_addr_t addr;
|
||||
int size;
|
||||
|
||||
size = (sizeof(*t) + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1);
|
||||
t = devm_kzalloc(dev->mt76.dev, size, GFP_ATOMIC);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
addr = dma_map_single(dev->mt76.dev, &t->txwi, sizeof(t->txwi), DMA_TO_DEVICE);
|
||||
t->dma_addr = addr;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct mt76x2_txwi_cache *
|
||||
__mt76x2_get_txwi(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct mt76x2_txwi_cache *t = NULL;
|
||||
|
||||
spin_lock_bh(&dev->lock);
|
||||
if (!list_empty(&dev->txwi_cache)) {
|
||||
t = list_first_entry(&dev->txwi_cache, struct mt76x2_txwi_cache,
|
||||
list);
|
||||
list_del(&t->list);
|
||||
}
|
||||
spin_unlock_bh(&dev->lock);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct mt76x2_txwi_cache *
|
||||
mt76x2_get_txwi(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct mt76x2_txwi_cache *t = __mt76x2_get_txwi(dev);
|
||||
|
||||
if (t)
|
||||
return t;
|
||||
|
||||
return mt76x2_alloc_txwi(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
mt76x2_put_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi_cache *t)
|
||||
{
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->lock);
|
||||
list_add(&t->list, &dev->txwi_cache);
|
||||
spin_unlock_bh(&dev->lock);
|
||||
}
|
||||
|
||||
int
|
||||
mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum mt76_txq_id qid,
|
||||
struct sk_buff *skb, int cmd, int seq)
|
||||
@@ -106,31 +44,19 @@ mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum mt76_txq_id qid,
|
||||
|
||||
int
|
||||
mt76x2_tx_queue_skb(struct mt76_dev *cdev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
struct sk_buff *skb, struct mt76_txwi_cache *t,
|
||||
struct mt76_wcid *wcid, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76x2_dev *dev = container_of(cdev, struct mt76x2_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct mt76x2_txwi_cache *t;
|
||||
dma_addr_t addr;
|
||||
u32 tx_info = 0;
|
||||
int idx, ret, len;
|
||||
int qsel = MT_QSEL_EDCA;
|
||||
|
||||
ret = -ENOMEM;
|
||||
t = mt76x2_get_txwi(dev);
|
||||
if (!t)
|
||||
goto free;
|
||||
|
||||
dma_sync_single_for_cpu(dev->mt76.dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
mt76x2_mac_write_txwi(dev, &t->txwi, skb, wcid, sta);
|
||||
dma_sync_single_for_device(dev->mt76.dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
ret = mt76_insert_hdr_pad(skb);
|
||||
if (ret)
|
||||
goto put_txwi;
|
||||
return ret;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
|
||||
qsel = 0;
|
||||
@@ -146,7 +72,7 @@ mt76x2_tx_queue_skb(struct mt76_dev *cdev, struct mt76_queue *q,
|
||||
|
||||
addr = dma_map_single(dev->mt76.dev, skb->data, skb->len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev->mt76.dev, addr))
|
||||
goto put_txwi;
|
||||
return -ENOMEM;
|
||||
|
||||
idx = mt76_queue_add_buf(dev, q, t->dma_addr, sizeof(struct mt76x2_txwi),
|
||||
addr, skb->len, tx_info);
|
||||
@@ -154,12 +80,6 @@ mt76x2_tx_queue_skb(struct mt76_dev *cdev, struct mt76_queue *q,
|
||||
q->entry[idx].txwi = t;
|
||||
|
||||
return idx;
|
||||
|
||||
put_txwi:
|
||||
mt76x2_put_txwi(dev, t);
|
||||
free:
|
||||
ieee80211_free_txskb(mt76_hw(dev), skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -170,7 +90,6 @@ mt76x2_tx_cleanup_entry(struct mt76_dev *mdev, struct mt76_queue *q,
|
||||
|
||||
if (e->txwi) {
|
||||
mt76x2_mac_queue_txdone(dev, e->skb, &e->txwi->txwi);
|
||||
mt76x2_put_txwi(dev, e->txwi);
|
||||
} else {
|
||||
dev_kfree_skb_any(e->skb);
|
||||
}
|
||||
@@ -406,7 +325,7 @@ int mt76x2_dma_init(struct mt76x2_dev *dev)
|
||||
|
||||
void mt76x2_dma_cleanup(struct mt76x2_dev *dev)
|
||||
{
|
||||
struct mt76x2_txwi_cache *t;
|
||||
struct mt76_txwi_cache __maybe_unused *t;
|
||||
int i;
|
||||
|
||||
BUILD_BUG_ON(sizeof(t->txwi) < sizeof(struct mt76x2_txwi));
|
||||
@@ -420,8 +339,4 @@ void mt76x2_dma_cleanup(struct mt76x2_dev *dev)
|
||||
mt76_tx_cleanup(dev, &dev->mt76.q_tx[i], true);
|
||||
mt76x2_rx_cleanup(dev, &dev->q_rx);
|
||||
mt76x2_rx_cleanup(dev, &dev->mcu.q_rx);
|
||||
|
||||
while ((t = __mt76x2_get_txwi(dev)) != NULL)
|
||||
dma_unmap_single(dev->mt76.dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
+1
-2
@@ -561,6 +561,7 @@ void mt76x2_cleanup(struct mt76x2_dev *dev)
|
||||
struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev)
|
||||
{
|
||||
static const struct mt76_driver_ops drv_ops = {
|
||||
.fill_txwi = mt76x2_mac_write_txwi,
|
||||
.tx_queue_skb = mt76x2_tx_queue_skb
|
||||
};
|
||||
struct ieee80211_hw *hw;
|
||||
@@ -575,7 +576,6 @@ struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev)
|
||||
dev->mt76.hw = hw;
|
||||
dev->mt76.drv = &drv_ops;
|
||||
mutex_init(&dev->mutex);
|
||||
spin_lock_init(&dev->lock);
|
||||
spin_lock_init(&dev->irq_lock);
|
||||
|
||||
return dev;
|
||||
@@ -681,7 +681,6 @@ int mt76x2_register_device(struct mt76x2_dev *dev)
|
||||
wiphy->iface_combinations = if_comb;
|
||||
wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
|
||||
|
||||
INIT_LIST_HEAD(&dev->txwi_cache);
|
||||
INIT_DELAYED_WORK(&dev->cal_work, mt76x2_phy_calibrate);
|
||||
INIT_DELAYED_WORK(&dev->mac_work, mt76x2_mac_work);
|
||||
|
||||
|
||||
+11
-8
@@ -145,16 +145,17 @@ mt76x2_mac_tx_rate_val(struct mt76x2_dev *dev, const struct ieee80211_tx_rate *r
|
||||
void mt76x2_mac_wcid_set_rate(struct mt76x2_dev *dev, struct mt76_wcid *wcid,
|
||||
const struct ieee80211_tx_rate *rate)
|
||||
{
|
||||
spin_lock_bh(&dev->lock);
|
||||
spin_lock_bh(&dev->mt76.lock);
|
||||
wcid->tx_rate = mt76x2_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
|
||||
wcid->tx_rate_set = true;
|
||||
spin_unlock_bh(&dev->lock);
|
||||
spin_unlock_bh(&dev->mt76.lock);
|
||||
}
|
||||
|
||||
void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
int mt76x2_mac_write_txwi(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||
struct mt76x2_txwi *txwi = txwi_ptr;
|
||||
@@ -171,14 +172,14 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, void *txwi_ptr,
|
||||
|
||||
txwi->pktid = 1;
|
||||
|
||||
spin_lock_bh(&dev->lock);
|
||||
spin_lock_bh(&dev->mt76.lock);
|
||||
if (rate->idx < 0 || !rate->count) {
|
||||
txwi->rate = wcid->tx_rate;
|
||||
nss = wcid->tx_rate_nss;
|
||||
} else {
|
||||
txwi->rate = mt76x2_mac_tx_rate_val(dev, rate, &nss);
|
||||
}
|
||||
spin_unlock_bh(&dev->lock);
|
||||
spin_unlock_bh(&dev->mt76.lock);
|
||||
|
||||
if (mt76xx_rev(dev) >= MT76XX_REV_E4)
|
||||
txwi->txstream = 0x13;
|
||||
@@ -211,6 +212,8 @@ void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, void *txwi_ptr,
|
||||
|
||||
txwi->flags |= cpu_to_le16(txwi_flags);
|
||||
txwi->len_ctl = cpu_to_le16(skb->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, void *rxi)
|
||||
@@ -583,7 +586,7 @@ mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
|
||||
if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x2_txwi)))
|
||||
return -ENOSPC;
|
||||
|
||||
mt76x2_mac_write_txwi(dev, &txwi, skb, NULL, NULL);
|
||||
mt76x2_mac_write_txwi(&dev->mt76, &txwi, skb, NULL, NULL);
|
||||
txwi.flags |= cpu_to_le16(MT_TXWI_FLAGS_TS);
|
||||
|
||||
mt76_wr_copy(dev, offset, &txwi, sizeof(txwi));
|
||||
|
||||
+5
-7
@@ -14,14 +14,12 @@
|
||||
#ifndef __MT76x2_MAC_H
|
||||
#define __MT76x2_MAC_H
|
||||
|
||||
#include "mt76.h"
|
||||
|
||||
struct mt76x2_dev;
|
||||
struct mt76x2_sta;
|
||||
struct mt76x2_vif;
|
||||
struct mt76_wcid;
|
||||
|
||||
struct mt76x2_txwi;
|
||||
struct mt76_queue;
|
||||
struct mt76x2_txwi_cache;
|
||||
|
||||
struct mt76x2_tx_status {
|
||||
u8 valid:1;
|
||||
@@ -161,9 +159,9 @@ void mt76x2_mac_resume(struct mt76x2_dev *dev);
|
||||
void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr);
|
||||
|
||||
int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb, void *rxwi);
|
||||
void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
int mt76x2_mac_write_txwi(struct mt76_dev *dev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta);
|
||||
void mt76x2_mac_wcid_setup(struct mt76x2_dev *dev, u8 idx, u8 vif_idx, u8 *mac);
|
||||
int mt76x2_mac_wcid_set_key(struct mt76x2_dev *dev, u8 idx,
|
||||
struct ieee80211_key_conf *key);
|
||||
|
||||
@@ -13,6 +13,71 @@
|
||||
|
||||
#include "mt76.h"
|
||||
|
||||
static struct mt76_txwi_cache *
|
||||
mt76_alloc_txwi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t;
|
||||
dma_addr_t addr;
|
||||
int size;
|
||||
|
||||
size = (sizeof(*t) + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1);
|
||||
t = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
addr = dma_map_single(dev->dev, &t->txwi, sizeof(t->txwi), DMA_TO_DEVICE);
|
||||
t->dma_addr = addr;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct mt76_txwi_cache *
|
||||
__mt76_get_txwi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t = NULL;
|
||||
|
||||
spin_lock_bh(&dev->lock);
|
||||
if (!list_empty(&dev->txwi_cache)) {
|
||||
t = list_first_entry(&dev->txwi_cache, struct mt76_txwi_cache,
|
||||
list);
|
||||
list_del(&t->list);
|
||||
}
|
||||
spin_unlock_bh(&dev->lock);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static struct mt76_txwi_cache *
|
||||
mt76_get_txwi(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t = __mt76_get_txwi(dev);
|
||||
|
||||
if (t)
|
||||
return t;
|
||||
|
||||
return mt76_alloc_txwi(dev);
|
||||
}
|
||||
|
||||
void
|
||||
mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
|
||||
{
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
spin_lock_bh(&dev->lock);
|
||||
list_add(&t->list, &dev->txwi_cache);
|
||||
spin_unlock_bh(&dev->lock);
|
||||
}
|
||||
|
||||
void mt76_tx_free(struct mt76_dev *dev)
|
||||
{
|
||||
struct mt76_txwi_cache *t;
|
||||
|
||||
while ((t = __mt76_get_txwi(dev)) != NULL)
|
||||
dma_unmap_single(dev->dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static int
|
||||
mt76_txq_get_qid(struct ieee80211_txq *txq)
|
||||
{
|
||||
@@ -22,6 +87,39 @@ mt76_txq_get_qid(struct ieee80211_txq *txq)
|
||||
return txq->ac;
|
||||
}
|
||||
|
||||
int mt76_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mt76_txwi_cache *t;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
t = mt76_get_txwi(dev);
|
||||
if (!t)
|
||||
goto free;
|
||||
|
||||
dma_sync_single_for_cpu(dev->dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
ret = dev->drv->fill_txwi(dev, &t->txwi, skb, wcid, sta);
|
||||
dma_sync_single_for_device(dev->dev, t->dma_addr, sizeof(t->txwi),
|
||||
DMA_TO_DEVICE);
|
||||
if (ret < 0)
|
||||
goto free_txwi;
|
||||
|
||||
ret = dev->drv->tx_queue_skb(dev, q, skb, t, wcid, sta);
|
||||
if (ret < 0)
|
||||
goto free_txwi;
|
||||
|
||||
return ret;
|
||||
|
||||
free_txwi:
|
||||
mt76_put_txwi(dev, t);
|
||||
free:
|
||||
ieee80211_free_txskb(dev->hw, skb);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_tx_queue_skb);
|
||||
|
||||
void
|
||||
mt76_tx(struct mt76_dev *dev, struct ieee80211_sta *sta,
|
||||
struct mt76_wcid *wcid, struct sk_buff *skb)
|
||||
|
||||
Reference in New Issue
Block a user