Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 08/12] mt76x02u: implement pre TBTT work for USB
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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>
---
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c    |  2 ++
 .../net/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 d77088b7659e..c0be90988f82 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -38,6 +38,7 @@
 	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 82b78cc5b362..89249621bcec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
@@ -164,9 +164,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);
 }
 
@@ -190,13 +213,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)
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 07/12] mt76x02: disable HW encryption for group frames
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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 168c62a90361..ed6463c9166e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -424,6 +424,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;
 
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 06/12] mt76x02u: add sta_ps
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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 1026939d6b63..168c62a90361 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -615,7 +615,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 7a5d539873ca..1f0b1bebed79 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -40,6 +40,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,
 	};
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 05/12] mt76x02: generalize some mmio beaconing functions
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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 +++
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c    | 102 +++++++++++++++++++++
 drivers/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 0bfc3a9839d0..93f9436ab809 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -195,8 +195,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_mac_start(struct mt76x02_dev *dev);
 
 void mt76x02_init_debugfs(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 e980becb6683..d77088b7659e 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 2be3ca0c67be..eea8e4718600 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -22,97 +22,16 @@
 #include "mt76x02_mcu.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].q;
 	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);
@@ -122,13 +41,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;
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 04/12] mt76x02u: implement beacon_ops
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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>
---
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    |  5 +---
 drivers/net/wireless/mediatek/mt76/mt76x02_usb.h   |  1 +
 .../net/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 6ff740f09bc9..a012410c5ae7 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, enum mt76_txq_id qid,
 			      struct mt76_queue_entry *e);
 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 eec6f856f88a..82b78cc5b362 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);
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 03/12] mt76x02: introduce beacon_ops
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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>
---
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c   |  8 ++++----
 drivers/net/wireless/mediatek/mt76/mt76x02.h       |  7 +++++++
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c    | 18 +++++------------
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c  | 23 ++++++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt76x02_usb_core.c  | 14 +++++++++++++
 .../net/wireless/mediatek/mt76/mt76x2/usb_main.c   |  4 ++++
 6 files changed, 57 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 @@
 	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 @@
 
 	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 9fa6e4fc221f..0bfc3a9839d0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -68,6 +68,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 */
 
@@ -91,6 +96,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..e980becb6683 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -162,14 +162,7 @@ int mt76x02_mac_set_beacon(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, false);
+
+	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 75dceeeed059..2be3ca0c67be 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -152,8 +152,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 f1a3d41c8209..eec6f856f88a 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);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
index 2ac78e4dc41a..1e6856856536 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c
@@ -57,6 +57,8 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
 
 	mt76_set_channel(&dev->mt76);
 
+	dev->beacon_ops->pre_tbtt_enable(dev, false);
+
 	mt76x2_mac_stop(dev, false);
 
 	err = mt76x2u_phy_set_channel(dev, chandef);
@@ -64,6 +66,8 @@ static void mt76x2u_stop(struct ieee80211_hw *hw)
 	mt76x2_mac_resume(dev);
 	mt76x02_edcca_init(dev, true);
 
+	dev->beacon_ops->pre_tbtt_enable(dev, true);
+
 	clear_bit(MT76_RESET, &dev->mt76.state);
 	mt76_txq_schedule_all(&dev->mt76);
 
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 02/12] mt76x02: add hrtimer for pre TBTT for USB
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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 +
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h  |  5 +-
 .../net/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 e93f4840cace..9fa6e4fc221f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -88,6 +88,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 7e0a5f364469..f1a3d41c8209 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);
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 01/12] mt76x02: introduce mt76x02_beacon.c
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka
In-Reply-To: <1552991867-5087-1-git-send-email-sgruszka@redhat.com>

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 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   |   1 -
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c    |   2 +
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    |   2 +
 drivers/net/wireless/mediatek/mt76/mt76x02.h       |   1 +
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c    | 212 +++++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.c   | 138 --------------
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c  |  17 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_usb.h   |   1 +
 .../net/wireless/mediatek/mt76/mt76x02_usb_core.c  |   6 +
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c  |  62 ------
 .../net/wireless/mediatek/mt76/mt76x2/pci_init.c   |   2 +-
 .../net/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 e07a62246db7..e35165416cf0 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 cb5792b41d2d..e93f4840cace 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -186,6 +186,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_mac_start(struct mt76x02_dev *dev);
 
 void mt76x02_init_debugfs(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 df6930a94f74..1eb669ccd5a7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -1053,141 +1053,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 ec94d612f53c..75dceeeed059 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c
@@ -152,6 +152,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_sw_queue *q,
 		      int idx, int n_desc)
@@ -230,8 +245,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 8f98cc6ce094..6ff740f09bc9 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,
 			    struct mt76_tx_info *tx_info);
 void mt76x02u_tx_complete_skb(struct mt76_dev *mdev, enum mt76_txq_id qid,
 			      struct mt76_queue_entry *e);
+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 394dfe5b4a2e..7e0a5f364469 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 81d65319d3ea..1026939d6b63 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -619,68 +619,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 d3927a13e92e..9e88a8cec9e5 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 @@ 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);
-- 
1.9.3


^ permalink raw reply related

* [PATCH v2 00/12] mt76x02: AP support for USB with PS
From: Stanislaw Gruszka @ 2019-03-19 10:37 UTC (permalink / raw)
  To: linux-wireless; +Cc: Felix Fietkau, Lorenzo Bianconi, Stanislaw Gruszka

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)

Tested on MT7610U and MT7630E (on this device TX hang
in AP mode on 2.4GHz band, but this is not related to this
patch set).

RFC -> v1:
- do no remove set_tim
- add tbtt_start/stop for mt76x2u  
- rebase on top of:
  [PATCH 0/5] introduce mt76_sw_queue data structure
  https://lore.kernel.org/linux-wireless/cover.1551533068.git.lorenzo@kernel.org/

v1 -> v2
- fix true/false bug in patch 3
- change beacon slot size for USB

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: disable HW encryption for group frames
  mt76x02u: implement pre TBTT work for USB
  mt76x02: make beacon slots bigger for USB
  mt76x02u: add mt76_release_buffered_frames
  mt76: unify set_tim
  mt76x02: enable AP mode for USB

 drivers/net/wireless/mediatek/mt76/Makefile        |   2 +-
 drivers/net/wireless/mediatek/mt76/mac80211.c      |   7 +
 drivers/net/wireless/mediatek/mt76/mt76.h          |   2 +
 drivers/net/wireless/mediatek/mt76/mt7603/main.c   |   8 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   |   1 -
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c   |   8 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c    |  11 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    |  10 +-
 drivers/net/wireless/mediatek/mt76/mt76x02.h       |  25 +-
 .../net/wireless/mediatek/mt76/mt76x02_beacon.c    | 286 +++++++++++++++++++++
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.c   | 138 ----------
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c  | 133 +++-------
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h  |   5 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_usb.h   |   2 +
 .../net/wireless/mediatek/mt76/mt76x02_usb_core.c  | 157 +++++++++++
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c  |  77 +-----
 .../net/wireless/mediatek/mt76/mt76x2/pci_init.c   |   2 +-
 .../net/wireless/mediatek/mt76/mt76x2/pci_main.c   |   8 +-
 drivers/net/wireless/mediatek/mt76/mt76x2/usb.c    |   1 +
 .../net/wireless/mediatek/mt76/mt76x2/usb_init.c   |   2 +-
 .../net/wireless/mediatek/mt76/mt76x2/usb_main.c   |   6 +
 drivers/net/wireless/mediatek/mt76/usb.c           |   7 +-
 22 files changed, 568 insertions(+), 330 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c

-- 
1.9.3


^ permalink raw reply

* Re: [PATCH 09/11] cfg80211: support profile split between elements
From: Dan Carpenter @ 2019-03-19  9:06 UTC (permalink / raw)
  To: kbuild, Luca Coelho
  Cc: kbuild-all, johannes, linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-10-luca@coelho.fi>

Hi Luca,

Thank you for the patch! Perhaps something to improve:

url:    https://github.com/0day-ci/linux/commits/Luca-Coelho/mac80211-Increase-MAX_MSG_LEN/20190316-083719
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master

smatch warnings:
net/wireless/scan.c:1610 cfg80211_parse_mbssid_data() warn: should '1 << (mbssid_index_ie[2])' be a 64 bit type?

# https://github.com/0day-ci/linux/commit/e28e850d09f80732c1e9c04e0079c4e40f23ef7d
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout e28e850d09f80732c1e9c04e0079c4e40f23ef7d
vim +1610 net/wireless/scan.c

e28e850d Sara Sharon   2019-03-15  1530  
0b8fb823 Peng Xu       2019-01-21  1531  static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
0b8fb823 Peng Xu       2019-01-21  1532  				       struct cfg80211_inform_bss *data,
0b8fb823 Peng Xu       2019-01-21  1533  				       enum cfg80211_bss_frame_type ftype,
0b8fb823 Peng Xu       2019-01-21  1534  				       const u8 *bssid, u64 tsf,
0b8fb823 Peng Xu       2019-01-21  1535  				       u16 beacon_interval, const u8 *ie,
0b8fb823 Peng Xu       2019-01-21  1536  				       size_t ielen,
0cd01efb Sara Sharon   2019-01-22  1537  				       struct cfg80211_non_tx_bss *non_tx_data,
0b8fb823 Peng Xu       2019-01-21  1538  				       gfp_t gfp)
0b8fb823 Peng Xu       2019-01-21  1539  {
1c8745f3 Johannes Berg 2019-02-07  1540  	const u8 *mbssid_index_ie;
1c8745f3 Johannes Berg 2019-02-07  1541  	const struct element *elem, *sub;
1c8745f3 Johannes Berg 2019-02-07  1542  	size_t new_ie_len;
0b8fb823 Peng Xu       2019-01-21  1543  	u8 new_bssid[ETH_ALEN];
e28e850d Sara Sharon   2019-03-15  1544  	u8 *new_ie, *profile;
e28e850d Sara Sharon   2019-03-15  1545  	u64 seen_indices = 0;
0b8fb823 Peng Xu       2019-01-21  1546  	u16 capability;
0b8fb823 Peng Xu       2019-01-21  1547  	struct cfg80211_bss *bss;
0b8fb823 Peng Xu       2019-01-21  1548  
0cd01efb Sara Sharon   2019-01-22  1549  	if (!non_tx_data)
0b8fb823 Peng Xu       2019-01-21  1550  		return;
0b8fb823 Peng Xu       2019-01-21  1551  	if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
0b8fb823 Peng Xu       2019-01-21  1552  		return;
213ed579 Sara Sharon   2019-01-16  1553  	if (!wiphy->support_mbssid)
213ed579 Sara Sharon   2019-01-16  1554  		return;
213ed579 Sara Sharon   2019-01-16  1555  	if (wiphy->support_only_he_mbssid &&
213ed579 Sara Sharon   2019-01-16  1556  	    !cfg80211_find_ext_ie(WLAN_EID_EXT_HE_CAPABILITY, ie, ielen))
213ed579 Sara Sharon   2019-01-16  1557  		return;
0b8fb823 Peng Xu       2019-01-21  1558  
0b8fb823 Peng Xu       2019-01-21  1559  	new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
0b8fb823 Peng Xu       2019-01-21  1560  	if (!new_ie)
0b8fb823 Peng Xu       2019-01-21  1561  		return;
0b8fb823 Peng Xu       2019-01-21  1562  
e28e850d Sara Sharon   2019-03-15  1563  	profile = kmalloc(ielen, gfp);
e28e850d Sara Sharon   2019-03-15  1564  	if (!profile)
e28e850d Sara Sharon   2019-03-15  1565  		goto out;
e28e850d Sara Sharon   2019-03-15  1566  
1c8745f3 Johannes Berg 2019-02-07  1567  	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) {
1c8745f3 Johannes Berg 2019-02-07  1568  		if (elem->datalen < 4)
1c8745f3 Johannes Berg 2019-02-07  1569  			continue;
1c8745f3 Johannes Berg 2019-02-07  1570  		for_each_element(sub, elem->data + 1, elem->datalen - 1) {
e28e850d Sara Sharon   2019-03-15  1571  			u8 profile_len;
e28e850d Sara Sharon   2019-03-15  1572  
1c8745f3 Johannes Berg 2019-02-07  1573  			if (sub->id != 0 || sub->datalen < 4) {
0b8fb823 Peng Xu       2019-01-21  1574  				/* not a valid BSS profile */
0b8fb823 Peng Xu       2019-01-21  1575  				continue;
0b8fb823 Peng Xu       2019-01-21  1576  			}
0b8fb823 Peng Xu       2019-01-21  1577  
1c8745f3 Johannes Berg 2019-02-07  1578  			if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
1c8745f3 Johannes Berg 2019-02-07  1579  			    sub->data[1] != 2) {
0b8fb823 Peng Xu       2019-01-21  1580  				/* The first element within the Nontransmitted
0b8fb823 Peng Xu       2019-01-21  1581  				 * BSSID Profile is not the Nontransmitted
0b8fb823 Peng Xu       2019-01-21  1582  				 * BSSID Capability element.
0b8fb823 Peng Xu       2019-01-21  1583  				 */
0b8fb823 Peng Xu       2019-01-21  1584  				continue;
0b8fb823 Peng Xu       2019-01-21  1585  			}
0b8fb823 Peng Xu       2019-01-21  1586  
e28e850d Sara Sharon   2019-03-15  1587  			memset(profile, 0, ielen);
e28e850d Sara Sharon   2019-03-15  1588  			profile_len = cfg80211_merge_profile(ie, ielen,
e28e850d Sara Sharon   2019-03-15  1589  							     elem,
e28e850d Sara Sharon   2019-03-15  1590  							     sub,
e28e850d Sara Sharon   2019-03-15  1591  							     &profile,
e28e850d Sara Sharon   2019-03-15  1592  							     ielen);
e28e850d Sara Sharon   2019-03-15  1593  
0b8fb823 Peng Xu       2019-01-21  1594  			/* found a Nontransmitted BSSID Profile */
0b8fb823 Peng Xu       2019-01-21  1595  			mbssid_index_ie = cfg80211_find_ie
0b8fb823 Peng Xu       2019-01-21  1596  				(WLAN_EID_MULTI_BSSID_IDX,
e28e850d Sara Sharon   2019-03-15  1597  				 profile, profile_len);
0b8fb823 Peng Xu       2019-01-21  1598  			if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
e28e850d Sara Sharon   2019-03-15  1599  			    mbssid_index_ie[2] == 0 ||
e28e850d Sara Sharon   2019-03-15  1600  			    mbssid_index_ie[2] > 46) {
0b8fb823 Peng Xu       2019-01-21  1601  				/* No valid Multiple BSSID-Index element */
0b8fb823 Peng Xu       2019-01-21  1602  				continue;
0b8fb823 Peng Xu       2019-01-21  1603  			}
0b8fb823 Peng Xu       2019-01-21  1604  
e28e850d Sara Sharon   2019-03-15  1605  			if (seen_indices & BIT(mbssid_index_ie[2]))
                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I should fix Smatch to generate a warning here as well...

e28e850d Sara Sharon   2019-03-15  1606  				/* We don't support legacy split of a profile */
e28e850d Sara Sharon   2019-03-15  1607  				net_dbg_ratelimited("Partial info for BSSID index %d\n",
e28e850d Sara Sharon   2019-03-15  1608  						    mbssid_index_ie[2]);
e28e850d Sara Sharon   2019-03-15  1609  
e28e850d Sara Sharon   2019-03-15 @1610  			seen_indices |= BIT(mbssid_index_ie[2]);
                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

e28e850d Sara Sharon   2019-03-15  1611  
0cd01efb Sara Sharon   2019-01-22  1612  			non_tx_data->bssid_index = mbssid_index_ie[2];
0cd01efb Sara Sharon   2019-01-22  1613  			non_tx_data->max_bssid_indicator = elem->data[0];
0cd01efb Sara Sharon   2019-01-22  1614  
0cd01efb Sara Sharon   2019-01-22  1615  			cfg80211_gen_new_bssid(bssid,
0cd01efb Sara Sharon   2019-01-22  1616  					       non_tx_data->max_bssid_indicator,
0cd01efb Sara Sharon   2019-01-22  1617  					       non_tx_data->bssid_index,
0b8fb823 Peng Xu       2019-01-21  1618  					       new_bssid);
0b8fb823 Peng Xu       2019-01-21  1619  			memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
e28e850d Sara Sharon   2019-03-15  1620  			new_ie_len = cfg80211_gen_new_ie(ie, ielen,
e28e850d Sara Sharon   2019-03-15  1621  							 profile,
e28e850d Sara Sharon   2019-03-15  1622  							 profile_len, new_ie,
0b8fb823 Peng Xu       2019-01-21  1623  							 gfp);
0b8fb823 Peng Xu       2019-01-21  1624  			if (!new_ie_len)
0b8fb823 Peng Xu       2019-01-21  1625  				continue;
0b8fb823 Peng Xu       2019-01-21  1626  
e28e850d Sara Sharon   2019-03-15  1627  			capability = get_unaligned_le16(profile + 2);
0b8fb823 Peng Xu       2019-01-21  1628  			bss = cfg80211_inform_single_bss_data(wiphy, data,
0b8fb823 Peng Xu       2019-01-21  1629  							      ftype,
0b8fb823 Peng Xu       2019-01-21  1630  							      new_bssid, tsf,
0b8fb823 Peng Xu       2019-01-21  1631  							      capability,
0b8fb823 Peng Xu       2019-01-21  1632  							      beacon_interval,
0b8fb823 Peng Xu       2019-01-21  1633  							      new_ie,
0b8fb823 Peng Xu       2019-01-21  1634  							      new_ie_len,
0cd01efb Sara Sharon   2019-01-22  1635  							      non_tx_data,
0cd01efb Sara Sharon   2019-01-22  1636  							      gfp);
0b8fb823 Peng Xu       2019-01-21  1637  			if (!bss)
0b8fb823 Peng Xu       2019-01-21  1638  				break;
0b8fb823 Peng Xu       2019-01-21  1639  			cfg80211_put_bss(wiphy, bss);
0b8fb823 Peng Xu       2019-01-21  1640  		}
0b8fb823 Peng Xu       2019-01-21  1641  	}
0b8fb823 Peng Xu       2019-01-21  1642  
e28e850d Sara Sharon   2019-03-15  1643  out:
0b8fb823 Peng Xu       2019-01-21  1644  	kfree(new_ie);
e28e850d Sara Sharon   2019-03-15  1645  	kfree(profile);
0b8fb823 Peng Xu       2019-01-21  1646  }
0b8fb823 Peng Xu       2019-01-21  1647  

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply

* Re: [PATCH] ath9k: Check for errors when reading SREV register
From: Tim Schumacher @ 2019-03-19  6:41 UTC (permalink / raw)
  To: Tom Psyborg
  Cc: QCA ath9k Development, Kalle Valo, David S. Miller,
	linux-wireless, netdev, linux-kernel
In-Reply-To: <CAKR_QV+wjuOZVfv9awX5bRLYC8xkoAy0h22LSPvL0DX6yg4-yw@mail.gmail.com>

On 18.03.19 23:35, Tom Psyborg wrote:
> On 18/03/2019, Tim Schumacher <timschumi@gmx.de> wrote:
>> Right now, if an error is encountered during the SREV register
>> read (i.e. an EIO in ath9k_regread()), that error code gets
>> passed all the way to __ath9k_hw_init(), where it is visible
>> during the "Chip rev not supported" message.
>>
>>     ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
>>     ath: phy2: Mac Chip Rev 0x0f.3 is not supported by this driver
>>     ath: phy2: Unable to initialize hardware; initialization status: -95
>>     ath: phy2: Unable to initialize hardware; initialization status: -95
>>     ath9k_htc: Failed to initialize the device
>>
>> Check for -EIO explicitly in ath9k_hw_read_revisions() and return
>> a boolean based on the success of the operation. Check for that in
>> __ath9k_hw_init() and abort with a more debugging-friendly message
>> if reading the revisions wasn't successful.
>>
> 
> you are still passing it all the way from ath9k_hw_init
> 

I meant the actual error code (i.e. -EIO) there, which gets checked
for right after the REG_READ() call in ath9k_hw_read_revisions(). If
it's present, it immediately prints the "SREV register" message and
returns false instead of true.

>>     ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
>>     ath: phy2: Failed to read SREV register
>>     ath: phy2: Could not read hardware revision
>>     ath: phy2: Unable to initialize hardware; initialization status: -95
>>     ath: phy2: Unable to initialize hardware; initialization status: -95
>>     ath9k_htc: Failed to initialize the device
>>
>> This helps when debugging by directly showing the first point of
>> failure and it could prevent possible errors if a 0x0f.3 revision
>> is ever supported.
>>
> 
> I don't think this is required. Mac Chip Rev 0x0f.3 at least prints
> what the problem is instead of generic SREV read failure.

The point of this patch is that the "Mac Chip Rev" (in this case)
is a false message and that it actually _doesn't_ show what the
problem is. There is no Rev that is 0x0f.3. It just falsely takes
the -EIO from ath9k_regread() as a valid return value (since it
is never caught earlier) and tries to extract a revision from it,
which results in 0x0f.3.

The case in where the revision succeeded to read, but it simply
isn't supported by the driver, is untouched and it still prints
the original message.

> Either wrong
> define in driver or address overlap caused by large/bad firmware in
> ath9k_htc case.
>

I don't know why it fails to read the SREV register in my specific
case (I tracked it down to a WMI command timeout, which seems to
only happen on a Raspberry Pi 3), but having the SREV error message
(which points to the actual issue) instead of the false-positive
"Rev not supported" message would have saved me quite some time that
I spent with debugging the issue, searching for the source of the
wrong value.

^ permalink raw reply

* Ath10k on XPS 9380 regularly disconnects
From: Kai-Heng Feng @ 2019-03-19  5:35 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Anthony Wong, linux-wireless, Linux Netdev List, linux-kernel

Hi Kalle,

There’s an issue that ath10k disconnects at regular basis [1], on Linux  
kernel 4.18.

Unfortunately I can’t reproduce the issue on XPS 9380 at my hand.

Is there already a fix in upstream kernel?

[1] https://bugs.launchpad.net/bugs/1818881

Kai-Heng

^ permalink raw reply

* [PATCH] net: Fix to check for kmemdup failure
From: Aditya Pakki @ 2019-03-19  3:19 UTC (permalink / raw)
  To: pakki001
  Cc: kjlu, Samuel Ortiz, David S. Miller, linux-wireless, netdev,
	linux-kernel

In case of kmemdup failure while setting the service name the patch
returns -ENOMEM upstream for processing.

Signed-off-by: Aditya Pakki <pakki001@umn.edu>
---
 net/nfc/llcp_sock.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index ae296273ce3d..17dcd0b5eb32 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -726,6 +726,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 	llcp_sock->service_name = kmemdup(addr->service_name,
 					  llcp_sock->service_name_len,
 					  GFP_KERNEL);
+	if (!llcp_sock->service_name) {
+		ret = -ENOMEM;
+		goto sock_llcp_release;
+	}
 
 	nfc_llcp_sock_link(&local->connecting_sockets, sk);
 
@@ -745,10 +749,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 	return ret;
 
 sock_unlink:
-	nfc_llcp_put_ssap(local, llcp_sock->ssap);
-
 	nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
 
+sock_llcp_release:
+	nfc_llcp_put_ssap(local, llcp_sock->ssap);
+
 put_dev:
 	nfc_put_device(dev);
 
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH v2 3/3] rt2x00: do not print error when queue is full
From: Tom Psyborg @ 2019-03-19  2:37 UTC (permalink / raw)
  To: Daniel Golle
  Cc: Kalle Valo, Stanislaw Gruszka, linux-wireless, Randy Oostdyk,
	Felix Fietkau, Mathias Kresin
In-Reply-To: <20190209172825.GB19297@makrotopia.org>

On 09/02/2019, Daniel Golle <daniel@makrotopia.org> wrote:

>>20MiB/s download rate is very impressive for 2.4GHz WiFi, I never saw
> anything even near that (using BitTorrent I get up to 8MiB/s when next
> to the router in low-noise environment with proprietry ubiquiti gear).

various apps and data transfer stacks may add significant overhead.
for real throughput testing i rely on iperf2 (tried iperf3 it was
mess). if interested take a look at bandwidth achieved on OCed QCA9531
device: https://forum.openwrt.org/t/different-wifi-speed-tx-rx-archer-c7-v2/18860/10?u=psyborg

^ permalink raw reply

* Re: [PATCH v3 4/4] rt2x00: do not print error when queue is full
From: Tom Psyborg @ 2019-03-19  2:12 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: linux-wireless, Daniel Golle, Felix Fietkau, Mathias Kresin
In-Reply-To: <1552384303-29529-5-git-send-email-sgruszka@redhat.com>

On 12/03/2019, Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> This make MT7620 OpenWRT routers more stable, what was reported
> by various users.

Confirmed.

^ permalink raw reply

* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Toke Høiland-Jørgensen @ 2019-03-18 23:05 UTC (permalink / raw)
  To: Felix Fietkau, linux-wireless
In-Reply-To: <d3bc4ad2-d4b7-d95d-dd49-105297653713@nbd.name>

Felix Fietkau <nbd@nbd.name> writes:

> On 2019-03-18 23:14, Toke Høiland-Jørgensen wrote:
>> Felix Fietkau <nbd@nbd.name> writes:
>> 
>>> On 2019-03-17 22:59, Toke Høiland-Jørgensen wrote:
>>>> Felix Fietkau <nbd@nbd.name> writes:
>>>>> I've looked at ath9k (the only user at the moment), and it seems to call
>>>>> the function in that way already: at PS wake or tx status time if it has
>>>>> frames in its internal retry queue.
>>>>> While it does not match the current documented behavior for that
>>>>> function, it nicely fits ath9k's currently unfulfilled expectations ;)
>>>> 
>>>> Heh, fair point :)
>>> I noticed another issue: after the migration to the mac80211 txq
>>> scheduling code, ath9k does not handle stations going to powersave
>>> properly anymore. mac80211 keeps returning txqs for stations that have
>>> gone to sleep and ath9k will send out frames for them.
>> 
>> Ah, right. Never did have a good grip on the powersave code...
>> 
>>> We could deal with this in the driver and simply not return queues for
>>> stations in PS mode, or mac80211 could actively cancel them once a
>>> station enters PS mode. What do you prefer?
>> 
>> I think the cleanest would be if mac80211 handled it and just
>> un-scheduled stations when they go to sleep.
> I agree. I'll send a patch tomorrow.

Cool, thanks! :)

>> BTW, I was just thinking the other day about why the retry queue is kept
>> around when a station goes to sleep? Isn't the station usually sleeping
>> pretty long (>100 ms), where it might make more sense to drop things
>> rather than try again once i comes back?
> It doesn't always sleep long. It might just be background scanning.
> There's no way for the AP to know in advance.
> In any case, the A-MPDU receiver reorder window still needs to be
> maintained, so dropping frames means we'd have to send a BAR frame to
> notify the receiver, which costs airtime as well.

Right, makes sense; thanks for the explanation.

-Toke

^ permalink raw reply

* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Felix Fietkau @ 2019-03-18 22:37 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, linux-wireless
In-Reply-To: <87sgvjsud7.fsf@toke.dk>

On 2019-03-18 23:14, Toke Høiland-Jørgensen wrote:
> Felix Fietkau <nbd@nbd.name> writes:
> 
>> On 2019-03-17 22:59, Toke Høiland-Jørgensen wrote:
>>> Felix Fietkau <nbd@nbd.name> writes:
>>>> I've looked at ath9k (the only user at the moment), and it seems to call
>>>> the function in that way already: at PS wake or tx status time if it has
>>>> frames in its internal retry queue.
>>>> While it does not match the current documented behavior for that
>>>> function, it nicely fits ath9k's currently unfulfilled expectations ;)
>>> 
>>> Heh, fair point :)
>> I noticed another issue: after the migration to the mac80211 txq
>> scheduling code, ath9k does not handle stations going to powersave
>> properly anymore. mac80211 keeps returning txqs for stations that have
>> gone to sleep and ath9k will send out frames for them.
> 
> Ah, right. Never did have a good grip on the powersave code...
> 
>> We could deal with this in the driver and simply not return queues for
>> stations in PS mode, or mac80211 could actively cancel them once a
>> station enters PS mode. What do you prefer?
> 
> I think the cleanest would be if mac80211 handled it and just
> un-scheduled stations when they go to sleep.
I agree. I'll send a patch tomorrow.
> BTW, I was just thinking the other day about why the retry queue is kept
> around when a station goes to sleep? Isn't the station usually sleeping
> pretty long (>100 ms), where it might make more sense to drop things
> rather than try again once i comes back?
It doesn't always sleep long. It might just be background scanning.
There's no way for the AP to know in advance.
In any case, the A-MPDU receiver reorder window still needs to be
maintained, so dropping frames means we'd have to send a BAR frame to
notify the receiver, which costs airtime as well.

- Felix

^ permalink raw reply

* Re: [PATCH] ath9k: Check for errors when reading SREV register
From: Tom Psyborg @ 2019-03-18 22:35 UTC (permalink / raw)
  To: Tim Schumacher
  Cc: QCA ath9k Development, Kalle Valo, David S. Miller,
	linux-wireless, netdev, linux-kernel
In-Reply-To: <20190318190557.21599-1-timschumi@gmx.de>

On 18/03/2019, Tim Schumacher <timschumi@gmx.de> wrote:
> Right now, if an error is encountered during the SREV register
> read (i.e. an EIO in ath9k_regread()), that error code gets
> passed all the way to __ath9k_hw_init(), where it is visible
> during the "Chip rev not supported" message.
>
>     ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
>     ath: phy2: Mac Chip Rev 0x0f.3 is not supported by this driver
>     ath: phy2: Unable to initialize hardware; initialization status: -95
>     ath: phy2: Unable to initialize hardware; initialization status: -95
>     ath9k_htc: Failed to initialize the device
>
> Check for -EIO explicitly in ath9k_hw_read_revisions() and return
> a boolean based on the success of the operation. Check for that in
> __ath9k_hw_init() and abort with a more debugging-friendly message
> if reading the revisions wasn't successful.
>

you are still passing it all the way from ath9k_hw_init

>     ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
>     ath: phy2: Failed to read SREV register
>     ath: phy2: Could not read hardware revision
>     ath: phy2: Unable to initialize hardware; initialization status: -95
>     ath: phy2: Unable to initialize hardware; initialization status: -95
>     ath9k_htc: Failed to initialize the device
>
> This helps when debugging by directly showing the first point of
> failure and it could prevent possible errors if a 0x0f.3 revision
> is ever supported.
>

I don't think this is required. Mac Chip Rev 0x0f.3 at least prints
what the problem is instead of generic SREV read failure. Either wrong
define in driver or address overlap caused by large/bad firmware in
ath9k_htc case.

^ permalink raw reply

* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Toke Høiland-Jørgensen @ 2019-03-18 22:14 UTC (permalink / raw)
  To: Felix Fietkau, linux-wireless
In-Reply-To: <111434f9-f04c-2fe2-c2b4-de757efc884c@nbd.name>

Felix Fietkau <nbd@nbd.name> writes:

> On 2019-03-17 22:59, Toke Høiland-Jørgensen wrote:
>> Felix Fietkau <nbd@nbd.name> writes:
>>> I've looked at ath9k (the only user at the moment), and it seems to call
>>> the function in that way already: at PS wake or tx status time if it has
>>> frames in its internal retry queue.
>>> While it does not match the current documented behavior for that
>>> function, it nicely fits ath9k's currently unfulfilled expectations ;)
>> 
>> Heh, fair point :)
> I noticed another issue: after the migration to the mac80211 txq
> scheduling code, ath9k does not handle stations going to powersave
> properly anymore. mac80211 keeps returning txqs for stations that have
> gone to sleep and ath9k will send out frames for them.

Ah, right. Never did have a good grip on the powersave code...

> We could deal with this in the driver and simply not return queues for
> stations in PS mode, or mac80211 could actively cancel them once a
> station enters PS mode. What do you prefer?

I think the cleanest would be if mac80211 handled it and just
un-scheduled stations when they go to sleep.

BTW, I was just thinking the other day about why the retry queue is kept
around when a station goes to sleep? Isn't the station usually sleeping
pretty long (>100 ms), where it might make more sense to drop things
rather than try again once i comes back?

-Toke

^ permalink raw reply

* Re: [PATCH 1/6] mt76: use mac80211 txq scheduling
From: Felix Fietkau @ 2019-03-18 20:08 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, linux-wireless
In-Reply-To: <87r2b5tb6a.fsf@toke.dk>

On 2019-03-17 22:59, Toke Høiland-Jørgensen wrote:
> Felix Fietkau <nbd@nbd.name> writes:
>> I've looked at ath9k (the only user at the moment), and it seems to call
>> the function in that way already: at PS wake or tx status time if it has
>> frames in its internal retry queue.
>> While it does not match the current documented behavior for that
>> function, it nicely fits ath9k's currently unfulfilled expectations ;)
> 
> Heh, fair point :)
I noticed another issue: after the migration to the mac80211 txq
scheduling code, ath9k does not handle stations going to powersave
properly anymore. mac80211 keeps returning txqs for stations that have
gone to sleep and ath9k will send out frames for them.

We could deal with this in the driver and simply not return queues for
stations in PS mode, or mac80211 could actively cancel them once a
station enters PS mode. What do you prefer?

- Felix

^ permalink raw reply

* [PATCH] ath9k: Check for errors when reading SREV register
From: Tim Schumacher @ 2019-03-18 19:05 UTC (permalink / raw)
  Cc: timschumi, QCA ath9k Development, Kalle Valo, David S. Miller,
	linux-wireless, netdev, linux-kernel

Right now, if an error is encountered during the SREV register
read (i.e. an EIO in ath9k_regread()), that error code gets
passed all the way to __ath9k_hw_init(), where it is visible
during the "Chip rev not supported" message.

    ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
    ath: phy2: Mac Chip Rev 0x0f.3 is not supported by this driver
    ath: phy2: Unable to initialize hardware; initialization status: -95
    ath: phy2: Unable to initialize hardware; initialization status: -95
    ath9k_htc: Failed to initialize the device

Check for -EIO explicitly in ath9k_hw_read_revisions() and return
a boolean based on the success of the operation. Check for that in
__ath9k_hw_init() and abort with a more debugging-friendly message
if reading the revisions wasn't successful.

    ath9k_htc 1-1.4:1.0: ath9k_htc: HTC initialized with 33 credits
    ath: phy2: Failed to read SREV register
    ath: phy2: Could not read hardware revision
    ath: phy2: Unable to initialize hardware; initialization status: -95
    ath: phy2: Unable to initialize hardware; initialization status: -95
    ath9k_htc: Failed to initialize the device

This helps when debugging by directly showing the first point of
failure and it could prevent possible errors if a 0x0f.3 revision
is ever supported.

Signed-off-by: Tim Schumacher <timschumi@gmx.de>
---
 drivers/net/wireless/ath/ath9k/hw.c | 32 +++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 8581d917635a..b6773d613f0c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -252,8 +252,9 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah,
 /* Chip Revisions */
 /******************/
 
-static void ath9k_hw_read_revisions(struct ath_hw *ah)
+static bool ath9k_hw_read_revisions(struct ath_hw *ah)
 {
+	u32 srev;
 	u32 val;
 
 	if (ah->get_mac_revision)
@@ -269,25 +270,33 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
 			val = REG_READ(ah, AR_SREV);
 			ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
 		}
-		return;
+		return true;
 	case AR9300_DEVID_AR9340:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9340;
-		return;
+		return true;
 	case AR9300_DEVID_QCA955X:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9550;
-		return;
+		return true;
 	case AR9300_DEVID_AR953X:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9531;
-		return;
+		return true;
 	case AR9300_DEVID_QCA956X:
 		ah->hw_version.macVersion = AR_SREV_VERSION_9561;
-		return;
+		return true;
 	}
 
-	val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+	srev = REG_READ(ah, AR_SREV);
+
+	if (srev == -EIO) {
+		ath_err(ath9k_hw_common(ah),
+			"Failed to read SREV register");
+		return false;
+	}
+
+	val = srev & AR_SREV_ID;
 
 	if (val == 0xFF) {
-		val = REG_READ(ah, AR_SREV);
+		val = srev;
 		ah->hw_version.macVersion =
 			(val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
 		ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
@@ -306,6 +315,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
 		if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)
 			ah->is_pciexpress = true;
 	}
+
+	return true;
 }
 
 /************************************/
@@ -559,7 +570,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	struct ath_common *common = ath9k_hw_common(ah);
 	int r = 0;
 
-	ath9k_hw_read_revisions(ah);
+	if (!ath9k_hw_read_revisions(ah)) {
+		ath_err(common, "Could not read hardware revisions");
+		return -EOPNOTSUPP;
+	}
 
 	switch (ah->hw_version.macVersion) {
 	case AR_SREV_VERSION_5416_PCI:
-- 
2.21.0


^ permalink raw reply related

* Re: [PATCH v3] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Toke Høiland-Jørgensen @ 2019-03-18 11:17 UTC (permalink / raw)
  To: Felix Fietkau, linux-wireless; +Cc: johannes
In-Reply-To: <20190318110058.73586-1-nbd@nbd.name>

Felix Fietkau <nbd@nbd.name> writes:

> Currently there is no way for the driver to signal to mac80211 that it should
> schedule a TXQ even if there are no packets on the mac80211 part of that queue.
> This is problematic if the driver has an internal retry queue to deal with
> software A-MPDU retry.
>
> This patch changes the behavior of ieee80211_schedule_txq to always schedule
> the queue, as its only user (ath9k) seems to expect such behavior already:
> it calls this function on tx status and on powersave wakeup whenever its
> internal retry queue is not empty.
>
> Also add an extra argument to ieee80211_return_txq to get the same behavior.
>
> This fixes an issue on ath9k where tx queues with packets to retry (and no
> new packets in mac80211) would not get serviced.
>
> Fixes: 89cea7493a346 ("ath9k: Switch to mac80211 TXQ scheduling and airtime APIs")
> Signed-off-by: Felix Fietkau <nbd@nbd.name>

Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>

^ permalink raw reply

* [RFC] mt76: usb: reduce locking in mt76u_tx_tasklet
From: Lorenzo Bianconi @ 2019-03-18 11:09 UTC (permalink / raw)
  To: nbd; +Cc: linux-wireless, lorenzo.bianconi, sgruszka
In-Reply-To: <cover.1552907276.git.lorenzo@kernel.org>

Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since
q->head is managed just in mt76u_tx_tasklet and q->queued is updated
holding q->lock

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/usb.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index ac03acdae279..8cd70c32d77a 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -634,29 +634,33 @@ static void mt76u_tx_tasklet(unsigned long data)
 	int i;
 
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		u32 n_queued = 0, n_sw_queued = 0;
+
 		sq = &dev->q_tx[i];
 		q = sq->q;
 
-		spin_lock_bh(&q->lock);
-		while (true) {
+		while (q->queued > n_queued) {
 			buf = &q->entry[q->head].ubuf;
-			if (!buf->done || !q->queued)
+			if (!buf->done)
 				break;
 
 			if (q->entry[q->head].schedule) {
 				q->entry[q->head].schedule = false;
-				sq->swq_queued--;
+				n_sw_queued++;
 			}
 
 			entry = q->entry[q->head];
 			q->head = (q->head + 1) % q->ndesc;
-			q->queued--;
+			n_queued++;
 
-			spin_unlock_bh(&q->lock);
 			dev->drv->tx_complete_skb(dev, i, &entry);
-			spin_lock_bh(&q->lock);
 		}
 
+		spin_lock_bh(&q->lock);
+
+		sq->swq_queued -= n_sw_queued;
+		q->queued -= n_queued;
+
 		wake = q->stopped && q->queued < q->ndesc - 8;
 		if (wake)
 			q->stopped = false;
-- 
2.20.1


^ permalink raw reply related

* [PATCH v3] mac80211: make ieee80211_schedule_txq schedule empty TXQs
From: Felix Fietkau @ 2019-03-18 11:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Toke Høiland-Jørgensen

Currently there is no way for the driver to signal to mac80211 that it should
schedule a TXQ even if there are no packets on the mac80211 part of that queue.
This is problematic if the driver has an internal retry queue to deal with
software A-MPDU retry.

This patch changes the behavior of ieee80211_schedule_txq to always schedule
the queue, as its only user (ath9k) seems to expect such behavior already:
it calls this function on tx status and on powersave wakeup whenever its
internal retry queue is not empty.

Also add an extra argument to ieee80211_return_txq to get the same behavior.

This fixes an issue on ath9k where tx queues with packets to retry (and no
new packets in mac80211) would not get serviced.

Fixes: 89cea7493a346 ("ath9k: Switch to mac80211 TXQ scheduling and airtime APIs")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 drivers/net/wireless/ath/ath10k/htt_rx.c |  2 +-
 drivers/net/wireless/ath/ath10k/mac.c    |  4 ++--
 drivers/net/wireless/ath/ath9k/xmit.c    |  5 ++++-
 include/net/mac80211.h                   | 24 ++++++++++++++++++++----
 net/mac80211/tx.c                        | 10 ++++++----
 5 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 4fc885617de1..895a94b2a63e 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2720,7 +2720,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb)
 			num_msdus++;
 			num_bytes += ret;
 		}
-		ieee80211_return_txq(hw, txq);
+		ieee80211_return_txq(hw, txq, false);
 		ieee80211_txq_schedule_end(hw, txq->ac);
 
 		record->num_msdus = cpu_to_le16(num_msdus);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b73c23d4ce86..41e89db244d2 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4089,7 +4089,7 @@ static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac)
 			if (ret < 0)
 				break;
 		}
-		ieee80211_return_txq(hw, txq);
+		ieee80211_return_txq(hw, txq, false);
 		ath10k_htt_tx_txq_update(hw, txq);
 		if (ret == -EBUSY)
 			break;
@@ -4374,7 +4374,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
 		if (ret < 0)
 			break;
 	}
-	ieee80211_return_txq(hw, txq);
+	ieee80211_return_txq(hw, txq, false);
 	ath10k_htt_tx_txq_update(hw, txq);
 out:
 	ieee80211_txq_schedule_end(hw, ac);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 06e0c5a6fab6..245a63932840 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1938,12 +1938,15 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 		goto out;
 
 	while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) {
+		bool force;
+
 		tid = (struct ath_atx_tid *)queue->drv_priv;
 
 		ret = ath_tx_sched_aggr(sc, txq, tid);
 		ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret);
 
-		ieee80211_return_txq(hw, queue);
+		force = !skb_queue_empty(&tid->retry_q);
+		ieee80211_return_txq(hw, queue, force);
 	}
 
 out:
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0de0aba580eb..5b5d28eead38 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6291,26 +6291,42 @@ static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
 {
 }
 
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+			      struct ieee80211_txq *txq, bool force);
+
 /**
  * ieee80211_schedule_txq - schedule a TXQ for transmission
  *
  * @hw: pointer as obtained from ieee80211_alloc_hw()
  * @txq: pointer obtained from station or virtual interface
  *
- * Schedules a TXQ for transmission if it is not already scheduled.
+ * Schedules a TXQ for transmission if it is not already scheduled,
+ * even if mac80211 does not have any packets buffered.
+ *
+ * The driver may call this function if it has buffered packets for
+ * this TXQ internally.
  */
-void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
+static inline void
+ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
+{
+	__ieee80211_schedule_txq(hw, txq, true);
+}
 
 /**
  * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
  *
  * @hw: pointer as obtained from ieee80211_alloc_hw()
  * @txq: pointer obtained from station or virtual interface
+ * @force: schedule txq even if mac80211 does not have any buffered packets.
+ *
+ * The driver may set force=true if it has buffered packets for this TXQ
+ * internally.
  */
 static inline void
-ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
+ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq,
+		     bool force)
 {
-	ieee80211_schedule_txq(hw, txq);
+	__ieee80211_schedule_txq(hw, txq, force);
 }
 
 /**
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 9fe8682d79ec..e22de40a7790 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3692,8 +3692,9 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
 }
 EXPORT_SYMBOL(ieee80211_next_txq);
 
-void ieee80211_schedule_txq(struct ieee80211_hw *hw,
-			    struct ieee80211_txq *txq)
+void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
+			      struct ieee80211_txq *txq,
+			      bool force)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct txq_info *txqi = to_txq_info(txq);
@@ -3701,7 +3702,8 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
 	spin_lock_bh(&local->active_txq_lock[txq->ac]);
 
 	if (list_empty(&txqi->schedule_order) &&
-	    (!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
+	    (force || !skb_queue_empty(&txqi->frags) ||
+	     txqi->tin.backlog_packets)) {
 		/* If airtime accounting is active, always enqueue STAs at the
 		 * head of the list to ensure that they only get moved to the
 		 * back by the airtime DRR scheduler once they have a negative
@@ -3721,7 +3723,7 @@ void ieee80211_schedule_txq(struct ieee80211_hw *hw,
 
 	spin_unlock_bh(&local->active_txq_lock[txq->ac]);
 }
-EXPORT_SYMBOL(ieee80211_schedule_txq);
+EXPORT_SYMBOL(__ieee80211_schedule_txq);
 
 bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
 				struct ieee80211_txq *txq)
-- 
2.17.0


^ permalink raw reply related

* Re: [PATCH 05/11] mac80211_hwsim: set p2p device interface support indication
From: Arend Van Spriel @ 2019-03-18 10:56 UTC (permalink / raw)
  To: Luca Coelho, johannes; +Cc: linux-wireless, Avraham Stern, Luca Coelho
In-Reply-To: <20190315153907.16192-6-luca@coelho.fi>

On 3/15/2019 4:39 PM, Luca Coelho wrote:
> From: Avraham Stern <avraham.stern@intel.com>
> 
> P2P device interface type was not indicated in the supported
> interface types even when hwsim was configured with p2p device
> support. Fix it.

Just wondering. Doesn't this affect the hwsim-based tests in wpa_supp? 
Or is that the intent behind this patch.

Regards,
Arend

> Signed-off-by: Avraham Stern <avraham.stern@intel.com>
> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
> ---
>   drivers/net/wireless/mac80211_hwsim.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
> index 0838af04d681..d79f3ee2a741 100644
> --- a/drivers/net/wireless/mac80211_hwsim.c
> +++ b/drivers/net/wireless/mac80211_hwsim.c
> @@ -3894,6 +3894,8 @@ static int __init init_mac80211_hwsim(void)
>   		param.p2p_device = support_p2p_device;
>   		param.use_chanctx = channels > 1;
>   		param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
> +		if (param.p2p_device)
> +			param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
>   
>   		err = mac80211_hwsim_new_radio(NULL, &param);
>   		if (err < 0)
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox