All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support
@ 2022-08-16  0:03 sean.wang
  2022-08-16  0:03 ` [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration sean.wang
                   ` (8 more replies)
  0 siblings, 9 replies; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek, Sean Wang

From: Sean Wang <objelf@gmail.com>

The patchset introduces chanctx support to enable the capability
on the newer firmware to manage the channel context scheduling on multiple 
roles running on the device including Station, AP, and P2P GC/GO mode
(will be extended based on the patchset in the future) to help users share
the network with others on a single device.
 
The things to be noted is that
1) The newer firmware is able to support the channel chanctx up to 2
interfaces simultaneously running on the different channels.

2) Before the driver is going sent out the management frames, the driver
has to get the privilege from the firmware to acquire the current channel
context for the frame until the frame handshake is completed and then get
the privilege back to the firmware.

3) The patchset has to rely on
("mt76: mt7921: fix the firmware version report")
("mt76: mt7921: add mt7921_mutex_acquire at mt7921_[start, stop]_ap")

Quan Zhou (1):
  wifi: mt76: mt7921: add unified ROC cmd/event support

Sean Wang (8):
  wifi: mac80211: allow enabling chanctx until hw registration
  wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx
  wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx
  wifi: mt76: mt7921: add chanctx parameter to
    mt76_connac_mcu_uni_add_bss signature
  wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver
  wifi: mt76: connac: accept hw scan request at a time
  wifi: mt76: mt7921: introduce remain_on_channel support
  wifi: mt76: mt7921: introduce chanctx support

 .../net/wireless/mediatek/mt76/mt7615/mcu.c   |   2 +-
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 152 ++++++------
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  16 +-
 .../net/wireless/mediatek/mt76/mt7921/init.c  |  74 +++++-
 .../net/wireless/mediatek/mt76/mt7921/mac.c   |   2 +-
 .../net/wireless/mediatek/mt76/mt7921/main.c  | 225 +++++++++++++++++-
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 151 +++++++++++-
 .../wireless/mediatek/mt76/mt7921/mt7921.h    |  54 +++++
 .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
 .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
 .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
 net/mac80211/main.c                           |   8 +
 12 files changed, 620 insertions(+), 89 deletions(-)

-- 
2.25.1


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

* [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-16  8:03   ` Johannes Berg
  2022-08-16  0:03 ` [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx sean.wang
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

MT7921 device can be supported with the channel context depending on
the newer firmware so that we need a way to enable the chanctx related
methods until hw is being registered.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 net/mac80211/main.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5b1c47ed0cc0..98d05ed1a081 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1011,6 +1011,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		return -EINVAL;
 #endif
 
+	/* check all or no channel context operations exist */
+	i = !!local->ops->add_chanctx + !!local->ops->remove_chanctx +
+	    !!local->ops->change_chanctx + !!local->ops->assign_vif_chanctx +
+	    !!local->ops->unassign_vif_chanctx;
+	if (WARN_ON(i != 0 && i != 5))
+		return -EINVAL;
+	local->use_chanctx = i == 5;
+
 	if (!local->use_chanctx) {
 		for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
 			const struct ieee80211_iface_combination *comb;
-- 
2.25.1


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

* [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
  2022-08-16  0:03 ` [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:13   ` Lorenzo Bianconi
  2022-08-16  0:03 ` [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx sean.wang
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

add mt76_connac_mcu_uni_set_chctx to set up the channel context per BSS
in the firmware

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 83 +++++++++++++++++++
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  3 +
 2 files changed, 86 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 0afcadce87fc..3d5c70765d4f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1311,6 +1311,89 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif,
 	he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
 }
 
+int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,
+				  struct ieee80211_chanctx_conf *ctx)
+{
+	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;
+	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
+	enum nl80211_band band = chandef->chan->band;
+	struct mt76_dev *mdev = phy->dev;
+
+	struct {
+		struct {
+			u8 bss_idx;
+			u8 pad[3];
+		} __packed hdr;
+		struct rlm_tlv {
+			__le16 tag;
+			__le16 len;
+			u8 control_channel;
+			u8 center_chan;
+			u8 center_chan2;
+			u8 bw;
+			u8 tx_streams;
+			u8 rx_streams;
+			u8 short_st;
+			u8 ht_op_info;
+			u8 sco;
+			u8 band;
+			u8 pad[2];
+		} __packed rlm;
+	} __packed rlm_req = {
+		.hdr = {
+			.bss_idx = mvif->idx,
+		},
+		.rlm = {
+			.tag = cpu_to_le16(UNI_BSS_INFO_RLM),
+			.len = cpu_to_le16(sizeof(struct rlm_tlv)),
+			.control_channel = chandef->chan->hw_value,
+			.center_chan = ieee80211_frequency_to_channel(freq1),
+			.center_chan2 = ieee80211_frequency_to_channel(freq2),
+			.tx_streams = hweight8(phy->antenna_mask),
+			.ht_op_info = 4, /* set HT 40M allowed */
+			.rx_streams = phy->chainmask,
+			.short_st = true,
+			.band = band,
+		},
+	};
+
+	switch (chandef->width) {
+	case NL80211_CHAN_WIDTH_40:
+		rlm_req.rlm.bw = CMD_CBW_40MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		rlm_req.rlm.bw = CMD_CBW_80MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+		rlm_req.rlm.bw = CMD_CBW_8080MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_160:
+		rlm_req.rlm.bw = CMD_CBW_160MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_5:
+		rlm_req.rlm.bw = CMD_CBW_5MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_10:
+		rlm_req.rlm.bw = CMD_CBW_10MHZ;
+		break;
+	case NL80211_CHAN_WIDTH_20_NOHT:
+	case NL80211_CHAN_WIDTH_20:
+	default:
+		rlm_req.rlm.bw = CMD_CBW_20MHZ;
+		rlm_req.rlm.ht_op_info = 0;
+		break;
+	}
+
+	if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan)
+		rlm_req.rlm.sco = 1; /* SCA */
+	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)
+		rlm_req.rlm.sco = 3; /* SCB */
+
+	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req,
+				 sizeof(rlm_req), true);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_set_chctx);
+
 int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 				struct ieee80211_vif *vif,
 				struct mt76_wcid *wcid,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index f1d7c05bd794..bf60b00d6020 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1727,6 +1727,9 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
 int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
 			   struct ieee80211_ampdu_params *params,
 			   int cmd, bool enable, bool tx);
+int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy,
+				  struct mt76_vif *vif,
+				  struct ieee80211_chanctx_conf *ctx);
 int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 				struct ieee80211_vif *vif,
 				struct mt76_wcid *wcid,
-- 
2.25.1


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

* [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
  2022-08-16  0:03 ` [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration sean.wang
  2022-08-16  0:03 ` [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:13   ` Lorenzo Bianconi
  2022-08-16  0:03 ` [PATCH 4/9] wifi: mt76: mt7921: add chanctx parameter to mt76_connac_mcu_uni_add_bss signature sean.wang
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

Reuse mt76_connac_mcu_uni_set_chctx to avoid the dupicated code.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 73 +------------------
 1 file changed, 1 insertion(+), 72 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 3d5c70765d4f..3e473a409790 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1401,7 +1401,6 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 {
 	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
 	struct cfg80211_chan_def *chandef = &phy->chandef;
-	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
 	enum nl80211_band band = chandef->chan->band;
 	struct mt76_dev *mdev = phy->dev;
 	struct {
@@ -1432,43 +1431,6 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 			.qos = vif->bss_conf.qos,
 		},
 	};
-	struct {
-		struct {
-			u8 bss_idx;
-			u8 pad[3];
-		} __packed hdr;
-		struct rlm_tlv {
-			__le16 tag;
-			__le16 len;
-			u8 control_channel;
-			u8 center_chan;
-			u8 center_chan2;
-			u8 bw;
-			u8 tx_streams;
-			u8 rx_streams;
-			u8 short_st;
-			u8 ht_op_info;
-			u8 sco;
-			u8 band;
-			u8 pad[2];
-		} __packed rlm;
-	} __packed rlm_req = {
-		.hdr = {
-			.bss_idx = mvif->idx,
-		},
-		.rlm = {
-			.tag = cpu_to_le16(UNI_BSS_INFO_RLM),
-			.len = cpu_to_le16(sizeof(struct rlm_tlv)),
-			.control_channel = chandef->chan->hw_value,
-			.center_chan = ieee80211_frequency_to_channel(freq1),
-			.center_chan2 = ieee80211_frequency_to_channel(freq2),
-			.tx_streams = hweight8(phy->antenna_mask),
-			.ht_op_info = 4, /* set HT 40M allowed */
-			.rx_streams = phy->chainmask,
-			.short_st = true,
-			.band = band,
-		},
-	};
 	int err, conn_type;
 	u8 idx, basic_phy;
 
@@ -1555,40 +1517,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 			return err;
 	}
 
-	switch (chandef->width) {
-	case NL80211_CHAN_WIDTH_40:
-		rlm_req.rlm.bw = CMD_CBW_40MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_80:
-		rlm_req.rlm.bw = CMD_CBW_80MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_80P80:
-		rlm_req.rlm.bw = CMD_CBW_8080MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_160:
-		rlm_req.rlm.bw = CMD_CBW_160MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_5:
-		rlm_req.rlm.bw = CMD_CBW_5MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_10:
-		rlm_req.rlm.bw = CMD_CBW_10MHZ;
-		break;
-	case NL80211_CHAN_WIDTH_20_NOHT:
-	case NL80211_CHAN_WIDTH_20:
-	default:
-		rlm_req.rlm.bw = CMD_CBW_20MHZ;
-		rlm_req.rlm.ht_op_info = 0;
-		break;
-	}
-
-	if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan)
-		rlm_req.rlm.sco = 1; /* SCA */
-	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)
-		rlm_req.rlm.sco = 3; /* SCB */
-
-	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req,
-				 sizeof(rlm_req), true);
+	return mt76_connac_mcu_uni_set_chctx(phy, mvif, NULL);
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
 
-- 
2.25.1


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

* [PATCH 4/9] wifi: mt76: mt7921: add chanctx parameter to mt76_connac_mcu_uni_add_bss signature
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (2 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-16  0:03 ` [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support sean.wang
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

Add a chanctx parameter to mt76_connac_mcu_uni_add_bss signature to allow
the firmware binds the BSS into the specific channel context.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7615/mcu.c      |  2 +-
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c |  7 ++++---
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt7921/mac.c      |  2 +-
 drivers/net/wireless/mediatek/mt76/mt7921/main.c     | 10 ++++++----
 5 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 3dac76e6df4d..83f30305414d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -1119,7 +1119,7 @@ mt7615_mcu_uni_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,
 	struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
 
 	return mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
-					   enable);
+					   enable, NULL);
 }
 
 static inline int
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 3e473a409790..c2ed5e755893 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1397,10 +1397,11 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_set_chctx);
 int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 				struct ieee80211_vif *vif,
 				struct mt76_wcid *wcid,
-				bool enable)
+				bool enable,
+				struct ieee80211_chanctx_conf *ctx)
 {
 	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
-	struct cfg80211_chan_def *chandef = &phy->chandef;
+	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;
 	enum nl80211_band band = chandef->chan->band;
 	struct mt76_dev *mdev = phy->dev;
 	struct {
@@ -1517,7 +1518,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 			return err;
 	}
 
-	return mt76_connac_mcu_uni_set_chctx(phy, mvif, NULL);
+	return mt76_connac_mcu_uni_set_chctx(phy, mvif, ctx);
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index bf60b00d6020..1fcc3e8c5380 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1733,7 +1733,8 @@ int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy,
 int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 				struct ieee80211_vif *vif,
 				struct mt76_wcid *wcid,
-				bool enable);
+				bool enable,
+				struct ieee80211_chanctx_conf *ctx);
 int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,
 			    struct mt76_sta_cmd_info *info);
 void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
index 7b2d1bc8aded..5be7972ba6f1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -745,7 +745,7 @@ mt7921_vif_connect_iter(void *priv, u8 *mac,
 
 	if (vif->type == NL80211_IFTYPE_AP) {
 		mt76_connac_mcu_uni_add_bss(dev->phy.mt76, vif, &mvif->sta.wcid,
-					    true);
+					    true, NULL);
 		mt7921_mcu_sta_update(dev, NULL, vif, true,
 				      MT76_STA_INFO_STATE_NONE);
 		mt7921_mcu_uni_add_beacon_offload(dev, hw, vif, true);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 7a4a3ed1817e..b280f184244f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -748,7 +748,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 
 	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
 		mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
-					    true);
+					    true, NULL);
 
 	mt7921_mac_wtbl_update(dev, msta->wcid.idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -779,7 +779,8 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 		ewma_rssi_init(&mvif->rssi);
 		if (!sta->tdls)
 			mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
-						    &mvif->sta.wcid, false);
+						    &mvif->sta.wcid, false,
+						    NULL);
 	}
 
 	spin_lock_bh(&dev->sta_poll_lock);
@@ -1529,7 +1530,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mt7921_mutex_acquire(dev);
 
 	err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
-					  true);
+					  true, NULL);
 	if (err)
 		goto failed;
 
@@ -1560,7 +1561,8 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	if (err)
 		goto failed;
 
-	mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false);
+	mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
+				    NULL);
 
 failed:
 	mt7921_mutex_release(dev);
-- 
2.25.1


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

* [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (3 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 4/9] wifi: mt76: mt7921: add chanctx parameter to mt76_connac_mcu_uni_add_bss signature sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:15   ` Lorenzo Bianconi
  2022-08-16  0:03 ` [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver sean.wang
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek, Quan Zhou, Deren Wu, Kaikai Hu

From: Quan Zhou <quan.zhou@mediatek.com>

Add unified ROC cmd/event which is only supported by the newer fw.

Co-developed-by: Sean Wang <sean.wang@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Co-developed-by: Kaikai Hu <kaikai.hu@mediatek.com>
Signed-off-by: Kaikai Hu <kaikai.hu@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
---
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  10 +-
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 119 ++++++++++++++++++
 .../wireless/mediatek/mt76/mt7921/mt7921.h    |  19 +++
 3 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 1fcc3e8c5380..f3c1e1dc574a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -114,11 +114,15 @@ struct mt76_connac2_mcu_rxd {
 
 	u8 eid;
 	u8 seq;
-	u8 rsv[2];
+	u8 option;
+	u8 __rsv;
+
 
 	u8 ext_eid;
 	u8 rsv1[2];
 	u8 s2d_index;
+
+	u8 tlv[0];
 };
 
 struct mt76_connac2_patch_hdr {
@@ -938,6 +942,9 @@ enum {
 	DEV_INFO_MAX_NUM
 };
 
+#define MCU_UNI_CMD_EVENT                       BIT(1)
+#define MCU_UNI_CMD_UNSOLICITED_EVENT           BIT(2)
+
 /* event table */
 enum {
 	MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
@@ -1144,6 +1151,7 @@ enum {
 	MCU_UNI_CMD_OFFLOAD = 0x06,
 	MCU_UNI_CMD_HIF_CTRL = 0x07,
 	MCU_UNI_CMD_SNIFFER = 0x24,
+	MCU_UNI_CMD_ROC = 0x27,
 };
 
 enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index da12d0ae0835..76c8afc00c24 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -275,6 +275,23 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
 	dev_kfree_skb(skb);
 }
 
+static void
+mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
+				    struct sk_buff *skb)
+{
+	struct mt76_connac2_mcu_rxd *rxd;
+
+	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
+
+	switch (rxd->eid) {
+	case MCU_UNI_EVENT_ROC:
+		break;
+	default:
+		break;
+	}
+	dev_kfree_skb(skb);
+}
+
 void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
 	struct mt76_connac2_mcu_rxd *rxd;
@@ -284,6 +301,11 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
 
 	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
 
+	if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) {
+		mt7921_mcu_uni_rx_unsolicited_event(dev, skb);
+		return;
+	}
+
 	if (rxd->eid == 0x6) {
 		mt76_mcu_rx_event(&dev->mt76, skb);
 		return;
@@ -521,6 +543,103 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
 				 &req_mu, sizeof(req_mu), false);
 }
 
+int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+		       struct ieee80211_channel *chan, int duration,
+		       enum mt7921_roc_req type, u8 token_id)
+{
+	int center_ch = ieee80211_frequency_to_channel(chan->center_freq);
+	struct mt7921_dev *dev = phy->dev;
+	struct {
+		struct {
+			u8 rsv[4];
+		} __packed hdr;
+		struct roc_acquire_tlv {
+			__le16 tag;
+			__le16 len;
+			u8 bss_idx;
+			u8 tokenid;
+			u8 control_channel;
+			u8 sco;
+			u8 band;
+			u8 bw;
+			u8 center_chan;
+			u8 center_chan2;
+			u8 bw_from_ap;
+			u8 center_chan_from_ap;
+			u8 center_chan2_from_ap;
+			u8 reqtype;
+			__le32 maxinterval;
+			u8 dbdcband;
+			u8 rsv[3];
+		} __packed roc;
+	} __packed req = {
+		.roc = {
+			.tag = cpu_to_le16(UNI_ROC_ACQUIRE),
+			.len = cpu_to_le16(sizeof(struct roc_acquire_tlv)),
+			.tokenid = token_id,
+			.reqtype = type,
+			.maxinterval = cpu_to_le32(duration),
+			.bss_idx = vif->mt76.idx,
+			.control_channel = chan->hw_value,
+			.bw = CMD_CBW_20MHZ,
+			.bw_from_ap = CMD_CBW_20MHZ,
+			.center_chan = center_ch,
+			.center_chan_from_ap = center_ch,
+			.dbdcband = 0xff, /* auto */
+		},
+	};
+
+	if (chan->hw_value < center_ch)
+		req.roc.sco = 1; /* SCA */
+	else if (chan->hw_value > center_ch)
+		req.roc.sco = 3; /* SCB */
+
+	switch (chan->band) {
+	case NL80211_BAND_6GHZ:
+		req.roc.band = 3;
+		break;
+	case NL80211_BAND_5GHZ:
+		req.roc.band = 2;
+		break;
+	default:
+		req.roc.band = 1;
+		break;
+	}
+
+	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
+				 &req, sizeof(req), false);
+}
+
+int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+			 u8 token_id)
+{
+	struct mt7921_dev *dev = phy->dev;
+	struct {
+		struct {
+			u8 rsv[4];
+		} __packed hdr;
+		struct roc_abort_tlv {
+			__le16 tag;
+			__le16 len;
+			u8 bss_idx;
+			u8 tokenid;
+			u8 dbdcband;
+			u8 rsv[5];
+		} __packed abort;
+	} __packed req = {
+		.abort = {
+			.tag = cpu_to_le16(UNI_ROC_ABORT),
+			.len = cpu_to_le16(sizeof(struct roc_abort_tlv)),
+			.tokenid = token_id,
+			.bss_idx = vif->mt76.idx,
+			.dbdcband = 0xff, /* auto*/
+		},
+	};
+
+	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
+				 &req, sizeof(req), false);
+}
+
 int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
 {
 	struct mt7921_dev *dev = phy->dev;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index c161031ac62a..c9044d546e94 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -51,6 +51,20 @@
 #define MT7921_SDIO_HDR_TX_BYTES	GENMASK(15, 0)
 #define MT7921_SDIO_HDR_PKT_TYPE	GENMASK(17, 16)
 
+#define MCU_UNI_EVENT_ROC  0x27
+
+enum {
+	UNI_ROC_ACQUIRE,
+	UNI_ROC_ABORT,
+	UNI_ROC_NUM
+};
+
+enum mt7921_roc_req {
+	MT7921_ROC_REQ_JOIN,
+	MT7921_ROC_REQ_ROC,
+	MT7921_ROC_REQ_NUM
+};
+
 enum mt7921_sdio_pkt_type {
 	MT7921_SDIO_TXD,
 	MT7921_SDIO_DATA,
@@ -479,4 +493,9 @@ mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
 #endif
 int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
 			  const struct cfg80211_sar_specs *sar);
+int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+		       struct ieee80211_channel *chan, int duration,
+		       enum mt7921_roc_req type, u8 token_id);
+int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
+			 u8 token_id);
 #endif
-- 
2.25.1


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

* [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (4 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:16   ` Lorenzo Bianconi
  2022-08-16  0:03 ` [PATCH 7/9] wifi: mt76: connac: accept hw scan request at a time sean.wang
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

The firmware would be in charge of braking and continuing the traffic while
the channel contexts are switching between different BSS and HW SCAN in the
background.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 76c8afc00c24..05b625e02265 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -175,15 +175,13 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
 static void
 mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
-	struct mt76_phy *mphy = &dev->mt76.phy;
 	struct mt76_connac_mcu_bss_event *event;
 
 	skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
 	event = (struct mt76_connac_mcu_bss_event *)skb->data;
-	if (event->is_absent)
-		ieee80211_stop_queues(mphy->hw);
-	else
-		ieee80211_wake_queues(mphy->hw);
+
+	dev_dbg(dev->mt76.dev, "BSS %d is %s\n", event->bss_idx,
+		event->is_absent ? "Absent" : "Present");
 }
 
 static void
-- 
2.25.1


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

* [PATCH 7/9] wifi: mt76: connac: accept hw scan request at a time
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (5 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-16  0:03 ` [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support sean.wang
  2022-08-16  0:03 ` [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
  8 siblings, 0 replies; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek

From: Sean Wang <sean.wang@mediatek.com>

The current hw scan cannot accept multiple hw scan requests at a time, we
return the proper error code when the hw scan is still undergoing.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index c2ed5e755893..0ade122de632 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1536,6 +1536,9 @@ int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
 	struct mt76_connac_hw_scan_req *req;
 	struct sk_buff *skb;
 
+	if (test_bit(MT76_HW_SCANNING, &phy->state))
+		return -EBUSY;
+
 	skb = mt76_mcu_msg_alloc(mdev, NULL, sizeof(*req));
 	if (!skb)
 		return -ENOMEM;
-- 
2.25.1


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

* [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (6 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 7/9] wifi: mt76: connac: accept hw scan request at a time sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:12   ` Lorenzo Bianconi
  2022-08-16  0:03 ` [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek, Deren Wu

From: Sean Wang <sean.wang@mediatek.com>

Introduce remain_on_channel support. Additionally, we add
mt7921_check_offload_capability to disable .remain_on_channel and
.cancel_remain_on_channel and related configuration because those
operations would rely on the fundamental MCU commands that will be only
supported with newer firmware.

Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7921/init.c  |  36 ++++++
 .../net/wireless/mediatek/mt76/mt7921/main.c  | 112 ++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  24 ++++
 .../wireless/mediatek/mt76/mt7921/mt7921.h    |  34 ++++++
 .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
 .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
 .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
 7 files changed, 225 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index cd960e23770f..1b7a18d42f5b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -44,6 +44,35 @@ mt7921_regd_notifier(struct wiphy *wiphy,
 	mt7921_mutex_release(dev);
 }
 
+static int mt7921_check_offload_capability(struct mt7921_dev *dev)
+{
+	struct ieee80211_hw *hw = mt76_hw(dev);
+	int year, mon, day, hour, min, sec;
+	struct wiphy *wiphy = hw->wiphy;
+	bool fw_can_roc = false;
+	int ret;
+
+	ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
+		     &year, &mon, &day, &hour, &min, &sec);
+	if (ret != 6)
+		goto out;
+
+	/* Old firmware cannot support remained on channel and channel
+	 * context management.
+	 */
+	fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
+		      mktime64(2022, 7, 15, 12, 1, 1);
+out:
+	if (!fw_can_roc) {
+		dev->ops->remain_on_channel = NULL;
+		dev->ops->cancel_remain_on_channel = NULL;
+
+		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+	}
+
+	return 0;
+}
+
 static int
 mt7921_init_wiphy(struct ieee80211_hw *hw)
 {
@@ -70,6 +99,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 				 BIT(NL80211_IFTYPE_AP);
 	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+	wiphy->max_remain_on_channel_duration = 5000;
 	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
 	wiphy->max_scan_ssids = 4;
 	wiphy->max_sched_scan_plan_interval =
@@ -79,6 +109,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
 	wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
 	wiphy->max_sched_scan_reqs = 1;
 	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 	wiphy->reg_notifier = mt7921_regd_notifier;
 
 	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
@@ -222,6 +253,7 @@ static void mt7921_init_work(struct work_struct *work)
 	if (ret)
 		return;
 
+	mt7921_check_offload_capability(dev);
 	mt76_set_stream_caps(&dev->mphy, true);
 	mt7921_set_stream_he_caps(&dev->phy);
 
@@ -277,6 +309,10 @@ int mt7921_register_device(struct mt7921_dev *dev)
 	INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
 	INIT_WORK(&dev->init_work, mt7921_init_work);
 
+	INIT_WORK(&dev->phy.roc_work, mt7921_roc_work);
+	timer_setup(&dev->phy.roc_timer, mt7921_roc_timer, 0);
+	init_waitqueue_head(&dev->phy.roc_wait);
+
 	dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
 	dev->pm.stats.last_wake_event = jiffies;
 	dev->pm.stats.last_doze_event = jiffies;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index b280f184244f..ae0aabe052e3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -386,6 +386,116 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
 	mt76_packet_id_flush(&dev->mt76, &msta->wcid);
 }
 
+static void mt7921_roc_iter(void *priv, u8 *mac,
+			    struct ieee80211_vif *vif)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_phy *phy = priv;
+
+	mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id);
+}
+
+void mt7921_roc_work(struct work_struct *work)
+{
+	struct mt7921_phy *phy;
+
+	phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy,
+						roc_work);
+
+	if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+		return;
+
+	mt7921_mutex_acquire(phy->dev);
+	ieee80211_iterate_active_interfaces(phy->mt76->hw,
+					    IEEE80211_IFACE_ITER_RESUME_ALL,
+					    mt7921_roc_iter, phy);
+	mt7921_mutex_release(phy->dev);
+	ieee80211_remain_on_channel_expired(phy->mt76->hw);
+}
+
+void mt7921_roc_timer(struct timer_list *timer)
+{
+	struct mt7921_phy *phy = from_timer(phy, timer, roc_timer);
+
+	ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
+}
+
+static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif)
+{
+	int err;
+
+	if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
+		return 0;
+
+	del_timer_sync(&phy->roc_timer);
+	cancel_work_sync(&phy->roc_work);
+	err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
+	clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+
+	return 00;
+}
+
+static int mt7921_set_roc(struct mt7921_phy *phy,
+			  struct mt7921_vif *vif,
+			  struct ieee80211_channel *chan,
+			  int duration,
+			  enum mt7921_roc_req type)
+{
+	int err;
+
+	if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))
+		return -EBUSY;
+
+	phy->roc_grant = false;
+
+	err = mt7921_mcu_set_roc(phy, vif, chan, duration, type,
+				 ++phy->roc_token_id);
+	if (err < 0) {
+		clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+		goto out;
+	}
+
+	if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) {
+		mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
+		clear_bit(MT76_STATE_ROC, &phy->mt76->state);
+		err = -ETIMEDOUT;
+	}
+
+out:
+	return err;
+}
+
+static int mt7921_remain_on_channel(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_channel *chan,
+				    int duration,
+				    enum ieee80211_roc_type type)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_phy *phy = mt7921_hw_phy(hw);
+	int err;
+
+	mt7921_mutex_acquire(phy->dev);
+	err = mt7921_set_roc(phy, mvif, chan, duration, MT7921_ROC_REQ_ROC);
+	mt7921_mutex_release(phy->dev);
+
+	return err;
+}
+
+static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw,
+					   struct ieee80211_vif *vif)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_phy *phy = mt7921_hw_phy(hw);
+	int err;
+
+	mt7921_mutex_acquire(phy->dev);
+	err = mt7921_abort_roc(phy, mvif);
+	mt7921_mutex_release(phy->dev);
+
+	return err;
+}
+
 static int mt7921_set_channel(struct mt7921_phy *phy)
 {
 	struct mt7921_dev *dev = phy->dev;
@@ -1618,6 +1728,8 @@ const struct ieee80211_ops mt7921_ops = {
 #endif /* CONFIG_PM */
 	.flush = mt7921_flush,
 	.set_sar_specs = mt7921_set_sar_specs,
+	.remain_on_channel = mt7921_remain_on_channel,
+	.cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
 };
 EXPORT_SYMBOL_GPL(mt7921_ops);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 05b625e02265..529fb56323ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -127,6 +127,29 @@ void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
 
 #endif /* CONFIG_PM */
 
+static void
+mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb)
+{
+	struct mt7921_roc_grant_tlv *grant;
+	struct mt76_connac2_mcu_rxd *rxd;
+	int duration;
+
+	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
+	grant = (struct mt7921_roc_grant_tlv *)(rxd->tlv + 4);
+
+	/* should never happen */
+	WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT));
+
+	if (grant->reqtype == MT7921_ROC_REQ_ROC)
+		ieee80211_ready_on_channel(dev->mt76.phy.hw);
+
+	dev->phy.roc_grant = true;
+	wake_up(&dev->phy.roc_wait);
+	duration = le32_to_cpu(grant->max_interval);
+	mod_timer(&dev->phy.roc_timer,
+		  round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
+}
+
 static void
 mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
 {
@@ -283,6 +306,7 @@ mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
 
 	switch (rxd->eid) {
 	case MCU_UNI_EVENT_ROC:
+		mt7921_mcu_uni_roc_event(dev, skb);
 		break;
 	default:
 		break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index c9044d546e94..280605ffc4da 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -65,6 +65,30 @@ enum mt7921_roc_req {
 	MT7921_ROC_REQ_NUM
 };
 
+enum {
+	UNI_EVENT_ROC_GRANT = 0,
+	UNI_EVENT_ROC_TAG_NUM
+};
+
+struct mt7921_roc_grant_tlv {
+	__le16 tag;
+	__le16 len;
+	u8 bss_idx;
+	u8 tokenid;
+	u8 status;
+	u8 primarychannel;
+	u8 rfsco;
+	u8 rfband;
+	u8 channelwidth;
+	u8 centerfreqseg1;
+	u8 centerfreqseg2;
+	u8 reqtype;
+	u8 dbdcband;
+	u8 rsv[1];
+	__le32 max_interval;
+} __packed;
+/* cnm end */
+
 enum mt7921_sdio_pkt_type {
 	MT7921_SDIO_TXD,
 	MT7921_SDIO_DATA,
@@ -185,9 +209,16 @@ struct mt7921_phy {
 
 	struct sk_buff_head scan_event_list;
 	struct delayed_work scan_work;
+
 #ifdef CONFIG_ACPI
 	struct mt7921_acpi_sar *acpisar;
 #endif
+
+	struct work_struct roc_work;
+	struct timer_list roc_timer;
+	wait_queue_head_t roc_wait;
+	u8 roc_token_id;
+	bool roc_grant;
 };
 
 #define mt7921_init_reset(dev)		((dev)->hif_ops->init_reset(dev))
@@ -228,6 +259,7 @@ struct mt7921_dev {
 	struct mt76_connac_pm pm;
 	struct mt76_connac_coredump coredump;
 	const struct mt7921_hif_ops *hif_ops;
+	struct ieee80211_ops *ops;
 
 	struct work_struct ipv6_ns_work;
 	/* IPv6 addresses for WoWLAN */
@@ -412,6 +444,8 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
 			 struct ieee80211_ampdu_params *params,
 			 bool enable);
 void mt7921_scan_work(struct work_struct *work);
+void mt7921_roc_work(struct work_struct *work);
+void mt7921_roc_timer(struct timer_list *timer);
 int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
 int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
 int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 9d1ba838e54f..0692fb0f91ca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -252,6 +252,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
 	};
 
 	struct mt76_bus_ops *bus_ops;
+	struct ieee80211_ops *ops;
 	struct mt7921_dev *dev;
 	struct mt76_dev *mdev;
 	int ret;
@@ -277,8 +278,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
 	if (mt7921_disable_aspm)
 		mt76_pci_disable_aspm(pdev);
 
-	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7921_ops,
-				 &drv_ops);
+	ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
+			   GFP_KERNEL);
+	if (!ops) {
+		ret = -ENOMEM;
+		goto err_free_pci_vec;
+	}
+
+	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
 	if (!mdev) {
 		ret = -ENOMEM;
 		goto err_free_pci_vec;
@@ -286,7 +293,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
 
 	dev = container_of(mdev, struct mt7921_dev, mt76);
 	dev->hif_ops = &mt7921_pcie_ops;
-
+	dev->ops = ops;
 	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
 	tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
index 487acd6e2be8..6d27875f41b8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
@@ -120,18 +120,23 @@ static int mt7921s_probe(struct sdio_func *func,
 		.fw_own = mt7921s_mcu_fw_pmctrl,
 	};
 
+	struct ieee80211_ops *ops;
 	struct mt7921_dev *dev;
 	struct mt76_dev *mdev;
 	int ret;
 
-	mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops,
-				 &drv_ops);
+	ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
+			   GFP_KERNEL);
+	if (!ops)
+		return -ENOMEM;
+
+	mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
 	if (!mdev)
 		return -ENOMEM;
 
 	dev = container_of(mdev, struct mt7921_dev, mt76);
 	dev->hif_ops = &mt7921_sdio_ops;
-
+	dev->ops = ops;
 	sdio_set_drvdata(func, dev);
 
 	ret = mt76s_init(mdev, func, &mt7921s_ops);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
index d06cee386acd..cf3ec59a4270 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
@@ -217,6 +217,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
 
 	dev = container_of(mdev, struct mt7921_dev, mt76);
 	dev->hif_ops = &hif_ops;
+	dev->ops = ops;
 
 	udev = usb_get_dev(udev);
 	usb_reset_device(udev);
-- 
2.25.1


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

* [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support
  2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
                   ` (7 preceding siblings ...)
  2022-08-16  0:03 ` [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support sean.wang
@ 2022-08-16  0:03 ` sean.wang
  2022-08-17  7:24   ` Lorenzo Bianconi
  8 siblings, 1 reply; 31+ messages in thread
From: sean.wang @ 2022-08-16  0:03 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: sean.wang, Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang,
	Deren.Wu, km.lin, jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh,
	posh.sun, ted.huang, Stella.Chang, Tom.Chou, steve.lee, jsiuda,
	frankgor, kuabhs, druth, abhishekpandit, shawnku, linux-wireless,
	linux-mediatek, Deren Wu

From: Sean Wang <sean.wang@mediatek.com>

The firmware can have the capability to manage the channel context
scheduling on multiple roles running on the device including Station,
AP and P2P GC/GO mode (will be extended based on the patchset) to help
users sharing the network with others on a single device.

The firmware is able to support the channel chanctx up to 2 interface
simultaneously running on the different channels.

Another thing to be noted is that before the driver is going sent out the
management frames, the driver has to get the privilege from the firmware
to occupy the current channel context until the frame handshake is
completed and then get the privilege back to the firmware.

We temporarily disable the feature with a module parameter
mt7921_disable_cnm for a while until we can ensure the patchset doesn't
cause any regression.

Co-developed-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7921/init.c  |  40 ++++++-
 .../net/wireless/mediatek/mt76/mt7921/main.c  | 111 +++++++++++++++++-
 .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
 3 files changed, 145 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 1b7a18d42f5b..208a6117cb69 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -7,6 +7,10 @@
 #include "mcu.h"
 #include "eeprom.h"
 
+static bool mt7921_disable_cnm = true;
+module_param_named(disable_cnm, mt7921_disable_cnm, bool, 0644);
+MODULE_PARM_DESC(disable_cnm, "disable concurrent network support");
+
 static const struct ieee80211_iface_limit if_limits[] = {
 	{
 		.max = MT7921_MAX_INTERFACES,
@@ -25,6 +29,27 @@ static const struct ieee80211_iface_combination if_comb[] = {
 		.max_interfaces = MT7921_MAX_INTERFACES,
 		.num_different_channels = 1,
 		.beacon_int_infra_match = true,
+	},
+};
+
+static const struct ieee80211_iface_limit if_limits_chanctx[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP),
+	}
+};
+
+static const struct ieee80211_iface_combination if_comb_chanctx[] = {
+	{
+		.limits = if_limits_chanctx,
+		.n_limits = ARRAY_SIZE(if_limits_chanctx),
+		.max_interfaces = 2,
+		.num_different_channels = 2,
+		.beacon_int_infra_match = false,
 	}
 };
 
@@ -63,11 +88,20 @@ static int mt7921_check_offload_capability(struct mt7921_dev *dev)
 	fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
 		      mktime64(2022, 7, 15, 12, 1, 1);
 out:
-	if (!fw_can_roc) {
+	if (!fw_can_roc || mt7921_disable_cnm) {
 		dev->ops->remain_on_channel = NULL;
 		dev->ops->cancel_remain_on_channel = NULL;
+		dev->ops->add_chanctx = NULL;
+		dev->ops->remove_chanctx = NULL;
+		dev->ops->change_chanctx = NULL;
+		dev->ops->assign_vif_chanctx = NULL;
+		dev->ops->unassign_vif_chanctx = NULL;
+		dev->ops->mgd_prepare_tx = NULL;
+		dev->ops->mgd_complete_tx = NULL;
 
 		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+		wiphy->iface_combinations = if_comb;
+		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
 	}
 
 	return 0;
@@ -93,12 +127,12 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
 	hw->sta_data_size = sizeof(struct mt7921_sta);
 	hw->vif_data_size = sizeof(struct mt7921_vif);
 
-	wiphy->iface_combinations = if_comb;
+	wiphy->iface_combinations = if_comb_chanctx;
 	wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
 			  WIPHY_FLAG_4ADDR_STATION);
 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 				 BIT(NL80211_IFTYPE_AP);
-	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
 	wiphy->max_remain_on_channel_duration = 5000;
 	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
 	wiphy->max_scan_ssids = 4;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index ae0aabe052e3..6386290ba71c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -858,7 +858,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 
 	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
 		mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
-					    true, NULL);
+					    true, mvif->ctx);
 
 	mt7921_mac_wtbl_update(dev, msta->wcid.idx,
 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
@@ -890,7 +890,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
 		if (!sta->tdls)
 			mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
 						    &mvif->sta.wcid, false,
-						    NULL);
+						    mvif->ctx);
 	}
 
 	spin_lock_bh(&dev->sta_poll_lock);
@@ -1640,7 +1640,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mt7921_mutex_acquire(dev);
 
 	err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
-					  true, NULL);
+					  true, mvif->ctx);
 	if (err)
 		goto failed;
 
@@ -1672,12 +1672,108 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		goto failed;
 
 	mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
-				    NULL);
+				    mvif->ctx);
 
 failed:
 	mt7921_mutex_release(dev);
 }
 
+static int
+mt7921_add_chanctx(struct ieee80211_hw *hw,
+		   struct ieee80211_chanctx_conf *ctx)
+{
+	return 0;
+}
+
+static void
+mt7921_remove_chanctx(struct ieee80211_hw *hw,
+		      struct ieee80211_chanctx_conf *ctx)
+{
+}
+
+static void mt7921_ctx_iter(void *priv, u8 *mac,
+			    struct ieee80211_vif *vif)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct ieee80211_chanctx_conf *ctx = priv;
+
+	if (ctx != mvif->ctx)
+		return;
+
+	mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
+}
+
+static void
+mt7921_change_chanctx(struct ieee80211_hw *hw,
+		      struct ieee80211_chanctx_conf *ctx,
+		      u32 changed)
+{
+	struct mt7921_phy *phy = mt7921_hw_phy(hw);
+
+	mt7921_mutex_acquire(phy->dev);
+	ieee80211_iterate_active_interfaces(phy->mt76->hw,
+					    IEEE80211_IFACE_ITER_ACTIVE,
+					    mt7921_ctx_iter, ctx);
+	mt7921_mutex_release(phy->dev);
+}
+
+static int
+mt7921_assign_vif_chanctx(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif,
+			  struct ieee80211_bss_conf *link_conf,
+			  struct ieee80211_chanctx_conf *ctx)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+	mt7921_mutex_acquire(dev);
+	mvif->ctx = ctx;
+	mt7921_mutex_release(dev);
+
+	return 0;
+}
+
+static void
+mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    struct ieee80211_bss_conf *link_conf,
+			    struct ieee80211_chanctx_conf *ctx)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+	mt7921_mutex_acquire(dev);
+	mvif->ctx = NULL;
+	mt7921_mutex_release(dev);
+}
+
+static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  struct ieee80211_prep_tx_info *info)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_dev *dev = mt7921_hw_dev(hw);
+	u16 duration = info->duration ? info->duration :
+		       jiffies_to_msecs(HZ);
+
+	mt7921_mutex_acquire(dev);
+	mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
+		       MT7921_ROC_REQ_JOIN);
+	mt7921_mutex_release(dev);
+}
+
+static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_prep_tx_info *info)
+{
+	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
+	struct mt7921_dev *dev = mt7921_hw_dev(hw);
+
+	mt7921_mutex_acquire(dev);
+	mt7921_abort_roc(mvif->phy, mvif);
+	mt7921_mutex_release(dev);
+}
+
 const struct ieee80211_ops mt7921_ops = {
 	.tx = mt7921_tx,
 	.start = mt7921_start,
@@ -1730,6 +1826,13 @@ const struct ieee80211_ops mt7921_ops = {
 	.set_sar_specs = mt7921_set_sar_specs,
 	.remain_on_channel = mt7921_remain_on_channel,
 	.cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
+	.add_chanctx = mt7921_add_chanctx,
+	.remove_chanctx = mt7921_remove_chanctx,
+	.change_chanctx = mt7921_change_chanctx,
+	.assign_vif_chanctx = mt7921_assign_vif_chanctx,
+	.unassign_vif_chanctx = mt7921_unassign_vif_chanctx,
+	.mgd_prepare_tx = mt7921_mgd_prepare_tx,
+	.mgd_complete_tx = mt7921_mgd_complete_tx,
 };
 EXPORT_SYMBOL_GPL(mt7921_ops);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 280605ffc4da..fda85252325c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -156,6 +156,7 @@ struct mt7921_vif {
 	struct ewma_rssi rssi;
 
 	struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
+	struct ieee80211_chanctx_conf *ctx;
 };
 
 struct mib_stats {
-- 
2.25.1


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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-16  0:03 ` [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration sean.wang
@ 2022-08-16  8:03   ` Johannes Berg
  2022-08-17  8:28     ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2022-08-16  8:03 UTC (permalink / raw)
  To: sean.wang, nbd, lorenzo.bianconi
  Cc: Soul.Huang, YN.Chen, Leon.Yen, Eric-SY.Chang, Deren.Wu, km.lin,
	jenhao.yang, robin.chiu, Eddie.Chen, ch.yeh, posh.sun, ted.huang,
	Stella.Chang, Tom.Chou, steve.lee, jsiuda, frankgor, kuabhs,
	druth, abhishekpandit, shawnku, linux-wireless, linux-mediatek

On Tue, 2022-08-16 at 08:03 +0800, sean.wang@mediatek.com wrote:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> MT7921 device can be supported with the channel context depending on
> the newer firmware so that we need a way to enable the chanctx related
> methods until hw is being registered.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  net/mac80211/main.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 5b1c47ed0cc0..98d05ed1a081 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -1011,6 +1011,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
>  		return -EINVAL;
>  #endif
>  
> +	/* check all or no channel context operations exist */
> +	i = !!local->ops->add_chanctx + !!local->ops->remove_chanctx +
> +	    !!local->ops->change_chanctx + !!local->ops->assign_vif_chanctx +
> +	    !!local->ops->unassign_vif_chanctx;
> +	if (WARN_ON(i != 0 && i != 5))
> +		return -EINVAL;
> +	local->use_chanctx = i == 5;
> +

Not sure I understand this - this just *adds* code, based on the
description I would've expected you to *move* code?

In any case, I'm not sure I see how this makes sense - ops is supposed
to be const, and you're supposed to pass it to alloc_hw already, so how
would it change?!

Also, conceptually, I'm not sure why it's needed to alloc_hw before
loading firmware, we also have a lot of things depend on the firmware
capabilities in iwlwifi/mvm, and so we alloc/register HW after loading
firmware.

johannes


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

* Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-16  0:03 ` [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support sean.wang
@ 2022-08-17  7:12   ` Lorenzo Bianconi
  2022-08-18  1:03     ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:12 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

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

> From: Sean Wang <sean.wang@mediatek.com>
> 
> Introduce remain_on_channel support. Additionally, we add
> mt7921_check_offload_capability to disable .remain_on_channel and
> .cancel_remain_on_channel and related configuration because those
> operations would rely on the fundamental MCU commands that will be only
> supported with newer firmware.
> 
> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  .../net/wireless/mediatek/mt76/mt7921/init.c  |  36 ++++++
>  .../net/wireless/mediatek/mt76/mt7921/main.c  | 112 ++++++++++++++++++
>  .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  24 ++++
>  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  34 ++++++
>  .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
>  .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
>  .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
>  7 files changed, 225 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> index cd960e23770f..1b7a18d42f5b 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> @@ -44,6 +44,35 @@ mt7921_regd_notifier(struct wiphy *wiphy,
>  	mt7921_mutex_release(dev);
>  }
>  
> +static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> +{
> +	struct ieee80211_hw *hw = mt76_hw(dev);
> +	int year, mon, day, hour, min, sec;
> +	struct wiphy *wiphy = hw->wiphy;
> +	bool fw_can_roc = false;
> +	int ret;
> +
> +	ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
> +		     &year, &mon, &day, &hour, &min, &sec);

does the fw have a differnt base version with respect to the previous ones?
checking the date is a bit ugly.

> +	if (ret != 6)
> +		goto out;
> +
> +	/* Old firmware cannot support remained on channel and channel
> +	 * context management.
> +	 */
> +	fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
> +		      mktime64(2022, 7, 15, 12, 1, 1);
> +out:
> +	if (!fw_can_roc) {
> +		dev->ops->remain_on_channel = NULL;
> +		dev->ops->cancel_remain_on_channel = NULL;
> +
> +		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int
>  mt7921_init_wiphy(struct ieee80211_hw *hw)
>  {
> @@ -70,6 +99,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
>  	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
>  				 BIT(NL80211_IFTYPE_AP);
>  	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> +	wiphy->max_remain_on_channel_duration = 5000;
>  	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
>  	wiphy->max_scan_ssids = 4;
>  	wiphy->max_sched_scan_plan_interval =
> @@ -79,6 +109,7 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
>  	wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;
>  	wiphy->max_sched_scan_reqs = 1;
>  	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
> +	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
>  	wiphy->reg_notifier = mt7921_regd_notifier;
>  
>  	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
> @@ -222,6 +253,7 @@ static void mt7921_init_work(struct work_struct *work)
>  	if (ret)
>  		return;
>  
> +	mt7921_check_offload_capability(dev);
>  	mt76_set_stream_caps(&dev->mphy, true);
>  	mt7921_set_stream_he_caps(&dev->phy);
>  
> @@ -277,6 +309,10 @@ int mt7921_register_device(struct mt7921_dev *dev)
>  	INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
>  	INIT_WORK(&dev->init_work, mt7921_init_work);
>  
> +	INIT_WORK(&dev->phy.roc_work, mt7921_roc_work);
> +	timer_setup(&dev->phy.roc_timer, mt7921_roc_timer, 0);
> +	init_waitqueue_head(&dev->phy.roc_wait);
> +
>  	dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
>  	dev->pm.stats.last_wake_event = jiffies;
>  	dev->pm.stats.last_doze_event = jiffies;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> index b280f184244f..ae0aabe052e3 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> @@ -386,6 +386,116 @@ static void mt7921_remove_interface(struct ieee80211_hw *hw,
>  	mt76_packet_id_flush(&dev->mt76, &msta->wcid);
>  }
>  
> +static void mt7921_roc_iter(void *priv, u8 *mac,
> +			    struct ieee80211_vif *vif)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_phy *phy = priv;
> +
> +	mt7921_mcu_abort_roc(phy, mvif, phy->roc_token_id);
> +}
> +
> +void mt7921_roc_work(struct work_struct *work)
> +{
> +	struct mt7921_phy *phy;
> +
> +	phy = (struct mt7921_phy *)container_of(work, struct mt7921_phy,
> +						roc_work);
> +
> +	if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
> +		return;
> +
> +	mt7921_mutex_acquire(phy->dev);
> +	ieee80211_iterate_active_interfaces(phy->mt76->hw,
> +					    IEEE80211_IFACE_ITER_RESUME_ALL,
> +					    mt7921_roc_iter, phy);
> +	mt7921_mutex_release(phy->dev);
> +	ieee80211_remain_on_channel_expired(phy->mt76->hw);
> +}
> +
> +void mt7921_roc_timer(struct timer_list *timer)
> +{
> +	struct mt7921_phy *phy = from_timer(phy, timer, roc_timer);
> +
> +	ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);
> +}
> +
> +static int mt7921_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif)
> +{
> +	int err;
> +
> +	if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))
> +		return 0;
> +
> +	del_timer_sync(&phy->roc_timer);
> +	cancel_work_sync(&phy->roc_work);
> +	err = mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
> +	clear_bit(MT76_STATE_ROC, &phy->mt76->state);
> +
> +	return 00;
> +}
> +
> +static int mt7921_set_roc(struct mt7921_phy *phy,
> +			  struct mt7921_vif *vif,
> +			  struct ieee80211_channel *chan,
> +			  int duration,
> +			  enum mt7921_roc_req type)
> +{
> +	int err;
> +
> +	if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state))
> +		return -EBUSY;
> +
> +	phy->roc_grant = false;
> +
> +	err = mt7921_mcu_set_roc(phy, vif, chan, duration, type,
> +				 ++phy->roc_token_id);
> +	if (err < 0) {
> +		clear_bit(MT76_STATE_ROC, &phy->mt76->state);
> +		goto out;
> +	}
> +
> +	if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) {
> +		mt7921_mcu_abort_roc(phy, vif, phy->roc_token_id);
> +		clear_bit(MT76_STATE_ROC, &phy->mt76->state);
> +		err = -ETIMEDOUT;
> +	}
> +
> +out:
> +	return err;
> +}
> +
> +static int mt7921_remain_on_channel(struct ieee80211_hw *hw,
> +				    struct ieee80211_vif *vif,
> +				    struct ieee80211_channel *chan,
> +				    int duration,
> +				    enum ieee80211_roc_type type)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_phy *phy = mt7921_hw_phy(hw);
> +	int err;
> +
> +	mt7921_mutex_acquire(phy->dev);
> +	err = mt7921_set_roc(phy, mvif, chan, duration, MT7921_ROC_REQ_ROC);
> +	mt7921_mutex_release(phy->dev);
> +
> +	return err;
> +}
> +
> +static int mt7921_cancel_remain_on_channel(struct ieee80211_hw *hw,
> +					   struct ieee80211_vif *vif)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_phy *phy = mt7921_hw_phy(hw);
> +	int err;
> +
> +	mt7921_mutex_acquire(phy->dev);
> +	err = mt7921_abort_roc(phy, mvif);
> +	mt7921_mutex_release(phy->dev);
> +
> +	return err;
> +}
> +
>  static int mt7921_set_channel(struct mt7921_phy *phy)
>  {
>  	struct mt7921_dev *dev = phy->dev;
> @@ -1618,6 +1728,8 @@ const struct ieee80211_ops mt7921_ops = {
>  #endif /* CONFIG_PM */
>  	.flush = mt7921_flush,
>  	.set_sar_specs = mt7921_set_sar_specs,
> +	.remain_on_channel = mt7921_remain_on_channel,
> +	.cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
>  };
>  EXPORT_SYMBOL_GPL(mt7921_ops);
>  
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> index 05b625e02265..529fb56323ef 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> @@ -127,6 +127,29 @@ void mt7921_mcu_set_suspend_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
>  
>  #endif /* CONFIG_PM */
>  
> +static void
> +mt7921_mcu_uni_roc_event(struct mt7921_dev *dev, struct sk_buff *skb)
> +{
> +	struct mt7921_roc_grant_tlv *grant;
> +	struct mt76_connac2_mcu_rxd *rxd;
> +	int duration;
> +
> +	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
> +	grant = (struct mt7921_roc_grant_tlv *)(rxd->tlv + 4);
> +
> +	/* should never happen */
> +	WARN_ON_ONCE((le16_to_cpu(grant->tag) != UNI_EVENT_ROC_GRANT));
> +
> +	if (grant->reqtype == MT7921_ROC_REQ_ROC)
> +		ieee80211_ready_on_channel(dev->mt76.phy.hw);
> +
> +	dev->phy.roc_grant = true;
> +	wake_up(&dev->phy.roc_wait);
> +	duration = le32_to_cpu(grant->max_interval);
> +	mod_timer(&dev->phy.roc_timer,
> +		  round_jiffies_up(jiffies + msecs_to_jiffies(duration)));
> +}
> +
>  static void
>  mt7921_mcu_scan_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  {
> @@ -283,6 +306,7 @@ mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
>  
>  	switch (rxd->eid) {
>  	case MCU_UNI_EVENT_ROC:
> +		mt7921_mcu_uni_roc_event(dev, skb);
>  		break;
>  	default:
>  		break;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> index c9044d546e94..280605ffc4da 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> @@ -65,6 +65,30 @@ enum mt7921_roc_req {
>  	MT7921_ROC_REQ_NUM
>  };
>  
> +enum {
> +	UNI_EVENT_ROC_GRANT = 0,
> +	UNI_EVENT_ROC_TAG_NUM
> +};
> +
> +struct mt7921_roc_grant_tlv {
> +	__le16 tag;
> +	__le16 len;
> +	u8 bss_idx;
> +	u8 tokenid;
> +	u8 status;
> +	u8 primarychannel;
> +	u8 rfsco;
> +	u8 rfband;
> +	u8 channelwidth;
> +	u8 centerfreqseg1;
> +	u8 centerfreqseg2;
> +	u8 reqtype;
> +	u8 dbdcband;
> +	u8 rsv[1];
> +	__le32 max_interval;
> +} __packed;
> +/* cnm end */
> +
>  enum mt7921_sdio_pkt_type {
>  	MT7921_SDIO_TXD,
>  	MT7921_SDIO_DATA,
> @@ -185,9 +209,16 @@ struct mt7921_phy {
>  
>  	struct sk_buff_head scan_event_list;
>  	struct delayed_work scan_work;
> +
>  #ifdef CONFIG_ACPI
>  	struct mt7921_acpi_sar *acpisar;
>  #endif
> +
> +	struct work_struct roc_work;
> +	struct timer_list roc_timer;
> +	wait_queue_head_t roc_wait;
> +	u8 roc_token_id;
> +	bool roc_grant;
>  };
>  
>  #define mt7921_init_reset(dev)		((dev)->hif_ops->init_reset(dev))
> @@ -228,6 +259,7 @@ struct mt7921_dev {
>  	struct mt76_connac_pm pm;
>  	struct mt76_connac_coredump coredump;
>  	const struct mt7921_hif_ops *hif_ops;
> +	struct ieee80211_ops *ops;
>  
>  	struct work_struct ipv6_ns_work;
>  	/* IPv6 addresses for WoWLAN */
> @@ -412,6 +444,8 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
>  			 struct ieee80211_ampdu_params *params,
>  			 bool enable);
>  void mt7921_scan_work(struct work_struct *work);
> +void mt7921_roc_work(struct work_struct *work);
> +void mt7921_roc_timer(struct timer_list *timer);
>  int mt7921_mcu_uni_bss_ps(struct mt7921_dev *dev, struct ieee80211_vif *vif);
>  int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev);
>  int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> index 9d1ba838e54f..0692fb0f91ca 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
> @@ -252,6 +252,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
>  	};
>  
>  	struct mt76_bus_ops *bus_ops;
> +	struct ieee80211_ops *ops;
>  	struct mt7921_dev *dev;
>  	struct mt76_dev *mdev;
>  	int ret;
> @@ -277,8 +278,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
>  	if (mt7921_disable_aspm)
>  		mt76_pci_disable_aspm(pdev);
>  
> -	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7921_ops,
> -				 &drv_ops);
> +	ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
> +			   GFP_KERNEL);

why do we need to copy mt7921_ops?

Regards,
Lorenzo

> +	if (!ops) {
> +		ret = -ENOMEM;
> +		goto err_free_pci_vec;
> +	}
> +
> +	mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
>  	if (!mdev) {
>  		ret = -ENOMEM;
>  		goto err_free_pci_vec;
> @@ -286,7 +293,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
>  
>  	dev = container_of(mdev, struct mt7921_dev, mt76);
>  	dev->hif_ops = &mt7921_pcie_ops;
> -
> +	dev->ops = ops;
>  	mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
>  	tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
>  
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> index 487acd6e2be8..6d27875f41b8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> @@ -120,18 +120,23 @@ static int mt7921s_probe(struct sdio_func *func,
>  		.fw_own = mt7921s_mcu_fw_pmctrl,
>  	};
>  
> +	struct ieee80211_ops *ops;
>  	struct mt7921_dev *dev;
>  	struct mt76_dev *mdev;
>  	int ret;
>  
> -	mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops,
> -				 &drv_ops);
> +	ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
> +			   GFP_KERNEL);
> +	if (!ops)
> +		return -ENOMEM;
> +
> +	mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
>  	if (!mdev)
>  		return -ENOMEM;
>  
>  	dev = container_of(mdev, struct mt7921_dev, mt76);
>  	dev->hif_ops = &mt7921_sdio_ops;
> -
> +	dev->ops = ops;
>  	sdio_set_drvdata(func, dev);
>  
>  	ret = mt76s_init(mdev, func, &mt7921s_ops);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> index d06cee386acd..cf3ec59a4270 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> @@ -217,6 +217,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
>  
>  	dev = container_of(mdev, struct mt7921_dev, mt76);
>  	dev->hif_ops = &hif_ops;
> +	dev->ops = ops;
>  
>  	udev = usb_get_dev(udev);
>  	usb_reset_device(udev);
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx
  2022-08-16  0:03 ` [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx sean.wang
@ 2022-08-17  7:13   ` Lorenzo Bianconi
  0 siblings, 0 replies; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:13 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

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

> From: Sean Wang <sean.wang@mediatek.com>
> 
> Reuse mt76_connac_mcu_uni_set_chctx to avoid the dupicated code.

I guess you can squash this patch with the previous one.

Regards,
Lorenzo

> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 73 +------------------
>  1 file changed, 1 insertion(+), 72 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> index 3d5c70765d4f..3e473a409790 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> @@ -1401,7 +1401,6 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
>  {
>  	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;
>  	struct cfg80211_chan_def *chandef = &phy->chandef;
> -	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
>  	enum nl80211_band band = chandef->chan->band;
>  	struct mt76_dev *mdev = phy->dev;
>  	struct {
> @@ -1432,43 +1431,6 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
>  			.qos = vif->bss_conf.qos,
>  		},
>  	};
> -	struct {
> -		struct {
> -			u8 bss_idx;
> -			u8 pad[3];
> -		} __packed hdr;
> -		struct rlm_tlv {
> -			__le16 tag;
> -			__le16 len;
> -			u8 control_channel;
> -			u8 center_chan;
> -			u8 center_chan2;
> -			u8 bw;
> -			u8 tx_streams;
> -			u8 rx_streams;
> -			u8 short_st;
> -			u8 ht_op_info;
> -			u8 sco;
> -			u8 band;
> -			u8 pad[2];
> -		} __packed rlm;
> -	} __packed rlm_req = {
> -		.hdr = {
> -			.bss_idx = mvif->idx,
> -		},
> -		.rlm = {
> -			.tag = cpu_to_le16(UNI_BSS_INFO_RLM),
> -			.len = cpu_to_le16(sizeof(struct rlm_tlv)),
> -			.control_channel = chandef->chan->hw_value,
> -			.center_chan = ieee80211_frequency_to_channel(freq1),
> -			.center_chan2 = ieee80211_frequency_to_channel(freq2),
> -			.tx_streams = hweight8(phy->antenna_mask),
> -			.ht_op_info = 4, /* set HT 40M allowed */
> -			.rx_streams = phy->chainmask,
> -			.short_st = true,
> -			.band = band,
> -		},
> -	};
>  	int err, conn_type;
>  	u8 idx, basic_phy;
>  
> @@ -1555,40 +1517,7 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
>  			return err;
>  	}
>  
> -	switch (chandef->width) {
> -	case NL80211_CHAN_WIDTH_40:
> -		rlm_req.rlm.bw = CMD_CBW_40MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_80:
> -		rlm_req.rlm.bw = CMD_CBW_80MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_80P80:
> -		rlm_req.rlm.bw = CMD_CBW_8080MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_160:
> -		rlm_req.rlm.bw = CMD_CBW_160MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_5:
> -		rlm_req.rlm.bw = CMD_CBW_5MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_10:
> -		rlm_req.rlm.bw = CMD_CBW_10MHZ;
> -		break;
> -	case NL80211_CHAN_WIDTH_20_NOHT:
> -	case NL80211_CHAN_WIDTH_20:
> -	default:
> -		rlm_req.rlm.bw = CMD_CBW_20MHZ;
> -		rlm_req.rlm.ht_op_info = 0;
> -		break;
> -	}
> -
> -	if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan)
> -		rlm_req.rlm.sco = 1; /* SCA */
> -	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)
> -		rlm_req.rlm.sco = 3; /* SCB */
> -
> -	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req,
> -				 sizeof(rlm_req), true);
> +	return mt76_connac_mcu_uni_set_chctx(phy, mvif, NULL);
>  }
>  EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);
>  
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx
  2022-08-16  0:03 ` [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx sean.wang
@ 2022-08-17  7:13   ` Lorenzo Bianconi
  0 siblings, 0 replies; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:13 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

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

On Aug 16, Sean Wang wrote:
> From: Sean Wang <sean.wang@mediatek.com>
> 
> add mt76_connac_mcu_uni_set_chctx to set up the channel context per BSS
> in the firmware
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  .../wireless/mediatek/mt76/mt76_connac_mcu.c  | 83 +++++++++++++++++++
>  .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  3 +
>  2 files changed, 86 insertions(+)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> index 0afcadce87fc..3d5c70765d4f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> @@ -1311,6 +1311,89 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif,
>  	he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;
>  }
>  
> +int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,
> +				  struct ieee80211_chanctx_conf *ctx)
> +{
> +	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;
> +	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
> +	enum nl80211_band band = chandef->chan->band;
> +	struct mt76_dev *mdev = phy->dev;
> +

nit: remove new-line here.

> +	struct {
> +		struct {
> +			u8 bss_idx;
> +			u8 pad[3];
> +		} __packed hdr;
> +		struct rlm_tlv {
> +			__le16 tag;
> +			__le16 len;
> +			u8 control_channel;
> +			u8 center_chan;
> +			u8 center_chan2;
> +			u8 bw;
> +			u8 tx_streams;
> +			u8 rx_streams;
> +			u8 short_st;
> +			u8 ht_op_info;
> +			u8 sco;
> +			u8 band;
> +			u8 pad[2];
> +		} __packed rlm;
> +	} __packed rlm_req = {
> +		.hdr = {
> +			.bss_idx = mvif->idx,
> +		},
> +		.rlm = {
> +			.tag = cpu_to_le16(UNI_BSS_INFO_RLM),
> +			.len = cpu_to_le16(sizeof(struct rlm_tlv)),
> +			.control_channel = chandef->chan->hw_value,
> +			.center_chan = ieee80211_frequency_to_channel(freq1),
> +			.center_chan2 = ieee80211_frequency_to_channel(freq2),
> +			.tx_streams = hweight8(phy->antenna_mask),
> +			.ht_op_info = 4, /* set HT 40M allowed */
> +			.rx_streams = phy->chainmask,
> +			.short_st = true,
> +			.band = band,
> +		},
> +	};
> +
> +	switch (chandef->width) {
> +	case NL80211_CHAN_WIDTH_40:
> +		rlm_req.rlm.bw = CMD_CBW_40MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_80:
> +		rlm_req.rlm.bw = CMD_CBW_80MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_80P80:
> +		rlm_req.rlm.bw = CMD_CBW_8080MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_160:
> +		rlm_req.rlm.bw = CMD_CBW_160MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_5:
> +		rlm_req.rlm.bw = CMD_CBW_5MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_10:
> +		rlm_req.rlm.bw = CMD_CBW_10MHZ;
> +		break;
> +	case NL80211_CHAN_WIDTH_20_NOHT:
> +	case NL80211_CHAN_WIDTH_20:
> +	default:
> +		rlm_req.rlm.bw = CMD_CBW_20MHZ;
> +		rlm_req.rlm.ht_op_info = 0;
> +		break;
> +	}
> +
> +	if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan)
> +		rlm_req.rlm.sco = 1; /* SCA */
> +	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)
> +		rlm_req.rlm.sco = 3; /* SCB */
> +
> +	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req,
> +				 sizeof(rlm_req), true);
> +}
> +EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_set_chctx);
> +
>  int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
>  				struct ieee80211_vif *vif,
>  				struct mt76_wcid *wcid,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> index f1d7c05bd794..bf60b00d6020 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> @@ -1727,6 +1727,9 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
>  int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,
>  			   struct ieee80211_ampdu_params *params,
>  			   int cmd, bool enable, bool tx);
> +int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy,
> +				  struct mt76_vif *vif,
> +				  struct ieee80211_chanctx_conf *ctx);
>  int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
>  				struct ieee80211_vif *vif,
>  				struct mt76_wcid *wcid,
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support
  2022-08-16  0:03 ` [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support sean.wang
@ 2022-08-17  7:15   ` Lorenzo Bianconi
  0 siblings, 0 replies; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:15 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek, Quan Zhou, Kaikai Hu

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

On Aug 16, Sean Wang wrote:
> From: Quan Zhou <quan.zhou@mediatek.com>
> 
> Add unified ROC cmd/event which is only supported by the newer fw.
> 
> Co-developed-by: Sean Wang <sean.wang@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> Co-developed-by: Kaikai Hu <kaikai.hu@mediatek.com>
> Signed-off-by: Kaikai Hu <kaikai.hu@mediatek.com>
> Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
> ---
>  .../wireless/mediatek/mt76/mt76_connac_mcu.h  |  10 +-
>  .../net/wireless/mediatek/mt76/mt7921/mcu.c   | 119 ++++++++++++++++++
>  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  19 +++
>  3 files changed, 147 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> index 1fcc3e8c5380..f3c1e1dc574a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
> @@ -114,11 +114,15 @@ struct mt76_connac2_mcu_rxd {
>  
>  	u8 eid;
>  	u8 seq;
> -	u8 rsv[2];
> +	u8 option;
> +	u8 __rsv;
> +

nit: remove new line here and use 'u8 rsv' to be consistent with the rest of
the code.

>  
>  	u8 ext_eid;
>  	u8 rsv1[2];
>  	u8 s2d_index;
> +
> +	u8 tlv[0];
>  };
>  
>  struct mt76_connac2_patch_hdr {
> @@ -938,6 +942,9 @@ enum {
>  	DEV_INFO_MAX_NUM
>  };
>  
> +#define MCU_UNI_CMD_EVENT                       BIT(1)
> +#define MCU_UNI_CMD_UNSOLICITED_EVENT           BIT(2)
> +
>  /* event table */
>  enum {
>  	MCU_EVENT_TARGET_ADDRESS_LEN = 0x01,
> @@ -1144,6 +1151,7 @@ enum {
>  	MCU_UNI_CMD_OFFLOAD = 0x06,
>  	MCU_UNI_CMD_HIF_CTRL = 0x07,
>  	MCU_UNI_CMD_SNIFFER = 0x24,
> +	MCU_UNI_CMD_ROC = 0x27,
>  };
>  
>  enum {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> index da12d0ae0835..76c8afc00c24 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> @@ -275,6 +275,23 @@ mt7921_mcu_rx_unsolicited_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  	dev_kfree_skb(skb);
>  }
>  
> +static void
> +mt7921_mcu_uni_rx_unsolicited_event(struct mt7921_dev *dev,
> +				    struct sk_buff *skb)
> +{
> +	struct mt76_connac2_mcu_rxd *rxd;
> +
> +	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
> +
> +	switch (rxd->eid) {
> +	case MCU_UNI_EVENT_ROC:
> +		break;
> +	default:
> +		break;
> +	}
> +	dev_kfree_skb(skb);
> +}
> +
>  void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  {
>  	struct mt76_connac2_mcu_rxd *rxd;
> @@ -284,6 +301,11 @@ void mt7921_mcu_rx_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  
>  	rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
>  
> +	if (rxd->option & MCU_UNI_CMD_UNSOLICITED_EVENT) {
> +		mt7921_mcu_uni_rx_unsolicited_event(dev, skb);
> +		return;
> +	}
> +
>  	if (rxd->eid == 0x6) {
>  		mt76_mcu_rx_event(&dev->mt76, skb);
>  		return;
> @@ -521,6 +543,103 @@ int mt7921_mcu_set_tx(struct mt7921_dev *dev, struct ieee80211_vif *vif)
>  				 &req_mu, sizeof(req_mu), false);
>  }
>  
> +int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
> +		       struct ieee80211_channel *chan, int duration,
> +		       enum mt7921_roc_req type, u8 token_id)
> +{
> +	int center_ch = ieee80211_frequency_to_channel(chan->center_freq);
> +	struct mt7921_dev *dev = phy->dev;
> +	struct {
> +		struct {
> +			u8 rsv[4];
> +		} __packed hdr;
> +		struct roc_acquire_tlv {
> +			__le16 tag;
> +			__le16 len;
> +			u8 bss_idx;
> +			u8 tokenid;
> +			u8 control_channel;
> +			u8 sco;
> +			u8 band;
> +			u8 bw;
> +			u8 center_chan;
> +			u8 center_chan2;
> +			u8 bw_from_ap;
> +			u8 center_chan_from_ap;
> +			u8 center_chan2_from_ap;
> +			u8 reqtype;
> +			__le32 maxinterval;
> +			u8 dbdcband;
> +			u8 rsv[3];
> +		} __packed roc;
> +	} __packed req = {
> +		.roc = {
> +			.tag = cpu_to_le16(UNI_ROC_ACQUIRE),
> +			.len = cpu_to_le16(sizeof(struct roc_acquire_tlv)),
> +			.tokenid = token_id,
> +			.reqtype = type,
> +			.maxinterval = cpu_to_le32(duration),
> +			.bss_idx = vif->mt76.idx,
> +			.control_channel = chan->hw_value,
> +			.bw = CMD_CBW_20MHZ,
> +			.bw_from_ap = CMD_CBW_20MHZ,
> +			.center_chan = center_ch,
> +			.center_chan_from_ap = center_ch,
> +			.dbdcband = 0xff, /* auto */
> +		},
> +	};
> +
> +	if (chan->hw_value < center_ch)
> +		req.roc.sco = 1; /* SCA */
> +	else if (chan->hw_value > center_ch)
> +		req.roc.sco = 3; /* SCB */
> +
> +	switch (chan->band) {
> +	case NL80211_BAND_6GHZ:
> +		req.roc.band = 3;
> +		break;
> +	case NL80211_BAND_5GHZ:
> +		req.roc.band = 2;
> +		break;
> +	default:
> +		req.roc.band = 1;
> +		break;
> +	}
> +
> +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
> +				 &req, sizeof(req), false);
> +}
> +
> +int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
> +			 u8 token_id)
> +{
> +	struct mt7921_dev *dev = phy->dev;
> +	struct {
> +		struct {
> +			u8 rsv[4];
> +		} __packed hdr;
> +		struct roc_abort_tlv {
> +			__le16 tag;
> +			__le16 len;
> +			u8 bss_idx;
> +			u8 tokenid;
> +			u8 dbdcband;
> +			u8 rsv[5];
> +		} __packed abort;
> +	} __packed req = {
> +		.abort = {
> +			.tag = cpu_to_le16(UNI_ROC_ABORT),
> +			.len = cpu_to_le16(sizeof(struct roc_abort_tlv)),
> +			.tokenid = token_id,
> +			.bss_idx = vif->mt76.idx,
> +			.dbdcband = 0xff, /* auto*/
> +		},
> +	};
> +
> +	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(ROC),
> +				 &req, sizeof(req), false);
> +}
> +
>  int mt7921_mcu_set_chan_info(struct mt7921_phy *phy, int cmd)
>  {
>  	struct mt7921_dev *dev = phy->dev;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> index c161031ac62a..c9044d546e94 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> @@ -51,6 +51,20 @@
>  #define MT7921_SDIO_HDR_TX_BYTES	GENMASK(15, 0)
>  #define MT7921_SDIO_HDR_PKT_TYPE	GENMASK(17, 16)
>  
> +#define MCU_UNI_EVENT_ROC  0x27
> +
> +enum {
> +	UNI_ROC_ACQUIRE,
> +	UNI_ROC_ABORT,
> +	UNI_ROC_NUM
> +};
> +
> +enum mt7921_roc_req {
> +	MT7921_ROC_REQ_JOIN,
> +	MT7921_ROC_REQ_ROC,
> +	MT7921_ROC_REQ_NUM
> +};
> +
>  enum mt7921_sdio_pkt_type {
>  	MT7921_SDIO_TXD,
>  	MT7921_SDIO_DATA,
> @@ -479,4 +493,9 @@ mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
>  #endif
>  int mt7921_set_tx_sar_pwr(struct ieee80211_hw *hw,
>  			  const struct cfg80211_sar_specs *sar);
> +int mt7921_mcu_set_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
> +		       struct ieee80211_channel *chan, int duration,
> +		       enum mt7921_roc_req type, u8 token_id);
> +int mt7921_mcu_abort_roc(struct mt7921_phy *phy, struct mt7921_vif *vif,
> +			 u8 token_id);
>  #endif
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver
  2022-08-16  0:03 ` [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver sean.wang
@ 2022-08-17  7:16   ` Lorenzo Bianconi
  2022-08-18  0:44     ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:16 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

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

> From: Sean Wang <sean.wang@mediatek.com>
> 
> The firmware would be in charge of braking and continuing the traffic while
> the channel contexts are switching between different BSS and HW SCAN in the
> background.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> index 76c8afc00c24..05b625e02265 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
> @@ -175,15 +175,13 @@ mt7921_mcu_connection_loss_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  static void
>  mt7921_mcu_bss_event(struct mt7921_dev *dev, struct sk_buff *skb)
>  {
> -	struct mt76_phy *mphy = &dev->mt76.phy;
>  	struct mt76_connac_mcu_bss_event *event;
>  
>  	skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
>  	event = (struct mt76_connac_mcu_bss_event *)skb->data;
> -	if (event->is_absent)
> -		ieee80211_stop_queues(mphy->hw);
> -	else
> -		ieee80211_wake_queues(mphy->hw);
> +
> +	dev_dbg(dev->mt76.dev, "BSS %d is %s\n", event->bss_idx,
> +		event->is_absent ? "Absent" : "Present");

do we really need this? I guess we can just drop mt7921_mcu_bss_event entirely

Regards,
Lorenzo

>  }
>  
>  static void
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support
  2022-08-16  0:03 ` [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
@ 2022-08-17  7:24   ` Lorenzo Bianconi
  2022-08-18  0:37     ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-17  7:24 UTC (permalink / raw)
  To: sean.wang
  Cc: nbd, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

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

> From: Sean Wang <sean.wang@mediatek.com>
> 
> The firmware can have the capability to manage the channel context
> scheduling on multiple roles running on the device including Station,
> AP and P2P GC/GO mode (will be extended based on the patchset) to help
> users sharing the network with others on a single device.
> 
> The firmware is able to support the channel chanctx up to 2 interface
> simultaneously running on the different channels.
> 
> Another thing to be noted is that before the driver is going sent out the
> management frames, the driver has to get the privilege from the firmware
> to occupy the current channel context until the frame handshake is
> completed and then get the privilege back to the firmware.
> 
> We temporarily disable the feature with a module parameter
> mt7921_disable_cnm for a while until we can ensure the patchset doesn't
> cause any regression.
> 
> Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
>  .../net/wireless/mediatek/mt76/mt7921/init.c  |  40 ++++++-
>  .../net/wireless/mediatek/mt76/mt7921/main.c  | 111 +++++++++++++++++-
>  .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
>  3 files changed, 145 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> index 1b7a18d42f5b..208a6117cb69 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> @@ -7,6 +7,10 @@
>  #include "mcu.h"
>  #include "eeprom.h"
>  
> +static bool mt7921_disable_cnm = true;
> +module_param_named(disable_cnm, mt7921_disable_cnm, bool, 0644);
> +MODULE_PARM_DESC(disable_cnm, "disable concurrent network support");

do we need it? I guess we can just leave it enabled by default and disable it
through a debugfs node. What do you think?

> +
>  static const struct ieee80211_iface_limit if_limits[] = {
>  	{
>  		.max = MT7921_MAX_INTERFACES,
> @@ -25,6 +29,27 @@ static const struct ieee80211_iface_combination if_comb[] = {
>  		.max_interfaces = MT7921_MAX_INTERFACES,
>  		.num_different_channels = 1,
>  		.beacon_int_infra_match = true,
> +	},
> +};
> +
> +static const struct ieee80211_iface_limit if_limits_chanctx[] = {
> +	{
> +		.max = 2,
> +		.types = BIT(NL80211_IFTYPE_STATION),
> +	},
> +	{
> +		.max = 1,
> +		.types = BIT(NL80211_IFTYPE_AP),
> +	}
> +};
> +
> +static const struct ieee80211_iface_combination if_comb_chanctx[] = {
> +	{
> +		.limits = if_limits_chanctx,
> +		.n_limits = ARRAY_SIZE(if_limits_chanctx),
> +		.max_interfaces = 2,
> +		.num_different_channels = 2,
> +		.beacon_int_infra_match = false,
>  	}
>  };
>  
> @@ -63,11 +88,20 @@ static int mt7921_check_offload_capability(struct mt7921_dev *dev)
>  	fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
>  		      mktime64(2022, 7, 15, 12, 1, 1);
>  out:
> -	if (!fw_can_roc) {
> +	if (!fw_can_roc || mt7921_disable_cnm) {
>  		dev->ops->remain_on_channel = NULL;
>  		dev->ops->cancel_remain_on_channel = NULL;
> +		dev->ops->add_chanctx = NULL;
> +		dev->ops->remove_chanctx = NULL;
> +		dev->ops->change_chanctx = NULL;
> +		dev->ops->assign_vif_chanctx = NULL;
> +		dev->ops->unassign_vif_chanctx = NULL;
> +		dev->ops->mgd_prepare_tx = NULL;
> +		dev->ops->mgd_complete_tx = NULL;
>  
>  		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> +		wiphy->iface_combinations = if_comb;
> +		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
>  	}
>  
>  	return 0;
> @@ -93,12 +127,12 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
>  	hw->sta_data_size = sizeof(struct mt7921_sta);
>  	hw->vif_data_size = sizeof(struct mt7921_vif);
>  
> -	wiphy->iface_combinations = if_comb;
> +	wiphy->iface_combinations = if_comb_chanctx;
>  	wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
>  			  WIPHY_FLAG_4ADDR_STATION);
>  	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
>  				 BIT(NL80211_IFTYPE_AP);
> -	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> +	wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
>  	wiphy->max_remain_on_channel_duration = 5000;
>  	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
>  	wiphy->max_scan_ssids = 4;
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> index ae0aabe052e3..6386290ba71c 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> @@ -858,7 +858,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>  
>  	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
>  		mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
> -					    true, NULL);
> +					    true, mvif->ctx);
>  
>  	mt7921_mac_wtbl_update(dev, msta->wcid.idx,
>  			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
> @@ -890,7 +890,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
>  		if (!sta->tdls)
>  			mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
>  						    &mvif->sta.wcid, false,
> -						    NULL);
> +						    mvif->ctx);
>  	}
>  
>  	spin_lock_bh(&dev->sta_poll_lock);
> @@ -1640,7 +1640,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>  	mt7921_mutex_acquire(dev);
>  
>  	err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
> -					  true, NULL);
> +					  true, mvif->ctx);
>  	if (err)
>  		goto failed;
>  
> @@ -1672,12 +1672,108 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
>  		goto failed;
>  
>  	mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
> -				    NULL);
> +				    mvif->ctx);
>  
>  failed:
>  	mt7921_mutex_release(dev);
>  }
>  
> +static int
> +mt7921_add_chanctx(struct ieee80211_hw *hw,
> +		   struct ieee80211_chanctx_conf *ctx)
> +{
> +	return 0;
> +}
> +
> +static void
> +mt7921_remove_chanctx(struct ieee80211_hw *hw,
> +		      struct ieee80211_chanctx_conf *ctx)
> +{
> +}
> +
> +static void mt7921_ctx_iter(void *priv, u8 *mac,
> +			    struct ieee80211_vif *vif)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct ieee80211_chanctx_conf *ctx = priv;
> +
> +	if (ctx != mvif->ctx)
> +		return;
> +
> +	mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
> +}
> +
> +static void
> +mt7921_change_chanctx(struct ieee80211_hw *hw,
> +		      struct ieee80211_chanctx_conf *ctx,
> +		      u32 changed)
> +{
> +	struct mt7921_phy *phy = mt7921_hw_phy(hw);
> +
> +	mt7921_mutex_acquire(phy->dev);
> +	ieee80211_iterate_active_interfaces(phy->mt76->hw,
> +					    IEEE80211_IFACE_ITER_ACTIVE,
> +					    mt7921_ctx_iter, ctx);
> +	mt7921_mutex_release(phy->dev);
> +}
> +
> +static int
> +mt7921_assign_vif_chanctx(struct ieee80211_hw *hw,
> +			  struct ieee80211_vif *vif,
> +			  struct ieee80211_bss_conf *link_conf,
> +			  struct ieee80211_chanctx_conf *ctx)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_dev *dev = mt7921_hw_dev(hw);
> +
> +	mt7921_mutex_acquire(dev);

I think in this case we can just grub the mutex without waking up the device.
what do you think?

> +	mvif->ctx = ctx;
> +	mt7921_mutex_release(dev);
> +
> +	return 0;
> +}
> +
> +static void
> +mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw,
> +			    struct ieee80211_vif *vif,
> +			    struct ieee80211_bss_conf *link_conf,
> +			    struct ieee80211_chanctx_conf *ctx)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_dev *dev = mt7921_hw_dev(hw);
> +
> +	mt7921_mutex_acquire(dev);

same here.

Regards,
Lorenzo

> +	mvif->ctx = NULL;
> +	mt7921_mutex_release(dev);
> +}
> +
> +static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
> +				  struct ieee80211_vif *vif,
> +				  struct ieee80211_prep_tx_info *info)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_dev *dev = mt7921_hw_dev(hw);
> +	u16 duration = info->duration ? info->duration :
> +		       jiffies_to_msecs(HZ);
> +
> +	mt7921_mutex_acquire(dev);
> +	mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
> +		       MT7921_ROC_REQ_JOIN);
> +	mt7921_mutex_release(dev);
> +}
> +
> +static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
> +				   struct ieee80211_vif *vif,
> +				   struct ieee80211_prep_tx_info *info)
> +{
> +	struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> +	struct mt7921_dev *dev = mt7921_hw_dev(hw);
> +
> +	mt7921_mutex_acquire(dev);
> +	mt7921_abort_roc(mvif->phy, mvif);
> +	mt7921_mutex_release(dev);
> +}
> +
>  const struct ieee80211_ops mt7921_ops = {
>  	.tx = mt7921_tx,
>  	.start = mt7921_start,
> @@ -1730,6 +1826,13 @@ const struct ieee80211_ops mt7921_ops = {
>  	.set_sar_specs = mt7921_set_sar_specs,
>  	.remain_on_channel = mt7921_remain_on_channel,
>  	.cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
> +	.add_chanctx = mt7921_add_chanctx,
> +	.remove_chanctx = mt7921_remove_chanctx,
> +	.change_chanctx = mt7921_change_chanctx,
> +	.assign_vif_chanctx = mt7921_assign_vif_chanctx,
> +	.unassign_vif_chanctx = mt7921_unassign_vif_chanctx,
> +	.mgd_prepare_tx = mt7921_mgd_prepare_tx,
> +	.mgd_complete_tx = mt7921_mgd_complete_tx,
>  };
>  EXPORT_SYMBOL_GPL(mt7921_ops);
>  
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> index 280605ffc4da..fda85252325c 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> @@ -156,6 +156,7 @@ struct mt7921_vif {
>  	struct ewma_rssi rssi;
>  
>  	struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
> +	struct ieee80211_chanctx_conf *ctx;
>  };
>  
>  struct mib_stats {
> -- 
> 2.25.1
> 

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

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-16  8:03   ` Johannes Berg
@ 2022-08-17  8:28     ` Sean Wang
  2022-08-17  8:30       ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-17  8:28 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

Hi Johannes,

On Tue, Aug 16, 2022 at 3:22 AM Johannes Berg <johannes@sipsolutions.net> wrote:
>
> On Tue, 2022-08-16 at 08:03 +0800, sean.wang@mediatek.com wrote:
> > From: Sean Wang <sean.wang@mediatek.com>
> >
> > MT7921 device can be supported with the channel context depending on
> > the newer firmware so that we need a way to enable the chanctx related
> > methods until hw is being registered.
> >
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > ---
> >  net/mac80211/main.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> > index 5b1c47ed0cc0..98d05ed1a081 100644
> > --- a/net/mac80211/main.c
> > +++ b/net/mac80211/main.c
> > @@ -1011,6 +1011,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
> >               return -EINVAL;
> >  #endif
> >
> > +     /* check all or no channel context operations exist */
> > +     i = !!local->ops->add_chanctx + !!local->ops->remove_chanctx +
> > +         !!local->ops->change_chanctx + !!local->ops->assign_vif_chanctx +
> > +         !!local->ops->unassign_vif_chanctx;
> > +     if (WARN_ON(i != 0 && i != 5))
> > +             return -EINVAL;
> > +     local->use_chanctx = i == 5;
> > +
>
> Not sure I understand this - this just *adds* code, based on the
> description I would've expected you to *move* code?

It can be done and looks better by *move* code instead of *adds* code.
I will change it in the next version. Thanks for your input.

>
> In any case, I'm not sure I see how this makes sense - ops is supposed
> to be const, and you're supposed to pass it to alloc_hw already, so how
> would it change?!
>
> Also, conceptually, I'm not sure why it's needed to alloc_hw before
> loading firmware, we also have a lot of things depend on the firmware
> capabilities in iwlwifi/mvm, and so we alloc/register HW after loading
> firmware.
>

Based on mt76 driver logic, alloc_hw would be needed before loading firmware
because alloc_hw creates an instance of "struct mt76_dev*" the
firmware loading relies on,
and so the firmware capabilities cannot be decided before we alloc_hw
in mt76 driver.

    sean

> johannes
>

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-17  8:28     ` Sean Wang
@ 2022-08-17  8:30       ` Johannes Berg
  2022-08-18  0:11         ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2022-08-17  8:30 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren.Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, linux-mediatek

On Wed, 2022-08-17 at 01:28 -0700, Sean Wang wrote:
> Based on mt76 driver logic, alloc_hw would be needed before loading firmware
> because alloc_hw creates an instance of "struct mt76_dev*" the
> firmware loading relies on,
> and so the firmware capabilities cannot be decided before we alloc_hw
> in mt76 driver.
> 

I don't really see why you couldn't change that though? There's no
fundamental reason you need to load the firmware before registering with
mac80211?

And fundamentally, I'm not even sure how you are achieving a change of
the ops - you're meant to point those to a *const* ops, so you need two
versions of the ops, one with and one without chanctx, and point to the
correct one at allocation ...

johannes

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-17  8:30       ` Johannes Berg
@ 2022-08-18  0:11         ` Sean Wang
  2022-08-18 10:49           ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-18  0:11 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Johannes,

On Wed, Aug 17, 2022 at 1:30 AM Johannes Berg <johannes@sipsolutions.net> wrote:
>
> On Wed, 2022-08-17 at 01:28 -0700, Sean Wang wrote:
> > Based on mt76 driver logic, alloc_hw would be needed before loading firmware
> > because alloc_hw creates an instance of "struct mt76_dev*" the
> > firmware loading relies on,
> > and so the firmware capabilities cannot be decided before we alloc_hw
> > in mt76 driver.
> >
>
> I don't really see why you couldn't change that though? There's no
> fundamental reason you need to load the firmware before registering with
> mac80211?
>

It could be changed but it would break the consistency of the current
mt76 driver.

mt76 driver does the things in the following order
- ieee80211_alloc_hw (where an instance of "struct mt76_dev *" would be created)
- register bus operation into mt76 core (depending on struct mt76_dev
to provide an abstraction layer for mt76 core to access bus)
- read chip identifier (depending on bus operation)
- load the firmware capabilities (depending on chip identifier)
- initialize the hardware
....
-ieee80211_register_hw

If firmware capability is needed to load before ieee80211_alloc_hw, we
need to create kind of similar functions to read chip identifiers and
load firmware.
I know It may not a strong reason not to change, but if we can support
read firmware capabilities after alloc_hw, it provides flexibility to
the vendor driver
and helps mt7921 look more consistent and save a few changes across
different mt7921 bus drivers (mt7921 now supports SDIO, USB, PCIe type
driver).

> And fundamentally, I'm not even sure how you are achieving a change of

I kmemdup the const ops and ieee80211_alloc_hw with the duplicated ops
the duplicated ops would be updated by the actual firmware
capabilities before ieee80211_register_hw.

> the ops - you're meant to point those to a *const* ops, so you need two
> versions of the ops, one with and one without chanctx, and point to the
> correct one at allocation ...
>

If you don't like the reason and the way I proposed in the patch,
please let me know. I still can move on to the way you suggested here.

> johannes

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

* Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support
  2022-08-17  7:24   ` Lorenzo Bianconi
@ 2022-08-18  0:37     ` Sean Wang
  2022-08-18  7:43       ` Lorenzo Bianconi
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-18  0:37 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

On Wed, Aug 17, 2022 at 12:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > From: Sean Wang <sean.wang@mediatek.com>
> >
> > The firmware can have the capability to manage the channel context
> > scheduling on multiple roles running on the device including Station,
> > AP and P2P GC/GO mode (will be extended based on the patchset) to help
> > users sharing the network with others on a single device.
> >
> > The firmware is able to support the channel chanctx up to 2 interface
> > simultaneously running on the different channels.
> >
> > Another thing to be noted is that before the driver is going sent out the
> > management frames, the driver has to get the privilege from the firmware
> > to occupy the current channel context until the frame handshake is
> > completed and then get the privilege back to the firmware.
> >
> > We temporarily disable the feature with a module parameter
> > mt7921_disable_cnm for a while until we can ensure the patchset doesn't
> > cause any regression.
> >
> > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > ---
> >  .../net/wireless/mediatek/mt76/mt7921/init.c  |  40 ++++++-
> >  .../net/wireless/mediatek/mt76/mt7921/main.c  | 111 +++++++++++++++++-
> >  .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
> >  3 files changed, 145 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > index 1b7a18d42f5b..208a6117cb69 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > @@ -7,6 +7,10 @@
> >  #include "mcu.h"
> >  #include "eeprom.h"
> >
> > +static bool mt7921_disable_cnm = true;
> > +module_param_named(disable_cnm, mt7921_disable_cnm, bool, 0644);
> > +MODULE_PARM_DESC(disable_cnm, "disable concurrent network support");
>
> do we need it? I guess we can just leave it enabled by default and disable it
> through a debugfs node. What do you think?

The kernel parameter would be checked before registering ops to
mac80211, it seemed to me the way debugfs node doesn't work for that
moment.

>
> > +
> >  static const struct ieee80211_iface_limit if_limits[] = {
> >       {
> >               .max = MT7921_MAX_INTERFACES,
> > @@ -25,6 +29,27 @@ static const struct ieee80211_iface_combination if_comb[] = {
> >               .max_interfaces = MT7921_MAX_INTERFACES,
> >               .num_different_channels = 1,
> >               .beacon_int_infra_match = true,
> > +     },
> > +};
> > +
> > +static const struct ieee80211_iface_limit if_limits_chanctx[] = {
> > +     {
> > +             .max = 2,
> > +             .types = BIT(NL80211_IFTYPE_STATION),
> > +     },
> > +     {
> > +             .max = 1,
> > +             .types = BIT(NL80211_IFTYPE_AP),
> > +     }
> > +};
> > +
> > +static const struct ieee80211_iface_combination if_comb_chanctx[] = {
> > +     {
> > +             .limits = if_limits_chanctx,
> > +             .n_limits = ARRAY_SIZE(if_limits_chanctx),
> > +             .max_interfaces = 2,
> > +             .num_different_channels = 2,
> > +             .beacon_int_infra_match = false,
> >       }
> >  };
> >
> > @@ -63,11 +88,20 @@ static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> >       fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
> >                     mktime64(2022, 7, 15, 12, 1, 1);
> >  out:
> > -     if (!fw_can_roc) {
> > +     if (!fw_can_roc || mt7921_disable_cnm) {
> >               dev->ops->remain_on_channel = NULL;
> >               dev->ops->cancel_remain_on_channel = NULL;
> > +             dev->ops->add_chanctx = NULL;
> > +             dev->ops->remove_chanctx = NULL;
> > +             dev->ops->change_chanctx = NULL;
> > +             dev->ops->assign_vif_chanctx = NULL;
> > +             dev->ops->unassign_vif_chanctx = NULL;
> > +             dev->ops->mgd_prepare_tx = NULL;
> > +             dev->ops->mgd_complete_tx = NULL;
> >
> >               wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> > +             wiphy->iface_combinations = if_comb;
> > +             wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> >       }
> >
> >       return 0;
> > @@ -93,12 +127,12 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
> >       hw->sta_data_size = sizeof(struct mt7921_sta);
> >       hw->vif_data_size = sizeof(struct mt7921_vif);
> >
> > -     wiphy->iface_combinations = if_comb;
> > +     wiphy->iface_combinations = if_comb_chanctx;
> >       wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
> >                         WIPHY_FLAG_4ADDR_STATION);
> >       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
> >                                BIT(NL80211_IFTYPE_AP);
> > -     wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> > +     wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
> >       wiphy->max_remain_on_channel_duration = 5000;
> >       wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
> >       wiphy->max_scan_ssids = 4;
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > index ae0aabe052e3..6386290ba71c 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > @@ -858,7 +858,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> >
> >       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
> >               mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
> > -                                         true, NULL);
> > +                                         true, mvif->ctx);
> >
> >       mt7921_mac_wtbl_update(dev, msta->wcid.idx,
> >                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
> > @@ -890,7 +890,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> >               if (!sta->tdls)
> >                       mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
> >                                                   &mvif->sta.wcid, false,
> > -                                                 NULL);
> > +                                                 mvif->ctx);
> >       }
> >
> >       spin_lock_bh(&dev->sta_poll_lock);
> > @@ -1640,7 +1640,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> >       mt7921_mutex_acquire(dev);
> >
> >       err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
> > -                                       true, NULL);
> > +                                       true, mvif->ctx);
> >       if (err)
> >               goto failed;
> >
> > @@ -1672,12 +1672,108 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> >               goto failed;
> >
> >       mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
> > -                                 NULL);
> > +                                 mvif->ctx);
> >
> >  failed:
> >       mt7921_mutex_release(dev);
> >  }
> >
> > +static int
> > +mt7921_add_chanctx(struct ieee80211_hw *hw,
> > +                struct ieee80211_chanctx_conf *ctx)
> > +{
> > +     return 0;
> > +}
> > +
> > +static void
> > +mt7921_remove_chanctx(struct ieee80211_hw *hw,
> > +                   struct ieee80211_chanctx_conf *ctx)
> > +{
> > +}
> > +
> > +static void mt7921_ctx_iter(void *priv, u8 *mac,
> > +                         struct ieee80211_vif *vif)
> > +{
> > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > +     struct ieee80211_chanctx_conf *ctx = priv;
> > +
> > +     if (ctx != mvif->ctx)
> > +             return;
> > +
> > +     mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
> > +}
> > +
> > +static void
> > +mt7921_change_chanctx(struct ieee80211_hw *hw,
> > +                   struct ieee80211_chanctx_conf *ctx,
> > +                   u32 changed)
> > +{
> > +     struct mt7921_phy *phy = mt7921_hw_phy(hw);
> > +
> > +     mt7921_mutex_acquire(phy->dev);
> > +     ieee80211_iterate_active_interfaces(phy->mt76->hw,
> > +                                         IEEE80211_IFACE_ITER_ACTIVE,
> > +                                         mt7921_ctx_iter, ctx);
> > +     mt7921_mutex_release(phy->dev);
> > +}
> > +
> > +static int
> > +mt7921_assign_vif_chanctx(struct ieee80211_hw *hw,
> > +                       struct ieee80211_vif *vif,
> > +                       struct ieee80211_bss_conf *link_conf,
> > +                       struct ieee80211_chanctx_conf *ctx)
> > +{
> > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > +
> > +     mt7921_mutex_acquire(dev);
>
> I think in this case we can just grub the mutex without waking up the device.
> what do you think?

ack

>
> > +     mvif->ctx = ctx;
> > +     mt7921_mutex_release(dev);
> > +
> > +     return 0;
> > +}
> > +
> > +static void
> > +mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw,
> > +                         struct ieee80211_vif *vif,
> > +                         struct ieee80211_bss_conf *link_conf,
> > +                         struct ieee80211_chanctx_conf *ctx)
> > +{
> > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > +
> > +     mt7921_mutex_acquire(dev);
>
> same here.

ack

>
> Regards,
> Lorenzo
>
> > +     mvif->ctx = NULL;
> > +     mt7921_mutex_release(dev);
> > +}
> > +
> > +static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
> > +                               struct ieee80211_vif *vif,
> > +                               struct ieee80211_prep_tx_info *info)
> > +{
> > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > +     u16 duration = info->duration ? info->duration :
> > +                    jiffies_to_msecs(HZ);
> > +
> > +     mt7921_mutex_acquire(dev);
> > +     mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
> > +                    MT7921_ROC_REQ_JOIN);
> > +     mt7921_mutex_release(dev);
> > +}
> > +
> > +static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
> > +                                struct ieee80211_vif *vif,
> > +                                struct ieee80211_prep_tx_info *info)
> > +{
> > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > +
> > +     mt7921_mutex_acquire(dev);
> > +     mt7921_abort_roc(mvif->phy, mvif);
> > +     mt7921_mutex_release(dev);
> > +}
> > +
> >  const struct ieee80211_ops mt7921_ops = {
> >       .tx = mt7921_tx,
> >       .start = mt7921_start,
> > @@ -1730,6 +1826,13 @@ const struct ieee80211_ops mt7921_ops = {
> >       .set_sar_specs = mt7921_set_sar_specs,
> >       .remain_on_channel = mt7921_remain_on_channel,
> >       .cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
> > +     .add_chanctx = mt7921_add_chanctx,
> > +     .remove_chanctx = mt7921_remove_chanctx,
> > +     .change_chanctx = mt7921_change_chanctx,
> > +     .assign_vif_chanctx = mt7921_assign_vif_chanctx,
> > +     .unassign_vif_chanctx = mt7921_unassign_vif_chanctx,
> > +     .mgd_prepare_tx = mt7921_mgd_prepare_tx,
> > +     .mgd_complete_tx = mt7921_mgd_complete_tx,
> >  };
> >  EXPORT_SYMBOL_GPL(mt7921_ops);
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > index 280605ffc4da..fda85252325c 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > @@ -156,6 +156,7 @@ struct mt7921_vif {
> >       struct ewma_rssi rssi;
> >
> >       struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
> > +     struct ieee80211_chanctx_conf *ctx;
> >  };
> >
> >  struct mib_stats {
> > --
> > 2.25.1
> >

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

* Re: [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver
  2022-08-17  7:16   ` Lorenzo Bianconi
@ 2022-08-18  0:44     ` Sean Wang
  0 siblings, 0 replies; 31+ messages in thread
From: Sean Wang @ 2022-08-18  0:44 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

HI Lorenzo,

<snip>
> > +
> > +     dev_dbg(dev->mt76.dev, "BSS %d is %s\n", event->bss_idx,
> > +             event->is_absent ? "Absent" : "Present");
>
> do we really need this? I guess we can just drop mt7921_mcu_bss_event entirely

That is not really necessary. That was just what I used to diagnose
firmware behavior. I think I will remove it in the next version.

     Sean
>
> Regards,
> Lorenzo
>
> >  }
> >
> >  static void
> > --
> > 2.25.1
> >

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

* Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-17  7:12   ` Lorenzo Bianconi
@ 2022-08-18  1:03     ` Sean Wang
  2022-08-18  7:39       ` Lorenzo Bianconi
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-18  1:03 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Lorenzo,

On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > From: Sean Wang <sean.wang@mediatek.com>
> >
> > Introduce remain_on_channel support. Additionally, we add
> > mt7921_check_offload_capability to disable .remain_on_channel and
> > .cancel_remain_on_channel and related configuration because those
> > operations would rely on the fundamental MCU commands that will be only
> > supported with newer firmware.
> >
> > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > ---
> >  .../net/wireless/mediatek/mt76/mt7921/init.c  |  36 ++++++
> >  .../net/wireless/mediatek/mt76/mt7921/main.c  | 112 ++++++++++++++++++
> >  .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  24 ++++
> >  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  34 ++++++
> >  .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
> >  .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
> >  .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
> >  7 files changed, 225 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > index cd960e23770f..1b7a18d42f5b 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > @@ -44,6 +44,35 @@ mt7921_regd_notifier(struct wiphy *wiphy,
> >       mt7921_mutex_release(dev);
> >  }
> >
> > +static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> > +{
> > +     struct ieee80211_hw *hw = mt76_hw(dev);
> > +     int year, mon, day, hour, min, sec;
> > +     struct wiphy *wiphy = hw->wiphy;
> > +     bool fw_can_roc = false;
> > +     int ret;
> > +
> > +     ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
> > +                  &year, &mon, &day, &hour, &min, &sec);
>
> does the fw have a differnt base version with respect to the previous ones?
> checking the date is a bit ugly.

I admitted that way was a bit ugly, but I have investigated for a
while, and that is the only way we can use to distinguish the version
in current mt7921 firmware.

>
> > +     if (ret != 6)
> > +             goto out;
> > +
> > +     /* Old firmware cannot support remained on channel and channel
> > +      * context management.
> > +      */
> > +     fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
> > +                   mktime64(2022, 7, 15, 12, 1, 1);
> > +out:
> > +     if (!fw_can_roc) {
> > +             dev->ops->remain_on_channel = NULL;
> > +             dev->ops->cancel_remain_on_channel = NULL;
> > +
> > +             wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> > +     }
> > +
> > +     return 0;
> > +}
> > +

<snip>

> > -     mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7921_ops,
> > -                              &drv_ops);
> > +     ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
> > +                        GFP_KERNEL);
>
> why do we need to copy mt7921_ops?
>

As the old fw cannot support the roc and chanctx and considering
backward compatibility, I need to copy the mt7921_ops here and
disable related operations for old fw before registering the hw to mac80211.

     Sean

> Regards,
> Lorenzo
>
> > +     if (!ops) {
> > +             ret = -ENOMEM;
> > +             goto err_free_pci_vec;
> > +     }
> > +
> > +     mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
> >       if (!mdev) {
> >               ret = -ENOMEM;
> >               goto err_free_pci_vec;
> > @@ -286,7 +293,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
> >
> >       dev = container_of(mdev, struct mt7921_dev, mt76);
> >       dev->hif_ops = &mt7921_pcie_ops;
> > -
> > +     dev->ops = ops;
> >       mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
> >       tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > index 487acd6e2be8..6d27875f41b8 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > @@ -120,18 +120,23 @@ static int mt7921s_probe(struct sdio_func *func,
> >               .fw_own = mt7921s_mcu_fw_pmctrl,
> >       };
> >
> > +     struct ieee80211_ops *ops;
> >       struct mt7921_dev *dev;
> >       struct mt76_dev *mdev;
> >       int ret;
> >
> > -     mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops,
> > -                              &drv_ops);
> > +     ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
> > +                        GFP_KERNEL);
> > +     if (!ops)
> > +             return -ENOMEM;
> > +
> > +     mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
> >       if (!mdev)
> >               return -ENOMEM;
> >
> >       dev = container_of(mdev, struct mt7921_dev, mt76);
> >       dev->hif_ops = &mt7921_sdio_ops;
> > -
> > +     dev->ops = ops;
> >       sdio_set_drvdata(func, dev);
> >
> >       ret = mt76s_init(mdev, func, &mt7921s_ops);
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > index d06cee386acd..cf3ec59a4270 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > @@ -217,6 +217,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
> >
> >       dev = container_of(mdev, struct mt7921_dev, mt76);
> >       dev->hif_ops = &hif_ops;
> > +     dev->ops = ops;
> >
> >       udev = usb_get_dev(udev);
> >       usb_reset_device(udev);
> > --
> > 2.25.1
> >

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

* Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-18  1:03     ` Sean Wang
@ 2022-08-18  7:39       ` Lorenzo Bianconi
  2022-08-25  0:10         ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-18  7:39 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

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

> Hi Lorenzo,
> 
> On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> >
> > > From: Sean Wang <sean.wang@mediatek.com>
> > >
> > > Introduce remain_on_channel support. Additionally, we add
> > > mt7921_check_offload_capability to disable .remain_on_channel and
> > > .cancel_remain_on_channel and related configuration because those
> > > operations would rely on the fundamental MCU commands that will be only
> > > supported with newer firmware.
> > >
> > > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > > ---
> > >  .../net/wireless/mediatek/mt76/mt7921/init.c  |  36 ++++++
> > >  .../net/wireless/mediatek/mt76/mt7921/main.c  | 112 ++++++++++++++++++
> > >  .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  24 ++++
> > >  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  34 ++++++
> > >  .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
> > >  .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
> > >  .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
> > >  7 files changed, 225 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > index cd960e23770f..1b7a18d42f5b 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > @@ -44,6 +44,35 @@ mt7921_regd_notifier(struct wiphy *wiphy,
> > >       mt7921_mutex_release(dev);
> > >  }
> > >
> > > +static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> > > +{
> > > +     struct ieee80211_hw *hw = mt76_hw(dev);
> > > +     int year, mon, day, hour, min, sec;
> > > +     struct wiphy *wiphy = hw->wiphy;
> > > +     bool fw_can_roc = false;
> > > +     int ret;
> > > +
> > > +     ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
> > > +                  &year, &mon, &day, &hour, &min, &sec);
> >
> > does the fw have a differnt base version with respect to the previous ones?
> > checking the date is a bit ugly.
> 
> I admitted that way was a bit ugly, but I have investigated for a
> while, and that is the only way we can use to distinguish the version
> in current mt7921 firmware.

the fw seems pretty new (2022/7/15), is it already available in linux-firmware
git tree? If not I guess you can increment fw version in a more evident way.
For the future please remember to do it for major fw changes.

> 
> >
> > > +     if (ret != 6)
> > > +             goto out;
> > > +
> > > +     /* Old firmware cannot support remained on channel and channel
> > > +      * context management.
> > > +      */
> > > +     fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
> > > +                   mktime64(2022, 7, 15, 12, 1, 1);
> > > +out:
> > > +     if (!fw_can_roc) {
> > > +             dev->ops->remain_on_channel = NULL;
> > > +             dev->ops->cancel_remain_on_channel = NULL;
> > > +
> > > +             wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> 
> <snip>
> 
> > > -     mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7921_ops,
> > > -                              &drv_ops);
> > > +     ops = devm_kmemdup(&pdev->dev, &mt7921_ops, sizeof(mt7921_ops),
> > > +                        GFP_KERNEL);
> >
> > why do we need to copy mt7921_ops?
> >
> 
> As the old fw cannot support the roc and chanctx and considering
> backward compatibility, I need to copy the mt7921_ops here and
> disable related operations for old fw before registering the hw to mac80211.

ack, right.

Regards,
Lorenzo

> 
>      Sean
> 
> > Regards,
> > Lorenzo
> >
> > > +     if (!ops) {
> > > +             ret = -ENOMEM;
> > > +             goto err_free_pci_vec;
> > > +     }
> > > +
> > > +     mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), ops, &drv_ops);
> > >       if (!mdev) {
> > >               ret = -ENOMEM;
> > >               goto err_free_pci_vec;
> > > @@ -286,7 +293,7 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
> > >
> > >       dev = container_of(mdev, struct mt7921_dev, mt76);
> > >       dev->hif_ops = &mt7921_pcie_ops;
> > > -
> > > +     dev->ops = ops;
> > >       mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]);
> > >       tasklet_init(&dev->irq_tasklet, mt7921_irq_tasklet, (unsigned long)dev);
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > > index 487acd6e2be8..6d27875f41b8 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c
> > > @@ -120,18 +120,23 @@ static int mt7921s_probe(struct sdio_func *func,
> > >               .fw_own = mt7921s_mcu_fw_pmctrl,
> > >       };
> > >
> > > +     struct ieee80211_ops *ops;
> > >       struct mt7921_dev *dev;
> > >       struct mt76_dev *mdev;
> > >       int ret;
> > >
> > > -     mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops,
> > > -                              &drv_ops);
> > > +     ops = devm_kmemdup(&func->dev, &mt7921_ops, sizeof(mt7921_ops),
> > > +                        GFP_KERNEL);
> > > +     if (!ops)
> > > +             return -ENOMEM;
> > > +
> > > +     mdev = mt76_alloc_device(&func->dev, sizeof(*dev), ops, &drv_ops);
> > >       if (!mdev)
> > >               return -ENOMEM;
> > >
> > >       dev = container_of(mdev, struct mt7921_dev, mt76);
> > >       dev->hif_ops = &mt7921_sdio_ops;
> > > -
> > > +     dev->ops = ops;
> > >       sdio_set_drvdata(func, dev);
> > >
> > >       ret = mt76s_init(mdev, func, &mt7921s_ops);
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > > index d06cee386acd..cf3ec59a4270 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
> > > @@ -217,6 +217,7 @@ static int mt7921u_probe(struct usb_interface *usb_intf,
> > >
> > >       dev = container_of(mdev, struct mt7921_dev, mt76);
> > >       dev->hif_ops = &hif_ops;
> > > +     dev->ops = ops;
> > >
> > >       udev = usb_get_dev(udev);
> > >       usb_reset_device(udev);
> > > --
> > > 2.25.1
> > >

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

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

* Re: [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support
  2022-08-18  0:37     ` Sean Wang
@ 2022-08-18  7:43       ` Lorenzo Bianconi
  0 siblings, 0 replies; 31+ messages in thread
From: Lorenzo Bianconi @ 2022-08-18  7:43 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

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

> On Wed, Aug 17, 2022 at 12:42 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> >
> > > From: Sean Wang <sean.wang@mediatek.com>
> > >
> > > The firmware can have the capability to manage the channel context
> > > scheduling on multiple roles running on the device including Station,
> > > AP and P2P GC/GO mode (will be extended based on the patchset) to help
> > > users sharing the network with others on a single device.
> > >
> > > The firmware is able to support the channel chanctx up to 2 interface
> > > simultaneously running on the different channels.
> > >
> > > Another thing to be noted is that before the driver is going sent out the
> > > management frames, the driver has to get the privilege from the firmware
> > > to occupy the current channel context until the frame handshake is
> > > completed and then get the privilege back to the firmware.
> > >
> > > We temporarily disable the feature with a module parameter
> > > mt7921_disable_cnm for a while until we can ensure the patchset doesn't
> > > cause any regression.
> > >
> > > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > > ---
> > >  .../net/wireless/mediatek/mt76/mt7921/init.c  |  40 ++++++-
> > >  .../net/wireless/mediatek/mt76/mt7921/main.c  | 111 +++++++++++++++++-
> > >  .../wireless/mediatek/mt76/mt7921/mt7921.h    |   1 +
> > >  3 files changed, 145 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > index 1b7a18d42f5b..208a6117cb69 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > @@ -7,6 +7,10 @@
> > >  #include "mcu.h"
> > >  #include "eeprom.h"
> > >
> > > +static bool mt7921_disable_cnm = true;
> > > +module_param_named(disable_cnm, mt7921_disable_cnm, bool, 0644);
> > > +MODULE_PARM_DESC(disable_cnm, "disable concurrent network support");
> >
> > do we need it? I guess we can just leave it enabled by default and disable it
> > through a debugfs node. What do you think?
> 
> The kernel parameter would be checked before registering ops to
> mac80211, it seemed to me the way debugfs node doesn't work for that
> moment.

I am wondering if it is ok to just enable it by default, what do you t think?
It is not a good practise to add a lot of module parameters.

Regards,
Lorenzo

> 
> >
> > > +
> > >  static const struct ieee80211_iface_limit if_limits[] = {
> > >       {
> > >               .max = MT7921_MAX_INTERFACES,
> > > @@ -25,6 +29,27 @@ static const struct ieee80211_iface_combination if_comb[] = {
> > >               .max_interfaces = MT7921_MAX_INTERFACES,
> > >               .num_different_channels = 1,
> > >               .beacon_int_infra_match = true,
> > > +     },
> > > +};
> > > +
> > > +static const struct ieee80211_iface_limit if_limits_chanctx[] = {
> > > +     {
> > > +             .max = 2,
> > > +             .types = BIT(NL80211_IFTYPE_STATION),
> > > +     },
> > > +     {
> > > +             .max = 1,
> > > +             .types = BIT(NL80211_IFTYPE_AP),
> > > +     }
> > > +};
> > > +
> > > +static const struct ieee80211_iface_combination if_comb_chanctx[] = {
> > > +     {
> > > +             .limits = if_limits_chanctx,
> > > +             .n_limits = ARRAY_SIZE(if_limits_chanctx),
> > > +             .max_interfaces = 2,
> > > +             .num_different_channels = 2,
> > > +             .beacon_int_infra_match = false,
> > >       }
> > >  };
> > >
> > > @@ -63,11 +88,20 @@ static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> > >       fw_can_roc =  mktime64(year, mon, day, hour, min, sec) >=
> > >                     mktime64(2022, 7, 15, 12, 1, 1);
> > >  out:
> > > -     if (!fw_can_roc) {
> > > +     if (!fw_can_roc || mt7921_disable_cnm) {
> > >               dev->ops->remain_on_channel = NULL;
> > >               dev->ops->cancel_remain_on_channel = NULL;
> > > +             dev->ops->add_chanctx = NULL;
> > > +             dev->ops->remove_chanctx = NULL;
> > > +             dev->ops->change_chanctx = NULL;
> > > +             dev->ops->assign_vif_chanctx = NULL;
> > > +             dev->ops->unassign_vif_chanctx = NULL;
> > > +             dev->ops->mgd_prepare_tx = NULL;
> > > +             dev->ops->mgd_complete_tx = NULL;
> > >
> > >               wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
> > > +             wiphy->iface_combinations = if_comb;
> > > +             wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> > >       }
> > >
> > >       return 0;
> > > @@ -93,12 +127,12 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
> > >       hw->sta_data_size = sizeof(struct mt7921_sta);
> > >       hw->vif_data_size = sizeof(struct mt7921_vif);
> > >
> > > -     wiphy->iface_combinations = if_comb;
> > > +     wiphy->iface_combinations = if_comb_chanctx;
> > >       wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
> > >                         WIPHY_FLAG_4ADDR_STATION);
> > >       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
> > >                                BIT(NL80211_IFTYPE_AP);
> > > -     wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
> > > +     wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
> > >       wiphy->max_remain_on_channel_duration = 5000;
> > >       wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
> > >       wiphy->max_scan_ssids = 4;
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > > index ae0aabe052e3..6386290ba71c 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> > > @@ -858,7 +858,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> > >
> > >       if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
> > >               mt76_connac_mcu_uni_add_bss(&dev->mphy, vif, &mvif->sta.wcid,
> > > -                                         true, NULL);
> > > +                                         true, mvif->ctx);
> > >
> > >       mt7921_mac_wtbl_update(dev, msta->wcid.idx,
> > >                              MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
> > > @@ -890,7 +890,7 @@ void mt7921_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
> > >               if (!sta->tdls)
> > >                       mt76_connac_mcu_uni_add_bss(&dev->mphy, vif,
> > >                                                   &mvif->sta.wcid, false,
> > > -                                                 NULL);
> > > +                                                 mvif->ctx);
> > >       }
> > >
> > >       spin_lock_bh(&dev->sta_poll_lock);
> > > @@ -1640,7 +1640,7 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> > >       mt7921_mutex_acquire(dev);
> > >
> > >       err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid,
> > > -                                       true, NULL);
> > > +                                       true, mvif->ctx);
> > >       if (err)
> > >               goto failed;
> > >
> > > @@ -1672,12 +1672,108 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> > >               goto failed;
> > >
> > >       mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false,
> > > -                                 NULL);
> > > +                                 mvif->ctx);
> > >
> > >  failed:
> > >       mt7921_mutex_release(dev);
> > >  }
> > >
> > > +static int
> > > +mt7921_add_chanctx(struct ieee80211_hw *hw,
> > > +                struct ieee80211_chanctx_conf *ctx)
> > > +{
> > > +     return 0;
> > > +}
> > > +
> > > +static void
> > > +mt7921_remove_chanctx(struct ieee80211_hw *hw,
> > > +                   struct ieee80211_chanctx_conf *ctx)
> > > +{
> > > +}
> > > +
> > > +static void mt7921_ctx_iter(void *priv, u8 *mac,
> > > +                         struct ieee80211_vif *vif)
> > > +{
> > > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > > +     struct ieee80211_chanctx_conf *ctx = priv;
> > > +
> > > +     if (ctx != mvif->ctx)
> > > +             return;
> > > +
> > > +     mt76_connac_mcu_uni_set_chctx(mvif->phy->mt76, &mvif->mt76, ctx);
> > > +}
> > > +
> > > +static void
> > > +mt7921_change_chanctx(struct ieee80211_hw *hw,
> > > +                   struct ieee80211_chanctx_conf *ctx,
> > > +                   u32 changed)
> > > +{
> > > +     struct mt7921_phy *phy = mt7921_hw_phy(hw);
> > > +
> > > +     mt7921_mutex_acquire(phy->dev);
> > > +     ieee80211_iterate_active_interfaces(phy->mt76->hw,
> > > +                                         IEEE80211_IFACE_ITER_ACTIVE,
> > > +                                         mt7921_ctx_iter, ctx);
> > > +     mt7921_mutex_release(phy->dev);
> > > +}
> > > +
> > > +static int
> > > +mt7921_assign_vif_chanctx(struct ieee80211_hw *hw,
> > > +                       struct ieee80211_vif *vif,
> > > +                       struct ieee80211_bss_conf *link_conf,
> > > +                       struct ieee80211_chanctx_conf *ctx)
> > > +{
> > > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > > +
> > > +     mt7921_mutex_acquire(dev);
> >
> > I think in this case we can just grub the mutex without waking up the device.
> > what do you think?
> 
> ack
> 
> >
> > > +     mvif->ctx = ctx;
> > > +     mt7921_mutex_release(dev);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void
> > > +mt7921_unassign_vif_chanctx(struct ieee80211_hw *hw,
> > > +                         struct ieee80211_vif *vif,
> > > +                         struct ieee80211_bss_conf *link_conf,
> > > +                         struct ieee80211_chanctx_conf *ctx)
> > > +{
> > > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > > +
> > > +     mt7921_mutex_acquire(dev);
> >
> > same here.
> 
> ack
> 
> >
> > Regards,
> > Lorenzo
> >
> > > +     mvif->ctx = NULL;
> > > +     mt7921_mutex_release(dev);
> > > +}
> > > +
> > > +static void mt7921_mgd_prepare_tx(struct ieee80211_hw *hw,
> > > +                               struct ieee80211_vif *vif,
> > > +                               struct ieee80211_prep_tx_info *info)
> > > +{
> > > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > > +     u16 duration = info->duration ? info->duration :
> > > +                    jiffies_to_msecs(HZ);
> > > +
> > > +     mt7921_mutex_acquire(dev);
> > > +     mt7921_set_roc(mvif->phy, mvif, mvif->ctx->def.chan, duration,
> > > +                    MT7921_ROC_REQ_JOIN);
> > > +     mt7921_mutex_release(dev);
> > > +}
> > > +
> > > +static void mt7921_mgd_complete_tx(struct ieee80211_hw *hw,
> > > +                                struct ieee80211_vif *vif,
> > > +                                struct ieee80211_prep_tx_info *info)
> > > +{
> > > +     struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv;
> > > +     struct mt7921_dev *dev = mt7921_hw_dev(hw);
> > > +
> > > +     mt7921_mutex_acquire(dev);
> > > +     mt7921_abort_roc(mvif->phy, mvif);
> > > +     mt7921_mutex_release(dev);
> > > +}
> > > +
> > >  const struct ieee80211_ops mt7921_ops = {
> > >       .tx = mt7921_tx,
> > >       .start = mt7921_start,
> > > @@ -1730,6 +1826,13 @@ const struct ieee80211_ops mt7921_ops = {
> > >       .set_sar_specs = mt7921_set_sar_specs,
> > >       .remain_on_channel = mt7921_remain_on_channel,
> > >       .cancel_remain_on_channel = mt7921_cancel_remain_on_channel,
> > > +     .add_chanctx = mt7921_add_chanctx,
> > > +     .remove_chanctx = mt7921_remove_chanctx,
> > > +     .change_chanctx = mt7921_change_chanctx,
> > > +     .assign_vif_chanctx = mt7921_assign_vif_chanctx,
> > > +     .unassign_vif_chanctx = mt7921_unassign_vif_chanctx,
> > > +     .mgd_prepare_tx = mt7921_mgd_prepare_tx,
> > > +     .mgd_complete_tx = mt7921_mgd_complete_tx,
> > >  };
> > >  EXPORT_SYMBOL_GPL(mt7921_ops);
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > > index 280605ffc4da..fda85252325c 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
> > > @@ -156,6 +156,7 @@ struct mt7921_vif {
> > >       struct ewma_rssi rssi;
> > >
> > >       struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
> > > +     struct ieee80211_chanctx_conf *ctx;
> > >  };
> > >
> > >  struct mib_stats {
> > > --
> > > 2.25.1
> > >

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

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-18  0:11         ` Sean Wang
@ 2022-08-18 10:49           ` Johannes Berg
  2022-08-18 23:40             ` Sean Wang
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2022-08-18 10:49 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Sean,

> It could be changed but it would break the consistency of the current
> mt76 driver.

I'm not really convinced ...

> mt76 driver does the things in the following order
> - ieee80211_alloc_hw (where an instance of "struct mt76_dev *" would be created)
> - register bus operation into mt76 core (depending on struct mt76_dev
> to provide an abstraction layer for mt76 core to access bus)
> - read chip identifier (depending on bus operation)
> - load the firmware capabilities (depending on chip identifier)
> - initialize the hardware
> ....
> -ieee80211_register_hw
> 
> If firmware capability is needed to load before ieee80211_alloc_hw, we
> need to create kind of similar functions to read chip identifiers and
> load firmware.
> I know It may not a strong reason not to change, but if we can support
> read firmware capabilities after alloc_hw, it provides flexibility to
> the vendor driver
> and helps mt7921 look more consistent and save a few changes across
> different mt7921 bus drivers (mt7921 now supports SDIO, USB, PCIe type
> driver).

But you're loading _firmware_, so to determine the capabilities all you
should need is the actual file, no? I mean, you don't even have to load
it into the device. Like iwlwifi, you could have an indication (or many
flags, or TLVs, or whatnot) in the file that says what it's capable of.

> I kmemdup the const ops and ieee80211_alloc_hw with the duplicated ops
> the duplicated ops would be updated by the actual firmware
> capabilities before ieee80211_register_hw.

Well ... yeah ok that works, but it's pretty wasteful, and also makes
this a nice security attack target - there's a reason ops structs are
supposed to be const, that's because they can then be really read-only
and you can't have function pointer changes. Some of the CFI stuff is
meant to help avoid that, but still ...

So anyway. I'm not really sure I buy this - even you while doing this
already kind of introduced a bug because you didn't change this code:

        if (!use_chanctx || ops->remain_on_channel)
                wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;

I guess you didn't notice because you have remain_on_channel in the
first place, but that's not the only code there assuming that we have
the ops in place and they don't change.

If we really, really need to allow changing the ops, then we should
probably make a much larger change to not even pass the ops until
register, though I'm not really sure it's worth it just to have mt7921
avoid loading the firmware from disk before allocation?

johannes

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-18 10:49           ` Johannes Berg
@ 2022-08-18 23:40             ` Sean Wang
  2022-08-19 17:16               ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-18 23:40 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Johannes,

On Thu, Aug 18, 2022 at 3:49 AM Johannes Berg <johannes@sipsolutions.net> wrote:
>
> Hi Sean,
>
> > It could be changed but it would break the consistency of the current
> > mt76 driver.
>
> I'm not really convinced ...
>
> > mt76 driver does the things in the following order
> > - ieee80211_alloc_hw (where an instance of "struct mt76_dev *" would be created)
> > - register bus operation into mt76 core (depending on struct mt76_dev
> > to provide an abstraction layer for mt76 core to access bus)
> > - read chip identifier (depending on bus operation)
> > - load the firmware capabilities (depending on chip identifier)
> > - initialize the hardware
> > ....
> > -ieee80211_register_hw
> >
> > If firmware capability is needed to load before ieee80211_alloc_hw, we
> > need to create kind of similar functions to read chip identifiers and
> > load firmware.
> > I know It may not a strong reason not to change, but if we can support
> > read firmware capabilities after alloc_hw, it provides flexibility to
> > the vendor driver
> > and helps mt7921 look more consistent and save a few changes across
> > different mt7921 bus drivers (mt7921 now supports SDIO, USB, PCIe type
> > driver).
>
> But you're loading _firmware_, so to determine the capabilities all you
> should need is the actual file, no? I mean, you don't even have to load
> it into the device. Like iwlwifi, you could have an indication (or many
> flags, or TLVs, or whatnot) in the file that says what it's capable of.
>
> > I kmemdup the const ops and ieee80211_alloc_hw with the duplicated ops
> > the duplicated ops would be updated by the actual firmware
> > capabilities before ieee80211_register_hw.
>
> Well ... yeah ok that works, but it's pretty wasteful, and also makes
> this a nice security attack target - there's a reason ops structs are
> supposed to be const, that's because they can then be really read-only
> and you can't have function pointer changes. Some of the CFI stuff is
> meant to help avoid that, but still ...
>
> So anyway. I'm not really sure I buy this - even you while doing this
> already kind of introduced a bug because you didn't change this code:
>
>         if (!use_chanctx || ops->remain_on_channel)
>                 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
>
> I guess you didn't notice because you have remain_on_channel in the
> first place, but that's not the only code there assuming that we have
> the ops in place and they don't change.
>
> If we really, really need to allow changing the ops, then we should
> probably make a much larger change to not even pass the ops until
> register, though I'm not really sure it's worth it just to have mt7921
> avoid loading the firmware from disk before allocation?
>
> johannes

Thanks for your input. I thought I'd try to write a patch to follow up
on the idea you mentioned here.
    sean

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-18 23:40             ` Sean Wang
@ 2022-08-19 17:16               ` Johannes Berg
  2022-08-19 17:36                 ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2022-08-19 17:16 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Sean,

> > If we really, really need to allow changing the ops, then we should
> > probably make a much larger change to not even pass the ops until
> > register, though I'm not really sure it's worth it just to have mt7921
> > avoid loading the firmware from disk before allocation?

> Thanks for your input. I thought I'd try to write a patch to follow up
> on the idea you mentioned here.
> 

I think you will introduce a bug into mt7921 when you do this, and I'm
curious if you will find it ;-)

Seriously though, this approach also seems fragile, and I don't even
know if other bugs would be introduced. And splitting into three
functions (alloc -> set_ops -> register) also feels a bit awkward.


Is there really no chance you could add bits to the firmware _file_
format so you can query the capabilities before you actually _run_ the
firmware? I guess you could even validate it at runtime again (and just
fail is somebody messed up the file), but it would make things a lot
simpler, I'm sure.

johannes

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

* Re: [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration
  2022-08-19 17:16               ` Johannes Berg
@ 2022-08-19 17:36                 ` Johannes Berg
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2022-08-19 17:36 UTC (permalink / raw)
  To: Sean Wang
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

On Fri, 2022-08-19 at 19:16 +0200, Johannes Berg wrote:
> Hi Sean,
> 
> > > If we really, really need to allow changing the ops, then we should
> > > probably make a much larger change to not even pass the ops until
> > > register, though I'm not really sure it's worth it just to have mt7921
> > > avoid loading the firmware from disk before allocation?
> 
> > Thanks for your input. I thought I'd try to write a patch to follow up
> > on the idea you mentioned here.
> > 
> 
> I think you will introduce a bug into mt7921 when you do this, and I'm
> curious if you will find it ;-)
> 

Actually, no, clearing WIPHY_FLAG_IBSS_RSN in mt7921_init_wiphy()
actually does nothing, I thought it was required.

Anyway, the point is that now we set some defaults in alloc_hw(), some
based on the ops, and then the driver could override those before it
does register_hw().

With the proposed change, that's no longer possible, and I'm not sure I
(or you) would want to audit each and every driver - WIPHY_FLAG_IBSS_RSN
was something that showed up easily in grep though.

So I still think you're better off doing it in the firmware file :-)

johannes

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

* Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-18  7:39       ` Lorenzo Bianconi
@ 2022-08-25  0:10         ` Sean Wang
  2022-08-30  5:18           ` Kalle Valo
  0 siblings, 1 reply; 31+ messages in thread
From: Sean Wang @ 2022-08-25  0:10 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Hi Lorenzo,

On Thu, Aug 18, 2022 at 12:39 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
>
> > Hi Lorenzo,
> >
> > On Wed, Aug 17, 2022 at 12:18 AM Lorenzo Bianconi <lorenzo@kernel.org> wrote:
> > >
> > > > From: Sean Wang <sean.wang@mediatek.com>
> > > >
> > > > Introduce remain_on_channel support. Additionally, we add
> > > > mt7921_check_offload_capability to disable .remain_on_channel and
> > > > .cancel_remain_on_channel and related configuration because those
> > > > operations would rely on the fundamental MCU commands that will be only
> > > > supported with newer firmware.
> > > >
> > > > Co-developed-by: Deren Wu <deren.wu@mediatek.com>
> > > > Signed-off-by: Deren Wu <deren.wu@mediatek.com>
> > > > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > > > ---
> > > >  .../net/wireless/mediatek/mt76/mt7921/init.c  |  36 ++++++
> > > >  .../net/wireless/mediatek/mt76/mt7921/main.c  | 112 ++++++++++++++++++
> > > >  .../net/wireless/mediatek/mt76/mt7921/mcu.c   |  24 ++++
> > > >  .../wireless/mediatek/mt76/mt7921/mt7921.h    |  34 ++++++
> > > >  .../net/wireless/mediatek/mt76/mt7921/pci.c   |  13 +-
> > > >  .../net/wireless/mediatek/mt76/mt7921/sdio.c  |  11 +-
> > > >  .../net/wireless/mediatek/mt76/mt7921/usb.c   |   1 +
> > > >  7 files changed, 225 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > > index cd960e23770f..1b7a18d42f5b 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
> > > > @@ -44,6 +44,35 @@ mt7921_regd_notifier(struct wiphy *wiphy,
> > > >       mt7921_mutex_release(dev);
> > > >  }
> > > >
> > > > +static int mt7921_check_offload_capability(struct mt7921_dev *dev)
> > > > +{
> > > > +     struct ieee80211_hw *hw = mt76_hw(dev);
> > > > +     int year, mon, day, hour, min, sec;
> > > > +     struct wiphy *wiphy = hw->wiphy;
> > > > +     bool fw_can_roc = false;
> > > > +     int ret;
> > > > +
> > > > +     ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
> > > > +                  &year, &mon, &day, &hour, &min, &sec);
> > >
> > > does the fw have a differnt base version with respect to the previous ones?
> > > checking the date is a bit ugly.
> >
> > I admitted that way was a bit ugly, but I have investigated for a
> > while, and that is the only way we can use to distinguish the version
> > in current mt7921 firmware.
>
> the fw seems pretty new (2022/7/15), is it already available in linux-firmware
> git tree? If not I guess you can increment fw version in a more evident way.
> For the future please remember to do it for major fw changes.

The new FW is not released in linux-firmware. I will try to figure out
a better way to recognize the FW can support the feature and add it in
v2.

     Sean
>
> >
> > >
<snip>

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

* Re: [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support
  2022-08-25  0:10         ` Sean Wang
@ 2022-08-30  5:18           ` Kalle Valo
  0 siblings, 0 replies; 31+ messages in thread
From: Kalle Valo @ 2022-08-30  5:18 UTC (permalink / raw)
  To: Sean Wang
  Cc: Lorenzo Bianconi, Sean Wang (王志亘),
	Felix Fietkau, lorenzo.bianconi, Soul.Huang, YN.Chen, Leon.Yen,
	Eric-SY.Chang, Deren Wu, km.lin, jenhao.yang, robin.chiu,
	Eddie.Chen, ch.yeh, posh.sun, ted.huang, Stella.Chang, Tom.Chou,
	steve.lee, jsiuda, frankgor, kuabhs, druth, abhishekpandit,
	shawnku, linux-wireless, moderated list:ARM/Mediatek SoC support

Sean Wang <sean.wang@kernel.org> writes:

>> > > > +static int mt7921_check_offload_capability(struct mt7921_dev *dev)
>> > > > +{
>> > > > +     struct ieee80211_hw *hw = mt76_hw(dev);
>> > > > +     int year, mon, day, hour, min, sec;
>> > > > +     struct wiphy *wiphy = hw->wiphy;
>> > > > +     bool fw_can_roc = false;
>> > > > +     int ret;
>> > > > +
>> > > > +     ret = sscanf(dev->mt76.hw->wiphy->fw_version + 11, "%4d%2d%2d%2d%2d%2d",
>> > > > +                  &year, &mon, &day, &hour, &min, &sec);
>> > >
>> > > does the fw have a differnt base version with respect to the previous ones?
>> > > checking the date is a bit ugly.
>> >
>> > I admitted that way was a bit ugly, but I have investigated for a
>> > while, and that is the only way we can use to distinguish the version
>> > in current mt7921 firmware.
>>
>> the fw seems pretty new (2022/7/15), is it already available in linux-firmware
>> git tree? If not I guess you can increment fw version in a more evident way.
>> For the future please remember to do it for major fw changes.
>
> The new FW is not released in linux-firmware. I will try to figure out
> a better way to recognize the FW can support the feature and add it in
> v2.

It would be a lot better and more future proof to use some kind feature
advertising instead of guessing from a firmware version. For example,
ath11k uses WMI service bits and other upstream drivers have something
similar.

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

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

end of thread, other threads:[~2022-08-30  5:18 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-16  0:03 [PATCH 0/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
2022-08-16  0:03 ` [PATCH 1/9] wifi: mac80211: allow enabling chanctx until hw registration sean.wang
2022-08-16  8:03   ` Johannes Berg
2022-08-17  8:28     ` Sean Wang
2022-08-17  8:30       ` Johannes Berg
2022-08-18  0:11         ` Sean Wang
2022-08-18 10:49           ` Johannes Berg
2022-08-18 23:40             ` Sean Wang
2022-08-19 17:16               ` Johannes Berg
2022-08-19 17:36                 ` Johannes Berg
2022-08-16  0:03 ` [PATCH 2/9] wifi: mt76: connac: add mt76_connac_mcu_uni_set_chctx sean.wang
2022-08-17  7:13   ` Lorenzo Bianconi
2022-08-16  0:03 ` [PATCH 3/9] wifi: mt76: connac: rely on mt76_connac_mcu_uni_set_chctx sean.wang
2022-08-17  7:13   ` Lorenzo Bianconi
2022-08-16  0:03 ` [PATCH 4/9] wifi: mt76: mt7921: add chanctx parameter to mt76_connac_mcu_uni_add_bss signature sean.wang
2022-08-16  0:03 ` [PATCH 5/9] wifi: mt76: mt7921: add unified ROC cmd/event support sean.wang
2022-08-17  7:15   ` Lorenzo Bianconi
2022-08-16  0:03 ` [PATCH 6/9] wifi: mt76: mt7921: drop ieee80211_[start, stop]_queues in driver sean.wang
2022-08-17  7:16   ` Lorenzo Bianconi
2022-08-18  0:44     ` Sean Wang
2022-08-16  0:03 ` [PATCH 7/9] wifi: mt76: connac: accept hw scan request at a time sean.wang
2022-08-16  0:03 ` [PATCH 8/9] wifi: mt76: mt7921: introduce remain_on_channel support sean.wang
2022-08-17  7:12   ` Lorenzo Bianconi
2022-08-18  1:03     ` Sean Wang
2022-08-18  7:39       ` Lorenzo Bianconi
2022-08-25  0:10         ` Sean Wang
2022-08-30  5:18           ` Kalle Valo
2022-08-16  0:03 ` [PATCH 9/9] wifi: mt76: mt7921: introduce chanctx support sean.wang
2022-08-17  7:24   ` Lorenzo Bianconi
2022-08-18  0:37     ` Sean Wang
2022-08-18  7:43       ` Lorenzo Bianconi

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