summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLorenzo Bianconi <lorenzo@kernel.org>2020-09-05 11:26:06 +0200
committerFelix Fietkau <nbd@nbd.name>2020-09-24 18:10:19 +0200
commit1522ff731f848cf87d8ac535dc8ce7bc62a17918 (patch)
tree02cb0ace31c8a53de8c48ea315d1ca36cc6d7ec0 /drivers/net
parent598daa4dbe14082b9369f018e46e753b2d79f730 (diff)
mt76: mt7663s: introduce sdio tx aggregation
Introduce sdio tx aggregation to reduce bus transaction ands improve tx throughput. For the moment the skb are copied in a dedicated buffer since mmc APIs do not support sg table for zero-copy. Since skb data are already copied in xmit_buff[], avoid linearization in ma80211 layer. Relying on tx aggregation, we improve tx tpt of ~65%. Tested-by: Sean Wang <sean.wang@mediatek.com> Co-developed-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c5
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h3
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/sdio.c12
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c49
4 files changed, 50 insertions, 19 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 425307c18df1..4befe7f937a9 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -308,10 +308,7 @@ mt76_phy_init(struct mt76_dev *dev, struct ieee80211_hw *hw)
if (!(dev->drv->drv_flags & MT_DRV_AMSDU_OFFLOAD)) {
ieee80211_hw_set(hw, TX_AMSDU);
-
- /* TODO: avoid linearization for SDIO */
- if (!mt76_is_sdio(dev))
- ieee80211_hw_set(hw, TX_FRAG_LIST);
+ ieee80211_hw_set(hw, TX_FRAG_LIST);
}
ieee80211_hw_set(hw, MFP_CAPABLE);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 72aa19e0e6ec..a5be66de1cff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -443,6 +443,7 @@ struct mt76_usb {
} mcu;
};
+#define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE)
struct mt76_sdio {
struct workqueue_struct *txrx_wq;
struct {
@@ -456,6 +457,8 @@ struct mt76_sdio {
struct work_struct stat_work;
+ u8 *xmit_buf[MT_TXQ_MCU_WA];
+
struct sdio_func *func;
void *intr_data;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
index 8621c6f579aa..874c929d8552 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
@@ -346,7 +346,7 @@ static int mt7663s_probe(struct sdio_func *func,
struct ieee80211_ops *ops;
struct mt7615_dev *dev;
struct mt76_dev *mdev;
- int ret;
+ int i, ret;
ops = devm_kmemdup(&func->dev, &mt7615_ops, sizeof(mt7615_ops),
GFP_KERNEL);
@@ -387,6 +387,16 @@ static int mt7663s_probe(struct sdio_func *func,
goto err_deinit;
}
+ for (i = 0; i < ARRAY_SIZE(mdev->sdio.xmit_buf); i++) {
+ mdev->sdio.xmit_buf[i] = devm_kmalloc(mdev->dev,
+ MT76S_XMIT_BUF_SZ,
+ GFP_KERNEL);
+ if (!mdev->sdio.xmit_buf[i]) {
+ ret = -ENOMEM;
+ goto err_deinit;
+ }
+ }
+
ret = mt76s_alloc_queues(&dev->mt76);
if (ret)
goto err_deinit;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index 4033fe431312..e82f6bdcbce4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -138,15 +138,11 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
return i;
}
-static int mt7663s_tx_pick_quota(struct mt76_dev *dev, enum mt76_txq_id qid,
+static int mt7663s_tx_pick_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid,
int buf_sz, int *pse_size, int *ple_size)
{
- struct mt76_sdio *sdio = &dev->sdio;
int pse_sz;
- if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
- return 0;
-
pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
if (qid == MT_TXQ_MCU) {
@@ -197,27 +193,52 @@ static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)
static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
{
- int nframes = 0, pse_sz = 0, ple_sz = 0;
+ int err, nframes = 0, len = 0, pse_sz = 0, ple_sz = 0;
struct mt76_queue *q = dev->q_tx[qid];
struct mt76_sdio *sdio = &dev->sdio;
while (q->first != q->head) {
struct mt76_queue_entry *e = &q->entry[q->first];
- int err;
+ struct sk_buff *iter;
+
+ if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state)) {
+ __skb_put_zero(e->skb, 4);
+ err = __mt7663s_xmit_queue(dev, e->skb->data,
+ e->skb->len);
+ if (err)
+ return err;
+
+ goto next;
+ }
+
+ if (len + e->skb->len + 4 > MT76S_XMIT_BUF_SZ)
+ break;
- if (mt7663s_tx_pick_quota(dev, qid, e->buf_sz, &pse_sz,
+ if (mt7663s_tx_pick_quota(sdio, qid, e->buf_sz, &pse_sz,
&ple_sz))
break;
- __skb_put_zero(e->skb, 4);
+ memcpy(sdio->xmit_buf[qid] + len, e->skb->data,
+ skb_headlen(e->skb));
+ len += skb_headlen(e->skb);
+ nframes++;
- err = __mt7663s_xmit_queue(dev, e->skb->data, e->skb->len);
+ skb_walk_frags(e->skb, iter) {
+ memcpy(sdio->xmit_buf[qid] + len, iter->data,
+ iter->len);
+ len += iter->len;
+ nframes++;
+ }
+next:
+ q->first = (q->first + 1) % q->ndesc;
+ e->done = true;
+ }
+
+ if (nframes) {
+ memset(sdio->xmit_buf[qid] + len, 0, 4);
+ err = __mt7663s_xmit_queue(dev, sdio->xmit_buf[qid], len + 4);
if (err)
return err;
-
- e->done = true;
- q->first = (q->first + 1) % q->ndesc;
- nframes++;
}
mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz);