Re: [PATCH v2] mt76: refactor cc_lock locking scheme

2019-10-15 Thread Stanislaw Gruszka
On Tue, Oct 15, 2019 at 05:16:43PM +0200, Lorenzo Bianconi wrote:
> Read busy counters not holding cc_lock spinlock since usb read can't be
> performed in interrupt context. Move cc_active and cc_rx counters out of
> cc_lock since they are not modified in interrupt context.
> Grab cc_lock updating cur_cc_bss_rx in mt76_airtime_report and do not
> hold rx_lock in mt76_update_survey.

> Fixes: 168aea24f4bb ("mt76: mt76x02u: enable survey support")

I think problem was introduced currently in mt76 driver version
that is not yet in mainline tree, so this is not right commit.
On Linus' tree we still read registers outside of cc_lock section.

void mt76x02_update_channel(struct mt76_dev *mdev)
{
...

busy = mt76_rr(dev, MT_CH_BUSY);
active = busy + mt76_rr(dev, MT_CH_IDLE);

spin_lock_bh(&dev->mt76.cc_lock);
state->cc_busy += busy;
state->cc_active += active;
spin_unlock_bh(&dev->mt76.cc_lock);
}

>   if (dev->drv->drv_flags & MT_DRV_SW_RX_AIRTIME) {
> - spin_lock_bh(&dev->rx_lock);
> - spin_lock(&dev->cc_lock);
> + spin_lock_bh(&dev->cc_lock);
>   state->cc_bss_rx += dev->cur_cc_bss_rx;
>   dev->cur_cc_bss_rx = 0;
> - spin_unlock(&dev->cc_lock);
> - spin_unlock_bh(&dev->rx_lock);
> + spin_unlock_bh(&dev->cc_lock);

Why dev->rx_lock was needed before and is not needed now ?

Stanislaw


Re: [PATCH] mac80211: simplify TX aggregation start

2019-10-02 Thread Stanislaw Gruszka
On Tue, Oct 01, 2019 at 10:06:29PM +0200, Johannes Berg wrote:
> index f1cdcd61c54a..b74e758cce09 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> @@ -10489,7 +10489,7 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, 
> struct ieee80211_vif *vif,
>*/
>   break;
>   case IEEE80211_AMPDU_TX_START:
> - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
>   break;
>   case IEEE80211_AMPDU_TX_STOP_CONT:
>   case IEEE80211_AMPDU_TX_STOP_FLUSH:

> +#define IEEE80211_AMPDU_TX_START_IMMEDIATE 1
> +
>  /**

On rt2x00 we already return 1 for case we do not have free HW WCID
number for a remote station.

if (sta_priv->wcid > WCID_END)
return 1;

So we should change that to some other error code i.e. -ENOSPC.

Stanislaw


Re: rt2x00 regression

2019-09-27 Thread Stanislaw Gruszka
On Thu, Sep 26, 2019 at 06:32:23PM +0200, Anton Olsson wrote:
> Hello I have a USB based ID 148f:3070 Ralink Technology, Corp. RT2870/RT3070 
> Wireless Adapter, that stops working with recent kernels. It works on kernel 
> 5.1.15 and does not work with 5.2.7 or 5.3.1 (I have not tested other 
> versions). I use it in AP mode.
> 
> I found this similar bug report 
> https://marc.info/?l=linux-wireless&m=156630037103575&w=2 but that did not 
> have related error messages so I assume this is different?
> 
> Logs of working kernel 5.1.15-arch1-1-ARCH.
> [   78.680555] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 3070, rev 
> 0201 detected
> [   78.690992] ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 0005 detected
> [   78.799625] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
> sep 26 17:13:03 kernel: usbcore: registered new interface driver rt2800usb
> sep 26 17:13:03 systemd[1]: Found device RT2870/RT3070 Wireless Adapter.
> [  113.812454] ieee80211 phy0: rt2x00lib_request_firmware: Info - Loading 
> firmware file 'rt2870.bin'
> [  113.905279] ieee80211 phy0: rt2x00lib_request_firmware: Info - Firmware 
> detected - version: 0.36
> [  114.028703] ieee80211 phy0: rt2x00usb_vendor_request: Error - Vendor 
> Request 0x06 failed for offset 0x0404 with error -71
> 
> The last error there does not seem to affect the operation of the device.
> 
> Logs of not working with kernel 5.3.1, 5.2.7 has similar output.
> sep 26 17:06:12 kernel: ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 
> 3070, rev 0201 detected
> sep 26 17:06:12 kernel: ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 0005 
> detected
> sep 26 17:06:12 kernel: ieee80211 phy0: Selected rate control algorithm 
> 'minstrel_ht'
> sep 26 17:06:12 kernel: usbcore: registered new interface driver rt2800usb
> sep 26 17:06:12 systemd[1]: Found device RT2870/RT3070 Wireless Adapter.
> sep 26 17:06:21 ieee80211 phy0: rt2x00lib_request_firmware: Info - Loading 
> firmware file 'rt2870.bin'
> sep 26 17:06:21 ieee80211 phy0: rt2x00lib_request_firmware: Info - Firmware 
> detected - version: 0.36
> sep 26 17:06:21 ieee80211 phy0: rt2x00usb_vendor_request: Error - Vendor 
> Request 0x06 failed for offset 0x0404 with>
> sep 26 17:06:22 ieee80211 phy0: rt2800_wait_csr_ready: Error - Unstable 
> hardware
> sep 26 17:06:22 ieee80211 phy0: rt2800usb_set_device_state: Error - Device 
> failed to enter state 4 (-5)
> 
> Unable to bring up the network interface here.

This most likely is the problem introduced by commit:

commit e383c70474db32b9d4a3de6dfbd08784d19e6751
Author: Stanislaw Gruszka 
Date:   Tue Mar 12 10:51:42 2019 +0100

rt2x00: check number of EPROTO errors

Plase check below patch that increase number of EPROTO checks 
before marking device removed. If it does not help, plese
check if reverting above commits helps.

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
index bc2dfef0de22..215c3f092306 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -30,7 +30,7 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev 
*rt2x00dev, int status)
else
rt2x00dev->num_proto_errs = 0;
 
-   if (rt2x00dev->num_proto_errs > 3)
+   if (rt2x00dev->num_proto_errs > 8)
return true;
 
return false;


[PATCH] rt2x00: initialize last_reset

2019-09-26 Thread Stanislaw Gruszka
Initialize last_reset variable to INITIAL_JIFFIES, otherwise it is not
possible to test H/W reset for first 5 minutes of system run.

Fixes: e403fa31ed71 ("rt2x00: add restart hw")
Reported-and-tested-by: Jonathan Liu 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index 4d4e3888ef20..f2395309ec00 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -555,7 +555,7 @@ static ssize_t rt2x00debug_write_restart_hw(struct file 
*file,
 {
struct rt2x00debug_intf *intf = file->private_data;
struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
-   static unsigned long last_reset;
+   static unsigned long last_reset = INITIAL_JIFFIES;
 
if (!rt2x00_has_cap_restart_hw(rt2x00dev))
return -EOPNOTSUPP;
-- 
2.20.1



[PATCH 5.3] Revert "rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band"

2019-08-29 Thread Stanislaw Gruszka
This reverts commit 9ad3b55654455258a9463384edb40077439d879f.

As reported by Sergey:

"I got some problem after upgrade kernel to 5.2 version (debian testing
linux-image-5.2.0-2-amd64). 5Ghz client  stopped to see AP.
Some tests with 1metre distance between client-AP: 2.4Ghz  -22dBm, for
5Ghz - 53dBm !, for longer distance (8m + walls) 2.4 - 61dBm, 5Ghz not
visible."

It was identified that rx signal level degradation was caused by
9ad3b5565445 ("rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band").
So revert this commit.

Cc:  # v5.1+
Reported-and-tested-by: Sergey Maranchuk 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index c9b957ac5733..b2bfa83819b0 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -4237,24 +4237,18 @@ static void rt2800_config_channel(struct rt2x00_dev 
*rt2x00dev,
switch (rt2x00dev->default_ant.rx_chain_num) {
case 3:
/* Turn on tertiary LNAs */
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN,
-  rf->channel > 14);
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN,
-  rf->channel <= 14);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1);
/* fall-through */
case 2:
/* Turn on secondary LNAs */
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN,
-  rf->channel > 14);
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN,
-  rf->channel <= 14);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
/* fall-through */
case 1:
/* Turn on primary LNAs */
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN,
-  rf->channel > 14);
-   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN,
-  rf->channel <= 14);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+   rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
break;
}
 
-- 
1.9.3



Re: rt2x00: 5Ghz signal power degradation with linux 5.2 kernel

2019-08-29 Thread Stanislaw Gruszka
On Thu, Aug 29, 2019 at 12:42:44PM +0300, Sergey Maranchuk wrote:
> I got some problem after upgrade kernel to 5.2 version (debian testing
> linux-image-5.2.0-2-amd64). 5Ghz client  stopped to see AP.
> Some tests with 1metre distance between client-AP: 2.4Ghz  -22dBm, for
> 5Ghz - 53dBm !, for longer distance (8m + walls) 2.4 - 61dBm, 5Ghz not
> visible.
> All works fine with kernel 4.19 and on windows 10, other devices also
> see AP without any problems with same distance.

After looking on the changlog most possible cause of it seems to be
commit 9ad3b55654455258a9463384edb40077439d879f:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9ad3b55654455258a9463384edb40077439d879f

Please try to revert it, and see if that improve rx signal level. 

It that would not help, please try to narrow regression to two
consecutive kernel versions - it is: 4.19 -> 5.0 or 5.0 -> 5.1
or 5.1 -> 5.2 ?

Stanislaw


[PATCH 5.3] rt2x00: clear up IV's on key removal

2019-08-23 Thread Stanislaw Gruszka
After looking at code I realized that my previous fix
95844124385e ("rt2x00: clear IV's on start to fix AP mode regression")
was incomplete. We can still have wrong IV's after re-keyring.
To fix that, clear up IV's also on key removal.

Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index ecbe78b8027b..28e2de04834e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1654,13 +1654,18 @@ static void rt2800_config_wcid_attr_cipher(struct 
rt2x00_dev *rt2x00dev,
 
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
-   rt2800_register_multiread(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
-   if ((crypto->cipher == CIPHER_TKIP) ||
-   (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
-   (crypto->cipher == CIPHER_AES))
-   iveiv_entry.iv[3] |= 0x20;
-   iveiv_entry.iv[3] |= key->keyidx << 6;
+   if (crypto->cmd == SET_KEY) {
+   rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
+   if ((crypto->cipher == CIPHER_TKIP) ||
+   (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+   (crypto->cipher == CIPHER_AES))
+   iveiv_entry.iv[3] |= 0x20;
+   iveiv_entry.iv[3] |= key->keyidx << 6;
+   } else {
+   memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+   }
+
rt2800_register_multiwrite(rt2x00dev, offset,
   &iveiv_entry, sizeof(iveiv_entry));
 }
-- 
1.9.3



Re: [PATCH 1/3] mt76: remove redundant mt76_txq_schedule_all

2019-08-23 Thread Stanislaw Gruszka
On Fri, Aug 23, 2019 at 11:27:41AM +0200, Felix Fietkau wrote:
> On 2019-08-23 10:52, Stanislaw Gruszka wrote:
> > Waking tx queues will cause that txq's will be scheduled. Calling
> > mt76_txq_schedule_all() while queues are blocked is not necessary.
> > We will not get any skb's from ieee80211_tx_dequeue() anyway, but
> > patch changes that transmit of mtxq->retry_q skb's will be a bit
> > deferred (on the moment after channel switch or other situation
> > when we wake up queues).
> > 
> > Signed-off-by: Stanislaw Gruszka 
> Waking tx queues will not always cause txqs to be scheduled - only if an
> attempt to dequeue was blocked because queues were stopped at that time.
> Because of that, I don't think this patch is correct.

Ok, please drop it.

Stanislaw


[PATCH 1/3] mt76: remove redundant mt76_txq_schedule_all

2019-08-23 Thread Stanislaw Gruszka
Waking tx queues will cause that txq's will be scheduled. Calling
mt76_txq_schedule_all() while queues are blocked is not necessary.
We will not get any skb's from ieee80211_tx_dequeue() anyway, but
patch changes that transmit of mtxq->retry_q skb's will be a bit
deferred (on the moment after channel switch or other situation
when we wake up queues).

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt7603/mac.c  | 1 -
 drivers/net/wireless/mediatek/mt76/mt7603/main.c | 2 --
 drivers/net/wireless/mediatek/mt76/mt7615/main.c | 1 -
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 2 --
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c| 1 -
 drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 --
 drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 1 -
 7 files changed, 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c 
b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
index c328192307c4..eb33de264c8a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1344,7 +1344,6 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev 
*dev)
napi_schedule(&dev->mt76.napi[1]);
 
ieee80211_wake_queues(dev->mt76.hw);
-   mt76_txq_schedule_all(&dev->mt76);
 }
 
 static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c 
b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 25d5b1608bc9..3a1b18795e05 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -170,8 +170,6 @@ void mt7603_init_edcca(struct mt7603_dev *dev)
 
clear_bit(MT76_RESET, &dev->mt76.state);
 
-   mt76_txq_schedule_all(&dev->mt76);
-
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
 msecs_to_jiffies(MT7603_WATCHDOG_TIME));
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c 
b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 87c748715b5d..41ca44ffb058 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -158,7 +158,6 @@ static int mt7615_set_channel(struct mt7615_dev *dev)
clear_bit(MT76_RESET, &dev->mt76.state);
mutex_unlock(&dev->mt76.mutex);
 
-   mt76_txq_schedule_all(&dev->mt76);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mt76.mac_work,
 MT7615_WATCHDOG_TIME);
return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index 3bc665643e51..562249eb918c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -33,8 +33,6 @@
}
mt76x02_pre_tbtt_enable(dev, true);
 
-   mt76_txq_schedule_all(&dev->mt76);
-
return ret;
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index dc773070481d..fdc0297c1d27 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -513,7 +513,6 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev)
ieee80211_restart_hw(dev->mt76.hw);
} else {
ieee80211_wake_queues(dev->mt76.hw);
-   mt76_txq_schedule_all(&dev->mt76);
}
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 4971685aafe8..8275a211fd20 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -68,8 +68,6 @@
tasklet_enable(&dev->dfs_pd.dfs_tasklet);
tasklet_enable(&dev->mt76.pre_tbtt_tasklet);
 
-   mt76_txq_schedule_all(&dev->mt76);
-
return ret;
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index eb73cb856c81..d5bfffd6099d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -58,7 +58,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
mutex_unlock(&dev->mt76.mutex);
 
mt76x02_pre_tbtt_enable(dev, true);
-   mt76_txq_schedule_all(&dev->mt76);
 
return err;
 }
-- 
1.9.3



[PATCH 3/3] mt76: mt76x0: remove unneeded return value on set channel

2019-08-23 Thread Stanislaw Gruszka
We allways return 0 from mt76x0_phy_set_channel(), no need to pass
return value upward.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c   | 13 -
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c|  8 +++-
 3 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index 562249eb918c..8a3bb924bef4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -8,18 +8,16 @@
 #include 
 #include "mt76x0.h"
 
-static int
+static void
 mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
 {
-   int ret;
-
cancel_delayed_work_sync(&dev->cal_work);
mt76x02_pre_tbtt_enable(dev, false);
if (mt76_is_mmio(dev))
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
 
mt76_set_channel(&dev->mt76);
-   ret = mt76x0_phy_set_channel(dev, chandef);
+   mt76x0_phy_set_channel(dev, chandef);
 
/* channel cycle counters read-and-clear */
mt76_rr(dev, MT_CH_IDLE);
@@ -32,20 +30,17 @@
tasklet_enable(&dev->dfs_pd.dfs_tasklet);
}
mt76x02_pre_tbtt_enable(dev, true);
-
-   return ret;
 }
 
 int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
 {
struct mt76x02_dev *dev = hw->priv;
-   int ret = 0;
 
mutex_lock(&dev->mt76.mutex);
 
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
ieee80211_stop_queues(hw);
-   ret = mt76x0_set_channel(dev, &hw->conf.chandef);
+   mt76x0_set_channel(dev, &hw->conf.chandef);
ieee80211_wake_queues(hw);
}
 
@@ -67,6 +62,6 @@ int mt76x0_config(struct ieee80211_hw *hw, u32 changed)
 
mutex_unlock(&dev->mt76.mutex);
 
-   return ret;
+   return 0;
 }
 EXPORT_SYMBOL_GPL(mt76x0_config);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index caa87f0c3cb8..26517e062bdb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -54,8 +54,8 @@ static inline bool is_mt7630(struct mt76x02_dev *dev)
 /* PHY */
 void mt76x0_phy_init(struct mt76x02_dev *dev);
 int mt76x0_phy_wait_bbp_ready(struct mt76x02_dev *dev);
-int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
-  struct cfg80211_chan_def *chandef);
+void mt76x0_phy_set_channel(struct mt76x02_dev *dev,
+   struct cfg80211_chan_def *chandef);
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev);
 void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on);
 #endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 1d00aa5da95b..711a352dfd5c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -909,8 +909,8 @@ void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool 
power_on)
 }
 EXPORT_SYMBOL_GPL(mt76x0_phy_calibrate);
 
-int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
-  struct cfg80211_chan_def *chandef)
+void mt76x0_phy_set_channel(struct mt76x02_dev *dev,
+   struct cfg80211_chan_def *chandef)
 {
u32 ext_cca_chan[4] = {
[0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) |
@@ -1004,7 +1004,7 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
/* enable vco */
mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7));
if (scan)
-   return 0;
+   return;
 
mt76x02_init_agc_gain(dev);
mt76x0_phy_calibrate(dev, false);
@@ -1012,8 +1012,6 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
 
ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
 MT_CALIBRATE_INTERVAL);
-
-   return 0;
 }
 
 static void mt76x0_phy_temp_sensor(struct mt76x02_dev *dev)
-- 
1.9.3



[PATCH 2/3] mt76: mt76x0: remove redundant chandef copy

2019-08-23 Thread Stanislaw Gruszka
We set dev->mt76.chandef in mt76_set_channel() already.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 31f988e86d92..1d00aa5da95b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -944,7 +944,6 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev,
freq1 = chandef->center_freq1;
channel = chandef->chan->hw_value;
rf_bw_band = (channel <= 14) ? RF_G_BAND : RF_A_BAND;
-   dev->mt76.chandef = *chandef;
 
switch (chandef->width) {
case NL80211_CHAN_WIDTH_40:
-- 
1.9.3



[PATCH 0/3] mt76: channel switch related cleanups

2019-08-23 Thread Stanislaw Gruszka
Stanislaw Gruszka (3):
  mt76: remove redundant mt76_txq_schedule_all
  mt76: mt76x0: remove redundant chandef copy
  mt76: mt76x0: remove unneeded return value on set channel

 drivers/net/wireless/mediatek/mt76/mt7603/mac.c  |  1 -
 drivers/net/wireless/mediatek/mt76/mt7603/main.c |  2 --
 drivers/net/wireless/mediatek/mt76/mt7615/main.c |  1 -
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 15 ---
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h   |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c  |  9 +++--
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c|  1 -
 drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c |  2 --
 drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c |  1 -
 9 files changed, 9 insertions(+), 27 deletions(-)

-- 
1.9.3



[PATCH] mt76: make mt76_rx_convert static

2019-08-23 Thread Stanislaw Gruszka
mt76_rx_convert() not need to be exported any longer.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mac80211.c | 3 +--
 drivers/net/wireless/mediatek/mt76/mt76.h | 2 --
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c 
b/drivers/net/wireless/mediatek/mt76/mac80211.c
index fa481d2f11bd..1a2c143b34d0 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -484,7 +484,7 @@ void mt76_wcid_key_setup(struct mt76_dev *dev, struct 
mt76_wcid *wcid,
 }
 EXPORT_SYMBOL(mt76_wcid_key_setup);
 
-struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb)
+static struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb)
 {
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct mt76_rx_status mstat;
@@ -511,7 +511,6 @@ struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb)
 
return wcid_to_sta(mstat.wcid);
 }
-EXPORT_SYMBOL(mt76_rx_convert);
 
 static int
 mt76_check_ccmp_pn(struct sk_buff *skb)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index d67c6a26c87c..570c159515a0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -749,8 +749,6 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 void __mt76_sta_remove(struct mt76_dev *dev, struct ieee80211_vif *vif,
   struct ieee80211_sta *sta);
 
-struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb);
-
 int mt76_get_min_avg_rssi(struct mt76_dev *dev);
 
 int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-- 
1.9.3



[PATCH] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on tx status

2019-08-23 Thread Stanislaw Gruszka
According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
to be used when we do not recive BA (BlockAck). However on rt2x00 we
use it when remote station fail to decode one or more subframes within
AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
in sent of BAR (BlockAck Request) frame and this might result of abuse
of BA session, since remote station can sent BA with incorrect
sequence numbers after receiving BAR. This problem is visible especially
when connecting two rt2800 devices.

Previously I observed some performance benefits when using the flag
when connecting with iwlwifi devices. But currently possibly due
to reacent changes in rt2x00 removing the flag has no effect on
those test cases.

So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 9d158237ac67..c3eab767bc21 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -371,9 +371,6 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev 
*rt2x00dev,
  IEEE80211_TX_CTL_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
-
-   if (!success)
-   tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
}
 
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-- 
1.9.3



Re: [RFC/RFT v2] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on tx status

2019-08-22 Thread Stanislaw Gruszka
On Fri, Jul 12, 2019 at 12:32:28PM +0200, Stanislaw Gruszka wrote:
> According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
> to be used when we do not receive BA (BlockAck). However on rt2x00 we
> use it when remote station fail to decode one or more subframes within
> AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
> in sent of BAR (BlockAck Request) frame and this might result of abuse
> of BA session, since remote station can sent BA with incorrect
> sequence numbers after receiving BAR. This problem is visible especially
> when connecting two rt2800 devices.
> 
> Previously I observed some performance benefits when using the flag
> when connecting with iwlwifi devices. But currently possibly due
> to recent changes in rt2x00 removing the flag has no effect on
> those test cases.
> 
> So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.
> 
> Additionally partially mimic mt76 behaviour: send BAR when
> starting/stopping BA session to workaround problems with some buggy
> clients. Do not sent BAR on PS wakeup since we lack all PS handling
> code what mt76 has.

Currently Felix posted patch that removed sending BAR on BA session
stop. And I do not see necessity for sending BAR on start, so I will
precede with first version of this patch, that just remove NO_BACK
flag. 

Stanislaw


Re: [PATCH] mt76: remove empty flag in mt76_txq_schedule_list

2019-08-22 Thread Stanislaw Gruszka
On Thu, Aug 22, 2019 at 01:50:52PM +0200, Lorenzo Bianconi wrote:
> > On Thu, Aug 22, 2019 at 11:49:10AM +0200, Lorenzo Bianconi wrote:
> > > Remove empty flag in mt76_txq_schedule_list and mt76_txq_send_burst
> > > since we just need retry_q length to notify mac80211 to reschedule the
> > > current tx queue
> > > 
> > > Signed-off-by: Lorenzo Bianconi 
> > > ---
> > >  drivers/net/wireless/mediatek/mt76/tx.c | 23 +++
> > >  1 file changed, 7 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> > > b/drivers/net/wireless/mediatek/mt76/tx.c
> > > index d7982aa83c11..51d69329ed06 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/tx.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> > > @@ -378,7 +378,7 @@ EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
> > >  
> > >  static int
> > >  mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq,
> > > - struct mt76_txq *mtxq, bool *empty)
> > > + struct mt76_txq *mtxq)
> > >  {
> > >   struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
> > >   enum mt76_txq_id qid = mt76_txq_get_qid(txq);
> > > @@ -392,16 +392,12 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct 
> > > mt76_sw_queue *sq,
> > >   bool probe;
> > >   int idx;
> > >  
> > > - if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
> > > - *empty = true;
> > > + if (test_bit(MT_WCID_FLAG_PS, &wcid->flags))
> > >   return 0;
> > 
> > This changes behaviour for station in PS state. If retry_q is not
> > empty, now we will be rescheduling tx queue for STA in PS mode.
> > Not sure if this is problem or not, though.
> 
> good point..looking at the code it seems not a issue since we will not 
> actually
> tx frames for PS stations. What do you think?

I do not see how changing this could possibly break things, but it 
was explicitly added by below commit, with changelog sugesting it is
needed:

commit d225581df3147060bc99e931b11f7cf2dcb1b2ca
Author: Felix Fietkau 
Date:   Mon Jan 21 17:33:38 2019 +0100

mt76: avoid scheduling tx queues for powersave stations

In case a tx queue wake call arrives after a client has transitioned to
powersave, make sure that the queue is not kept active until the client
has left powersave mode

Stanislaw


Re: [PATCH] mt76: remove empty flag in mt76_txq_schedule_list

2019-08-22 Thread Stanislaw Gruszka
On Thu, Aug 22, 2019 at 11:49:10AM +0200, Lorenzo Bianconi wrote:
> Remove empty flag in mt76_txq_schedule_list and mt76_txq_send_burst
> since we just need retry_q length to notify mac80211 to reschedule the
> current tx queue
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/tx.c | 23 +++
>  1 file changed, 7 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> b/drivers/net/wireless/mediatek/mt76/tx.c
> index d7982aa83c11..51d69329ed06 100644
> --- a/drivers/net/wireless/mediatek/mt76/tx.c
> +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> @@ -378,7 +378,7 @@ EXPORT_SYMBOL_GPL(mt76_release_buffered_frames);
>  
>  static int
>  mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_sw_queue *sq,
> - struct mt76_txq *mtxq, bool *empty)
> + struct mt76_txq *mtxq)
>  {
>   struct ieee80211_txq *txq = mtxq_to_txq(mtxq);
>   enum mt76_txq_id qid = mt76_txq_get_qid(txq);
> @@ -392,16 +392,12 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct 
> mt76_sw_queue *sq,
>   bool probe;
>   int idx;
>  
> - if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) {
> - *empty = true;
> + if (test_bit(MT_WCID_FLAG_PS, &wcid->flags))
>   return 0;

This changes behaviour for station in PS state. If retry_q is not
empty, now we will be rescheduling tx queue for STA in PS mode.
Not sure if this is problem or not, though.

Stanislaw


Re: [PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-21 Thread Stanislaw Gruszka
On Wed, Aug 21, 2019 at 12:40:14PM +0200, Felix Fietkau wrote:
> On 2019-08-21 11:03, Felix Fietkau wrote:
> > On 2019-08-21 10:47, Stanislaw Gruszka wrote:
> >> On Tue, Aug 20, 2019 at 01:24:39PM +0200, Stanislaw Gruszka wrote:
> >>> > Can you test if disabling hw encryption only for shared or only for
> >>> > pairwise keys makes any difference?
> >>> 
> >>> Disabling only pairwise keys helps. Disabling only shared keys does
> >>> not help.
> >>> 
> >>> Not sure if this will be helpful information or make things more
> >>> confusing, but seems the difference between mt76_txq_schedule()
> >>> and tasklet_schedule() in mt76_wake_tx_queue() is that on 
> >>> mt76_txq_schedule() some tx packets are serialized by dev->rx_lock
> >>> (because some ARP and TCP packets are sent via network stack as response
> >>> of incoming packet within ieee80211_rx_napi() call). Removing
> >>> spin_lock(&dev->rx_lock) in mt76_rx_complete() make the problem
> >>> reproducible again with mt76_txq_schedule() & HW encryption.
> >> 
> >> So, I think this is FW/HW issue related with encryption and ordering
> >> and we should apply patch originally posted in this thread that
> >> disable HW encryption for MT7630E.
> >> 
> >> I do not think we should disable HW encryption only for pairwise keys,
> >> because FW/HW can have the same bug for shared keys, but is not
> >> triggered in my test, as we do not sent lot of group frames.
> > I'm still not convinced that this is just the hardware implementation of
> > hw crypto being faulty. I think it's more likely that there's a bug in
> > the tx path somewhere, which causes hangs on MT7630E but remains hidden
> > (or at least recoverable) on other devices.
> > I'm currently reviewing key handling in the mac80211 fast-xmit codepath
> > and get the feeling that something might be racy there.
> > I will let you know when I make some progress with that review.
> > If we can't find the bug soon, then I'm fine with merging this patch.
> > Right now, I would like to see first if we can fix it properly.
> Another question: Does a watchdog restart happen before tx fails?

No, we do not run wdt_work for mt76x0e.

Stanislaw


Re: [PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-21 Thread Stanislaw Gruszka
On Tue, Aug 20, 2019 at 01:24:39PM +0200, Stanislaw Gruszka wrote:
> > Can you test if disabling hw encryption only for shared or only for
> > pairwise keys makes any difference?
> 
> Disabling only pairwise keys helps. Disabling only shared keys does
> not help.
> 
> Not sure if this will be helpful information or make things more
> confusing, but seems the difference between mt76_txq_schedule()
> and tasklet_schedule() in mt76_wake_tx_queue() is that on 
> mt76_txq_schedule() some tx packets are serialized by dev->rx_lock
> (because some ARP and TCP packets are sent via network stack as response
> of incoming packet within ieee80211_rx_napi() call). Removing
> spin_lock(&dev->rx_lock) in mt76_rx_complete() make the problem
> reproducible again with mt76_txq_schedule() & HW encryption.

So, I think this is FW/HW issue related with encryption and ordering
and we should apply patch originally posted in this thread that
disable HW encryption for MT7630E.

I do not think we should disable HW encryption only for pairwise keys,
because FW/HW can have the same bug for shared keys, but is not
triggered in my test, as we do not sent lot of group frames.

Stanislaw


Re: [PATCH 1/1] rt2x00: Queue flush fix

2019-08-21 Thread Stanislaw Gruszka
On Wed, Aug 21, 2019 at 03:43:05AM +0530, Balakrishna Bandi wrote:
> Added rt2x00 queue flush fix and beacon frames checks.

Please post separate patch for each issue and provide
more descriptive information about the changes, especially
what problems are intended to solve.

> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c 
> b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
> index 110bb39..9964371 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
> @@ -566,7 +566,7 @@ void rt2800mmio_queue_init(struct data_queue *queue)
>  
>   switch (queue->qid) {
>   case QID_RX:
> - queue->limit = 128;
> + queue->limit = 512;

How this is related with flush or beaconing ?

At this point of rt2x00 driver development I'm pretty reluctant to
increase queue size. But maybe we can do this for some particular
chip if things were tested on this chip and improve or fix something.

>   if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
>   goto exit_free_skb;
> + /* Dirty hack for queue overrun protection,
> +  * if AC_VO/AC_VI/AC_BE is full, use next queue.
> +  * if AC_BK is full use previous queue.
> +  */

No dirty hacks please.

>  void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
>  {
> + unsigned int i;
> + bool started;
>   bool tx_queue =
>   (queue->qid == QID_AC_VO) ||
>   (queue->qid == QID_AC_VI) ||
>   (queue->qid == QID_AC_BE) ||
>   (queue->qid == QID_AC_BK);
> + mutex_lock(&queue->status_lock);
> + /* If the queue has been started, we must stop it temporarily
> +  * to prevent any new frames to be queued on the device. If
> +  * we are not dropping the pending frames, the queue must
> +  * only be stopped in the software and not the hardware,
> +  * otherwise the queue will never become empty on its own.
> +  */

Since linux 5.2 there is rework done on related area. So maybe flush
issue you are trying to fix by this patch is already fixed. If not let
me know and provide description what is the problem.

> Disclaimer:- The information contained in this electronic message and any 
> attachments to this message are intended for the exclusive use of the 
> addressee(s) and may contain proprietary, confidential or privileged 
> information. If you are not the intended recipient, you should not 
> disseminate, distribute or copy this e-mail. Please notify the sender 
> immediately and destroy all copies of this message and any attachments. The 
> views expressed in this E-mail message (including the enclosure/(s) or 
> attachment/(s) if any) are those of the individual sender, except where the 
> sender expressly, and with authority, states them to be the views of 
> GlobalEdge. Before opening any mail and attachments please check them for 
> viruses .GlobalEdge does not accept any liability for virus infected mails.
> 

You should not sent this disclaimer to open mailing list.
Fix this or use different email service to post patches.

Stanislaw


Re: rt2800: Commit 710e6cc1595e breaks ID 148f:3070 RT2870/RT3070 USB wifi

2019-08-20 Thread Stanislaw Gruszka
On Tue, Aug 20, 2019 at 01:20:50PM +0200, Fredrik Noring wrote:
> Hi Stanislaw,
> 
> Commit 710e6cc1595e ("rt2800: do not nullify initialization vector data")
> breaks USB device 006: ID 148f:3070 Ralink Technology, Corp. RT2870/RT3070
> Wireless Adapter. No particular error messages are produced, but its
> interface becomes unreachable. Reverting this commit in 5.3.0-rc5 solves
> the problem.

Hi, I've recently sent the patch that should fix the problem:
https://lore.kernel.org/linux-wireless/1566213607-6723-1-git-send-email-sgrus...@redhat.com/T/#u

Stanislaw


Re: [PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-20 Thread Stanislaw Gruszka
On Tue, Aug 20, 2019 at 12:31:56PM +0200, Felix Fietkau wrote:
> >> >> void mt76x0e_wake_tx_queue(struct ieee80211_hw *hw, struct 
> >> >> ieee80211_txq *txq)
> >> >> {
> >> >> if (is_mt7630(dev)) {
> >> >> mt76_txq_schedule(dev, txq->ac);
> >> >> } else {
> >> >> tasklet_schedule(&dev->tx_tasklet);
> >> >> }
> >> >> }
> >> > 
> >> > Not sure about reduction of lock contention for which the tx_tasklet
> >> > was introduced here, but looks ok for me as fix.
> >> I think if we work around the bug like this, it can easily come back to
> >> bite us again later. 
> > 
> > I'm not into workarounds any kind, but this is really strange issue,
> > maybe FW bug that triggers just by slightly different driver behaviour.
> > 
> >> I don't see any logical explanation as to how this
> >> makes a difference with hardware encryption.
> >> Also, I think it would be helpful to figure out what key operation (if
> >> any) triggers this, adding or removing keys.
> > 
> > Seems not to be related with set_key operation at all. We set 2 HW
> > keys at the beginning and hang happen after some tx/rx traffic
> > without any re-keyring.
> > 
> > I'm not sure why disabling HW encryption helps. Maybe it is due to
> > ordering or timing. With SW encryption we spend more time in mac80211
> > before pass skb's to the driver. Or maybe we just mix some HW keys 
> > and SW (group) keys in way that FW does not like.
> > 
> >> Maybe it could also help if we change the order in which the WCID table
> >> entries are updated, i.e. changing MT_WCID_ATTR first when removing keys.
> >> 
> >> Maybe temporarily clearing MT_MAC_SYS_CTRL_ENABLE_TX before the key
> >> update and setting it again afterwards could also help.
> > 
> > I tested below patch and it did not help.
> Can you test if disabling hw encryption only for shared or only for
> pairwise keys makes any difference?

Disabling only pairwise keys helps. Disabling only shared keys does
not help.

Not sure if this will be helpful information or make things more
confusing, but seems the difference between mt76_txq_schedule()
and tasklet_schedule() in mt76_wake_tx_queue() is that on 
mt76_txq_schedule() some tx packets are serialized by dev->rx_lock
(because some ARP and TCP packets are sent via network stack as response
of incoming packet within ieee80211_rx_napi() call). Removing
spin_lock(&dev->rx_lock) in mt76_rx_complete() make the problem
reproducible again with mt76_txq_schedule() & HW encryption.

Stanislaw


[PATCH 5.3] rt2x00: clear IV's on start to fix AP mode regression

2019-08-19 Thread Stanislaw Gruszka
To do not brake HW restart we should keep initialization vectors data.
I assumed that on start the data is already initialized to zeros, but
that not true on some scenarios and we should clear it. So add
additional flag to check if we are under HW restart and clear IV's
data if we are not.

Patch fixes AP mode regression.

Reported-and-tested-by: Emil Karlson 
Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c |  9 +
 drivers/net/wireless/ralink/rt2x00/rt2x00.h|  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 13 -
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 4a996550288e..cbec2131e943 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -6095,6 +6095,15 @@ static int rt2800_init_registers(struct rt2x00_dev 
*rt2x00dev)
}
 
/*
+* Clear encryption initialization vectors on start, but keep them
+* for watchdog reset. Otherwise we will have wrong IVs and not be
+* able to keep connections after reset.
+*/
+   if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
+   for (i = 0; i < 256; i++)
+   rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+
+   /*
 * Clear all beacons
 */
for (i = 0; i < 8; i++)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index d35ef06c5c7a..1dd54a0d083d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -659,6 +659,7 @@ enum rt2x00_state_flags {
DEVICE_STATE_ENABLED_RADIO,
DEVICE_STATE_SCANNING,
DEVICE_STATE_FLUSHING,
+   DEVICE_STATE_RESET,
 
/*
 * Driver configuration
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index ad063c920323..c3eab767bc21 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -1253,13 +1253,14 @@ static int rt2x00lib_initialize(struct rt2x00_dev 
*rt2x00dev)
 
 int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 {
-   int retval;
+   int retval = 0;
 
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
/*
 * This is special case for ieee80211_restart_hw(), otherwise
 * mac80211 never call start() two times in row without stop();
 */
+   set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
rt2x00lib_stop(rt2x00dev);
}
@@ -1270,14 +1271,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 */
retval = rt2x00lib_load_firmware(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
/*
 * Initialize the device.
 */
retval = rt2x00lib_initialize(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
@@ -1286,11 +1287,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
/* Enable the radio */
retval = rt2x00lib_enable_radio(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
 
-   return 0;
+out:
+   clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+   return retval;
 }
 
 void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
-- 
1.9.3



Re: [PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-19 Thread Stanislaw Gruszka
On Thu, Aug 15, 2019 at 12:20:54PM +0200, Felix Fietkau wrote:
> On 2019-08-15 12:09, Stanislaw Gruszka wrote:
> >> Hi Stanislaw,
> >> 
> >> Can you please try if disabling/enabling the tx tasklet during hw key
> >> configuration fixes the issue?
> >> Doing something like:
> >> 
> >> tasklet_disable(tx_tasklet)
> >> mt76x02_set_key()
> >> tasklet_enable(tx_tasklet)
> > 
> > It does not help with the problem.
> > 
> >> Moreover, have you double checked if there is any performance impact
> >> of not using hw encryption?
> > 
> > I didn't observe any, but realized on this machine I have
> > aesni_intel encryption accelerator. After rebuild kernel without
> > CONFIG_CRYPTO_AES_NI_INTEL, 'perf top' showed extra 20% of cpu usage
> > in aes_encrypt() when sending data with HW encryption disabled.
> > 
> >> If so, I guess it is better to just redefine mt76_wake_tx_queue for
> >> mt76x0e and run mt76_txq_schedule for 7630e:
> >> 
> >> void mt76x0e_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq 
> >> *txq)
> >> {
> >> if (is_mt7630(dev)) {
> >> mt76_txq_schedule(dev, txq->ac);
> >> } else {
> >> tasklet_schedule(&dev->tx_tasklet);
> >> }
> >> }
> > 
> > Not sure about reduction of lock contention for which the tx_tasklet
> > was introduced here, but looks ok for me as fix.
> I think if we work around the bug like this, it can easily come back to
> bite us again later. 

I'm not into workarounds any kind, but this is really strange issue,
maybe FW bug that triggers just by slightly different driver behaviour.

> I don't see any logical explanation as to how this
> makes a difference with hardware encryption.
> Also, I think it would be helpful to figure out what key operation (if
> any) triggers this, adding or removing keys.

Seems not to be related with set_key operation at all. We set 2 HW
keys at the beginning and hang happen after some tx/rx traffic
without any re-keyring.

I'm not sure why disabling HW encryption helps. Maybe it is due to
ordering or timing. With SW encryption we spend more time in mac80211
before pass skb's to the driver. Or maybe we just mix some HW keys 
and SW (group) keys in way that FW does not like.

> Maybe it could also help if we change the order in which the WCID table
> entries are updated, i.e. changing MT_WCID_ATTR first when removing keys.
> 
> Maybe temporarily clearing MT_MAC_SYS_CTRL_ENABLE_TX before the key
> update and setting it again afterwards could also help.

I tested below patch and it did not help.

Stanislaw

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 82bafb5ac326..846652f2b3f1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -105,11 +105,14 @@ int mt76x02_mac_wcid_set_key(struct mt76x02_dev *dev, u8 
idx,
if (cipher == MT_CIPHER_NONE && key)
return -EOPNOTSUPP;
 
+   if (!key)
+   mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, 
MT_CIPHER_NONE);
+
mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
-   mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, cipher);
 
memset(iv_data, 0, sizeof(iv_data));
if (key) {
+   mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, 
cipher);
mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE,
   !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index fa45ed280ab1..6f624e3329f9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -391,7 +391,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 }
 EXPORT_SYMBOL_GPL(mt76x02_ampdu_action);
 
-int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+int __mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
 {
@@ -466,6 +466,35 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum 
set_key_cmd cmd,
 
return mt76x02_mac_wcid_set_key(dev, msta->wcid.idx, key);
 }
+
+int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+   struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+   struct ieee80211_key_conf *key)
+

Re: Ap mode regression in linux-5.3-rc1 in rt2800usb

2019-08-16 Thread Stanislaw Gruszka
On Fri, Aug 16, 2019 at 11:00:12AM +0300, Emil Karlson wrote:
> Greetings
> 
> On Wed, 14 Aug 2019 10:50:19 +0200
> Stanislaw Gruszka  wrote:
> 
> > (cc linux-wireless mailing list)
> > 
> > On Tue, Aug 13, 2019 at 09:50:00PM +0300, Emil Karlson wrote:
> > > Greetings
> > > 
> > > After upgrading my ap running rt2800usb to linux-5.3-rc1 I noticed
> > > an unusual problem of not being able to connect to my ap with my
> > > android devices (nexus7/flo and nexus5x/bullhead), from tcpdump it
> > > seemed ap was receiving packets from the android devices after
> > > successful association, but android devices were not seeing the
> > > dhcp replies.
> > > 
> > > I reverted drivers/net/wireless/ralink to the state it is in v5.2.8
> > > and android clients can connect again normally. I did not
> > > explicitly set watchdog parameter to any value.
> 
> > Most suspicious are 710e6cc1595e and 41a531ffa4c5 .
> 
> It seems to me that reverting only
> 710e6cc1595e25378c4b9977f7a8b4ad4a72a109
> allows all my android devices to successfully connect to the internet.

Please test attached patch as proposed fix for
710e6cc1595e25378c4b9977f7a8b4ad4a72a109 and report back. Thanks.

Stanislaw
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 4a996550288e..cbec2131e943 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -6095,6 +6095,15 @@ static int rt2800_init_registers(struct rt2x00_dev 
*rt2x00dev)
}
 
/*
+* Clear encryption initialization vectors on start, but keep them
+* for watchdog reset. Otherwise we will have wrong IVs and not be
+* able to keep connections after reset.
+*/
+   if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags))
+   for (i = 0; i < 256; i++)
+   rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+
+   /*
 * Clear all beacons
 */
for (i = 0; i < 8; i++)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index d35ef06c5c7a..1dd54a0d083d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -659,6 +659,7 @@ enum rt2x00_state_flags {
DEVICE_STATE_ENABLED_RADIO,
DEVICE_STATE_SCANNING,
DEVICE_STATE_FLUSHING,
+   DEVICE_STATE_RESET,
 
/*
 * Driver configuration
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index ad063c920323..c3eab767bc21 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -1253,13 +1253,14 @@ static int rt2x00lib_initialize(struct rt2x00_dev 
*rt2x00dev)
 
 int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 {
-   int retval;
+   int retval = 0;
 
if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) {
/*
 * This is special case for ieee80211_restart_hw(), otherwise
 * mac80211 never call start() two times in row without stop();
 */
+   set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev);
rt2x00lib_stop(rt2x00dev);
}
@@ -1270,14 +1271,14 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
 */
retval = rt2x00lib_load_firmware(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
/*
 * Initialize the device.
 */
retval = rt2x00lib_initialize(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
rt2x00dev->intf_ap_count = 0;
rt2x00dev->intf_sta_count = 0;
@@ -1286,11 +1287,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
/* Enable the radio */
retval = rt2x00lib_enable_radio(rt2x00dev);
if (retval)
-   return retval;
+   goto out;
 
set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
 
-   return 0;
+out:
+   clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags);
+   return retval;
 }
 
 void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)


Re: [PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-15 Thread Stanislaw Gruszka
On Wed, Aug 14, 2019 at 11:50:12AM +0200, Lorenzo Bianconi wrote:
> >
> > Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
> > I can observe firmware hangs on MT7630E on station mode: tx stop
> > functioning after minor activity (rx keep working) and on module
> > unload device fail to stop with messages:
> >
> > [ 5446.141413] mt76x0e :06:00.0: TX DMA did not stop
> > [ 5449.176764] mt76x0e :06:00.0: TX DMA did not stop
> >
> > Loading module again results in failure to associate with AP.
> > Only machine power off / power on cycle can make device work again.
> >
> > It's unclear why commit 41634aa8d6db causes the problem, but it is
> > related to HW encryption. Since issue is a firmware hang, that is super
> > hard to debug, just disable HW encryption as fix for the issue.
> >
> > Fixes: 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
> > Signed-off-by: Stanislaw Gruszka 
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 15 ++-
> >  1 file changed, 14 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c 
> > b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
> > index 4585e1b756c2..6117e6ca08cb 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
> > @@ -62,6 +62,19 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
> > mt76x0e_stop_hw(dev);
> >  }
> >
> > +static int
> > +mt76x0e_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
> > +   struct ieee80211_vif *vif, struct ieee80211_sta *sta,
> > +   struct ieee80211_key_conf *key)
> > +{
> > +   struct mt76x02_dev *dev = hw->priv;
> > +
> > +   if (is_mt7630(dev))
> > +   return -EOPNOTSUPP;
> 
> Hi Stanislaw,
> 
> Can you please try if disabling/enabling the tx tasklet during hw key
> configuration fixes the issue?
> Doing something like:
> 
> tasklet_disable(tx_tasklet)
> mt76x02_set_key()
> tasklet_enable(tx_tasklet)

It does not help with the problem.

> Moreover, have you double checked if there is any performance impact
> of not using hw encryption?

I didn't observe any, but realized on this machine I have
aesni_intel encryption accelerator. After rebuild kernel without
CONFIG_CRYPTO_AES_NI_INTEL, 'perf top' showed extra 20% of cpu usage
in aes_encrypt() when sending data with HW encryption disabled.

> If so, I guess it is better to just redefine mt76_wake_tx_queue for
> mt76x0e and run mt76_txq_schedule for 7630e:
> 
> void mt76x0e_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
> {
> if (is_mt7630(dev)) {
> mt76_txq_schedule(dev, txq->ac);
> } else {
> tasklet_schedule(&dev->tx_tasklet);
> }
> }

Not sure about reduction of lock contention for which the tx_tasklet
was introduced here, but looks ok for me as fix.
 
Stanislaw


Re: [PATCH 5.3] mt76: mt76x0e: disable 5GHz band for MT7630E

2019-08-14 Thread Stanislaw Gruszka
On Tue, Aug 13, 2019 at 05:55:26PM +, Sasha Levin wrote:
> Hi,
> 
> [This is an automated email]
> 
> This commit has been processed because it contains a -stable tag.
> The stable tag indicates that it's relevant for the following trees: all
> 
> The bot has tested the following trees: v5.2.8, v4.19.66, v4.14.138, 
> v4.9.189, v4.4.189.
> 
> v5.2.8: Build OK!
> v4.19.66: Failed to apply! Possible dependencies:
> 86c71d3deefa ("mt76: move eeprom utility routines in mt76x02_eeprom.h")
> d6500cf3700f ("mt76x0: add quirk to disable 2.4GHz band for Archer T1U")
> eef40d209ad0 ("mt76: move common eeprom definitions in mt76x02-lib 
> module")

> NOTE: The patch will not be queued to stable trees until it is upstream.
> 
> How should we proceed with this patch?

mt76x0e support was added in 4.20 , so it's fine just to apply this
commit in 5.2 .

Stanislaw 


Re: Ap mode regression in linux-5.3-rc1 in rt2800usb

2019-08-14 Thread Stanislaw Gruszka
(cc linux-wireless mailing list)

On Tue, Aug 13, 2019 at 09:50:00PM +0300, Emil Karlson wrote:
> Greetings
> 
> After upgrading my ap running rt2800usb to linux-5.3-rc1 I noticed an
> unusual problem of not being able to connect to my ap with my android
> devices (nexus7/flo and nexus5x/bullhead), from tcpdump it seemed ap
> was receiving packets from the android devices after successful
> association, but android devices were not seeing the dhcp replies.
> 
> I reverted drivers/net/wireless/ralink to the state it is in v5.2.8 and
> android clients can connect again normally. I did not explicitly set
> watchdog parameter to any value.
> 
> Do you have any insights or is this already fixed?

Most likely is not fixed. We have those new commits in 5.3:

41a531ffa4c5 rt2x00usb: fix rx queue hang
0f47aeeada2a rt2800: do not enable watchdog by default
e403fa31ed71 rt2x00: add restart hw
710e6cc1595e rt2800: do not nullify initialization vector data
09db3b000619 rt2800: add pre_reset_hw callback
759c5b599cf4 rt2800: initial watchdog implementation
2034afe4db4a rt2800: add helpers for reading dma done index
9f3e3323e996 rt2x00: allow to specify watchdog interval

Most suspicious are 710e6cc1595e and 41a531ffa4c5 .

Could you test by reverting one single commit on 5.3
(first 710e6cc1595e and if that not help 41a531ffa4c5)
and check if it makes the problem gone?

Stanislaw


[PATCH 5.3] mt76: mt76x0e: disable 5GHz band for MT7630E

2019-08-13 Thread Stanislaw Gruszka
MT7630E hardware does support 5GHz, but we do not properly configure phy
for 5GHz channels. Scanning at this band not only do not show any APs
but also can hang the firmware.

Since vendor reference driver do not support 5GHz we don't know how
properly configure 5GHz channels. So disable this band for MT7630E .

Cc: sta...@vger.kernel.org
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index ab6dfc026acb..36918b1bd653 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -67,6 +67,11 @@ static void mt76x0_set_chip_cap(struct mt76x02_dev *dev)
dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
}
 
+   if (is_mt7630(dev)) {
+   dev->mt76.cap.has_5ghz = false;
+   dev_dbg(dev->mt76.dev, "mask out 5GHz support\n");
+   }
+
if (!mt76x02_field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
 
-- 
1.9.3



[PATCH 5.3] mt76: mt76x0e: don't use hw encryption for MT7630E

2019-08-13 Thread Stanislaw Gruszka
Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
I can observe firmware hangs on MT7630E on station mode: tx stop
functioning after minor activity (rx keep working) and on module
unload device fail to stop with messages:

[ 5446.141413] mt76x0e :06:00.0: TX DMA did not stop
[ 5449.176764] mt76x0e :06:00.0: TX DMA did not stop

Loading module again results in failure to associate with AP.
Only machine power off / power on cycle can make device work again.

It's unclear why commit 41634aa8d6db causes the problem, but it is
related to HW encryption. Since issue is a firmware hang, that is super
hard to debug, just disable HW encryption as fix for the issue.

Fixes: 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index 4585e1b756c2..6117e6ca08cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -62,6 +62,19 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
mt76x0e_stop_hw(dev);
 }
 
+static int
+mt76x0e_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+   struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+   struct ieee80211_key_conf *key)
+{
+   struct mt76x02_dev *dev = hw->priv;
+
+   if (is_mt7630(dev))
+   return -EOPNOTSUPP;
+
+   return mt76x02_set_key(hw, cmd, vif, sta, key);
+}
+
 static void
 mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  u32 queues, bool drop)
@@ -78,7 +91,7 @@ static void mt76x0e_stop(struct ieee80211_hw *hw)
.configure_filter = mt76x02_configure_filter,
.bss_info_changed = mt76x02_bss_info_changed,
.sta_state = mt76_sta_state,
-   .set_key = mt76x02_set_key,
+   .set_key = mt76x0e_set_key,
.conf_tx = mt76x02_conf_tx,
.sw_scan_start = mt76x02_sw_scan,
.sw_scan_complete = mt76x02_sw_scan_complete,
-- 
1.9.3



Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-08-12 Thread Stanislaw Gruszka
On Mon, Aug 05, 2019 at 02:39:16PM +0200, Stanislaw Gruszka wrote:
> On Mon, Aug 05, 2019 at 01:27:19PM +0200, Lorenzo Bianconi wrote:
> > > ... but I think we have bug when do mt76_txq_schedule_all() in
> > > tx_tasklet, because we can schedule on queues that are stoped.
> > > So reverting 41634aa8d6db and then optimize by removing tx_tasklet
> > > for mmio and remove not needed mt76_txq_schedule_all() calls looks
> > > more reasoneble to me.
> > 
> > schedule a stopped queue seems not harmful at a first glance since we do not
> > copy pending skbs if we have not enough room in the dma ring.
> 
> mac80211 stop queues for various other reasons than 
> IEEE80211_QUEUE_STOP_REASON_DRIVER .

After looking in more details, we check if queue is stopped in 
ieee80211_tx_dequeue(). But we do not check that for skb's queued
in mtxq->retry_q .

> > diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> > b/drivers/net/wireless/mediatek/mt76/tx.c
> > index 5397827668b9..bd2d34c4f326 100644
> > --- a/drivers/net/wireless/mediatek/mt76/tx.c
> > +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> > @@ -495,6 +495,9 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum 
> > mt76_txq_id qid)
> > while (1) {
> > bool empty = false;
> >  
> > +   if (hwq->stopped)
> > +   break;
> > +
> > if (sq->swq_queued >= 4)
> > break;
> > 
> > Does it fix the issue you are facing?
> 
> I'll not be able to test this patch this week. Will have access to
> the hardware next week. 
> 
> I checeked before, if
> 'q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1' is triggered
> when MT7630E hangs and it is not. But maybe second part of the patch
> will help.

Patch did not help.

I debugged problem a bit more and issue is related with HW encryption.
Using full mac80211 SW encyption by retuning -EOPNOTSUPP
mt76x02_set_key() make the problem gone as well. Looks there is
some race between setting HW keys and transmitting.

Stanislaw


Re: [PATCH] mt76: mt76x02u: enable multi-vif support

2019-08-12 Thread Stanislaw Gruszka
On Mon, Aug 05, 2019 at 01:08:15PM +0200, Lorenzo Bianconi wrote:
> >
> > On Fri, Aug 02, 2019 at 04:36:20PM +0200, Lorenzo Bianconi wrote:
> > > Enable multi-interface support for mt76x02u driver. For the moment
> > > allow max two concurrent interfaces in order to preserve enough room
> > > for ps traffic since we are using beacon slots for it.
> > > I have successfully tested the following configuration:
> > > - AP + STA
> > > - AP0 + AP1
> >
> > The combination that did not work in my testing was STA + STA .
> > This should be fixed or disabled.
> >
> 
> Hi Stanislaw,
> 
> I have just tested STA/STA configuration and it works in my setup.

Confirmed, it works for me as well on current code base.

Tested-by: Stanislaw Gruszka 


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-08-05 Thread Stanislaw Gruszka
On Mon, Aug 05, 2019 at 01:27:19PM +0200, Lorenzo Bianconi wrote:
> > ... but I think we have bug when do mt76_txq_schedule_all() in
> > tx_tasklet, because we can schedule on queues that are stoped.
> > So reverting 41634aa8d6db and then optimize by removing tx_tasklet
> > for mmio and remove not needed mt76_txq_schedule_all() calls looks
> > more reasoneble to me.
> 
> schedule a stopped queue seems not harmful at a first glance since we do not
> copy pending skbs if we have not enough room in the dma ring.

mac80211 stop queues for various other reasons than 
IEEE80211_QUEUE_STOP_REASON_DRIVER .
 
> Maybe we can be
> more conservative doing something like:
>
> diff --git a/drivers/net/wireless/mediatek/mt76/dma.c 
> b/drivers/net/wireless/mediatek/mt76/dma.c
> index d8f61e540bfd..c6482155e5e4 100644
> --- a/drivers/net/wireless/mediatek/mt76/dma.c
> +++ b/drivers/net/wireless/mediatek/mt76/dma.c
> @@ -346,6 +346,11 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, enum 
> mt76_txq_id qid,
>   goto unmap;
>  
>   if (q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1) {
> + if (!q->stopped) {
> + ieee80211_stop_queue(dev->hw,
> +  skb_get_queue_mapping(skb));
> + q->stopped = true;
> + }
>   ret = -ENOMEM;
>   goto unmap;
>   }
> diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> b/drivers/net/wireless/mediatek/mt76/tx.c
> index 5397827668b9..bd2d34c4f326 100644
> --- a/drivers/net/wireless/mediatek/mt76/tx.c
> +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> @@ -495,6 +495,9 @@ mt76_txq_schedule_list(struct mt76_dev *dev, enum 
> mt76_txq_id qid)
>   while (1) {
>   bool empty = false;
>  
> + if (hwq->stopped)
> + break;
> +
>   if (sq->swq_queued >= 4)
>   break;
> 
> Does it fix the issue you are facing?

I'll not be able to test this patch this week. Will have access to
the hardware next week. 

I checeked before, if
'q->queued + (tx_info.nbuf + 1) / 2 >= q->ndesc - 1' is triggered
when MT7630E hangs and it is not. But maybe second part of the patch
will help.

Stanislaw


Re: rt2x00usb warning while channel hopping

2019-08-05 Thread Stanislaw Gruszka
On Thu, Aug 01, 2019 at 12:43:26PM -0400, Sid Hayn wrote:
> While testing wireless-testing kernel for some other fixes, I
> encountered this warning.  I have a few different chipsets and drivers
> all channel hopping in monitor mode on the test box, but I get this
> warning from rt2x00 over and over again (lots).  I am testing two
> patches from johill on top of wireless testing, I don't believe they
> are causing this, but I'll include them for completeness.
> 
> https://patchwork.kernel.org/patch/11063915/
> https://patchwork.kernel.org/patch/11069625/

The way to find out is drop those patches and see if the warning
is still there. But it still can be rt2x00 problem that is only
triggered with those patches, so let's try to debug. 
   
> I'm happy to test anything required, although I will be traveling next
> week which may cause delays.


> [  170.055276] [ cut here ]
> [  170.055305] WARNING: CPU: 3 PID: 5777 at
> rt2x00lib_config.cold.0+0xc/0x2a [rt2x00lib]

This seems to be warning at rt2x00ht_center_channel() in:

for (i = 0; i < spec->num_channels; i++)
if (spec->channels[i].channel == center_channel)
return i;

WARN_ON(1);
return conf->chandef.chan->hw_value;

So looks like we set channel that is not specified in rt2800 channels
table. Not sure at the moment if mac80211 provide wrong channel spec or
rt2x00 do something wrong. Please apply below patch and provide prints.

Stanislaw

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
index 0ee1813e8453..5f6dadef9f7c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
@@ -185,7 +185,11 @@ static u16 rt2x00ht_center_channel(struct rt2x00_dev 
*rt2x00dev,
if (spec->channels[i].channel == center_channel)
return i;
 
-   WARN_ON(1);
+   WARN_ONCE(1, "hw_value %d channel %d center_channel %d\n",
+ conf->chandef.chan->hw_value,
+ spec->channels[conf->chandef.chan->hw_value].channel,
+ center_channel);
+
return conf->chandef.chan->hw_value;
 }
 


Re: [PATCH] mt76: mt76x02u: enable multi-vif support

2019-08-05 Thread Stanislaw Gruszka
On Fri, Aug 02, 2019 at 04:36:20PM +0200, Lorenzo Bianconi wrote:
> Enable multi-interface support for mt76x02u driver. For the moment
> allow max two concurrent interfaces in order to preserve enough room
> for ps traffic since we are using beacon slots for it.
> I have successfully tested the following configuration:
> - AP + STA
> - AP0 + AP1

The combination that did not work in my testing was STA + STA .
This should be fixed or disabled.

Stanislaw
 


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-08-05 Thread Stanislaw Gruszka
On Wed, Jul 31, 2019 at 11:09:27AM +0200, Lorenzo Bianconi wrote:
> > On Wed, Jul 31, 2019 at 10:19:58AM +0200, Stanislaw Gruszka wrote:
> > > On Tue, Jul 30, 2019 at 04:55:31PM +0200, Lorenzo Bianconi wrote:
> > > > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
> > > > > > > b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > > > index 467b28379870..622251faa415 100644
> > > > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > > > @@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct 
> > > > > > > *napi, int budget)
> > > > > > >  mt76.tx_napi);
> > > > > > >   int i;
> > > > > > >  
> > > > > > > - mt76x02_mac_poll_tx_status(dev, false);
> > > > > > > + mt76x02_mac_poll_tx_status(dev, true);
> > > > > > 
> > > > > > I am not sure if we really need mt76x02_mac_poll_tx_status() here 
> > > > > > since we run
> > > > > > it in mt76x02_tx_complete_skb() and in mt76x02_tx_tasklet(). Anyway 
> > > > > > the only
> > > > > > difference doing so is we do not run mt76x02_send_tx_status().
> > > > > 
> > > > > I thought this is the problem, but it was my mistake during testing.
> > > > > I tested the above change together with mt76_txq_schedule(dev, 
> > > > > txq->ac)
> > > > > change and get wrong impression it fixes the issue. But above change
> > > > > alone does not help.
> > > > > 
> > > > > I tried to add some locking to avoid parallel execution of 
> > > > > mt76x02_poll_tx()
> > > > > and mt76x02_tx_tasklet(), but it didn't help either. So far only patch
> > > > > originally posted here make the problem gone.
> > > > 
> > > > so, in order to be on the same page, if you comment out 
> > > > mt76x02_mac_poll_tx_status()
> > > > in mt76x02_poll_tx() the issue will still occur. The only to 'fix' it 
> > > > is to run
> > > > mt76_txq_schedule_all() in mt76x02_poll_tx(), right?
> > > 
> > > Yes.
> > 
> > Err, no, I should read more cerfully. It is partiall revert of 
> > 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet") : 
> > 
> > diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> > b/drivers/net/wireless/mediatek/mt76/tx.c
> > index 5397827668b9..fefe0ee52584 100644
> > --- a/drivers/net/wireless/mediatek/mt76/tx.c
> > +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> > @@ -598,7 +598,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct 
> > ieee80211_txq *txq)
> > if (!test_bit(MT76_STATE_RUNNING, &dev->state))
> > return;
> >  
> > -   tasklet_schedule(&dev->tx_tasklet);
> > +   mt76_txq_schedule(dev, txq->ac);
> >  }
> >  EXPORT_SYMBOL_GPL(mt76_wake_tx_queue);
> 
> reviewing the code I think:
> 
> - we should not run mt76u_tx_tasklet() from mt76_wake_tx_queue() since we do
>   not have tx_napi for usb and it will unnecessary go through tx queue checks.
>   We should probably do in mt76_wake_tx_queue() something like:
> 
>   if (is_mmio())

Adding '&& !is_mt7630()' will solve the problem for MT7630E as well ...

> tasklet_schedule(&dev->tx_tasklet);
>   else
> mt76_txq_schedule(dev, txq->ac);
> 
>   Another solution would be add a status_tasklet that just goes through the tx
>   queues receiving the usb tx completion and it schedules the tx_tasklet
>   What do you think?
> 
> - I guess it does not fix the 76x0e issue but we should just schedule tx 
> queues in
>   mt76x02_tx_tasklet() (like it is done for mt7603 and mt7615) and move status
>   processing in mt76x02_poll_tx()

... but I think we have bug when do mt76_txq_schedule_all() in
tx_tasklet, because we can schedule on queues that are stoped.
So reverting 41634aa8d6db and then optimize by removing tx_tasklet
for mmio and remove not needed mt76_txq_schedule_all() calls looks
more reasoneble to me.
 
Stanislaw 


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-07-31 Thread Stanislaw Gruszka
On Wed, Jul 31, 2019 at 10:19:58AM +0200, Stanislaw Gruszka wrote:
> On Tue, Jul 30, 2019 at 04:55:31PM +0200, Lorenzo Bianconi wrote:
> > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
> > > > > b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > index 467b28379870..622251faa415 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > > @@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct 
> > > > > *napi, int budget)
> > > > >  mt76.tx_napi);
> > > > >   int i;
> > > > >  
> > > > > - mt76x02_mac_poll_tx_status(dev, false);
> > > > > + mt76x02_mac_poll_tx_status(dev, true);
> > > > 
> > > > I am not sure if we really need mt76x02_mac_poll_tx_status() here since 
> > > > we run
> > > > it in mt76x02_tx_complete_skb() and in mt76x02_tx_tasklet(). Anyway the 
> > > > only
> > > > difference doing so is we do not run mt76x02_send_tx_status().
> > > 
> > > I thought this is the problem, but it was my mistake during testing.
> > > I tested the above change together with mt76_txq_schedule(dev, txq->ac)
> > > change and get wrong impression it fixes the issue. But above change
> > > alone does not help.
> > > 
> > > I tried to add some locking to avoid parallel execution of 
> > > mt76x02_poll_tx()
> > > and mt76x02_tx_tasklet(), but it didn't help either. So far only patch
> > > originally posted here make the problem gone.
> > 
> > so, in order to be on the same page, if you comment out 
> > mt76x02_mac_poll_tx_status()
> > in mt76x02_poll_tx() the issue will still occur. The only to 'fix' it is to 
> > run
> > mt76_txq_schedule_all() in mt76x02_poll_tx(), right?
> 
> Yes.

Err, no, I should read more cerfully. It is partiall revert of 
41634aa8d6db ("mt76: only schedule txqs from the tx tasklet") : 

diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
b/drivers/net/wireless/mediatek/mt76/tx.c
index 5397827668b9..fefe0ee52584 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -598,7 +598,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct 
ieee80211_txq *txq)
if (!test_bit(MT76_STATE_RUNNING, &dev->state))
return;
 
-   tasklet_schedule(&dev->tx_tasklet);
+   mt76_txq_schedule(dev, txq->ac);
 }
 EXPORT_SYMBOL_GPL(mt76_wake_tx_queue);


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-07-31 Thread Stanislaw Gruszka
On Tue, Jul 30, 2019 at 04:55:31PM +0200, Lorenzo Bianconi wrote:
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
> > > > b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > index 467b28379870..622251faa415 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > > > @@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct 
> > > > *napi, int budget)
> > > >mt76.tx_napi);
> > > > int i;
> > > >  
> > > > -   mt76x02_mac_poll_tx_status(dev, false);
> > > > +   mt76x02_mac_poll_tx_status(dev, true);
> > > 
> > > I am not sure if we really need mt76x02_mac_poll_tx_status() here since 
> > > we run
> > > it in mt76x02_tx_complete_skb() and in mt76x02_tx_tasklet(). Anyway the 
> > > only
> > > difference doing so is we do not run mt76x02_send_tx_status().
> > 
> > I thought this is the problem, but it was my mistake during testing.
> > I tested the above change together with mt76_txq_schedule(dev, txq->ac)
> > change and get wrong impression it fixes the issue. But above change
> > alone does not help.
> > 
> > I tried to add some locking to avoid parallel execution of mt76x02_poll_tx()
> > and mt76x02_tx_tasklet(), but it didn't help either. So far only patch
> > originally posted here make the problem gone.
> 
> so, in order to be on the same page, if you comment out 
> mt76x02_mac_poll_tx_status()
> in mt76x02_poll_tx() the issue will still occur. The only to 'fix' it is to 
> run
> mt76_txq_schedule_all() in mt76x02_poll_tx(), right?

Yes.

Stanislaw


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-07-30 Thread Stanislaw Gruszka
On Mon, Jul 29, 2019 at 04:02:41PM +0200, Lorenzo Bianconi wrote:
> > On Fri, Jul 26, 2019 at 02:10:56PM +0200, Stanislaw Gruszka wrote:
> > > Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
> > > I can observe firmware hangs on MT7630E on station mode: tx stop
> > > functioning after minor activity (rx keep working) and on module
> > > unload device fail to stop with messages:
> > > 
> > > [ 5446.141413] mt76x0e :06:00.0: TX DMA did not stop
> > > [ 5449.176764] mt76x0e :06:00.0: TX DMA did not stop
> > > 
> > > Loading module again results in failure to associate with AP.
> > > Only machine power off / power on cycle can make device work again.
> > > 
> > > I have no idea why the commit caused F/W hangs. Most likely some proper
> > > fix is needed of changing registers programming (or assuring proper order
> > > of actions), but so far I can not came up with any better fix than
> > > a partial revert of 41634aa8d6db.
> > 
> > The difference is that with 41634aa8d6db we can run mt76x02_poll_tx()
> > and mt76x02_tx_tasklet() in parallel on 2 different CPUs. Without
> > the commit, since tasklet is not scheduled from mt76_wake_tx_queue(),
> > it does not happen.
> > 
> > I'm not quite sure why, but MT7630E does not like when we poll tx status
> > on 2 cpus at once. Change like below:
> 
> Hi Stanislaw,

Hi

> have you tried to look at the commit: 6fe533378795f87
> ("mt76: mt76x02: remove irqsave/restore in locking for tx status fifo")?
> Could it be a race between a registermap update and a stats load? (we are 
> using a
> different lock now)

This commit seems to be fine, reverting it did not solve the issue.

> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
> > b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > index 467b28379870..622251faa415 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
> > @@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct *napi, 
> > int budget)
> >mt76.tx_napi);
> > int i;
> >  
> > -   mt76x02_mac_poll_tx_status(dev, false);
> > +   mt76x02_mac_poll_tx_status(dev, true);
> 
> I am not sure if we really need mt76x02_mac_poll_tx_status() here since we run
> it in mt76x02_tx_complete_skb() and in mt76x02_tx_tasklet(). Anyway the only
> difference doing so is we do not run mt76x02_send_tx_status().

I thought this is the problem, but it was my mistake during testing.
I tested the above change together with mt76_txq_schedule(dev, txq->ac)
change and get wrong impression it fixes the issue. But above change
alone does not help.

I tried to add some locking to avoid parallel execution of mt76x02_poll_tx()
and mt76x02_tx_tasklet(), but it didn't help either. So far only patch
originally posted here make the problem gone.

Stanislaw



Re: [PATCH v2 5/5] rtw88: add BT co-existence support

2019-07-29 Thread Stanislaw Gruszka
On Tue, Jul 30, 2019 at 03:13:35AM +, Tony Chuang wrote:
> > Those coex response skb buffers are allocated in rtw_pci_rx_isr(),
> > but I do not see where they are freed (seems we do not process
> > them in c2h_work which does dev_kfree_skb()).
> 
> You're right, that SKB leaked. Should free them after responded.
> I will send v2 to fix it :)

FWIW maybe would be better to process coex commands entairly in
c2h_work ? Not sure if that would work or really would be better,
just an idea you can consider :-) 

Stanislaw


Re: [RFC] mt76: fix tx hung regression on MT7630E

2019-07-29 Thread Stanislaw Gruszka
On Fri, Jul 26, 2019 at 02:10:56PM +0200, Stanislaw Gruszka wrote:
> Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
> I can observe firmware hangs on MT7630E on station mode: tx stop
> functioning after minor activity (rx keep working) and on module
> unload device fail to stop with messages:
> 
> [ 5446.141413] mt76x0e :06:00.0: TX DMA did not stop
> [ 5449.176764] mt76x0e :06:00.0: TX DMA did not stop
> 
> Loading module again results in failure to associate with AP.
> Only machine power off / power on cycle can make device work again.
> 
> I have no idea why the commit caused F/W hangs. Most likely some proper
> fix is needed of changing registers programming (or assuring proper order
> of actions), but so far I can not came up with any better fix than
> a partial revert of 41634aa8d6db.

The difference is that with 41634aa8d6db we can run mt76x02_poll_tx()
and mt76x02_tx_tasklet() in parallel on 2 different CPUs. Without
the commit, since tasklet is not scheduled from mt76_wake_tx_queue(),
it does not happen.

I'm not quite sure why, but MT7630E does not like when we poll tx status
on 2 cpus at once. Change like below:

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 467b28379870..622251faa415 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -170,7 +170,7 @@ static int mt76x02_poll_tx(struct napi_struct *napi, int 
budget)
   mt76.tx_napi);
int i;
 
-   mt76x02_mac_poll_tx_status(dev, false);
+   mt76x02_mac_poll_tx_status(dev, true);
 
for (i = MT_TXQ_MCU; i >= 0; i--)
mt76_queue_tx_cleanup(dev, i, false);

is sufficient to avoid the hangs.

> diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
> b/drivers/net/wireless/mediatek/mt76/tx.c
> index 5397827668b9..fefe0ee52584 100644
> --- a/drivers/net/wireless/mediatek/mt76/tx.c
> +++ b/drivers/net/wireless/mediatek/mt76/tx.c
> @@ -598,7 +598,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct 
> ieee80211_txq *txq)
>   if (!test_bit(MT76_STATE_RUNNING, &dev->state))
>   return;
>  
> - tasklet_schedule(&dev->tx_tasklet);
> + mt76_txq_schedule(dev, txq->ac);

However I'm not sure if change to tasklet_schedule() is indeed correct,
since on tasklet we schedule all queues, hence queues that could
possibly be still blocked? And on mt76_wake_tx_queue() we schedule only
one queue.

Stanislaw


Re: [PATCH v2 5/5] rtw88: add BT co-existence support

2019-07-29 Thread Stanislaw Gruszka
On Thu, Jul 25, 2019 at 10:53:31AM +0800, yhchu...@realtek.com wrote:
> +static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
> +  struct rtw_coex_info_req *req)
> +{
> + struct rtw_coex *coex = &rtwdev->coex;
> + struct sk_buff *skb_resp = NULL;
> +
> + mutex_lock(&coex->mutex);
> +
> + rtw_fw_query_bt_mp_info(rtwdev, req);
> +
> + if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
> + COEX_REQUEST_TIMEOUT)) {
> + rtw_err(rtwdev, "coex request time out\n");
> + goto out;
> + }
> +
> + skb_resp = skb_dequeue(&coex->queue);
> + if (!skb_resp) {
> + rtw_err(rtwdev, "failed to get coex info response\n");
> + goto out;
> + }
> +
> +out:
> + mutex_unlock(&coex->mutex);
> + return skb_resp;
> +}
> +
> +static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
> +{
> + struct rtw_coex_info_req req = {0};
> + struct sk_buff *skb;
> + u8 *payload;
> + bool ret = false;
> +
> + req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
> + skb = rtw_coex_info_request(rtwdev, &req);
> + if (!skb)
> + goto out;
> +
> + payload = get_payload_from_coex_resp(skb);
> + *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
> + ret = true;
> +
> +out:
> + return ret;
> +}
> +
> +static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
> +  u8 lna_constrain_level)
> +{
> + struct rtw_coex_info_req req = {0};
> + struct sk_buff *skb;
> + bool ret = false;
> +
> + req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
> + req.para1 = lna_constrain_level;
> + skb = rtw_coex_info_request(rtwdev, &req);
> + if (!skb)
> + goto out;

Those coex response skb buffers are allocated in rtw_pci_rx_isr(),
but I do not see where they are freed (seems we do not process
them in c2h_work which does dev_kfree_skb()).

Stanislaw


[RFC] mt76: fix tx hung regression on MT7630E

2019-07-26 Thread Stanislaw Gruszka
Since 41634aa8d6db ("mt76: only schedule txqs from the tx tasklet")
I can observe firmware hangs on MT7630E on station mode: tx stop
functioning after minor activity (rx keep working) and on module
unload device fail to stop with messages:

[ 5446.141413] mt76x0e :06:00.0: TX DMA did not stop
[ 5449.176764] mt76x0e :06:00.0: TX DMA did not stop

Loading module again results in failure to associate with AP.
Only machine power off / power on cycle can make device work again.

I have no idea why the commit caused F/W hangs. Most likely some proper
fix is needed of changing registers programming (or assuring proper order
of actions), but so far I can not came up with any better fix than
a partial revert of 41634aa8d6db.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/tx.c 
b/drivers/net/wireless/mediatek/mt76/tx.c
index 5397827668b9..fefe0ee52584 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -598,7 +598,7 @@ void mt76_wake_tx_queue(struct ieee80211_hw *hw, struct 
ieee80211_txq *txq)
if (!test_bit(MT76_STATE_RUNNING, &dev->state))
return;
 
-   tasklet_schedule(&dev->tx_tasklet);
+   mt76_txq_schedule(dev, txq->ac);
 }
 EXPORT_SYMBOL_GPL(mt76_wake_tx_queue);
 
-- 
1.9.3



Re: mt76x0u blocks resume from suspend

2019-07-23 Thread Stanislaw Gruszka
Hi

On Mon, Jul 22, 2019 at 06:40:20PM +0200, Johannes Stezenbach wrote:
> I met failure to resume from suspend to RAM with v5.1.19
> and TP-Link Archer T2UH connected to my PC (Asus P8H77-V).
> I tried about a dozen times while trying to figure out the reason,
> the issue happened every time.
> Eventually I connected a serial console and captured this:
> 
> [   87.803576][ T4640] mt76x0u 2-1.6:1.0: vendor request req:06 off:ac80 
> failed:-110
> [   91.030328][ T4640] mt76x0u 2-1.6:1.0: vendor request req:07 off:b000 
> failed:-110
> [   94.256950][ T4640] mt76x0u 2-1.6:1.0: vendor request req:06 off:b000 
> failed:-110
> [   97.483579][ T4640] mt76x0u 2-1.6:1.0: vendor request req:06 off:aca0 
> failed:-110
> (repeats)
> [  107.492106][C0] Call Trace:
> [  107.495293][C0]  ? __schedule+0x381/0xa30
> [  107.499706][C0]  schedule+0x36/0x90
> [  107.503575][C0]  schedule_timeout+0x1e8/0x4c0
> [  107.508310][C0]  ? collect_expired_timers+0xb0/0xb0
> [  107.513593][C0]  wait_for_common+0x15f/0x190
> [  107.518249][C0]  ? wake_up_q+0x80/0x80
> [  107.522412][C0]  usb_start_wait_urb+0x82/0x160
> [  107.527222][C0]  ? wait_for_common+0x38/0x190
> [  107.531961][C0]  usb_control_msg+0xdc/0x140
> [  107.536542][C0]  __mt76u_vendor_request+0xc4/0x100 [mt76_usb]
> [  107.542687][C0]  mt76u_copy+0x8b/0xb0 [mt76_usb]
> [  107.547721][C0]  mt76x02_mac_shared_key_setup+0xdf/0x130 [mt76x02_lib]

> The whole machine is hanging at this point. without serial console
> my only choice was to press the reset button.  At least mt76x0u should
> bail out with an error and not block the resume completely.
> Unplugging the hardware also didn't cause it to bail.

I recently sent fix for that
https://lore.kernel.org/linux-wireless/1563446290-2813-1-git-send-email-sgrus...@redhat.com/raw

Stanislaw 


Re: [PATCH 5.3] mt76: mt76x0u: do not reset radio on resume

2019-07-18 Thread Stanislaw Gruszka
On Fri, Jul 19, 2019 at 12:45:23AM +, Sasha Levin wrote:
> v5.1.18: Failed to apply! Possible dependencies:
> Unable to calculate
> 
> v4.19.59: Failed to apply! Possible dependencies:


> How should we proceed with this patch?

I'll provide backported version of the patch for 4.19 and 5.1 
after it will be merged to Linus' tree.

Stanislaw


[PATCH 5.3] mt76: mt76x0u: do not reset radio on resume

2019-07-18 Thread Stanislaw Gruszka
On some machines mt76x0u firmware can hung during resume,
what result on messages like below:

[  475.480062] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  475.990066] mt76x0 1-8:1.0: Error: send MCU cmd failed:-110
[  475.990075] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  476.53] mt76x0 1-8:1.0: Error: send MCU cmd failed:-110
[  476.500012] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  477.010046] mt76x0 1-8:1.0: Error: send MCU cmd failed:-110
[  477.010055] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  477.529997] mt76x0 1-8:1.0: Error: send MCU cmd failed:-110
[  477.530006] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  477.824907] mt76x0 1-8:1.0: Error: send MCU cmd failed:-71
[  477.824916] mt76x0 1-8:1.0: Error: MCU response pre-completed!
[  477.825029] usb 1-8: USB disconnect, device number 6

and possible whole system freeze.

This can be avoided, if we do not perform mt76x0_chip_onoff() reset.

Cc: sta...@vger.kernel.org
Fixes: 134b2d0d1fcf ("mt76x0: init files")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 627ed1fc7b15..645f4d15fb61 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -136,11 +136,11 @@ static int mt76x0u_start(struct ieee80211_hw *hw)
.release_buffered_frames = mt76_release_buffered_frames,
 };
 
-static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)
 {
int err;
 
-   mt76x0_chip_onoff(dev, true, true);
+   mt76x0_chip_onoff(dev, true, reset);
 
if (!mt76x02_wait_for_mac(&dev->mt76))
return -ETIMEDOUT;
@@ -173,7 +173,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
if (err < 0)
goto out_err;
 
-   err = mt76x0u_init_hardware(dev);
+   err = mt76x0u_init_hardware(dev, true);
if (err < 0)
goto out_err;
 
@@ -309,7 +309,7 @@ static int __maybe_unused mt76x0_resume(struct 
usb_interface *usb_intf)
if (ret < 0)
goto err;
 
-   ret = mt76x0u_init_hardware(dev);
+   ret = mt76x0u_init_hardware(dev, false);
if (ret)
goto err;
 
-- 
1.9.3



[PATCH] mt7601u: use params->ssn value directly

2019-07-12 Thread Stanislaw Gruszka
There is no point to use pointer to params->ssn.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt7601u/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c 
b/drivers/net/wireless/mediatek/mt7601u/main.c
index 89a7b1234ffb..72e608cc53af 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -351,7 +351,7 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
-   u16 *ssn = ¶ms->ssn;
+   u16 ssn = params->ssn;
struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv;
 
WARN_ON(msta->wcid.idx > GROUP_WCID(0));
@@ -371,7 +371,7 @@ mt76_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
break;
case IEEE80211_AMPDU_TX_START:
-   msta->agg_ssn[tid] = *ssn << 4;
+   msta->agg_ssn[tid] = ssn << 4;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
-- 
2.20.1



[PATCH 1/3] mt76: mt76x02: use params->ssn value directly

2019-07-12 Thread Stanislaw Gruszka
There is no point to use pointer to params->ssn.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index ad5323447ed4..fa45ed280ab1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -348,7 +348,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
struct mt76x02_sta *msta = (struct mt76x02_sta *) sta->drv_priv;
struct ieee80211_txq *txq = sta->txq[params->tid];
u16 tid = params->tid;
-   u16 *ssn = ¶ms->ssn;
+   u16 ssn = params->ssn;
struct mt76_txq *mtxq;
 
if (!txq)
@@ -359,7 +359,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
switch (action) {
case IEEE80211_AMPDU_RX_START:
mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid,
-  *ssn, params->buf_size);
+  ssn, params->buf_size);
mt76_set(dev, MT_WCID_ADDR(msta->wcid.idx) + 4, BIT(16 + tid));
break;
case IEEE80211_AMPDU_RX_STOP:
@@ -378,7 +378,7 @@ int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn);
break;
case IEEE80211_AMPDU_TX_START:
-   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn);
+   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
-- 
2.20.1



[PATCH 3/3] mt76: mt7615: use params->ssn value directly

2019-07-12 Thread Stanislaw Gruszka
There is no point to use pointer to params->ssn.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt7615/main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c 
b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index 3f5f355d1f9b..2c702b31d55f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -443,7 +443,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
struct ieee80211_txq *txq = sta->txq[params->tid];
struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;
u16 tid = params->tid;
-   u16 *ssn = ¶ms->ssn;
+   u16 ssn = params->ssn;
struct mt76_txq *mtxq;
 
if (!txq)
@@ -453,7 +453,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 
switch (action) {
case IEEE80211_AMPDU_RX_START:
-   mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn,
+   mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
   params->buf_size);
mt7615_mcu_set_rx_ba(dev, params, 1);
break;
@@ -473,7 +473,7 @@ mt7615_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
mt7615_mcu_set_tx_ba(dev, params, 0);
break;
case IEEE80211_AMPDU_TX_START:
-   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn);
+   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
-- 
2.20.1



[PATCH 2/3] mt76: mt7603: use params->ssn value directly

2019-07-12 Thread Stanislaw Gruszka
There is no point to use pointer to params->ssn.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt7603/main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c 
b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index e5d4cb6381a8..d70f42dac923 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -569,7 +569,7 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
struct ieee80211_txq *txq = sta->txq[params->tid];
struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
u16 tid = params->tid;
-   u16 *ssn = ¶ms->ssn;
+   u16 ssn = params->ssn;
u8 ba_size = params->buf_size;
struct mt76_txq *mtxq;
 
@@ -580,7 +580,7 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 
switch (action) {
case IEEE80211_AMPDU_RX_START:
-   mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn,
+   mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
   params->buf_size);
mt7603_mac_rx_ba_reset(dev, sta->addr, tid);
break;
@@ -599,7 +599,7 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);
break;
case IEEE80211_AMPDU_TX_START:
-   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(*ssn);
+   mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
-- 
2.20.1



[RFC/RFT v2] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on tx status

2019-07-12 Thread Stanislaw Gruszka
According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
to be used when we do not receive BA (BlockAck). However on rt2x00 we
use it when remote station fail to decode one or more subframes within
AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
in sent of BAR (BlockAck Request) frame and this might result of abuse
of BA session, since remote station can sent BA with incorrect
sequence numbers after receiving BAR. This problem is visible especially
when connecting two rt2800 devices.

Previously I observed some performance benefits when using the flag
when connecting with iwlwifi devices. But currently possibly due
to recent changes in rt2x00 removing the flag has no effect on
those test cases.

So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.

Additionally partially mimic mt76 behaviour: send BAR when
starting/stopping BA session to workaround problems with some buggy
clients. Do not sent BAR on PS wakeup since we lack all PS handling
code what mt76 has.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c |  4 
 drivers/net/wireless/ralink/rt2x00/rt2x00.h|  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c |  3 ---
 drivers/net/wireless/ralink/rt2x00/rt2x00mac.c | 18 ++
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index c9b957ac5733..4a996550288e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -10481,14 +10481,18 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, 
struct ieee80211_vif *vif,
 */
break;
case IEEE80211_AMPDU_TX_START:
+   sta_priv->agg_ssn[tid] = IEEE80211_SN_TO_SEQ(params->ssn);
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
case IEEE80211_AMPDU_TX_STOP_FLUSH:
+   ieee80211_send_bar(vif, sta->addr, tid, sta_priv->agg_ssn[tid]);
+   break;
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
+   ieee80211_send_bar(vif, sta->addr, tid, sta_priv->agg_ssn[tid]);
break;
default:
rt2x00_warn((struct rt2x00_dev *)hw->priv,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 7e43690a861c..d35ef06c5c7a 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -500,6 +500,7 @@ struct rt2x00intf_conf {
  */
 struct rt2x00_sta {
int wcid;
+   u16 agg_ssn[IEEE80211_NUM_TIDS];
 };
 
 static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index 35414f97a978..ad063c920323 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -371,9 +371,6 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev 
*rt2x00dev,
  IEEE80211_TX_CTL_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
-
-   if (!success)
-   tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
}
 
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index beb20c5faf5f..14896d37f0cc 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -86,6 +86,21 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
return retval;
 }
 
+static void rt2x00mac_save_agg_seqno(struct sk_buff *skb,
+struct ieee80211_sta *sta)
+{
+   struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+   struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+   u8 tid;
+
+   if (!ieee80211_is_data_qos(hdr->frame_control) ||
+   !ieee80211_is_data_present(hdr->frame_control))
+   return;
+
+   tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
+   sta_priv->agg_ssn[tid] = le16_to_cpu(hdr->seq_ctrl) + 0x10;
+}
+
 void rt2x00mac_tx(struct ieee80211_hw *hw,
  struct ieee80211_tx_control *control,
  struct sk_buff *skb)
@@ -119,6 +134,9 @@ void rt2x00mac_tx(struct ieee80211_hw *hw,
goto exit_free_skb;
}
 
+   if (control->sta)
+   rt2x00mac_save_agg_seqno(skb, control->sta);
+
/*

Re: [RFC/RFT] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on tx status

2019-07-12 Thread Stanislaw Gruszka
On Thu, Jul 04, 2019 at 01:06:52PM +0200, Stanislaw Gruszka wrote:
> According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
> to be used when we do not recive BA (BlockAck). However on rt2x00 we
> use it when remote station fail to decode one or more subframes within
> AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
> in sent of BAR (BlockAck Request) frame and this might result of abuse
> of BA session, since remote station can sent BA with incorrect 
> sequence numbers after receiving BAR. This problem is visible especially
> when connecting two rt2800 devices.
> 
> Previously I observed some performance benefits when using the flag
> when connecting with iwlwifi devices. But currently possibly due
> to reacent changes in rt2x00 removing the flag has no effect on
> those test cases.
> 
> So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.
> 
> Perhaps we should send BAR exlicitly on BA session start/stop
> and when remote STA went to PowerSave mode (for AP) like mt76 does.
> But I do not understand for what this is needed.

This commit 

https://github.com/openwrt/mt76/commit/3e447e7797d64dbf4dc1dd5553d08be0d8150d7e

explained that sending BAR on stop aggregation is workaround for
buggy clients. I can implement that on rt2x00. But I will skip
sending BAR on remote station PS wakeup, since we do not implement
all PS related code in rt2x00.  

Stanislaw 


[PATCH v2 1/2] mt76: usb: fix endian in mt76u_copy

2019-07-09 Thread Stanislaw Gruszka
In contrast to mt76_wr() which we use to program registers,
on mt76_wr_copy() we should not change endian of the data.

Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/usb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index 5be584ca7497..828939e78a3b 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -165,11 +165,11 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
 
mutex_lock(&usb->usb_ctrl_mtx);
for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
-   put_unaligned_le32(val[i], usb->data);
+   put_unaligned(val[i], (u32 *) usb->data);
ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE,
 USB_DIR_OUT | USB_TYPE_VENDOR,
 0, offset + i * 4, usb->data,
-sizeof(__le32));
+sizeof(u32));
if (ret < 0)
break;
}
-- 
2.20.1



[PATCH v2 0/2] mt76: usb: alignment and endianes improvements

2019-07-09 Thread Stanislaw Gruszka
Fix endian bug and do some minor optimizations in mt76u_{copy,rr,wr} .

v1 -> v2:
- drop patch 3
- fix pointer size in patch 1

Stanislaw Gruszka (2):
  mt76: usb: fix endian in mt76u_copy
  mt76: usb: remove unneeded {put,get}_unaligned

 drivers/net/wireless/mediatek/mt76/mt76.h |  5 -
 drivers/net/wireless/mediatek/mt76/usb.c  | 12 ++--
 2 files changed, 10 insertions(+), 7 deletions(-)

-- 
2.20.1



[PATCH v2 2/2] mt76: usb: remove unneeded {put,get}_unaligned

2019-07-09 Thread Stanislaw Gruszka
Compiler give us guaranties on variables alignment, so use
an variable as buffer when read/write registers and remove
unneeded {put,get}_unaligned.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76.h | 5 -
 drivers/net/wireless/mediatek/mt76/usb.c  | 8 
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index 56bf93a8988e..094e6e543542 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -389,7 +389,10 @@ enum mt76u_out_ep {
 #define MCU_RESP_URB_SIZE  1024
 struct mt76_usb {
struct mutex usb_ctrl_mtx;
-   u8 data[32];
+   union {
+   u8 data[32];
+   __le32 reg_val;
+   };
 
struct tasklet_struct rx_tasklet;
struct delayed_work stat_work;
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index 828939e78a3b..00069c2536f8 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -95,9 +95,9 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
 
ret = __mt76u_vendor_request(dev, req,
 USB_DIR_IN | USB_TYPE_VENDOR,
-0, offset, usb->data, sizeof(__le32));
+0, offset, &usb->reg_val, sizeof(__le32));
if (ret == sizeof(__le32))
-   data = get_unaligned_le32(usb->data);
+   data = le32_to_cpu(usb->reg_val);
trace_usb_reg_rr(dev, addr, data);
 
return data;
@@ -131,10 +131,10 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, 
u32 val)
}
offset = addr & ~MT_VEND_TYPE_MASK;
 
-   put_unaligned_le32(val, usb->data);
+   usb->reg_val = cpu_to_le32(val);
__mt76u_vendor_request(dev, req,
   USB_DIR_OUT | USB_TYPE_VENDOR, 0,
-  offset, usb->data, sizeof(__le32));
+  offset, &usb->reg_val, sizeof(__le32));
trace_usb_reg_wr(dev, addr, val);
 }
 
-- 
2.20.1



Re: [PATCH 3/3] mt76: usb: use full intermediate buffer in mt76u_copy

2019-07-09 Thread Stanislaw Gruszka
On Tue, Jul 02, 2019 at 05:06:01PM +0200, Stanislaw Gruszka wrote:
> Instead of use several 4 bytes usb requests, use full 32 bytes buffer
> to copy data to device. With the change we use less requests and copy
> exact data size to the device regardless size is multiple of 4 or not.

And this does not work correctly on some usb hosts, request which
are not multiple of 4 do not ended being written to hardware, 
what results in original problem of having last part of beacon
corrupted.

I would prefer to drop this set - and I would post 2 patches
(first patch fixed and third dropped). But since this is now in
Felix's wireless tree I guess I need to post fixes on top of this
set?

Stanislaw


Re: [PATCH 1/3] mt76: usb: fix endian in mt76u_copy

2019-07-09 Thread Stanislaw Gruszka
On Tue, Jul 02, 2019 at 05:05:59PM +0200, Stanislaw Gruszka wrote:
> In contrast to mt76_wr() which we use to program registers,
> on mt76_wr_copy() we should not change endian of the data.
> 
> Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
> Signed-off-by: Stanislaw Gruszka 
> ---
>  drivers/net/wireless/mediatek/mt76/usb.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
> b/drivers/net/wireless/mediatek/mt76/usb.c
> index 87ecbe290f99..db90ec6b8775 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -165,11 +165,11 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
>  
>   mutex_lock(&usb->usb_ctrl_mtx);
>   for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
> - put_unaligned_le32(val[i], usb->data);
> + put_unaligned(val[i], usb->data);

This is bug as put_unaligned() use size based second argument
pointer type, correct version should looks like this:

put_unaligned(val[i], (u32 *) usb->data);

Stanislaw


[RFC/RFT] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on tx status

2019-07-04 Thread Stanislaw Gruszka
According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose
to be used when we do not recive BA (BlockAck). However on rt2x00 we
use it when remote station fail to decode one or more subframes within
AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result
in sent of BAR (BlockAck Request) frame and this might result of abuse
of BA session, since remote station can sent BA with incorrect 
sequence numbers after receiving BAR. This problem is visible especially
when connecting two rt2800 devices.

Previously I observed some performance benefits when using the flag
when connecting with iwlwifi devices. But currently possibly due
to reacent changes in rt2x00 removing the flag has no effect on
those test cases.

So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK.

Perhaps we should send BAR exlicitly on BA session start/stop
and when remote STA went to PowerSave mode (for AP) like mt76 does.
But I do not understand for what this is needed.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index a6c374c483c2..c547bec044a8 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -371,9 +371,6 @@ static void rt2x00lib_fill_tx_status(struct rt2x00_dev 
*rt2x00dev,
  IEEE80211_TX_CTL_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
-
-   if (!success)
-   tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
}
 
if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-- 
2.20.1



Re: [PATCH v2] rt2x00: no need to check return value of debugfs_create functions

2019-07-04 Thread Stanislaw Gruszka
On Wed, Jul 03, 2019 at 01:39:56PM +0200, Greg Kroah-Hartman wrote:
> 
> When calling debugfs functions, there is no need to ever check the
> return value.  The function can work or not, but the code logic should
> never do something different based on this.
> 
> Because we don't need to save the individual debugfs files and
> directories, remove the local storage of them and just remove the entire
> debugfs directory in a single call, making things a lot simpler.
> 
> Cc: Stanislaw Gruszka 
> Cc: Helmut Schaa 
> Cc: Kalle Valo 
> Cc: "David S. Miller" 
> Cc: linux-wireless@vger.kernel.org
> Cc: net...@vger.kernel.org
> Signed-off-by: Greg Kroah-Hartman 

Acked-by: Stanislaw Gruszka 


Re: [PATCH] rt2x00: no need to check return value of debugfs_create functions

2019-07-03 Thread Stanislaw Gruszka
On Wed, Jul 03, 2019 at 08:56:31AM +0200, Greg Kroah-Hartman wrote:
> When calling debugfs functions, there is no need to ever check the
> return value.  The function can work or not, but the code logic should
> never do something different based on this.
> 
> Because we don't need to save the individual debugfs files and
> directories, remove the local storage of them and just remove the entire
> debugfs directory in a single call, making things a lot simpler.
> 
> Cc: Stanislaw Gruszka 
> Cc: Helmut Schaa 
> Cc: Kalle Valo 
> Cc: "David S. Miller" 
> Cc: linux-wireless@vger.kernel.org
> Cc: net...@vger.kernel.org
> Signed-off-by: Greg Kroah-Hartman 
> ---
>  .../net/wireless/ralink/rt2x00/rt2x00debug.c  | 100 --
>  1 file changed, 23 insertions(+), 77 deletions(-)

This patch will not apply on wireless-drivers-next due to my recent
change which add new debugfs file:

commit e7f15d58dfe43f18199251f430d7713b0b8fad34
Author: Stanislaw Gruszka 
Date:   Thu May 2 11:07:00 2019 +0200

rt2x00: add restart hw

Could you please rebase the patch ? (I can do this as well
if you want me to).

Stanislaw


Re: rtl8xxxu do not see/connect any wifi network until suspend/resume

2019-07-03 Thread Stanislaw Gruszka
On Mon, Jul 01, 2019 at 07:25:16PM +0500, Andrej Surkov wrote:
> Hi!
> 
> Do you aware of rtl8xxxu do not work until suspend/resume issue?
> 
> On my laptop, see below for details, after reboot wifi-menu tool shows one 
> single wifi network found and can't connect to it, but after 'sudo systemctl 
> suspend' and resume by keystroke wifi-menu and connections work well.

This sound like this bug:
https://bugzilla.kernel.org/show_bug.cgi?id=202541
Which happen to be xhci_hcd regression, not yet fixed AFAIK.

Stanislaw


[PATCH 3/3] mt76: usb: use full intermediate buffer in mt76u_copy

2019-07-02 Thread Stanislaw Gruszka
Instead of use several 4 bytes usb requests, use full 32 bytes buffer
to copy data to device. With the change we use less requests and copy
exact data size to the device regardless size is multiple of 4 or not.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/usb.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index a61bb8171557..7c564cc68c7c 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -160,19 +160,24 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
   const void *data, int len)
 {
struct mt76_usb *usb = &dev->usb;
-   const u32 *val = data;
-   int i, ret;
+   int ret, req_len;
 
mutex_lock(&usb->usb_ctrl_mtx);
-   for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
-   put_unaligned(val[i], usb->data);
+   do {
+   req_len = min_t(int, len, sizeof(usb->data));
+
+   memcpy(usb->data, data, req_len);
+
ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE,
 USB_DIR_OUT | USB_TYPE_VENDOR,
-0, offset + i * 4, usb->data,
-sizeof(u32));
+0, offset, usb->data, req_len);
if (ret < 0)
break;
-   }
+
+   data += req_len;
+   offset += req_len;
+   len -= req_len;
+   } while (len > 0);
mutex_unlock(&usb->usb_ctrl_mtx);
 }
 
-- 
1.9.3



[PATCH 1/3] mt76: usb: fix endian in mt76u_copy

2019-07-02 Thread Stanislaw Gruszka
In contrast to mt76_wr() which we use to program registers,
on mt76_wr_copy() we should not change endian of the data.

Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/usb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index 87ecbe290f99..db90ec6b8775 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -165,11 +165,11 @@ static void mt76u_copy(struct mt76_dev *dev, u32 offset,
 
mutex_lock(&usb->usb_ctrl_mtx);
for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
-   put_unaligned_le32(val[i], usb->data);
+   put_unaligned(val[i], usb->data);
ret = __mt76u_vendor_request(dev, MT_VEND_MULTI_WRITE,
 USB_DIR_OUT | USB_TYPE_VENDOR,
 0, offset + i * 4, usb->data,
-sizeof(__le32));
+sizeof(u32));
if (ret < 0)
break;
}
-- 
1.9.3



[PATCH 0/3] mt76: usb: alignment and endianes improvements

2019-07-02 Thread Stanislaw Gruszka
Fix endian bug and do some minor optimizations in mt76u_{copy,rr,wr} .

I do not mark cc stable endian fix as noboby reported this issue,
i.e. use the driver on big endian machine, but make it a separate patch,
so it can be backported if needed.

This is on top of:
[PATCH] mt76: round up length on mt76_wr_copy 

Stanislaw Gruszka (3):
  mt76: usb: fix endian in mt76u_copy
  mt76: usb: remove unneeded {put,get}_unaligned
  mt76: usb: use full intermediate buffer in mt76u_copy

 drivers/net/wireless/mediatek/mt76/mt76.h |  5 -
 drivers/net/wireless/mediatek/mt76/usb.c  | 27 ---
 2 files changed, 20 insertions(+), 12 deletions(-)

-- 
1.9.3



[PATCH 2/3] mt76: usb: remove unneeded {put,get}_unaligned

2019-07-02 Thread Stanislaw Gruszka
Compiler give us guaranties on variables alignment, so use
an variable as buffer when read/write registers and remove
unneeded {put,get}_unaligned.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76.h | 5 -
 drivers/net/wireless/mediatek/mt76/usb.c  | 8 
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index 56bf93a8988e..094e6e543542 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -389,7 +389,10 @@ enum mt76u_out_ep {
 #define MCU_RESP_URB_SIZE  1024
 struct mt76_usb {
struct mutex usb_ctrl_mtx;
-   u8 data[32];
+   union {
+   u8 data[32];
+   __le32 reg_val;
+   };
 
struct tasklet_struct rx_tasklet;
struct delayed_work stat_work;
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index db90ec6b8775..a61bb8171557 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -95,9 +95,9 @@ static u32 __mt76u_rr(struct mt76_dev *dev, u32 addr)
 
ret = __mt76u_vendor_request(dev, req,
 USB_DIR_IN | USB_TYPE_VENDOR,
-0, offset, usb->data, sizeof(__le32));
+0, offset, &usb->reg_val, sizeof(__le32));
if (ret == sizeof(__le32))
-   data = get_unaligned_le32(usb->data);
+   data = le32_to_cpu(usb->reg_val);
trace_usb_reg_rr(dev, addr, data);
 
return data;
@@ -131,10 +131,10 @@ static void __mt76u_wr(struct mt76_dev *dev, u32 addr, 
u32 val)
}
offset = addr & ~MT_VEND_TYPE_MASK;
 
-   put_unaligned_le32(val, usb->data);
+   usb->reg_val = cpu_to_le32(val);
__mt76u_vendor_request(dev, req,
   USB_DIR_OUT | USB_TYPE_VENDOR, 0,
-  offset, usb->data, sizeof(__le32));
+  offset, &usb->reg_val, sizeof(__le32));
trace_usb_reg_wr(dev, addr, val);
 }
 
-- 
1.9.3



[PATCH v2 6/7] rt2x00: add restart hw

2019-06-15 Thread Stanislaw Gruszka
Add ieee80211_restart_hw() to watchdog and debugfs file for testing
if restart works as expected.

Signed-off-by: Stanislaw Gruszka 
---
 .../net/wireless/ralink/rt2x00/rt2800lib.c|  4 +++
 drivers/net/wireless/ralink/rt2x00/rt2x00.h   |  7 
 .../net/wireless/ralink/rt2x00/rt2x00debug.c  | 35 +++
 .../net/wireless/ralink/rt2x00/rt2x00dev.c| 10 --
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 32a4b84e6e05..0fb519f2b83f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1263,6 +1263,9 @@ void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
 
if (hung_rx)
rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+
+   if (hung_tx || hung_rx)
+   ieee80211_restart_hw(rt2x00dev->hw);
 }
 EXPORT_SYMBOL_GPL(rt2800_watchdog);
 
@@ -10283,6 +10286,7 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
}
 
+   __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
 
/*
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index dc6b79e4be3b..7c7cced009bd 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -712,6 +712,7 @@ enum rt2x00_capability_flags {
CAPABILITY_VCO_RECALIBRATION,
CAPABILITY_EXTERNAL_PA_TX0,
CAPABILITY_EXTERNAL_PA_TX1,
+   CAPABILITY_RESTART_HW,
 };
 
 /*
@@ -1268,6 +1269,12 @@ rt2x00_has_cap_vco_recalibration(struct rt2x00_dev 
*rt2x00dev)
return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION);
 }
 
+static inline bool
+rt2x00_has_cap_restart_hw(struct rt2x00_dev *rt2x00dev)
+{
+   return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RESTART_HW);
+}
+
 /**
  * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
  * @entry: Pointer to &struct queue_entry
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index aac3aae7afaa..ef5f51512212 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -52,6 +52,7 @@ struct rt2x00debug_intf {
 *   - chipset file
 *   - device state flags file
 *   - device capability flags file
+*   - hardware restart file
 *   - register folder
 * - csr offset/value files
 * - eeprom offset/value files
@@ -68,6 +69,7 @@ struct rt2x00debug_intf {
struct dentry *chipset_entry;
struct dentry *dev_flags;
struct dentry *cap_flags;
+   struct dentry *restart_hw;
struct dentry *register_folder;
struct dentry *csr_off_entry;
struct dentry *csr_val_entry;
@@ -566,6 +568,34 @@ static const struct file_operations 
rt2x00debug_fop_cap_flags = {
.llseek = default_llseek,
 };
 
+static ssize_t rt2x00debug_write_restart_hw(struct file *file,
+   const char __user *buf,
+   size_t length,
+   loff_t *offset)
+{
+   struct rt2x00debug_intf *intf = file->private_data;
+   struct rt2x00_dev *rt2x00dev = intf->rt2x00dev;
+   static unsigned long last_reset;
+
+   if (!rt2x00_has_cap_restart_hw(rt2x00dev))
+   return -EOPNOTSUPP;
+
+   if (time_before(jiffies, last_reset + msecs_to_jiffies(2000)))
+   return -EBUSY;
+
+   last_reset = jiffies;
+
+   ieee80211_restart_hw(rt2x00dev->hw);
+   return length;
+}
+
+static const struct file_operations rt2x00debug_restart_hw = {
+   .owner = THIS_MODULE,
+   .write = rt2x00debug_write_restart_hw,
+   .open = simple_open,
+   .llseek = generic_file_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 struct rt2x00debug_intf
 *intf,
@@ -661,6 +691,10 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
  intf->driver_folder, intf,
  &rt2x00debug_fop_cap_flags);
 
+   intf->restart_hw = debugfs_create_file("restart_hw", 0200,
+  intf->driver_folder, intf,
+  &rt2x00debug_restart_hw);
+
intf->register_folder =
debugfs_create_dir("register", intf->driver_folder);
 
@@ -742,6 +776,7 @@ void rt2x00deb

[PATCH v2 7/7] rt2800: do not enable watchdog by default

2019-06-15 Thread Stanislaw Gruszka
Make watchdog disabled by default and add module parameter to enable it.

User will have to create file in /etc/modprobe.d/ with

options rt2800lib watchdog=1

to enable the watchdog or load "rt2800lib watchdog=1" module manually
before loading rt2800{soc,pci,usb} module.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c  | 12 ++--
 drivers/net/wireless/ralink/rt2x00/rt2x00.h |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00link.c |  2 +-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0fb519f2b83f..c9b957ac5733 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -30,6 +30,10 @@
 #include "rt2800lib.h"
 #include "rt2800.h"
 
+static bool modparam_watchdog;
+module_param_named(watchdog, modparam_watchdog, bool, S_IRUGO);
+MODULE_PARM_DESC(watchdog, "Enable watchdog to detect tx/rx hangs and reset 
hardware if detected");
+
 /*
  * Register access.
  * All access to the CSR registers will go through the methods
@@ -10286,8 +10290,12 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
}
 
-   __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
-   rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+   if (modparam_watchdog) {
+   __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags);
+   rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+   } else {
+   rt2x00dev->link.watchdog_disabled = true;
+   }
 
/*
 * Set the rssi offset.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 7c7cced009bd..7e43690a861c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -326,6 +326,7 @@ struct link {
 */
struct delayed_work watchdog_work;
unsigned int watchdog_interval;
+   bool watchdog_disabled;
 
/*
 * Work structure for scheduling periodic AGC adjustments.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
index 15ebebf88e72..b052c96347d6 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -384,7 +384,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
struct link *link = &rt2x00dev->link;
 
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
-   rt2x00dev->ops->lib->watchdog)
+   rt2x00dev->ops->lib->watchdog && !link->watchdog_disabled)
ieee80211_queue_delayed_work(rt2x00dev->hw,
 &link->watchdog_work,
 link->watchdog_interval);
-- 
2.20.1



[PATCH v2 5/7] rt2800: do not nullify initialization vector data

2019-06-15 Thread Stanislaw Gruszka
If we restart hw we should keep existing IV (initialization vector)
otherwise HW encryption will be broken after restart.

Also fix some coding style issues on the way.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 499e9afa0026..32a4b84e6e05 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1647,14 +1647,15 @@ static void rt2800_config_wcid_attr_cipher(struct 
rt2x00_dev *rt2x00dev,
 
offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
-   memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+   rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
if ((crypto->cipher == CIPHER_TKIP) ||
(crypto->cipher == CIPHER_TKIP_NO_MIC) ||
(crypto->cipher == CIPHER_AES))
iveiv_entry.iv[3] |= 0x20;
iveiv_entry.iv[3] |= key->keyidx << 6;
rt2800_register_multiwrite(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
+  &iveiv_entry, sizeof(iveiv_entry));
 }
 
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -6079,13 +6080,11 @@ static int rt2800_init_registers(struct rt2x00_dev 
*rt2x00dev)
 * ASIC will keep garbage value after boot, clear encryption keys.
 */
for (i = 0; i < 4; i++)
-   rt2800_register_write(rt2x00dev,
-SHARED_KEY_MODE_ENTRY(i), 0);
+   rt2800_register_write(rt2x00dev, SHARED_KEY_MODE_ENTRY(i), 0);
 
for (i = 0; i < 256; i++) {
rt2800_config_wcid(rt2x00dev, NULL, i);
rt2800_delete_wcid_attr(rt2x00dev, i);
-   rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
}
 
/*
-- 
2.20.1



[PATCH v2 2/7] rt2800: add helpers for reading dma done index

2019-06-15 Thread Stanislaw Gruszka
For mmio we do not properlly trace dma done Q_INDEX_DMA_DONE index
for TX queues. That would require implementing INT_SOURCE_CSR_*_DMA_DONE
interrupts, what is rather not worth to do due to adding extra
CPU load (small but still somewhat not necessary otherwise).

We can just read TX DMA done indexes from registers directly. What
will be used by watchdog.

Signed-off-by: Stanislaw Gruszka 
---
 .../net/wireless/ralink/rt2x00/rt2800lib.h|  8 +
 .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 31 +++
 .../net/wireless/ralink/rt2x00/rt2800mmio.h   |  2 ++
 .../net/wireless/ralink/rt2x00/rt2800pci.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800soc.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800usb.c|  9 ++
 6 files changed, 52 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index 48adc6cc3233..dbb413ec8b08 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -65,6 +65,7 @@ struct rt2800_ops {
  const u8 *data, const size_t len);
int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
__le32 *(*drv_get_txwi)(struct queue_entry *entry);
+   unsigned int (*drv_get_dma_done)(struct data_queue *queue);
 };
 
 static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev,
@@ -166,6 +167,13 @@ static inline __le32 *rt2800_drv_get_txwi(struct 
queue_entry *entry)
return rt2800ops->drv_get_txwi(entry);
 }
 
+static inline unsigned int rt2800_drv_get_dma_done(struct data_queue *queue)
+{
+   const struct rt2800_ops *rt2800ops = queue->rt2x00dev->ops->drv;
+
+   return rt2800ops->drv_get_dma_done(queue);
+}
+
 void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index d1de8e2ff690..110bb391c372 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -24,6 +24,37 @@
 #include "rt2800lib.h"
 #include "rt2800mmio.h"
 
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue)
+{
+   struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+   struct queue_entry *entry;
+   int idx, qid;
+
+   switch (queue->qid) {
+   case QID_AC_VO:
+   case QID_AC_VI:
+   case QID_AC_BE:
+   case QID_AC_BK:
+   qid = queue->qid;
+   idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid));
+   break;
+   case QID_MGMT:
+   idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(5));
+   break;
+   case QID_RX:
+   entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+   idx = entry->entry_idx;
+   break;
+   default:
+   WARN_ON_ONCE(1);
+   idx = 0;
+   break;
+   }
+
+   return idx;
+}
+EXPORT_SYMBOL_GPL(rt2800mmio_get_dma_done);
+
 /*
  * TX descriptor initialization
  */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h 
b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
index 29b5cfd2856f..adcd9d54ac1c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
@@ -114,6 +114,8 @@
 #define RXD_W3_PLCP_SIGNAL FIELD32(0x0002)
 #define RXD_W3_PLCP_RSSI   FIELD32(0x0004)
 
+unsigned int rt2800mmio_get_dma_done(struct data_queue *queue);
+
 /* TX descriptor initialization */
 __le32 *rt2800mmio_get_txwi(struct queue_entry *entry);
 void rt2800mmio_write_tx_desc(struct queue_entry *entry,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index ead8bd3e9236..71ef8f07b47b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -326,6 +326,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
.drv_write_firmware = rt2800pci_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi   = rt2800mmio_get_txwi,
+   .drv_get_dma_done   = rt2800mmio_get_dma_done,
 };
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 230557d36c52..34e9291d949c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -171,6 +171,7 @@ static const struct rt2800_ops rt2800soc_rt2800_ops = {
.drv_write_firmware = rt2800soc_write_firmware,
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi   =

[PATCH v2 1/7] rt2x00: allow to specify watchdog interval

2019-06-15 Thread Stanislaw Gruszka
Allow subdriver to change watchdog interval by intialize
link->watchdog_interval value before rt2x00link_register().

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2x00.h |  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 13 +
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 64a792a8fb2c..2b551dbe9844 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -325,6 +325,7 @@ struct link {
 * to bring the device/driver back into the desired state.
 */
struct delayed_work watchdog_work;
+   unsigned int watchdog_interval;
 
/*
 * Work structure for scheduling periodic AGC adjustments.
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
index 939cfa5141c6..15ebebf88e72 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c
@@ -387,7 +387,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
rt2x00dev->ops->lib->watchdog)
ieee80211_queue_delayed_work(rt2x00dev->hw,
 &link->watchdog_work,
-WATCHDOG_INTERVAL);
+link->watchdog_interval);
 }
 
 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -413,11 +413,16 @@ static void rt2x00link_watchdog(struct work_struct *work)
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
ieee80211_queue_delayed_work(rt2x00dev->hw,
 &link->watchdog_work,
-WATCHDOG_INTERVAL);
+link->watchdog_interval);
 }
 
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
 {
-   INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
-   INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
+   struct link *link = &rt2x00dev->link;
+
+   INIT_DELAYED_WORK(&link->work, rt2x00link_tuner);
+   INIT_DELAYED_WORK(&link->watchdog_work, rt2x00link_watchdog);
+
+   if (link->watchdog_interval == 0)
+   link->watchdog_interval = WATCHDOG_INTERVAL;
 }
-- 
2.20.1



[PATCH v2 0/7] rt2800: add experimental watchdog implementation

2019-06-15 Thread Stanislaw Gruszka
Add watchdog to address some remaining problems of Ralink devices
random hungs.

RFC -> v1
 - better description for module parameter 
 - fix white space

v1 -> v2:
 - rebase on latest tree.

Stanislaw Gruszka (7):
  rt2x00: allow to specify watchdog interval
  rt2800: add helpers for reading dma done index
  rt2800: initial watchdog implementation
  rt2800: add pre_reset_hw callback
  rt2800: do not nullify initialization vector data
  rt2x00: add restart hw
  rt2800: do not enable watchdog by default

 .../net/wireless/ralink/rt2x00/rt2800lib.c| 96 ++-
 .../net/wireless/ralink/rt2x00/rt2800lib.h| 11 +++
 .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 31 ++
 .../net/wireless/ralink/rt2x00/rt2800mmio.h   |  2 +
 .../net/wireless/ralink/rt2x00/rt2800pci.c|  3 +
 .../net/wireless/ralink/rt2x00/rt2800soc.c|  3 +
 .../net/wireless/ralink/rt2x00/rt2800usb.c| 11 +++
 drivers/net/wireless/ralink/rt2x00/rt2x00.h   | 10 ++
 .../net/wireless/ralink/rt2x00/rt2x00debug.c  | 35 +++
 .../net/wireless/ralink/rt2x00/rt2x00dev.c| 10 +-
 .../net/wireless/ralink/rt2x00/rt2x00link.c   | 15 ++-
 .../net/wireless/ralink/rt2x00/rt2x00queue.h  |  6 ++
 12 files changed, 221 insertions(+), 12 deletions(-)

-- 
2.20.1



[PATCH v2 3/7] rt2800: initial watchdog implementation

2019-06-15 Thread Stanislaw Gruszka
Add watchdog for rt2800 devices. For now it only detect hung
and print error.

[Note: I verified that printing messages from process context is
fine on MT7620 (WT3020) platform that have problem when printk
is called from interrupt context].

Signed-off-by: Stanislaw Gruszka 
---
 .../net/wireless/ralink/rt2x00/rt2800lib.c| 56 +++
 .../net/wireless/ralink/rt2x00/rt2800lib.h|  2 +
 .../net/wireless/ralink/rt2x00/rt2800pci.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800soc.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800usb.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2x00queue.h  |  6 ++
 6 files changed, 67 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 621cd4ce69e2..d420d759a877 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1212,6 +1212,60 @@ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus);
 
+static int rt2800_check_hung(struct data_queue *queue)
+{
+   unsigned int cur_idx = rt2800_drv_get_dma_done(queue);
+
+   if (queue->wd_idx != cur_idx)
+   queue->wd_count = 0;
+   else
+   queue->wd_count++;
+
+   return queue->wd_count > 16;
+}
+
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+   struct data_queue *queue;
+   bool hung_tx = false;
+   bool hung_rx = false;
+
+   if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
+   return;
+
+   queue_for_each(rt2x00dev, queue) {
+   switch (queue->qid) {
+   case QID_AC_VO:
+   case QID_AC_VI:
+   case QID_AC_BE:
+   case QID_AC_BK:
+   case QID_MGMT:
+   if (rt2x00queue_empty(queue))
+   continue;
+   hung_tx = rt2800_check_hung(queue);
+   break;
+   case QID_RX:
+   /* For station mode we should reactive at least
+* beacons. TODO: need to find good way detect
+* RX hung for AP mode.
+*/
+   if (rt2x00dev->intf_sta_count == 0)
+   continue;
+   hung_rx = rt2800_check_hung(queue);
+   break;
+   default:
+   break;
+   }
+   }
+
+   if (hung_tx)
+   rt2x00_warn(rt2x00dev, "Watchdog TX hung detected\n");
+
+   if (hung_rx)
+   rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n");
+}
+EXPORT_SYMBOL_GPL(rt2800_watchdog);
+
 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
  unsigned int index)
 {
@@ -10211,6 +10265,8 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
}
 
+   rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100);
+
/*
 * Set the rssi offset.
 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index dbb413ec8b08..f35f4e20d5aa 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -197,6 +197,8 @@ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
 bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
 bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
 
+void rt2800_watchdog(struct rt2x00_dev *rt2x00dev);
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc 
*txdesc);
 void rt2800_clear_beacon(struct queue_entry *entry);
 
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index 71ef8f07b47b..df6345a92f72 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -351,6 +351,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.link_tuner = rt2800_link_tuner,
.gain_calibration   = rt2800_gain_calibration,
.vco_calibration= rt2800_vco_calibration,
+   .watchdog   = rt2800_watchdog,
.start_queue= rt2800mmio_start_queue,
.kick_queue = rt2800mmio_kick_queue,
.stop_queue = rt2800mmio_stop_queue,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 34e9291d949c..1054ade65af2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -196,6 +196,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
.link_tuner 

[PATCH v2 4/7] rt2800: add pre_reset_hw callback

2019-06-15 Thread Stanislaw Gruszka
Add routine to cleanup interfaces data before hw reset as
ieee80211_restart_hw() will do setup interfaces again.

Signed-off-by: Stanislaw Gruszka 
---
 .../net/wireless/ralink/rt2x00/rt2800lib.c| 19 +++
 .../net/wireless/ralink/rt2x00/rt2800lib.h|  1 +
 .../net/wireless/ralink/rt2x00/rt2800pci.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800soc.c|  1 +
 .../net/wireless/ralink/rt2x00/rt2800usb.c|  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00.h   |  1 +
 6 files changed, 24 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index d420d759a877..499e9afa0026 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1843,6 +1843,25 @@ int rt2800_sta_remove(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 }
 EXPORT_SYMBOL_GPL(rt2800_sta_remove);
 
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev)
+{
+   struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+   struct data_queue *queue = rt2x00dev->bcn;
+   struct queue_entry *entry;
+   int i, wcid;
+
+   for (wcid = WCID_START; wcid < WCID_END; wcid++) {
+   drv_data->wcid_to_sta[wcid - WCID_START] = NULL;
+   __clear_bit(wcid - WCID_START, drv_data->sta_ids);
+   }
+
+   for (i = 0; i < queue->limit; i++) {
+   entry = &queue->entries[i];
+   clear_bit(ENTRY_BCN_ASSIGNED, &entry->flags);
+   }
+}
+EXPORT_SYMBOL_GPL(rt2800_pre_reset_hw);
+
 void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
  const unsigned int filter_flags)
 {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
index f35f4e20d5aa..1139405c0ebb 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -257,5 +257,6 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
 void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev,
   unsigned short *txwi_size,
   unsigned short *rxwi_size);
+void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev);
 
 #endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
index df6345a92f72..a23c26574002 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -368,6 +368,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+   .pre_reset_hw   = rt2800_pre_reset_hw,
 };
 
 static const struct rt2x00_ops rt2800pci_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
index 1054ade65af2..7b931bb96a9e 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
@@ -213,6 +213,7 @@ static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+   .pre_reset_hw   = rt2800_pre_reset_hw,
 };
 
 static const struct rt2x00_ops rt2800soc_ops = {
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
index da813dfa9a91..fdf0504b5f1d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
@@ -706,6 +706,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.config_erp = rt2800_config_erp,
.config_ant = rt2800_config_ant,
.config = rt2800_config,
+   .pre_reset_hw   = rt2800_pre_reset_hw,
 };
 
 static void rt2800usb_queue_init(struct data_queue *queue)
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 2b551dbe9844..dc6b79e4be3b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -616,6 +616,7 @@ struct rt2x00lib_ops {
void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int changed_flags);
+   void (*pre_reset_hw) (struct rt2x00_dev *rt2x00dev);
int (*sta_add) (struct rt2x00_dev *rt2x00dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
-- 
2.20.1



Re: [PATCH v3 wireless-drivers 3/3] mt76: usb: do not always copy the first part of received frames

2019-06-15 Thread Stanislaw Gruszka
On Fri, Jun 14, 2019 at 02:46:36PM +0200, Lorenzo Bianconi wrote:
> > > 
> > > ack, right. I think patch 2/3 and 3/3 can go directly in Felix's tree
> > > 
> > > > 
> > > > > + int i, data_size;
> > > > >  
> > > > > + data_size = rounddown(SKB_WITH_OVERHEAD(q->buf_size),
> > > > > +   
> > > > > dev->usb.in_ep[MT_EP_IN_PKT_RX].max_packet);
> > > > >   for (i = 0; i < nsgs; i++) {
> > > > >   struct page *page;
> > > > >   void *data;
> > > > > @@ -302,7 +304,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct 
> > > > > mt76_queue *q, struct urb *urb,
> > > > >  
> > > > >   page = virt_to_head_page(data);
> > > > >   offset = data - page_address(page);
> > > > > - sg_set_page(&urb->sg[i], page, q->buf_size, offset);
> > > > > + sg_set_page(&urb->sg[i], page, data_size, offset);
> > > > 
> > > > > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > > > >   q->ndesc = MT_NUM_RX_ENTRIES;
> > > > > + q->buf_size = PAGE_SIZE;
> > > > > +
> > > > 
> > > > This should be associated with decrease of MT_SG_MAX_SIZE to value that
> > > > is actually needed and currently this is 2 for 4k AMSDU.
> > > 
> > > MT_SG_MAX_SIZE is used even on tx side and I do not think we will end up 
> > > with a
> > > huge difference here
> > 
> > So use different value as argument for mt76u_fill_rx_sg() in
> > mt76u_rx_urb_alloc(). After changing buf_size to PAGE_SIZE we will
> > allocate 8 pages per rx queue entry, but only 2 pages will be used
> > (with data_size change, 1 without data_size change). Or I'm wrong?
> 
> yes, it is right (we will use two pages with data_size change). Maybe better 
> to
> use 4 pages for each rx queue entry? (otherwise we will probably change it in
> the future)

We should not allocate more than is required. If support for bigger
rx AMSDUs will be added and announced in vht/ht capabilities to remote
stations, then increase of number of segments will be needed.

> > > > However I don't think allocating 2 pages to avoid ieee80211 header and 
> > > > SNAP
> > > > copy is worth to do. For me best approach would be allocate 1 page for
> > > > 4k AMSDU, 2 for 8k and 3 for 12k (still using sg, but without data_size
> > > > change to avoid 32B copying).
> > > 
> > > From my point of view it is better to avoid copying if it is possible. 
> > > Are you
> > > sure there is no difference?
> > 
> > I do not understand what you mean by difference here.
> 
> tpt differences, not sure if there are any

I would not expect any measurable difference in tpt nor in cpu usage
either way.

But I think, if some AMSDU subframe will be spited into two fragments,
data most likely will need to be linearised/copied, at some point before
passed to application, what will overcome any benefit of avoiding coping
802.11 header. Thought, I don't think this somehow will be visible in
benchmarking.

Stanislaw


Re: [PATCH v3 wireless-drivers 1/3] mt76: usb: fix rx A-MSDU support

2019-06-14 Thread Stanislaw Gruszka
On Fri, Jun 14, 2019 at 12:20:59PM +0200, Johannes Berg wrote:
> On Fri, 2019-06-14 at 12:11 +0200, Lorenzo Bianconi wrote:
> 
> > Looking at __ieee80211_amsdu_copy() now I got why other drivers copy hdrlen 
> > +
> > 8, thx :)
> > In our case reuse_frag is true in __ieee80211_amsdu_copy, so we will end up
> > copying 32B + ether_len. Anyway I think 32 is a little bit too low and we 
> > could get
> > better performances increasing it a little bit.
> > A typical use case (e.g IPv6 + TCP):
> > 
> > IPv6 = 40B, TCP = 32B --> so 72B..I guess 128B is a good value :)
> > @Felix, Johannes: what do you think?
> 
> I think while we might *allocate* more, I don't think we should *copy*
> more, since then the TCP payload will no longer be in pages.
> 
> It'd probably be better to implement leaving enough tailroom (allocate
> 128), but copying nothing, unless the *entire* packet fits.

iwl4965 put entire packet in fragment in il4965_pass_packet_to_mac80211() .
Initially I thought this is a bug, since mac80211 require header be
in the linear area, but looks like ieee80211_rx_monitor() copy header
before rest of mac80211 check it, so 4965 is fine.

Anyway I think the driver should put ieee80211 header in linear area
and iwlwifi & mt7601u implementation is somewhat optimal.

Stanislaw


Re: [PATCH v3 wireless-drivers 1/3] mt76: usb: fix rx A-MSDU support

2019-06-14 Thread Stanislaw Gruszka
On Fri, Jun 14, 2019 at 12:11:17PM +0200, Lorenzo Bianconi wrote:
> > On Thu, Jun 13, 2019 at 11:43:11PM +0200, Lorenzo Bianconi wrote:
> > > Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
> > > for rx") breaks A-MSDU support. When A-MSDU is enable the device can
> > > receive frames up to q->buf_size but they will be discarded in
> > > mt76u_process_rx_entry since there is no enough room for
> > > skb_shared_info. Fix the issue reallocating the skb and copying in the
> > > linear area the first 128B of the received frames and in the frag_list
> > > the remaining part.
> > > 
> > > Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes 
> > > for rx")
> > > Signed-off-by: Lorenzo Bianconi 
> > > ---
> > >  drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
> > >  drivers/net/wireless/mediatek/mt76/usb.c  | 49 ++-
> > >  2 files changed, 41 insertions(+), 9 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
> > > b/drivers/net/wireless/mediatek/mt76/mt76.h
> > > index 8ecbf81a906f..889b76deb703 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> > > @@ -30,6 +30,7 @@
> > >  #define MT_TX_RING_SIZE 256
> > >  #define MT_MCU_RING_SIZE32
> > >  #define MT_RX_BUF_SIZE  2048
> > > +#define MT_SKB_HEAD_LEN 128
> > >  
> > >  struct mt76_dev;
> > >  struct mt76_wcid;
> > > diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
> > > b/drivers/net/wireless/mediatek/mt76/usb.c
> > > index bbaa1365bbda..12d60d31cb51 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/usb.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> > > @@ -429,6 +429,45 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 
> > > data_len)
> > >   return dma_len;
> > >  }
> > >  
> > > +static struct sk_buff *
> > > +mt76u_build_rx_skb(u8 *data, int len, int buf_size)
> > > +{
> > > + struct sk_buff *skb;
> > > +
> > > + if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) {
> > > + struct page *page;
> > > + int offset;
> > > +
> > > + /* slow path, not enough space for data and
> > > +  * skb_shared_info
> > > +  */
> > > + skb = alloc_skb(MT_SKB_HEAD_LEN, GFP_ATOMIC);
> > > + if (!skb)
> > > + return NULL;
> > > +
> > > + skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN);
> > 
> > I looked how rx amsdu is processed in mac80211 and it is decomposed and
> > copied into newly allocated individual skb's, see ieee80211_amsdu_to_8023s()
> > 
> > So copy L3 & L4 headers doesn't do anything good here, actually seems to
> > be better to have them in frag as __ieee80211_amsdu_copy_frag() do some
> > magic to avid copy.
> 
> Looking at __ieee80211_amsdu_copy() now I got why other drivers copy hdrlen +
> 8, thx :)
> In our case reuse_frag is true in __ieee80211_amsdu_copy, so we will end up

I don't think reuse_frag is true in our case since skb->head_frag is
not set when we use alloc_skb(). 

Stanislaw


Re: [PATCH v3 wireless-drivers 3/3] mt76: usb: do not always copy the first part of received frames

2019-06-14 Thread Stanislaw Gruszka
On Fri, Jun 14, 2019 at 12:22:48PM +0200, Lorenzo Bianconi wrote:
> > On Thu, Jun 13, 2019 at 11:43:13PM +0200, Lorenzo Bianconi wrote:
> > > Set usb buffer size taking into account skb_shared_info in order to
> > > not always copy the first part of received frames if A-MSDU is enabled
> > > for SG capable devices. Moreover align usb buffer size to max_ep
> > > boundaries and set buf_size to PAGE_SIZE even for sg case
> > 
> > I think this should not be applied to wirless-drivers, only first patch
> > that fix the bug and optimizations should be done in -next.
> 
> ack, right. I think patch 2/3 and 3/3 can go directly in Felix's tree
> 
> > 
> > > + int i, data_size;
> > >  
> > > + data_size = rounddown(SKB_WITH_OVERHEAD(q->buf_size),
> > > +   dev->usb.in_ep[MT_EP_IN_PKT_RX].max_packet);
> > >   for (i = 0; i < nsgs; i++) {
> > >   struct page *page;
> > >   void *data;
> > > @@ -302,7 +304,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct 
> > > mt76_queue *q, struct urb *urb,
> > >  
> > >   page = virt_to_head_page(data);
> > >   offset = data - page_address(page);
> > > - sg_set_page(&urb->sg[i], page, q->buf_size, offset);
> > > + sg_set_page(&urb->sg[i], page, data_size, offset);
> > 
> > > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > >   q->ndesc = MT_NUM_RX_ENTRIES;
> > > + q->buf_size = PAGE_SIZE;
> > > +
> > 
> > This should be associated with decrease of MT_SG_MAX_SIZE to value that
> > is actually needed and currently this is 2 for 4k AMSDU.
> 
> MT_SG_MAX_SIZE is used even on tx side and I do not think we will end up with 
> a
> huge difference here

So use different value as argument for mt76u_fill_rx_sg() in
mt76u_rx_urb_alloc(). After changing buf_size to PAGE_SIZE we will
allocate 8 pages per rx queue entry, but only 2 pages will be used
(with data_size change, 1 without data_size change). Or I'm wrong?

> > However I don't think allocating 2 pages to avoid ieee80211 header and SNAP
> > copy is worth to do. For me best approach would be allocate 1 page for
> > 4k AMSDU, 2 for 8k and 3 for 12k (still using sg, but without data_size
> > change to avoid 32B copying).
> 
> From my point of view it is better to avoid copying if it is possible. Are you
> sure there is no difference?

I do not understand what you mean by difference here.

Stanislaw


Re: [PATCH v3 wireless-drivers 3/3] mt76: usb: do not always copy the first part of received frames

2019-06-14 Thread Stanislaw Gruszka
On Thu, Jun 13, 2019 at 11:43:13PM +0200, Lorenzo Bianconi wrote:
> Set usb buffer size taking into account skb_shared_info in order to
> not always copy the first part of received frames if A-MSDU is enabled
> for SG capable devices. Moreover align usb buffer size to max_ep
> boundaries and set buf_size to PAGE_SIZE even for sg case

I think this should not be applied to wirless-drivers, only first patch
that fix the bug and optimizations should be done in -next.

> + int i, data_size;
>  
> + data_size = rounddown(SKB_WITH_OVERHEAD(q->buf_size),
> +   dev->usb.in_ep[MT_EP_IN_PKT_RX].max_packet);
>   for (i = 0; i < nsgs; i++) {
>   struct page *page;
>   void *data;
> @@ -302,7 +304,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue 
> *q, struct urb *urb,
>  
>   page = virt_to_head_page(data);
>   offset = data - page_address(page);
> - sg_set_page(&urb->sg[i], page, q->buf_size, offset);
> + sg_set_page(&urb->sg[i], page, data_size, offset);

> - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
>   q->ndesc = MT_NUM_RX_ENTRIES;
> + q->buf_size = PAGE_SIZE;
> +

This should be associated with decrease of MT_SG_MAX_SIZE to value that
is actually needed and currently this is 2 for 4k AMSDU.

However I don't think allocating 2 pages to avoid ieee80211 header and SNAP
copy is worth to do. For me best approach would be allocate 1 page for
4k AMSDU, 2 for 8k and 3 for 12k (still using sg, but without data_size
change to avoid 32B copying).

Stanislaw


Re: [PATCH v3 wireless-drivers 1/3] mt76: usb: fix rx A-MSDU support

2019-06-14 Thread Stanislaw Gruszka
On Thu, Jun 13, 2019 at 11:43:11PM +0200, Lorenzo Bianconi wrote:
> Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
> for rx") breaks A-MSDU support. When A-MSDU is enable the device can
> receive frames up to q->buf_size but they will be discarded in
> mt76u_process_rx_entry since there is no enough room for
> skb_shared_info. Fix the issue reallocating the skb and copying in the
> linear area the first 128B of the received frames and in the frag_list
> the remaining part.
> 
> Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes for 
> rx")
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
>  drivers/net/wireless/mediatek/mt76/usb.c  | 49 ++-
>  2 files changed, 41 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
> b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 8ecbf81a906f..889b76deb703 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -30,6 +30,7 @@
>  #define MT_TX_RING_SIZE 256
>  #define MT_MCU_RING_SIZE32
>  #define MT_RX_BUF_SIZE  2048
> +#define MT_SKB_HEAD_LEN 128
>  
>  struct mt76_dev;
>  struct mt76_wcid;
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
> b/drivers/net/wireless/mediatek/mt76/usb.c
> index bbaa1365bbda..12d60d31cb51 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -429,6 +429,45 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
>   return dma_len;
>  }
>  
> +static struct sk_buff *
> +mt76u_build_rx_skb(u8 *data, int len, int buf_size)
> +{
> + struct sk_buff *skb;
> +
> + if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) {
> + struct page *page;
> + int offset;
> +
> + /* slow path, not enough space for data and
> +  * skb_shared_info
> +  */
> + skb = alloc_skb(MT_SKB_HEAD_LEN, GFP_ATOMIC);
> + if (!skb)
> + return NULL;
> +
> + skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN);

I looked how rx amsdu is processed in mac80211 and it is decomposed and
copied into newly allocated individual skb's, see ieee80211_amsdu_to_8023s()

So copy L3 & L4 headers doesn't do anything good here, actually seems to
be better to have them in frag as __ieee80211_amsdu_copy_frag() do some
magic to avid copy.

Stanislaw


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-13 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 04:44:01PM +0200, Lorenzo Bianconi wrote:
> On Jun 12, Stanislaw Gruszka wrote:
> > On Wed, Jun 12, 2019 at 02:59:05PM +0200, Stanislaw Gruszka wrote:
> > > > > If max RX AMSDU size is 3839B I do not see reason why we allocate
> > > > > MT_SG_MAX_SIZE=8 of MT_RX_BUF_SIZE=2k buffers for sg_en case.
> > > > > I thought the reason is that max AMSDU size is 16kB so it fit into
> > > > > 8 sg buffers of 2k.
> > > > > 
> > > > > In other words, for me, looks like either
> > > > > - we can not handle AMSDU for non sg case because we do not
> > > > > allocate big enough buffer
> > > > 
> > > > I think AMSDU is mandatory and we currently support it even for non-sg 
> > > > case
> > > > (since max rx AMSDU is 3839B)
> > > > 
> > > > > or
> > > > > - we can just use one PAGE_SIZE buffer for rx and remove sg
> > > > > buffers for rx completely 
> > > > 
> > > > using sg buffers we can support bigger rx AMSDU size in the future 
> > > > without using
> > > > huge buffers (e.g. we can try to use IEEE80211_MAX_MPDU_LEN_HT_7935 with
> > > > mt76x2u)
> > > 
> > > I think it would be simpler just to allocate 2 pages for 7935B .
> > 
> > And if we could determine that there is no true need to use sg for rx,
> > I think best approach here would be revert f8f527b16db5 in v5.2 to fix
> > regression and remove rx sg in -next. That would make code simpler,
> > allocate 4k instead 16k per packet, allow to use build_skb (4096 - 3839
> > give enough space for shared info) and not use usb hcd bounce buffer.
> 
> I do not think we should drop sg support since:
> - it allow us to rx huge amsdu frames (e.g. IEEE80211_MAX_MPDU_LEN_VHT_11454)
>   using multiple one page buffer. I think there will be new usb devices where 
> we can
>   increase amsdu size (we can increase it even on mt76x2u usb 3.0 devices)

I looked at intel wifi drivers and this is handled by amsdu_size module
parameter, supported values are 4k, 8k and 12k. RX allocation size and
proper values in vht_cap & ht_cap are set accordingly. Assuming (some)
mt76 HW and FW can handle bigger AMSDUs I think we should do similar
thing.

Otherwise looks for me, we just waste memory and have not needed code
for no true reason. 

>   space needed for skb_shared_info is 320B on a x86_64 device

Uhh, I haven't expected that sk_shared_info() is that big, so indeed build_skb
could not used and 128B copy fallback will be necessary.


Stanislaw


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-13 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 04:27:42PM +0200, Lorenzo Bianconi wrote:
> > On Wed, Jun 12, 2019 at 02:28:48PM +0200, Lorenzo Bianconi wrote:
> 
> [...]
> 
> > > 
> > > using sg buffers we can support bigger rx AMSDU size in the future 
> > > without using
> > > huge buffers (e.g. we can try to use IEEE80211_MAX_MPDU_LEN_HT_7935 with
> > > mt76x2u)
> > I think it would be simpler just to allocate 2 pages for 7935B .
> > 
> 
> We should avoid increasing buffer size to more than PAGE_SIZE for
> performance reasons.

Interesting, at what place and how this affect performance negatively ?

> As suggested by Felix what about of setting buf_size to
> PAGE_SIZE for both sg and non-sg cases and for sg setting usb data size to
> 
> SKB_WITH_OVERHEAD(q->buf_size) & (usb_endpoint_maxp() - 1);

Increasing to PAGE_SIZE for sg looks reasonable to me.

Not sure if understand data_size logic. If this mean 'PAGE_SIZE - 
usb_endpint_maxp()',
looks ok to me as well (for first segment), but would require one extra segment
to avoid coping (i.e. 2 pages for 3839 , 3 pages for 7935 ...) If we would 
like to stay with 128B copy fallback, we can have 1 page for 3839 , 2 for 7935 
...

It would be interesting how frequently AMSDU of max size is sent by
remote station. If this is rare situation I would be opting for
smaller allocation and 128B copy fallback. If this is frequent
for bigger allocation to assure we can always use build_skb().

Stanislaw 


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-13 Thread Stanislaw Gruszka
Hi

On Thu, Jun 13, 2019 at 10:26:38AM +0200, Lorenzo Bianconi wrote:
> [...]
> 
> > I looked at intel wifi drivers and this is handled by amsdu_size module
> > parameter, supported values are 4k, 8k and 12k. RX allocation size and
> > proper values in vht_cap & ht_cap are set accordingly. Assuming (some)
> > mt76 HW and FW can handle bigger AMSDUs I think we should do similar
> > thing.
> > 
> > Otherwise looks for me, we just waste memory and have not needed code
> > for no true reason. 
> > 
> > >   space needed for skb_shared_info is 320B on a x86_64 device
> > 
> > Uhh, I haven't expected that sk_shared_info() is that big, so indeed 
> > build_skb
> > could not used and 128B copy fallback will be necessary.
> 
> Hi Stanislaw,
> 
> reviewing the original patch I think we can't trigger any IOMMU bug since the
> usb buffer length is actually 2048 and not 2048 + skb_shared_info_size:

I'm concerned about alignment and crossing pages boundaries. If you
allocate via page_frag_alloc() buffers, except first one, will have
'not natural' alignment and every second will be spanned across
two pages.

Stanislaw



Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 02:59:05PM +0200, Stanislaw Gruszka wrote:
> > > If max RX AMSDU size is 3839B I do not see reason why we allocate
> > > MT_SG_MAX_SIZE=8 of MT_RX_BUF_SIZE=2k buffers for sg_en case.
> > > I thought the reason is that max AMSDU size is 16kB so it fit into
> > > 8 sg buffers of 2k.
> > > 
> > > In other words, for me, looks like either
> > > - we can not handle AMSDU for non sg case because we do not
> > > allocate big enough buffer
> > 
> > I think AMSDU is mandatory and we currently support it even for non-sg case
> > (since max rx AMSDU is 3839B)
> > 
> > > or
> > > - we can just use one PAGE_SIZE buffer for rx and remove sg
> > > buffers for rx completely 
> > 
> > using sg buffers we can support bigger rx AMSDU size in the future without 
> > using
> > huge buffers (e.g. we can try to use IEEE80211_MAX_MPDU_LEN_HT_7935 with
> > mt76x2u)
> 
> I think it would be simpler just to allocate 2 pages for 7935B .

And if we could determine that there is no true need to use sg for rx,
I think best approach here would be revert f8f527b16db5 in v5.2 to fix
regression and remove rx sg in -next. That would make code simpler,
allocate 4k instead 16k per packet, allow to use build_skb (4096 - 3839
give enough space for shared info) and not use usb hcd bounce buffer.

Stanislaw


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 02:28:48PM +0200, Lorenzo Bianconi wrote:
> [...]
> > 
> > My sense of humor declined quite drastically lastly ;-/
> > 
> > > > > but we can be more cautious since probably copying
> > > > > the first 128B will not make any difference
> > > > 
> > > > Not sure if I understand what you mean.
> > > 
> > > Please correct me if I am wrong but I think max amsdu rx size is 3839B for
> > > mt76. For the sg_en case this frame will span over multiple sg buffers 
> > > since
> > > sg buffer size is 2048B (2 sg buffers). Moreover if we do not take into 
> > > account
> > > skb_shared_info when configuring the sg buffer size we will need to 
> > > always copy
> > > the first 128B of the first buffer since received len will be set to 2048 
> > > and
> > > the following if condition will always fail:
> > > 
> > > if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) {
> > > }
> > 
> > Ok, that I understand.
> > 
> > > > > > And skb_shered_info is needed only in first buffer IIUC.
> > > > > > 
> > > > > > Also this patch seems to make first patch unnecessary except for
> > > > > > non sg_en case (in which I think rx AMSDU is broken anyway),
> > > > > > so I would prefer just to apply first patch.
> > > > > 
> > > > > I do not think rx AMSDU is broken for non sg_en case since the max rx 
> > > > > value
> > > > > allowed should be 3839 IIRC and we alloc one page in this case
> > > > 
> > > > If that's the case we should be fine, but then I do not understand
> > > > why we allocate 8*2k buffers for sg_en case, isn't that AP can
> > > > sent AMSDU frame 16k big?
> > > 
> > > Sorry I did not get what you mean here, could you please explain?
> > 
> > If max RX AMSDU size is 3839B I do not see reason why we allocate
> > MT_SG_MAX_SIZE=8 of MT_RX_BUF_SIZE=2k buffers for sg_en case.
> > I thought the reason is that max AMSDU size is 16kB so it fit into
> > 8 sg buffers of 2k.
> > 
> > In other words, for me, looks like either
> > - we can not handle AMSDU for non sg case because we do not
> > allocate big enough buffer
> 
> I think AMSDU is mandatory and we currently support it even for non-sg case
> (since max rx AMSDU is 3839B)
> 
> > or
> > - we can just use one PAGE_SIZE buffer for rx and remove sg
> > buffers for rx completely 
> 
> using sg buffers we can support bigger rx AMSDU size in the future without 
> using
> huge buffers (e.g. we can try to use IEEE80211_MAX_MPDU_LEN_HT_7935 with
> mt76x2u)

I think it would be simpler just to allocate 2 pages for 7935B .

Stanislaw 


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 12:49:22PM +0200, Lorenzo Bianconi wrote:
> > On Wed, Jun 12, 2019 at 11:53:03AM +0200, Lorenzo Bianconi wrote:
> > > > On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
> > > 
> > > [...]
> > > 
> > > > >   }
> > > > >  
> > > > >   urb->num_sgs = max_t(int, i, urb->num_sgs);
> > > > > - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> > > > > + urb->transfer_buffer_length = urb->num_sgs * data_size;
> > > > >   sg_init_marker(urb->sg, urb->num_sgs);
> > > > >  
> > > > >   return i ? : -ENOMEM;
> > > > > @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> > > > >   if (!q->entry)
> > > > >   return -ENOMEM;
> > > > >  
> > > > > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > > > > + if (dev->usb.sg_en)
> > > > > + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);
> > > > 
> > > > I strongly recommend to not doing this. While this should work
> > > > in theory creating buffer with size of 2k + some bytes might
> > > > trigger various bugs in dma mapping or other low level code.
> > > 
> > > even in practice actually :)
> > 
> > I wouldn't be sure about this. It's not common to have buffers of
> > such size and crossing pages boundaries. It really can trigger
> > nasty bugs on various IOMMU drivers.
> 
> I was just joking, I mean that it worked in the tests I carried out, but I
> agree it can trigger some issues in buggy IOMMU drivers

My sense of humor declined quite drastically lastly ;-/

> > > but we can be more cautious since probably copying
> > > the first 128B will not make any difference
> > 
> > Not sure if I understand what you mean.
> 
> Please correct me if I am wrong but I think max amsdu rx size is 3839B for
> mt76. For the sg_en case this frame will span over multiple sg buffers since
> sg buffer size is 2048B (2 sg buffers). Moreover if we do not take into 
> account
> skb_shared_info when configuring the sg buffer size we will need to always 
> copy
> the first 128B of the first buffer since received len will be set to 2048 and
> the following if condition will always fail:
> 
> if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) {
> }

Ok, that I understand.

> > > > And skb_shered_info is needed only in first buffer IIUC.
> > > > 
> > > > Also this patch seems to make first patch unnecessary except for
> > > > non sg_en case (in which I think rx AMSDU is broken anyway),
> > > > so I would prefer just to apply first patch.
> > > 
> > > I do not think rx AMSDU is broken for non sg_en case since the max rx 
> > > value
> > > allowed should be 3839 IIRC and we alloc one page in this case
> > 
> > If that's the case we should be fine, but then I do not understand
> > why we allocate 8*2k buffers for sg_en case, isn't that AP can
> > sent AMSDU frame 16k big?
> 
> Sorry I did not get what you mean here, could you please explain?

If max RX AMSDU size is 3839B I do not see reason why we allocate
MT_SG_MAX_SIZE=8 of MT_RX_BUF_SIZE=2k buffers for sg_en case.
I thought the reason is that max AMSDU size is 16kB so it fit into
8 sg buffers of 2k.

In other words, for me, looks like either
- we can not handle AMSDU for non sg case because we do not
allocate big enough buffer
or
- we can just use one PAGE_SIZE buffer for rx and remove sg
buffers for rx completely 

Do I miss something ?

Stanislaw


Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 12:21:34PM +0200, Lorenzo Bianconi wrote:
> On Jun 12, Stanislaw Gruszka wrote:
> > On Wed, Jun 12, 2019 at 11:45:21AM +0200, Lorenzo Bianconi wrote:
> > > > > +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> > > > > +int *nsgs)
> > > > > +{
> > > > > + int data_len = min(len, MT_SKB_HEAD_LEN);
> > 
> > Oh, and this looks unneeded as well as for len < MT_SKB_HEAD_LEN=128
> > we will go through fast path.
> 
> I guess if we remove data_len = min(len, MT_SKB_HEAD_LEN) and even *nsgs = 0 
> at
> the end we are making some assumptions on the value of MT_SKB_HEAD_LEN and
> buf_size. In the patch I just avoided them but maybe we can just assume that
> MT_SKB_HEAD_LEN and buf_size will not changed in the future. What do you
> think?

Yes, sure. Other drivers just use 128 value directly and don't even
create a macro for that. And if somebody will decide to change
buf_size it will not be small value.

> > > > mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
> > > > of the buffer in fragment, which supose to be more efficient,
> > > > see comment in iwl_mvm_pass_packet_to_mac80211().
> > > 
> > > Right here we copy 128B instead of 32 but I think it is good to have L3 
> > > and L4
> > > header in the linear area of the skb since otherwise the stack will need 
> > > to
> > > align them
> > 
> > Not sure if understand, I think aliment of L3 & L4 headers will be
> > the same, assuming ieee80211 header is aligned the same in fragment
> > buffer and in linear area. But if you think this is better to copy those
> > to linear area I'm ok with that.
> 
> Sorry I have not been so clear. I mean in the stack before accessing a given
> header we will run pskb_may_pull() that can end up copying the skb if there is
> not enough space in the skb->head

Ok, so L3 and L4 headers should be in linear area of skb and if not 
network stack will copy them from fragment. But I wonder why other
drivers just copy ieee80211_hdr and SNAP ? Isn't that if we copy 
128B then is possible that part of the payload will be in linear
area and part in fragment, whereas is expected that payload
will not be broken into two parts?

Stanislaw


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 11:53:03AM +0200, Lorenzo Bianconi wrote:
> > On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
> 
> [...]
> 
> > >   }
> > >  
> > >   urb->num_sgs = max_t(int, i, urb->num_sgs);
> > > - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> > > + urb->transfer_buffer_length = urb->num_sgs * data_size;
> > >   sg_init_marker(urb->sg, urb->num_sgs);
> > >  
> > >   return i ? : -ENOMEM;
> > > @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> > >   if (!q->entry)
> > >   return -ENOMEM;
> > >  
> > > - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> > > + if (dev->usb.sg_en)
> > > + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);
> > 
> > I strongly recommend to not doing this. While this should work
> > in theory creating buffer with size of 2k + some bytes might
> > trigger various bugs in dma mapping or other low level code.
> 
> even in practice actually :)

I wouldn't be sure about this. It's not common to have buffers of
such size and crossing pages boundaries. It really can trigger
nasty bugs on various IOMMU drivers.

> but we can be more cautious since probably copying
> the first 128B will not make any difference

Not sure if I understand what you mean.

> > And skb_shered_info is needed only in first buffer IIUC.
> > 
> > Also this patch seems to make first patch unnecessary except for
> > non sg_en case (in which I think rx AMSDU is broken anyway),
> > so I would prefer just to apply first patch.
> 
> I do not think rx AMSDU is broken for non sg_en case since the max rx value
> allowed should be 3839 IIRC and we alloc one page in this case

If that's the case we should be fine, but then I do not understand
why we allocate 8*2k buffers for sg_en case, isn't that AP can
sent AMSDU frame 16k big?

Stanislaw



Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support

2019-06-12 Thread Stanislaw Gruszka
On Wed, Jun 12, 2019 at 11:45:21AM +0200, Lorenzo Bianconi wrote:
> > > +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> > > +int *nsgs)
> > > +{
> > > + int data_len = min(len, MT_SKB_HEAD_LEN);

Oh, and this looks unneeded as well as for len < MT_SKB_HEAD_LEN=128
we will go through fast path.

> > mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
> > of the buffer in fragment, which supose to be more efficient,
> > see comment in iwl_mvm_pass_packet_to_mac80211().
> 
> Right here we copy 128B instead of 32 but I think it is good to have L3 and L4
> header in the linear area of the skb since otherwise the stack will need to
> align them

Not sure if understand, I think aliment of L3 & L4 headers will be
the same, assuming ieee80211 header is aligned the same in fragment
buffer and in linear area. But if you think this is better to copy those
to linear area I'm ok with that.

Stanislaw


Re: rtw88: M.2 RTL8822BE not working - rfe 3 isn't supported

2019-06-12 Thread Stanislaw Gruszka
Cc Tony 

On Sat, Jun 08, 2019 at 02:26:51PM +0200, g.schlmm wrote:
> my RTL8822BE M.2 card is not working with linux 5.2rc3
> 
> the staging r8822be driver in linux 5.1 was working for this card
> 
> from dmesg:
> > [8.001186] rtw_pci :04:00.0: rfe 3 isn't supported  
> >
> > [8.003870] rtw_pci :04:00.0: failed to setup chip efuse info
> >
> > [8.006405] rtw_pci :04:00.0: failed to setup chip information 
> 
> lspci:
> > 04:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. RTL8822BE 
> > 802.11a/b/g/n/ac WiFi adapter
> > Subsystem: Lenovo RTL8822BE 802.11a/b/g/n/ac WiFi adapter
> > Flags: fast devsel, IRQ 19
> > I/O ports at c000 [size=256]
> > Memory at 8120 (64-bit, non-prefetchable) [size=64K]
> > Capabilities: [40] Power Management version 3
> > Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> > Capabilities: [70] Express Endpoint, MSI 00
> > Capabilities: [100] Advanced Error Reporting
> > Capabilities: [148] Device Serial Number 00-e0-4c-ff-fe-b8-22-01
> > Capabilities: [158] Latency Tolerance Reporting
> > Capabilities: [160] L1 PM Substates
> > Kernel modules: rtwpci


Re: [PATCH v2 2/2] mt76: usb: do not always copy the first part of received frames

2019-06-12 Thread Stanislaw Gruszka
On Fri, May 31, 2019 at 11:38:23AM +0200, Lorenzo Bianconi wrote:
> Set usb buffer size taking into account skb_shared_info in order to
> not always copy the first part of received frames if A-MSDU is enabled
> for SG capable devices
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/mt76.h |  3 +++
>  drivers/net/wireless/mediatek/mt76/usb.c  | 12 
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
> b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 74d4edf941d6..7899e9b88b54 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -32,6 +32,9 @@
>  #define MT_RX_BUF_SIZE  2048
>  #define MT_SKB_HEAD_LEN 128
>  
> +#define MT_BUF_WITH_OVERHEAD(x) \
> + ((x) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
> +
>  struct mt76_dev;
>  struct mt76_wcid;
>  
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
> b/drivers/net/wireless/mediatek/mt76/usb.c
> index 2bfc8214c0d8..5081643ce701 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -286,7 +286,7 @@ static int
>  mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
>int nsgs, gfp_t gfp)
>  {
> - int i;
> + int i, data_size = SKB_WITH_OVERHEAD(q->buf_size);
>  
>   for (i = 0; i < nsgs; i++) {
>   struct page *page;
> @@ -299,7 +299,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue 
> *q, struct urb *urb,
>  
>   page = virt_to_head_page(data);
>   offset = data - page_address(page);
> - sg_set_page(&urb->sg[i], page, q->buf_size, offset);
> + sg_set_page(&urb->sg[i], page, data_size, offset);
>   }
>  
>   if (i < nsgs) {
> @@ -311,7 +311,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue 
> *q, struct urb *urb,
>   }
>  
>   urb->num_sgs = max_t(int, i, urb->num_sgs);
> - urb->transfer_buffer_length = urb->num_sgs * q->buf_size,
> + urb->transfer_buffer_length = urb->num_sgs * data_size;
>   sg_init_marker(urb->sg, urb->num_sgs);
>  
>   return i ? : -ENOMEM;
> @@ -611,8 +611,12 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
>   if (!q->entry)
>   return -ENOMEM;
>  
> - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> + if (dev->usb.sg_en)
> + q->buf_size = MT_BUF_WITH_OVERHEAD(MT_RX_BUF_SIZE);

I strongly recommend to not doing this. While this should work
in theory creating buffer with size of 2k + some bytes might
trigger various bugs in dma mapping or other low level code.

And skb_shered_info is needed only in first buffer IIUC.

Also this patch seems to make first patch unnecessary except for
non sg_en case (in which I think rx AMSDU is broken anyway),
so I would prefer just to apply first patch.

Stanislaw



Re: [PATCH v2 1/2] mt76: usb: fix rx A-MSDU support

2019-06-12 Thread Stanislaw Gruszka
Hi and sorry for late comment.

On Fri, May 31, 2019 at 11:38:22AM +0200, Lorenzo Bianconi wrote:
> Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
> for rx") breaks A-MSDU support. When A-MSDU is enable the device can
> receive frames up to q->buf_size but they will be discarded in
> mt76u_process_rx_entry since there is no enough room for
> skb_shared_info. Fix the issue reallocating the skb and copying in the
> linear area the first 128B of the received frames and in the frag_list
> the remaining part.
> 
> Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes for 
> rx")
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
>  drivers/net/wireless/mediatek/mt76/usb.c  | 52 +++
>  2 files changed, 44 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
> b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 97a1296562d0..74d4edf941d6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -30,6 +30,7 @@
>  #define MT_TX_RING_SIZE 256
>  #define MT_MCU_RING_SIZE32
>  #define MT_RX_BUF_SIZE  2048
> +#define MT_SKB_HEAD_LEN 128
>  
>  struct mt76_dev;
>  struct mt76_wcid;
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
> b/drivers/net/wireless/mediatek/mt76/usb.c
> index bbaa1365bbda..2bfc8214c0d8 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -429,6 +429,48 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
>   return dma_len;
>  }
>  
> +static struct sk_buff *
> +mt76u_build_rx_skb(u8 *data, int len, int buf_size,
> +int *nsgs)
> +{
> + int data_len = min(len, MT_SKB_HEAD_LEN);
> + struct sk_buff *skb;
> +
> + if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) {
> + /* fast path */
> + skb = build_skb(data, buf_size);
> + if (!skb)
> + return NULL;
> +
> + skb_reserve(skb, MT_DMA_HDR_LEN);
> + __skb_put(skb, len);
> +
> + return skb;
> + }
> +
> + /* slow path, not enough space for data and
> +  * skb_shared_info
> +  */
> + skb = alloc_skb(data_len, GFP_ATOMIC);
> + if (!skb)
> + return NULL;
> +
> + skb_put_data(skb, data + MT_DMA_HDR_LEN, data_len);
mt7601u and iwlmvm just copy hdrlen + 8 and put the rest
of the buffer in fragment, which supose to be more efficient,
see comment in iwl_mvm_pass_packet_to_mac80211().
 
> + data += (data_len + MT_DMA_HDR_LEN);
> + len -= data_len;
> + if (len > 0) {
> + struct page *page = virt_to_head_page(data);
> + int offset = data - (u8 *)page_address(page);
u8 cast not needed.

> + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
> + page, offset, len, buf_size);
> + } else {
> + *nsgs = 0;
This seems to be not necessary or a bug (use first buffer 2 times). 

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Wed, May 15, 2019 at 03:48:29PM +0200, Stanislaw Gruszka wrote:
> > Tx hangs occur in very particular conditions (e.g 200Mbps bidirectional
> > traffic) and moreover they do not always occur so I am not convinced they
> > are always EDCCA related and so I am not confident to remove the watchdog
> 
> I'm not opting for watchdog removal, but for full EDCCA removal.
On mt76x02, on other chips/firmwares it can work just fine.

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Wed, May 15, 2019 at 02:07:42PM +0200, Lorenzo Bianconi wrote:
> > On Wed, May 15, 2019 at 01:13:49PM +0200, Lorenzo Bianconi wrote:
> > > > On Wed, May 15, 2019 at 12:03:44PM +0200, Lorenzo Bianconi wrote:
> > > > > > On Wed, May 15, 2019 at 11:43:55AM +0200, Lorenzo Bianconi wrote:
> > > > > > > > On Mon, May 13, 2019 at 11:48:37AM +0200, Stanislaw Gruszka 
> > > > > > > > wrote:
> > > > > > > > > On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi 
> > > > > > > > > wrote:
> > > > > > > > > > > Lorenzo Bianconi  writes:
> > > > > > > > > > > 
> > > > > > > > > > > > Introduce a knob in mt7603 debugfs in order to 
> > > > > > > > > > > > enable/disable
> > > > > > > > > > > > edcca processing
> > > > > > > > > > > >
> > > > > > > > > > > > Signed-off-by: Lorenzo Bianconi 
> > > > > > > > > > > 
> > > > > > > > > > > It's good to explain what edcca does and how the file is 
> > > > > > > > > > > used supposed
> > > > > > > > > > > to be used. In other words, have a small introduction for 
> > > > > > > > > > > the user.
> > > > > > > > > > 
> > > > > > > > > > Hi Kalle,
> > > > > > > > > > 
> > > > > > > > > > edcca is used for adjusting energy detect based on CCA 
> > > > > > > > > > thresholds.
> > > > > > > > > > The code was already there so I just reported the acronym.
> > > > > > > > > 
> > > > > > > > > What for it is needed ?
> > > > > > > > 
> > > > > > > > Care to comment why EDCCA is needed at all ?
> > > > > > > > 
> > > > > > > > Taking that debugfs file that enable it is read-only, it looks 
> > > > > > > > like
> > > > > > > > feature that nobody needs nor tests.
> > > > > > > 
> > > > > > > already fixed in v2
> > > > > > > https://patchwork.kernel.org/patch/10940645/
> > > > > > 
> > > > > > I'm aware of this patch and other one for mt76x02. But so far in the
> > > > > > sources EDCCA is disabled for mt76x02 without possibility to enable 
> > > > > > it
> > > > > > (and this permission file issue was pointed by Kalle during review, 
> > > > > > not
> > > > > > by someone who want to test EDCCA). So again, what for EDCCA is 
> > > > > > needed ?
> > > > > 
> > > > > As I have already written in a previous email, ED/CCA is used to 
> > > > > control tx power
> > > > > according to the CCA MIB counters (e.g do not transmit if the channel 
> > > > > busy time
> > > > > is higher than 90% for given amount of time in a row). I guess it is 
> > > > > required
> > > > > by ETSI regulatory.
> > > > But what is user case for that, i.e. who need this (it wasn't 
> > > > implemented in
> > > > mt76x2 since you added it on Dec 2018). What will happen if it will be 
> > > > removed?
> > > > 
> > > > > Regarding file permission for mt76x02 debugfs edcca node is a typo.
> > > > Typo or not, effectively disable the feature and show nobody is
> > > > testing it.
> > > > 
> > > > The reason I'm asking is that seems EDCCA is the main reason to
> > > > implement watchod for mt76x2, it wasn't necessary to have a watchdog
> > > > as seems devices did not hung before EDCCA was added.
> > > 
> > > IIRC I added the first watchdog implementation to fix tx hangs that occur
> > > under heavy load even using FCC regulatory (so when EDCCA processing is
> > > disabled)
> > 
> > There was changes in various registers programming introduced by EDCCA
> > support, even with EDCCA disabled. It's rally not convenient that
> > watchdog and EDCCA are not related, since you added tx hung watchdog
> > 2 weeks after adding EDCCA.
> > 
> > You can look at this report:
> > https://github.com/openwrt/mt76/issues/246
> > Before mt76x2e worked without hungs & watchodg. Now, even with EDCCA
> > disabled watchdog and HW restarts are required to fix hungs on runtime.
> 
> Tx hangs occur in very particular conditions (e.g 200Mbps bidirectional
> traffic) and moreover they do not always occur so I am not convinced they
> are always EDCCA related and so I am not confident to remove the watchdog

I'm not opting for watchdog removal, but for full EDCCA removal.
Apparently nobody cares, if it can be enabled or not.

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Wed, May 15, 2019 at 01:13:49PM +0200, Lorenzo Bianconi wrote:
> > On Wed, May 15, 2019 at 12:03:44PM +0200, Lorenzo Bianconi wrote:
> > > > On Wed, May 15, 2019 at 11:43:55AM +0200, Lorenzo Bianconi wrote:
> > > > > > On Mon, May 13, 2019 at 11:48:37AM +0200, Stanislaw Gruszka wrote:
> > > > > > > On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi wrote:
> > > > > > > > > Lorenzo Bianconi  writes:
> > > > > > > > > 
> > > > > > > > > > Introduce a knob in mt7603 debugfs in order to 
> > > > > > > > > > enable/disable
> > > > > > > > > > edcca processing
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Lorenzo Bianconi 
> > > > > > > > > 
> > > > > > > > > It's good to explain what edcca does and how the file is used 
> > > > > > > > > supposed
> > > > > > > > > to be used. In other words, have a small introduction for the 
> > > > > > > > > user.
> > > > > > > > 
> > > > > > > > Hi Kalle,
> > > > > > > > 
> > > > > > > > edcca is used for adjusting energy detect based on CCA 
> > > > > > > > thresholds.
> > > > > > > > The code was already there so I just reported the acronym.
> > > > > > > 
> > > > > > > What for it is needed ?
> > > > > > 
> > > > > > Care to comment why EDCCA is needed at all ?
> > > > > > 
> > > > > > Taking that debugfs file that enable it is read-only, it looks like
> > > > > > feature that nobody needs nor tests.
> > > > > 
> > > > > already fixed in v2
> > > > > https://patchwork.kernel.org/patch/10940645/
> > > > 
> > > > I'm aware of this patch and other one for mt76x02. But so far in the
> > > > sources EDCCA is disabled for mt76x02 without possibility to enable it
> > > > (and this permission file issue was pointed by Kalle during review, not
> > > > by someone who want to test EDCCA). So again, what for EDCCA is needed ?
> > > 
> > > As I have already written in a previous email, ED/CCA is used to control 
> > > tx power
> > > according to the CCA MIB counters (e.g do not transmit if the channel 
> > > busy time
> > > is higher than 90% for given amount of time in a row). I guess it is 
> > > required
> > > by ETSI regulatory.
> > But what is user case for that, i.e. who need this (it wasn't implemented in
> > mt76x2 since you added it on Dec 2018). What will happen if it will be 
> > removed?
> > 
> > > Regarding file permission for mt76x02 debugfs edcca node is a typo.
> > Typo or not, effectively disable the feature and show nobody is
> > testing it.
> > 
> > The reason I'm asking is that seems EDCCA is the main reason to
> > implement watchod for mt76x2, it wasn't necessary to have a watchdog
> > as seems devices did not hung before EDCCA was added.
> 
> IIRC I added the first watchdog implementation to fix tx hangs that occur
> under heavy load even using FCC regulatory (so when EDCCA processing is
> disabled)

There was changes in various registers programming introduced by EDCCA
support, even with EDCCA disabled. It's rally not convenient that
watchdog and EDCCA are not related, since you added tx hung watchdog
2 weeks after adding EDCCA.

You can look at this report:
https://github.com/openwrt/mt76/issues/246
Before mt76x2e worked without hungs & watchodg. Now, even with EDCCA
disabled watchdog and HW restarts are required to fix hungs on runtime.

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Wed, May 15, 2019 at 12:03:44PM +0200, Lorenzo Bianconi wrote:
> > On Wed, May 15, 2019 at 11:43:55AM +0200, Lorenzo Bianconi wrote:
> > > > On Mon, May 13, 2019 at 11:48:37AM +0200, Stanislaw Gruszka wrote:
> > > > > On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi wrote:
> > > > > > > Lorenzo Bianconi  writes:
> > > > > > > 
> > > > > > > > Introduce a knob in mt7603 debugfs in order to enable/disable
> > > > > > > > edcca processing
> > > > > > > >
> > > > > > > > Signed-off-by: Lorenzo Bianconi 
> > > > > > > 
> > > > > > > It's good to explain what edcca does and how the file is used 
> > > > > > > supposed
> > > > > > > to be used. In other words, have a small introduction for the 
> > > > > > > user.
> > > > > > 
> > > > > > Hi Kalle,
> > > > > > 
> > > > > > edcca is used for adjusting energy detect based on CCA thresholds.
> > > > > > The code was already there so I just reported the acronym.
> > > > > 
> > > > > What for it is needed ?
> > > > 
> > > > Care to comment why EDCCA is needed at all ?
> > > > 
> > > > Taking that debugfs file that enable it is read-only, it looks like
> > > > feature that nobody needs nor tests.
> > > 
> > > already fixed in v2
> > > https://patchwork.kernel.org/patch/10940645/
> > 
> > I'm aware of this patch and other one for mt76x02. But so far in the
> > sources EDCCA is disabled for mt76x02 without possibility to enable it
> > (and this permission file issue was pointed by Kalle during review, not
> > by someone who want to test EDCCA). So again, what for EDCCA is needed ?
> 
> As I have already written in a previous email, ED/CCA is used to control tx 
> power
> according to the CCA MIB counters (e.g do not transmit if the channel busy 
> time
> is higher than 90% for given amount of time in a row). I guess it is required
> by ETSI regulatory.
But what is user case for that, i.e. who need this (it wasn't implemented in
mt76x2 since you added it on Dec 2018). What will happen if it will be removed?

> Regarding file permission for mt76x02 debugfs edcca node is a typo.
Typo or not, effectively disable the feature and show nobody is
testing it.

The reason I'm asking is that seems EDCCA is the main reason to
implement watchod for mt76x2, it wasn't necessary to have a watchdog
as seems devices did not hung before EDCCA was added.

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Wed, May 15, 2019 at 11:43:55AM +0200, Lorenzo Bianconi wrote:
> > On Mon, May 13, 2019 at 11:48:37AM +0200, Stanislaw Gruszka wrote:
> > > On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi wrote:
> > > > > Lorenzo Bianconi  writes:
> > > > > 
> > > > > > Introduce a knob in mt7603 debugfs in order to enable/disable
> > > > > > edcca processing
> > > > > >
> > > > > > Signed-off-by: Lorenzo Bianconi 
> > > > > 
> > > > > It's good to explain what edcca does and how the file is used supposed
> > > > > to be used. In other words, have a small introduction for the user.
> > > > 
> > > > Hi Kalle,
> > > > 
> > > > edcca is used for adjusting energy detect based on CCA thresholds.
> > > > The code was already there so I just reported the acronym.
> > > 
> > > What for it is needed ?
> > 
> > Care to comment why EDCCA is needed at all ?
> > 
> > Taking that debugfs file that enable it is read-only, it looks like
> > feature that nobody needs nor tests.
> 
> already fixed in v2
> https://patchwork.kernel.org/patch/10940645/

I'm aware of this patch and other one for mt76x02. But so far in the
sources EDCCA is disabled for mt76x02 without possibility to enable it
(and this permission file issue was pointed by Kalle during review, not
by someone who want to test EDCCA). So again, what for EDCCA is needed ?

Stanislaw


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-15 Thread Stanislaw Gruszka
On Mon, May 13, 2019 at 11:48:37AM +0200, Stanislaw Gruszka wrote:
> On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi wrote:
> > > Lorenzo Bianconi  writes:
> > > 
> > > > Introduce a knob in mt7603 debugfs in order to enable/disable
> > > > edcca processing
> > > >
> > > > Signed-off-by: Lorenzo Bianconi 
> > > 
> > > It's good to explain what edcca does and how the file is used supposed
> > > to be used. In other words, have a small introduction for the user.
> > 
> > Hi Kalle,
> > 
> > edcca is used for adjusting energy detect based on CCA thresholds.
> > The code was already there so I just reported the acronym.
> 
> What for it is needed ?

Care to comment why EDCCA is needed at all ?

Taking that debugfs file that enable it is read-only, it looks like
feature that nobody needs nor tests.

Stanislaw 


Re: [PATCH] mt76: mt7603: add debugfs knob to enable/disable edcca

2019-05-13 Thread Stanislaw Gruszka
On Mon, May 13, 2019 at 10:41:28AM +0200, Lorenzo Bianconi wrote:
> > Lorenzo Bianconi  writes:
> > 
> > > Introduce a knob in mt7603 debugfs in order to enable/disable
> > > edcca processing
> > >
> > > Signed-off-by: Lorenzo Bianconi 
> > 
> > It's good to explain what edcca does and how the file is used supposed
> > to be used. In other words, have a small introduction for the user.
> 
> Hi Kalle,
> 
> edcca is used for adjusting energy detect based on CCA thresholds.
> The code was already there so I just reported the acronym.

What for it is needed ?

Stanislaw


Re: [PATCH 3/4] mt76: mt76x2: move mutex_lock inside mt76x2_set_channel

2019-05-13 Thread Stanislaw Gruszka
On Mon, May 13, 2019 at 11:19:06AM +0200, Lorenzo Bianconi wrote:
> > On Sat, May 11, 2019 at 12:17:53PM +0200, Lorenzo Bianconi wrote:
> > > This is a preliminary patch to run mt76x02_edcca_init atomically
> > > 
> > > Signed-off-by: Lorenzo Bianconi 
> > > ---
> > >  .../wireless/mediatek/mt76/mt76x2/pci_main.c  | 16 --
> > >  .../wireless/mediatek/mt76/mt76x2/usb_main.c  | 22 ++-
> > >  2 files changed, 21 insertions(+), 17 deletions(-)
> > > 
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c 
> > > b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> > > index e416eee6a306..3a1467326f4d 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> > > @@ -54,14 +54,14 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct 
> > > cfg80211_chan_def *chandef)
> > >   int ret;
> > >  
> > >   cancel_delayed_work_sync(&dev->cal_work);
> > 
> > Since now you use mutex in mt76x2_phy_calibrate() you can remove  
> > cancel_delayed_work_sync() and drop other changes from this patch
> > as releasing mutex just to acquire it in almost next step make
> > no sense.
> 
> I agree with you, the only difference is in that way we will perform phy
> calibration even during scanning. If the there are no
> objections I will post a v3 removing cancel_delayed_work_sync and
> reworking patch 3/4

Oh, calibration work should not be done during scanning, so cancel
cal_work should be added to .sw_scan_start() callback or this patch
should stay unchanged.

Stanislaw



Re: [PATCH 3/4] mt76: mt76x2: move mutex_lock inside mt76x2_set_channel

2019-05-13 Thread Stanislaw Gruszka
On Sat, May 11, 2019 at 12:17:53PM +0200, Lorenzo Bianconi wrote:
> This is a preliminary patch to run mt76x02_edcca_init atomically
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  .../wireless/mediatek/mt76/mt76x2/pci_main.c  | 16 --
>  .../wireless/mediatek/mt76/mt76x2/usb_main.c  | 22 ++-
>  2 files changed, 21 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c 
> b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> index e416eee6a306..3a1467326f4d 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
> @@ -54,14 +54,14 @@ mt76x2_set_channel(struct mt76x02_dev *dev, struct 
> cfg80211_chan_def *chandef)
>   int ret;
>  
>   cancel_delayed_work_sync(&dev->cal_work);

Since now you use mutex in mt76x2_phy_calibrate() you can remove  
cancel_delayed_work_sync() and drop other changes from this patch
as releasing mutex just to acquire it in almost next step make
no sense.

Stanislaw


  1   2   3   4   5   6   7   8   9   10   >