* [PATCH 0/7] add tx aggregation for mt7663s
@ 2020-09-05 9:26 Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic Lorenzo Bianconi
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
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.
Fixed a quota leak in mt7663s_refill_sched_quota.
Do not update quota in case of tx errors.
Lorenzo Bianconi (7):
mt76: mt7663s: do not use altx for ctl/mgmt taffic
mt76: mt7663s: split mt7663s_tx_update_sched in
mt7663s_tx_{pick,update}_quota
mt76: mt7663s: introduce __mt7663s_xmit_queue routine
mt76: move pad estimation out of mt76_skb_adjust_pad
mt76: mt7663s: fix possible quota leak in mt7663s_refill_sched_quota
mt76: mt7663s: introduce sdio tx aggregation
mt76: mt7663: check isr read return value in mt7663s_rx_work
drivers/net/wireless/mediatek/mt76/mac80211.c | 5 +-
drivers/net/wireless/mediatek/mt76/mt76.h | 5 +-
.../net/wireless/mediatek/mt76/mt7615/sdio.c | 14 +-
.../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 174 ++++++++++++------
.../wireless/mediatek/mt76/mt7615/usb_mcu.c | 6 +-
.../wireless/mediatek/mt76/mt7615/usb_sdio.c | 6 +-
.../wireless/mediatek/mt76/mt76x02_usb_core.c | 5 +-
drivers/net/wireless/mediatek/mt76/sdio.c | 5 +-
drivers/net/wireless/mediatek/mt76/tx.c | 6 +-
9 files changed, 145 insertions(+), 81 deletions(-)
--
2.26.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 11:32 ` Felix Fietkau
2020-09-05 9:26 ` [PATCH 2/7] mt76: mt7663s: split mt7663s_tx_update_sched in mt7663s_tx_{pick,update}_quota Lorenzo Bianconi
` (5 subsequent siblings)
6 siblings, 1 reply; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
Since the sdio engine does not report quota for altx queue, move
ctl/mgmt traffic to standard data queues
Tested-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7615/sdio.c | 2 +-
.../net/wireless/mediatek/mt76/mt7615/sdio_txrx.c | 12 +++---------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
index e0603e82e33d..8621c6f579aa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio.c
@@ -323,7 +323,7 @@ static int mt7663s_probe(struct sdio_func *func,
{
static const struct mt76_driver_ops drv_ops = {
.txwi_size = MT_USB_TXD_SIZE,
- .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,
+ .drv_flags = MT_DRV_RX_DMA_HDR,
.tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,
.tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,
.tx_status_data = mt7663_usb_sdio_tx_status_data,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index 3557df52846f..b2b528cba7f1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -124,16 +124,14 @@ static int mt7663s_tx_update_sched(struct mt76_dev *dev,
bool mcu)
{
struct mt76_sdio *sdio = &dev->sdio;
- struct mt76_phy *mphy = &dev->phy;
- struct ieee80211_hdr *hdr;
int size, ret = -EBUSY;
+ if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
+ return 0;
+
size = DIV_ROUND_UP(e->buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
if (mcu) {
- if (!test_bit(MT76_STATE_MCU_RUNNING, &mphy->state))
- return 0;
-
mutex_lock(&sdio->sched.lock);
if (sdio->sched.pse_mcu_quota > size) {
sdio->sched.pse_mcu_quota -= size;
@@ -144,10 +142,6 @@ static int mt7663s_tx_update_sched(struct mt76_dev *dev,
return ret;
}
- hdr = (struct ieee80211_hdr *)(e->skb->data + MT_USB_TXD_SIZE);
- if (ieee80211_is_ctl(hdr->frame_control))
- return 0;
-
mutex_lock(&sdio->sched.lock);
if (sdio->sched.pse_data_quota > size &&
sdio->sched.ple_data_quota > 0) {
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/7] mt76: mt7663s: split mt7663s_tx_update_sched in mt7663s_tx_{pick,update}_quota
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 3/7] mt76: mt7663s: introduce __mt7663s_xmit_queue routine Lorenzo Bianconi
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
In order to not update the available quota in case of a tx error, split
mt7663s_tx_update_sched in mt7663s_tx_{pick,update}_quota routines
Tested-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 56 ++++++++++---------
1 file changed, 31 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index b2b528cba7f1..ced7820021c2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -119,52 +119,57 @@ static int mt7663s_rx_run_queue(struct mt76_dev *dev, enum mt76_rxq_id qid,
return i;
}
-static int mt7663s_tx_update_sched(struct mt76_dev *dev,
- struct mt76_queue_entry *e,
- bool mcu)
+static int mt7663s_tx_pick_quota(struct mt76_dev *dev, enum mt76_txq_id qid,
+ int buf_sz, int *pse_size, int *ple_size)
{
struct mt76_sdio *sdio = &dev->sdio;
- int size, ret = -EBUSY;
+ int pse_sz;
if (!test_bit(MT76_STATE_MCU_RUNNING, &dev->phy.state))
return 0;
- size = DIV_ROUND_UP(e->buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
+ pse_sz = DIV_ROUND_UP(buf_sz + sdio->sched.deficit, MT_PSE_PAGE_SZ);
- if (mcu) {
- mutex_lock(&sdio->sched.lock);
- if (sdio->sched.pse_mcu_quota > size) {
- sdio->sched.pse_mcu_quota -= size;
- ret = 0;
- }
- mutex_unlock(&sdio->sched.lock);
+ if (qid == MT_TXQ_MCU) {
+ if (sdio->sched.pse_mcu_quota < *pse_size + pse_sz)
+ return -EBUSY;
+ } else {
+ if (sdio->sched.pse_data_quota < *pse_size + pse_sz ||
+ sdio->sched.ple_data_quota < *ple_size)
+ return -EBUSY;
- return ret;
+ *ple_size = *ple_size + 1;
}
+ *pse_size = *pse_size + pse_sz;
+
+ return 0;
+}
+static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid,
+ int pse_size, int ple_size)
+{
mutex_lock(&sdio->sched.lock);
- if (sdio->sched.pse_data_quota > size &&
- sdio->sched.ple_data_quota > 0) {
- sdio->sched.pse_data_quota -= size;
- sdio->sched.ple_data_quota--;
- ret = 0;
+ if (qid == MT_TXQ_MCU) {
+ sdio->sched.pse_mcu_quota -= pse_size;
+ } else {
+ sdio->sched.pse_data_quota -= pse_size;
+ sdio->sched.ple_data_quota -= ple_size;
}
mutex_unlock(&sdio->sched.lock);
-
- return ret;
}
-static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
+static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
{
- bool mcu = q == dev->q_tx[MT_TXQ_MCU];
+ int nframes = 0, pse_sz = 0, ple_sz = 0;
+ struct mt76_queue *q = dev->q_tx[qid];
struct mt76_sdio *sdio = &dev->sdio;
- int nframes = 0;
while (q->first != q->head) {
struct mt76_queue_entry *e = &q->entry[q->first];
int err, len = e->skb->len;
- if (mt7663s_tx_update_sched(dev, e, mcu))
+ if (mt7663s_tx_pick_quota(dev, qid, e->buf_sz, &pse_sz,
+ &ple_sz))
break;
if (len > sdio->func->cur_blksize)
@@ -184,6 +189,7 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, struct mt76_queue *q)
q->first = (q->first + 1) % q->ndesc;
nframes++;
}
+ mt7663s_tx_update_quota(sdio, qid, pse_sz, ple_sz);
return nframes;
}
@@ -198,7 +204,7 @@ void mt7663s_tx_work(struct work_struct *work)
for (i = 0; i < MT_TXQ_MCU_WA; i++) {
int ret;
- ret = mt7663s_tx_run_queue(dev, dev->q_tx[i]);
+ ret = mt7663s_tx_run_queue(dev, i);
if (ret < 0)
break;
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/7] mt76: mt7663s: introduce __mt7663s_xmit_queue routine
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 2/7] mt76: mt7663s: split mt7663s_tx_update_sched in mt7663s_tx_{pick,update}_quota Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 4/7] mt76: move pad estimation out of mt76_skb_adjust_pad Lorenzo Bianconi
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
This is a preliminary patch to introduce sdio tx aggregation
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>
---
.../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 35 ++++++++++++-------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index ced7820021c2..ebae2a24c45b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -158,6 +158,24 @@ static void mt7663s_tx_update_quota(struct mt76_sdio *sdio, enum mt76_txq_id qid
mutex_unlock(&sdio->sched.lock);
}
+static int __mt7663s_xmit_queue(struct mt76_dev *dev, u8 *data, int len)
+{
+ struct mt76_sdio *sdio = &dev->sdio;
+ int err;
+
+ if (len > sdio->func->cur_blksize)
+ len = roundup(len, sdio->func->cur_blksize);
+
+ sdio_claim_host(sdio->func);
+ err = sdio_writesb(sdio->func, MCR_WTDR1, data, len);
+ sdio_release_host(sdio->func);
+
+ if (err)
+ dev_err(dev->dev, "sdio write failed: %d\n", err);
+
+ return err;
+}
+
static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
{
int nframes = 0, pse_sz = 0, ple_sz = 0;
@@ -166,24 +184,15 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
while (q->first != q->head) {
struct mt76_queue_entry *e = &q->entry[q->first];
- int err, len = e->skb->len;
+ int err;
if (mt7663s_tx_pick_quota(dev, qid, e->buf_sz, &pse_sz,
&ple_sz))
break;
- if (len > sdio->func->cur_blksize)
- len = roundup(len, sdio->func->cur_blksize);
-
- /* TODO: skb_walk_frags and then write to SDIO port */
- sdio_claim_host(sdio->func);
- err = sdio_writesb(sdio->func, MCR_WTDR1, e->skb->data, len);
- sdio_release_host(sdio->func);
-
- if (err) {
- dev_err(dev->dev, "sdio write failed: %d\n", err);
- return -EIO;
- }
+ err = __mt7663s_xmit_queue(dev, e->skb->data, e->skb->len);
+ if (err)
+ return err;
e->done = true;
q->first = (q->first + 1) % q->ndesc;
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/7] mt76: move pad estimation out of mt76_skb_adjust_pad
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
` (2 preceding siblings ...)
2020-09-05 9:26 ` [PATCH 3/7] mt76: mt7663s: introduce __mt7663s_xmit_queue routine Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 5/7] mt76: mt7663s: fix possible quota leak in mt7663s_refill_sched_quota Lorenzo Bianconi
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
Move frame pad computation out of mt76_skb_adjust_pad routine.
This is a preliminary patch to introduce sdio tx aggregation.
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>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c | 2 ++
drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c | 6 +++---
drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c | 6 +++++-
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 5 +++--
drivers/net/wireless/mediatek/mt76/sdio.c | 5 +++--
drivers/net/wireless/mediatek/mt76/tx.c | 6 +-----
7 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 59eed5374b38..209d23846d4c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1048,7 +1048,7 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
-int mt76_skb_adjust_pad(struct sk_buff *skb);
+int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
int mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
void *buf, size_t len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index ebae2a24c45b..4754b3abd0a2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -190,6 +190,8 @@ static int mt7663s_tx_run_queue(struct mt76_dev *dev, enum mt76_txq_id qid)
&ple_sz))
break;
+ __skb_put_zero(e->skb, 4);
+
err = __mt7663s_xmit_queue(dev, e->skb->data, e->skb->len);
if (err)
return err;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c
index adbed373798e..4d8be366af31 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c
@@ -18,8 +18,7 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
int cmd, bool wait_resp)
{
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
- int ret, seq, ep;
- u32 len;
+ int ret, seq, ep, len, pad;
mutex_lock(&mdev->mcu.mutex);
@@ -31,7 +30,8 @@ mt7663u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
len = skb->len;
put_unaligned_le32(len, skb_push(skb, sizeof(len)));
- ret = mt76_skb_adjust_pad(skb);
+ pad = round_up(skb->len, 4) + 4 - skb->len;
+ ret = mt76_skb_adjust_pad(skb, pad);
if (ret < 0)
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
index 56d82bd3a615..c24f26499537 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
@@ -247,6 +247,7 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct sk_buff *skb = tx_info->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ int pad;
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
!msta->rate_probe) {
@@ -262,9 +263,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
u32 len = skb->len;
put_unaligned_le32(len, skb_push(skb, sizeof(len)));
+ pad = round_up(skb->len, 4) + 4 - skb->len;
+ } else {
+ pad = round_up(skb->len, 4) - skb->len;
}
- return mt76_skb_adjust_pad(skb);
+ return mt76_skb_adjust_pad(skb, pad);
}
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 5d0a2857f193..2c2f56112b57 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -45,7 +45,7 @@ EXPORT_SYMBOL_GPL(mt76x02u_mac_start);
int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
{
- u32 info;
+ u32 info, pad;
/* Buffer layout:
* | 4B | xfer len | pad | 4B |
@@ -57,7 +57,8 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags)
FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags;
put_unaligned_le32(info, skb_push(skb, sizeof(info)));
- return mt76_skb_adjust_pad(skb);
+ pad = round_up(skb->len, 4) + 4 - skb->len;
+ return mt76_skb_adjust_pad(skb, pad);
}
int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c
index 7777d4944081..9a4d95a2a707 100644
--- a/drivers/net/wireless/mediatek/mt76/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/sdio.c
@@ -226,12 +226,13 @@ mt76s_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid,
struct sk_buff *skb, u32 tx_info)
{
struct mt76_queue *q = dev->q_tx[qid];
- int ret = -ENOSPC, len = skb->len;
+ int ret = -ENOSPC, len = skb->len, pad;
if (q->queued == q->ndesc)
goto error;
- ret = mt76_skb_adjust_pad(skb);
+ pad = round_up(skb->len, 4) - skb->len;
+ ret = mt76_skb_adjust_pad(skb, pad);
if (ret)
goto error;
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index b6e52a324e28..ce15efcf7e3a 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -694,13 +694,9 @@ u8 mt76_ac_to_hwq(u8 ac)
}
EXPORT_SYMBOL_GPL(mt76_ac_to_hwq);
-int mt76_skb_adjust_pad(struct sk_buff *skb)
+int mt76_skb_adjust_pad(struct sk_buff *skb, int pad)
{
struct sk_buff *iter, *last = skb;
- u32 pad;
-
- /* Add zero pad of 4 - 7 bytes */
- pad = round_up(skb->len, 4) + 4 - skb->len;
/* First packet of a A-MSDU burst keeps track of the whole burst
* length, need to update length of it and the last packet.
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/7] mt76: mt7663s: fix possible quota leak in mt7663s_refill_sched_quota
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
` (3 preceding siblings ...)
2020-09-05 9:26 ` [PATCH 4/7] mt76: move pad estimation out of mt76_skb_adjust_pad Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 6/7] mt76: mt7663s: introduce sdio tx aggregation Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 7/7] mt76: mt7663: check isr read return value in mt7663s_rx_work Lorenzo Bianconi
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
Look just at reported quota since the hw sporadically reports mcu tx
quota without setting WHIER_TX_DONE_INT_EN bit
Tested-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 43 +++++++++++++------
1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index 4754b3abd0a2..4033fe431312 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -19,21 +19,40 @@
#include "sdio.h"
#include "mac.h"
-static void mt7663s_refill_sched_quota(struct mt76_dev *dev, u32 *data)
+static int mt7663s_refill_sched_quota(struct mt76_dev *dev, u32 *data)
{
+ u32 ple_ac_data_quota[] = {
+ FIELD_GET(TXQ_CNT_L, data[4]), /* VO */
+ FIELD_GET(TXQ_CNT_H, data[3]), /* VI */
+ FIELD_GET(TXQ_CNT_L, data[3]), /* BE */
+ FIELD_GET(TXQ_CNT_H, data[2]), /* BK */
+ };
+ u32 pse_ac_data_quota[] = {
+ FIELD_GET(TXQ_CNT_H, data[1]), /* VO */
+ FIELD_GET(TXQ_CNT_L, data[1]), /* VI */
+ FIELD_GET(TXQ_CNT_H, data[0]), /* BE */
+ FIELD_GET(TXQ_CNT_L, data[0]), /* BK */
+ };
+ u32 pse_mcu_quota = FIELD_GET(TXQ_CNT_L, data[2]);
+ u32 pse_data_quota = 0, ple_data_quota = 0;
struct mt76_sdio *sdio = &dev->sdio;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pse_ac_data_quota); i++) {
+ pse_data_quota += pse_ac_data_quota[i];
+ ple_data_quota += ple_ac_data_quota[i];
+ }
+
+ if (!pse_data_quota && !ple_data_quota && !pse_mcu_quota)
+ return 0;
mutex_lock(&sdio->sched.lock);
- sdio->sched.pse_data_quota += FIELD_GET(TXQ_CNT_L, data[0]) + /* BK */
- FIELD_GET(TXQ_CNT_H, data[0]) + /* BE */
- FIELD_GET(TXQ_CNT_L, data[1]) + /* VI */
- FIELD_GET(TXQ_CNT_H, data[1]); /* VO */
- sdio->sched.ple_data_quota += FIELD_GET(TXQ_CNT_H, data[2]) + /* BK */
- FIELD_GET(TXQ_CNT_L, data[3]) + /* BE */
- FIELD_GET(TXQ_CNT_H, data[3]) + /* VI */
- FIELD_GET(TXQ_CNT_L, data[4]); /* VO */
- sdio->sched.pse_mcu_quota += FIELD_GET(TXQ_CNT_L, data[2]);
+ sdio->sched.pse_mcu_quota += pse_mcu_quota;
+ sdio->sched.pse_data_quota += pse_data_quota;
+ sdio->sched.ple_data_quota += ple_data_quota;
mutex_unlock(&sdio->sched.lock);
+
+ return pse_data_quota + ple_data_quota + pse_mcu_quota;
}
static struct sk_buff *mt7663s_build_rx_skb(void *data, int data_len,
@@ -259,10 +278,8 @@ void mt7663s_rx_work(struct work_struct *work)
}
}
- if (intr->isr & WHIER_TX_DONE_INT_EN) {
- mt7663s_refill_sched_quota(dev, intr->tx.wtqcr);
+ if (mt7663s_refill_sched_quota(dev, intr->tx.wtqcr))
queue_work(sdio->txrx_wq, &sdio->tx.xmit_work);
- }
if (nframes) {
queue_work(sdio->txrx_wq, &sdio->rx.recv_work);
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/7] mt76: mt7663s: introduce sdio tx aggregation
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
` (4 preceding siblings ...)
2020-09-05 9:26 ` [PATCH 5/7] mt76: mt7663s: fix possible quota leak in mt7663s_refill_sched_quota Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 7/7] mt76: mt7663: check isr read return value in mt7663s_rx_work Lorenzo Bianconi
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
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>
---
drivers/net/wireless/mediatek/mt76/mac80211.c | 5 +-
drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++
.../net/wireless/mediatek/mt76/mt7615/sdio.c | 12 ++++-
.../wireless/mediatek/mt76/mt7615/sdio_txrx.c | 49 +++++++++++++------
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 7014846fd854..bd692431b07f 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -307,10 +307,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 209d23846d4c..c4a02b5aa990 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -444,6 +444,7 @@ struct mt76_usb {
} mcu;
};
+#define MT76S_XMIT_BUF_SZ (16 * PAGE_SIZE)
struct mt76_sdio {
struct workqueue_struct *txrx_wq;
struct {
@@ -457,6 +458,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);
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/7] mt76: mt7663: check isr read return value in mt7663s_rx_work
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
` (5 preceding siblings ...)
2020-09-05 9:26 ` [PATCH 6/7] mt76: mt7663s: introduce sdio tx aggregation Lorenzo Bianconi
@ 2020-09-05 9:26 ` Lorenzo Bianconi
6 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 9:26 UTC (permalink / raw)
To: nbd; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
In order to avoid using stale isr values, check return value from
sdio_readsb() in mt7663s_rx_work()
Tested-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
index e82f6bdcbce4..2486cda3243b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/sdio_txrx.c
@@ -278,9 +278,12 @@ void mt7663s_rx_work(struct work_struct *work)
/* disable interrupt */
sdio_claim_host(sdio->func);
sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
- sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(struct mt76s_intr));
+ ret = sdio_readsb(sdio->func, intr, MCR_WHISR, sizeof(*intr));
sdio_release_host(sdio->func);
+ if (ret < 0)
+ goto out;
+
trace_dev_irq(dev, intr->isr, 0);
if (intr->isr & WHIER_RX0_DONE_INT_EN) {
@@ -306,7 +309,7 @@ void mt7663s_rx_work(struct work_struct *work)
queue_work(sdio->txrx_wq, &sdio->rx.recv_work);
return;
}
-
+out:
/* enable interrupt */
sdio_claim_host(sdio->func);
sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
--
2.26.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic
2020-09-05 9:26 ` [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic Lorenzo Bianconi
@ 2020-09-05 11:32 ` Felix Fietkau
2020-09-05 11:47 ` Lorenzo Bianconi
0 siblings, 1 reply; 10+ messages in thread
From: Felix Fietkau @ 2020-09-05 11:32 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
On 2020-09-05 11:26, Lorenzo Bianconi wrote:
> Since the sdio engine does not report quota for altx queue, move
> ctl/mgmt traffic to standard data queues
>
> Tested-by: Sean Wang <sean.wang@mediatek.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Wouldn't this add powersave buffering to non-bufferable mgmt frames in
AP mode?
- Felix
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic
2020-09-05 11:32 ` Felix Fietkau
@ 2020-09-05 11:47 ` Lorenzo Bianconi
0 siblings, 0 replies; 10+ messages in thread
From: Lorenzo Bianconi @ 2020-09-05 11:47 UTC (permalink / raw)
To: Felix Fietkau; +Cc: lorenzo.bianconi, linux-wireless, sean.wang
[-- Attachment #1: Type: text/plain, Size: 640 bytes --]
On Sep 05, Felix Fietkau wrote:
> On 2020-09-05 11:26, Lorenzo Bianconi wrote:
> > Since the sdio engine does not report quota for altx queue, move
> > ctl/mgmt traffic to standard data queues
> >
> > Tested-by: Sean Wang <sean.wang@mediatek.com>
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> Wouldn't this add powersave buffering to non-bufferable mgmt frames in
> AP mode?
Right, but sdio devices do not have a hw dma scheduler like pcie or usb
ones and just report the availale quota for new trasmission for data queues only
AFAIU. Moreover AP support is not tested yet.
Regards,
Lorenzo
>
> - Felix
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2020-09-05 11:48 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-05 9:26 [PATCH 0/7] add tx aggregation for mt7663s Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 1/7] mt76: mt7663s: do not use altx for ctl/mgmt traffic Lorenzo Bianconi
2020-09-05 11:32 ` Felix Fietkau
2020-09-05 11:47 ` Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 2/7] mt76: mt7663s: split mt7663s_tx_update_sched in mt7663s_tx_{pick,update}_quota Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 3/7] mt76: mt7663s: introduce __mt7663s_xmit_queue routine Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 4/7] mt76: move pad estimation out of mt76_skb_adjust_pad Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 5/7] mt76: mt7663s: fix possible quota leak in mt7663s_refill_sched_quota Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 6/7] mt76: mt7663s: introduce sdio tx aggregation Lorenzo Bianconi
2020-09-05 9:26 ` [PATCH 7/7] mt76: mt7663: check isr read return value in mt7663s_rx_work Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).