Search Linux Wireless

Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Feb 16, 2019 at 08:17:07PM +0100, Stefan Wahren wrote:
> this is a misunderstanding. The warning is about memory alignment to 32 bit addresses, not about page alignment. This is a typical ARM restriction. Maybe we need to make sure in mt76 that the DMA buffer needs to be aligned. But it's also possible that the warning isn't the root cause of our problem.
> 

I see, it needs 4 bytes alignment . There is already dwc2 code checks
that and allocate new buffer if the alignment is not right:
dwc2_alloc_dma_aligned_buffer(), but it does nothing if urb->sg
is not NULL. I thought mt76usb already provide aligned buffers, but
looks it does not for one TX special case, which are PROBE REQUEST
frames. Other frames are aligned by inserting L2 header pad. One
solution for this would be just submit urb with  NULL sg (same as
Lorenzo's patches do, but still allocating buffers via buf->sg),
but I think, you have right, we should provide 4 bytes aligned buffers
by default as other DMA hardware may require that. I'm attaching yet
another patch to test, which fix up alignment for PROBE REQUEST frames.

> > Attached patch should fix this, plese test, thanks in advance.
> 
> Anyway i tested the following patch combinations against next with the same results as 1,2,3 (no wifi, alignment warning):
> 1,3
> 1,2,3,4

I noticed on my setup that patch 4 can cause troubles, but still
device is workable here on my PC machines.

> > > Btw i can confirm a regression was introduced after 4.19, because in 4.19 there was no firmware timeout but even no working wifi:
> > 
> > You ment 'no working wifi' or 'working wifi'?
> 
> Wifi is broken in 4.19, 4.20, 5.0 and next. It only worked with Lorenzo's SG avoid patches so far. Btw the regression (firmware timeout) started in 4.20. I also tested it today.

That somewhat strange because 4.19 mt76x0u does not use SG.
On 4.19 there is phy calibration bug fixed in 4.19.5:

commit 0d9813319b40399a0d8fd761d2fcfedee5701487
Author: Lorenzo Bianconi <lorenzo.bianconi@xxxxxxxxxx>
Date:   Fri Sep 7 23:13:12 2018 +0200

    mt76x0: run vco calibration for each channel configuration

It's possible that without this vco calibration fix, MT7610U device
does not see AP if it's signal is weak.

Stanislaw

>From d420961afd1ae2ca8590ee2c79defc0a48fa8e73 Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@xxxxxxxxxx>
Date: Mon, 18 Feb 2019 14:39:38 +0100
Subject: [PATCH] mt76x02: make sure probe request skb's are 4 bytes aligned

We add 2 bytes header pad if header length is not multiple of 4 bytes,
this assure most tx skb buffers are 4 bytes aligned. But this is not
true for probe request frames which have n*4 bytes header length and
are not aligned.

I think is ok to assume that frames have to be 4 bytes aligned
for DMA purpose, so mt76 driver should take care of that.

Signed-off-by: Stanislaw Gruszka <sgruszka@xxxxxxxxxx>
---
 drivers/net/wireless/mediatek/mt76/mt76x02.h       |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c  |  5 +---
 .../net/wireless/mediatek/mt76/mt76x02_usb_core.c  |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c  | 32 +++++++++++++++-------
 4 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 6d96766a6ed3..ad329db7de4e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -155,7 +155,7 @@ void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
 void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
 				s16 coverage_class);
 int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
-int mt76x02_insert_hdr_pad(struct sk_buff *skb);
+void mt76x02_align_skb(struct sk_buff *skb);
 void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
 bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
 void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
index a5413a309a0a..63c5520a65ca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c
@@ -163,7 +163,6 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 	struct mt76x02_txwi *txwi = txwi_ptr;
 	int qsel = MT_QSEL_EDCA;
 	int pid;
-	int ret;
 
 	if (q == &dev->mt76.q_tx[MT_TXQ_PSD] && wcid && wcid->idx < 128)
 		mt76x02_mac_wcid_set_drop(dev, wcid->idx, false);
@@ -173,9 +172,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
 	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
 	txwi->pktid = pid;
 
-	ret = mt76x02_insert_hdr_pad(skb);
-	if (ret < 0)
-		return ret;
+	mt76x02_align_skb(skb);
 
 	if (pid >= MT_PACKET_ID_FIRST)
 		qsel = MT_QSEL_MGMT;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 098d05e109e7..bd5838c26f43 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -79,7 +79,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 	u32 flags;
 	int pid;
 
-	mt76x02_insert_hdr_pad(skb);
+	mt76x02_align_skb(skb);
 
 	txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
 	mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 062614ad0d51..08425b1d2c30 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -550,21 +550,33 @@ void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL_GPL(mt76x02_sta_rate_tbl_update);
 
-int mt76x02_insert_hdr_pad(struct sk_buff *skb)
+void mt76x02_align_skb(struct sk_buff *skb)
 {
-	int len = ieee80211_get_hdrlen_from_skb(skb);
+	int align = ((unsigned long) skb->data) & 3;
+	int hdrlen, skblen;
 
-	if (len % 4 == 0)
-		return 0;
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	WARN_ON_ONCE(align == 0 && (hdrlen & 3));
+
+	if (align == 0)
+		return;
 
-	skb_push(skb, 2);
-	memmove(skb->data, skb->data + 2, len);
+	if (hdrlen & 3) {
+		/* Align frame and add 2 bytes pad after header. */
+		skb_push(skb, 2);
+		memmove(skb->data, skb->data + 2, hdrlen);
 
-	skb->data[len] = 0;
-	skb->data[len + 1] = 0;
-	return 2;
+		skb->data[hdrlen] = 0;
+		skb->data[hdrlen + 1] = 0;
+	} else {
+		/* Only for probe request frames. */
+		skblen = skb->len;
+		skb_push(skb, 2);
+		memmove(skb->data, skb->data + 2, skblen);
+		skb_trim(skb, skblen);
+	}
 }
-EXPORT_SYMBOL_GPL(mt76x02_insert_hdr_pad);
+EXPORT_SYMBOL_GPL(mt76x02_align_skb);
 
 void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len)
 {
-- 
2.7.5


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux