2019-11-26 21:50:38

by Markus Theil

[permalink] [raw]
Subject: [PATCH v9 0/6] mt76: channel switch support for USB devices

This patch series adds channel switch support for mt76 usb interfaces.
When testing, I noticed that between 5 or 7 consecutive beacons had the
identical channel switch count set. After some debugging I found out,
that beacon copying over usb took far too long (up to 700ms for one call
of mt76x02u_pre_tbtt_work).

Therefore the first five patches speed up beacon copying and provide beaconing
fixes. The last patch enables channel switch support also for usb interfaces.

Thanks to Stanislaw, Lorenzo and Felix for their help.

v9:
* use beacon_data_count instead of beacon_data_mask
* add missing txwi copy again
* move csa_check for usb under beacon iteration (send beacons and no ps frames
in case of finished csa)

v8:
* fix mbss beaconing
* fix adding vifs with idx 8
* fix memory leaks by dropping beacon buffer
* permanently enable 7 additional bss to save another usb call and make
beacon masking easier
* added beacon_prepare call again, which now also clears beacon_data_mask

v7:
* fix mbss beacon settings (incorrect try)
* fix compilation with latest upstream

v6:
* use min_t in mt76u_copy
* use round_up in mt76u_copy
* use additional copy for mmio beacon set again

v5:
* ommit empty mt76x2u_channel_switch_beacon
* copy txwi into beacon skb

v4:
* use multiple of 4 len for usb copy again

v3:
* fixed checkpatch errors

v2:
* correctly track beacon data mask
* clean-ups
* make channel switch fn static (reported by kbuild test robot)

Markus Theil (6):
mt76: mt76x02: ommit beacon slot clearing
mt76: mt76x02: split beaconing
mt76: mt76x02: add check for invalid vif idx
mt76: mt76x02: remove a copy call for usb speedup
mt76: speed up usb bulk copy
mt76: mt76x02: add channel switch support for usb interfaces

drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x02.h | 3 +-
.../wireless/mediatek/mt76/mt76x02_beacon.c | 97 +++++++------------
.../net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +
.../net/wireless/mediatek/mt76/mt76x02_mac.h | 5 +-
.../net/wireless/mediatek/mt76/mt76x02_mmio.c | 4 +
.../wireless/mediatek/mt76/mt76x02_usb_core.c | 22 +++--
.../net/wireless/mediatek/mt76/mt76x02_util.c | 6 +-
drivers/net/wireless/mediatek/mt76/usb.c | 24 +++--
9 files changed, 85 insertions(+), 80 deletions(-)

--
2.24.0


2019-11-26 21:50:38

by Markus Theil

[permalink] [raw]
Subject: [PATCH v9 5/6] mt76: speed up usb bulk copy

Use larger batches for usb copy to speed this operation up. Otherwise it
would be too slow for copying new beacons or broadcast frames over usb.
Assure, that always a multiple of 4 Bytes is copied, as outlined in
850e8f6fbd "mt76: round up length on mt76_wr_copy" from Felix Fietkau.

Signed-off-by: Markus Theil <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/usb.c | 24 +++++++++++++++++------
2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index fb077760347a..1981912de1f9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -382,7 +382,7 @@ enum mt76u_out_ep {
struct mt76_usb {
struct mutex usb_ctrl_mtx;
union {
- u8 data[32];
+ u8 data[128];
__le32 reg_val;
};

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index d6d47081e281..97b263ce3872 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -149,18 +149,30 @@ 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;
+ const u8 *val = data;
+ int ret;
+ int current_batch_size;
+ int i = 0;
+
+ /* Assure that always a multiple of 4 bytes are copied,
+ * otherwise beacons can be corrupted.
+ * See: "mt76: round up length on mt76_wr_copy"
+ * Commit 850e8f6fbd5d0003b0
+ */
+ len = round_up(len, 4);

mutex_lock(&usb->usb_ctrl_mtx);
- for (i = 0; i < DIV_ROUND_UP(len, 4); i++) {
- put_unaligned(val[i], (u32 *)usb->data);
+ while (i < len) {
+ current_batch_size = min_t(int, sizeof(usb->data), len - i);
+ memcpy(usb->data, val + i, current_batch_size);
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 + i, usb->data,
+ current_batch_size);
if (ret < 0)
break;
+
+ i += current_batch_size;
}
mutex_unlock(&usb->usb_ctrl_mtx);
}
--
2.24.0

2019-11-26 21:51:09

by Markus Theil

[permalink] [raw]
Subject: [PATCH v9 6/6] mt76: mt76x02: add channel switch support for usb interfaces

This patch enables channel switch support on mt76 usb interfaces.

Signed-off-by: Markus Theil <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 8 ++++++++
drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index fca861f10563..3dc3682d585a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -214,6 +214,13 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
IEEE80211_IFACE_ITER_RESUME_ALL,
mt76x02_update_beacon_iter, dev);

+ mt76_csa_check(&dev->mt76);
+
+ if (dev->mt76.csa_complete) {
+ mt76_csa_finish(&dev->mt76);
+ goto out;
+ }
+
nbeacons = hweight8(dev->mt76.beacon_mask);
mt76x02_enqueue_buffered_bc(dev, &data, N_BCN_SLOTS - nbeacons);

@@ -222,6 +229,7 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
mt76x02_mac_set_beacon(dev, skb);
}

+out:
mt76x02_mac_set_beacon_finish(dev);

mt76x02u_restart_pre_tbtt_timer(dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 6073f8a4a8f6..dbda7fb6dab7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -166,7 +166,6 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy->iface_combinations = mt76x02_if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb);
- wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;

/* init led callbacks */
if (IS_ENABLED(CONFIG_MT76_LEDS)) {
@@ -176,6 +175,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
}
}

+ wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);

hw->sta_data_size = sizeof(struct mt76x02_sta);
--
2.24.0