linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths
@ 2015-06-02 19:11 Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 2/4] mt7601u: watch out for invalid-length frames Jakub Kicinski
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Jakub Kicinski @ 2015-06-02 19:11 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Jakub Kicinski

From: Jakub Kicinski <kubakici@wp.pl>

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
---
 drivers/net/wireless/mediatek/mt7601u/dma.c | 62 ++++++-----------------------
 1 file changed, 12 insertions(+), 50 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index 9c9e1288644b..16df67b2e62c 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -34,56 +34,28 @@ static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
 
 static struct sk_buff *
 mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
-			u8 *data, u32 seg_len)
+			void *data, u32 seg_len, u32 truesize, struct page *p)
 {
 	struct sk_buff *skb;
 	u32 true_len;
+	int hdr_len, copy, frag;
 
-	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD))
-		seg_len -= 2;
-
-	skb = alloc_skb(seg_len, GFP_ATOMIC);
-	if (!skb)
-		return NULL;
-
-	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
-		int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
-
-		memcpy(skb_put(skb, hdr_len), data, hdr_len);
-		data += hdr_len + 2;
-		seg_len -= hdr_len;
-	}
-
-	memcpy(skb_put(skb, seg_len), data, seg_len);
-
-	true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi);
-	skb_trim(skb, true_len);
-
-	return skb;
-}
-
-static struct sk_buff *
-mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
-			      struct mt7601u_rxwi *rxwi, void *data,
-			      u32 seg_len, u32 truesize, struct page *p)
-{
-	unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
-	unsigned int true_len, copy, frag;
-	struct sk_buff *skb;
-
-	skb = alloc_skb(128, GFP_ATOMIC);
+	skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
 	if (!skb)
 		return NULL;
 
 	true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
 
+	hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
 	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
 		memcpy(skb_put(skb, hdr_len), data, hdr_len);
+
 		data += hdr_len + 2;
 		true_len -= hdr_len;
 		hdr_len = 0;
 	}
 
+	/* If not doing paged RX allocated skb will always have enough space */
 	copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
 	frag = true_len - copy;
 
@@ -100,7 +72,7 @@ mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
 }
 
 static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
-				   u32 seg_len, struct page *p, bool paged)
+				   u32 seg_len, struct page *p)
 {
 	struct sk_buff *skb;
 	struct mt7601u_rxwi *rxwi;
@@ -126,11 +98,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
 
 	trace_mt_rx(dev, rxwi, fce_info);
 
-	if (paged)
-		skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len,
-						    truesize, p);
-	else
-		skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len);
+	skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p);
 	if (!skb)
 		return;
 
@@ -158,23 +126,17 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
 	u32 seg_len, data_len = e->urb->actual_length;
 	u8 *data = page_address(e->p);
 	struct page *new_p = NULL;
-	bool paged = true;
 	int cnt = 0;
 
 	if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state))
 		return;
 
 	/* Copy if there is very little data in the buffer. */
-	if (data_len < 512) {
-		paged = false;
-	} else {
+	if (data_len > 512)
 		new_p = dev_alloc_pages(MT_RX_ORDER);
-		if (!new_p)
-			paged = false;
-	}
 
 	while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) {
-		mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged);
+		mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL);
 
 		data_len -= seg_len;
 		data += seg_len;
@@ -182,9 +144,9 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
 	}
 
 	if (cnt > 1)
-		trace_mt_rx_dma_aggr(dev, cnt, paged);
+		trace_mt_rx_dma_aggr(dev, cnt, !!new_p);
 
-	if (paged) {
+	if (new_p) {
 		/* we have one extra ref from the allocator */
 		__free_pages(e->p, MT_RX_ORDER);
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/4] mt7601u: watch out for invalid-length frames
  2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
@ 2015-06-02 19:11 ` Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 3/4] mt7601u: don't cleanup device second time after .resume() Jakub Kicinski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2015-06-02 19:11 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Jakub Kicinski

From: Jakub Kicinski <kubakici@wp.pl>

Users of older Ralink devices report that received frames
sometimes have zero length.  Watch out for that.

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
---
 drivers/net/wireless/mediatek/mt7601u/dma.c | 14 ++++++++++++--
 drivers/net/wireless/mediatek/mt7601u/mac.c |  8 ++++++--
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c
index 16df67b2e62c..7217da4f1543 100644
--- a/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ b/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -37,16 +37,20 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
 			void *data, u32 seg_len, u32 truesize, struct page *p)
 {
 	struct sk_buff *skb;
-	u32 true_len;
-	int hdr_len, copy, frag;
+	u32 true_len, hdr_len = 0, copy, frag;
 
 	skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
 	if (!skb)
 		return NULL;
 
 	true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
+	if (!true_len || true_len > seg_len)
+		goto bad_frame;
 
 	hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
+	if (!hdr_len)
+		goto bad_frame;
+
 	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
 		memcpy(skb_put(skb, hdr_len), data, hdr_len);
 
@@ -69,6 +73,12 @@ mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
 	}
 
 	return skb;
+
+bad_frame:
+	dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n",
+			    true_len, hdr_len);
+	dev_kfree_skb(skb);
+	return NULL;
 }
 
 static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
diff --git a/drivers/net/wireless/mediatek/mt7601u/mac.c b/drivers/net/wireless/mediatek/mt7601u/mac.c
index c161bcc6a7fa..7514bce1ac91 100644
--- a/drivers/net/wireless/mediatek/mt7601u/mac.c
+++ b/drivers/net/wireless/mediatek/mt7601u/mac.c
@@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
 {
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct mt7601u_rxwi *rxwi = rxi;
-	u32 ctl = le32_to_cpu(rxwi->ctl);
+	u32 len, ctl = le32_to_cpu(rxwi->ctl);
 	u16 rate = le16_to_cpu(rxwi->rate);
 	int rssi;
 
+	len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+	if (len < 10)
+		return 0;
+
 	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
 		status->flag |= RX_FLAG_DECRYPTED;
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -474,7 +478,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
 		dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
 	spin_unlock_bh(&dev->con_mon_lock);
 
-	return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+	return len;
 }
 
 static enum mt76_cipher_type
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/4] mt7601u: don't cleanup device second time after .resume()
  2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 2/4] mt7601u: watch out for invalid-length frames Jakub Kicinski
@ 2015-06-02 19:11 ` Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 4/4] mt7601u: set promiscous mode based on FIF_OTHER_BSS Jakub Kicinski
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2015-06-02 19:11 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Jakub Kicinski

From: Jakub Kicinski <kubakici@wp.pl>

Make sure .disconnect() doesn't cleanup the device if
.resume() failed.  This may happen when device is removed
during suspend.

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
---
 drivers/net/wireless/mediatek/mt7601u/init.c | 3 +++
 drivers/net/wireless/mediatek/mt7601u/usb.c  | 9 ++++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt7601u/init.c b/drivers/net/wireless/mediatek/mt7601u/init.c
index 1fc86e865c8c..45eb0796a2e5 100644
--- a/drivers/net/wireless/mediatek/mt7601u/init.c
+++ b/drivers/net/wireless/mediatek/mt7601u/init.c
@@ -427,6 +427,9 @@ err:
 
 void mt7601u_cleanup(struct mt7601u_dev *dev)
 {
+	if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state))
+		return;
+
 	mt7601u_stop_hardware(dev);
 	mt7601u_dma_cleanup(dev);
 	mt7601u_mcu_cmd_deinit(dev);
diff --git a/drivers/net/wireless/mediatek/mt7601u/usb.c b/drivers/net/wireless/mediatek/mt7601u/usb.c
index 99e2b3997bfa..54dba4001865 100644
--- a/drivers/net/wireless/mediatek/mt7601u/usb.c
+++ b/drivers/net/wireless/mediatek/mt7601u/usb.c
@@ -338,8 +338,15 @@ static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
 static int mt7601u_resume(struct usb_interface *usb_intf)
 {
 	struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
+	int ret;
+
+	ret = mt7601u_init_hardware(dev);
+	if (ret)
+		return ret;
+
+	set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
 
-	return mt7601u_init_hardware(dev);
+	return 0;
 }
 
 MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 4/4] mt7601u: set promiscous mode based on FIF_OTHER_BSS
  2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 2/4] mt7601u: watch out for invalid-length frames Jakub Kicinski
  2015-06-02 19:11 ` [PATCH 3/4] mt7601u: don't cleanup device second time after .resume() Jakub Kicinski
@ 2015-06-02 19:11 ` Jakub Kicinski
  2015-06-08  7:09 ` [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Kalle Valo
  2015-06-08 11:28 ` Kalle Valo
  4 siblings, 0 replies; 6+ messages in thread
From: Jakub Kicinski @ 2015-06-02 19:11 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, Jakub Kicinski

From: Jakub Kicinski <kubakici@wp.pl>

Most drivers use FIF_OTHER_BSS to set promiscous mode.  Let us
follow their lead even though it doesn't match exactly the HW
filter flags.

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
---
 drivers/net/wireless/mediatek/mt7601u/main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index ced82abb414f..169384b48b27 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -119,6 +119,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 	dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
 
+	MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC);
 	MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
 	MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
 	MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths
  2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
                   ` (2 preceding siblings ...)
  2015-06-02 19:11 ` [PATCH 4/4] mt7601u: set promiscous mode based on FIF_OTHER_BSS Jakub Kicinski
@ 2015-06-08  7:09 ` Kalle Valo
  2015-06-08 11:28 ` Kalle Valo
  4 siblings, 0 replies; 6+ messages in thread
From: Kalle Valo @ 2015-06-08  7:09 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: linux-wireless, Jakub Kicinski

Jakub Kicinski <moorray3@wp.pl> writes:

> From: Jakub Kicinski <kubakici@wp.pl>
>
> Signed-off-by: Jakub Kicinski <kubakici@wp.pl>

No need to change anything now but in the future please avoid empty
commit logs. And at some point I'll start automatically rejecting
patches with empty commit logs so better get used to this already now.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths
  2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
                   ` (3 preceding siblings ...)
  2015-06-08  7:09 ` [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Kalle Valo
@ 2015-06-08 11:28 ` Kalle Valo
  4 siblings, 0 replies; 6+ messages in thread
From: Kalle Valo @ 2015-06-08 11:28 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: linux-wireless, Jakub Kicinski

Jakub Kicinski <moorray3@wp.pl> writes:

> From: Jakub Kicinski <kubakici@wp.pl>
>
> Signed-off-by: Jakub Kicinski <kubakici@wp.pl>

Thanks, applied all four manually.

-- 
Kalle Valo

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-06-08 11:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-02 19:11 [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Jakub Kicinski
2015-06-02 19:11 ` [PATCH 2/4] mt7601u: watch out for invalid-length frames Jakub Kicinski
2015-06-02 19:11 ` [PATCH 3/4] mt7601u: don't cleanup device second time after .resume() Jakub Kicinski
2015-06-02 19:11 ` [PATCH 4/4] mt7601u: set promiscous mode based on FIF_OTHER_BSS Jakub Kicinski
2015-06-08  7:09 ` [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths Kalle Valo
2015-06-08 11:28 ` Kalle Valo

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).