2015-06-02 19:11:40

by Jakub Kicinski

[permalink] [raw]
Subject: [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths

From: Jakub Kicinski <[email protected]>

Signed-off-by: Jakub Kicinski <[email protected]>
---
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



2015-06-02 19:11:44

by Jakub Kicinski

[permalink] [raw]
Subject: [PATCH 4/4] mt7601u: set promiscous mode based on FIF_OTHER_BSS

From: Jakub Kicinski <[email protected]>

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 <[email protected]>
---
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


2015-06-08 07:09:10

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths

Jakub Kicinski <[email protected]> writes:

> From: Jakub Kicinski <[email protected]>
>
> Signed-off-by: Jakub Kicinski <[email protected]>

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

2015-06-02 19:11:40

by Jakub Kicinski

[permalink] [raw]
Subject: [PATCH 2/4] mt7601u: watch out for invalid-length frames

From: Jakub Kicinski <[email protected]>

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

Signed-off-by: Jakub Kicinski <[email protected]>
---
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


2015-06-08 11:28:59

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 1/4] mt7601u: unify paged and non-paged RX dma paths

Jakub Kicinski <[email protected]> writes:

> From: Jakub Kicinski <[email protected]>
>
> Signed-off-by: Jakub Kicinski <[email protected]>

Thanks, applied all four manually.

--
Kalle Valo

2015-06-02 19:11:42

by Jakub Kicinski

[permalink] [raw]
Subject: [PATCH 3/4] mt7601u: don't cleanup device second time after .resume()

From: Jakub Kicinski <[email protected]>

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 <[email protected]>
---
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