linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).