All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/12] mt76x02: AP support for with PS
@ 2019-02-28  8:03 Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 01/12] mt76x02: introduce mt76x02_beacon.c Stanislaw Gruszka
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

On USB we do not have available PSD queue. Using standard AC queues is
unreliable for sending PS buffered frames, stations can go sleep again
before frames are sent. Only reliable way I could find to sent broadcast
PS buffered frames is put them into beacon data registers, then frames
are sent just after proper beacon. HW do the work when we encrypt the 
frames in software.

I tested functionality used arping to iwlwifi station that do
aggressive PS, it works like this:

# arping -c 1 -I wlan0 192.168.9.110 
ARPING 192.168.9.110 from 192.168.9.1 wlan0
Unicast reply from 192.168.9.110 [4C:34:88:5E:76:D5]  324.885ms
Sent 1 probes (1 broadcast(s))

Otherwise arping fails:

# arping -c 1 -I wlan0 192.168.9.110 
ARPING 192.168.9.110 from 192.168.1.148 wlan0
Sent 1 probes (1 broadcast(s))
Received 0 response(s)

I'm not sure how to test mt76_release_buffered_frames functionality.
Also I have not tested on MMIO hardware, but for this only code
movement was done so things should not break.

Stanislaw Gruszka (12):
  mt76x02: introduce mt76x02_beacon.c
  mt76x02: add hrtimer for pre TBTT for USB
  mt76x02: introduce beacon_ops
  mt76x02u: implement beacon_ops
  mt76x02: generalize some mmio beaconing functions
  mt76x02u: add sta_ps
  mt76x02: fix hdr pointer in write txwi for USB
  mt76x02: disable HW encryption for group frames
  mt76x02u: implement pre TBTT work for USB
  mt76x02u: add mt76_release_buffered_frames
  mt76x02: enable AP mode for USB
  mt76x02: remove set_tim

 drivers/net/wireless/mediatek/mt76/Makefile   |   2 +-
 .../net/wireless/mediatek/mt76/mt76x0/init.c  |   1 -
 .../net/wireless/mediatek/mt76/mt76x0/main.c  |   8 +-
 .../net/wireless/mediatek/mt76/mt76x0/pci.c   |  10 +-
 .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   9 +-
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |  22 ++
 .../wireless/mediatek/mt76/mt76x02_beacon.c   | 308 ++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt76x02_mac.c  | 138 --------
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 131 +++-----
 .../net/wireless/mediatek/mt76/mt76x02_regs.h |   5 +-
 .../net/wireless/mediatek/mt76/mt76x02_usb.h  |   2 +
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 156 ++++++++-
 .../net/wireless/mediatek/mt76/mt76x02_util.c |  77 +----
 .../wireless/mediatek/mt76/mt76x2/pci_init.c  |   2 +-
 .../wireless/mediatek/mt76/mt76x2/pci_main.c  |   7 -
 .../net/wireless/mediatek/mt76/mt76x2/usb.c   |   1 +
 .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
 .../wireless/mediatek/mt76/mt76x2/usb_main.c  |   1 +
 drivers/net/wireless/mediatek/mt76/usb.c      |  13 +-
 19 files changed, 568 insertions(+), 327 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c

-- 
2.20.1


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

* [RFC 01/12] mt76x02: introduce mt76x02_beacon.c
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 02/12] mt76x02: add hrtimer for pre TBTT for USB Stanislaw Gruszka
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Move most of beaconing code into separate file and separate beacon
initialization for USB and MMIO as pre TBTT implementation for USB
will be different.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/Makefile   |   2 +-
 .../net/wireless/mediatek/mt76/mt76x0/init.c  |   1 -
 .../net/wireless/mediatek/mt76/mt76x0/pci.c   |   2 +
 .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   2 +
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |   1 +
 .../wireless/mediatek/mt76/mt76x02_beacon.c   | 212 ++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt76x02_mac.c  | 138 ------------
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c |  17 +-
 .../net/wireless/mediatek/mt76/mt76x02_usb.h  |   1 +
 .../wireless/mediatek/mt76/mt76x02_usb_core.c |   6 +
 .../net/wireless/mediatek/mt76/mt76x02_util.c |  62 -----
 .../wireless/mediatek/mt76/mt76x2/pci_init.c  |   2 +-
 .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
 13 files changed, 242 insertions(+), 206 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c

diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile
index 3fd1b64b4aa7..cad4fed1a6ac 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -16,7 +16,7 @@ CFLAGS_mt76x02_trace.o := -I$(src)
 mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o mt76x02_mcu.o \
 		 mt76x02_eeprom.o mt76x02_phy.o mt76x02_mmio.o \
 		 mt76x02_txrx.o mt76x02_trace.o mt76x02_debugfs.o \
-		 mt76x02_dfs.o
+		 mt76x02_dfs.o mt76x02_beacon.o
 
 mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index bcb72e019fd2..e5f4ce3b595b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -259,7 +259,6 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev)
 		return ret;
 
 	mt76x0_phy_init(dev);
-	mt76x02_init_beacon_config(dev);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index f302162036d0..fafe57653ac0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -128,6 +128,8 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev)
 	if (err < 0)
 		return err;
 
+	mt76x02e_init_beacon_config(dev);
+
 	if (mt76_chip(&dev->mt76) == 0x7610) {
 		u16 val;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 91718647da02..9d3ad8586530 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -175,6 +175,8 @@ static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
 	if (err < 0)
 		return err;
 
+	mt76x02u_init_beacon_config(dev);
+
 	mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
 	mt76_wr(dev, MT_TXOP_CTRL_CFG,
 		FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 6915cce5def9..78bc0211e479 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -183,6 +183,7 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 
 extern const u16 mt76x02_beacon_offsets[16];
 void mt76x02_init_beacon_config(struct mt76x02_dev *dev);
+void mt76x02e_init_beacon_config(struct mt76x02_dev *dev);
 void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set);
 void mt76x02_mac_start(struct mt76x02_dev *dev);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
new file mode 100644
index 000000000000..e9f71def9f21
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mt76x02.h"
+
+const u16 mt76x02_beacon_offsets[16] = {
+	/* 1024 byte per beacon */
+	0xc000,
+	0xc400,
+	0xc800,
+	0xcc00,
+	0xd000,
+	0xd400,
+	0xd800,
+	0xdc00,
+	/* BSS idx 8-15 not used for beacons */
+	0xc000,
+	0xc000,
+	0xc000,
+	0xc000,
+	0xc000,
+	0xc000,
+	0xc000,
+	0xc000,
+};
+
+static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
+{
+	u16 val, base = MT_BEACON_BASE;
+	u32 regs[4] = {};
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		val = mt76x02_beacon_offsets[i] - base;
+		regs[i / 4] |= (val / 64) << (8 * (i % 4));
+	}
+
+	for (i = 0; i < 4; i++)
+		mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
+}
+
+static int
+mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb)
+{
+	int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+	struct mt76x02_txwi txwi;
+
+	if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
+		return -ENOSPC;
+
+	mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len);
+
+	mt76_wr_copy(dev, offset, &txwi, sizeof(txwi));
+	offset += sizeof(txwi);
+
+	mt76_wr_copy(dev, offset, skb->data, skb->len);
+	return 0;
+}
+
+static int
+__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx,
+			 struct sk_buff *skb)
+{
+	int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+	int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
+	int ret = 0;
+	int i;
+
+	/* Prevent corrupt transmissions during update */
+	mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx));
+
+	if (skb) {
+		ret = mt76x02_write_beacon(dev, beacon_addr, skb);
+		if (!ret)
+			dev->beacon_data_mask |= BIT(bcn_idx);
+	} else {
+		dev->beacon_data_mask &= ~BIT(bcn_idx);
+		for (i = 0; i < beacon_len; i += 4)
+			mt76_wr(dev, beacon_addr + i, 0);
+	}
+
+	mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask);
+
+	return ret;
+}
+
+int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
+			   struct sk_buff *skb)
+{
+	bool force_update = false;
+	int bcn_idx = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) {
+		if (vif_idx == i) {
+			force_update = !!dev->beacons[i] ^ !!skb;
+
+			if (dev->beacons[i])
+				dev_kfree_skb(dev->beacons[i]);
+
+			dev->beacons[i] = skb;
+			__mt76x02_mac_set_beacon(dev, bcn_idx, skb);
+		} else if (force_update && dev->beacons[i]) {
+			__mt76x02_mac_set_beacon(dev, bcn_idx,
+						 dev->beacons[i]);
+		}
+
+		bcn_idx += !!dev->beacons[i];
+	}
+
+	for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) {
+		if (!(dev->beacon_data_mask & BIT(i)))
+			break;
+
+		__mt76x02_mac_set_beacon(dev, i, NULL);
+	}
+
+	mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N,
+		       bcn_idx - 1);
+	return 0;
+}
+
+static void
+__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
+				bool val, struct sk_buff *skb)
+{
+	u8 old_mask = dev->beacon_mask;
+	bool en;
+	u32 reg;
+
+	if (val) {
+		dev->beacon_mask |= BIT(vif_idx);
+		if (skb)
+			mt76x02_mac_set_beacon(dev, vif_idx, skb);
+	} else {
+		dev->beacon_mask &= ~BIT(vif_idx);
+		mt76x02_mac_set_beacon(dev, vif_idx, NULL);
+	}
+
+	if (!!old_mask == !!dev->beacon_mask)
+		return;
+
+	en = dev->beacon_mask;
+
+	reg = MT_BEACON_TIME_CFG_BEACON_TX |
+	      MT_BEACON_TIME_CFG_TBTT_EN |
+	      MT_BEACON_TIME_CFG_TIMER_EN;
+	mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
+
+	if (mt76_is_usb(dev))
+		return;
+
+	mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
+	if (en)
+		mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+	else
+		mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+}
+
+void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
+				   struct ieee80211_vif *vif, bool val)
+{
+	u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx;
+	struct sk_buff *skb = NULL;
+
+	if (mt76_is_mmio(dev))
+		tasklet_disable(&dev->pre_tbtt_tasklet);
+	else if (val)
+		skb = ieee80211_beacon_get(mt76_hw(dev), vif);
+
+	if (!dev->beacon_mask)
+		dev->tbtt_count = 0;
+
+	__mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
+
+	if (mt76_is_mmio(dev))
+		tasklet_enable(&dev->pre_tbtt_tasklet);
+}
+
+void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
+{
+	int i;
+
+	mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
+					     MT_BEACON_TIME_CFG_TBTT_EN |
+					     MT_BEACON_TIME_CFG_BEACON_TX));
+	mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE);
+	mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff);
+
+	for (i = 0; i < 8; i++)
+		mt76x02_mac_set_beacon(dev, i, NULL);
+
+	mt76x02_set_beacon_offsets(dev);
+}
+EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config);
+
+
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 91ff6598eccf..71bd82cccb6b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -996,141 +996,3 @@ void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr)
 	mt76_rmw_field(dev, MT_MAC_APC_BSSID_H(idx), MT_MAC_APC_BSSID_H_ADDR,
 		       get_unaligned_le16(addr + 4));
 }
-
-static int
-mt76x02_write_beacon(struct mt76x02_dev *dev, int offset, struct sk_buff *skb)
-{
-	int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
-	struct mt76x02_txwi txwi;
-
-	if (WARN_ON_ONCE(beacon_len < skb->len + sizeof(struct mt76x02_txwi)))
-		return -ENOSPC;
-
-	mt76x02_mac_write_txwi(dev, &txwi, skb, NULL, NULL, skb->len);
-
-	mt76_wr_copy(dev, offset, &txwi, sizeof(txwi));
-	offset += sizeof(txwi);
-
-	mt76_wr_copy(dev, offset, skb->data, skb->len);
-	return 0;
-}
-
-static int
-__mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 bcn_idx,
-			 struct sk_buff *skb)
-{
-	int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
-	int beacon_addr = mt76x02_beacon_offsets[bcn_idx];
-	int ret = 0;
-	int i;
-
-	/* Prevent corrupt transmissions during update */
-	mt76_set(dev, MT_BCN_BYPASS_MASK, BIT(bcn_idx));
-
-	if (skb) {
-		ret = mt76x02_write_beacon(dev, beacon_addr, skb);
-		if (!ret)
-			dev->beacon_data_mask |= BIT(bcn_idx);
-	} else {
-		dev->beacon_data_mask &= ~BIT(bcn_idx);
-		for (i = 0; i < beacon_len; i += 4)
-			mt76_wr(dev, beacon_addr + i, 0);
-	}
-
-	mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xff00 | ~dev->beacon_data_mask);
-
-	return ret;
-}
-
-int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
-			   struct sk_buff *skb)
-{
-	bool force_update = false;
-	int bcn_idx = 0;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) {
-		if (vif_idx == i) {
-			force_update = !!dev->beacons[i] ^ !!skb;
-
-			if (dev->beacons[i])
-				dev_kfree_skb(dev->beacons[i]);
-
-			dev->beacons[i] = skb;
-			__mt76x02_mac_set_beacon(dev, bcn_idx, skb);
-		} else if (force_update && dev->beacons[i]) {
-			__mt76x02_mac_set_beacon(dev, bcn_idx,
-						 dev->beacons[i]);
-		}
-
-		bcn_idx += !!dev->beacons[i];
-	}
-
-	for (i = bcn_idx; i < ARRAY_SIZE(dev->beacons); i++) {
-		if (!(dev->beacon_data_mask & BIT(i)))
-			break;
-
-		__mt76x02_mac_set_beacon(dev, i, NULL);
-	}
-
-	mt76_rmw_field(dev, MT_MAC_BSSID_DW1, MT_MAC_BSSID_DW1_MBEACON_N,
-		       bcn_idx - 1);
-	return 0;
-}
-
-static void
-__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
-				bool val, struct sk_buff *skb)
-{
-	u8 old_mask = dev->beacon_mask;
-	bool en;
-	u32 reg;
-
-	if (val) {
-		dev->beacon_mask |= BIT(vif_idx);
-		if (skb)
-			mt76x02_mac_set_beacon(dev, vif_idx, skb);
-	} else {
-		dev->beacon_mask &= ~BIT(vif_idx);
-		mt76x02_mac_set_beacon(dev, vif_idx, NULL);
-	}
-
-	if (!!old_mask == !!dev->beacon_mask)
-		return;
-
-	en = dev->beacon_mask;
-
-	reg = MT_BEACON_TIME_CFG_BEACON_TX |
-	      MT_BEACON_TIME_CFG_TBTT_EN |
-	      MT_BEACON_TIME_CFG_TIMER_EN;
-	mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
-
-	if (mt76_is_usb(dev))
-		return;
-
-	mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
-	if (en)
-		mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
-	else
-		mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
-}
-
-void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
-				   struct ieee80211_vif *vif, bool val)
-{
-	u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx;
-	struct sk_buff *skb = NULL;
-
-	if (mt76_is_mmio(dev))
-		tasklet_disable(&dev->pre_tbtt_tasklet);
-	else if (val)
-		skb = ieee80211_beacon_get(mt76_hw(dev), vif);
-
-	if (!dev->beacon_mask)
-		dev->tbtt_count = 0;
-
-	__mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
-
-	if (mt76_is_mmio(dev))
-		tasklet_enable(&dev->pre_tbtt_tasklet);
-}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index 1229f19f2b02..c21bcb56c7de 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -151,6 +151,21 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
 	spin_unlock_bh(&q->lock);
 }
 
+void mt76x02e_init_beacon_config(struct mt76x02_dev *dev)
+{
+	tasklet_init(&dev->pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
+		     (unsigned long)dev);
+
+	/* Fire a pre-TBTT interrupt 8 ms before TBTT */
+	mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 8 << 4);
+	mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
+		       MT_DFS_GP_INTERVAL);
+	mt76_wr(dev, MT_INT_TIMER_EN, 0);
+
+	mt76x02_init_beacon_config(dev);
+}
+EXPORT_SYMBOL_GPL(mt76x02e_init_beacon_config);
+
 static int
 mt76x02_init_tx_queue(struct mt76x02_dev *dev, struct mt76_queue *q,
 		      int idx, int n_desc)
@@ -228,8 +243,6 @@ int mt76x02_dma_init(struct mt76x02_dev *dev)
 		return -ENOMEM;
 
 	tasklet_init(&dev->tx_tasklet, mt76x02_tx_tasklet, (unsigned long) dev);
-	tasklet_init(&dev->pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
-		     (unsigned long)dev);
 
 	kfifo_init(&dev->txstatus_fifo, status_fifo, fifo_size);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
index 0126e51d77ed..3874f363418f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
@@ -31,4 +31,5 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 			    u32 *tx_info);
 void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
 			      struct mt76_queue_entry *e, bool flush);
+void mt76x02u_init_beacon_config(struct mt76x02_dev *dev);
 #endif /* __MT76x02_USB_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 43f07461c8d3..833ca97d07fc 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -104,3 +104,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 	return mt76x02u_skb_dma_info(skb, WLAN_PORT, flags);
 }
 EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb);
+
+void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
+{
+	mt76x02_init_beacon_config(dev);
+}
+EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index a48c261b0c63..83fc9d1add82 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -629,68 +629,6 @@ void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,
 }
 EXPORT_SYMBOL_GPL(mt76x02_sta_ps);
 
-const u16 mt76x02_beacon_offsets[16] = {
-	/* 1024 byte per beacon */
-	0xc000,
-	0xc400,
-	0xc800,
-	0xcc00,
-	0xd000,
-	0xd400,
-	0xd800,
-	0xdc00,
-	/* BSS idx 8-15 not used for beacons */
-	0xc000,
-	0xc000,
-	0xc000,
-	0xc000,
-	0xc000,
-	0xc000,
-	0xc000,
-	0xc000,
-};
-
-static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
-{
-	u16 val, base = MT_BEACON_BASE;
-	u32 regs[4] = {};
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		val = mt76x02_beacon_offsets[i] - base;
-		regs[i / 4] |= (val / 64) << (8 * (i % 4));
-	}
-
-	for (i = 0; i < 4; i++)
-		mt76_wr(dev, MT_BCN_OFFSET(i), regs[i]);
-}
-
-void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
-{
-	int i;
-
-	if (mt76_is_mmio(dev)) {
-		/* Fire a pre-TBTT interrupt 8 ms before TBTT */
-		mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT,
-			       8 << 4);
-		mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
-			       MT_DFS_GP_INTERVAL);
-		mt76_wr(dev, MT_INT_TIMER_EN, 0);
-	}
-
-	mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
-					     MT_BEACON_TIME_CFG_TBTT_EN |
-					     MT_BEACON_TIME_CFG_BEACON_TX));
-	mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE);
-	mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff);
-
-	for (i = 0; i < 8; i++)
-		mt76x02_mac_set_beacon(dev, i, NULL);
-
-	mt76x02_set_beacon_offsets(dev);
-}
-EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config);
-
 void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_bss_conf *info,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
index 984d9c4c2e1a..7a40a2b0a632 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
@@ -120,7 +120,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
 	mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN);
 
 	mt76x02_mac_setaddr(dev, macaddr);
-	mt76x02_init_beacon_config(dev);
+	mt76x02e_init_beacon_config(dev);
 	if (!hard)
 		return 0;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
index 1da90e58d942..35bdf5ffae00 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
@@ -183,7 +183,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev)
 			mt76x02_mac_shared_key_setup(dev, i, k, NULL);
 	}
 
-	mt76x02_init_beacon_config(dev);
+	mt76x02u_init_beacon_config(dev);
 
 	mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
 	mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f);
-- 
2.20.1


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

* [RFC 02/12] mt76x02: add hrtimer for pre TBTT for USB
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 01/12] mt76x02: introduce mt76x02_beacon.c Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 03/12] mt76x02: introduce beacon_ops Stanislaw Gruszka
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Add timer and work for pre TBTT for USB devices. For now code
doesn't do anyting useful, just add hrtimer which synchronize
with hardware MT_TBTT_TIMER.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |  3 +
 .../net/wireless/mediatek/mt76/mt76x02_regs.h |  5 +-
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 70 +++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 78bc0211e479..edb1c140c487 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -87,6 +87,9 @@ struct mt76x02_dev {
 	struct delayed_work mac_work;
 	struct delayed_work wdt_work;
 
+	struct hrtimer pre_tbtt_timer;
+	struct work_struct pre_tbtt_work;
+
 	u32 aggr_stats[32];
 
 	struct sk_buff *beacons[8];
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
index 7401cb94fb72..2ce05b543dff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
@@ -356,7 +356,10 @@
 #define MT_BEACON_TIME_CFG_TSF_COMP	GENMASK(31, 24)
 
 #define MT_TBTT_SYNC_CFG		0x1118
-#define MT_TBTT_TIMER_CFG		0x1124
+#define MT_TSF_TIMER_DW0		0x111c
+#define MT_TSF_TIMER_DW1		0x1120
+#define MT_TBTT_TIMER			0x1124
+#define MT_TBTT_TIMER_VAL		GENMASK(16, 0)
 
 #define MT_INT_TIMER_CFG		0x1128
 #define MT_INT_TIMER_CFG_PRE_TBTT	GENMASK(15, 0)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 833ca97d07fc..051fa68a85d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -105,8 +105,78 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 }
 EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb);
 
+/* Trigger pre-TBTT event 8 ms before TBTT */
+#define PRE_TBTT_USEC 8000
+static void mt76x02u_start_pre_tbtt_timer(struct mt76x02_dev *dev)
+{
+	u64 time;
+	u32 tbtt;
+
+	/* Get remaining TBTT in usec */
+	tbtt = mt76_get_field(dev, MT_TBTT_TIMER, MT_TBTT_TIMER_VAL);
+	tbtt *= 32;
+
+	if (tbtt <= PRE_TBTT_USEC) {
+		queue_work(system_highpri_wq, &dev->pre_tbtt_work);
+		return;
+	}
+
+	time = (tbtt - PRE_TBTT_USEC) * 1000ull;
+	hrtimer_start(&dev->pre_tbtt_timer, time, HRTIMER_MODE_REL);
+}
+
+static void mt76x02u_restart_pre_tbtt_timer(struct mt76x02_dev *dev)
+{
+	u32 tbtt, dw0, dw1;
+	u64 tsf, time;
+
+	/* Get remaining TBTT in usec */
+	tbtt = mt76_get_field(dev, MT_TBTT_TIMER, MT_TBTT_TIMER_VAL);
+	tbtt *= 32;
+
+	dw0 = mt76_rr(dev, MT_TSF_TIMER_DW0);
+	dw1 = mt76_rr(dev, MT_TSF_TIMER_DW1);
+	tsf = (u64)dw0 << 32 | dw1;
+	dev_dbg(dev->mt76.dev, "TSF: %llu us TBTT %u us\n", tsf, tbtt);
+
+	/* Convert beacon interval in TU (1024 usec) to nsec */
+	time = ((1000000000ull * dev->beacon_int) >> 10);
+
+	/* Adjust time to trigger hrtimer 8ms before TBTT */
+	if (tbtt < PRE_TBTT_USEC)
+		time -= (PRE_TBTT_USEC - tbtt) * 1000ull;
+	else
+		time += (tbtt - PRE_TBTT_USEC) * 1000ull;
+
+	hrtimer_start(&dev->pre_tbtt_timer, time, HRTIMER_MODE_REL);
+}
+
+static void mt76x02u_pre_tbtt_work(struct work_struct *work)
+{
+	struct mt76x02_dev *dev =
+		container_of(work, struct mt76x02_dev, pre_tbtt_work);
+
+	if (!dev->beacon_mask)
+		return;
+	mt76x02u_restart_pre_tbtt_timer(dev);
+}
+
+static enum hrtimer_restart mt76x02u_pre_tbtt_interrupt(struct hrtimer *timer)
+{
+	struct mt76x02_dev *dev =
+	    container_of(timer, struct mt76x02_dev, pre_tbtt_timer);
+
+	queue_work(system_highpri_wq, &dev->pre_tbtt_work);
+
+	return HRTIMER_NORESTART;
+}
+
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
 {
+	hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt;
+	INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work);
+
 	mt76x02_init_beacon_config(dev);
 }
 EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config);
-- 
2.20.1


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

* [RFC 03/12] mt76x02: introduce beacon_ops
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 01/12] mt76x02: introduce mt76x02_beacon.c Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 02/12] mt76x02: add hrtimer for pre TBTT for USB Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 04/12] mt76x02u: implement beacon_ops Stanislaw Gruszka
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Enabling/disableing TBTT and beacon will be diffrent for USB. Introduce
beacon_ops to encapsulate that and implement it for MMIO. USB
implementation is noop for now.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 .../net/wireless/mediatek/mt76/mt76x0/main.c  |  8 +++----
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |  7 ++++++
 .../wireless/mediatek/mt76/mt76x02_beacon.c   | 18 ++++-----------
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c | 23 +++++++++++++++++++
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 14 +++++++++++
 5 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index fee16ab21edb..691984037f98 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -22,10 +22,9 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
 	int ret;
 
 	cancel_delayed_work_sync(&dev->cal_work);
-	if (mt76_is_mmio(dev)) {
-		tasklet_disable(&dev->pre_tbtt_tasklet);
+	dev->beacon_ops->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);
@@ -38,9 +37,10 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
 
 	if (mt76_is_mmio(dev)) {
 		mt76x02_dfs_init_params(dev);
-		tasklet_enable(&dev->pre_tbtt_tasklet);
 		tasklet_enable(&dev->dfs_pd.dfs_tasklet);
 	}
+	dev->beacon_ops->pre_tbtt_enable(dev, true);
+
 	mt76_txq_schedule_all(&dev->mt76);
 
 	return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index edb1c140c487..46c4635cd66a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -67,6 +67,11 @@ struct mt76x02_calibration {
 	s8 tssi_dc;
 };
 
+struct mt76x02_beacon_ops {
+	void (*pre_tbtt_enable) (struct mt76x02_dev *, bool);
+	void (*beacon_enable) (struct mt76x02_dev *, bool);
+};
+
 struct mt76x02_dev {
 	struct mt76_dev mt76; /* must be first */
 
@@ -90,6 +95,8 @@ struct mt76x02_dev {
 	struct hrtimer pre_tbtt_timer;
 	struct work_struct pre_tbtt_work;
 
+	const struct mt76x02_beacon_ops *beacon_ops;
+
 	u32 aggr_stats[32];
 
 	struct sk_buff *beacons[8];
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index e9f71def9f21..42798a918c0c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -162,14 +162,7 @@ __mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
 	      MT_BEACON_TIME_CFG_TIMER_EN;
 	mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en);
 
-	if (mt76_is_usb(dev))
-		return;
-
-	mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
-	if (en)
-		mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
-	else
-		mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+	dev->beacon_ops->beacon_enable(dev, en);
 }
 
 void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
@@ -178,9 +171,9 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
 	u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx;
 	struct sk_buff *skb = NULL;
 
-	if (mt76_is_mmio(dev))
-		tasklet_disable(&dev->pre_tbtt_tasklet);
-	else if (val)
+	dev->beacon_ops->pre_tbtt_enable(dev, true);
+
+	if (mt76_is_usb(dev))
 		skb = ieee80211_beacon_get(mt76_hw(dev), vif);
 
 	if (!dev->beacon_mask)
@@ -188,8 +181,7 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
 
 	__mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb);
 
-	if (mt76_is_mmio(dev))
-		tasklet_enable(&dev->pre_tbtt_tasklet);
+	dev->beacon_ops->pre_tbtt_enable(dev, true);
 }
 
 void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index c21bcb56c7de..f83a633144ab 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -151,8 +151,31 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
 	spin_unlock_bh(&q->lock);
 }
 
+static void mt76x02e_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
+{
+	if (en)
+		tasklet_enable(&dev->pre_tbtt_tasklet);
+	else
+		tasklet_disable(&dev->pre_tbtt_tasklet);
+}
+
+static void mt76x02e_beacon_enable(struct mt76x02_dev *dev, bool en)
+{
+	mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en);
+	if (en)
+		mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+	else
+		mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT);
+}
+
 void mt76x02e_init_beacon_config(struct mt76x02_dev *dev)
 {
+	static const struct mt76x02_beacon_ops beacon_ops = {
+		.pre_tbtt_enable = mt76x02e_pre_tbtt_enable,
+		.beacon_enable = mt76x02e_beacon_enable,
+	};
+	dev->beacon_ops = &beacon_ops;
+
 	tasklet_init(&dev->pre_tbtt_tasklet, mt76x02_pre_tbtt_tasklet,
 		     (unsigned long)dev);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 051fa68a85d5..5dd39c59a797 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -171,8 +171,22 @@ static enum hrtimer_restart mt76x02u_pre_tbtt_interrupt(struct hrtimer *timer)
 	return HRTIMER_NORESTART;
 }
 
+static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
+{
+}
+
+static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
+{
+}
+
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
 {
+	static const struct mt76x02_beacon_ops beacon_ops = {
+		.pre_tbtt_enable = mt76x02u_pre_tbtt_enable,
+		.beacon_enable = mt76x02u_beacon_enable,
+	};
+	dev->beacon_ops = &beacon_ops;
+
 	hrtimer_init(&dev->pre_tbtt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	dev->pre_tbtt_timer.function = mt76x02u_pre_tbtt_interrupt;
 	INIT_WORK(&dev->pre_tbtt_work, mt76x02u_pre_tbtt_work);
-- 
2.20.1


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

* [RFC 04/12] mt76x02u: implement beacon_ops
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (2 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 03/12] mt76x02: introduce beacon_ops Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 05/12] mt76x02: generalize some mmio beaconing functions Stanislaw Gruszka
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Add implementation of beacon_ops for USB and exit function to
stop the timer if running when device is removed. Still no
actual work on pre tbtt event.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 .../net/wireless/mediatek/mt76/mt76x0/usb.c   |  5 +--
 .../net/wireless/mediatek/mt76/mt76x02_usb.h  |  1 +
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 33 +++++++++++++++++++
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 9d3ad8586530..7f3113b91498 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -87,14 +87,11 @@ static void mt76x0u_mac_stop(struct mt76x02_dev *dev)
 	cancel_delayed_work_sync(&dev->cal_work);
 	cancel_delayed_work_sync(&dev->mac_work);
 	mt76u_stop_stat_wk(&dev->mt76);
+	mt76x02u_exit_beacon_config(dev);
 
 	if (test_bit(MT76_REMOVED, &dev->mt76.state))
 		return;
 
-	mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN |
-		   MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN |
-		   MT_BEACON_TIME_CFG_BEACON_TX);
-
 	if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000))
 		dev_warn(dev->mt76.dev, "TX DMA did not stop\n");
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
index 3874f363418f..d9389bf6dabe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb.h
@@ -32,4 +32,5 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
 			      struct mt76_queue_entry *e, bool flush);
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev);
+void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev);
 #endif /* __MT76x02_USB_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index 5dd39c59a797..fdd6a021914d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -151,6 +151,15 @@ static void mt76x02u_restart_pre_tbtt_timer(struct mt76x02_dev *dev)
 	hrtimer_start(&dev->pre_tbtt_timer, time, HRTIMER_MODE_REL);
 }
 
+static void mt76x02u_stop_pre_tbtt_timer(struct mt76x02_dev *dev)
+{
+	do {
+		hrtimer_cancel(&dev->pre_tbtt_timer);
+		cancel_work_sync(&dev->pre_tbtt_work);
+		/* Timer can be rearmed by work. */
+	} while (hrtimer_active(&dev->pre_tbtt_timer));
+}
+
 static void mt76x02u_pre_tbtt_work(struct work_struct *work)
 {
 	struct mt76x02_dev *dev =
@@ -173,10 +182,21 @@ static enum hrtimer_restart mt76x02u_pre_tbtt_interrupt(struct hrtimer *timer)
 
 static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
 {
+	if (en && dev->beacon_mask && !hrtimer_active(&dev->pre_tbtt_timer))
+		mt76x02u_start_pre_tbtt_timer(dev);
+	if (!en)
+		mt76x02u_stop_pre_tbtt_timer(dev);
 }
 
 static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
 {
+	if (WARN_ON_ONCE(!dev->beacon_int))
+		return;
+
+	if (en)
+		mt76x02u_start_pre_tbtt_timer(dev);
+
+	/* Nothing to do on disable as timer is already stopped */
 }
 
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
@@ -194,3 +214,16 @@ void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
 	mt76x02_init_beacon_config(dev);
 }
 EXPORT_SYMBOL_GPL(mt76x02u_init_beacon_config);
+
+void mt76x02u_exit_beacon_config(struct mt76x02_dev *dev)
+{
+	if (!test_bit(MT76_REMOVED, &dev->mt76.state))
+		mt76_clear(dev, MT_BEACON_TIME_CFG,
+			   MT_BEACON_TIME_CFG_TIMER_EN |
+			   MT_BEACON_TIME_CFG_SYNC_MODE |
+			   MT_BEACON_TIME_CFG_TBTT_EN |
+			   MT_BEACON_TIME_CFG_BEACON_TX);
+
+	mt76x02u_stop_pre_tbtt_timer(dev);
+}
+EXPORT_SYMBOL_GPL(mt76x02u_exit_beacon_config);
-- 
2.20.1


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

* [RFC 05/12] mt76x02: generalize some mmio beaconing functions
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (3 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 04/12] mt76x02u: implement beacon_ops Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 06/12] mt76x02u: add sta_ps Stanislaw Gruszka
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Move some TBTT mmio functions to mt76x02_beacon.c and create new ones
in order to be reused by USB pre-TBTT.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |  11 ++
 .../wireless/mediatek/mt76/mt76x02_beacon.c   | 102 ++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt76x02_mmio.c |  91 +---------------
 3 files changed, 115 insertions(+), 89 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index 46c4635cd66a..356ea5e443d2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -192,8 +192,19 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 			      struct ieee80211_bss_conf *info, u32 changed);
 
 extern const u16 mt76x02_beacon_offsets[16];
+struct beacon_bc_data {
+	struct mt76x02_dev *dev;
+	struct sk_buff_head q;
+	struct sk_buff *tail[8];
+};
 void mt76x02_init_beacon_config(struct mt76x02_dev *dev);
 void mt76x02e_init_beacon_config(struct mt76x02_dev *dev);
+void mt76x02_resync_beacon_timer(struct mt76x02_dev *dev);
+void mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
+void mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev,
+				 struct beacon_bc_data *data,
+				 int max_nframes);
+
 void mt76x02_set_irq_mask(struct mt76x02_dev *dev, u32 clear, u32 set);
 void mt76x02_mac_start(struct mt76x02_dev *dev);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index 42798a918c0c..28102082772b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -184,6 +184,108 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev,
 	dev->beacon_ops->pre_tbtt_enable(dev, true);
 }
 
+void
+mt76x02_resync_beacon_timer(struct mt76x02_dev *dev)
+{
+	u32 timer_val = dev->beacon_int << 4;
+
+	dev->tbtt_count++;
+
+	/*
+	 * Beacon timer drifts by 1us every tick, the timer is configured
+	 * in 1/16 TU (64us) units.
+	 */
+	if (dev->tbtt_count < 63)
+		return;
+
+	/*
+	 * The updated beacon interval takes effect after two TBTT, because
+	 * at this point the original interval has already been loaded into
+	 * the next TBTT_TIMER value
+	 */
+	if (dev->tbtt_count == 63)
+		timer_val -= 1;
+
+	mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
+		       MT_BEACON_TIME_CFG_INTVAL, timer_val);
+
+	if (dev->tbtt_count >= 64) {
+		dev->tbtt_count = 0;
+		return;
+	}
+}
+EXPORT_SYMBOL_GPL(mt76x02_resync_beacon_timer);
+
+void
+mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct mt76x02_dev *dev = (struct mt76x02_dev *)priv;
+	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
+	struct sk_buff *skb = NULL;
+
+	if (!(dev->beacon_mask & BIT(mvif->idx)))
+		return;
+
+	skb = ieee80211_beacon_get(mt76_hw(dev), vif);
+	if (!skb)
+		return;
+
+	mt76x02_mac_set_beacon(dev, mvif->idx, skb);
+}
+EXPORT_SYMBOL_GPL(mt76x02_update_beacon_iter);
+
+static void
+mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct beacon_bc_data *data = priv;
+	struct mt76x02_dev *dev = data->dev;
+	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
+	struct ieee80211_tx_info *info;
+	struct sk_buff *skb;
+
+	if (!(dev->beacon_mask & BIT(mvif->idx)))
+		return;
+
+	skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
+	if (!skb)
+		return;
+
+	info = IEEE80211_SKB_CB(skb);
+	info->control.vif = vif;
+	info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
+	mt76_skb_set_moredata(skb, true);
+	__skb_queue_tail(&data->q, skb);
+	data->tail[mvif->idx] = skb;
+}
+
+void
+mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev, struct beacon_bc_data *data,
+			    int max_nframes)
+{
+	int i, nframes;
+
+	data->dev = dev;
+	__skb_queue_head_init(&data->q);
+
+	do {
+		nframes = skb_queue_len(&data->q);
+		ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+			IEEE80211_IFACE_ITER_RESUME_ALL,
+			mt76x02_add_buffered_bc, data);
+	} while (nframes != skb_queue_len(&data->q) &&
+		 skb_queue_len(&data->q) < max_nframes);
+
+	if (!skb_queue_len(&data->q))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(data->tail); i++) {
+		if (!data->tail[i])
+			continue;
+		mt76_skb_set_moredata(data->tail[i], false);
+	}
+}
+EXPORT_SYMBOL_GPL(mt76x02_enqueue_buffered_bc);
+
 void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
 {
 	int i;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
index f83a633144ab..e6723bd44e04 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -21,97 +21,16 @@
 #include "mt76x02.h"
 #include "mt76x02_trace.h"
 
-struct beacon_bc_data {
-	struct mt76x02_dev *dev;
-	struct sk_buff_head q;
-	struct sk_buff *tail[8];
-};
-
-static void
-mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct mt76x02_dev *dev = (struct mt76x02_dev *)priv;
-	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
-	struct sk_buff *skb = NULL;
-
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
-		return;
-
-	skb = ieee80211_beacon_get(mt76_hw(dev), vif);
-	if (!skb)
-		return;
-
-	mt76x02_mac_set_beacon(dev, mvif->idx, skb);
-}
-
-static void
-mt76x02_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct beacon_bc_data *data = priv;
-	struct mt76x02_dev *dev = data->dev;
-	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
-	struct ieee80211_tx_info *info;
-	struct sk_buff *skb;
-
-	if (!(dev->beacon_mask & BIT(mvif->idx)))
-		return;
-
-	skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif);
-	if (!skb)
-		return;
-
-	info = IEEE80211_SKB_CB(skb);
-	info->control.vif = vif;
-	info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
-	mt76_skb_set_moredata(skb, true);
-	__skb_queue_tail(&data->q, skb);
-	data->tail[mvif->idx] = skb;
-}
-
-static void
-mt76x02_resync_beacon_timer(struct mt76x02_dev *dev)
-{
-	u32 timer_val = dev->beacon_int << 4;
-
-	dev->tbtt_count++;
-
-	/*
-	 * Beacon timer drifts by 1us every tick, the timer is configured
-	 * in 1/16 TU (64us) units.
-	 */
-	if (dev->tbtt_count < 63)
-		return;
-
-	/*
-	 * The updated beacon interval takes effect after two TBTT, because
-	 * at this point the original interval has already been loaded into
-	 * the next TBTT_TIMER value
-	 */
-	if (dev->tbtt_count == 63)
-		timer_val -= 1;
-
-	mt76_rmw_field(dev, MT_BEACON_TIME_CFG,
-		       MT_BEACON_TIME_CFG_INTVAL, timer_val);
-
-	if (dev->tbtt_count >= 64) {
-		dev->tbtt_count = 0;
-		return;
-	}
-}
-
 static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
 {
 	struct mt76x02_dev *dev = (struct mt76x02_dev *)arg;
 	struct mt76_queue *q = &dev->mt76.q_tx[MT_TXQ_PSD];
 	struct beacon_bc_data data = {};
 	struct sk_buff *skb;
-	int i, nframes;
+	int i;
 
 	mt76x02_resync_beacon_timer(dev);
 
-	data.dev = dev;
-	__skb_queue_head_init(&data.q);
-
 	ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
 		IEEE80211_IFACE_ITER_RESUME_ALL,
 		mt76x02_update_beacon_iter, dev);
@@ -121,13 +40,7 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg)
 	if (dev->mt76.csa_complete)
 		return;
 
-	do {
-		nframes = skb_queue_len(&data.q);
-		ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
-			IEEE80211_IFACE_ITER_RESUME_ALL,
-			mt76x02_add_buffered_bc, &data);
-	} while (nframes != skb_queue_len(&data.q) &&
-		 skb_queue_len(&data.q) < 8);
+	mt76x02_enqueue_buffered_bc(dev, &data, 8);
 
 	if (!skb_queue_len(&data.q))
 		return;
-- 
2.20.1


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

* [RFC 06/12] mt76x02u: add sta_ps
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (4 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 05/12] mt76x02: generalize some mmio beaconing functions Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB Stanislaw Gruszka
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Add sta_ps callback but dont set WCID drop sicne registers for USB
can not be accessed from tasklet context.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c   | 1 +
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x2/usb.c   | 1 +
 3 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 7f3113b91498..0348a1b38d2d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -222,6 +222,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
 		.tx_complete_skb = mt76x02u_tx_complete_skb,
 		.tx_status_data = mt76x02_tx_status_data,
 		.rx_skb = mt76x02_queue_rx_skb,
+		.sta_ps = mt76x02_sta_ps,
 		.sta_add = mt76x02_sta_add,
 		.sta_remove = mt76x02_sta_remove,
 	};
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 83fc9d1add82..97a8aa30c333 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -625,7 +625,8 @@ void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta,
 	int idx = msta->wcid.idx;
 
 	mt76_stop_tx_queues(&dev->mt76, sta, true);
-	mt76x02_mac_wcid_set_drop(dev, idx, ps);
+	if (mt76_is_mmio(dev))
+		mt76x02_mac_wcid_set_drop(dev, idx, ps);
 }
 EXPORT_SYMBOL_GPL(mt76x02_sta_ps);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index ddb6b2c48e01..03cd744bb89d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -41,6 +41,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
 		.tx_complete_skb = mt76x02u_tx_complete_skb,
 		.tx_status_data = mt76x02_tx_status_data,
 		.rx_skb = mt76x02_queue_rx_skb,
+		.sta_ps = mt76x02_sta_ps,
 		.sta_add = mt76x02_sta_add,
 		.sta_remove = mt76x02_sta_remove,
 	};
-- 
2.20.1


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

* [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (5 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 06/12] mt76x02u: add sta_ps Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  9:38   ` Lorenzo Bianconi
  2019-02-28  8:03 ` [RFC 08/12] mt76x02: disable HW encryption for group frames Stanislaw Gruszka
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Since we add txwi at the begining of skb->data, it no longer point
to ieee80211_hdr. This breaks settings TS bit for probe response and
beacons.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++-
 1 file changed, 2 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 fdd6a021914d..bcf3126efda9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 
 	mt76x02_insert_hdr_pad(skb);
 
-	txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
+	txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
 	mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
+	skb_push(skb, sizeof(struct mt76x02_txwi));
 
 	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
 	txwi->pktid = pid;
-- 
2.20.1


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

* [RFC 08/12] mt76x02: disable HW encryption for group frames
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (6 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 09/12] mt76x02u: implement pre TBTT work for USB Stanislaw Gruszka
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

This is required to sent multicast/broadcast frames in USB AP
mode just after beacon.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 97a8aa30c333..6e5ad900bf4e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -418,6 +418,16 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 		return -EOPNOTSUPP;
 
+	/*
+	 * In USB AP mode, broadcast/multicast frames are setup in beacon
+	 * data registers and sent via HW beacons engine, they require to
+	 * be already encrypted.
+	 */
+	if (mt76_is_usb(dev) &&
+	    vif->type == NL80211_IFTYPE_AP &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
 	msta = sta ? (struct mt76x02_sta *) sta->drv_priv : NULL;
 	wcid = msta ? &msta->wcid : &mvif->group_wcid;
 
-- 
2.20.1


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

* [RFC 09/12] mt76x02u: implement pre TBTT work for USB
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (7 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 08/12] mt76x02: disable HW encryption for group frames Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 10/12] mt76x02u: add mt76_release_buffered_frames Stanislaw Gruszka
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Program beacons data and PS buffered frames on TBTT work for USB.
We do not have MT_TXQ_PSD queue available via USB endpoints. The way
we can send PS broadcast frames in timely manner before PS stations go
sleep again is program them in beacon data area. Hardware do not modify
those frames since TXWI is properly configured. mt76x02_mac_set_beacon()
already handle this and free no longer used frames.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 .../wireless/mediatek/mt76/mt76x02_beacon.c   |  2 ++
 .../wireless/mediatek/mt76/mt76x02_usb_core.c | 36 +++++++++++++++++--
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
index 28102082772b..63e2926cdd0c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -38,6 +38,7 @@ const u16 mt76x02_beacon_offsets[16] = {
 	0xc000,
 	0xc000,
 };
+EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
 
 static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev)
 {
@@ -134,6 +135,7 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx,
 		       bcn_idx - 1);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mt76x02_mac_set_beacon);
 
 static void
 __mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
index bcf3126efda9..2761a9300755 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -165,9 +165,32 @@ static void mt76x02u_pre_tbtt_work(struct work_struct *work)
 {
 	struct mt76x02_dev *dev =
 		container_of(work, struct mt76x02_dev, pre_tbtt_work);
+	int beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
+	struct beacon_bc_data data = {};
+	struct sk_buff *skb;
+	int i, nbeacons;
 
 	if (!dev->beacon_mask)
 		return;
+
+	mt76x02_resync_beacon_timer(dev);
+
+	ieee80211_iterate_active_interfaces(mt76_hw(dev),
+		IEEE80211_IFACE_ITER_RESUME_ALL,
+		mt76x02_update_beacon_iter, dev);
+
+	nbeacons = hweight8(dev->beacon_mask);
+	mt76x02_enqueue_buffered_bc(dev, &data, 8 - nbeacons);
+
+	for (i = nbeacons; i < 8; i++) {
+		skb = __skb_dequeue(&data.q);
+		if (skb && skb->len >= beacon_len) {
+			dev_kfree_skb(skb);
+			skb = NULL;
+		}
+		mt76x02_mac_set_beacon(dev, i, skb);
+	}
+
 	mt76x02u_restart_pre_tbtt_timer(dev);
 }
 
@@ -191,13 +214,20 @@ static void mt76x02u_pre_tbtt_enable(struct mt76x02_dev *dev, bool en)
 
 static void mt76x02u_beacon_enable(struct mt76x02_dev *dev, bool en)
 {
+	int i;
+
 	if (WARN_ON_ONCE(!dev->beacon_int))
 		return;
 
-	if (en)
+	if (en) {
 		mt76x02u_start_pre_tbtt_timer(dev);
-
-	/* Nothing to do on disable as timer is already stopped */
+	} else {
+		/* Timer is already stopped, only clean up
+		 * PS buffered frames if any.
+		 */
+		for (i = 0; i < 8; i++)
+			mt76x02_mac_set_beacon(dev, i, NULL);
+	}
 }
 
 void mt76x02u_init_beacon_config(struct mt76x02_dev *dev)
-- 
2.20.1


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

* [RFC 10/12] mt76x02u: add mt76_release_buffered_frames
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (8 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 09/12] mt76x02u: implement pre TBTT work for USB Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 11/12] mt76x02: enable AP mode for USB Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 12/12] mt76x02: remove set_tim Stanislaw Gruszka
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Create software MT_TXQ_PSD queue for USB and map it to MT_TXQ_VO
since we do not have USB endpoint for PSD. This should make
mt76_release_buffered_frames() work by sending released frames
via MT_TXQ_VO.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c     |  1 +
 .../net/wireless/mediatek/mt76/mt76x2/usb_main.c    |  1 +
 drivers/net/wireless/mediatek/mt76/usb.c            | 13 ++++++++-----
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 0348a1b38d2d..b9b8a1dafbc9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -152,6 +152,7 @@ static const struct ieee80211_ops mt76x0u_ops = {
 	.set_rts_threshold = mt76x02_set_rts_threshold,
 	.wake_tx_queue = mt76_wake_tx_queue,
 	.get_txpower = mt76_get_txpower,
+	.release_buffered_frames = mt76_release_buffered_frames,
 };
 
 static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 2ac78e4dc41a..653b8df29ca3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -125,4 +125,5 @@ const struct ieee80211_ops mt76x2u_ops = {
 	.sw_scan_complete = mt76x02_sw_scan_complete,
 	.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
 	.get_txpower = mt76_get_txpower,
+	.release_buffered_frames = mt76_release_buffered_frames,
 };
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index ae6ada370597..f181200c05cb 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -632,7 +632,7 @@ static void mt76u_tx_tasklet(unsigned long data)
 	bool wake;
 	int i;
 
-	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+	for (i = 0; i <= MT_TXQ_PSD; i++) {
 		q = &dev->q_tx[i];
 
 		spin_lock_bh(&q->lock);
@@ -785,11 +785,14 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
 	struct mt76_queue *q;
 	int i, j;
 
-	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+	for (i = 0; i <= MT_TXQ_PSD; i++) {
 		q = &dev->q_tx[i];
 		spin_lock_init(&q->lock);
 		INIT_LIST_HEAD(&q->swq);
-		q->hw_idx = mt76_ac_to_hwq(i);
+		if (i < IEEE80211_NUM_ACS)
+			q->hw_idx = mt76_ac_to_hwq(i);
+		else
+			q->hw_idx = 0;
 
 		q->entry = devm_kcalloc(dev->dev,
 					MT_NUM_TX_ENTRIES, sizeof(*q->entry),
@@ -825,7 +828,7 @@ static void mt76u_free_tx(struct mt76_dev *dev)
 	struct mt76_queue *q;
 	int i, j;
 
-	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+	for (i = 0; i <= MT_TXQ_PSD; i++) {
 		q = &dev->q_tx[i];
 		for (j = 0; j < q->ndesc; j++)
 			usb_free_urb(q->entry[j].ubuf.urb);
@@ -837,7 +840,7 @@ static void mt76u_stop_tx(struct mt76_dev *dev)
 	struct mt76_queue *q;
 	int i, j;
 
-	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+	for (i = 0; i <= MT_TXQ_PSD; i++) {
 		q = &dev->q_tx[i];
 		for (j = 0; j < q->ndesc; j++)
 			usb_kill_urb(q->entry[j].ubuf.urb);
-- 
2.20.1


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

* [RFC 11/12] mt76x02: enable AP mode for USB
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (9 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 10/12] mt76x02u: add mt76_release_buffered_frames Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28  8:03 ` [RFC 12/12] mt76x02: remove set_tim Stanislaw Gruszka
  11 siblings, 0 replies; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

Enable AP mode. For now without multi-vif support, this will require
more testing and investigation.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 6e5ad900bf4e..49da4e6ae0c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -142,6 +142,7 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
 
 	wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_AP) |
 #ifdef CONFIG_MAC80211_MESH
 		BIT(NL80211_IFTYPE_MESH_POINT) |
 #endif
@@ -158,7 +159,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->interface_modes |= BIT(NL80211_IFTYPE_AP);
 		wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
 		/* init led callbacks */
-- 
2.20.1


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

* [RFC 12/12] mt76x02: remove set_tim
  2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
                   ` (10 preceding siblings ...)
  2019-02-28  8:03 ` [RFC 11/12] mt76x02: enable AP mode for USB Stanislaw Gruszka
@ 2019-02-28  8:03 ` Stanislaw Gruszka
  2019-02-28 10:51   ` Felix Fietkau
  11 siblings, 1 reply; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28  8:03 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless, Lorenzo Bianconi

set_tim callback is not used by mac80211 if AP_LINK_PS hw flag is set.

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c      | 8 --------
 drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 7 -------
 2 files changed, 15 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index fafe57653ac0..68d44929dafa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -74,13 +74,6 @@ mt76x0e_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 }
 
-static int
-mt76x0e_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-		bool set)
-{
-	return 0;
-}
-
 static const struct ieee80211_ops mt76x0e_ops = {
 	.tx = mt76x02_tx,
 	.start = mt76x0e_start,
@@ -101,7 +94,6 @@ static const struct ieee80211_ops mt76x0e_ops = {
 	.get_survey = mt76_get_survey,
 	.get_txpower = mt76_get_txpower,
 	.flush = mt76x0e_flush,
-	.set_tim = mt76x0e_set_tim,
 	.release_buffered_frames = mt76_release_buffered_frames,
 	.set_coverage_class = mt76x02_set_coverage_class,
 	.set_rts_threshold = mt76x02_set_rts_threshold,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
index 878ce92405ed..f45847f48920 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
@@ -135,12 +135,6 @@ mt76x2_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
 }
 
-static int
-mt76x2_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
-	return 0;
-}
-
 static int mt76x2_set_antenna(struct ieee80211_hw *hw, u32 tx_ant,
 			      u32 rx_ant)
 {
@@ -197,7 +191,6 @@ const struct ieee80211_ops mt76x2_ops = {
 	.release_buffered_frames = mt76_release_buffered_frames,
 	.set_coverage_class = mt76x02_set_coverage_class,
 	.get_survey = mt76_get_survey,
-	.set_tim = mt76x2_set_tim,
 	.set_antenna = mt76x2_set_antenna,
 	.get_antenna = mt76x2_get_antenna,
 	.set_rts_threshold = mt76x02_set_rts_threshold,
-- 
2.20.1


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

* Re: [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB
  2019-02-28  8:03 ` [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB Stanislaw Gruszka
@ 2019-02-28  9:38   ` Lorenzo Bianconi
  2019-02-28 13:52     ` Stanislaw Gruszka
  0 siblings, 1 reply; 17+ messages in thread
From: Lorenzo Bianconi @ 2019-02-28  9:38 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 1284 bytes --]

> Since we add txwi at the begining of skb->data, it no longer point
> to ieee80211_hdr. This breaks settings TS bit for probe response and
> beacons.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++-
>  1 file changed, 2 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 fdd6a021914d..bcf3126efda9 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
> @@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
>  
>  	mt76x02_insert_hdr_pad(skb);
>  
> -	txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
> +	txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
>  	mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
> +	skb_push(skb, sizeof(struct mt76x02_txwi));
>  
>  	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
>  	txwi->pktid = pid;
> -- 
> 2.20.1
> 

Good catch :)
I think we should post it ontop of wireless-drivers since sw encryption is not
working now.

Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [RFC 12/12] mt76x02: remove set_tim
  2019-02-28  8:03 ` [RFC 12/12] mt76x02: remove set_tim Stanislaw Gruszka
@ 2019-02-28 10:51   ` Felix Fietkau
  0 siblings, 0 replies; 17+ messages in thread
From: Felix Fietkau @ 2019-02-28 10:51 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linux-wireless, Lorenzo Bianconi

On 2019-02-28 09:03, Stanislaw Gruszka wrote:
> set_tim callback is not used by mac80211 if AP_LINK_PS hw flag is set.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>

There's a check in __sta_info_recalc_tim:

    /* No need to do anything if the driver does all */
    if (ieee80211_hw_check(&local->hw, AP_LINK_PS) && !local->ops->set_tim)
        return;

At the moment we need this dummy callback to ensure that the 
beacon TIM bits are set. 

- Felix 

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

* Re: [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB
  2019-02-28  9:38   ` Lorenzo Bianconi
@ 2019-02-28 13:52     ` Stanislaw Gruszka
  2019-02-28 14:23       ` Kalle Valo
  0 siblings, 1 reply; 17+ messages in thread
From: Stanislaw Gruszka @ 2019-02-28 13:52 UTC (permalink / raw)
  To: Lorenzo Bianconi, Kalle Valo; +Cc: Felix Fietkau, linux-wireless

On Thu, Feb 28, 2019 at 10:38:20AM +0100, Lorenzo Bianconi wrote:
> > Since we add txwi at the begining of skb->data, it no longer point
> > to ieee80211_hdr. This breaks settings TS bit for probe response and
> > beacons.
> > 
> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++-
> >  1 file changed, 2 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 fdd6a021914d..bcf3126efda9 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
> > @@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
> >  
> >  	mt76x02_insert_hdr_pad(skb);
> >  
> > -	txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
> > +	txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
> >  	mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
> > +	skb_push(skb, sizeof(struct mt76x02_txwi));
> >  
> >  	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
> >  	txwi->pktid = pid;
> > -- 
> > 2.20.1
> > 
> 
> Good catch :)
> I think we should post it ontop of wireless-drivers since sw encryption is not
> working now.
> 
> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>

I can send it against 5.0, if Kalle will accept it, however
I do not have practical bug associated with this. Maybe we
sometimes can send ordinal frame with TS bit in txwi and it
is then malformed by HW, but I'm not sure. IBSS work with
this bug, not sure about MESH.

Stanislaw


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

* Re: [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB
  2019-02-28 13:52     ` Stanislaw Gruszka
@ 2019-02-28 14:23       ` Kalle Valo
  0 siblings, 0 replies; 17+ messages in thread
From: Kalle Valo @ 2019-02-28 14:23 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Lorenzo Bianconi, Felix Fietkau, linux-wireless

Stanislaw Gruszka <sgruszka@redhat.com> writes:

> On Thu, Feb 28, 2019 at 10:38:20AM +0100, Lorenzo Bianconi wrote:
>> > Since we add txwi at the begining of skb->data, it no longer point
>> > to ieee80211_hdr. This breaks settings TS bit for probe response and
>> > beacons.
>> > 
>> > Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
>> > ---
>> >  drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 ++-
>> >  1 file changed, 2 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 fdd6a021914d..bcf3126efda9 100644
>> > --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
>> > +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
>> > @@ -85,8 +85,9 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
>> >  
>> >  	mt76x02_insert_hdr_pad(skb);
>> >  
>> > -	txwi = skb_push(skb, sizeof(struct mt76x02_txwi));
>> > +	txwi = (struct mt76x02_txwi *)(skb->data - sizeof(struct mt76x02_txwi));
>> >  	mt76x02_mac_write_txwi(dev, txwi, skb, wcid, sta, len);
>> > +	skb_push(skb, sizeof(struct mt76x02_txwi));
>> >  
>> >  	pid = mt76_tx_status_skb_add(mdev, wcid, skb);
>> >  	txwi->pktid = pid;
>> > -- 
>> > 2.20.1
>> > 
>> 
>> Good catch :)
>> I think we should post it ontop of wireless-drivers since sw encryption is not
>> working now.
>> 
>> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
>
> I can send it against 5.0, if Kalle will accept it, however
> I do not have practical bug associated with this. Maybe we
> sometimes can send ordinal frame with TS bit in txwi and it
> is then malformed by HW, but I'm not sure. IBSS work with
> this bug, not sure about MESH.

Too late for 5.0 as Linus will most likely release it on Sunday. I
recommend sending it to wireless-drivers-next so that I can queue it for
5.1.

-- 
Kalle Valo

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

end of thread, other threads:[~2019-02-28 14:23 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-28  8:03 [RFC 00/12] mt76x02: AP support for with PS Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 01/12] mt76x02: introduce mt76x02_beacon.c Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 02/12] mt76x02: add hrtimer for pre TBTT for USB Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 03/12] mt76x02: introduce beacon_ops Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 04/12] mt76x02u: implement beacon_ops Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 05/12] mt76x02: generalize some mmio beaconing functions Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 06/12] mt76x02u: add sta_ps Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 07/12] mt76x02: fix hdr pointer in write txwi for USB Stanislaw Gruszka
2019-02-28  9:38   ` Lorenzo Bianconi
2019-02-28 13:52     ` Stanislaw Gruszka
2019-02-28 14:23       ` Kalle Valo
2019-02-28  8:03 ` [RFC 08/12] mt76x02: disable HW encryption for group frames Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 09/12] mt76x02u: implement pre TBTT work for USB Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 10/12] mt76x02u: add mt76_release_buffered_frames Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 11/12] mt76x02: enable AP mode for USB Stanislaw Gruszka
2019-02-28  8:03 ` [RFC 12/12] mt76x02: remove set_tim Stanislaw Gruszka
2019-02-28 10:51   ` Felix Fietkau

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.