From 1389db799ab14c359f56f85df2ad044fe8677b7b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 17 Dec 2015 15:48:55 +0100 Subject: [PATCH] move txwi cache to core Signed-off-by: Felix Fietkau --- dma.c | 2 ++ mac80211.c | 12 +++++++ mt76.h | 29 ++++++++++++--- mt7603_pci.c | 2 +- mt76x2.h | 8 ++--- mt76x2_dma.c | 95 +++---------------------------------------------- mt76x2_init.c | 3 +- mt76x2_mac.c | 19 +++++----- mt76x2_mac.h | 12 +++---- tx.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 162 insertions(+), 118 deletions(-) diff --git a/dma.c b/dma.c index 6a9c7532..e9ef2858 100644 --- a/dma.c +++ b/dma.c @@ -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--; diff --git a/mac80211.c b/mac80211.c index 971401c6..7fbeaa85 100644 --- a/mac80211.c +++ b/mac80211.c @@ -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); diff --git a/mt76.h b/mt76.h index 81dfbd58..d76762cb 100644 --- a/mt76.h +++ b/mt76.h @@ -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 diff --git a/mt7603_pci.c b/mt7603_pci.c index fe0d819e..ca648907 100644 --- a/mt7603_pci.c +++ b/mt7603_pci.c @@ -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)); diff --git a/mt76x2.h b/mt76x2.h index 477cb8c6..afc29031 100644 --- a/mt76x2.h +++ b/mt76x2.h @@ -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, diff --git a/mt76x2_dma.c b/mt76x2_dma.c index 7924f538..f52d5dee 100644 --- a/mt76x2_dma.c +++ b/mt76x2_dma.c @@ -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); } diff --git a/mt76x2_init.c b/mt76x2_init.c index 7b5e4f3a..dfe46d9d 100644 --- a/mt76x2_init.c +++ b/mt76x2_init.c @@ -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); diff --git a/mt76x2_mac.c b/mt76x2_mac.c index 4cd131b6..b8356879 100644 --- a/mt76x2_mac.c +++ b/mt76x2_mac.c @@ -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)); diff --git a/mt76x2_mac.h b/mt76x2_mac.h index 763fa44d..38bd60a4 100644 --- a/mt76x2_mac.h +++ b/mt76x2_mac.h @@ -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); diff --git a/tx.c b/tx.c index c0f0c619..39432092 100644 --- a/tx.c +++ b/tx.c @@ -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)